Kernel
Threads by month
- ----- 2026 -----
- 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
- 47 participants
- 23619 discussions
This series is going to backport three patch from upstream to fix
hist field name issue.
David Carlier (1):
tracing: Avoid NULL return from hist_field_name() on truncation
Pengpeng Hou (1):
tracing: Rebuild full_name on each hist_field_name() call
Tom Zanussi (1):
tracing: Fix fully-qualified variable reference printing in histograms
kernel/trace/trace_events_hist.c | 25 +++++++++++++++----------
1 file changed, 15 insertions(+), 10 deletions(-)
--
2.34.1
1
3
[PATCH OLK-6.6] arm64/ACPI: fix build error when CONFIG_ACPI_APEI_GHES is disabled
by Wupeng Ma 26 May '26
by Wupeng Ma 26 May '26
26 May '26
hulk inclusion
category: bugfix
bugzilla: https://atomgit.com/openeuler/kernel/issues/9116
------------------------------------------
When CONFIG_ACPI_APEI_GHES=n, apei_claim_sei() is not defined.
Commit cd342fd16526 ("ACPI/APEI/arm64: add vendor SEI handling for
firmware-first RAS") placed its declaration and inline stub inside the
CONFIG_ACPI block in arch/arm64/include/asm/acpi.h, but the function is
implemented in ghes.c which depends on CONFIG_ACPI_APEI_GHES, not
CONFIG_ACPI. This leads to a link failure:
aarch64-linux-gnu-ld: arch/arm64/kernel/traps.o: in function
`arm64_is_fatal_ras_serror':
traps.c:(.text+0x1490): undefined reference to `apei_claim_sei'
Fix it by moving the declaration and stub to include/acpi/ghes.h, where
they are correctly guarded by CONFIG_ACPI_APEI_GHES, and add the
necessary #include in traps.c.
Fixes: cd342fd16526 ("ACPI/APEI/arm64: add vendor SEI handling for firmware-first RAS")
Signed-off-by: Wupeng Ma <mawupeng1(a)huawei.com>
---
arch/arm64/include/asm/acpi.h | 2 --
arch/arm64/kernel/traps.c | 1 +
include/acpi/ghes.h | 3 +++
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index 693dc4c7b8173..c07a58b96329d 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -134,11 +134,9 @@ static inline int get_cpu_for_acpi_id(u32 uid)
static inline void arch_fix_phys_package_id(int num, u32 slot) { }
void __init acpi_init_cpus(void);
int apei_claim_sea(struct pt_regs *regs);
-int apei_claim_sei(struct pt_regs *regs);
#else
static inline void acpi_init_cpus(void) { }
static inline int apei_claim_sea(struct pt_regs *regs) { return -ENOENT; }
-static inline int apei_claim_sei(struct pt_regs *regs) { return -ENOENT; }
#endif /* CONFIG_ACPI */
#ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index e8ef661715f00..6d5c4039b9219 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -31,6 +31,7 @@
#include <linux/ubsan.h>
#include <linux/cfi.h>
#include <linux/acpi.h>
+#include <acpi/ghes.h>
#include <asm/atomic.h>
#include <asm/bug.h>
diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h
index ebd21b05fe6ed..73a4e64c89002 100644
--- a/include/acpi/ghes.h
+++ b/include/acpi/ghes.h
@@ -72,10 +72,13 @@ void ghes_unregister_vendor_record_notifier(struct notifier_block *nb);
struct list_head *ghes_get_devices(void);
void ghes_estatus_pool_region_free(unsigned long addr, u32 size);
+int apei_claim_sei(struct pt_regs *regs);
#else
static inline struct list_head *ghes_get_devices(void) { return NULL; }
static inline void ghes_estatus_pool_region_free(unsigned long addr, u32 size) { return; }
+
+static inline int apei_claim_sei(struct pt_regs *regs) { return -ENOENT; }
#endif
int ghes_estatus_pool_init(unsigned int num_ghes);
--
2.43.0
2
1
[PATCH OLK-5.10] scsi: storvsc: Fix scheduling while atomic on PREEMPT_RT
by Zhang Qilong 26 May '26
by Zhang Qilong 26 May '26
26 May '26
From: Jan Kiszka <jan.kiszka(a)siemens.com>
stable inclusion
from stable-v5.10.253
commit cf00cb15f2515e38d3b7571bf6800b7c6ce70a84
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15032
CVE: CVE-2026-43475
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
[ Upstream commit 57297736c08233987e5d29ce6584c6ca2a831b12 ]
This resolves the follow splat and lock-up when running with PREEMPT_RT
enabled on Hyper-V:
[ 415.140818] BUG: scheduling while atomic: stress-ng-iomix/1048/0x00000002
[ 415.140822] INFO: lockdep is turned off.
[ 415.140823] Modules linked in: intel_rapl_msr intel_rapl_common intel_uncore_frequency_common intel_pmc_core pmt_telemetry pmt_discovery pmt_class intel_pmc_ssram_telemetry intel_vsec ghash_clmulni_intel aesni_intel rapl binfmt_misc nls_ascii nls_cp437 vfat fat snd_pcm hyperv_drm snd_timer drm_client_lib drm_shmem_helper snd sg soundcore drm_kms_helper pcspkr hv_balloon hv_utils evdev joydev drm configfs efi_pstore nfnetlink vsock_loopback vmw_vsock_virtio_transport_common hv_sock vmw_vsock_vmci_transport vsock vmw_vmci efivarfs autofs4 ext4 crc16 mbcache jbd2 sr_mod sd_mod cdrom hv_storvsc serio_raw hid_generic scsi_transport_fc hid_hyperv scsi_mod hid hv_netvsc hyperv_keyboard scsi_common
[ 415.140846] Preemption disabled at:
[ 415.140847] [<ffffffffc0656171>] storvsc_queuecommand+0x2e1/0xbe0 [hv_storvsc]
[ 415.140854] CPU: 8 UID: 0 PID: 1048 Comm: stress-ng-iomix Not tainted 6.19.0-rc7 #30 PREEMPT_{RT,(full)}
[ 415.140856] Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS Hyper-V UEFI Release v4.1 09/04/2024
[ 415.140857] Call Trace:
[ 415.140861] <TASK>
[ 415.140861] ? storvsc_queuecommand+0x2e1/0xbe0 [hv_storvsc]
[ 415.140863] dump_stack_lvl+0x91/0xb0
[ 415.140870] __schedule_bug+0x9c/0xc0
[ 415.140875] __schedule+0xdf6/0x1300
[ 415.140877] ? rtlock_slowlock_locked+0x56c/0x1980
[ 415.140879] ? rcu_is_watching+0x12/0x60
[ 415.140883] schedule_rtlock+0x21/0x40
[ 415.140885] rtlock_slowlock_locked+0x502/0x1980
[ 415.140891] rt_spin_lock+0x89/0x1e0
[ 415.140893] hv_ringbuffer_write+0x87/0x2a0
[ 415.140899] vmbus_sendpacket_mpb_desc+0xb6/0xe0
[ 415.140900] ? rcu_is_watching+0x12/0x60
[ 415.140902] storvsc_queuecommand+0x669/0xbe0 [hv_storvsc]
[ 415.140904] ? HARDIRQ_verbose+0x10/0x10
[ 415.140908] ? __rq_qos_issue+0x28/0x40
[ 415.140911] scsi_queue_rq+0x760/0xd80 [scsi_mod]
[ 415.140926] __blk_mq_issue_directly+0x4a/0xc0
[ 415.140928] blk_mq_issue_direct+0x87/0x2b0
[ 415.140931] blk_mq_dispatch_queue_requests+0x120/0x440
[ 415.140933] blk_mq_flush_plug_list+0x7a/0x1a0
[ 415.140935] __blk_flush_plug+0xf4/0x150
[ 415.140940] __submit_bio+0x2b2/0x5c0
[ 415.140944] ? submit_bio_noacct_nocheck+0x272/0x360
[ 415.140946] submit_bio_noacct_nocheck+0x272/0x360
[ 415.140951] ext4_read_bh_lock+0x3e/0x60 [ext4]
[ 415.140995] ext4_block_write_begin+0x396/0x650 [ext4]
[ 415.141018] ? __pfx_ext4_da_get_block_prep+0x10/0x10 [ext4]
[ 415.141038] ext4_da_write_begin+0x1c4/0x350 [ext4]
[ 415.141060] generic_perform_write+0x14e/0x2c0
[ 415.141065] ext4_buffered_write_iter+0x6b/0x120 [ext4]
[ 415.141083] vfs_write+0x2ca/0x570
[ 415.141087] ksys_write+0x76/0xf0
[ 415.141089] do_syscall_64+0x99/0x1490
[ 415.141093] ? rcu_is_watching+0x12/0x60
[ 415.141095] ? finish_task_switch.isra.0+0xdf/0x3d0
[ 415.141097] ? rcu_is_watching+0x12/0x60
[ 415.141098] ? lock_release+0x1f0/0x2a0
[ 415.141100] ? rcu_is_watching+0x12/0x60
[ 415.141101] ? finish_task_switch.isra.0+0xe4/0x3d0
[ 415.141103] ? rcu_is_watching+0x12/0x60
[ 415.141104] ? __schedule+0xb34/0x1300
[ 415.141106] ? hrtimer_try_to_cancel+0x1d/0x170
[ 415.141109] ? do_nanosleep+0x8b/0x160
[ 415.141111] ? hrtimer_nanosleep+0x89/0x100
[ 415.141114] ? __pfx_hrtimer_wakeup+0x10/0x10
[ 415.141116] ? xfd_validate_state+0x26/0x90
[ 415.141118] ? rcu_is_watching+0x12/0x60
[ 415.141120] ? do_syscall_64+0x1e0/0x1490
[ 415.141121] ? do_syscall_64+0x1e0/0x1490
[ 415.141123] ? rcu_is_watching+0x12/0x60
[ 415.141124] ? do_syscall_64+0x1e0/0x1490
[ 415.141125] ? do_syscall_64+0x1e0/0x1490
[ 415.141127] ? irqentry_exit+0x140/0x7e0
[ 415.141129] entry_SYSCALL_64_after_hwframe+0x76/0x7e
get_cpu() disables preemption while the spinlock hv_ringbuffer_write is
using is converted to an rt-mutex under PREEMPT_RT.
Signed-off-by: Jan Kiszka <jan.kiszka(a)siemens.com>
Tested-by: Florian Bezdeka <florian.bezdeka(a)siemens.com>
Reviewed-by: Michael Kelley <mhklinux(a)outlook.com>
Tested-by: Michael Kelley <mhklinux(a)outlook.com>
Link: https://patch.msgid.link/0c7fb5cd-fb21-4760-8593-e04bade84744@siemens.com
Signed-off-by: Martin K. Petersen <martin.petersen(a)oracle.com>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: Zhang Qilong <zhangqilong3(a)huawei.com>
---
drivers/scsi/storvsc_drv.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 37ad5f525647..c8111d26feff 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -1821,12 +1821,13 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
cmd_request->payload = payload;
cmd_request->payload_sz = payload_sz;
/* Invokes the vsc to start an IO */
- ret = storvsc_do_io(dev, cmd_request, get_cpu());
- put_cpu();
+ migrate_disable();
+ ret = storvsc_do_io(dev, cmd_request, smp_processor_id());
+ migrate_enable();
if (ret == -EAGAIN) {
if (payload_sz > sizeof(cmd_request->mpb))
kfree(payload);
/* no more space */
--
2.43.0
2
1
26 May '26
From: Jan Kiszka <jan.kiszka(a)siemens.com>
stable inclusion
from stable-v6.6.130
commit e7919a293f9b6101e38bde0d8613daea6c9955df
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/15032
CVE: CVE-2026-43475
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
[ Upstream commit 57297736c08233987e5d29ce6584c6ca2a831b12 ]
This resolves the follow splat and lock-up when running with PREEMPT_RT
enabled on Hyper-V:
[ 415.140818] BUG: scheduling while atomic: stress-ng-iomix/1048/0x00000002
[ 415.140822] INFO: lockdep is turned off.
[ 415.140823] Modules linked in: intel_rapl_msr intel_rapl_common intel_uncore_frequency_common intel_pmc_core pmt_telemetry pmt_discovery pmt_class intel_pmc_ssram_telemetry intel_vsec ghash_clmulni_intel aesni_intel rapl binfmt_misc nls_ascii nls_cp437 vfat fat snd_pcm hyperv_drm snd_timer drm_client_lib drm_shmem_helper snd sg soundcore drm_kms_helper pcspkr hv_balloon hv_utils evdev joydev drm configfs efi_pstore nfnetlink vsock_loopback vmw_vsock_virtio_transport_common hv_sock vmw_vsock_vmci_transport vsock vmw_vmci efivarfs autofs4 ext4 crc16 mbcache jbd2 sr_mod sd_mod cdrom hv_storvsc serio_raw hid_generic scsi_transport_fc hid_hyperv scsi_mod hid hv_netvsc hyperv_keyboard scsi_common
[ 415.140846] Preemption disabled at:
[ 415.140847] [<ffffffffc0656171>] storvsc_queuecommand+0x2e1/0xbe0 [hv_storvsc]
[ 415.140854] CPU: 8 UID: 0 PID: 1048 Comm: stress-ng-iomix Not tainted 6.19.0-rc7 #30 PREEMPT_{RT,(full)}
[ 415.140856] Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS Hyper-V UEFI Release v4.1 09/04/2024
[ 415.140857] Call Trace:
[ 415.140861] <TASK>
[ 415.140861] ? storvsc_queuecommand+0x2e1/0xbe0 [hv_storvsc]
[ 415.140863] dump_stack_lvl+0x91/0xb0
[ 415.140870] __schedule_bug+0x9c/0xc0
[ 415.140875] __schedule+0xdf6/0x1300
[ 415.140877] ? rtlock_slowlock_locked+0x56c/0x1980
[ 415.140879] ? rcu_is_watching+0x12/0x60
[ 415.140883] schedule_rtlock+0x21/0x40
[ 415.140885] rtlock_slowlock_locked+0x502/0x1980
[ 415.140891] rt_spin_lock+0x89/0x1e0
[ 415.140893] hv_ringbuffer_write+0x87/0x2a0
[ 415.140899] vmbus_sendpacket_mpb_desc+0xb6/0xe0
[ 415.140900] ? rcu_is_watching+0x12/0x60
[ 415.140902] storvsc_queuecommand+0x669/0xbe0 [hv_storvsc]
[ 415.140904] ? HARDIRQ_verbose+0x10/0x10
[ 415.140908] ? __rq_qos_issue+0x28/0x40
[ 415.140911] scsi_queue_rq+0x760/0xd80 [scsi_mod]
[ 415.140926] __blk_mq_issue_directly+0x4a/0xc0
[ 415.140928] blk_mq_issue_direct+0x87/0x2b0
[ 415.140931] blk_mq_dispatch_queue_requests+0x120/0x440
[ 415.140933] blk_mq_flush_plug_list+0x7a/0x1a0
[ 415.140935] __blk_flush_plug+0xf4/0x150
[ 415.140940] __submit_bio+0x2b2/0x5c0
[ 415.140944] ? submit_bio_noacct_nocheck+0x272/0x360
[ 415.140946] submit_bio_noacct_nocheck+0x272/0x360
[ 415.140951] ext4_read_bh_lock+0x3e/0x60 [ext4]
[ 415.140995] ext4_block_write_begin+0x396/0x650 [ext4]
[ 415.141018] ? __pfx_ext4_da_get_block_prep+0x10/0x10 [ext4]
[ 415.141038] ext4_da_write_begin+0x1c4/0x350 [ext4]
[ 415.141060] generic_perform_write+0x14e/0x2c0
[ 415.141065] ext4_buffered_write_iter+0x6b/0x120 [ext4]
[ 415.141083] vfs_write+0x2ca/0x570
[ 415.141087] ksys_write+0x76/0xf0
[ 415.141089] do_syscall_64+0x99/0x1490
[ 415.141093] ? rcu_is_watching+0x12/0x60
[ 415.141095] ? finish_task_switch.isra.0+0xdf/0x3d0
[ 415.141097] ? rcu_is_watching+0x12/0x60
[ 415.141098] ? lock_release+0x1f0/0x2a0
[ 415.141100] ? rcu_is_watching+0x12/0x60
[ 415.141101] ? finish_task_switch.isra.0+0xe4/0x3d0
[ 415.141103] ? rcu_is_watching+0x12/0x60
[ 415.141104] ? __schedule+0xb34/0x1300
[ 415.141106] ? hrtimer_try_to_cancel+0x1d/0x170
[ 415.141109] ? do_nanosleep+0x8b/0x160
[ 415.141111] ? hrtimer_nanosleep+0x89/0x100
[ 415.141114] ? __pfx_hrtimer_wakeup+0x10/0x10
[ 415.141116] ? xfd_validate_state+0x26/0x90
[ 415.141118] ? rcu_is_watching+0x12/0x60
[ 415.141120] ? do_syscall_64+0x1e0/0x1490
[ 415.141121] ? do_syscall_64+0x1e0/0x1490
[ 415.141123] ? rcu_is_watching+0x12/0x60
[ 415.141124] ? do_syscall_64+0x1e0/0x1490
[ 415.141125] ? do_syscall_64+0x1e0/0x1490
[ 415.141127] ? irqentry_exit+0x140/0x7e0
[ 415.141129] entry_SYSCALL_64_after_hwframe+0x76/0x7e
get_cpu() disables preemption while the spinlock hv_ringbuffer_write is
using is converted to an rt-mutex under PREEMPT_RT.
Signed-off-by: Jan Kiszka <jan.kiszka(a)siemens.com>
Tested-by: Florian Bezdeka <florian.bezdeka(a)siemens.com>
Reviewed-by: Michael Kelley <mhklinux(a)outlook.com>
Tested-by: Michael Kelley <mhklinux(a)outlook.com>
Link: https://patch.msgid.link/0c7fb5cd-fb21-4760-8593-e04bade84744@siemens.com
Signed-off-by: Martin K. Petersen <martin.petersen(a)oracle.com>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: Zhang Qilong <zhangqilong3(a)huawei.com>
---
drivers/scsi/storvsc_drv.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 9dcad02ce489..106bccaac427 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -1859,12 +1859,13 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd)
cmd_request->payload = payload;
cmd_request->payload_sz = payload_sz;
/* Invokes the vsc to start an IO */
- ret = storvsc_do_io(dev, cmd_request, get_cpu());
- put_cpu();
+ migrate_disable();
+ ret = storvsc_do_io(dev, cmd_request, smp_processor_id());
+ migrate_enable();
if (ret)
scsi_dma_unmap(scmnd);
if (ret == -EAGAIN) {
--
2.43.0
2
1
From: Ilya Dryomov <idryomov(a)gmail.com>
stable inclusion
from stable-v6.6.128
commit e1dc45d97975f9db65694d234fbddf1915176e16
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/14861
CVE: CVE-2026-43304
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
[ Upstream commit ac431d597a9bdfc2ba6b314813f29a6ef2b4a3bf ]
When decoding the key, verify that the key material would fit into
a fixed-size buffer in process_auth_done() and generally has a sane
length.
The new CEPH_MAX_KEY_LEN check replaces the existing check for a key
with no key material which is a) not universal since CEPH_CRYPTO_NONE
has to be excluded and b) doesn't provide much value since a smaller
than needed key is just as invalid as no key -- this has to be handled
elsewhere anyway.
Signed-off-by: Ilya Dryomov <idryomov(a)gmail.com>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: Zhang Qilong <zhangqilong3(a)huawei.com>
---
net/ceph/crypto.c | 8 +++++---
net/ceph/crypto.h | 2 +-
net/ceph/messenger_v2.c | 2 +-
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
index 051d22c0e4ad..3397d105f74f 100644
--- a/net/ceph/crypto.c
+++ b/net/ceph/crypto.c
@@ -35,13 +35,10 @@ static int set_secret(struct ceph_crypto_key *key, void *buf)
break;
default:
return -ENOTSUPP;
}
- if (!key->len)
- return -EINVAL;
-
key->key = kmemdup(buf, key->len, GFP_NOIO);
if (!key->key) {
ret = -ENOMEM;
goto fail;
}
@@ -93,10 +90,15 @@ int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end)
ceph_decode_need(p, end, 2*sizeof(u16) + sizeof(key->created), bad);
key->type = ceph_decode_16(p);
ceph_decode_copy(p, &key->created, sizeof(key->created));
key->len = ceph_decode_16(p);
ceph_decode_need(p, end, key->len, bad);
+ if (key->len > CEPH_MAX_KEY_LEN) {
+ pr_err("secret too big %d\n", key->len);
+ return -EINVAL;
+ }
+
ret = set_secret(key, *p);
memzero_explicit(*p, key->len);
*p += key->len;
return ret;
diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h
index 13bd526349fa..0d32f1649f3d 100644
--- a/net/ceph/crypto.h
+++ b/net/ceph/crypto.h
@@ -3,11 +3,11 @@
#define _FS_CEPH_CRYPTO_H
#include <linux/ceph/types.h>
#include <linux/ceph/buffer.h>
-#define CEPH_KEY_LEN 16
+#define CEPH_MAX_KEY_LEN 16
#define CEPH_MAX_CON_SECRET_LEN 64
/*
* cryptographic secret
*/
diff --git a/net/ceph/messenger_v2.c b/net/ceph/messenger_v2.c
index 858198724439..f82029bd33db 100644
--- a/net/ceph/messenger_v2.c
+++ b/net/ceph/messenger_v2.c
@@ -2391,11 +2391,11 @@ static int process_auth_reply_more(struct ceph_connection *con,
* setup_crypto(). __aligned(16) isn't guaranteed to work for stack
* objects, so do it by hand.
*/
static int process_auth_done(struct ceph_connection *con, void *p, void *end)
{
- u8 session_key_buf[CEPH_KEY_LEN + 16];
+ u8 session_key_buf[CEPH_MAX_KEY_LEN + 16];
u8 con_secret_buf[CEPH_MAX_CON_SECRET_LEN + 16];
u8 *session_key = PTR_ALIGN(&session_key_buf[0], 16);
u8 *con_secret = PTR_ALIGN(&con_secret_buf[0], 16);
int session_key_len, con_secret_len;
int payload_len;
--
2.43.0
2
1
From: Dongdong Hao <doubled(a)leap-io-kernel.com>
LeapIO inclusion
category: feature
bugzilla: https://atomgit.com/openeuler/kernel/issues/9235
------------------------------------------
leapraid driver changes from v2.0.0.6 to v2.0.1.2.
This update includes:
- overheat handling rework
- reset flow stabilization
- improved timeout diagnostics
- sysfs enhancement
- topology and transport error-path fixes
- memory leak/UAF/reference leak fixes
- mmap/ioctl validation fixes
- improved queue depth handling
- improved interrupt and resource cleanup logic
The update also fixes several race conditions and improves
overall driver robustness under reset, topology change,
and controller abnormal scenarios.
Signed-off-by: Dongdong Hao <doubled(a)leap-io-kernel.com>
---
drivers/scsi/leapraid/Kconfig | 2 +-
drivers/scsi/leapraid/leapraid.h | 1335 +++---
drivers/scsi/leapraid/leapraid_app.c | 529 +--
drivers/scsi/leapraid/leapraid_func.c | 4229 ++++++++++++--------
drivers/scsi/leapraid/leapraid_func.h | 1086 ++---
drivers/scsi/leapraid/leapraid_os.c | 910 +++--
drivers/scsi/leapraid/leapraid_transport.c | 485 ++-
7 files changed, 4863 insertions(+), 3713 deletions(-)
diff --git a/drivers/scsi/leapraid/Kconfig b/drivers/scsi/leapraid/Kconfig
index b539183b24a7..f4ece78f80d3 100644
--- a/drivers/scsi/leapraid/Kconfig
+++ b/drivers/scsi/leapraid/Kconfig
@@ -5,7 +5,7 @@ config SCSI_LEAPRAID
depends on PCI && SCSI
select SCSI_SAS_ATTRS
help
- This driver supports LeapIO PCIe-based Storage
+ This driver supports LeapIO PCIe-based storage
and RAID controllers.
<http://www.leap-io.com>
diff --git a/drivers/scsi/leapraid/leapraid.h b/drivers/scsi/leapraid/leapraid.h
index 77bb93b79254..2a99417143ad 100644
--- a/drivers/scsi/leapraid/leapraid.h
+++ b/drivers/scsi/leapraid/leapraid.h
@@ -1,13 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Copyright (C) 2025 LeapIO Tech Inc.
+ * Copyright (C) 2026 LeapIO Tech Inc.
*
- * LeapRAID Storage and RAID Controller driver.
+ * LeapRAID storage and RAID controller driver.
*/
#ifndef LEAPRAID_H
#define LEAPRAID_H
-/* doorbell register definitions */
+/* Doorbell register definitions. */
#define LEAPRAID_DB_RESET 0x00000000
#define LEAPRAID_DB_READY 0x10000000
#define LEAPRAID_DB_OPERATIONAL 0x20000000
@@ -22,55 +22,60 @@
#define LEAPRAID_DB_FUNC_SHIFT 24
#define LEAPRAID_DB_ADD_DWORDS_SHIFT 16
-/* maximum number of retries waiting for doorbell to become ready */
+/* Maximum number of retries waiting for doorbell to become ready. */
#define LEAPRAID_DB_RETRY_COUNT_MAX 10
-/* maximum number of retries waiting for doorbell to become operational */
-#define LEAPRAID_DB_WAIT_OPERATIONAL 10
-/* sleep interval (in seconds) between doorbell polls */
+/* 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 30
+/* Maximum number of retries waiting for host to end recovery. */
+#define LEAPRAID_WAIT_SHOST_RECOVERY 400
-/* diagnostic register definitions */
+/* Diagnostic register definitions. */
#define LEAPRAID_DIAG_WRITE_ENABLE 0x00000080
#define LEAPRAID_DIAG_RESET 0x00000004
-#define LEAPRAID_DIAG_HOLD_ADAPTER_RESET 0x00000002
-/* interrupt status register definitions */
+/* Interrupt status register definitions. */
#define LEAPRAID_HOST2ADAPTER_DB_STATUS 0x80000000
#define LEAPRAID_ADAPTER2HOST_DB_STATUS 0x00000001
-/* the number of debug register */
+/* The number of debug register. */
#define LEAPRAID_DEBUGLOG_SZ_MAX 16
+#define LEAPRAID_DEBUGLOG_DWORDS_PER_LINE 4
-/* reply post host register defines */
+/* Reply post host register definitions. */
#define REP_POST_HOST_IDX_REG_CNT 16
#define LEAPRAID_RPHI_MSIX_IDX_SHIFT 24
-/* vphy flags */
+/* Virtual PHY flags. */
#define LEAPRAID_SAS_PHYINFO_VPHY 0x00001000
-/* linux driver init fw */
+/* Linux driver init firmware. */
#define LEAPRAID_WHOINIT_LINUX_DRIVER 0x04
-/* rdpq array mode */
+/* Reply descriptor post queue array mode. */
#define LEAPRAID_ADAPTER_INIT_MSGFLG_RDPQ_ARRAY_MODE 0x01
-/* request description flags */
+/* Request description flags. */
#define LEAPRAID_REQ_DESC_FLG_SCSI_IO 0x00
#define LEAPRAID_REQ_DESC_FLG_HPR 0x06
#define LEAPRAID_REQ_DESC_FLG_DFLT_TYPE 0x08
-/* reply description flags */
+/* Reply description flags. */
#define LEAPRAID_RPY_DESC_FLG_TYPE_MASK 0x0F
#define LEAPRAID_RPY_DESC_FLG_SCSI_IO_SUCCESS 0x00
#define LEAPRAID_RPY_DESC_FLG_ADDRESS_REPLY 0x01
#define LEAPRAID_RPY_DESC_FLG_FP_SCSI_IO_SUCCESS 0x06
#define LEAPRAID_RPY_DESC_FLG_UNUSED 0x0F
-/* MPI functions */
-#define LEAPRAID_FUNC_SCSIIO_REQ 0x00
+/* Request and reply messages share the same set of function codes.
+ *
+ * Note: SCSIIO (SCSI I/O) represents SCSI I/O operations and is used
+ * consistently throughout the driver for all SCSI command handling.
+ */
+#define LEAPRAID_FUNC_SCSIIO 0x00
#define LEAPRAID_FUNC_SCSI_TMF 0x01
#define LEAPRAID_FUNC_ADAPTER_INIT 0x02
#define LEAPRAID_FUNC_GET_ADAPTER_FEATURES 0x03
@@ -79,17 +84,16 @@
#define LEAPRAID_FUNC_EVENT_NOTIFY 0x07
#define LEAPRAID_FUNC_FW_DOWNLOAD 0x09
#define LEAPRAID_FUNC_FW_UPLOAD 0x12
-#define LEAPRAID_FUNC_RAID_ACTION 0x15
-#define LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH 0x16
+#define LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH 0x16
#define LEAPRAID_FUNC_SCSI_ENC_PROCESSOR 0x18
#define LEAPRAID_FUNC_SMP_PASSTHROUGH 0x1A
#define LEAPRAID_FUNC_SAS_IO_UNIT_CTRL 0x1B
-#define LEAPRAID_FUNC_SATA_PASSTHROUGH 0x1C
+#define LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH 0x1C
#define LEAPRAID_FUNC_ADAPTER_UNIT_RESET 0x40
#define LEAPRAID_FUNC_HANDSHAKE 0x42
#define LEAPRAID_FUNC_LOGBUF_INIT 0x57
-/* adapter status values */
+/* Adapter status values. */
#define LEAPRAID_ADAPTER_STATUS_MASK 0x7FFF
#define LEAPRAID_ADAPTER_STATUS_SUCCESS 0x0000
#define LEAPRAID_ADAPTER_STATUS_BUSY 0x0002
@@ -113,7 +117,7 @@
#define LEAPRAID_ADAPTER_STATUS_SCSI_ADAPTER_TERMINATED 0x004B
#define LEAPRAID_ADAPTER_STATUS_SCSI_EXT_TERMINATED 0x004C
-/* sge flags */
+/* SGE flags. */
#define LEAPRAID_SGE_FLG_LAST_ONE 0x80
#define LEAPRAID_SGE_FLG_EOB 0x40
#define LEAPRAID_SGE_FLG_EOL 0x01
@@ -129,15 +133,19 @@
#define LEAPRAID_IEEE_SGE_FLG_CHAIN_ONE 0x80
#define LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR 0x00
-#define LEAPRAID_SGE_OFFSET_SIZE 4
+#define LEAPRAID_SGE_NO_DATA_ADDR -1
+#define LEAPRAID_SGE_OFFSET_SIZE 4
-/* page and ext page type */
+/* The type of page. */
#define LEAPRAID_CFG_PT_IO_UNIT 0x00
#define LEAPRAID_CFG_PT_ADAPTER 0x01
#define LEAPRAID_CFG_PT_BIOS 0x02
#define LEAPRAID_CFG_PT_RAID_VOLUME 0x08
+#define LEAPRAID_CFG_PT_MANUFACTURING 0x09
#define LEAPRAID_CFG_PT_RAID_PHYSDISK 0x0A
#define LEAPRAID_CFG_PT_EXTENDED 0x0F
+
+/* The type of extended page. */
#define LEAPRAID_CFG_EXTPT_SAS_IO_UNIT 0x10
#define LEAPRAID_CFG_EXTPT_SAS_EXP 0x11
#define LEAPRAID_CFG_EXTPT_SAS_DEV 0x12
@@ -145,7 +153,7 @@
#define LEAPRAID_CFG_EXTPT_ENC 0x15
#define LEAPRAID_CFG_EXTPT_RAID_CONFIG 0x16
-/* config page address */
+/* Config page address. */
#define LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP 0x00000000
#define LEAPRAID_SAS_ENC_CFG_PGAD_HDL 0x10000000
#define LEAPRAID_SAS_DEV_CFG_PGAD_HDL 0x20000000
@@ -156,51 +164,55 @@
#define LEAPRAID_SAS_PHY_CFG_PGAD_PHY_NUMBER 0x00000000
#define LEAPRAID_PHYSDISK_CFG_PGAD_PHYSDISKNUM 0x10000000
-/* config page operations */
+/* Config page operations. */
#define LEAPRAID_CFG_ACT_PAGE_HEADER 0x00
#define LEAPRAID_CFG_ACT_PAGE_READ_CUR 0x01
#define LEAPRAID_CFG_ACT_PAGE_WRITE_CUR 0x02
-/* bios pages */
+/* BIOS page number. */
#define LEAPRAID_CFG_PAGE_NUM_BIOS2 0x2
#define LEAPRAID_CFG_PAGE_NUM_BIOS3 0x3
-/* sas device pages */
+/* Manufacturing page number. */
+#define LEAPRAID_CFG_PAGE_NUM_MANU0 0x0
+
+/* SAS device page number. */
#define LEAPRAID_CFG_PAGE_NUM_DEV0 0x0
-/* sas device page 0 flags */
+/* 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
-/* sas IO unit pages */
+/* SAS I/O unit page number. */
#define LEAPRAID_CFG_PAGE_NUM_IOUNIT0 0x0
#define LEAPRAID_CFG_PAGE_NUM_IOUNIT1 0x1
-/* sas expander pages */
+/* SAS expander page number. */
#define LEAPRAID_CFG_PAGE_NUM_EXP0 0x0
#define LEAPRAID_CFG_PAGE_NUM_EXP1 0x1
-/* sas enclosure page */
+/* SAS enclosure page number. */
#define LEAPRAID_CFG_PAGE_NUM_ENC0 0x0
-/* sas phy page */
+/* SAS PHY page number. */
#define LEAPRAID_CFG_PAGE_NUM_PHY0 0x0
-/* raid volume pages */
+/* RAID volume page number. */
#define LEAPRAID_CFG_PAGE_NUM_VOL0 0x0
#define LEAPRAID_CFG_PAGE_NUM_VOL1 0x1
-/* physical disk page */
+/* Physical disk page number. */
#define LEAPRAID_CFG_PAGE_NUM_PD0 0x0
-/* adapter page */
+/* Adapter page number. */
#define LEAPRAID_CFG_PAGE_NUM_ADAPTER1 0x1
#define LEAPRAID_CFG_UNIT_SIZE 4
-/* raid volume type and state */
+/* Raid volume type and state. */
#define LEAPRAID_VOL_STATE_MISSING 0x00
#define LEAPRAID_VOL_STATE_FAILED 0x01
#define LEAPRAID_VOL_STATE_INITIALIZING 0x02
@@ -213,17 +225,17 @@
#define LEAPRAID_VOL_TYPE_RAID10 0x05
#define LEAPRAID_VOL_TYPE_UNKNOWN 0xFF
-/* raid volume element flags */
+/* Raid volume element flags. */
#define LEAPRAID_RAIDCFG_P0_EFLG_MASK_ELEMENT_TYPE 0x000F
#define LEAPRAID_RAIDCFG_P0_EFLG_VOL_PHYS_DISK_ELEMENT 0x0001
#define LEAPRAID_RAIDCFG_P0_EFLG_HOT_SPARE_ELEMENT 0x0002
#define LEAPRAID_RAIDCFG_P0_EFLG_OCE_ELEMENT 0x0003
-/* raid action */
+/* Raid action. */
#define LEAPRAID_RAID_ACT_SYSTEM_SHUTDOWN_INITIATED 0x20
#define LEAPRAID_RAID_ACT_PHYSDISK_HIDDEN 0x24
-/* sas negotiated link rates */
+/* SAS negotiated link rates. */
#define LEAPRAID_SAS_NEG_LINK_RATE_MASK_PHYSICAL 0x0F
#define LEAPRAID_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE 0x00
#define LEAPRAID_SAS_NEG_LINK_RATE_PHY_DISABLED 0x01
@@ -231,6 +243,7 @@
#define LEAPRAID_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE 0x03
#define LEAPRAID_SAS_NEG_LINK_RATE_PORT_SELECTOR 0x04
#define LEAPRAID_SAS_NEG_LINK_RATE_SMP_RESETTING 0x05
+#define LEAPRAID_SAS_NEG_LINK_RATE_SHIFT 4
#define LEAPRAID_SAS_NEG_LINK_RATE_1_5 0x08
#define LEAPRAID_SAS_NEG_LINK_RATE_3_0 0x09
@@ -240,8 +253,11 @@
#define LEAPRAID_SAS_PRATE_MIN_RATE_MASK 0x0F
#define LEAPRAID_SAS_HWRATE_MIN_RATE_MASK 0x0F
-/* scsi IO control bits */
-#define LEAPRAID_SCSIIO_CTRL_ADDCDBLEN_SHIFT 26
+/*
+ * Control flags for a SCSI I/O Request.
+ */
+#define LEAPRAID_SCSIIO_CTRL_CDB_32BYTE 4
+#define LEAPRAID_SCSIIO_CTRL_CDB_LEN_SHIFT 26
#define LEAPRAID_SCSIIO_CTRL_NODATATRANSFER 0x00000000
#define LEAPRAID_SCSIIO_CTRL_WRITE 0x01000000
#define LEAPRAID_SCSIIO_CTRL_READ 0x02000000
@@ -250,7 +266,7 @@
#define LEAPRAID_SCSIIO_CTRL_ORDEREDQ 0x00000200
#define LEAPRAID_SCSIIO_CTRL_CMDPRI 0x00000800
-/* scsi state and status */
+/* SCSI state and status. */
#define LEAPRAID_SCSI_STATUS_BUSY 0x08
#define LEAPRAID_SCSI_STATUS_RESERVATION_CONFLICT 0x18
#define LEAPRAID_SCSI_STATUS_TASK_SET_FULL 0x28
@@ -261,7 +277,7 @@
#define LEAPRAID_SCSI_STATE_AUTOSENSE_FAILED 0x02
#define LEAPRAID_SCSI_STATE_AUTOSENSE_VALID 0x01
-/* scsi task management defines */
+/* SCSI task management defines. */
#define LEAPRAID_TM_TASKTYPE_ABORT_TASK 0x01
#define LEAPRAID_TM_TASKTYPE_ABRT_TASK_SET 0x02
#define LEAPRAID_TM_TASKTYPE_TARGET_RESET 0x03
@@ -277,21 +293,20 @@
#define LEAPRAID_TM_RSP_TM_SUCCEEDED 0x08
#define LEAPRAID_TM_RSP_IO_QUEUED_ON_ADAPTER 0x80
-/* scsi sep request defines */
+/* SCSI enclosure processor request defines. */
#define LEAPRAID_SEP_REQ_ACT_WRITE_STATUS 0x00
#define LEAPRAID_SEP_REQ_FLG_DEVHDL_ADDRESS 0x00
#define LEAPRAID_SEP_REQ_FLG_ENCLOSURE_SLOT_ADDRESS 0x01
#define LEAPRAID_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT 0x00000040
-/* the capabilities of the adapter */
+/* 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 */
+/* Event code definitions for the firmware. */
#define LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE 0x000F
-#define LEAPRAID_EVT_SAS_DISCOVERY 0x0016
#define LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST 0x001C
#define LEAPRAID_EVT_SAS_ENCL_DEV_STATUS_CHANGE 0x001D
#define LEAPRAID_EVT_IR_CHANGE 0x0020
@@ -303,7 +318,7 @@
#define LEAPRAID_EVT_SAS_DEV_STAT_RC_INTERNAL_DEV_RESET 0x08
#define LEAPRAID_EVT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET 0x0E
-/* raid configuration change event */
+/* RAID configuration change event. */
#define LEAPRAID_EVT_IR_RC_VOLUME_ADD 0x01
#define LEAPRAID_EVT_IR_RC_VOLUME_DELETE 0x02
#define LEAPRAID_EVT_IR_RC_PD_HIDDEN_TO_ADD 0x03
@@ -313,27 +328,25 @@
#define LEAPRAID_EVT_IR_RC_VOLUME_HIDE 0x0A
#define LEAPRAID_EVT_IR_RC_VOLUME_UNHIDE 0x0B
-/* sas topology change event */
+/* SAS topology change event. */
#define LEAPRAID_EVT_SAS_TOPO_ES_NO_EXPANDER 0x00
#define LEAPRAID_EVT_SAS_TOPO_ES_ADDED 0x01
#define LEAPRAID_EVT_SAS_TOPO_ES_NOT_RESPONDING 0x02
#define LEAPRAID_EVT_SAS_TOPO_ES_RESPONDING 0x03
#define LEAPRAID_EVT_SAS_TOPO_RC_MASK 0x0F
-#define LEAPRAID_EVT_SAS_TOPO_RC_CLEAR_MASK 0xF0
#define LEAPRAID_EVT_SAS_TOPO_RC_TARG_ADDED 0x01
#define LEAPRAID_EVT_SAS_TOPO_RC_TARG_NOT_RESPONDING 0x02
-#define LEAPRAID_EVT_SAS_TOPO_RC_PHY_CHANGED 0x03
-/* sas discovery event defines */
+/* 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 */
+/* Enclosure device status change event. */
#define LEAPRAID_EVT_SAS_ENCL_RC_ADDED 0x01
#define LEAPRAID_EVT_SAS_ENCL_RC_NOT_RESPONDING 0x02
-/* device type and identifiers */
+/* Device type and identifiers. */
#define LEAPRAID_DEVTYP_SEP 0x00004000
#define LEAPRAID_DEVTYP_SSP_TGT 0x00000400
#define LEAPRAID_DEVTYP_STP_TGT 0x00000200
@@ -350,12 +363,12 @@
#define LEAPRAID_DEVTYP_EDGE_EXPANDER 0x00000002
#define LEAPRAID_DEVTYP_FANOUT_EXPANDER 0x00000003
-/* sas control operation */
+/* SAS control operation. */
#define LEAPRAID_SAS_OP_PHY_LINK_RESET 0x06
#define LEAPRAID_SAS_OP_PHY_HARD_RESET 0x07
#define LEAPRAID_SAS_OP_SET_PARAMETER 0x0F
-/* boot device defines */
+/* Boot device defines */
#define LEAPRAID_BOOTDEV_FORM_MASK 0x0F
#define LEAPRAID_BOOTDEV_FORM_NONE 0x00
#define LEAPRAID_BOOTDEV_FORM_SAS_WWID 0x05
@@ -365,21 +378,21 @@
/**
* struct leapraid_reg_base - Register layout of the LeapRAID controller
*
- * @db: Doorbell register used to signal commands or status to firmware
- * @ws: Write sequence register for synchronizing doorbell operations
- * @host_diag: Diagnostic register used for status or debug reporting
- * @r1: Reserved
- * @host_int_status: Interrupt status register reporting active interrupts
- * @host_int_mask: Interrupt mask register enabling or disabling sources
- * @r2: Reserved
- * @rep_msg_host_idx: Reply message index for the next available reply slot
- * @r3: Reserved
- * @debug_log: DebugLog registers for firmware debug and diagnostic output
- * @r4: Reserved
- * @atomic_req_desc_post: Atomic register for single descriptor posting
- * @adapter_log_buf_pos: Adapter log buffer write position
- * @host_log_buf_pos: Host log buffer write position
- * @r5: Reserved
+ * @db: Doorbell register used to signal commands or status to firmware.
+ * @ws: Write sequence register for synchronizing doorbell operations.
+ * @host_diag: Diagnostic register used for status or debug reporting.
+ * @r1: Reserved.
+ * @host_int_status: Interrupt status register reporting active interrupts.
+ * @host_int_mask: Interrupt mask register enabling or disabling sources.
+ * @r2: Reserved.
+ * @rep_msg_host_idx: Reply message index for the next available reply slot.
+ * @r3: Reserved.
+ * @debug_log: DebugLog registers for firmware debug and diagnostic output.
+ * @r4: Reserved.
+ * @atomic_req_desc_post: Atomic register for single descriptor posting.
+ * @adapter_log_buf_pos: Adapter log buffer write position.
+ * @host_log_buf_pos: Host log buffer write position.
+ * @r5: Reserved.
* @rep_post_reg_idx: Array of reply post index registers, one per queue.
* The number of entries is defined by
* REP_POST_HOST_IDX_REG_CNT.
@@ -411,9 +424,9 @@ struct leapraid_reg_base {
/**
* struct leapraid_atomic_req_desc - Atomic request descriptor
*
- * @flg: Descriptor flag indicating the type of request (e.g. SCSI I/O)
- * @msix_idx: MSI-X vector index used for interrupt routing
- * @taskid: Unique task identifier associated with this request
+ * @flg: Descriptor flag indicating the type of request (e.g. SCSI I/O).
+ * @msix_idx: MSI-X vector index used for interrupt routing.
+ * @taskid: Unique task identifier associated with this request.
*/
struct leapraid_atomic_req_desc {
u8 flg;
@@ -424,23 +437,23 @@ struct leapraid_atomic_req_desc {
/**
* union leapraid_rep_desc_union - Unified reply descriptor format
*
- * @dflt_rep: Default reply descriptor containing basic completion info
- * @dflt_rep.rep_flg: Reply flag indicating reply type or status
- * @dflt_rep.msix_idx: MSI-X index for interrupt routing
- * @dflt_rep.taskid: Task identifier matching the submitted request
- * @r1: Reserved
+ * @dflt_rep: Default reply descriptor containing basic completion info.
+ * @dflt_rep.rep_flg: Reply flag indicating reply type or status.
+ * @dflt_rep.msix_idx: MSI-X index for interrupt routing.
+ * @dflt_rep.taskid: Task identifier matching the submitted request.
+ * @r1: Reserved.
*
* @addr_rep: Address reply descriptor used when firmware returns a
- * memory address associated with the reply
- * @addr_rep.rep_flg: Reply flag indicating reply type or status
- * @addr_rep.msix_idx: MSI-X index for interrupt routing
- * @addr_rep.taskid: Task identifier matching the submitted request
- * @addr_rep.rep_frame_addr: Physical address of the reply frame
+ * memory address associated with the reply.
+ * @addr_rep.rep_flg: Reply flag indicating reply type or status.
+ * @addr_rep.msix_idx: MSI-X index for interrupt routing.
+ * @addr_rep.taskid: Task identifier matching the submitted request.
+ * @addr_rep.rep_frame_addr: Physical address of the reply frame.
*
- * @words: Raw 64-bit representation of the reply descriptor
- * @u: Alternative access using 32-bit low/high words
- * @u.low: Lower 32 bits of the descriptor
- * @u.high: Upper 32 bits of the descriptor
+ * @words: Raw 64-bit representation of the reply descriptor.
+ * @u: Alternative access using 32-bit low/high words.
+ * @u.low: Lower 32 bits of the descriptor.
+ * @u.high: Upper 32 bits of the descriptor.
*/
union leapraid_rep_desc_union {
struct leapraid_rep_desc {
@@ -465,10 +478,10 @@ union leapraid_rep_desc_union {
/**
* struct leapraid_req - Generic request header
*
- * @func_dep1: Function-dependent parameter (low 16 bits)
- * @r1: Reserved
- * @func: Function code identifying the command type
- * @r2: Reserved
+ * @func_dep1: Function-dependent parameter (low 16 bits).
+ * @r1: Reserved.
+ * @func: Function code identifying the command type.
+ * @r2: Reserved.
*/
struct leapraid_req {
__le16 func_dep1;
@@ -480,12 +493,12 @@ struct leapraid_req {
/**
* struct leapraid_rep - Generic reply header
*
- * @r1: Reserved
- * @msg_len: Length of the reply message in bytes
- * @function: Function code corresponding to the request
- * @r2: Reserved
- * @adapter_status: Status code reported by the adapter
- * @r3: Reserved
+ * @r1: Reserved.
+ * @msg_len: Length of the reply message in bytes.
+ * @function: Function code corresponding to the request.
+ * @r2: Reserved.
+ * @adapter_status: Status code reported by the adapter.
+ * @r3: Reserved.
*/
struct leapraid_rep {
u8 r1[2];
@@ -499,8 +512,8 @@ struct leapraid_rep {
/**
* struct leapraid_sge_simple32 - 32-bit simple scatter-gather entry
*
- * @flg_and_len: Combined field for flags and segment length
- * @addr: 32-bit physical address of the data buffer
+ * @flg_and_len: Combined field for flags and segment length.
+ * @addr: 32-bit physical address of the data buffer.
*/
struct leapraid_sge_simple32 {
__le32 flg_and_len;
@@ -510,8 +523,8 @@ struct leapraid_sge_simple32 {
/**
* struct leapraid_sge_simple64 - 64-bit simple scatter-gather entry
*
- * @flg_and_len: Combined field for flags and segment length
- * @addr: 64-bit physical address of the data buffer
+ * @flg_and_len: Combined field for flags and segment length.
+ * @addr: 64-bit physical address of the data buffer.
*/
struct leapraid_sge_simple64 {
__le32 flg_and_len;
@@ -521,9 +534,9 @@ struct leapraid_sge_simple64 {
/**
* struct leapraid_sge_simple_union - Unified 32/64-bit SGE representation
*
- * @flg_and_len: Combined field for flags and segment length
- * @u.addr32: 32-bit address field
- * @u.addr64: 64-bit address field
+ * @flg_and_len: Combined field for flags and segment length.
+ * @u.addr32: 32-bit address field.
+ * @u.addr64: 64-bit address field.
*/
struct leapraid_sge_simple_union {
__le32 flg_and_len;
@@ -536,11 +549,11 @@ struct leapraid_sge_simple_union {
/**
* struct leapraid_sge_chain_union - Chained scatter-gather entry
*
- * @len: Length of the chain descriptor
- * @next_chain_offset: Offset to the next SGE chain
- * @flg: Flags indicating chain or termination properties
- * @u.addr32: 32-bit physical address
- * @u.addr64: 64-bit physical address
+ * @len: Length of the chain descriptor.
+ * @next_chain_offset: Offset to the next SGE chain.
+ * @flg: Flags indicating chain or termination properties.
+ * @u.addr32: 32-bit physical address.
+ * @u.addr64: 64-bit physical address.
*/
struct leapraid_sge_chain_union {
__le16 len;
@@ -555,8 +568,8 @@ struct leapraid_sge_chain_union {
/**
* struct leapraid_ieee_sge_simple32 - IEEE 32-bit simple SGE format
*
- * @addr: 32-bit physical address of the data buffer
- * @flg_and_len: Combined field for flags and data length
+ * @addr: 32-bit physical address of the data buffer.
+ * @flg_and_len: Combined field for flags and data length.
*/
struct leapraid_ieee_sge_simple32 {
__le32 addr;
@@ -566,10 +579,10 @@ struct leapraid_ieee_sge_simple32 {
/**
* struct leapraid_ieee_sge_simple64 - IEEE 64-bit simple SGE format
*
- * @addr: 64-bit physical address of the data buffer
- * @len: Length of the data segment
- * @r1: Reserved
- * @flg: Flags indicating transfer properties
+ * @addr: 64-bit physical address of the data buffer.
+ * @len: Length of the data segment.
+ * @r1: Reserved.
+ * @flg: Flags indicating transfer properties.
*/
struct leapraid_ieee_sge_simple64 {
__le64 addr;
@@ -581,8 +594,8 @@ struct leapraid_ieee_sge_simple64 {
/**
* union leapraid_ieee_sge_simple_union - Unified IEEE SGE format
*
- * @simple32: IEEE 32-bit simple SGE entry
- * @simple64: IEEE 64-bit simple SGE entry
+ * @simple32: IEEE 32-bit simple SGE entry.
+ * @simple64: IEEE 64-bit simple SGE entry.
*/
union leapraid_ieee_sge_simple_union {
struct leapraid_ieee_sge_simple32 simple32;
@@ -592,8 +605,8 @@ union leapraid_ieee_sge_simple_union {
/**
* union leapraid_ieee_sge_chain_union - Unified IEEE SGE chain format
*
- * @chain32: IEEE 32-bit chain SGE entry
- * @chain64: IEEE 64-bit chain SGE entry
+ * @chain32: IEEE 32-bit chain SGE entry.
+ * @chain64: IEEE 64-bit chain SGE entry.
*/
union leapraid_ieee_sge_chain_union {
struct leapraid_ieee_sge_simple32 chain32;
@@ -603,11 +616,11 @@ union leapraid_ieee_sge_chain_union {
/**
* struct leapraid_chain64_ieee_sg - 64-bit IEEE chain SGE descriptor
*
- * @addr: Physical address of the next chain segment
- * @len: Length of the current SGE
- * @r1: Reserved
- * @next_chain_offset: Offset to the next chain element
- * @flg: Flags that describe SGE attributes
+ * @addr: Physical address of the next chain segment.
+ * @len: Length of the current SGE.
+ * @r1: Reserved.
+ * @next_chain_offset: Offset to the next chain element.
+ * @flg: Flags that describe SGE attributes.
*/
struct leapraid_chain64_ieee_sg {
__le64 addr;
@@ -620,8 +633,8 @@ struct leapraid_chain64_ieee_sg {
/**
* union leapraid_ieee_sge_io_union - IEEE-style SGE union for I/O
*
- * @ieee_simple: Simple IEEE SGE descriptor
- * @ieee_chain: IEEE chain SGE descriptor
+ * @ieee_simple: Simple IEEE SGE descriptor.
+ * @ieee_chain: IEEE chain SGE descriptor.
*/
union leapraid_ieee_sge_io_union {
struct leapraid_ieee_sge_simple64 ieee_simple;
@@ -631,25 +644,25 @@ union leapraid_ieee_sge_io_union {
/**
* union leapraid_simple_sge_union - Union of simple SGE descriptors
*
- * @leapio_simple: LeapIO-style simple SGE
- * @ieee_simple: IEEE-style simple SGE
+ * @leapraid_simple: LeapRAID simple SGE.
+ * @ieee_simple: IEEE-style simple SGE.
*/
union leapraid_simple_sge_union {
- struct leapraid_sge_simple_union leapio_simple;
+ struct leapraid_sge_simple_union leapraid_simple;
union leapraid_ieee_sge_simple_union ieee_simple;
};
/**
* union leapraid_sge_io_union - Combined SGE union for all I/O types
*
- * @leapio_simple: LeapIO simple SGE format
- * @leapio_chain: LeapIO chain SGE format
- * @ieee_simple: IEEE simple SGE format
- * @ieee_chain: IEEE chain SGE format
+ * @leapraid_simple: LeapRAID simple SGE format.
+ * @leapraid_chain: LeapRAID chain SGE format.
+ * @ieee_simple: IEEE simple SGE format.
+ * @ieee_chain: IEEE chain SGE format.
*/
union leapraid_sge_io_union {
- struct leapraid_sge_simple_union leapio_simple;
- struct leapraid_sge_chain_union leapio_chain;
+ struct leapraid_sge_simple_union leapraid_simple;
+ struct leapraid_sge_chain_union leapraid_chain;
union leapraid_ieee_sge_simple_union ieee_simple;
union leapraid_ieee_sge_chain_union ieee_chain;
};
@@ -657,10 +670,10 @@ union leapraid_sge_io_union {
/**
* struct leapraid_cfg_pg_header - Standard configuration page header
*
- * @r1: Reserved
- * @page_len: Length of the page in 4-byte units
- * @page_num: Page number
- * @page_type: Page type
+ * @r1: Reserved.
+ * @page_len: Length of the page in 4-byte units.
+ * @page_num: Page number.
+ * @page_type: Page type.
*/
struct leapraid_cfg_pg_header {
u8 r1;
@@ -672,13 +685,13 @@ struct leapraid_cfg_pg_header {
/**
* struct leapraid_cfg_ext_pg_header - Extended configuration page header
*
- * @r1: Reserved
- * @r2: Reserved
- * @page_num: Page number
- * @page_type: Page type
- * @ext_page_len: Extended page length
- * @ext_page_type: Extended page type
- * @r3: Reserved
+ * @r1: Reserved.
+ * @r2: Reserved.
+ * @page_num: Page number.
+ * @page_type: Page type.
+ * @ext_page_len: Extended page length.
+ * @ext_page_type: Extended page type.
+ * @r3: Reserved.
*/
struct leapraid_cfg_ext_pg_header {
u8 r1;
@@ -693,17 +706,17 @@ struct leapraid_cfg_ext_pg_header {
/**
* struct leapraid_cfg_req - Configuration request message
*
- * @action: Requested action type
- * @sgl_flag: SGL flag field
- * @chain_offset: Offset to next chain SGE
- * @func: Function code
- * @ext_page_len: Extended page length
- * @ext_page_type: Extended page type
- * @msg_flag: Message flags
- * @r1: Reserved
- * @header: Configuration page header
- * @page_addr: Address of the page buffer
- * @page_buf_sge: SGE describing the page buffer
+ * @action: Requested action type.
+ * @sgl_flag: SGL flag field.
+ * @chain_offset: Offset to next chain SGE.
+ * @func: Function code.
+ * @ext_page_len: Extended page length.
+ * @ext_page_type: Extended page type.
+ * @msg_flag: Message flags.
+ * @r1: Reserved.
+ * @header: Configuration page header.
+ * @page_addr: Address of the page buffer.
+ * @page_buf_sge: SGE describing the page buffer.
*/
struct leapraid_cfg_req {
u8 action;
@@ -722,17 +735,17 @@ struct leapraid_cfg_req {
/**
* struct leapraid_cfg_rep - Configuration reply message
*
- * @action: Action type from the request
- * @r1: Reserved
- * @msg_len: Message length in bytes
- * @func: Function code
- * @ext_page_len: Extended page length
- * @ext_page_type: Extended page type
- * @msg_flag: Message flags
- * @r2: Reserved
- * @adapter_status: Adapter status code
- * @r3: Reserved
- * @header: Configuration page header
+ * @action: Action type from the request.
+ * @r1: Reserved.
+ * @msg_len: Message length in bytes.
+ * @func: Function code.
+ * @ext_page_len: Extended page length.
+ * @ext_page_type: Extended page type.
+ * @msg_flag: Message flags.
+ * @r2: Reserved.
+ * @adapter_status: Adapter status code.
+ * @r3: Reserved.
+ * @header: Configuration page header.
*/
struct leapraid_cfg_rep {
u8 action;
@@ -751,9 +764,9 @@ struct leapraid_cfg_rep {
/**
* struct leapraid_boot_dev_format_sas_wwid - Boot device identified by wwid
*
- * @sas_addr: SAS address of the device
- * @lun: Logical unit number
- * @r1: Reserved
+ * @sas_addr: SAS address of the device.
+ * @lun: Logical unit number.
+ * @r1: Reserved.
*/
struct leapraid_boot_dev_format_sas_wwid {
__le64 sas_addr;
@@ -764,10 +777,10 @@ struct leapraid_boot_dev_format_sas_wwid {
/**
* struct leapraid_boot_dev_format_enc_slot - identified by enclosure
*
- * @enc_lid: Enclosure logical ID
- * @r1: Reserved
- * @slot_num: Slot number in the enclosure
- * @r2: Reserved
+ * @enc_lid: Enclosure logical ID.
+ * @r1: Reserved.
+ * @slot_num: Slot number in the enclosure.
+ * @r2: Reserved.
*/
struct leapraid_boot_dev_format_enc_slot {
__le64 enc_lid;
@@ -779,9 +792,9 @@ struct leapraid_boot_dev_format_enc_slot {
/**
* struct leapraid_boot_dev_format_dev_name - Boot device by device name
*
- * @dev_name: Device name identifier
- * @lun: Logical unit number
- * @r1: Reserved
+ * @dev_name: Device name identifier.
+ * @lun: Logical unit number.
+ * @r1: Reserved.
*/
struct leapraid_boot_dev_format_dev_name {
__le64 dev_name;
@@ -792,9 +805,9 @@ struct leapraid_boot_dev_format_dev_name {
/**
* union leapraid_boot_dev_format - Boot device format union
*
- * @sas_wwid: Format using SAS WWID and LUN
- * @enc_slot: Format using enclosure slot and ID
- * @dev_name: Format using device name and LUN
+ * @sas_wwid: Format using SAS WWID and LUN.
+ * @enc_slot: Format using enclosure slot and ID.
+ * @dev_name: Format using device name and LUN.
*/
union leapraid_boot_dev_format {
struct leapraid_boot_dev_format_sas_wwid sas_wwid;
@@ -802,20 +815,39 @@ union leapraid_boot_dev_format {
struct leapraid_boot_dev_format_dev_name dev_name;
};
+/**
+ * struct leapraid_manufacturing_p0 - Manufacturing configuration page 0
+ *
+ * @header: Configuration page header.
+ * @chip_name: Chip name as a 16-byte ASCII string.
+ * @chip_revision: Chip revision as an 8-byte ASCII string.
+ * @board_name: Board name as a 16-byte ASCII string.
+ * @board_assembly: Board assembly as a 16-byte ASCII string.
+ * @board_tracer_number: Board tracer number as a 16-byte ASCII string.
+ */
+struct leapraid_manufacturing_p0 {
+ struct leapraid_cfg_pg_header header;
+ u8 chip_name[16];
+ u8 chip_revision[8];
+ u8 board_name[16];
+ u8 board_assembly[16];
+ u8 board_tracer_number[16];
+};
+
/**
* struct leapraid_bios_page2 - BIOS configuration page 2
*
- * @header: Configuration page header
- * @r1: Reserved
- * @requested_boot_dev_form: Format type of the requested boot device
- * @r2: Reserved
- * @requested_boot_dev: Boot device requested by BIOS or user
- * @requested_alt_boot_dev_form: Format of the alternate boot device
- * @r3: Reserved
- * @requested_alt_boot_dev: Alternate boot device requested
- * @current_boot_dev_form: Format type of the active boot device
- * @r4: Reserved
- * @current_boot_dev: Currently active boot device in use
+ * @header: Configuration page header.
+ * @r1: Reserved.
+ * @requested_boot_dev_form: Format type of the requested boot device.
+ * @r2: Reserved.
+ * @requested_boot_dev: Boot device requested by BIOS or user.
+ * @requested_alt_boot_dev_form: Format of the alternate boot device.
+ * @r3: Reserved.
+ * @requested_alt_boot_dev: Alternate boot device requested.
+ * @current_boot_dev_form: Format type of the active boot device.
+ * @r4: Reserved.
+ * @current_boot_dev: Currently active boot device in use.
*/
struct leapraid_bios_page2 {
struct leapraid_cfg_pg_header header;
@@ -834,10 +866,10 @@ struct leapraid_bios_page2 {
/**
* struct leapraid_bios_page3 - BIOS configuration page 3
*
- * @header: Configuration page header
- * @r1: Reserved
- * @bios_version: BIOS firmware version number
- * @r2: Reserved
+ * @header: Configuration page header.
+ * @r1: Reserved.
+ * @bios_version: BIOS firmware version number.
+ * @r2: Reserved.
*/
struct leapraid_bios_page3 {
struct leapraid_cfg_pg_header header;
@@ -849,9 +881,9 @@ struct leapraid_bios_page3 {
/**
* struct leapraid_raidvol0_phys_disk - Physical disk in RAID volume
*
- * @r1: Reserved
- * @phys_disk_num: Physical disk number within the RAID volume
- * @r2: Reserved
+ * @r1: Reserved.
+ * @phys_disk_num: Physical disk number within the RAID volume.
+ * @r2: Reserved.
*/
struct leapraid_raidvol0_phys_disk {
u8 r1[2];
@@ -862,14 +894,14 @@ struct leapraid_raidvol0_phys_disk {
/**
* struct leapraid_raidvol_p0 - RAID volume configuration page 0
*
- * @header: Configuration page header
- * @dev_hdl: Device handle for the RAID volume
- * @volume_state: State of the RAID volume
- * @volume_type: RAID type
- * @r1: Reserved
- * @num_phys_disks: Number of physical disks in the volume
- * @r2: Reserved
- * @phys_disk: Array of physical disks in this volume
+ * @header: Configuration page header.
+ * @dev_hdl: Device handle for the RAID volume.
+ * @volume_state: State of the RAID volume.
+ * @volume_type: RAID type.
+ * @r1: Reserved.
+ * @num_phys_disks: Number of physical disks in the volume.
+ * @r2: Reserved.
+ * @phys_disk: Array of physical disks in this volume.
*/
struct leapraid_raidvol_p0 {
struct leapraid_cfg_pg_header header;
@@ -885,11 +917,11 @@ struct leapraid_raidvol_p0 {
/**
* struct leapraid_raidvol_p1 - RAID volume configuration page 1
*
- * @header: Configuration page header
- * @dev_hdl: Device handle of the RAID volume
- * @r1: Reserved
- * @wwid: World-wide identifier for the volume
- * @r2: Reserved
+ * @header: Configuration page header.
+ * @dev_hdl: Device handle of the RAID volume.
+ * @r1: Reserved.
+ * @wwid: World-wide identifier for the volume.
+ * @r2: Reserved.
*/
struct leapraid_raidvol_p1 {
struct leapraid_cfg_pg_header header;
@@ -902,11 +934,11 @@ struct leapraid_raidvol_p1 {
/**
* struct leapraid_raidpd_p0 - Physical disk configuration page 0
*
- * @header: Configuration page header
- * @dev_hdl: Device handle of the physical disk
- * @r1: Reserved
- * @phys_disk_num: Physical disk number
- * @r2: Reserved
+ * @header: Configuration page header.
+ * @dev_hdl: Device handle of the physical disk.
+ * @r1: Reserved.
+ * @phys_disk_num: Physical disk number.
+ * @r2: Reserved.
*/
struct leapraid_raidpd_p0 {
struct leapraid_cfg_pg_header header;
@@ -919,14 +951,14 @@ struct leapraid_raidpd_p0 {
/**
* struct leapraid_sas_io_unit0_phy_info - PHY info for SAS I/O unit
*
- * @port: Port number the PHY belongs to
- * @port_flg: Flags describing port status
- * @phy_flg: Flags describing PHY status
- * @neg_link_rate: Negotiated link rate of the PHY
- * @controller_phy_dev_info: Controller PHY device info
- * @attached_dev_hdl: Handle of attached device
- * @controller_dev_hdl: Handle of the controller device
- * @r1: Reserved
+ * @port: Port number the PHY belongs to.
+ * @port_flg: Flags describing port status.
+ * @phy_flg: Flags describing PHY status.
+ * @neg_link_rate: Negotiated link rate of the PHY.
+ * @controller_phy_dev_info: Controller PHY device info.
+ * @attached_dev_hdl: Handle of attached device.
+ * @controller_dev_hdl: Handle of the controller device.
+ * @r1: Reserved.
*/
struct leapraid_sas_io_unit0_phy_info {
u8 port;
@@ -942,11 +974,11 @@ struct leapraid_sas_io_unit0_phy_info {
/**
* struct leapraid_sas_io_unit_p0 - SAS I/O unit configuration page 0
*
- * @header: Extended configuration page header
- * @r1: Reserved
- * @phy_num: Number of PHYs in this unit
- * @r2: Reserved
- * @phy_info: Array of PHY information
+ * @header: Extended configuration page header.
+ * @r1: Reserved.
+ * @phy_num: Number of PHYs in this unit.
+ * @r2: Reserved.
+ * @phy_info: Array of PHY information.
*/
struct leapraid_sas_io_unit_p0 {
struct leapraid_cfg_ext_pg_header header;
@@ -956,54 +988,20 @@ struct leapraid_sas_io_unit_p0 {
struct leapraid_sas_io_unit0_phy_info phy_info[];
};
-/**
- * struct leapraid_sas_io_unit1_phy_info - Placeholder for SAS unit page 1 PHY
- *
- * @r1: Reserved
- */
-struct leapraid_sas_io_unit1_phy_info {
- u8 r1[12];
-};
-
-/**
- * struct leapraid_sas_io_unit_page1 - SAS I/O unit configuration page 1
- *
- * @header: Extended configuration page header
- * @r1: Reserved
- * @narrowport_max_queue_depth: Maximum queue depth for narrow ports
- * @r2: Reserved
- * @wideport_max_queue_depth: Maximum queue depth for wide ports
- * @r3: Reserved
- * @sata_max_queue_depth: Maximum SATA queue depth
- * @r4: Reserved
- * @phy_info: Array of PHY info structures
- */
-struct leapraid_sas_io_unit_page1 {
- struct leapraid_cfg_ext_pg_header header;
- u8 r1[2];
- __le16 narrowport_max_queue_depth;
- u8 r2[2];
- __le16 wideport_max_queue_depth;
- u8 r3;
- u8 sata_max_queue_depth;
- u8 r4[2];
- struct leapraid_sas_io_unit1_phy_info phy_info[];
-};
-
/**
* struct leapraid_exp_p0 - SAS expander page 0
*
- * @header: Extended page header
- * @physical_port: Physical port number
- * @r1: Reserved
- * @enc_hdl: Enclosure handle
- * @sas_address: SAS address of the expander
- * @r2: Reserved
- * @dev_hdl: Device handle of this expander
- * @parent_dev_hdl: Device handle of parent expander
- * @r3: Reserved
- * @phy_num: Number of PHYs
- * @r4: Reserved
+ * @header: Extended page header.
+ * @physical_port: Physical port number.
+ * @r1: Reserved.
+ * @enc_hdl: Enclosure handle.
+ * @sas_address: SAS address of the expander.
+ * @r2: Reserved.
+ * @dev_hdl: Device handle of this expander.
+ * @parent_dev_hdl: Device handle of parent expander.
+ * @r3: Reserved.
+ * @phy_num: Number of PHYs.
+ * @r4: Reserved.
*/
struct leapraid_exp_p0 {
struct leapraid_cfg_ext_pg_header header;
@@ -1022,14 +1020,14 @@ struct leapraid_exp_p0 {
/**
* struct leapraid_exp_p1 - SAS expander page 1
*
- * @header: Extended page header
- * @r1: Reserved
- * @p_link_rate: PHY link rate
- * @hw_link_rate: Hardware supported link rate
- * @attached_dev_hdl: Attached device handle
- * @r2: Reserved
- * @neg_link_rate: Negotiated link rate
- * @r3: Reserved
+ * @header: Extended page header.
+ * @r1: Reserved.
+ * @p_link_rate: PHY link rate.
+ * @hw_link_rate: Hardware supported link rate.
+ * @attached_dev_hdl: Attached device handle.
+ * @r2: Reserved.
+ * @neg_link_rate: Negotiated link rate.
+ * @r3: Reserved.
*/
struct leapraid_exp_p1 {
struct leapraid_cfg_ext_pg_header header;
@@ -1045,25 +1043,25 @@ struct leapraid_exp_p1 {
/**
* struct leapraid_sas_dev_p0 - SAS device page 0
*
- * @header: Extended configuration page header
- * @slot: Slot number
- * @enc_hdl: Enclosure handle
- * @sas_address: SAS address
- * @parent_dev_hdl: Parent device handle
- * @phy_num: Number of PHYs
- * @r1: Reserved
- * @dev_hdl: Device handle
- * @r2: Reserved
- * @dev_info: Device information
- * @flg: Flags
- * @physical_port: Physical port number
- * @max_port_connections: Maximum port connections
- * @dev_name: Device name
- * @port_groups: Number of port groups
- * @r3: Reserved
- * @enc_level: Enclosure level
- * @connector_name: Connector identifier
- * @r4: Reserved
+ * @header: Extended configuration page header.
+ * @slot: Slot number.
+ * @enc_hdl: Enclosure handle.
+ * @sas_address: SAS address.
+ * @parent_dev_hdl: Parent device handle.
+ * @phy_num: Number of PHYs.
+ * @r1: Reserved.
+ * @dev_hdl: Device handle.
+ * @r2: Reserved.
+ * @dev_info: Device information.
+ * @flg: Flags.
+ * @physical_port: Physical port number.
+ * @max_port_connections: Maximum port connections.
+ * @dev_name: Device name.
+ * @port_groups: Number of port groups.
+ * @r3: Reserved.
+ * @enc_level: Enclosure level.
+ * @connector_name: Connector identifier.
+ * @r4: Reserved.
*/
struct leapraid_sas_dev_p0 {
struct leapraid_cfg_ext_pg_header header;
@@ -1083,23 +1081,23 @@ struct leapraid_sas_dev_p0 {
u8 port_groups;
u8 r3[2];
u8 enc_level;
- u8 connector_name[4];
+ u8 connector_name[LEAPRAID_SAS_DEV_P0_CON_NAME_LEN];
u8 r4[4];
} __packed __aligned(4);
/**
* struct leapraid_sas_phy_p0 - SAS PHY configuration page 0
*
- * @header: Extended configuration page header
- * @r1: Reserved
- * @attached_dev_hdl: Handle of attached device
- * @r2: Reserved
- * @p_link_rate: PHY link rate
- * @hw_link_rate: Hardware supported link rate
- * @r3: Reserved
- * @phy_info: PHY information
- * @neg_link_rate: Negotiated link rate
- * @r4: Reserved
+ * @header: Extended configuration page header.
+ * @r1: Reserved.
+ * @attached_dev_hdl: Handle of attached device.
+ * @r2: Reserved.
+ * @p_link_rate: PHY link rate.
+ * @hw_link_rate: Hardware supported link rate.
+ * @r3: Reserved.
+ * @phy_info: PHY information.
+ * @neg_link_rate: Negotiated link rate.
+ * @r4: Reserved.
*/
struct leapraid_sas_phy_p0 {
struct leapraid_cfg_ext_pg_header header;
@@ -1117,12 +1115,12 @@ struct leapraid_sas_phy_p0 {
/**
* struct leapraid_enc_p0 - SAS enclosure page 0
*
- * @header: Extended configuration page header
- * @r1: Reserved
- * @enc_lid: Enclosure logical ID
- * @r2: Reserved
- * @enc_hdl: Enclosure handle
- * @r3: Reserved
+ * @header: Extended configuration page header.
+ * @r1: Reserved.
+ * @enc_lid: Enclosure logical ID.
+ * @r2: Reserved.
+ * @enc_hdl: Enclosure handle.
+ * @r3: Reserved.
*/
struct leapraid_enc_p0 {
struct leapraid_cfg_ext_pg_header header;
@@ -1136,10 +1134,10 @@ struct leapraid_enc_p0 {
/**
* struct leapraid_raid_cfg_p0_element - RAID configuration element
*
- * @element_flg: Element flags
- * @vol_dev_hdl: Volume device handle
- * @r1: Reserved
- * @phys_disk_dev_hdl: Physical disk device handle
+ * @element_flg: Element flags.
+ * @vol_dev_hdl: Volume device handle.
+ * @r1: Reserved.
+ * @phys_disk_dev_hdl: Physical disk device handle.
*/
struct leapraid_raid_cfg_p0_element {
__le16 element_flg;
@@ -1151,13 +1149,13 @@ struct leapraid_raid_cfg_p0_element {
/**
* struct leapraid_raid_cfg_p0 - RAID configuration page 0
*
- * @header: Extended configuration page header
- * @r1: Reserved
- * @cfg_num: Configuration number
- * @r2: Reserved
- * @elements_num: Number of RAID elements
- * @r3: Reserved
- * @cfg_element: Array of RAID elements
+ * @header: Extended configuration page header.
+ * @r1: Reserved.
+ * @cfg_num: Configuration number.
+ * @r2: Reserved.
+ * @elements_num: Number of RAID elements.
+ * @r3: Reserved.
+ * @cfg_element: Array of RAID elements.
*/
struct leapraid_raid_cfg_p0 {
struct leapraid_cfg_ext_pg_header header;
@@ -1172,8 +1170,8 @@ struct leapraid_raid_cfg_p0 {
/**
* union leapraid_mpi_scsi_io_cdb_union - SCSI I/O CDB or simple SGE
*
- * @cdb32: 32-byte SCSI command descriptor block
- * @sge: Simple SGE format
+ * @cdb32: 32-byte SCSI command descriptor block.
+ * @sge: Simple SGE format.
*/
union leapraid_mpi_scsi_io_cdb_union {
u8 cdb32[32];
@@ -1183,32 +1181,32 @@ union leapraid_mpi_scsi_io_cdb_union {
/**
* struct leapraid_mpi_scsiio_req - MPI SCSI I/O request
*
- * @dev_hdl: Device handle for the target
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @r1: Reserved
- * @msg_flg: Message flags
- * @r2: Reserved
- * @sense_buffer_low_add: Lower 32-bit address of sense buffer
- * @dma_flag: DMA flags
- * @r3: Reserved
- * @sense_buffer_len: Sense buffer length
- * @r4: Reserved
- * @sgl_offset0..3: SGL offsets
- * @skip_count: Bytes to skip before transfer
- * @data_len: Length of data transfer
- * @bi_dir_data_len: Bi-directional transfer length
- * @io_flg: I/O flags
- * @eedp_flag: EEDP flags
- * @eedp_block_size: EEDP block size
- * @r5: Reserved
- * @secondary_ref_tag: Secondary reference tag
- * @secondary_app_tag: Secondary application tag
- * @app_tag_trans_mask: Application tag mask
- * @lun: Logical Unit Number
- * @ctrl: Control flags
- * @cdb: SCSI Command Descriptor Block or simple SGE
- * @sgl: Scatter-gather list
+ * @dev_hdl: Device handle for the target.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @r1: Reserved.
+ * @msg_flg: Message flags.
+ * @r2: Reserved.
+ * @sense_buffer_low_add: Lower 32-bit address of sense buffer.
+ * @dma_flag: DMA flags.
+ * @r3: Reserved.
+ * @sense_buffer_len: Sense buffer length.
+ * @r4: Reserved.
+ * @sgl_offset0..3: SGL offsets.
+ * @skip_count: Bytes to skip before transfer.
+ * @data_len: Length of data transfer.
+ * @bi_dir_data_len: Bi-directional transfer length.
+ * @io_flg: I/O flags.
+ * @eedp_flag: End-to-end data protection flags.
+ * @eedp_block_size: End-to-end data protection block size.
+ * @r5: Reserved.
+ * @secondary_ref_tag: Secondary reference tag.
+ * @secondary_app_tag: Secondary application tag.
+ * @app_tag_trans_mask: Application tag mask.
+ * @lun: Logical Unit Number.
+ * @ctrl: Control flags.
+ * @cdb: SCSI Command Descriptor Block or simple SGE.
+ * @sgl: Scatter-gather list.
*/
struct leapraid_mpi_scsiio_req {
__le16 dev_hdl;
@@ -1245,8 +1243,8 @@ struct leapraid_mpi_scsiio_req {
/**
* union leapraid_scsi_io_cdb_union - SCSI I/O CDB or IEEE simple SGE
*
- * @cdb32: 32-byte SCSI CDB
- * @sge: IEEE simple 64-bit SGE
+ * @cdb32: 32-byte SCSI CDB.
+ * @sge: IEEE simple 64-bit SGE.
*/
union leapraid_scsi_io_cdb_union {
u8 cdb32[32];
@@ -1256,32 +1254,32 @@ union leapraid_scsi_io_cdb_union {
/**
* struct leapraid_scsiio_req - SCSI I/O request
*
- * @dev_hdl: Device handle
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @r1: Reserved
- * @msg_flg: Message flags
- * @r2: Reserved
- * @sense_buffer_low_add: Lower 32-bit address of sense buffer
- * @dma_flag: DMA flag
- * @r3: Reserved
- * @sense_buffer_len: Sense buffer length
- * @r4: Reserved
- * @sgl_offset0-3: SGL offsets
- * @skip_count: Bytes to skip before transfer
- * @data_len: Length of data transfer
- * @bi_dir_data_len: Bi-directional transfer length
- * @io_flg: I/O flags
- * @eedp_flag: EEDP flags
- * @eedp_block_size: EEDP block size
- * @r5: Reserved
- * @secondary_ref_tag: Secondary reference tag
- * @secondary_app_tag: Secondary application tag
- * @app_tag_trans_mask: Application tag mask
- * @lun: Logical Unit Number
- * @ctrl: Control flags
- * @cdb: SCSI Command Descriptor Block or simple SGE
- * @sgl: Scatter-gather list
+ * @dev_hdl: Device handle.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @r1: Reserved.
+ * @msg_flg: Message flags.
+ * @r2: Reserved.
+ * @sense_buffer_low_add: Lower 32-bit address of sense buffer.
+ * @dma_flag: DMA flag.
+ * @r3: Reserved.
+ * @sense_buffer_len: Sense buffer length.
+ * @r4: Reserved.
+ * @sgl_offset0-3: SGL offsets.
+ * @skip_count: Bytes to skip before transfer.
+ * @data_len: Length of data transfer.
+ * @bi_dir_data_len: Bi-directional transfer length.
+ * @io_flg: I/O flags.
+ * @eedp_flag: End-to-end data protection flags.
+ * @eedp_block_size: End-to-end data protection block size.
+ * @r5: Reserved.
+ * @secondary_ref_tag: Secondary reference tag.
+ * @secondary_app_tag: Secondary application tag.
+ * @app_tag_trans_mask: Application tag mask.
+ * @lun: Logical Unit Number.
+ * @ctrl: Control flags.
+ * @cdb: SCSI Command Descriptor Block or simple SGE.
+ * @sgl: Scatter-gather list.
*/
struct leapraid_scsiio_req {
__le16 dev_hdl;
@@ -1318,23 +1316,23 @@ struct leapraid_scsiio_req {
/**
* struct leapraid_scsiio_rep - SCSI I/O response
*
- * @dev_hdl: Device handle
- * @msg_len: Length of response message
- * @func: Function code
- * @r1: Reserved
- * @msg_flg: Message flags
- * @r2: Reserved
- * @scsi_status: SCSI status
- * @scsi_state: SCSI state
- * @adapter_status: Adapter status
- * @r3: Reserved
- * @transfer_count: Number of bytes transferred
- * @sense_count: Number of sense bytes
- * @resp_info: Additional response info
- * @task_tag: Task identifier
- * @scsi_status_qualifier: SCSI status qualifier
- * @bi_dir_trans_count: Bi-directional transfer count
- * @r4: Reserved
+ * @dev_hdl: Device handle.
+ * @msg_len: Length of response message.
+ * @func: Function code.
+ * @r1: Reserved.
+ * @msg_flg: Message flags.
+ * @r2: Reserved.
+ * @scsi_status: SCSI status.
+ * @scsi_state: SCSI state.
+ * @adapter_status: Adapter status.
+ * @r3: Reserved.
+ * @transfer_count: Number of bytes transferred.
+ * @sense_count: Number of sense bytes.
+ * @resp_info: Additional response info.
+ * @task_tag: Task identifier.
+ * @scsi_status_qualifier: SCSI status qualifier.
+ * @bi_dir_trans_count: Bi-directional transfer count.
+ * @r4: Reserved.
*/
struct leapraid_scsiio_rep {
__le16 dev_hdl;
@@ -1359,18 +1357,18 @@ struct leapraid_scsiio_rep {
/**
* struct leapraid_scsi_tm_req - SCSI Task Management request
*
- * @dev_hdl: Device handle
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @r1: Reserved
- * @task_type: Task management function type
- * @r2: Reserved
- * @msg_flg: Message flags
- * @r3: Reserved
- * @lun: Logical Unit Number
- * @r4: Reserved
- * @task_mid: Task identifier
- * @r5: Reserved
+ * @dev_hdl: Device handle.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @r1: Reserved.
+ * @task_type: Task management function type.
+ * @r2: Reserved.
+ * @msg_flg: Message flags.
+ * @r3: Reserved.
+ * @lun: Logical Unit Number.
+ * @r4: Reserved.
+ * @task_mid: Task identifier.
+ * @r5: Reserved.
*/
struct leapraid_scsi_tm_req {
__le16 dev_hdl;
@@ -1390,18 +1388,18 @@ struct leapraid_scsi_tm_req {
/**
* struct leapraid_scsi_tm_rep - SCSI Task Management response
*
- * @dev_hdl: Device handle
- * @msg_len: Length of response message
- * @func: Function code
- * @resp_code: Response code
- * @task_type: Task management type
- * @r1: Reserved
- * @msg_flag: Message flags
- * @r2: Reserved
- * @adapter_status: Adapter status
- * @r3: Reserved
- * @termination_count: Count of terminated tasks
- * @response_info: Additional response info
+ * @dev_hdl: Device handle.
+ * @msg_len: Length of response message.
+ * @func: Function code.
+ * @resp_code: Response code.
+ * @task_type: Task management type.
+ * @r1: Reserved.
+ * @msg_flag: Message flags.
+ * @r2: Reserved.
+ * @adapter_status: Adapter status.
+ * @r3: Reserved.
+ * @termination_count: Count of terminated tasks.
+ * @response_info: Additional response info.
*/
struct leapraid_scsi_tm_rep {
__le16 dev_hdl;
@@ -1421,18 +1419,18 @@ struct leapraid_scsi_tm_rep {
/**
* struct leapraid_sep_req - SEP (SCSI Enclosure Processor) request
*
- * @dev_hdl: Device handle
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @act: Action to perform
- * @flg: Flags
- * @r1: Reserved
- * @msg_flag: Message flags
- * @r2: Reserved
- * @slot_status: Slot status
- * @r3: Reserved
- * @slot: Slot number
- * @enc_hdl: Enclosure handle
+ * @dev_hdl: Device handle.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @act: Action to perform.
+ * @flg: Flags.
+ * @r1: Reserved.
+ * @msg_flag: Message flags.
+ * @r2: Reserved.
+ * @slot_status: Slot status.
+ * @r3: Reserved.
+ * @slot: Slot number.
+ * @enc_hdl: Enclosure handle.
*/
struct leapraid_sep_req {
__le16 dev_hdl;
@@ -1452,19 +1450,19 @@ struct leapraid_sep_req {
/**
* struct leapraid_sep_rep - SEP response
*
- * @dev_hdl: Device handle
- * @msg_len: Message length
- * @func: Function code
- * @act: Action performed
- * @flg: Flags
- * @msg_flag: Message flags
- * @r1: Reserved
- * @adapter_status: Adapter status
- * @r2: Reserved
- * @slot_status: Slot status
- * @r3: Reserved
- * @slot: Slot number
- * @enc_hdl: Enclosure handle
+ * @dev_hdl: Device handle.
+ * @msg_len: Message length.
+ * @func: Function code.
+ * @act: Action performed.
+ * @flg: Flags.
+ * @msg_flag: Message flags.
+ * @r1: Reserved.
+ * @adapter_status: Adapter status.
+ * @r2: Reserved.
+ * @slot_status: Slot status.
+ * @r3: Reserved.
+ * @slot: Slot number.
+ * @enc_hdl: Enclosure handle.
*/
struct leapraid_sep_rep {
__le16 dev_hdl;
@@ -1486,29 +1484,29 @@ struct leapraid_sep_rep {
/**
* struct leapraid_adapter_init_req - Adapter initialization request
*
- * @who_init: Initiator of the initialization
- * @r1: Reserved
- * @chain_offset: Chain offset
- * @func: Function code
- * @r2: Reserved
- * @msg_flg: Message flags
- * @r3: Reserved
- * @msg_ver: Message version
- * @header_ver: Header version
- * @host_buf_addr: Host buffer address (non adapter-ref)
- * @r4: Reserved
- * @host_buf_size: Host buffer size (non adapter-ref)
- * @host_msix_vectors: Number of host MSI-X vectors
- * @r6: Reserved
- * @req_frame_size: Request frame size
- * @rep_desc_qd: Reply descriptor queue depth
- * @rep_msg_qd: Reply message queue depth
- * @sense_buffer_add_high: High 32-bit of sense buffer address
- * @rep_msg_dma_high: High 32-bit of reply message DMA address
- * @task_desc_base_addr: Base address of task descriptors
- * @rep_desc_q_arr_addr: Address of reply descriptor queue array
- * @rep_msg_addr_dma: Reply message DMA address
- * @time_stamp: Timestamp
+ * @who_init: Initiator of the initialization.
+ * @r1: Reserved.
+ * @chain_offset: Chain offset.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @msg_flg: Message flags.
+ * @r3: Reserved.
+ * @msg_ver: Message version.
+ * @header_ver: Header version.
+ * @host_buf_addr: Host buffer address (non adapter-ref).
+ * @r4: Reserved.
+ * @host_buf_size: Host buffer size (non adapter-ref).
+ * @host_msix_vectors: Number of host MSI-X vectors.
+ * @r6: Reserved.
+ * @req_frame_size: Request frame size.
+ * @rep_desc_qd: Reply descriptor queue depth.
+ * @rep_msg_qd: Reply message queue depth.
+ * @sense_buffer_add_high: High 32-bit of sense buffer address.
+ * @rep_msg_dma_high: High 32-bit of reply message DMA address.
+ * @task_desc_base_addr: Base address of task descriptors.
+ * @rep_desc_q_arr_addr: Address of reply descriptor queue array.
+ * @rep_msg_addr_dma: Reply message DMA address.
+ * @time_stamp: Timestamp.
*/
struct leapraid_adapter_init_req {
u8 who_init;
@@ -1539,8 +1537,8 @@ struct leapraid_adapter_init_req {
/**
* struct leapraid_rep_desc_q_arr - Reply descriptor queue array
*
- * @rep_desc_base_addr: Base address of the reply descriptors
- * @r1: Reserved
+ * @rep_desc_base_addr: Base address of the reply descriptors.
+ * @r1: Reserved.
*/
struct leapraid_rep_desc_q_arr {
__le64 rep_desc_base_addr;
@@ -1550,15 +1548,15 @@ struct leapraid_rep_desc_q_arr {
/**
* struct leapraid_adapter_init_rep - Adapter initialization reply
*
- * @who_init: Initiator of the initialization
- * @r1: Reserved
- * @msg_len: Length of reply message
- * @func: Function code
- * @r2: Reserved
- * @msg_flag: Message flags
- * @r3: Reserved
- * @adapter_status: Adapter status
- * @r4: Reserved
+ * @who_init: Initiator of the initialization.
+ * @r1: Reserved.
+ * @msg_len: Length of reply message.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @msg_flag: Message flags.
+ * @r3: Reserved.
+ * @adapter_status: Adapter status.
+ * @r4: Reserved.
*/
struct leapraid_adapter_init_rep {
u8 who_init;
@@ -1575,15 +1573,15 @@ struct leapraid_adapter_init_rep {
/**
* struct leapraid_adapter_log_req - Adapter log request
*
- * @action: Action code
- * @type: Log type
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * r1: Reserved
- * @msg_flag: Message flags
- * r2: Reserved
- * @mbox: Mailbox for command-specific parameters
- * @sge: Scatter-gather entry for data buffer
+ * @action: Action code.
+ * @type: Log type.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * r1: Reserved.
+ * @msg_flag: Message flags.
+ * r2: Reserved.
+ * @mbox: Mailbox for command-specific parameters.
+ * @sge: Scatter-gather entry for data buffer.
*/
struct leapraid_adapter_log_req {
u8 action;
@@ -1604,14 +1602,14 @@ struct leapraid_adapter_log_req {
/**
* struct leapraid_adapter_log_rep - Adapter log reply
*
- * @action: Action code echoed
- * @type: Log type echoed
- * @msg_len: Length of message
- * @func: Function code
- * @r1: Reserved
- * @msg_flag: Message flags
- * @r2: Reserved
- * @adapter_status: Status returned by adapter
+ * @action: Action code echoed.
+ * @type: Log type echoed.
+ * @msg_len: Length of message.
+ * @func: Function code.
+ * @r1: Reserved.
+ * @msg_flag: Message flags.
+ * @r2: Reserved.
+ * @adapter_status: Status returned by adapter.
*/
struct leapraid_adapter_log_rep {
u8 action;
@@ -1627,12 +1625,12 @@ struct leapraid_adapter_log_rep {
/**
* struct leapraid_adapter_features_req - Request adapter features
*
- * @r1: Reserved
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @r2: Reserved
- * @msg_flag: Message flags
- * @r3: Reserved
+ * @r1: Reserved.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @msg_flag: Message flags.
+ * @r3: Reserved.
*/
struct leapraid_adapter_features_req {
u8 r1[2];
@@ -1646,32 +1644,32 @@ struct leapraid_adapter_features_req {
/**
* struct leapraid_adapter_features_rep - Adapter features reply
*
- * @msg_ver: Message version
- * @msg_len: Length of reply message
- * @func: Function code
- * @header_ver: Header version
- * @r1: Reserved
- * @msg_flag: Message flags
- * @r2: Reserved
- * @adapter_status: Adapter status
- * @r3: Reserved
- * @who_init: Who initialized the adapter
- * @r4: Reserved
- * @max_msix_vectors: Max MSI-X vectors supported
- * @req_slot: Number of request slots
- * @r5: Reserved
- * @adapter_caps: Adapter capabilities
- * @fw_version: Firmware version
- * @sas_wide_max_qdepth: Max wide SAS queue depth
- * @sas_narrow_max_qdepth: Max narrow SAS queue depth
- * @r6: Reserved
- * @hp_slot: Number of high-priority slots
- * @r7: Reserved
- * @max_volumes: Maximum supported volumes
- * @max_dev_hdl: Maximum device handle
- * @r8: Reserved
- * @min_dev_hdl: Minimum device handle
- * @r9: Reserved
+ * @msg_ver: Message version.
+ * @msg_len: Length of reply message.
+ * @func: Function code.
+ * @header_ver: Header version.
+ * @r1: Reserved.
+ * @msg_flag: Message flags.
+ * @r2: Reserved.
+ * @adapter_status: Adapter status.
+ * @r3: Reserved.
+ * @who_init: Who initialized the adapter.
+ * @r4: Reserved.
+ * @max_msix_vectors: Max MSI-X vectors supported.
+ * @req_slot: Number of request slots.
+ * @r5: Reserved.
+ * @adapter_caps: Adapter capabilities.
+ * @fw_version: Firmware version.
+ * @sas_wide_max_qdepth: Max wide SAS queue depth.
+ * @sas_narrow_max_qdepth: Max narrow SAS queue depth.
+ * @r6: Reserved.
+ * @hp_slot: Number of high-priority slots.
+ * @r7: Reserved.
+ * @max_volumes: Maximum supported volumes.
+ * @max_dev_hdl: Maximum device handle.
+ * @r8: Reserved.
+ * @min_dev_hdl: Minimum device handle.
+ * @r9: Reserved.
*/
struct leapraid_adapter_features_rep {
u16 msg_ver;
@@ -1706,12 +1704,12 @@ struct leapraid_adapter_features_rep {
/**
* struct leapraid_scan_dev_req - Request to scan devices
*
- * @r1: Reserved
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @r2: Reserved
- * @msg_flag: Message flags
- * @r3: Reserved
+ * @r1: Reserved.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @msg_flag: Message flags.
+ * @r3: Reserved.
*/
struct leapraid_scan_dev_req {
u8 r1[2];
@@ -1725,14 +1723,14 @@ struct leapraid_scan_dev_req {
/**
* struct leapraid_scan_dev_rep - Scan devices reply
*
- * @r1: Reserved
- * @msg_len: Length of message
- * @func: Function code
- * @r2: Reserved
- * @msg_flag: Message flags
- * @r3: Reserved
- * @adapter_status: Adapter status
- * @r4: Reserved
+ * @r1: Reserved.
+ * @msg_len: Length of message.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @msg_flag: Message flags.
+ * @r3: Reserved.
+ * @adapter_status: Adapter status.
+ * @r4: Reserved.
*/
struct leapraid_scan_dev_rep {
u8 r1[2];
@@ -1748,14 +1746,14 @@ struct leapraid_scan_dev_rep {
/**
* struct leapraid_evt_notify_req - Event notification request
*
- * @r1: Reserved
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @r2: Reserved
- * @msg_flag: Message flags
- * @r3: Reserved
- * @evt_masks: Event masks to enable notifications
- * @r4: Reserved
+ * @r1: Reserved.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @msg_flag: Message flags.
+ * @r3: Reserved.
+ * @evt_masks: Event masks to enable notifications.
+ * @r4: Reserved.
*/
struct leapraid_evt_notify_req {
u8 r1[2];
@@ -1771,18 +1769,18 @@ struct leapraid_evt_notify_req {
/**
* struct leapraid_evt_notify_rep - Event notification reply
*
- * @evt_data_len: Length of event data
- * @msg_len: Length of message
- * @func: Function code
- * @r1: Reserved
- * @r2: Reserved
- * @msg_flag: Message flags
- * @r3: Reserved
- * @adapter_status: Adapter status
- * @r4: Reserved
- * @evt: Event code
- * @r5: Reserved
- * @evt_data: Event data array
+ * @evt_data_len: Length of event data.
+ * @msg_len: Length of message.
+ * @func: Function code.
+ * @r1: Reserved.
+ * @r2: Reserved.
+ * @msg_flag: Message flags.
+ * @r3: Reserved.
+ * @adapter_status: Adapter status.
+ * @r4: Reserved.
+ * @evt: Event code.
+ * @r5: Reserved.
+ * @evt_data: Event data array.
*/
struct leapraid_evt_notify_rep {
__le16 evt_data_len;
@@ -1802,14 +1800,14 @@ struct leapraid_evt_notify_rep {
/**
* struct leapraid_evt_data_sas_dev_status_change - SAS device status change
*
- * @task_tag: Task identifier
- * @reason_code: Reason for status change
- * @physical_port: Physical port number
- * @r1: Reserved
- * @dev_hdl: Device handle
- * @r2: Reserved
- * @sas_address: SAS address of device
- * @lun: Logical Unit Number
+ * @task_tag: Task identifier.
+ * @reason_code: Reason for status change.
+ * @physical_port: Physical port number.
+ * @r1: Reserved.
+ * @dev_hdl: Device handle.
+ * @r2: Reserved.
+ * @sas_address: SAS address of device.
+ * @lun: Logical unit Number.
*/
struct leapraid_evt_data_sas_dev_status_change {
__le16 task_tag;
@@ -1824,11 +1822,11 @@ struct leapraid_evt_data_sas_dev_status_change {
/**
* struct leapraid_evt_data_ir_change - IR (Integrated RAID) change event data
*
- * @r1: Reserved
- * @reason_code: Reason for IR change
- * @r2: Reserved
- * @vol_dev_hdl: Volume device handle
- * @phys_disk_dev_hdl: Physical disk device handle
+ * @r1: Reserved.
+ * @reason_code: Reason for IR change.
+ * @r2: Reserved.
+ * @vol_dev_hdl: Volume device handle.
+ * @phys_disk_dev_hdl: Physical disk device handle.
*/
struct leapraid_evt_data_ir_change {
u8 r1;
@@ -1841,10 +1839,10 @@ struct leapraid_evt_data_ir_change {
/**
* struct leapraid_evt_data_sas_disc - SAS discovery event data
*
- * @r1: Reserved
- * @reason_code: Reason for discovery event
- * @physical_port: Physical port number where event occurred
- * @r2: Reserved
+ * @r1: Reserved.
+ * @reason_code: Reason for discovery event.
+ * @physical_port: Physical port number where event occurred.
+ * @r2: Reserved.
*/
struct leapraid_evt_data_sas_disc {
u8 r1;
@@ -1856,9 +1854,9 @@ struct leapraid_evt_data_sas_disc {
/**
* struct leapraid_evt_sas_topo_phy_entry - SAS topology PHY entry
*
- * @attached_dev_hdl: Device handle attached to PHY
- * @link_rate: Current link rate
- * @phy_status: PHY status flags
+ * @attached_dev_hdl: Device handle attached to PHY.
+ * @link_rate: Current link rate.
+ * @phy_status: PHY status flags.
*/
struct leapraid_evt_sas_topo_phy_entry {
__le16 attached_dev_hdl;
@@ -1869,15 +1867,15 @@ struct leapraid_evt_sas_topo_phy_entry {
/**
* struct leapraid_evt_data_sas_topo_change_list - SAS topology change list
*
- * @encl_hdl: Enclosure handle
- * @exp_dev_hdl: Expander device handle
- * @num_phys: Number of PHYs in this entry
- * @r1: Reserved
- * @entry_num: Entry index
- * @start_phy_num: Start PHY number
- * @exp_status: Expander status
- * @physical_port: Physical port number
- * @phy: Array of SAS PHY entries
+ * @encl_hdl: Enclosure handle.
+ * @exp_dev_hdl: Expander device handle.
+ * @num_phys: Number of PHYs in this entry.
+ * @r1: Reserved.
+ * @entry_num: Entry index.
+ * @start_phy_num: Start PHY number.
+ * @exp_status: Expander status.
+ * @physical_port: Physical port number.
+ * @phy: Array of SAS PHY entries.
*/
struct leapraid_evt_data_sas_topo_change_list {
__le16 encl_hdl;
@@ -1892,15 +1890,16 @@ struct leapraid_evt_data_sas_topo_change_list {
};
/**
- * struct leapraid_evt_data_sas_enc_dev_status_change - SAS enclosure device status
+ * struct leapraid_evt_data_sas_enc_dev_status_change -
+ * SAS enclosure device status
*
- * @enc_hdl: Enclosure handle
- * @reason_code: Reason code for status change
- * @physical_port: Physical port number
- * @encl_logical_id: Enclosure logical ID
- * @num_slots: Number of slots in enclosure
- * @start_slot: First affected slot
- * @phy_bits: Bitmap of affected PHYs
+ * @enc_hdl: Enclosure handle.
+ * @reason_code: Reason code for status change.
+ * @physical_port: Physical port number.
+ * @encl_logical_id: Enclosure logical ID.
+ * @num_slots: Number of slots in enclosure.
+ * @start_slot: First affected slot.
+ * @phy_bits: Bitmap of affected PHYs.
*/
struct leapraid_evt_data_sas_enc_dev_status_change {
__le16 enc_hdl;
@@ -1913,21 +1912,21 @@ struct leapraid_evt_data_sas_enc_dev_status_change {
};
/**
- * struct leapraid_io_unit_ctrl_req - IO unit control request
+ * struct leapraid_io_unit_ctrl_req - I/O unit control request
*
- * @op: Operation code
- * @r1: Reserved
- * @chain_offset: SGE chain offset
- * @func: Function code
- * @dev_hdl: Device handle
- * @adapter_para: Adapter parameter selector
- * @msg_flag: Message flags
- * @r2: Reserved
- * @phy_num: PHY number
- * @r3: Reserved
- * @adapter_para_value: Value for adapter parameter
- * @adapter_para_value2: Optional second parameter value
- * @r4: Reserved
+ * @op: Operation code.
+ * @r1: Reserved.
+ * @chain_offset: SGE chain offset.
+ * @func: Function code.
+ * @dev_hdl: Device handle.
+ * @adapter_para: Adapter parameter selector.
+ * @msg_flag: Message flags.
+ * @r2: Reserved.
+ * @phy_num: PHY number.
+ * @r3: Reserved.
+ * @adapter_para_value: Value for adapter parameter.
+ * @adapter_para_value2: Optional second parameter value.
+ * @r4: Reserved.
*/
struct leapraid_io_unit_ctrl_req {
u8 op;
@@ -1946,13 +1945,13 @@ struct leapraid_io_unit_ctrl_req {
};
/**
- * struct leapraid_io_unit_ctrl_rep - IO unit control reply
+ * struct leapraid_io_unit_ctrl_rep - I/O unit control reply
*
- * @op: Operation code echoed
- * @r1: Reserved
- * @func: Function code
- * @dev_hdl: Device handle
- * @r2: Reserved
+ * @op: Operation code echoed.
+ * @r1: Reserved.
+ * @func: Function code.
+ * @dev_hdl: Device handle.
+ * @r2: Reserved.
*/
struct leapraid_io_unit_ctrl_rep {
u8 op;
@@ -1965,13 +1964,13 @@ struct leapraid_io_unit_ctrl_rep {
/**
* struct leapraid_raid_act_req - RAID action request
*
- * @act: RAID action code
- * @r1: Reserved
- * @func: Function code
- * @r2: Reserved
- * @phys_disk_num: Number of physical disks involved
- * @r3: Reserved
- * @action_data_sge: SGE describing action-specific data
+ * @act: RAID action code.
+ * @r1: Reserved.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @phys_disk_num: Number of physical disks involved.
+ * @r3: Reserved.
+ * @action_data_sge: SGE describing action-specific data.
*/
struct leapraid_raid_act_req {
u8 act;
@@ -1986,13 +1985,13 @@ struct leapraid_raid_act_req {
/**
* struct leapraid_raid_act_rep - RAID action reply
*
- * @act: RAID action code echoed
- * @r1: Reserved
- * @func: Function code
- * @vol_dev_hdl: Volume device handle
+ * @act: RAID action code echoed.
+ * @r1: Reserved.
+ * @func: Function code.
+ * @vol_dev_hdl: Volume device handle.
* @r2: Reserved
- * @adapter_status: Status returned by adapter
- * @r3: Reserved
+ * @adapter_status: Status returned by adapter.
+ * @r3: Reserved.
*/
struct leapraid_raid_act_rep {
u8 act;
@@ -2007,15 +2006,15 @@ struct leapraid_raid_act_rep {
/**
* struct leapraid_smp_passthrough_req - SMP passthrough request
*
- * @passthrough_flg: Passthrough flags
- * @physical_port: Target PHY port
- * @r1: Reserved
- * @func: Function code
- * @req_data_len: Request data length
- * @r2: Reserved
- * @sas_address: SAS address of target device
- * @r3: Reserved
- * @sgl: Scatter-gather list describing request buffer
+ * @passthrough_flg: Passthrough flags.
+ * @physical_port: Target PHY port.
+ * @r1: Reserved.
+ * @func: Function code.
+ * @req_data_len: Request data length.
+ * @r2: Reserved.
+ * @sas_address: SAS address of target device.
+ * @r3: Reserved.
+ * @sgl: Scatter-gather list describing request buffer.
*/
struct leapraid_smp_passthrough_req {
u8 passthrough_flg;
@@ -2032,14 +2031,14 @@ struct leapraid_smp_passthrough_req {
/**
* struct leapraid_smp_passthrough_rep - SMP passthrough reply
*
- * @passthrough_flg: Passthrough flags echoed
- * @physical_port: Target PHY port
- * @r1: Reserved
- * @func: Function code
- * @resp_data_len: Length of response data
- * @r2: Reserved
- * @adapter_status: Adapter status
- * @r3: Reserved
+ * @passthrough_flg: Passthrough flags echoed.
+ * @physical_port: Target PHY port.
+ * @r1: Reserved.
+ * @func: Function code.
+ * @resp_data_len: Length of response data.
+ * @r2: Reserved.
+ * @adapter_status: Adapter status.
+ * @r3: Reserved.
*/
struct leapraid_smp_passthrough_rep {
u8 passthrough_flg;
@@ -2053,13 +2052,13 @@ struct leapraid_smp_passthrough_rep {
};
/**
- * struct leapraid_sas_io_unit_ctrl_req - SAS IO unit control request
+ * struct leapraid_sas_io_unit_ctrl_req - SAS I/O unit control request
*
- * @op: Operation code
- * @r1: Reserved
- * @func: Function code
- * @dev_hdl: Device handle
- * @r2: Reserved
+ * @op: Operation code.
+ * @r1: Reserved.
+ * @func: Function code.
+ * @dev_hdl: Device handle.
+ * @r2: Reserved.
*/
struct leapraid_sas_io_unit_ctrl_req {
u8 op;
diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c
index f838bd5aa20e..25ec57c2ce4b 100644
--- a/drivers/scsi/leapraid/leapraid_app.c
+++ b/drivers/scsi/leapraid/leapraid_app.c
@@ -1,23 +1,22 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2025 LeapIO Tech Inc.
+ * Copyright (C) 2026 LeapIO Tech Inc.
*
- * LeapRAID Storage and RAID Controller driver.
+ * LeapRAID storage and RAID controller driver.
*/
-
#include <linux/compat.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include "leapraid_func.h"
-/* ioctl device file */
+/* IOCTL device file name. */
#define LEAPRAID_DEV_NAME "leapraid_ctl"
-/* ioctl version */
+/* IOCTL version. */
#define LEAPRAID_IOCTL_VERSION 0x07
-/* ioctl command */
+/* IOCTL commands. */
#define LEAPRAID_ADAPTER_INFO 17
#define LEAPRAID_COMMAND 20
#define LEAPRAID_EVENTQUERY 21
@@ -25,9 +24,10 @@
/**
* struct leapraid_ioctl_header - IOCTL command header
- * @adapter_id : Adapter identifier
- * @port_number: Port identifier
- * @max_data_size: Maximum data size for transfer
+ *
+ * @adapter_id : Adapter identifier.
+ * @port_number: Port identifier.
+ * @max_data_size: Maximum data size for transfer.
*/
struct leapraid_ioctl_header {
u32 adapter_id;
@@ -37,7 +37,8 @@ struct leapraid_ioctl_header {
/**
* struct leapraid_ioctl_diag_reset - Diagnostic reset request
- * @hdr: Common IOCTL header
+ *
+ * @hdr: Common IOCTL header.
*/
struct leapraid_ioctl_diag_reset {
struct leapraid_ioctl_header hdr;
@@ -45,12 +46,13 @@ struct leapraid_ioctl_diag_reset {
/**
* struct leapraid_ioctl_pci_info - PCI device information
- * @u: Union holding PCI bus/device/function information
- * @u.bits.dev: PCI device number
- * @u.bits.func: PCI function number
- * @u.bits.bus: PCI bus number
- * @u.word: Combined representation of PCI BDF
- * @seg_id: PCI segment identifier
+ *
+ * @u: Union holding PCI bus/device/function information.
+ * @u.bits.dev: PCI device number.
+ * @u.bits.func: PCI function number.
+ * @u.bits.bus: PCI bus number.
+ * @u.word: Combined representation of PCI BDF.
+ * @seg_id: PCI segment identifier.
*/
struct leapraid_ioctl_pci_info {
union {
@@ -66,21 +68,22 @@ struct leapraid_ioctl_pci_info {
/**
* struct leapraid_ioctl_adapter_info - Adapter information for IOCTL
- * @hdr: IOCTL header
- * @adapter_type: Adapter type identifier
- * @port_number: Port number
- * @pci_id: PCI device ID
- * @revision: Revision number
- * @sub_dev: Subsystem device ID
- * @sub_vendor: Subsystem vendor ID
- * @r0: Reserved
- * @fw_ver: Firmware version
- * @bios_ver: BIOS version
- * @driver_ver: Driver version
- * @r1: Reserved
- * @scsi_id: SCSI ID
- * @r2: Reserved
- * @pci_info: PCI information structure
+ *
+ * @hdr: IOCTL header.
+ * @adapter_type: Adapter type identifier.
+ * @port_number: Port number.
+ * @pci_id: PCI device ID.
+ * @revision: Revision number.
+ * @sub_dev: Subsystem device ID.
+ * @sub_vendor: Subsystem vendor ID.
+ * @r0: Reserved.
+ * @fw_ver: Firmware version.
+ * @bios_ver: BIOS version.
+ * @driver_ver: Driver version.
+ * @r1: Reserved.
+ * @scsi_id: SCSI ID.
+ * @r2: Reserved.
+ * @pci_info: PCI information structure.
*/
struct leapraid_ioctl_adapter_info {
struct leapraid_ioctl_header hdr;
@@ -102,18 +105,19 @@ struct leapraid_ioctl_adapter_info {
/**
* struct leapraid_ioctl_command - IOCTL command structure
- * @hdr: IOCTL header
- * @timeout: Command timeout
- * @rep_msg_buf_ptr: User pointer to reply message buffer
- * @c2h_buf_ptr: User pointer to card-to-host data buffer
- * @h2c_buf_ptr: User pointer to host-to-card data buffer
- * @sense_data_ptr: User pointer to sense data buffer
- * @max_rep_bytes: Maximum reply bytes
- * @c2h_size: Card-to-host data size
- * @h2c_size: Host-to-card data size
- * @max_sense_bytes: Maximum sense data bytes
- * @data_sge_offset: Data SGE offset
- * @mf: Message frame data (flexible array)
+ *
+ * @hdr: IOCTL header.
+ * @timeout: Command timeout.
+ * @rep_msg_buf_ptr: User pointer to reply message buffer.
+ * @c2h_buf_ptr: User pointer to card-to-host data buffer.
+ * @h2c_buf_ptr: User pointer to host-to-card data buffer.
+ * @sense_data_ptr: User pointer to sense data buffer.
+ * @max_rep_bytes: Maximum reply bytes.
+ * @c2h_size: Card-to-host data size.
+ * @h2c_size: Host-to-card data size.
+ * @max_sense_bytes: Maximum sense data bytes.
+ * @data_sge_offset: Data SGE offset.
+ * @mf: Message frame data (flexible array).
*/
struct leapraid_ioctl_command {
struct leapraid_ioctl_header hdr;
@@ -146,39 +150,38 @@ static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id)
return NULL;
}
-static void leapraid_cli_scsiio_cmd(struct leapraid_adapter *adapter,
- struct leapraid_req *ctl_sp_mpi_req, u16 taskid,
+static void leapraid_ctl_scsiio_cmd(struct leapraid_adapter *adapter,
+ void *ctl_sp_mpi_req,
+ u16 taskid,
dma_addr_t h2c_dma_addr, size_t h2c_size,
dma_addr_t c2h_dma_addr, size_t c2h_size,
u16 dev_hdl, void *psge)
{
- struct leapraid_mpi_scsiio_req *scsiio_request =
- (struct leapraid_mpi_scsiio_req *)ctl_sp_mpi_req;
+ struct leapraid_mpi_scsiio_req *scsiio_request = ctl_sp_mpi_req;
scsiio_request->sense_buffer_len = SCSI_SENSE_BUFFERSIZE;
scsiio_request->sense_buffer_low_add =
- leapraid_get_sense_buffer_dma(adapter, taskid);
- memset((void *)(&adapter->driver_cmds.ctl_cmd.sense),
+ leapraid_get_sense_buffer_dma(adapter, taskid);
+ memset(&adapter->driver_cmds.ctl_cmd.sense,
0, SCSI_SENSE_BUFFERSIZE);
leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr,
h2c_size, c2h_dma_addr, c2h_size);
- if (scsiio_request->func == LEAPRAID_FUNC_SCSIIO_REQ)
+ if (scsiio_request->func == LEAPRAID_FUNC_SCSIIO)
leapraid_fire_scsi_io(adapter, taskid, dev_hdl);
else
leapraid_fire_task(adapter, taskid);
}
-static void leapraid_ctl_smp_passthrough_cmd(struct leapraid_adapter *adapter,
- struct leapraid_req *ctl_sp_mpi_req,
- u16 taskid,
- dma_addr_t h2c_dma_addr,
- size_t h2c_size,
- dma_addr_t c2h_dma_addr,
- size_t c2h_size,
- void *psge, void *h2c)
+static int leapraid_ctl_smp_passthrough_cmd(struct leapraid_adapter *adapter,
+ void *ctl_sp_req,
+ u16 taskid,
+ dma_addr_t h2c_dma_addr,
+ size_t h2c_size,
+ dma_addr_t c2h_dma_addr,
+ size_t c2h_size,
+ void *psge, void *h2c)
{
- struct leapraid_smp_passthrough_req *smp_pt_req =
- (struct leapraid_smp_passthrough_req *)ctl_sp_mpi_req;
+ struct leapraid_smp_passthrough_req *smp_pt_req = ctl_sp_req;
u8 *data;
if (!adapter->adapter_attr.enable_mp)
@@ -188,83 +191,49 @@ static void leapraid_ctl_smp_passthrough_cmd(struct leapraid_adapter *adapter,
else
data = h2c;
- if (data[1] == LEAPRAID_SMP_FN_REPORT_PHY_ERR_LOG &&
- (data[10] == 1 || data[10] == 2))
- adapter->reset_desc.adapter_link_resetting = true;
+ if (!(smp_pt_req->passthrough_flg & LEAPRAID_SMP_PT_FLAG_SGL_PTR) &&
+ h2c_size <= 10) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Invalid request size=%zu\n",
+ __func__, h2c_size);
+ return -EINVAL;
+ }
+
+ if (data[1] == SMP_PHY_CONTROL &&
+ (data[10] == SMP_PHY_CONTROL_LINK_RESET ||
+ data[10] == SMP_PHY_CONTROL_HARD_RESET))
+ adapter->reset_desc.adapter_link_resetting = 1;
+
leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr,
h2c_size, c2h_dma_addr, c2h_size);
leapraid_fire_task(adapter, taskid);
+ return 0;
}
-static void leapraid_ctl_fire_ieee_cmd(struct leapraid_adapter *adapter,
- dma_addr_t h2c_dma_addr,
- size_t h2c_size,
- dma_addr_t c2h_dma_addr,
- size_t c2h_size,
- void *psge, u16 taskid)
-{
- leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size,
- c2h_dma_addr, c2h_size);
- leapraid_fire_task(adapter, taskid);
-}
-
-static void leapraid_ctl_sata_passthrough_cmd(struct leapraid_adapter *adapter,
+static void leapraid_ctl_sas_io_unit_ctrl_cmd(struct leapraid_adapter *adapter,
+ void *ctl_sp_req,
dma_addr_t h2c_dma_addr,
size_t h2c_size,
dma_addr_t c2h_dma_addr,
size_t c2h_size,
void *psge, u16 taskid)
{
- leapraid_ctl_fire_ieee_cmd(adapter, h2c_dma_addr,
- h2c_size, c2h_dma_addr,
- c2h_size, psge, taskid);
-}
-
-static void leapraid_ctl_load_fw_cmd(struct leapraid_adapter *adapter,
- dma_addr_t h2c_dma_addr, size_t h2c_size,
- dma_addr_t c2h_dma_addr, size_t c2h_size,
- void *psge, u16 taskid)
-{
- leapraid_ctl_fire_ieee_cmd(adapter, h2c_dma_addr,
- h2c_size, c2h_dma_addr,
- c2h_size, psge, taskid);
-}
+ struct leapraid_sas_io_unit_ctrl_req *sas_io_unit_ctl_req = ctl_sp_req;
-static void leapraid_ctl_fire_mpi_cmd(struct leapraid_adapter *adapter,
- dma_addr_t h2c_dma_addr, size_t h2c_size,
- dma_addr_t c2h_dma_addr, size_t c2h_size,
- void *psge, u16 taskid)
-{
+ if (sas_io_unit_ctl_req->op == LEAPRAID_SAS_OP_PHY_HARD_RESET ||
+ sas_io_unit_ctl_req->op == LEAPRAID_SAS_OP_PHY_LINK_RESET)
+ adapter->reset_desc.adapter_link_resetting = 1;
leapraid_build_mpi_sg(adapter, psge, h2c_dma_addr,
h2c_size, c2h_dma_addr, c2h_size);
leapraid_fire_task(adapter, taskid);
}
-static void leapraid_ctl_sas_io_unit_ctrl_cmd(struct leapraid_adapter *adapter,
- struct leapraid_req *ctl_sp_mpi_req,
- dma_addr_t h2c_dma_addr,
- size_t h2c_size,
- dma_addr_t c2h_dma_addr,
- size_t c2h_size,
- void *psge, u16 taskid)
+static int leapraid_ctl_do_command(struct leapraid_adapter *adapter,
+ struct leapraid_ioctl_command *karg,
+ void __user *mf)
{
- struct leapraid_sas_io_unit_ctrl_req *sas_io_unit_ctrl_req =
- (struct leapraid_sas_io_unit_ctrl_req *)ctl_sp_mpi_req;
-
- if (sas_io_unit_ctrl_req->op == LEAPRAID_SAS_OP_PHY_HARD_RESET ||
- sas_io_unit_ctrl_req->op == LEAPRAID_SAS_OP_PHY_LINK_RESET)
- adapter->reset_desc.adapter_link_resetting = true;
- leapraid_ctl_fire_mpi_cmd(adapter, h2c_dma_addr,
- h2c_size, c2h_dma_addr,
- c2h_size, psge, taskid);
-}
-
-static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
- struct leapraid_ioctl_command *karg,
- void __user *mf)
-{
- struct leapraid_req *leap_mpi_req = NULL;
- struct leapraid_req *ctl_sp_mpi_req = NULL;
+ struct leapraid_req *leap_mpi_req;
+ struct leapraid_req *ctl_sp_mpi_req;
u16 taskid;
void *h2c = NULL;
size_t h2c_size = 0;
@@ -277,74 +246,88 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
u16 dev_hdl = LEAPRAID_INVALID_DEV_HANDLE;
bool issue_reset = false;
u32 sz;
- long rc = 0;
+ int rc;
- rc = leapraid_check_adapter_is_op(adapter);
+ rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
+ __func__);
if (rc)
- goto out;
+ return rc;
leap_mpi_req = kzalloc(LEAPRAID_REQUEST_SIZE, GFP_KERNEL);
- if (!leap_mpi_req) {
- rc = -ENOMEM;
- goto out;
- }
+ if (!leap_mpi_req)
+ return -ENOMEM;
- if (karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE > LEAPRAID_REQUEST_SIZE ||
- karg->data_sge_offset > ((UINT_MAX) / LEAPRAID_SGE_OFFSET_SIZE)) {
+ if (karg->data_sge_offset > (UINT_MAX / LEAPRAID_SGE_OFFSET_SIZE) ||
+ karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE >
+ LEAPRAID_REQUEST_SIZE) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Invalid data_sge_offset=%u\n",
+ __func__, karg->data_sge_offset);
rc = -EINVAL;
- goto out;
+ goto out_cleanup;
}
if (copy_from_user(leap_mpi_req, mf,
karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy request message from user\n",
+ __func__);
rc = -EFAULT;
- goto out;
+ goto out_cleanup;
}
taskid = adapter->driver_cmds.ctl_cmd.taskid;
adapter->driver_cmds.ctl_cmd.status = LEAPRAID_CMD_PENDING;
- memset((void *)(&adapter->driver_cmds.ctl_cmd.reply), 0,
- LEAPRAID_REPLY_SIEZ);
+ 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);
- if (ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO_REQ ||
- ctl_sp_mpi_req->func == LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH ||
- ctl_sp_mpi_req->func == LEAPRAID_FUNC_SATA_PASSTHROUGH) {
+ if (ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO ||
+ ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH ||
+ ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH) {
dev_hdl = le16_to_cpu(ctl_sp_mpi_req->func_dep1);
- if (!dev_hdl || dev_hdl > adapter->adapter_attr.features.max_dev_handle) {
+ if (!dev_hdl ||
+ dev_hdl > adapter->adapter_attr.features.max_dev_handle) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Invalid device handle\n", __func__);
rc = -EINVAL;
- goto out;
+ goto out_cleanup;
}
}
- if (WARN_ON(ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSI_TMF))
- return -EINVAL;
+ if (WARN_ON(ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSI_TMF)) {
+ rc = -EINVAL;
+ 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_ATOMIC);
+ &h2c_dma_addr, GFP_KERNEL);
if (!h2c) {
rc = -ENOMEM;
- goto out;
+ goto out_cleanup;
}
if (copy_from_user(h2c, karg->h2c_buf_ptr, h2c_size)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy h2c from user\n",
+ __func__);
rc = -EFAULT;
- goto out;
+ goto out_cleanup;
}
}
if (c2h_size) {
- c2h = dma_alloc_coherent(&adapter->pdev->dev,
- c2h_size, &c2h_dma_addr, GFP_ATOMIC);
+ c2h = dma_alloc_coherent(&adapter->pdev->dev, c2h_size,
+ &c2h_dma_addr, GFP_KERNEL);
if (!c2h) {
rc = -ENOMEM;
- goto out;
+ goto out_cleanup;
}
}
@@ -353,13 +336,9 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
init_completion(&adapter->driver_cmds.ctl_cmd.done);
switch (ctl_sp_mpi_req->func) {
- case LEAPRAID_FUNC_SCSIIO_REQ:
- case LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH:
- if (test_bit(dev_hdl, (unsigned long *)adapter->dev_topo.dev_removing)) {
- rc = -EINVAL;
- goto out;
- }
- leapraid_cli_scsiio_cmd(adapter, ctl_sp_mpi_req, taskid,
+ case LEAPRAID_FUNC_SCSIIO:
+ case LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH:
+ leapraid_ctl_scsiio_cmd(adapter, ctl_sp_mpi_req, taskid,
h2c_dma_addr, h2c_size,
c2h_dma_addr, c2h_size,
dev_hdl, psge);
@@ -367,28 +346,26 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
case LEAPRAID_FUNC_SMP_PASSTHROUGH:
if (!h2c) {
rc = -EINVAL;
- goto out;
+ goto out_cleanup;
}
- leapraid_ctl_smp_passthrough_cmd(adapter,
- ctl_sp_mpi_req, taskid,
- h2c_dma_addr, h2c_size,
- c2h_dma_addr, c2h_size,
- psge, h2c);
+ rc = leapraid_ctl_smp_passthrough_cmd(adapter,
+ ctl_sp_mpi_req, taskid,
+ h2c_dma_addr, h2c_size,
+ c2h_dma_addr, c2h_size,
+ psge, h2c);
+ if (rc)
+ goto out_cleanup;
break;
- case LEAPRAID_FUNC_SATA_PASSTHROUGH:
- if (test_bit(dev_hdl, (unsigned long *)adapter->dev_topo.dev_removing)) {
- rc = -EINVAL;
- goto out;
- }
- leapraid_ctl_sata_passthrough_cmd(adapter, h2c_dma_addr,
- h2c_size, c2h_dma_addr,
- c2h_size, psge, taskid);
+ case LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH:
+ leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size,
+ c2h_dma_addr, c2h_size);
+ leapraid_fire_task(adapter, taskid);
break;
case LEAPRAID_FUNC_FW_DOWNLOAD:
case LEAPRAID_FUNC_FW_UPLOAD:
- leapraid_ctl_load_fw_cmd(adapter, h2c_dma_addr,
- h2c_size, c2h_dma_addr,
- c2h_size, psge, taskid);
+ leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size,
+ c2h_dma_addr, c2h_size);
+ leapraid_fire_task(adapter, taskid);
break;
case LEAPRAID_FUNC_SAS_IO_UNIT_CTRL:
leapraid_ctl_sas_io_unit_ctrl_cmd(adapter, ctl_sp_mpi_req,
@@ -397,23 +374,27 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
psge, taskid);
break;
default:
- leapraid_ctl_fire_mpi_cmd(adapter, h2c_dma_addr,
- h2c_size, c2h_dma_addr,
- c2h_size, psge, taskid);
+ leapraid_build_mpi_sg(adapter, psge, h2c_dma_addr,
+ h2c_size, c2h_dma_addr, c2h_size);
+ leapraid_fire_task(adapter, taskid);
break;
}
timeout = karg->timeout;
if (timeout < LEAPRAID_CTL_CMD_TIMEOUT)
timeout = LEAPRAID_CTL_CMD_TIMEOUT;
- wait_for_completion_timeout(&adapter->driver_cmds.ctl_cmd.done,
- timeout * HZ);
+ if (!wait_for_completion_timeout(&adapter->driver_cmds.ctl_cmd.done,
+ timeout * HZ)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: ctl_cmd timeout, status=0x%x\n",
+ __func__, adapter->driver_cmds.ctl_cmd.status);
+ }
if ((leap_mpi_req->func == LEAPRAID_FUNC_SMP_PASSTHROUGH ||
leap_mpi_req->func == LEAPRAID_FUNC_SAS_IO_UNIT_CTRL) &&
- adapter->reset_desc.adapter_link_resetting) {
- adapter->reset_desc.adapter_link_resetting = false;
- }
+ adapter->reset_desc.adapter_link_resetting)
+ adapter->reset_desc.adapter_link_resetting = 0;
+
if (!(adapter->driver_cmds.ctl_cmd.status & LEAPRAID_CMD_DONE)) {
issue_reset =
leapraid_check_reset(
@@ -421,57 +402,66 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
goto reset;
}
- if (c2h_size) {
- if (copy_to_user(karg->c2h_buf_ptr, c2h, c2h_size)) {
- rc = -ENODATA;
- goto out;
- }
+ if (c2h_size && copy_to_user(karg->c2h_buf_ptr, c2h, c2h_size)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy c2h to user\n", __func__);
+ rc = -ENODATA;
+ goto out_cleanup;
}
if (karg->max_rep_bytes) {
- sz = min_t(u32, karg->max_rep_bytes, LEAPRAID_REPLY_SIEZ);
+ sz = min_t(u32, karg->max_rep_bytes, LEAPRAID_REPLY_SIZE);
if (copy_to_user(karg->rep_msg_buf_ptr,
- (void *)&adapter->driver_cmds.ctl_cmd.reply,
+ &adapter->driver_cmds.ctl_cmd.reply,
sz)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy reply to user\n",
+ __func__);
rc = -ENODATA;
- goto out;
+ goto out_cleanup;
}
}
if (karg->max_sense_bytes &&
- (leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO_REQ ||
- leap_mpi_req->func == LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH)) {
+ (leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO ||
+ leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH)) {
if (!karg->sense_data_ptr)
- goto out;
+ goto out_cleanup;
sz = min_t(u32, karg->max_sense_bytes, SCSI_SENSE_BUFFERSIZE);
if (copy_to_user(karg->sense_data_ptr,
- (void *)&adapter->driver_cmds.ctl_cmd.sense,
+ &adapter->driver_cmds.ctl_cmd.sense,
sz)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy sense data to user\n",
+ __func__);
rc = -ENODATA;
- goto out;
+ goto out_cleanup;
}
}
reset:
if (issue_reset) {
rc = -ENODATA;
- if (leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO_REQ ||
- leap_mpi_req->func == LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH ||
- leap_mpi_req->func == LEAPRAID_FUNC_SATA_PASSTHROUGH) {
+ if (leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO ||
+ leap_mpi_req->func ==
+ LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH ||
+ leap_mpi_req->func ==
+ LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH) {
dev_err(&adapter->pdev->dev,
- "fire tgt reset: hdl=0x%04x\n",
+ "Fire tgt reset, hdl=0x%04x\n",
le16_to_cpu(leap_mpi_req->func_dep1));
- leapraid_issue_locked_tm(adapter,
+ leapraid_issue_locked_tm(
+ adapter,
le16_to_cpu(leap_mpi_req->func_dep1), 0, 0, 0,
LEAPRAID_TM_TASKTYPE_TARGET_RESET, taskid,
LEAPRAID_TM_MSGFLAGS_LINK_RESET);
} else {
dev_info(&adapter->pdev->dev,
- "%s:%d call hard_reset\n",
+ "%s:%d: call hard_reset\n",
__func__, __LINE__);
leapraid_hard_reset_handler(adapter, FULL_RESET);
}
}
-out:
+out_cleanup:
if (c2h)
dma_free_coherent(&adapter->pdev->dev, c2h_size,
c2h, c2h_dma_addr);
@@ -483,12 +473,12 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
return rc;
}
-static long leapraid_ctl_get_adapter_info(struct leapraid_adapter *adapter,
- void __user *arg)
+static int leapraid_ctl_get_adapter_info(struct leapraid_adapter *adapter,
+ void __user *arg)
{
struct leapraid_ioctl_adapter_info *karg;
- ssize_t __maybe_unused ret;
u8 revision;
+ int rc = 0;
karg = kzalloc(sizeof(*karg), GFP_KERNEL);
if (!karg)
@@ -504,80 +494,98 @@ static long leapraid_ctl_get_adapter_info(struct leapraid_adapter *adapter,
karg->pci_info.u.bits.func = PCI_FUNC(adapter->pdev->devfn);
karg->pci_info.seg_id = pci_domain_nr(adapter->pdev->bus);
karg->fw_ver = adapter->adapter_attr.features.fw_version;
- ret = strscpy(karg->driver_ver, LEAPRAID_DRIVER_NAME,
- sizeof(karg->driver_ver));
- strcat(karg->driver_ver, "-");
- strcat(karg->driver_ver, LEAPRAID_DRIVER_VERSION);
+
+ snprintf(karg->driver_ver, sizeof(karg->driver_ver), "%s-%s",
+ LEAPRAID_DRIVER_NAME, LEAPRAID_DRIVER_VERSION);
+
karg->adapter_type = LEAPRAID_IOCTL_VERSION;
karg->bios_ver = adapter->adapter_attr.bios_version;
if (copy_to_user(arg, karg,
sizeof(struct leapraid_ioctl_adapter_info))) {
- kfree(karg);
- return -EFAULT;
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy info to user\n", __func__);
+ rc = -EFAULT;
+ goto free_buf;
}
+free_buf:
kfree(karg);
- return 0;
+ return rc;
}
-static long leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd,
- void __user *arg, u8 compat)
+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;
- long rc = -ENOIOCTLCMD;
- int count;
-
- if (copy_from_user(&ioctl_header, (char __user *)arg,
- sizeof(struct leapraid_ioctl_header)))
+ struct leapraid_ioctl_command __user *uarg;
+ struct leapraid_ioctl_command karg;
+ int rc = -ENOIOCTLCMD;
+
+ if (copy_from_user(&ioctl_header, arg,
+ sizeof(struct leapraid_ioctl_header))) {
+ pr_err("%s:%s: Failed to copy header from user\n",
+ LEAPRAID_DRIVER_NAME, __func__);
return -EFAULT;
+ }
adapter = leapraid_ctl_lookup_adapter(ioctl_header.adapter_id);
if (!adapter)
return -EFAULT;
+ if (atomic_read(&adapter->overheat_desc.thermal_alert)) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed, thermal_alert=%d\n",
+ __func__,
+ atomic_read(&adapter->overheat_desc.thermal_alert));
+ return -EFAULT;
+ }
+
mutex_lock(&adapter->access_ctrl.pci_access_lock);
- rc = leapraid_check_adapter_is_op(adapter);
+ rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_LONG,
+ __func__);
if (rc)
- goto out;
+ goto unlock;
- count = LEAPRAID_WAIT_SHOST_RECOVERY;
- while (count--) {
- if (!adapter->access_ctrl.shost_recovering)
- break;
- ssleep(1);
+ if (!wait_event_timeout(adapter->access_ctrl.shost_recover_wq,
+ !adapter->access_ctrl.shost_recover_async,
+ LEAPRAID_WAIT_SHOST_RECOVERY * HZ)) {
+ dev_warn(&adapter->pdev->dev,
+ "Timeout waiting for shost recovery async\n");
+ rc = -EAGAIN;
+ goto unlock;
}
- if (adapter->access_ctrl.shost_recovering ||
- adapter->access_ctrl.pcie_recovering ||
+ if (adapter->access_ctrl.pcie_recovering ||
adapter->scan_dev_desc.driver_loading ||
adapter->access_ctrl.host_removing) {
rc = -EAGAIN;
- goto out;
+ goto unlock;
}
if (file->f_flags & O_NONBLOCK) {
if (!mutex_trylock(&adapter->driver_cmds.ctl_cmd.mutex)) {
rc = -EAGAIN;
- goto out;
+ goto unlock;
}
- } else if (mutex_lock_interruptible(&adapter->driver_cmds.ctl_cmd.mutex)) {
+ } else if (mutex_lock_interruptible(&adapter->driver_cmds
+ .ctl_cmd.mutex)) {
rc = -ERESTARTSYS;
- goto out;
+ goto unlock;
}
switch (_IOC_NR(cmd)) {
case LEAPRAID_ADAPTER_INFO:
- if (_IOC_SIZE(cmd) == sizeof(struct leapraid_ioctl_adapter_info))
+ if (_IOC_SIZE(cmd) ==
+ sizeof(struct leapraid_ioctl_adapter_info))
rc = leapraid_ctl_get_adapter_info(adapter, arg);
break;
case LEAPRAID_COMMAND:
- {
- struct leapraid_ioctl_command __user *uarg;
- struct leapraid_ioctl_command karg;
-
if (copy_from_user(&karg, arg, sizeof(karg))) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy data from user\n",
+ __func__);
rc = -EFAULT;
break;
}
@@ -591,61 +599,77 @@ static long leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd,
uarg = arg;
rc = leapraid_ctl_do_command(adapter, &karg,
&uarg->mf);
+ if (rc)
+ dev_warn(&adapter->pdev->dev,
+ "%s: IOCTL cmd failed rc=%d\n",
+ __func__, rc);
}
break;
- }
case LEAPRAID_EVENTQUERY:
case LEAPRAID_EVENTREPORT:
rc = 0;
break;
default:
- pr_err("unknown ioctl opcode=0x%08x\n", cmd);
+ dev_err(&adapter->pdev->dev,
+ "Unknown IOCTL opcode=0x%08x\n", cmd);
break;
}
mutex_unlock(&adapter->driver_cmds.ctl_cmd.mutex);
-out:
+unlock:
mutex_unlock(&adapter->access_ctrl.pci_access_lock);
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, 0);
+ return leapraid_ctl_ioctl_main(file, cmd, (void __user *)arg);
}
static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct leapraid_adapter *adapter;
+ /* Userspace passes the adapter ID via vma->vm_pgoff. */
+ u32 adapter_id = vma->vm_pgoff;
unsigned long length;
- unsigned long pfn;
+ int rc;
length = vma->vm_end - vma->vm_start;
- adapter = list_first_entry(&leapraid_adapter_list,
- struct leapraid_adapter, list);
+ adapter = leapraid_ctl_lookup_adapter(adapter_id);
+ if (!adapter) {
+ pr_err("%s: No adapter found!\n", __func__);
+ return -EINVAL;
+ }
if (length > (LEAPRAID_SYS_LOG_BUF_SIZE +
LEAPRAID_SYS_LOG_BUF_RESERVE)) {
dev_err(&adapter->pdev->dev,
- "requested mapping size is too large!\n");
+ "Requested mapping size is too large!\n");
return -EINVAL;
}
if (!adapter->fw_log_desc.fw_log_buffer) {
- dev_err(&adapter->pdev->dev, "no log buffer!\n");
+ dev_err(&adapter->pdev->dev, "No log buffer!\n");
return -EINVAL;
}
- pfn = virt_to_phys(adapter->fw_log_desc.fw_log_buffer) >> PAGE_SHIFT;
+ vma->vm_pgoff = 0;
- if (remap_pfn_range(vma, vma->vm_start, pfn, length,
- vma->vm_page_prot)) {
+ rc = dma_mmap_coherent(&adapter->pdev->dev, vma,
+ adapter->fw_log_desc.fw_log_buffer,
+ adapter->fw_log_desc.fw_log_buffer_dma,
+ length);
+ if (rc) {
dev_err(&adapter->pdev->dev,
- "failed to map memory to user space!\n");
- return -EAGAIN;
+ "Failed to map memory to user space!\n");
+ return rc;
}
return 0;
@@ -655,6 +679,7 @@ 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 = {
@@ -663,10 +688,14 @@ static struct miscdevice leapraid_ctl_dev = {
.fops = &leapraid_ctl_fops,
};
-void leapraid_ctl_init(void)
+int leapraid_ctl_init(void)
{
- if (misc_register(&leapraid_ctl_dev) < 0)
- pr_err("%s can't register misc device\n", LEAPRAID_DRIVER_NAME);
+ if (misc_register(&leapraid_ctl_dev) < 0) {
+ pr_err("%s Can't register misc device\n",
+ LEAPRAID_DRIVER_NAME);
+ return -ENODEV;
+ }
+ return 0;
}
void leapraid_ctl_exit(void)
diff --git a/drivers/scsi/leapraid/leapraid_func.c b/drivers/scsi/leapraid/leapraid_func.c
index ad8aee40e2c1..f2574feb2514 100644
--- a/drivers/scsi/leapraid/leapraid_func.c
+++ b/drivers/scsi/leapraid/leapraid_func.c
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2025 LeapIO Tech Inc.
+ * Copyright (C) 2026 LeapIO Tech Inc.
*
- * LeapRAID Storage and RAID Controller driver.
+ * LeapRAID storage and RAID controller driver.
*/
-
#include <linux/module.h>
#include "leapraid_func.h"
@@ -22,15 +21,16 @@ MODULE_PARM_DESC(smart_poll,
static int interrupt_mode;
module_param(interrupt_mode, int, 0444);
MODULE_PARM_DESC(interrupt_mode,
- "intr mode: 0 for MSI-X, 1 for MSI, 2 for legacy. (default=0)");
+ "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,
"specifies the number of queues for io_uring poll mode.");
-static int max_msix_vectors = -1;
+
+static int max_msix_vectors = LEAPRAID_INVALID_MSIX_VECTORS;
module_param(max_msix_vectors, int, 0444);
-MODULE_PARM_DESC(max_msix_vectors, " max msix vectors");
+MODULE_PARM_DESC(max_msix_vectors, "max msix vectors");
static void leapraid_remove_device(struct leapraid_adapter *adapter,
struct leapraid_sas_dev *sas_dev);
@@ -39,11 +39,48 @@ static void leapraid_set_led(struct leapraid_adapter *adapter,
static void leapraid_ublk_io_dev(struct leapraid_adapter *adapter,
u64 sas_address,
struct leapraid_card_port *port);
+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 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)
+{
+ struct leapraid_reg_base __iomem *iomem_base = adapter->iomem_base;
+ u32 debug_log[LEAPRAID_DEBUGLOG_SZ_MAX];
+ bool changed = false;
+ int i;
+
+ 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]);
+}
static inline bool leapraid_is_end_dev(u32 dev_type)
{
return (dev_type & LEAPRAID_DEVTYP_END_DEV) &&
@@ -57,12 +94,14 @@ bool leapraid_pci_removed(struct leapraid_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
u32 vendor_id;
- if (pci_bus_read_config_dword(pdev->bus, pdev->devfn, PCI_VENDOR_ID,
+ if (pci_bus_read_config_dword(pdev->bus,
+ pdev->devfn,
+ PCI_VENDOR_ID,
&vendor_id))
return true;
- return ((vendor_id & LEAPRAID_PCI_VENDOR_ID_MASK) !=
- LEAPRAID_VENDOR_ID);
+ return (vendor_id & LEAPRAID_PCI_VENDOR_ID_MASK) !=
+ LEAPRAID_VENDOR_ID;
}
static bool leapraid_pci_active(struct leapraid_adapter *adapter)
@@ -82,14 +121,14 @@ void *leapraid_get_reply_vaddr(struct leapraid_adapter *adapter, u32 rep_paddr)
void *leapraid_get_task_desc(struct leapraid_adapter *adapter, u16 taskid)
{
- return (void *)(adapter->mem_desc.task_desc +
- (taskid * LEAPRAID_REQUEST_SIZE));
+ return adapter->mem_desc.task_desc +
+ taskid * LEAPRAID_REQUEST_SIZE;
}
void *leapraid_get_sense_buffer(struct leapraid_adapter *adapter, u16 taskid)
{
- return (void *)(adapter->mem_desc.sense_data +
- ((taskid - 1) * SCSI_SENSE_BUFFERSIZE));
+ return adapter->mem_desc.sense_data +
+ (taskid - 1) * SCSI_SENSE_BUFFERSIZE;
}
__le32 leapraid_get_sense_buffer_dma(struct leapraid_adapter *adapter,
@@ -103,7 +142,7 @@ void leapraid_mask_int(struct leapraid_adapter *adapter)
{
u32 reg;
- adapter->mask_int = true;
+ adapter->mask_int = 1;
reg = leapraid_readl(&adapter->iomem_base->host_int_mask);
reg |= LEAPRAID_TO_SYS_DB_MASK + LEAPRAID_REPLY_INT_MASK +
LEAPRAID_RESET_IRQ_MASK;
@@ -118,35 +157,59 @@ void leapraid_unmask_int(struct leapraid_adapter *adapter)
reg = leapraid_readl(&adapter->iomem_base->host_int_mask);
reg &= ~LEAPRAID_REPLY_INT_MASK;
writel(reg, &adapter->iomem_base->host_int_mask);
- adapter->mask_int = false;
+ adapter->mask_int = 0;
}
-static void leapraid_flush_io_and_panic(struct leapraid_adapter *adapter)
+static void leapraid_overheat_suspend(struct leapraid_adapter *adapter)
{
- adapter->access_ctrl.adapter_thermal_alert = true;
- leapraid_smart_polling_stop(adapter);
- leapraid_fw_log_stop(adapter);
- leapraid_mq_polling_pause(adapter);
- leapraid_clean_active_scsi_cmds(adapter);
+ struct workqueue_struct *wq;
+ struct Scsi_Host *shost;
+ struct pci_dev *pdev;
+
+ if (!adapter)
+ return;
+
+ pdev = adapter->pdev;
+ shost = pci_get_drvdata(pdev);
+
+ if (!shost) {
+ dev_warn(&pdev->dev,
+ "Overheat suspend failed, invalid host or adapter\n");
+ return;
+ }
+
+ wq = adapter->overheat_desc.fault_overheat_wq;
+ if (!wq)
+ return;
+
+ if (atomic_cmpxchg(&adapter->overheat_desc.thermal_alert, 0, 1))
+ return;
+
+ queue_work(wq, &adapter->overheat_desc.fault_overheat_work);
}
-static void leapraid_check_panic_needed(struct leapraid_adapter *adapter,
- u32 db, u32 adapter_state)
+static void leapraid_stop_adapter_on_fault(struct leapraid_adapter *adapter,
+ u32 db)
{
- bool fault_1 = adapter_state == LEAPRAID_DB_MASK;
- bool fault_2 = (adapter_state == LEAPRAID_DB_FAULT) &&
- ((db & LEAPRAID_DB_DATA_MASK) == LEAPRAID_DB_OVER_TEMPERATURE);
+ u32 adapter_state = db & LEAPRAID_DB_MASK;
+ bool fault_1 = false;
+ bool fault_2 = false;
+
+ fault_1 = adapter_state == LEAPRAID_DB_MASK;
+ fault_2 = adapter_state == LEAPRAID_DB_FAULT &&
+ (db & LEAPRAID_DB_DATA_MASK) == LEAPRAID_DB_OVER_TEMPERATURE;
if (!fault_1 && !fault_2)
return;
if (fault_1)
- pr_err("%s, doorbell status 0xFFFF!\n", __func__);
+ dev_err(&adapter->pdev->dev,
+ "%s: Doorbell status 0xFFFF!\n", __func__);
else
- pr_err("%s, adapter overheating detected!\n", __func__);
+ dev_err(&adapter->pdev->dev,
+ "%s: Adapter overheating detected!\n", __func__);
- leapraid_flush_io_and_panic(adapter);
- panic("%s overheating detected, panic now!!!\n", __func__);
+ leapraid_overheat_suspend(adapter);
}
u32 leapraid_get_adapter_state(struct leapraid_adapter *adapter)
@@ -156,38 +219,40 @@ u32 leapraid_get_adapter_state(struct leapraid_adapter *adapter)
db = leapraid_readl(&adapter->iomem_base->db);
adapter_state = db & LEAPRAID_DB_MASK;
- leapraid_check_panic_needed(adapter, db, adapter_state);
+ leapraid_stop_adapter_on_fault(adapter, db);
return adapter_state;
}
static bool leapraid_wait_adapter_ready(struct leapraid_adapter *adapter)
{
u32 cur_state;
- u32 cnt = LEAPRAID_ADAPTER_READY_MAX_RETRY;
+ u32 cnt;
- do {
+ for (cnt = LEAPRAID_ADAPTER_READY_MAX_RETRY; cnt > 0; cnt--) {
cur_state = leapraid_get_adapter_state(adapter);
+
if (cur_state == LEAPRAID_DB_READY)
return true;
if (cur_state == LEAPRAID_DB_FAULT)
break;
usleep_range(LEAPRAID_ADAPTER_READY_SLEEP_MIN_US,
LEAPRAID_ADAPTER_READY_SLEEP_MAX_US);
- } while (--cnt);
+ }
return false;
}
static int leapraid_db_wait_int_host(struct leapraid_adapter *adapter)
{
- u32 cnt = LEAPRAID_DB_WAIT_MAX_RETRY;
+ u32 cnt;
- do {
+ for (cnt = LEAPRAID_DB_WAIT_MAX_RETRY; cnt > 0; cnt--) {
if (leapraid_readl(&adapter->iomem_base->host_int_status) &
LEAPRAID_ADAPTER2HOST_DB_STATUS)
return 0;
+
udelay(LEAPRAID_DB_WAIT_DELAY_US);
- } while (--cnt);
+ }
return -EFAULT;
}
@@ -198,25 +263,26 @@ static int leapraid_db_wait_ack_and_clear_int(struct leapraid_adapter *adapter)
u32 int_status;
u32 cnt;
- cnt = LEAPRAID_ADAPTER_READY_MAX_RETRY;
- do {
+ for (cnt = LEAPRAID_ADAPTER_READY_MAX_RETRY; cnt > 0; cnt--) {
int_status =
leapraid_readl(&adapter->iomem_base->host_int_status);
- if (!(int_status & LEAPRAID_HOST2ADAPTER_DB_STATUS)) {
+
+ if (int_status == 0xFFFFFFFF)
+ return -EFAULT;
+
+ if (!(int_status & LEAPRAID_HOST2ADAPTER_DB_STATUS))
return 0;
- } else if (int_status & LEAPRAID_ADAPTER2HOST_DB_STATUS) {
+
+ if (int_status & LEAPRAID_ADAPTER2HOST_DB_STATUS) {
adapter_state = leapraid_get_adapter_state(adapter);
if (adapter_state == LEAPRAID_DB_FAULT)
return -EFAULT;
- } else if (int_status == 0xFFFFFFFF) {
- goto out;
}
usleep_range(LEAPRAID_ADAPTER_READY_SLEEP_MIN_US,
LEAPRAID_ADAPTER_READY_SLEEP_MAX_US);
- } while (--cnt);
+ }
-out:
return -EFAULT;
}
@@ -226,8 +292,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
{
int failed, i;
- if ((leapraid_readl(&adapter->iomem_base->db) &
- LEAPRAID_DB_USED)) {
+ if (leapraid_readl(&adapter->iomem_base->db) & LEAPRAID_DB_USED) {
dev_err(&adapter->pdev->dev, "doorbell used\n");
return -EFAULT;
}
@@ -242,7 +307,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
&adapter->iomem_base->db);
if (leapraid_db_wait_int_host(adapter)) {
- dev_err(&adapter->pdev->dev, "%d:wait db interrupt timeout\n",
+ dev_err(&adapter->pdev->dev, "%d: Wait db interrupt timeout\n",
__LINE__);
return -EFAULT;
}
@@ -250,7 +315,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
writel(0, &adapter->iomem_base->host_int_status);
if (leapraid_db_wait_ack_and_clear_int(adapter)) {
- dev_err(&adapter->pdev->dev, "%d:wait ack failure\n",
+ dev_err(&adapter->pdev->dev, "%d: Wait ack failure\n",
__LINE__);
return -EFAULT;
}
@@ -258,12 +323,12 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
for (i = 0, failed = 0;
i < req_bytes / LEAPRAID_DWORDS_BYTE_SIZE && !failed;
i++) {
- writel((u32)(req[i]), &adapter->iomem_base->db);
+ writel((u32)req[i], &adapter->iomem_base->db);
if (leapraid_db_wait_ack_and_clear_int(adapter))
failed = 1;
}
if (failed) {
- dev_err(&adapter->pdev->dev, "%d:wait ack failure\n",
+ dev_err(&adapter->pdev->dev, "%d: Wait ack failure\n",
__LINE__);
return -EFAULT;
}
@@ -271,7 +336,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
for (i = 0; i < rep_bytes / LEAPRAID_WORD_BYTE_SIZE; i++) {
if (leapraid_db_wait_int_host(adapter)) {
dev_err(&adapter->pdev->dev,
- "%d:wait db interrupt timeout\n", __LINE__);
+ "%d: Wait db interrupt timeout\n", __LINE__);
return -EFAULT;
}
rep[i] = (u16)(leapraid_readl(&adapter->iomem_base->db)
@@ -280,7 +345,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
}
if (leapraid_db_wait_int_host(adapter)) {
- dev_err(&adapter->pdev->dev, "%d:wait db interrupt timeout\n",
+ dev_err(&adapter->pdev->dev, "%d: Wait db interrupt timeout\n",
__LINE__);
return -EFAULT;
}
@@ -290,28 +355,32 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
return 0;
}
-int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter)
+int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter, int wait,
+ const char *caller)
{
- int wait_count = LEAPRAID_DB_WAIT_OPERATIONAL;
+ int wait_count;
- do {
- if (leapraid_pci_removed(adapter))
+ for (wait_count = wait; wait_count > 0; wait_count--) {
+ if (leapraid_pci_removed(adapter)) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: PCI device removed\n", __func__);
return -EFAULT;
+ }
if (leapraid_get_adapter_state(adapter) ==
LEAPRAID_DB_OPERATIONAL)
return 0;
- dev_info(&adapter->pdev->dev,
- "waiting for adapter to become op status(cnt=%d)\n",
- LEAPRAID_DB_WAIT_OPERATIONAL - wait_count);
+ dev_dbg(&adapter->pdev->dev,
+ "%s: Wait for adapter to become op status(cnt=%d)\n",
+ caller, wait - wait_count);
ssleep(1);
- } while (--wait_count);
+ }
dev_err(&adapter->pdev->dev,
- "adapter failed to become op state, last state=%d\n",
- leapraid_get_adapter_state(adapter));
+ "%s: Adapter failed to become op state, last state=%d\n",
+ caller, leapraid_get_adapter_state(adapter));
return -EFAULT;
}
@@ -329,7 +398,7 @@ struct leapraid_io_req_tracker *leapraid_get_io_tracker_from_taskid(
scmd = leapraid_get_scmd_from_taskid(adapter, taskid);
if (scmd)
- return leapraid_get_scmd_priv(scmd);
+ return scsi_cmd_priv(scmd);
return NULL;
}
@@ -354,7 +423,8 @@ static u8 leapraid_get_cb_idx(struct leapraid_adapter *adapter, u16 taskid)
}
struct scsi_cmnd *leapraid_get_scmd_from_taskid(
- struct leapraid_adapter *adapter, u16 taskid)
+ struct leapraid_adapter *adapter,
+ u16 taskid)
{
struct leapraid_scsiio_req *leap_mpi_req;
struct leapraid_io_req_tracker *st;
@@ -372,7 +442,7 @@ struct scsi_cmnd *leapraid_get_scmd_from_taskid(
scmd = scsi_host_find_tag(adapter->shost, uniq_tag);
if (scmd) {
- st = leapraid_get_scmd_priv(scmd);
+ st = scsi_cmd_priv(scmd);
if (st && st->taskid == taskid)
return scmd;
}
@@ -393,7 +463,7 @@ u16 leapraid_alloc_scsiio_taskid(struct leapraid_adapter *adapter,
adapter->mem_desc.taskid_to_uniq_tag[tag] =
blk_mq_unique_tag_to_hwq(unique_tag);
- request = leapraid_get_scmd_priv(scmd);
+ request = scsi_cmd_priv(scmd);
taskid = tag + 1;
request->taskid = taskid;
request->scmd = scmd;
@@ -410,8 +480,9 @@ static void leapraid_check_pending_io(struct leapraid_adapter *adapter)
}
}
-static void leapraid_clear_io_tracker(struct leapraid_adapter *adapter,
- struct leapraid_io_req_tracker *io_tracker)
+static void leapraid_clear_io_tracker(
+ struct leapraid_adapter *adapter,
+ struct leapraid_io_req_tracker *io_tracker)
{
if (!io_tracker)
return;
@@ -425,17 +496,18 @@ static void leapraid_clear_io_tracker(struct leapraid_adapter *adapter,
static bool leapraid_is_fixed_taskid(struct leapraid_adapter *adapter,
u16 taskid)
{
- return (taskid == adapter->driver_cmds.ctl_cmd.taskid ||
- taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid ||
- taskid == adapter->driver_cmds.tm_cmd.hp_taskid ||
- taskid == adapter->driver_cmds.ctl_cmd.hp_taskid ||
- taskid == adapter->driver_cmds.scan_dev_cmd.inter_taskid ||
- taskid == adapter->driver_cmds.timestamp_sync_cmd.inter_taskid ||
- taskid == adapter->driver_cmds.raid_action_cmd.inter_taskid ||
- taskid == adapter->driver_cmds.transport_cmd.inter_taskid ||
- taskid == adapter->driver_cmds.cfg_op_cmd.inter_taskid ||
- taskid == adapter->driver_cmds.enc_cmd.inter_taskid ||
- taskid == adapter->driver_cmds.notify_event_cmd.inter_taskid);
+ 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 ||
+ taskid == driver_cmds->notify_event_cmd.inter_taskid);
}
void leapraid_free_taskid(struct leapraid_adapter *adapter, u16 taskid)
@@ -531,6 +603,7 @@ void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter)
{
struct leapraid_io_req_tracker *io_tracker;
struct scsi_cmnd *scmd;
+ void *task_desc;
u16 taskid;
for (taskid = 1; taskid <= adapter->shost->can_queue; taskid++) {
@@ -538,15 +611,17 @@ void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter)
if (!scmd)
continue;
- io_tracker = leapraid_get_scmd_priv(scmd);
+ io_tracker = scsi_cmd_priv(scmd);
if (io_tracker && io_tracker->taskid == 0)
continue;
scsi_dma_unmap(scmd);
+ task_desc = leapraid_get_task_desc(adapter, taskid);
+ memset(task_desc, 0, LEAPRAID_REQUEST_SIZE);
leapraid_clear_io_tracker(adapter, io_tracker);
if (!leapraid_pci_active(adapter) ||
adapter->reset_desc.adapter_reset_results != 0 ||
- adapter->access_ctrl.adapter_thermal_alert ||
+ atomic_read(&adapter->overheat_desc.thermal_alert) ||
adapter->access_ctrl.host_removing)
scmd->result = DID_NO_CONNECT << 16;
else
@@ -555,36 +630,37 @@ void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter)
}
}
-static void leapraid_clean_active_driver_cmd(
- struct leapraid_driver_cmd *driver_cmd)
+static void leapraid_clean_active_driver_cmd(struct leapraid_driver_cmd *cmd)
{
- if (driver_cmd->status & LEAPRAID_CMD_PENDING) {
- driver_cmd->status |= LEAPRAID_CMD_RESET;
- complete(&driver_cmd->done);
+ if (cmd->status & LEAPRAID_CMD_PENDING) {
+ cmd->status |= LEAPRAID_CMD_RESET;
+ complete(&cmd->done);
}
}
static void leapraid_clean_active_driver_cmds(struct leapraid_adapter *adapter)
{
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.timestamp_sync_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.raid_action_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.driver_scsiio_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.tm_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.transport_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.enc_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.notify_event_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.cfg_op_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.ctl_cmd);
-
- if (adapter->driver_cmds.scan_dev_cmd.status & LEAPRAID_CMD_PENDING) {
- adapter->scan_dev_desc.scan_dev_failed = true;
- adapter->driver_cmds.scan_dev_cmd.status |= LEAPRAID_CMD_RESET;
+ 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);
+ leapraid_clean_active_driver_cmd(&driver_cmds->notify_event_cmd);
+ leapraid_clean_active_driver_cmd(&driver_cmds->cfg_op_cmd);
+ leapraid_clean_active_driver_cmd(&driver_cmds->ctl_cmd);
+
+ if (driver_cmds->scan_dev_cmd.status & LEAPRAID_CMD_PENDING) {
+ adapter->scan_dev_desc.scan_dev_failed = 1;
+ driver_cmds->scan_dev_cmd.status |= LEAPRAID_CMD_RESET;
if (adapter->scan_dev_desc.driver_loading) {
adapter->scan_dev_desc.scan_start_failed =
LEAPRAID_ADAPTER_STATUS_INTERNAL_ERROR;
- adapter->scan_dev_desc.scan_start = false;
+ adapter->scan_dev_desc.scan_start = 0;
} else {
- complete(&adapter->driver_cmds.scan_dev_cmd.done);
+ complete(&driver_cmds->scan_dev_cmd.done);
}
}
}
@@ -592,10 +668,6 @@ static void leapraid_clean_active_driver_cmds(struct leapraid_adapter *adapter)
static void leapraid_clean_active_cmds(struct leapraid_adapter *adapter)
{
leapraid_clean_active_driver_cmds(adapter);
- memset(adapter->dev_topo.pending_dev_add, 0,
- adapter->dev_topo.pending_dev_add_sz);
- memset(adapter->dev_topo.dev_removing, 0,
- adapter->dev_topo.dev_removing_sz);
leapraid_clean_active_fw_evt(adapter);
leapraid_clean_active_scsi_cmds(adapter);
}
@@ -604,9 +676,9 @@ static void leapraid_tgt_not_responding(struct leapraid_adapter *adapter,
u16 hdl)
{
struct leapraid_starget_priv *starget_priv = NULL;
- struct leapraid_sas_dev *sas_dev = NULL;
+ struct leapraid_sas_dev *sas_dev;
unsigned long flags = 0;
- u32 adapter_state = 0;
+ u32 adapter_state;
if (adapter->access_ctrl.pcie_recovering)
return;
@@ -615,15 +687,15 @@ static void leapraid_tgt_not_responding(struct leapraid_adapter *adapter,
if (adapter_state != LEAPRAID_DB_OPERATIONAL)
return;
- if (test_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls))
+ if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle ||
+ test_bit(hdl, adapter->dev_topo.pd_hdls))
return;
- clear_bit(hdl, (unsigned long *)adapter->dev_topo.pending_dev_add);
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl);
if (sas_dev && sas_dev->starget && sas_dev->starget->hostdata) {
starget_priv = sas_dev->starget->hostdata;
- starget_priv->deleted = true;
+ starget_priv->deleted = 1;
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -637,9 +709,9 @@ static void leapraid_tgt_not_responding(struct leapraid_adapter *adapter,
static void leapraid_tgt_rst_send(struct leapraid_adapter *adapter, u16 hdl)
{
struct leapraid_starget_priv *starget_priv = NULL;
- struct leapraid_sas_dev *sas_dev = NULL;
- struct leapraid_card_port *port = NULL;
- u64 sas_address = 0;
+ struct leapraid_sas_dev *sas_dev;
+ struct leapraid_card_port *port;
+ u64 sas_address;
unsigned long flags;
u32 adapter_state;
@@ -650,15 +722,15 @@ static void leapraid_tgt_rst_send(struct leapraid_adapter *adapter, u16 hdl)
if (adapter_state != LEAPRAID_DB_OPERATIONAL)
return;
- if (test_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls))
+ if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle ||
+ test_bit(hdl, adapter->dev_topo.pd_hdls))
return;
- clear_bit(hdl, (unsigned long *)adapter->dev_topo.pending_dev_add);
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl);
if (sas_dev && sas_dev->starget && sas_dev->starget->hostdata) {
starget_priv = sas_dev->starget->hostdata;
- starget_priv->deleted = true;
+ starget_priv->deleted = 1;
sas_address = sas_dev->sas_addr;
port = sas_dev->card_port;
}
@@ -672,26 +744,30 @@ static void leapraid_tgt_rst_send(struct leapraid_adapter *adapter, u16 hdl)
leapraid_sdev_put(sas_dev);
}
-static inline void leapraid_single_mpi_sg_append(struct leapraid_adapter *adapter,
- void *sge, u32 flag_and_len,
- dma_addr_t dma_addr)
+static inline void leapraid_single_mpi_sg_append(
+ struct leapraid_adapter *adapter,
+ void *sge,
+ u32 flag_and_len,
+ dma_addr_t dma_addr)
{
if (adapter->adapter_attr.use_32_dma_mask) {
- ((struct leapraid_sge_simple32 *)sge)->flg_and_len =
+ struct leapraid_sge_simple32 *sge32 = sge;
+
+ sge32->flg_and_len =
cpu_to_le32(flag_and_len |
(LEAPRAID_SGE_FLG_32 |
LEAPRAID_SGE_FLG_SYSTEM_ADDR) <<
LEAPRAID_SGE_FLG_SHIFT);
- ((struct leapraid_sge_simple32 *)sge)->addr =
- cpu_to_le32(dma_addr);
+ sge32->addr = cpu_to_le32(dma_addr);
} else {
- ((struct leapraid_sge_simple64 *)sge)->flg_and_len =
+ struct leapraid_sge_simple64 *sge64 = sge;
+
+ sge64->flg_and_len =
cpu_to_le32(flag_and_len |
(LEAPRAID_SGE_FLG_64 |
LEAPRAID_SGE_FLG_SYSTEM_ADDR) <<
LEAPRAID_SGE_FLG_SHIFT);
- ((struct leapraid_sge_simple64 *)sge)->addr =
- cpu_to_le64(dma_addr);
+ sge64->addr = cpu_to_le64(dma_addr);
}
}
@@ -700,11 +776,12 @@ static inline void leapraid_single_ieee_sg_append(void *sge, u8 flag,
u32 len,
dma_addr_t dma_addr)
{
- ((struct leapraid_chain64_ieee_sg *)sge)->flg = flag;
- ((struct leapraid_chain64_ieee_sg *)sge)->next_chain_offset =
- next_chain_offset;
- ((struct leapraid_chain64_ieee_sg *)sge)->len = cpu_to_le32(len);
- ((struct leapraid_chain64_ieee_sg *)sge)->addr = cpu_to_le64(dma_addr);
+ struct leapraid_chain64_ieee_sg *ieee_sg = sge;
+
+ ieee_sg->flg = flag;
+ ieee_sg->next_chain_offset = next_chain_offset;
+ ieee_sg->len = cpu_to_le32(len);
+ ieee_sg->addr = cpu_to_le64(dma_addr);
}
static void leapraid_build_nodata_mpi_sg(struct leapraid_adapter *adapter,
@@ -712,12 +789,12 @@ static void leapraid_build_nodata_mpi_sg(struct leapraid_adapter *adapter,
{
leapraid_single_mpi_sg_append(adapter,
sge,
- (u32)((LEAPRAID_SGE_FLG_LAST_ONE |
- LEAPRAID_SGE_FLG_EOB |
- LEAPRAID_SGE_FLG_EOL |
- LEAPRAID_SGE_FLG_SIMPLE_ONE) <<
- LEAPRAID_SGE_FLG_SHIFT),
- -1);
+ (LEAPRAID_SGE_FLG_LAST_ONE |
+ LEAPRAID_SGE_FLG_EOB |
+ LEAPRAID_SGE_FLG_EOL |
+ LEAPRAID_SGE_FLG_SIMPLE_ONE) <<
+ LEAPRAID_SGE_FLG_SHIFT,
+ LEAPRAID_SGE_NO_DATA_ADDR);
}
void leapraid_build_mpi_sg(struct leapraid_adapter *adapter, void *sge,
@@ -768,7 +845,7 @@ void leapraid_build_mpi_sg(struct leapraid_adapter *adapter, void *sge,
c2h_size,
c2h_dma_addr);
} else {
- return leapraid_build_nodata_mpi_sg(adapter, sge);
+ leapraid_build_nodata_mpi_sg(adapter, sge);
}
}
@@ -778,7 +855,9 @@ void leapraid_build_ieee_nodata_sg(struct leapraid_adapter *adapter, void *sge)
(LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR |
LEAPRAID_IEEE_SGE_FLG_EOL),
- 0, 0, -1);
+ 0,
+ 0,
+ LEAPRAID_SGE_NO_DATA_ADDR);
}
int leapraid_build_scmd_ieee_sg(struct leapraid_adapter *adapter,
@@ -796,7 +875,7 @@ int leapraid_build_scmd_ieee_sg(struct leapraid_adapter *adapter,
u32 chain_offset_in_cur_seg;
u32 chain_len_in_cur_seg;
- io_tracker = leapraid_get_scmd_priv(scmd);
+ io_tracker = scsi_cmd_priv(scmd);
scsiio_req = leapraid_get_task_desc(adapter, taskid);
scmd_sg_cur = scsi_sglist(scmd);
sg_entries_left = scsi_dma_map(scmd);
@@ -834,7 +913,8 @@ int leapraid_build_scmd_ieee_sg(struct leapraid_adapter *adapter,
if (chain_offset_in_cur_seg)
chain_len_in_cur_seg += LEAPRAID_IEEE_SGE64_ENTRY_SIZE;
- leapraid_single_ieee_sg_append(sg_entry_cur,
+ leapraid_single_ieee_sg_append(
+ sg_entry_cur,
LEAPRAID_IEEE_SGE_FLG_CHAIN_ONE |
LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR,
chain_offset_in_cur_seg, chain_len_in_cur_seg,
@@ -844,7 +924,8 @@ int leapraid_build_scmd_ieee_sg(struct leapraid_adapter *adapter,
goto fill_last_seg;
while (sg_entries_in_cur_seg) {
- leapraid_single_ieee_sg_append(sg_entry_cur,
+ leapraid_single_ieee_sg_append(
+ sg_entry_cur,
LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR,
0, sg_dma_len(scmd_sg_cur),
@@ -881,39 +962,44 @@ void leapraid_build_ieee_sg(struct leapraid_adapter *adapter, void *sge,
dma_addr_t h2c_dma_addr, size_t h2c_size,
dma_addr_t c2h_dma_addr, size_t c2h_size)
{
+ u32 base_flag;
+ u32 flag;
+
+ base_flag = LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
+ LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR;
+
if (h2c_size && !c2h_size) {
+ flag = base_flag | LEAPRAID_IEEE_SGE_FLG_EOL;
+
leapraid_single_ieee_sg_append(sge,
- LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
- LEAPRAID_IEEE_SGE_FLG_EOL |
- LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR,
+ flag,
0,
h2c_size,
h2c_dma_addr);
} else if (!h2c_size && c2h_size) {
+ flag = base_flag | LEAPRAID_IEEE_SGE_FLG_EOL;
+
leapraid_single_ieee_sg_append(sge,
- LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
- LEAPRAID_IEEE_SGE_FLG_EOL |
- LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR,
+ flag,
0,
c2h_size,
c2h_dma_addr);
} else if (h2c_size && c2h_size) {
leapraid_single_ieee_sg_append(sge,
- LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
- LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR,
+ base_flag,
0,
h2c_size,
h2c_dma_addr);
sge += LEAPRAID_IEEE_SGE64_ENTRY_SIZE;
+
+ flag = base_flag | LEAPRAID_IEEE_SGE_FLG_EOL;
leapraid_single_ieee_sg_append(sge,
- LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
- LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR |
- LEAPRAID_IEEE_SGE_FLG_EOL,
+ flag,
0,
c2h_size,
c2h_dma_addr);
} else {
- return leapraid_build_ieee_nodata_sg(adapter, sge);
+ leapraid_build_ieee_nodata_sg(adapter, sge);
}
}
@@ -967,8 +1053,11 @@ static struct leapraid_card_port *leapraid_get_port_by_id(
if (unlikely(!adapter->adapter_attr.enable_mp)) {
port = kzalloc(sizeof(*port), GFP_ATOMIC);
- if (!port)
+ if (!port) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed to alloc port\n", __func__);
return NULL;
+ }
port->port_id = LEAPRAID_DISABLE_MP_PORT_ID;
list_add_tail(&port->list, &adapter->dev_topo.card_port_list);
@@ -995,7 +1084,8 @@ struct leapraid_vphy *leapraid_get_vphy_by_phy(struct leapraid_card_port *port,
}
struct leapraid_sas_dev *leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(
- struct leapraid_adapter *adapter, u64 sas_address,
+ struct leapraid_adapter *adapter,
+ u64 sas_address,
struct sas_rphy *rphy)
{
struct leapraid_sas_dev *sas_dev;
@@ -1025,8 +1115,10 @@ struct leapraid_sas_dev *leapraid_hold_lock_get_sas_dev_by_addr(
{
struct leapraid_sas_dev *sas_dev;
- if (!port)
+ if (!port) {
+ dev_warn(&adapter->pdev->dev, "%s: Invalid port\n", __func__);
return NULL;
+ }
assert_spin_locked(&adapter->dev_topo.sas_dev_lock);
list_for_each_entry(sas_dev, &adapter->dev_topo.sas_dev_list, list)
@@ -1054,8 +1146,10 @@ struct leapraid_sas_dev *leapraid_get_sas_dev_by_addr(
struct leapraid_sas_dev *sas_dev;
unsigned long flags;
- if (!port)
+ if (!port) {
+ dev_warn(&adapter->pdev->dev, "%s: Invalid port\n", __func__);
return NULL;
+ }
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter, sas_address,
@@ -1104,8 +1198,11 @@ void leapraid_sas_dev_remove(struct leapraid_adapter *adapter,
unsigned long flags;
bool del_from_list;
- if (!sas_dev)
+ if (!sas_dev) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid SAS device\n", __func__);
return;
+ }
del_from_list = false;
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
@@ -1115,8 +1212,10 @@ void leapraid_sas_dev_remove(struct leapraid_adapter *adapter,
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
- if (del_from_list)
+ if (del_from_list) {
+ leapraid_clear_cached_boot_dev(adapter, sas_dev, 0);
leapraid_sdev_put(sas_dev);
+ }
}
static void leapraid_sas_dev_remove_by_hdl(struct leapraid_adapter *adapter,
@@ -1132,12 +1231,10 @@ static void leapraid_sas_dev_remove_by_hdl(struct leapraid_adapter *adapter,
del_from_list = false;
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl);
- if (sas_dev) {
- if (!list_empty(&sas_dev->list)) {
- list_del_init(&sas_dev->list);
- del_from_list = true;
- leapraid_sdev_put(sas_dev);
- }
+ if (sas_dev && (!list_empty(&sas_dev->list))) {
+ list_del_init(&sas_dev->list);
+ del_from_list = true;
+ leapraid_sdev_put(sas_dev);
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -1162,12 +1259,10 @@ void leapraid_sas_dev_remove_by_sas_address(struct leapraid_adapter *adapter,
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter, sas_address,
port);
- if (sas_dev) {
- if (!list_empty(&sas_dev->list)) {
- list_del_init(&sas_dev->list);
- del_from_list = true;
- leapraid_sdev_put(sas_dev);
- }
+ if (sas_dev && (!list_empty(&sas_dev->list))) {
+ list_del_init(&sas_dev->list);
+ del_from_list = true;
+ leapraid_sdev_put(sas_dev);
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -1181,14 +1276,19 @@ struct leapraid_raid_volume *leapraid_raid_volume_find_by_id(
struct leapraid_adapter *adapter, uint id, uint channel)
{
struct leapraid_raid_volume *raid_volume;
+ unsigned long flags;
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
list_for_each_entry(raid_volume, &adapter->dev_topo.raid_volume_list,
list) {
- if (raid_volume->id == id &&
- raid_volume->channel == channel) {
+ if (raid_volume->id == id && raid_volume->channel == channel) {
+ leapraid_raid_volume_get(raid_volume);
+ spin_unlock_irqrestore(
+ &adapter->dev_topo.raid_volume_lock, flags);
return raid_volume;
}
}
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
return NULL;
}
@@ -1197,12 +1297,19 @@ struct leapraid_raid_volume *leapraid_raid_volume_find_by_hdl(
struct leapraid_adapter *adapter, u16 hdl)
{
struct leapraid_raid_volume *raid_volume;
+ unsigned long flags;
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
list_for_each_entry(raid_volume, &adapter->dev_topo.raid_volume_list,
list) {
- if (raid_volume->hdl == hdl)
+ if (raid_volume->hdl == hdl) {
+ leapraid_raid_volume_get(raid_volume);
+ spin_unlock_irqrestore(
+ &adapter->dev_topo.raid_volume_lock, flags);
return raid_volume;
+ }
}
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
return NULL;
}
@@ -1211,12 +1318,19 @@ static struct leapraid_raid_volume *leapraid_raid_volume_find_by_wwid(
struct leapraid_adapter *adapter, u64 wwid)
{
struct leapraid_raid_volume *raid_volume;
+ unsigned long flags;
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
list_for_each_entry(raid_volume, &adapter->dev_topo.raid_volume_list,
list) {
- if (raid_volume->wwid == wwid)
+ if (raid_volume->wwid == wwid) {
+ leapraid_raid_volume_get(raid_volume);
+ spin_unlock_irqrestore(
+ &adapter->dev_topo.raid_volume_lock, flags);
return raid_volume;
+ }
}
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
return NULL;
}
@@ -1227,6 +1341,7 @@ static void leapraid_raid_volume_add(struct leapraid_adapter *adapter,
unsigned long flags;
spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ leapraid_raid_volume_get(raid_volume);
list_add_tail(&raid_volume->list, &adapter->dev_topo.raid_volume_list);
spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
}
@@ -1235,11 +1350,24 @@ void leapraid_raid_volume_remove(struct leapraid_adapter *adapter,
struct leapraid_raid_volume *raid_volume)
{
unsigned long flags;
+ bool del_from_list = false;
+
+ if (!raid_volume) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid RAID volume\n", __func__);
+ return;
+ }
spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
- list_del(&raid_volume->list);
- kfree(raid_volume);
+ if (!list_empty(&raid_volume->list)) {
+ list_del_init(&raid_volume->list);
+ del_from_list = true;
+ }
spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+
+ leapraid_clear_cached_boot_dev(adapter, raid_volume, RAID_CHANNEL);
+ if (del_from_list)
+ leapraid_raid_volume_put(raid_volume);
}
static struct leapraid_enc_node *leapraid_enc_find_by_hdl(
@@ -1247,10 +1375,9 @@ static struct leapraid_enc_node *leapraid_enc_find_by_hdl(
{
struct leapraid_enc_node *enc_dev;
- list_for_each_entry(enc_dev, &adapter->dev_topo.enc_list, list) {
+ list_for_each_entry(enc_dev, &adapter->dev_topo.enc_list, list)
if (le16_to_cpu(enc_dev->pg0.enc_hdl) == hdl)
return enc_dev;
- }
return NULL;
}
@@ -1261,15 +1388,19 @@ struct leapraid_topo_node *leapraid_exp_find_by_sas_address(
{
struct leapraid_topo_node *sas_exp;
- if (!port)
+ if (!port) {
+ dev_warn(&adapter->pdev->dev, "%s: Invalid port\n", __func__);
return NULL;
+ }
- list_for_each_entry(sas_exp, &adapter->dev_topo.exp_list, list) {
+ list_for_each_entry(sas_exp, &adapter->dev_topo.exp_list, list)
if (sas_exp->sas_address == sas_address &&
sas_exp->card_port == port)
return sas_exp;
- }
+ dev_warn(&adapter->pdev->dev,
+ "%s: No expander found for SAS addr=0x%016llx port=%p\n",
+ __func__, (unsigned long long)sas_address, port);
return NULL;
}
@@ -1316,10 +1447,9 @@ static struct leapraid_topo_node *leapraid_exp_find_by_hdl(
{
struct leapraid_topo_node *sas_exp;
- list_for_each_entry(sas_exp, &adapter->dev_topo.exp_list, list) {
+ list_for_each_entry(sas_exp, &adapter->dev_topo.exp_list, list)
if (sas_exp->hdl == hdl)
return sas_exp;
- }
return NULL;
}
@@ -1347,7 +1477,7 @@ static enum leapraid_card_port_checking_flg leapraid_get_card_port_feature(
return CARD_PORT_FURTHER_CHECKING_NEEDED;
}
-static int leapraid_process_card_port_feature(
+static bool leapraid_process_card_port_feature(
struct leapraid_card_port_feature *feature)
{
struct leapraid_card_port *old_card_port;
@@ -1356,8 +1486,10 @@ static int leapraid_process_card_port_feature(
if (feature->exact_phy) {
feature->checking_state = SAME_PORT_WITH_NOTHING_CHANGED;
feature->expected_old_port = old_card_port;
- return 1;
- } else if (feature->phy_overlap) {
+ return true;
+ }
+
+ if (feature->phy_overlap) {
if (feature->same_port) {
feature->checking_state =
SAME_PORT_WITH_PARTIALLY_CHANGED_PHYS;
@@ -1368,21 +1500,20 @@ static int leapraid_process_card_port_feature(
SAME_ADDR_WITH_PARTIALLY_CHANGED_PHYS;
feature->expected_old_port = old_card_port;
}
- } else {
- if (feature->checking_state !=
- SAME_PORT_WITH_PARTIALLY_CHANGED_PHYS &&
- feature->checking_state !=
- SAME_ADDR_WITH_PARTIALLY_CHANGED_PHYS) {
- feature->checking_state = SAME_ADDR_ONLY;
- feature->expected_old_port = old_card_port;
- feature->same_addr_port_count++;
- }
+ } else if (feature->checking_state !=
+ SAME_PORT_WITH_PARTIALLY_CHANGED_PHYS &&
+ feature->checking_state !=
+ SAME_ADDR_WITH_PARTIALLY_CHANGED_PHYS) {
+ feature->checking_state = SAME_ADDR_ONLY;
+ feature->expected_old_port = old_card_port;
+ feature->same_addr_port_count++;
}
- return 0;
+ return false;
}
-static int leapraid_check_card_port(struct leapraid_adapter *adapter,
+static int leapraid_check_card_port(
+ struct leapraid_adapter *adapter,
struct leapraid_card_port *card_port,
struct leapraid_card_port **expected_card_port,
int *count)
@@ -1428,7 +1559,8 @@ static void leapraid_del_phy_part_of_anther_port(
continue;
if (card_port_table[i].phy_mask & BIT(offset)) {
- leapraid_transport_detach_phy_to_port(adapter,
+ leapraid_transport_detach_phy_to_port(
+ adapter,
card_topo_node,
&card_topo_node->card_phy[offset]);
found = true;
@@ -1448,7 +1580,7 @@ static void leapraid_add_or_del_phys_from_existing_port(
{
struct leapraid_topo_node *card_topo_node;
u32 phy_mask_diff;
- u32 offset = 0;
+ u32 offset;
card_topo_node = &adapter->dev_topo.card;
phy_mask_diff = card_port->phy_mask ^
@@ -1466,12 +1598,15 @@ static void leapraid_add_or_del_phys_from_existing_port(
}
if (card_topo_node->card_phy[offset].phy_is_assigned)
- leapraid_transport_detach_phy_to_port(adapter,
+ leapraid_transport_detach_phy_to_port(
+ adapter,
card_topo_node,
&card_topo_node->card_phy[offset]);
- leapraid_transport_attach_phy_to_port(adapter,
- card_topo_node, &card_topo_node->card_phy[offset],
+ leapraid_transport_attach_phy_to_port(
+ adapter,
+ card_topo_node,
+ &card_topo_node->card_phy[offset],
card_port->sas_address,
card_port);
}
@@ -1486,7 +1621,8 @@ struct leapraid_sas_dev *leapraid_get_next_sas_dev_from_init_list(
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
if (!list_empty(&adapter->dev_topo.sas_dev_init_list)) {
sas_dev = list_first_entry(&adapter->dev_topo.sas_dev_init_list,
- struct leapraid_sas_dev, list);
+ struct leapraid_sas_dev,
+ list);
leapraid_sdev_get(sas_dev);
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -1498,37 +1634,66 @@ static bool leapraid_check_boot_dev_internal(u64 sas_address, u64 dev_name,
struct leapraid_boot_dev *boot_dev,
u8 form)
{
+ struct leapraid_boot_dev_format_sas_wwid *wwid;
+ struct leapraid_boot_dev_format_enc_slot *es;
+ struct leapraid_boot_dev_format_dev_name *dn;
+ void *pg_dev;
+
if (!boot_dev)
return false;
+ pg_dev = boot_dev->pg_dev;
switch (form & LEAPRAID_BOOTDEV_FORM_MASK) {
case LEAPRAID_BOOTDEV_FORM_SAS_WWID:
+ wwid = pg_dev;
+
if (!sas_address)
return false;
- return sas_address ==
- le64_to_cpu(((struct leapraid_boot_dev_format_sas_wwid *)(
- boot_dev->pg_dev))->sas_addr);
+ return sas_address == le64_to_cpu(wwid->sas_addr);
case LEAPRAID_BOOTDEV_FORM_ENC_SLOT:
+ es = pg_dev;
+
if (!enc_lid)
return false;
- return (enc_lid == le64_to_cpu(((struct leapraid_boot_dev_format_enc_slot *)(
- boot_dev->pg_dev))->enc_lid) &&
- slot == le16_to_cpu(((struct leapraid_boot_dev_format_enc_slot *)(
- boot_dev->pg_dev))->slot_num));
+ return (enc_lid == le64_to_cpu(es->enc_lid) &&
+ slot == le16_to_cpu(es->slot_num));
case LEAPRAID_BOOTDEV_FORM_DEV_NAME:
+ dn = pg_dev;
+
if (!dev_name)
return false;
- return dev_name == le64_to_cpu(((struct leapraid_boot_dev_format_dev_name *)(
- boot_dev->pg_dev))->dev_name);
+ return dev_name == le64_to_cpu(dn->dev_name);
case LEAPRAID_BOOTDEV_FORM_NONE:
default:
return false;
}
}
+void leapraid_boot_dev_get(void *dev, u32 chnl)
+{
+ if (!dev)
+ return;
+
+ if (chnl == RAID_CHANNEL)
+ leapraid_raid_volume_get((struct leapraid_raid_volume *)dev);
+ else
+ leapraid_sdev_get((struct leapraid_sas_dev *)dev);
+}
+
+void leapraid_boot_dev_put(void *dev, u32 chnl)
+{
+ if (!dev)
+ return;
+
+ if (chnl == RAID_CHANNEL)
+ leapraid_raid_volume_put((struct leapraid_raid_volume *)dev);
+ else
+ leapraid_sdev_put((struct leapraid_sas_dev *)dev);
+}
+
static void leapraid_try_set_boot_dev(struct leapraid_boot_dev *boot_dev,
u64 sas_addr, u64 dev_name,
u64 enc_lid, u16 slot,
@@ -1543,15 +1708,56 @@ static void leapraid_try_set_boot_dev(struct leapraid_boot_dev *boot_dev,
slot, boot_dev,
boot_dev->form);
if (matched) {
+ leapraid_boot_dev_get(dev, chnl);
boot_dev->dev = dev;
boot_dev->chnl = chnl;
}
}
+static void leapraid_clear_boot_dev(struct leapraid_adapter *adapter,
+ struct leapraid_boot_dev *boot_dev,
+ void *dev, u32 chnl)
+{
+ void *cached_dev;
+ u32 cached_chnl;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->boot_devs.lock, flags);
+ if (boot_dev->dev != dev || boot_dev->chnl != chnl)
+ goto out_unlock;
+
+ cached_dev = boot_dev->dev;
+ cached_chnl = boot_dev->chnl;
+ boot_dev->dev = NULL;
+ boot_dev->chnl = 0;
+ spin_unlock_irqrestore(&adapter->boot_devs.lock, flags);
+ leapraid_boot_dev_put(cached_dev, cached_chnl);
+ return;
+
+out_unlock:
+ spin_unlock_irqrestore(&adapter->boot_devs.lock, flags);
+}
+
+static void leapraid_clear_cached_boot_dev(struct leapraid_adapter *adapter,
+ void *dev, u32 chnl)
+{
+ leapraid_clear_boot_dev(adapter,
+ &adapter->boot_devs.requested_boot_dev,
+ dev, chnl);
+ leapraid_clear_boot_dev(adapter,
+ &adapter->boot_devs.requested_alt_boot_dev,
+ dev, chnl);
+ leapraid_clear_boot_dev(adapter,
+ &adapter->boot_devs.current_boot_dev,
+ dev, chnl);
+}
+
static void leapraid_check_boot_dev(struct leapraid_adapter *adapter,
void *dev, u32 chnl)
{
- u64 sas_addr = 0;
+ struct leapraid_raid_volume *raid_volume;
+ struct leapraid_sas_dev *sas_dev;
+ u64 sas_addr;
u64 dev_name = 0;
u64 enc_lid = 0;
u16 slot = 0;
@@ -1561,24 +1767,17 @@ static void leapraid_check_boot_dev(struct leapraid_adapter *adapter,
switch (chnl) {
case RAID_CHANNEL:
- {
- struct leapraid_raid_volume *raid_volume =
- (struct leapraid_raid_volume *)dev;
-
+ raid_volume = dev;
sas_addr = raid_volume->wwid;
break;
- }
default:
- {
- struct leapraid_sas_dev *sas_dev =
- (struct leapraid_sas_dev *)dev;
+ sas_dev = dev;
sas_addr = sas_dev->sas_addr;
dev_name = sas_dev->dev_name;
enc_lid = sas_dev->enc_lid;
slot = sas_dev->slot;
break;
}
- }
leapraid_try_set_boot_dev(&adapter->boot_devs.requested_boot_dev,
sas_addr, dev_name, enc_lid,
@@ -1591,17 +1790,272 @@ static void leapraid_check_boot_dev(struct leapraid_adapter *adapter,
slot, dev, chnl);
}
-static void leapraid_build_and_fire_cfg_req(struct leapraid_adapter *adapter,
+static const char *leapraid_func_name(u8 func)
+{
+ switch (func) {
+ case LEAPRAID_FUNC_SCSIIO:
+ return "SCSIIO";
+ case LEAPRAID_FUNC_SCSI_TMF:
+ return "SCSI_TMF";
+ case LEAPRAID_FUNC_ADAPTER_INIT:
+ return "ADAPTER_INIT";
+ case LEAPRAID_FUNC_GET_ADAPTER_FEATURES:
+ return "GET_ADAPTER_FEATURES";
+ case LEAPRAID_FUNC_CONFIG_OP:
+ return "CONFIG_OP";
+ case LEAPRAID_FUNC_SCAN_DEV:
+ return "SCAN_DEV";
+ case LEAPRAID_FUNC_EVENT_NOTIFY:
+ return "EVENT_NOTIFY";
+ case LEAPRAID_FUNC_FW_DOWNLOAD:
+ return "FW_DOWNLOAD";
+ case LEAPRAID_FUNC_FW_UPLOAD:
+ return "FW_UPLOAD";
+ case LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH:
+ return "SCSIIO_RAID_PASSTHROUGH";
+ case LEAPRAID_FUNC_SCSI_ENC_PROCESSOR:
+ return "SCSI_ENC_PROCESSOR";
+ case LEAPRAID_FUNC_SMP_PASSTHROUGH:
+ return "SMP_PASSTHROUGH";
+ case LEAPRAID_FUNC_SAS_IO_UNIT_CTRL:
+ return "SAS_IO_UNIT_CTRL";
+ case LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH:
+ return "SCSIIO_SATA_PASSTHROUGH";
+ case LEAPRAID_FUNC_ADAPTER_UNIT_RESET:
+ return "ADAPTER_UNIT_RESET";
+ case LEAPRAID_FUNC_HANDSHAKE:
+ return "HANDSHAKE";
+ case LEAPRAID_FUNC_LOGBUF_INIT:
+ return "LOGBUF_INIT";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char *leapraid_cfg_action_name(u8 action)
+{
+ switch (action) {
+ case LEAPRAID_CFG_ACT_PAGE_HEADER:
+ return "PAGE_HEADER";
+ case LEAPRAID_CFG_ACT_PAGE_READ_CUR:
+ return "PAGE_READ_CUR";
+ case LEAPRAID_CFG_ACT_PAGE_WRITE_CUR:
+ return "PAGE_WRITE_CUR";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char *leapraid_cfg_page_type_name(u8 page_type)
+{
+ switch (page_type) {
+ case LEAPRAID_CFG_PT_IO_UNIT:
+ return "IO_UNIT";
+ case LEAPRAID_CFG_PT_ADAPTER:
+ return "ADAPTER";
+ case LEAPRAID_CFG_PT_BIOS:
+ return "BIOS";
+ case LEAPRAID_CFG_PT_RAID_VOLUME:
+ return "RAID_VOLUME";
+ case LEAPRAID_CFG_PT_MANUFACTURING:
+ return "MANUFACTURING";
+ case LEAPRAID_CFG_PT_RAID_PHYSDISK:
+ return "RAID_PHYSDISK";
+ case LEAPRAID_CFG_PT_EXTENDED:
+ return "EXTENDED";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char *leapraid_cfg_ext_page_type_name(u8 ext_page_type)
+{
+ switch (ext_page_type) {
+ case LEAPRAID_CFG_EXTPT_SAS_IO_UNIT:
+ return "SAS_IO_UNIT";
+ case LEAPRAID_CFG_EXTPT_SAS_EXP:
+ return "SAS_EXPANDER";
+ case LEAPRAID_CFG_EXTPT_SAS_DEV:
+ return "SAS_DEVICE";
+ case LEAPRAID_CFG_EXTPT_SAS_PHY:
+ return "SAS_PHY";
+ case LEAPRAID_CFG_EXTPT_ENC:
+ return "ENCLOSURE";
+ case LEAPRAID_CFG_EXTPT_RAID_CONFIG:
+ return "RAID_CONFIG";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char *leapraid_sep_action_name(u8 action)
+{
+ switch (action) {
+ case LEAPRAID_SEP_REQ_ACT_WRITE_STATUS:
+ return "WRITE_STATUS";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char *leapraid_sas_op_name(u8 op)
+{
+ switch (op) {
+ case LEAPRAID_SAS_OP_PHY_LINK_RESET:
+ return "PHY_LINK_RESET";
+ case LEAPRAID_SAS_OP_PHY_HARD_RESET:
+ return "PHY_HARD_RESET";
+ case LEAPRAID_SAS_OP_SET_PARAMETER:
+ return "SET_PARAMETER";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+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) {
+ case LEAPRAID_TM_TASKTYPE_ABORT_TASK:
+ return "ABORT_TASK";
+ case LEAPRAID_TM_TASKTYPE_ABRT_TASK_SET:
+ return "ABORT_TASK_SET";
+ case LEAPRAID_TM_TASKTYPE_TARGET_RESET:
+ return "TARGET_RESET";
+ case LEAPRAID_TM_TASKTYPE_LOGICAL_UNIT_RESET:
+ return "LOGICAL_UNIT_RESET";
+ case LEAPRAID_TM_TASKTYPE_CLEAR_TASK_SET:
+ return "CLEAR_TASK_SET";
+ case LEAPRAID_TM_TASKTYPE_QUERY_TASK:
+ return "QUERY_TASK";
+ case LEAPRAID_TM_TASKTYPE_CLEAR_ACA:
+ return "CLEAR_ACA";
+ case LEAPRAID_TM_TASKTYPE_QUERY_TASK_SET:
+ return "QUERY_TASK_SET";
+ case LEAPRAID_TM_TASKTYPE_QUERY_ASYNC_EVENT:
+ return "QUERY_ASYNC_EVENT";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+void leapraid_log_req_context(struct leapraid_adapter *adapter,
+ const void *req_data)
+{
+ const struct leapraid_req *req = req_data;
+
+ if (!adapter || !adapter->pdev || !req_data)
+ return;
+
+ switch (req->func) {
+ case LEAPRAID_FUNC_CONFIG_OP: {
+ 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->action,
+ leapraid_cfg_action_name(cfg_req->action));
+ dev_err(&adapter->pdev->dev,
+ "cfg-req: page_type=0x%02x(%s) page_num=%u\n",
+ cfg_req->header.page_type,
+ leapraid_cfg_page_type_name(cfg_req->header.page_type),
+ cfg_req->header.page_num);
+ if (cfg_req->header.page_type == LEAPRAID_CFG_PT_EXTENDED)
+ dev_err(&adapter->pdev->dev,
+ "cfg-req: ext_page_type=0x%02x(%s)\n",
+ cfg_req->ext_page_type,
+ leapraid_cfg_ext_page_type_name(
+ cfg_req->ext_page_type));
+ dev_err(&adapter->pdev->dev, "cfg-req: page_addr=0x%08x\n",
+ le32_to_cpu(cfg_req->page_addr));
+ break;
+ }
+ case LEAPRAID_FUNC_SCSI_TMF: {
+ 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),
+ 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",
+ le16_to_cpu(tm_req->dev_hdl),
+ le16_to_cpu(tm_req->task_mid));
+ break;
+ }
+ case LEAPRAID_FUNC_SCSI_ENC_PROCESSOR: {
+ 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_req->act,
+ leapraid_sep_action_name(sep_req->act));
+ dev_err(&adapter->pdev->dev,
+ "sep: dev_hdl=0x%04x slot=%u enc_hdl=0x%04x\n",
+ le16_to_cpu(sep_req->dev_hdl),
+ le16_to_cpu(sep_req->slot),
+ le16_to_cpu(sep_req->enc_hdl));
+ break;
+ }
+ case LEAPRAID_FUNC_SAS_IO_UNIT_CTRL: {
+ 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),
+ 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",
+ le16_to_cpu(io_req->dev_hdl),
+ io_req->adapter_para,
+ leapraid_io_param_name(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_req->physical_port,
+ le16_to_cpu(smp_req->req_data_len));
+ dev_err(&adapter->pdev->dev, "transport: 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));
+ break;
+ }
+}
+
+static void leapraid_build_and_fire_cfg_req(
+ struct leapraid_adapter *adapter,
struct leapraid_cfg_req *leap_mpi_cfgp_req,
struct leapraid_cfg_rep *leap_mpi_cfgp_rep)
{
struct leapraid_cfg_req *local_leap_cfg_req;
memset(leap_mpi_cfgp_rep, 0, sizeof(struct leapraid_cfg_rep));
- memset((void *)(&adapter->driver_cmds.cfg_op_cmd.reply), 0,
+ 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,
+ local_leap_cfg_req = leapraid_get_task_desc(
+ adapter,
adapter->driver_cmds.cfg_op_cmd.inter_taskid);
memcpy(local_leap_cfg_req, leap_mpi_cfgp_req,
sizeof(struct leapraid_cfg_req));
@@ -1629,17 +2083,18 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter,
if (retry_cnt) {
if (retry_cnt > LEAPRAID_CFG_REQ_RETRY_TIMES) {
rc = -EFAULT;
- goto out;
+ goto out_cleanup;
}
dev_warn(&adapter->pdev->dev,
- "cfg-req: retry request, cnt=%u\n", retry_cnt);
+ "cfg-req: Retry request, cnt=%u\n", retry_cnt);
}
- rc = leapraid_check_adapter_is_op(adapter);
+ rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
+ __func__);
if (rc) {
dev_err(&adapter->pdev->dev,
- "cfg-req: adapter not operational\n");
- goto out;
+ "cfg-req: Adapter not operational\n");
+ goto out_cleanup;
}
leapraid_build_and_fire_cfg_req(adapter, leap_mpi_cfgp_req,
@@ -1649,44 +2104,47 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter,
if (adapter->driver_cmds.cfg_op_cmd.status &
LEAPRAID_CMD_RESET) {
dev_warn(&adapter->pdev->dev,
- "cfg-req: cmd gg due to hard reset\n");
+ "cfg-req: CMD fail due to hard reset\n");
goto retry;
}
if (adapter->access_ctrl.shost_recovering ||
adapter->access_ctrl.pcie_recovering) {
dev_err(&adapter->pdev->dev,
- "cfg-req: cmd not done during %s, skip reset\n",
+ "cfg-req: pending in %s, status=0x%x\n",
adapter->access_ctrl.shost_recovering ?
- "shost recovery" : "pcie recovery");
+ "shost recovery" : "pcie recovery",
+ adapter->driver_cmds.cfg_op_cmd.status);
+ leapraid_log_req_context(adapter, leap_mpi_cfgp_req);
issue_reset = false;
rc = -EFAULT;
} else {
dev_err(&adapter->pdev->dev,
- "cfg-req: cmd timeout, issuing hard reset\n");
+ "cfg-req: timeout, status=0x%x, reset\n",
+ adapter->driver_cmds.cfg_op_cmd.status);
+ leapraid_log_req_context(adapter, leap_mpi_cfgp_req);
issue_reset = true;
}
- goto out;
+ goto out_cleanup;
}
if (adapter->driver_cmds.cfg_op_cmd.status &
LEAPRAID_CMD_REPLY_VALID) {
memcpy(leap_mpi_cfgp_rep,
- (void *)(&adapter->driver_cmds.cfg_op_cmd.reply),
+ &adapter->driver_cmds.cfg_op_cmd.reply,
sizeof(struct leapraid_cfg_rep));
adapter_status = le16_to_cpu(
leap_mpi_cfgp_rep->adapter_status) &
LEAPRAID_ADAPTER_STATUS_MASK;
- if (adapter_status == LEAPRAID_ADAPTER_STATUS_SUCCESS) {
- if (target_cfg_pg && real_cfg_pg_addr &&
- target_real_cfg_pg_sz)
- if (leap_mpi_cfgp_req->action ==
- LEAPRAID_CFG_ACT_PAGE_READ_CUR)
- memcpy(target_cfg_pg,
- real_cfg_pg_addr,
- target_real_cfg_pg_sz);
- } else {
+ if (adapter_status == LEAPRAID_ADAPTER_STATUS_SUCCESS &&
+ target_cfg_pg && real_cfg_pg_addr &&
+ target_real_cfg_pg_sz &&
+ leap_mpi_cfgp_req->action ==
+ LEAPRAID_CFG_ACT_PAGE_READ_CUR)
+ memcpy(target_cfg_pg, real_cfg_pg_addr,
+ target_real_cfg_pg_sz);
+ if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS) {
if (adapter_status !=
LEAPRAID_ADAPTER_STATUS_CONFIG_INVALID_PAGE)
dev_err(&adapter->pdev->dev,
@@ -1695,30 +2153,30 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter,
rc = -EFAULT;
}
} else {
- dev_err(&adapter->pdev->dev, "cfg-rep: reply invalid\n");
+ dev_err(&adapter->pdev->dev, "cfg-rep: Reply invalid\n");
rc = -EFAULT;
}
-out:
+out_cleanup:
adapter->driver_cmds.cfg_op_cmd.status = LEAPRAID_CMD_NOT_USED;
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,
- "%s:%d cfg-req: failure, issuing reset\n",
+ "%s:%d cfg-req: Failure, issuing reset\n",
__func__, __LINE__);
leapraid_hard_reset_handler(adapter, FULL_RESET);
- rc = -EFAULT;
} else {
dev_warn(&adapter->pdev->dev,
- "cfg-req: cmd gg during init, skip reset\n");
- rc = -EFAULT;
+ "cfg-req: CMD fail in init, skip reset\n");
}
+ rc = -EFAULT;
}
return rc;
}
-static int leapraid_request_cfg_pg_header(struct leapraid_adapter *adapter,
+static int leapraid_request_cfg_pg_header(
+ struct leapraid_adapter *adapter,
struct leapraid_cfg_req *leap_mpi_cfgp_req,
struct leapraid_cfg_rep *leap_mpi_cfgp_rep)
{
@@ -1744,8 +2202,8 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
{
struct leapraid_cfg_req leap_mpi_cfgp_req;
struct leapraid_cfg_rep leap_mpi_cfgp_rep;
- u16 real_cfg_pg_sz = 0;
- void *real_cfg_pg_addr = NULL;
+ u16 real_cfg_pg_sz;
+ void *real_cfg_pg_addr;
dma_addr_t real_cfg_pg_dma = 0;
u32 __page_size;
int rc;
@@ -1767,6 +2225,13 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
LEAPRAID_CFG_PAGE_NUM_BIOS2;
__page_size = sizeof(struct leapraid_bios_page2);
break;
+ case GET_MANUFACTURING_PG0:
+ leap_mpi_cfgp_req.header.page_type =
+ LEAPRAID_CFG_PT_MANUFACTURING;
+ leap_mpi_cfgp_req.header.page_num =
+ LEAPRAID_CFG_PAGE_NUM_MANU0;
+ __page_size = sizeof(struct leapraid_manufacturing_p0);
+ break;
case GET_SAS_DEVICE_PG0:
leap_mpi_cfgp_req.header.page_type = LEAPRAID_CFG_PT_EXTENDED;
leap_mpi_cfgp_req.ext_page_type = LEAPRAID_CFG_EXTPT_SAS_DEV;
@@ -1833,9 +2298,8 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
break;
default:
dev_err(&adapter->pdev->dev,
- "unsupported config page action=%d!\n", cfg_op);
- rc = -EINVAL;
- goto out;
+ "Unsupported config page action=%d!\n", cfg_op);
+ return -EINVAL;
}
leapraid_build_nodata_mpi_sg(adapter,
@@ -1845,8 +2309,8 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
&leap_mpi_cfgp_rep);
if (rc) {
dev_err(&adapter->pdev->dev,
- "cfg-req: header failed rc=%dn", rc);
- goto out;
+ "cfg-req: Header failed rc=%dn", rc);
+ return rc;
}
if (cfg_op == GET_SAS_DEVICE_PG0 ||
@@ -1882,17 +2346,14 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
leap_mpi_cfgp_req.ext_page_type = leap_mpi_cfgp_rep.ext_page_type;
real_cfg_pg_sz = (leap_mpi_cfgp_req.header.page_len) ?
- leap_mpi_cfgp_req.header.page_len * 4 :
- le16_to_cpu(leap_mpi_cfgp_rep.ext_page_len) * 4;
+ leap_mpi_cfgp_req.header.page_len * sizeof(u32) :
+ le16_to_cpu(leap_mpi_cfgp_rep.ext_page_len) * sizeof(u32);
real_cfg_pg_addr = dma_alloc_coherent(&adapter->pdev->dev,
real_cfg_pg_sz,
&real_cfg_pg_dma,
GFP_KERNEL);
- if (!real_cfg_pg_addr) {
- dev_err(&adapter->pdev->dev, "cfg-req: dma alloc failed\n");
- rc = -ENOMEM;
- goto out;
- }
+ if (!real_cfg_pg_addr)
+ return -ENOMEM;
if (leap_mpi_cfgp_req.action == LEAPRAID_CFG_ACT_PAGE_WRITE_CUR) {
leapraid_single_mpi_sg_append(adapter,
@@ -1929,12 +2390,11 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
real_cfg_pg_addr,
min_t(u16, real_cfg_pg_sz, __page_size));
if (rc) {
- u32 adapter_status;
+ u32 status;
- adapter_status = le16_to_cpu(leap_mpi_cfgp_rep.adapter_status) &
- LEAPRAID_ADAPTER_STATUS_MASK;
- if (adapter_status !=
- LEAPRAID_ADAPTER_STATUS_CONFIG_INVALID_PAGE)
+ status = le16_to_cpu(leap_mpi_cfgp_rep.adapter_status) &
+ LEAPRAID_ADAPTER_STATUS_MASK;
+ if (status != LEAPRAID_ADAPTER_STATUS_CONFIG_INVALID_PAGE)
dev_err(&adapter->pdev->dev,
"cfg-req: rc=%d, pg_info: 0x%x, 0x%x, %d\n",
rc, leap_mpi_cfgp_req.header.page_type,
@@ -1947,10 +2407,52 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
real_cfg_pg_sz,
real_cfg_pg_addr,
real_cfg_pg_dma);
-out:
+
return rc;
}
+static int leapraid_cfg_find_vol_in_page(
+ struct leapraid_raid_cfg_p0 *raid_cfg_p0,
+ u16 pd_hdl, u16 *vol_hdl)
+{
+ u16 elements = raid_cfg_p0->elements_num;
+ int i;
+
+ for (i = 0; i < elements; i++) {
+ struct leapraid_raid_cfg_p0_element *elem;
+ u16 type;
+
+ elem = &raid_cfg_p0->cfg_element[i];
+
+ type = le16_to_cpu(elem->element_flg) &
+ LEAPRAID_RAIDCFG_P0_EFLG_MASK_ELEMENT_TYPE;
+
+ switch (type) {
+ case LEAPRAID_RAIDCFG_P0_EFLG_VOL_PHYS_DISK_ELEMENT:
+ case LEAPRAID_RAIDCFG_P0_EFLG_OCE_ELEMENT: {
+ 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;
+
+ default:
+ break;
+ }
+ }
+
+ return -ENOENT;
+}
+
static int leapraid_cfg_get_volume_hdl_dispatch(
struct leapraid_adapter *adapter,
struct leapraid_cfg_req *cfg_req,
@@ -1961,13 +2463,11 @@ static int leapraid_cfg_get_volume_hdl_dispatch(
u16 raid_cfg_p0_sz,
u16 pd_hdl, u16 *vol_hdl)
{
- u16 phys_disk_dev_hdl;
u16 adapter_status;
- u16 element_type;
int config_num;
- int rc, i;
+ int rc;
- config_num = 0xff;
+ config_num = 0xFF;
while (true) {
cfg_req->page_addr =
cpu_to_le32(config_num +
@@ -1988,35 +2488,14 @@ static int leapraid_cfg_get_volume_hdl_dispatch(
}
if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS)
- return -1;
-
- for (i = 0; i < raid_cfg_p0->elements_num; i++) {
- element_type =
- le16_to_cpu(raid_cfg_p0->cfg_element[i].element_flg) &
- LEAPRAID_RAIDCFG_P0_EFLG_MASK_ELEMENT_TYPE;
-
- switch (element_type) {
- case LEAPRAID_RAIDCFG_P0_EFLG_VOL_PHYS_DISK_ELEMENT:
- case LEAPRAID_RAIDCFG_P0_EFLG_OCE_ELEMENT:
- phys_disk_dev_hdl =
- le16_to_cpu(raid_cfg_p0->cfg_element[i]
- .phys_disk_dev_hdl);
- if (phys_disk_dev_hdl == pd_hdl) {
- *vol_hdl =
- le16_to_cpu
- (raid_cfg_p0->cfg_element[i]
- .vol_dev_hdl);
- return 0;
- }
- break;
+ return LEAPRAID_OPERATION_FAILED;
+
+ rc = leapraid_cfg_find_vol_in_page(raid_cfg_p0,
+ pd_hdl,
+ vol_hdl);
+ if (rc != -ENOENT)
+ return rc;
- case LEAPRAID_RAIDCFG_P0_EFLG_HOT_SPARE_ELEMENT:
- *vol_hdl = 0;
- return 0;
- default:
- break;
- }
- }
config_num = raid_cfg_p0->cfg_num;
}
return 0;
@@ -2025,12 +2504,12 @@ static int leapraid_cfg_get_volume_hdl_dispatch(
int leapraid_cfg_get_volume_hdl(struct leapraid_adapter *adapter,
u16 pd_hdl, u16 *vol_hdl)
{
- struct leapraid_raid_cfg_p0 *raid_cfg_p0 = NULL;
+ struct leapraid_raid_cfg_p0 *raid_cfg_p0;
struct leapraid_cfg_req cfg_req;
struct leapraid_cfg_rep cfg_rep;
dma_addr_t real_cfg_pg_dma = 0;
- void *real_cfg_pg_addr = NULL;
- u16 real_cfg_pg_sz = 0;
+ void *real_cfg_pg_addr;
+ u16 real_cfg_pg_sz;
int rc, raid_cfg_p0_sz;
*vol_hdl = 0;
@@ -2044,16 +2523,14 @@ int leapraid_cfg_get_volume_hdl(struct leapraid_adapter *adapter,
leapraid_build_nodata_mpi_sg(adapter, &cfg_req.page_buf_sge);
rc = leapraid_request_cfg_pg_header(adapter, &cfg_req, &cfg_rep);
if (rc)
- goto out;
+ return rc;
cfg_req.action = LEAPRAID_CFG_ACT_PAGE_READ_CUR;
raid_cfg_p0_sz = le16_to_cpu(cfg_rep.ext_page_len) *
LEAPRAID_CFG_UNIT_SIZE;
raid_cfg_p0 = kmalloc(raid_cfg_p0_sz, GFP_KERNEL);
- if (!raid_cfg_p0) {
- rc = -1;
- goto out;
- }
+ if (!raid_cfg_p0)
+ return -ENOMEM;
real_cfg_pg_sz = (cfg_req.header.page_len) ?
cfg_req.header.page_len * LEAPRAID_CFG_UNIT_SIZE :
@@ -2064,7 +2541,7 @@ int leapraid_cfg_get_volume_hdl(struct leapraid_adapter *adapter,
GFP_KERNEL);
if (!real_cfg_pg_addr) {
rc = -ENOMEM;
- goto out;
+ goto out_free;
}
memset(raid_cfg_p0, 0, raid_cfg_p0_sz);
@@ -2088,7 +2565,7 @@ int leapraid_cfg_get_volume_hdl(struct leapraid_adapter *adapter,
raid_cfg_p0_sz,
pd_hdl, vol_hdl);
-out:
+out_free:
if (real_cfg_pg_addr)
dma_free_coherent(&adapter->pdev->dev,
real_cfg_pg_sz, real_cfg_pg_addr,
@@ -2103,7 +2580,7 @@ static int leapraid_get_adapter_phys(struct leapraid_adapter *adapter,
struct leapraid_sas_io_unit_p0 sas_io_unit_page0;
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- int rc = 0;
+ int rc;
*nr_phys = 0;
cfgp1.size = sizeof(struct leapraid_sas_io_unit_p0);
@@ -2156,7 +2633,8 @@ int leapraid_cfg_get_volume_wwid(struct leapraid_adapter *adapter,
return rc;
}
-static int leapraid_get_sas_io_unit_page0(struct leapraid_adapter *adapter,
+static int leapraid_get_sas_io_unit_page0(
+ struct leapraid_adapter *adapter,
struct leapraid_sas_io_unit_p0 *sas_io_unit_p0,
u16 sas_iou_pg0_sz)
{
@@ -2178,8 +2656,8 @@ static int leapraid_get_sas_address(struct leapraid_adapter *adapter,
*sas_address = 0;
cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
cfgp2.handle = hdl;
- if ((leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1,
- cfgp2, GET_SAS_DEVICE_PG0)))
+ if (leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1,
+ cfgp2, GET_SAS_DEVICE_PG0))
return -ENXIO;
if (hdl <= adapter->dev_topo.card.phys_num &&
@@ -2201,9 +2679,10 @@ int leapraid_get_volume_cap(struct leapraid_adapter *adapter,
struct leapraid_raidpd_p0 raidpd_p0;
u8 num_pds;
u16 sz;
+ int rc = 0;
- if ((leapraid_cfg_get_number_pds(adapter, raid_volume->hdl,
- &num_pds)) || !num_pds)
+ if (leapraid_cfg_get_number_pds(adapter, raid_volume->hdl,
+ &num_pds) || !num_pds)
return -EFAULT;
raid_volume->pd_num = num_pds;
@@ -2211,14 +2690,14 @@ int leapraid_get_volume_cap(struct leapraid_adapter *adapter,
(num_pds * sizeof(struct leapraid_raidvol0_phys_disk));
raidvol_p0 = kzalloc(sz, GFP_KERNEL);
if (!raidvol_p0)
- return -EFAULT;
+ return -ENOMEM;
cfgp1.size = sz;
cfgp2.handle = raid_volume->hdl;
- if ((leapraid_op_config_page(adapter, raidvol_p0, cfgp1, cfgp2,
- GET_RAID_VOLUME_PG0))) {
- kfree(raidvol_p0);
- return -EFAULT;
+ if (leapraid_op_config_page(adapter, raidvol_p0, cfgp1, cfgp2,
+ GET_RAID_VOLUME_PG0)) {
+ rc = -EFAULT;
+ goto out_cleanup;
}
raid_volume->vol_type = raidvol_p0->volume_type;
@@ -2229,14 +2708,28 @@ int leapraid_get_volume_cap(struct leapraid_adapter *adapter,
cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
cfgp2.handle = le16_to_cpu(raidpd_p0.dev_hdl);
if (!(leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1,
- cfgp2, GET_SAS_DEVICE_PG0))) {
+ cfgp2, GET_SAS_DEVICE_PG0)))
raid_volume->dev_info =
le32_to_cpu(sas_dev_p0.dev_info);
- }
}
+out_cleanup:
kfree(raidvol_p0);
- return 0;
+ return rc;
+}
+
+static bool leapraid_should_skip_poll_work(struct leapraid_adapter *adapter)
+{
+ unsigned long flags;
+ bool skip;
+
+ spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
+ skip = adapter->access_ctrl.shost_recovering ||
+ adapter->access_ctrl.pcie_recovering ||
+ adapter->access_ctrl.host_removing;
+ spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
+
+ return skip;
}
static void leapraid_fw_log_work(struct work_struct *work)
@@ -2244,26 +2737,34 @@ static void leapraid_fw_log_work(struct work_struct *work)
struct leapraid_adapter *adapter = container_of(work,
struct leapraid_adapter, fw_log_desc.fw_log_work.work);
struct leapraid_fw_log_info *infom;
+ struct leapraid_reg_base __iomem *iomem_base;
unsigned long flags;
- infom = (struct leapraid_fw_log_info *)(adapter->fw_log_desc.fw_log_buffer +
- LEAPRAID_SYS_LOG_BUF_SIZE);
+ if (leapraid_should_skip_poll_work(adapter))
+ goto scheduled_timer;
+
+ infom = (struct leapraid_fw_log_info *)
+ (adapter->fw_log_desc.fw_log_buffer +
+ LEAPRAID_SYS_LOG_BUF_SIZE);
+ iomem_base = adapter->iomem_base;
if (adapter->fw_log_desc.fw_log_init_flag == 0) {
infom->user_position =
- leapraid_readl(&adapter->iomem_base->host_log_buf_pos);
+ leapraid_readl(&iomem_base->host_log_buf_pos);
infom->adapter_position =
- leapraid_readl(&adapter->iomem_base->adapter_log_buf_pos);
+ leapraid_readl(&iomem_base->adapter_log_buf_pos);
adapter->fw_log_desc.fw_log_init_flag++;
}
- writel(infom->user_position, &adapter->iomem_base->host_log_buf_pos);
+ writel(infom->user_position, &iomem_base->host_log_buf_pos);
infom->adapter_position =
- leapraid_readl(&adapter->iomem_base->adapter_log_buf_pos);
+ leapraid_readl(&iomem_base->adapter_log_buf_pos);
+scheduled_timer:
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
if (adapter->fw_log_desc.fw_log_wq)
- queue_delayed_work(adapter->fw_log_desc.fw_log_wq,
+ queue_delayed_work(
+ adapter->fw_log_desc.fw_log_wq,
&adapter->fw_log_desc.fw_log_work,
msecs_to_jiffies(LEAPRAID_PCIE_LOG_POLLING_INTERVAL));
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
@@ -2282,7 +2783,8 @@ void leapraid_fw_log_stop(struct leapraid_adapter *adapter)
adapter->fw_log_desc.fw_log_wq = NULL;
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
if (wq) {
- if (!cancel_delayed_work_sync(&adapter->fw_log_desc.fw_log_work))
+ if (!cancel_delayed_work_sync(&adapter->fw_log_desc
+ .fw_log_work))
flush_workqueue(wq);
destroy_workqueue(wq);
}
@@ -2312,7 +2814,8 @@ void leapraid_fw_log_start(struct leapraid_adapter *adapter)
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
if (adapter->fw_log_desc.fw_log_wq)
- queue_delayed_work(adapter->fw_log_desc.fw_log_wq,
+ queue_delayed_work(
+ adapter->fw_log_desc.fw_log_wq,
&adapter->fw_log_desc.fw_log_work,
msecs_to_jiffies(LEAPRAID_PCIE_LOG_POLLING_INTERVAL));
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
@@ -2323,12 +2826,13 @@ 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 = 0;
+ 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,
+ 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;
@@ -2343,18 +2847,27 @@ static void leapraid_timestamp_sync(struct leapraid_adapter *adapter)
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);
- wait_for_completion_timeout(&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))
+ 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",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
leapraid_hard_reset_handler(adapter, FULL_RESET);
}
@@ -2363,20 +2876,6 @@ static void leapraid_timestamp_sync(struct leapraid_adapter *adapter)
mutex_unlock(&adapter->driver_cmds.timestamp_sync_cmd.mutex);
}
-static bool leapraid_should_skip_fault_check(struct leapraid_adapter *adapter)
-{
- unsigned long flags;
- bool skip;
-
- spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
- skip = adapter->access_ctrl.shost_recovering ||
- adapter->access_ctrl.pcie_recovering ||
- adapter->access_ctrl.host_removing;
- spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
-
- return skip;
-}
-
static void leapraid_check_scheduled_fault_work(struct work_struct *work)
{
struct leapraid_adapter *adapter;
@@ -2387,16 +2886,16 @@ static void leapraid_check_scheduled_fault_work(struct work_struct *work)
adapter = container_of(work, struct leapraid_adapter,
reset_desc.fault_reset_work.work);
- if (leapraid_should_skip_fault_check(adapter))
+ if (leapraid_should_skip_poll_work(adapter))
goto scheduled_timer;
adapter_state = leapraid_get_adapter_state(adapter);
if (adapter_state != LEAPRAID_DB_OPERATIONAL) {
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
- dev_warn(&adapter->pdev->dev, "%s: hard reset: %s\n",
- __func__, (rc == 0) ? "success" : "failed");
+ 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)
@@ -2412,7 +2911,8 @@ static void leapraid_check_scheduled_fault_work(struct work_struct *work)
scheduled_timer:
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
if (adapter->reset_desc.fault_reset_wq)
- queue_delayed_work(adapter->reset_desc.fault_reset_wq,
+ queue_delayed_work(
+ adapter->reset_desc.fault_reset_wq,
&adapter->reset_desc.fault_reset_work,
msecs_to_jiffies(LEAPRAID_FAULT_POLLING_INTERVAL));
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
@@ -2437,14 +2937,15 @@ void leapraid_check_scheduled_fault_start(struct leapraid_adapter *adapter)
adapter->reset_desc.fault_reset_wq_name);
if (!adapter->reset_desc.fault_reset_wq) {
dev_err(&adapter->pdev->dev,
- "create single thread workqueue failed!\n");
+ "Create single thread workqueue failed!\n");
return;
}
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
if (adapter->reset_desc.fault_reset_wq)
- queue_delayed_work(adapter->reset_desc.fault_reset_wq,
- &adapter->reset_desc.fault_reset_work,
+ queue_delayed_work(
+ adapter->reset_desc.fault_reset_wq,
+ &adapter->reset_desc.fault_reset_work,
msecs_to_jiffies(LEAPRAID_FAULT_POLLING_INTERVAL));
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
}
@@ -2471,17 +2972,24 @@ static bool leapraid_ready_for_scsi_io(struct leapraid_adapter *adapter,
u16 hdl)
{
if (adapter->access_ctrl.pcie_recovering ||
- adapter->access_ctrl.shost_recovering)
- return false;
-
- if (leapraid_check_adapter_is_op(adapter))
+ 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 (hdl == LEAPRAID_INVALID_DEV_HANDLE)
+ if (leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
+ __func__))
return false;
- if (test_bit(hdl, (unsigned long *)adapter->dev_topo.dev_removing))
+ if (hdl == LEAPRAID_INVALID_DEV_HANDLE) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Device handle is invalid\n", __func__);
return false;
+ }
return true;
}
@@ -2490,13 +2998,13 @@ 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 = 0;
- u8 sdev_flg = 0;
+ dma_addr_t dma_addr;
bool issue_reset = false;
- int rc = 0;
+ int rc;
if (WARN_ON(!adapter->driver_cmds.internal_scmd))
return -EINVAL;
@@ -2507,23 +3015,28 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter,
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;
+ goto out_cleanup;
}
adapter->driver_cmds.driver_scsiio_cmd.status = LEAPRAID_CMD_PENDING;
- __shost_for_each_device(sdev, adapter->shost) {
+ 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) {
- sdev_flg = 1;
+ target_sdev = sdev;
break;
}
}
- if (!sdev_flg) {
+ if (!target_sdev) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Device not found\n", __func__);
rc = -ENXIO;
- goto out;
+ goto out_cleanup;
}
if (cmd_desc->data_length) {
@@ -2532,7 +3045,7 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter,
&dma_addr, GFP_ATOMIC);
if (!dma_buffer) {
rc = -ENOMEM;
- goto out;
+ goto out_cleanup;
}
if (cmd_desc->dir == DMA_TO_DEVICE)
memcpy(dma_buffer, cmd_desc->data_buffer,
@@ -2540,7 +3053,7 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter,
}
scmd = adapter->driver_cmds.internal_scmd;
- scmd->device = sdev;
+ 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;
@@ -2553,11 +3066,14 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter,
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;
+ goto out_cleanup;
}
- wait_for_completion_timeout(&adapter->driver_cmds.driver_scsiio_cmd.done,
+ wait_for_completion_timeout(&adapter->driver_cmds
+ .driver_scsiio_cmd.done,
cmd_desc->time_out * HZ);
if (!(adapter->driver_cmds.driver_scsiio_cmd.status &
@@ -2579,15 +3095,22 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter,
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_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:
+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);
+ 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;
@@ -2597,7 +3120,8 @@ static int leapraid_dispatch_logsense(struct leapraid_adapter *adapter,
u16 hdl, u32 lun)
{
struct leapraid_scsi_cmd_desc *desc;
- int rc = 0;
+ char *buf;
+ int rc;
desc = kzalloc(sizeof(*desc), GFP_KERNEL);
if (!desc)
@@ -2611,7 +3135,7 @@ static int leapraid_dispatch_logsense(struct leapraid_adapter *adapter,
desc->cdb[0] = LOG_SENSE;
desc->cdb[2] = LEAPRAID_LOGSENSE_CDB_CODE;
desc->cdb[8] = desc->data_length;
- desc->raid_member = false;
+ desc->raid_member = 0;
desc->time_out = LEAPRAID_LOGSENSE_TIMEOUT;
desc->data_buffer = kzalloc(desc->data_length, GFP_KERNEL);
@@ -2621,11 +3145,10 @@ static int leapraid_dispatch_logsense(struct leapraid_adapter *adapter,
}
rc = leapraid_dispatch_scsi_io(adapter, desc);
- if (!rc) {
- if (((char *)desc->data_buffer)[8] ==
- LEAPRAID_LOGSENSE_SMART_CODE)
- leapraid_smart_fault_detect(adapter, hdl);
- }
+ buf = desc->data_buffer;
+
+ if (!rc && buf[8] == LEAPRAID_LOGSENSE_SMART_CODE)
+ leapraid_smart_fault_detect(adapter, hdl);
kfree(desc->data_buffer);
kfree(desc);
@@ -2637,31 +3160,32 @@ 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 = NULL;
+ struct leapraid_sas_dev *sas_dev;
if (!sdev_priv || !sdev_priv->starget_priv->card_port)
- goto out;
+ return false;
- sas_dev = leapraid_get_sas_dev_by_addr(adapter,
- sdev_priv->starget_priv->sas_address,
- sdev_priv->starget_priv->card_port);
+ 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;
+ goto out_fail;
if (reset_flg)
- sas_dev->led_on = false;
+ sas_dev->led_on = 0;
else if (sas_dev->led_on)
- goto out;
+ goto out_fail;
- if ((sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER) ||
- (sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME) ||
+ 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;
+ goto out_fail;
leapraid_sdev_put(sas_dev);
return true;
-out:
+out_fail:
if (sas_dev)
leapraid_sdev_put(sas_dev);
return false;
@@ -2674,16 +3198,21 @@ static void leapraid_sata_smart_poll_work(struct work_struct *work)
smart_poll_desc.smart_poll_work.work);
struct scsi_device *sdev;
struct leapraid_sdev_priv *sdev_priv;
- static u32 reset_cnt;
bool reset_flg = false;
- if (leapraid_check_adapter_is_op(adapter))
- goto out;
+ 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;
- reset_flg = (reset_cnt < adapter->reset_desc.reset_cnt);
- reset_cnt = adapter->reset_desc.reset_cnt;
+ adapter->reset_desc.last_reset_cnt = adapter->reset_desc.reset_cnt;
- __shost_for_each_device(sdev, adapter->shost) {
+ 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,
@@ -2691,11 +3220,12 @@ static void leapraid_sata_smart_poll_work(struct work_struct *work)
sdev_priv->lun);
}
-out:
+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));
+ 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)
@@ -2724,20 +3254,118 @@ void leapraid_smart_polling_start(struct leapraid_adapter *adapter)
void leapraid_smart_polling_stop(struct leapraid_adapter *adapter)
{
struct workqueue_struct *wq;
+ struct leapraid_smart_poll_desc *desc;
- if (!adapter->smart_poll_desc.smart_poll_wq)
+ desc = &adapter->smart_poll_desc;
+ if (!desc->smart_poll_wq)
return;
- wq = adapter->smart_poll_desc.smart_poll_wq;
- adapter->smart_poll_desc.smart_poll_wq = NULL;
+ wq = desc->smart_poll_wq;
+ desc->smart_poll_wq = NULL;
if (wq) {
- if (!cancel_delayed_work_sync(&adapter->smart_poll_desc.smart_poll_work))
+ 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;
+ struct leapraid_adapter *adapter;
+ struct workqueue_struct *wq;
+ struct Scsi_Host *shost;
+ struct pci_dev *pdev;
+ unsigned long flags;
+
+ desc = container_of(work, struct leapraid_overheat_desc,
+ fault_overheat_work);
+ adapter = container_of(desc, struct leapraid_adapter, overheat_desc);
+ pdev = adapter->pdev;
+ shost = pci_get_drvdata(pdev);
+
+ if (!shost) {
+ dev_err(&pdev->dev,
+ "Overheat processing failed: invalid host/adapter\n");
+ atomic_set(&adapter->overheat_desc.thermal_alert, 0);
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
+ return;
+ }
+
+ if (adapter->access_ctrl.host_removing) {
+ atomic_set(&adapter->overheat_desc.thermal_alert, 0);
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
+ return;
+ }
+
+ adapter->access_ctrl.host_removing = 1;
+ adapter->access_ctrl.shost_recover_async = 0;
+ 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);
+
+ leapraid_clean_active_cmds(adapter);
+ spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
+ wq = adapter->fw_evt_s.fw_evt_thread;
+ adapter->fw_evt_s.fw_evt_thread = NULL;
+ spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
+ if (wq)
+ destroy_workqueue(wq);
+
+ sas_remove_host(shost);
+ leapraid_cleanup_lists(adapter);
+ atomic_set(&adapter->overheat_desc.thermal_alert, 0);
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
+ dev_err(&pdev->dev, "%s: Suspend adapter due to overheat\n", __func__);
+}
+
+static void leapraid_overheat_init(struct leapraid_adapter *adapter)
+{
+ if (adapter->overheat_desc.fault_overheat_wq)
+ return;
+
+ atomic_set(&adapter->overheat_desc.thermal_alert, 0);
+ snprintf(adapter->overheat_desc.fault_overheat_wq_name,
+ sizeof(adapter->overheat_desc.fault_overheat_wq_name),
+ "driver_%s%u_overheat",
+ LEAPRAID_DRIVER_NAME,
+ adapter->adapter_attr.id);
+ adapter->overheat_desc.fault_overheat_wq =
+ create_singlethread_workqueue(
+ adapter->overheat_desc.fault_overheat_wq_name);
+ if (!adapter->overheat_desc.fault_overheat_wq) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to create overheat workqueue\n");
+ return;
+ }
+
+ INIT_WORK(&adapter->overheat_desc.fault_overheat_work,
+ leapraid_overheat_work);
+}
+
+void leapraid_overheat_cleanup(struct leapraid_adapter *adapter)
+{
+ struct workqueue_struct *wq;
+
+ wq = xchg(&adapter->overheat_desc.fault_overheat_wq, NULL);
+ if (!wq)
+ return;
+
+ cancel_work_sync(&adapter->overheat_desc.fault_overheat_work);
+ destroy_workqueue(wq);
+}
+
static void leapraid_fw_work(struct leapraid_adapter *adapter,
struct leapraid_fw_evt_work *fw_evt);
@@ -2822,7 +3450,6 @@ static struct leapraid_fw_evt_work *leapraid_next_fw_evt(
fw_evt = list_first_entry(&adapter->fw_evt_s.fw_evt_list,
struct leapraid_fw_evt_work, list);
list_del_init(&fw_evt->list);
- leapraid_fw_evt_put(fw_evt);
}
spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
return fw_evt;
@@ -2831,56 +3458,65 @@ static struct leapraid_fw_evt_work *leapraid_next_fw_evt(
void leapraid_clean_active_fw_evt(struct leapraid_adapter *adapter)
{
struct leapraid_fw_evt_work *fw_evt;
- bool rc = false;
+ unsigned long flags;
+ bool in_fw_evt_context;
+ bool rc;
if ((list_empty(&adapter->fw_evt_s.fw_evt_list) &&
!adapter->fw_evt_s.cur_evt) || !adapter->fw_evt_s.fw_evt_thread)
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;
- while ((fw_evt = leapraid_next_fw_evt(adapter)) ||
- (fw_evt = adapter->fw_evt_s.cur_evt)) {
- if (fw_evt == adapter->fw_evt_s.cur_evt &&
- adapter->fw_evt_s.cur_evt->evt_type !=
- LEAPRAID_EVT_REMOVE_DEAD_DEV) {
- adapter->fw_evt_s.cur_evt = NULL;
- continue;
- }
-
+ while ((fw_evt = leapraid_next_fw_evt(adapter))) {
rc = cancel_work_sync(&fw_evt->work);
-
if (rc)
leapraid_fw_evt_put(fw_evt);
+ leapraid_fw_evt_put(fw_evt);
}
+
+ spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
+ fw_evt = adapter->fw_evt_s.cur_evt;
+ if (fw_evt) {
+ in_fw_evt_context = adapter->fw_evt_s.cur_evt_task == current;
+ leapraid_fw_evt_get(fw_evt);
+ }
+ spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
+ if (fw_evt) {
+ if (!in_fw_evt_context)
+ cancel_work_sync(&fw_evt->work);
+ leapraid_fw_evt_put(fw_evt);
+ }
+
adapter->fw_evt_s.fw_evt_cleanup = 0;
}
static void leapraid_internal_dev_ublk(struct scsi_device *sdev,
struct leapraid_sdev_priv *sdev_priv)
{
- int rc = 0;
+ int rc;
sdev_printk(KERN_WARNING, sdev,
- "hdl 0x%04x: now internal unblkg dev\n",
+ "hdl 0x%04x: Now internal unblkg dev\n",
sdev_priv->starget_priv->hdl);
- sdev_priv->block = false;
+ sdev_priv->block = 0;
rc = scsi_internal_device_unblock_nowait(sdev, SDEV_RUNNING);
if (rc == -EINVAL) {
sdev_printk(KERN_WARNING, sdev,
"hdl 0x%04x: unblkg failed, rc=%d\n",
sdev_priv->starget_priv->hdl, rc);
- sdev_priv->block = true;
+ sdev_priv->block = 1;
rc = scsi_internal_device_block_nowait(sdev);
if (rc)
sdev_printk(KERN_WARNING, sdev,
- "hdl 0x%04x: blkg failed: earlier unblkg err, rc=%d\n",
+ "hdl 0x%04x: Earlier ublkg err, rc=%d\n",
sdev_priv->starget_priv->hdl, rc);
- sdev_priv->block = false;
+ sdev_priv->block = 0;
rc = scsi_internal_device_unblock_nowait(sdev, SDEV_RUNNING);
if (rc)
sdev_printk(KERN_WARNING, sdev,
@@ -2889,38 +3525,6 @@ static void leapraid_internal_dev_ublk(struct scsi_device *sdev,
}
}
-static void leapraid_internal_ublk_io_dev_to_running(struct scsi_device *sdev)
-{
- struct leapraid_sdev_priv *sdev_priv;
-
- sdev_priv = sdev->hostdata;
- sdev_priv->block = false;
- scsi_internal_device_unblock_nowait(sdev, SDEV_RUNNING);
- sdev_printk(KERN_WARNING, sdev, "%s: ublk hdl 0x%04x\n",
- __func__, sdev_priv->starget_priv->hdl);
-}
-
-static void leapraid_ublk_io_dev_to_running(
- struct leapraid_adapter *adapter, u64 sas_addr,
- struct leapraid_card_port *card_port)
-{
- struct leapraid_sdev_priv *sdev_priv;
- struct scsi_device *sdev;
-
- shost_for_each_device(sdev, adapter->shost) {
- sdev_priv = sdev->hostdata;
- if (!sdev_priv)
- continue;
-
- if (sdev_priv->starget_priv->sas_address != sas_addr ||
- sdev_priv->starget_priv->card_port != card_port)
- continue;
-
- if (sdev_priv->block)
- leapraid_internal_ublk_io_dev_to_running(sdev);
- }
-}
-
static void leapraid_ublk_io_dev(struct leapraid_adapter *adapter,
u64 sas_addr,
struct leapraid_card_port *card_port)
@@ -2972,15 +3576,15 @@ static void leapraid_ublk_io_all_dev(struct leapraid_adapter *adapter)
}
}
-static void __maybe_unused leapraid_internal_dev_blk(
+static void leapraid_internal_dev_blk(
struct scsi_device *sdev,
struct leapraid_sdev_priv *sdev_priv)
{
- int rc = 0;
+ int rc;
- sdev_printk(KERN_INFO, sdev, "internal blkg hdl 0x%04x\n",
+ sdev_printk(KERN_INFO, sdev, "Internal blkg hdl 0x%04x\n",
sdev_priv->starget_priv->hdl);
- sdev_priv->block = true;
+ sdev_priv->block = 1;
rc = scsi_internal_device_block_nowait(sdev);
if (rc == -EINVAL)
sdev_printk(KERN_WARNING, sdev,
@@ -2988,42 +3592,6 @@ static void __maybe_unused leapraid_internal_dev_blk(
rc, sdev_priv->starget_priv->hdl);
}
-static void __maybe_unused leapraid_blkio_dev(struct leapraid_adapter *adapter,
- u16 hdl)
-{
- struct leapraid_sdev_priv *sdev_priv;
- struct leapraid_sas_dev *sas_dev;
- struct scsi_device *sdev;
-
- sas_dev = leapraid_get_sas_dev_by_hdl(adapter, hdl);
- shost_for_each_device(sdev, adapter->shost) {
- sdev_priv = sdev->hostdata;
- if (!sdev_priv)
- continue;
-
- if (sdev_priv->starget_priv->hdl != hdl)
- continue;
-
- if (sdev_priv->block)
- continue;
-
- if (sas_dev && sas_dev->pend_sas_rphy_add)
- continue;
-
- if (sdev_priv->sep) {
- sdev_printk(KERN_INFO, sdev,
- "sep hdl 0x%04x skip blkg\n",
- sdev_priv->starget_priv->hdl);
- continue;
- }
-
- leapraid_internal_dev_blk(sdev, sdev_priv);
- }
-
- if (sas_dev)
- leapraid_sdev_put(sas_dev);
-}
-
static void leapraid_imm_blkio_to_end_dev(struct leapraid_adapter *adapter,
struct leapraid_sas_port *sas_port)
{
@@ -3055,8 +3623,7 @@ static void leapraid_imm_blkio_to_end_dev(struct leapraid_adapter *adapter,
if (sdev_priv->sep) {
sdev_printk(KERN_INFO, sdev,
- "%s skip dev blk for sep hdl 0x%04x\n",
- __func__,
+ "skip dev blk: sep hdl 0x%04x\n",
sdev_priv->starget_priv->hdl);
continue;
}
@@ -3077,10 +3644,8 @@ static void leapraid_imm_blkio_set_end_dev_blk_hdls(
list_for_each_entry(sas_port,
&topo_node_exp->sas_port_list, port_list) {
- if (sas_port->remote_identify.device_type ==
- SAS_END_DEVICE) {
+ if (sas_port->remote_identify.device_type == SAS_END_DEVICE)
leapraid_imm_blkio_to_end_dev(adapter, sas_port);
- }
}
}
@@ -3102,7 +3667,7 @@ static void leapraid_imm_blkio_to_sib_exp(
sas_port->remote_identify.device_type ==
SAS_FANOUT_EXPANDER_DEVICE) {
topo_node_exp_sib =
- leapraid_exp_find_by_sas_address(
+ leapraid_exp_find_by_sas_address(
adapter,
sas_port->remote_identify.sas_address,
sas_port->card_port);
@@ -3141,17 +3706,15 @@ static void leapraid_report_sdev_directly(struct leapraid_adapter *adapter,
if (!sas_dev->starget) {
if (!adapter->scan_dev_desc.driver_loading) {
- leapraid_transport_port_remove(adapter,
- sas_dev->sas_addr,
- sas_dev->parent_sas_addr,
- sas_dev->card_port);
+ leapraid_transport_port_remove(
+ adapter,
+ sas_dev->sas_addr,
+ sas_dev->parent_sas_addr,
+ sas_dev->card_port);
leapraid_sas_dev_remove(adapter, sas_dev);
}
return;
}
-
- clear_bit(sas_dev->hdl,
- (unsigned long *)adapter->dev_topo.pending_dev_add);
}
static struct leapraid_sas_dev *leapraid_init_sas_dev(
@@ -3162,6 +3725,7 @@ static struct leapraid_sas_dev *leapraid_init_sas_dev(
{
struct leapraid_sas_dev *sas_dev;
struct leapraid_enc_node *enc_dev;
+ unsigned long flags;
sas_dev = kzalloc(sizeof(*sas_dev), GFP_KERNEL);
if (!sas_dev)
@@ -3176,28 +3740,32 @@ static struct leapraid_sas_dev *leapraid_init_sas_dev(
sas_dev->phy = sas_dev_pg0->phy_num;
sas_dev->enc_hdl = le16_to_cpu(sas_dev_pg0->enc_hdl);
sas_dev->dev_name = le64_to_cpu(sas_dev_pg0->dev_name);
- sas_dev->port_type = sas_dev_pg0->max_port_connections;
+ 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;
- memcpy(sas_dev->connector_name, sas_dev_pg0->connector_name, 4);
- sas_dev->connector_name[4] = '\0';
+ memcpy(sas_dev->connector_name,
+ sas_dev_pg0->connector_name,
+ LEAPRAID_SAS_DEV_P0_CON_NAME_LEN);
+ sas_dev->connector_name[LEAPRAID_SAS_DEV_P0_CON_NAME_LEN] =
+ '\0';
} else {
sas_dev->enc_level = 0;
sas_dev->connector_name[0] = '\0';
}
- if (le16_to_cpu(sas_dev_pg0->enc_hdl)) {
- enc_dev = leapraid_enc_find_by_hdl(adapter,
- le16_to_cpu(sas_dev_pg0->enc_hdl));
- sas_dev->enc_lid = enc_dev ?
- le64_to_cpu(enc_dev->pg0.enc_lid) : 0;
+ if (sas_dev->enc_hdl) {
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags);
+ enc_dev = leapraid_enc_find_by_hdl(adapter, sas_dev->enc_hdl);
+ if (enc_dev)
+ sas_dev->enc_lid = le64_to_cpu(enc_dev->pg0.enc_lid);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
}
dev_info(&adapter->pdev->dev,
- "add dev: hdl=0x%0x, sas addr=0x%016llx, port_type=0x%0x\n",
- hdl, sas_dev->sas_addr, sas_dev->port_type);
+ "add dev: hdl=0x%x, SAS addr=0x%016llx, port connect=0x%x\n",
+ hdl, sas_dev->sas_addr, sas_dev->port_connection);
return sas_dev;
}
@@ -3217,15 +3785,14 @@ static void leapraid_add_dev(struct leapraid_adapter *adapter, u16 hdl)
cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
cfgp2.handle = hdl;
- if ((leapraid_op_config_page(adapter, &sas_dev_pg0,
- cfgp1, cfgp2, GET_SAS_DEVICE_PG0)))
+ if (leapraid_op_config_page(adapter, &sas_dev_pg0,
+ cfgp1, cfgp2, GET_SAS_DEVICE_PG0))
return;
dev_info = le32_to_cpu(sas_dev_pg0.dev_info);
if (!(leapraid_is_end_dev(dev_info)))
return;
- set_bit(hdl, (unsigned long *)adapter->dev_topo.pending_dev_add);
sas_addr = le64_to_cpu(sas_dev_pg0.sas_address);
if (!(le16_to_cpu(sas_dev_pg0.flg) &
LEAPRAID_SAS_DEV_P0_FLG_DEV_PRESENT))
@@ -3238,8 +3805,6 @@ static void leapraid_add_dev(struct leapraid_adapter *adapter, u16 hdl)
sas_dev = leapraid_get_sas_dev_by_addr(adapter, sas_addr, card_port);
if (sas_dev) {
- clear_bit(hdl,
- (unsigned long *)adapter->dev_topo.pending_dev_add);
leapraid_sdev_put(sas_dev);
return;
}
@@ -3254,6 +3819,7 @@ static void leapraid_add_dev(struct leapraid_adapter *adapter, u16 hdl)
dev_info);
if (!sas_dev)
return;
+
if (adapter->scan_dev_desc.wait_scan_dev_done) {
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
leapraid_sdev_get(sas_dev);
@@ -3268,6 +3834,7 @@ static void leapraid_add_dev(struct leapraid_adapter *adapter, u16 hdl)
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
leapraid_report_sdev_directly(adapter, sas_dev);
}
+ leapraid_sdev_put(sas_dev);
}
static void leapraid_remove_device(struct leapraid_adapter *adapter,
@@ -3275,14 +3842,15 @@ static void leapraid_remove_device(struct leapraid_adapter *adapter,
{
struct leapraid_starget_priv *starget_priv;
+ leapraid_clear_cached_boot_dev(adapter, sas_dev, 0);
if (sas_dev->led_on) {
leapraid_set_led(adapter, sas_dev, false);
- sas_dev->led_on = false;
+ sas_dev->led_on = 0;
}
if (sas_dev->starget && sas_dev->starget->hostdata) {
starget_priv = sas_dev->starget->hostdata;
- starget_priv->deleted = true;
+ starget_priv->deleted = 1;
leapraid_ublk_io_dev(adapter,
sas_dev->sas_addr, sas_dev->card_port);
starget_priv->hdl = LEAPRAID_INVALID_DEV_HANDLE;
@@ -3294,12 +3862,13 @@ static void leapraid_remove_device(struct leapraid_adapter *adapter,
sas_dev->card_port);
dev_info(&adapter->pdev->dev,
- "remove dev: hdl=0x%04x, sas addr=0x%016llx\n",
+ "remove dev: hdl=0x%04x, SAS addr=0x%016llx\n",
sas_dev->hdl, (unsigned long long)sas_dev->sas_addr);
}
-static struct leapraid_vphy *leapraid_alloc_vphy(struct leapraid_adapter *adapter,
- u8 port_id, u8 phy_num)
+static struct leapraid_vphy *leapraid_alloc_vphy(
+ struct leapraid_adapter *adapter,
+ u8 port_id, u8 phy_num)
{
struct leapraid_card_port *port;
struct leapraid_vphy *vphy;
@@ -3311,7 +3880,6 @@ static struct leapraid_vphy *leapraid_alloc_vphy(struct leapraid_adapter *adapte
vphy = leapraid_get_vphy_by_phy(port, phy_num);
if (vphy)
return vphy;
-
vphy = kzalloc(sizeof(*vphy), GFP_KERNEL);
if (!vphy)
return NULL;
@@ -3325,46 +3893,157 @@ static struct leapraid_vphy *leapraid_alloc_vphy(struct leapraid_adapter *adapte
return vphy;
}
-static int leapraid_add_port_to_card_port_list(struct leapraid_adapter *adapter,
- u8 port_id, bool refresh)
+static int leapraid_add_port_to_card_port_list(
+ struct leapraid_adapter *adapter,
+ u8 port_id, bool refresh)
{
struct leapraid_card_port *card_port;
card_port = leapraid_get_port_by_id(adapter, port_id, false);
if (card_port)
return 0;
-
card_port = kzalloc(sizeof(*card_port), GFP_KERNEL);
if (!card_port)
return -ENOMEM;
card_port->port_id = port_id;
- dev_info(&adapter->pdev->dev,
- "port: %d is added to card_port list\n",
- card_port->port_id);
+ dev_dbg(&adapter->pdev->dev,
+ "port: %d is added to card_port list\n",
+ card_port->port_id);
- if (refresh)
- if (adapter->access_ctrl.shost_recovering)
- card_port->flg = LEAPRAID_CARD_PORT_FLG_NEW;
+ if (refresh && adapter->access_ctrl.shost_recovering)
+ card_port->flg = LEAPRAID_CARD_PORT_FLG_NEW;
list_add_tail(&card_port->list, &adapter->dev_topo.card_port_list);
return 0;
}
+static int leapraid_add_card_phy(struct leapraid_adapter *adapter,
+ struct leapraid_sas_io_unit_p0 *iou,
+ int i)
+{
+ struct leapraid_sas_phy_p0 phy_pg0;
+ union cfg_param_1 cfgp1 = {0};
+ union cfg_param_2 cfgp2 = {0};
+ struct leapraid_topo_node *card = &adapter->dev_topo.card;
+ u8 port_id;
+
+ cfgp1.phy_number = i;
+
+ if (leapraid_op_config_page(adapter, &phy_pg0,
+ cfgp1, cfgp2, GET_PHY_PG0))
+ return -EINVAL;
+
+ port_id = iou->phy_info[i].port;
+
+ if (leapraid_add_port_to_card_port_list(adapter, port_id, false))
+ return -EINVAL;
+
+ if ((le32_to_cpu(phy_pg0.phy_info) &
+ LEAPRAID_SAS_PHYINFO_VPHY) &&
+ ((phy_pg0.neg_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) >=
+ LEAPRAID_SAS_NEG_LINK_RATE_1_5)) {
+ if (!leapraid_alloc_vphy(adapter, port_id, i))
+ return -ENOMEM;
+
+ card->card_phy[i].vphy = 1;
+ }
+
+ card->card_phy[i].hdl = card->hdl;
+ card->card_phy[i].phy_id = i;
+ card->card_phy[i].card_port =
+ leapraid_get_port_by_id(adapter, port_id, false);
+
+ leapraid_transport_add_card_phy(adapter,
+ &card->card_phy[i],
+ &phy_pg0,
+ card->parent_dev);
+
+ return 0;
+}
+
+static int leapraid_refresh_card_phy(struct leapraid_adapter *adapter,
+ struct leapraid_sas_io_unit_p0 *iou,
+ int i)
+{
+ struct leapraid_topo_node *card = &adapter->dev_topo.card;
+ struct leapraid_sas_phy_p0 phy_pg0;
+ union cfg_param_1 cfgp1 = {0};
+ union cfg_param_2 cfgp2 = {0};
+ u16 attached_hdl;
+ u32 dev_info;
+ u8 link_rate;
+ u8 port_id;
+
+ link_rate = iou->phy_info[i].neg_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT;
+ port_id = iou->phy_info[i].port;
+ if (leapraid_add_port_to_card_port_list(adapter, port_id, true))
+ return -EINVAL;
+
+ dev_info = le32_to_cpu(iou->phy_info[i].controller_phy_dev_info);
+ if (dev_info & LEAPRAID_DEVTYP_SEP &&
+ link_rate >= LEAPRAID_SAS_NEG_LINK_RATE_1_5) {
+ cfgp1.phy_number = i;
+
+ if (leapraid_op_config_page(adapter, &phy_pg0,
+ cfgp1, cfgp2, GET_PHY_PG0))
+ 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;
+ }
+
+ card->card_phy[i].hdl = card->hdl;
+
+ attached_hdl = le16_to_cpu(iou->phy_info[i].attached_dev_hdl);
+ if (attached_hdl && link_rate < LEAPRAID_SAS_NEG_LINK_RATE_1_5)
+ link_rate = LEAPRAID_SAS_NEG_LINK_RATE_1_5;
+
+ card->card_phy[i].card_port =
+ leapraid_get_port_by_id(adapter, port_id, false);
+
+ if (!card->card_phy[i].phy) {
+ cfgp1.phy_number = i;
+ if (leapraid_op_config_page(adapter, &phy_pg0,
+ cfgp1, cfgp2, GET_PHY_PG0))
+ return 0;
+
+ card->card_phy[i].phy_id = i;
+
+ leapraid_transport_add_card_phy(adapter,
+ &card->card_phy[i],
+ &phy_pg0,
+ card->parent_dev);
+ return 0;
+ }
+
+ leapraid_transport_update_links(adapter,
+ card->sas_address,
+ attached_hdl,
+ i,
+ link_rate,
+ card->card_phy[i].card_port);
+
+ return 0;
+}
+
static void leapraid_sas_host_add(struct leapraid_adapter *adapter,
bool refresh)
{
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- struct leapraid_sas_phy_p0 phy_pg0;
struct leapraid_sas_dev_p0 sas_dev_pg0;
struct leapraid_enc_p0 enc_pg0;
struct leapraid_sas_io_unit_p0 *sas_iou_pg0;
u16 sas_iou_pg0_sz;
- u16 attached_hdl;
u8 phys_num;
- u8 port_id;
- u8 link_rate;
int i;
+ int rc;
if (!refresh) {
if (leapraid_get_adapter_phys(adapter, &phys_num) || !phys_num)
@@ -3379,128 +4058,46 @@ static void leapraid_sas_host_add(struct leapraid_adapter *adapter,
adapter->dev_topo.card.phys_num = phys_num;
}
- sas_iou_pg0_sz = offsetof(struct leapraid_sas_io_unit_p0, phy_info) +
- (adapter->dev_topo.card.phys_num *
- sizeof(struct leapraid_sas_io_unit0_phy_info));
+ sas_iou_pg0_sz =
+ offsetof(struct leapraid_sas_io_unit_p0, phy_info) +
+ (adapter->dev_topo.card.phys_num *
+ sizeof(struct leapraid_sas_io_unit0_phy_info));
sas_iou_pg0 = kzalloc(sas_iou_pg0_sz, GFP_KERNEL);
if (!sas_iou_pg0)
- goto out;
+ return;
if (leapraid_get_sas_io_unit_page0(adapter,
sas_iou_pg0,
sas_iou_pg0_sz))
- goto out;
+ goto out_free;
adapter->dev_topo.card.parent_dev = &adapter->shost->shost_gendev;
adapter->dev_topo.card.hdl =
le16_to_cpu(sas_iou_pg0->phy_info[0].controller_dev_hdl);
for (i = 0; i < adapter->dev_topo.card.phys_num; i++) {
- if (!refresh) { /* add */
- cfgp1.phy_number = i;
- if (leapraid_op_config_page(adapter, &phy_pg0, cfgp1,
- cfgp2, GET_PHY_PG0))
- goto out;
-
- port_id = sas_iou_pg0->phy_info[i].port;
- if (leapraid_add_port_to_card_port_list(adapter,
- port_id,
- false))
- goto out;
-
- if ((le32_to_cpu(phy_pg0.phy_info) &
- LEAPRAID_SAS_PHYINFO_VPHY) &&
- (phy_pg0.neg_link_rate >> 4) >=
- LEAPRAID_SAS_NEG_LINK_RATE_1_5) {
- if (!leapraid_alloc_vphy(adapter, port_id, i))
- goto out;
- adapter->dev_topo.card.card_phy[i].vphy = true;
- }
-
- adapter->dev_topo.card.card_phy[i].hdl =
- adapter->dev_topo.card.hdl;
- adapter->dev_topo.card.card_phy[i].phy_id = i;
- adapter->dev_topo.card.card_phy[i].card_port =
- leapraid_get_port_by_id(adapter,
- port_id,
- false);
- leapraid_transport_add_card_phy(
- adapter,
- &adapter->dev_topo.card.card_phy[i],
- &phy_pg0, adapter->dev_topo.card.parent_dev);
- } else { /* refresh */
- link_rate = sas_iou_pg0->phy_info[i].neg_link_rate >> 4;
- port_id = sas_iou_pg0->phy_info[i].port;
- if (leapraid_add_port_to_card_port_list(adapter,
- port_id,
- true))
- goto out;
-
- if (le32_to_cpu(sas_iou_pg0->phy_info[i]
- .controller_phy_dev_info) &
- LEAPRAID_DEVTYP_SEP &&
- link_rate >= LEAPRAID_SAS_NEG_LINK_RATE_1_5) {
- cfgp1.phy_number = i;
- if ((leapraid_op_config_page(adapter, &phy_pg0,
- cfgp1, cfgp2,
- GET_PHY_PG0)))
- continue;
-
- if ((le32_to_cpu(phy_pg0.phy_info) &
- LEAPRAID_SAS_PHYINFO_VPHY)) {
- if (!leapraid_alloc_vphy(adapter,
- port_id,
- i))
- goto out;
- adapter->dev_topo.card.card_phy[i].vphy = true;
- }
- }
-
- adapter->dev_topo.card.card_phy[i].hdl =
- adapter->dev_topo.card.hdl;
- attached_hdl =
- le16_to_cpu(sas_iou_pg0->phy_info[i].attached_dev_hdl);
- if (attached_hdl && link_rate < LEAPRAID_SAS_NEG_LINK_RATE_1_5)
- link_rate = LEAPRAID_SAS_NEG_LINK_RATE_1_5;
-
- adapter->dev_topo.card.card_phy[i].card_port =
- leapraid_get_port_by_id(adapter,
- port_id,
- false);
- if (!adapter->dev_topo.card.card_phy[i].phy) {
- cfgp1.phy_number = i;
- if ((leapraid_op_config_page(adapter, &phy_pg0,
- cfgp1, cfgp2,
- GET_PHY_PG0)))
- continue;
-
- adapter->dev_topo.card.card_phy[i].phy_id = i;
- leapraid_transport_add_card_phy(adapter,
- &adapter->dev_topo.card.card_phy[i],
- &phy_pg0,
- adapter->dev_topo.card.parent_dev);
- continue;
- }
-
- leapraid_transport_update_links(adapter,
- adapter->dev_topo.card.sas_address,
- attached_hdl, i, link_rate,
- adapter->dev_topo.card.card_phy[i].card_port);
- }
+ if (!refresh) /* add */
+ rc = leapraid_add_card_phy(adapter, sas_iou_pg0, i);
+ else /* refresh */
+ rc = leapraid_refresh_card_phy(adapter,
+ sas_iou_pg0,
+ i);
+ if (rc)
+ goto out_free;
}
if (!refresh) {
cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
cfgp2.handle = adapter->dev_topo.card.hdl;
- if ((leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1,
- cfgp2, GET_SAS_DEVICE_PG0)))
- goto out;
+ if (leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1,
+ cfgp2, GET_SAS_DEVICE_PG0))
+ goto out_free;
adapter->dev_topo.card.enc_hdl =
le16_to_cpu(sas_dev_pg0.enc_hdl);
adapter->dev_topo.card.sas_address =
le64_to_cpu(sas_dev_pg0.sas_address);
dev_info(&adapter->pdev->dev,
- "add host: devhdl=0x%04x, sas addr=0x%016llx, phynums=%d\n",
+ "add host: hdl=0x%04x, SAS addr=0x%016llx, phy=%d\n",
adapter->dev_topo.card.hdl,
(unsigned long long)adapter->dev_topo.card.sas_address,
adapter->dev_topo.card.phys_num);
@@ -3515,7 +4112,7 @@ static void leapraid_sas_host_add(struct leapraid_adapter *adapter,
le64_to_cpu(enc_pg0.enc_lid);
}
}
-out:
+out_free:
kfree(sas_iou_pg0);
}
@@ -3529,22 +4126,24 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter,
struct leapraid_sas_port *sas_port = NULL;
struct leapraid_enc_node *enc_dev;
struct leapraid_exp_p1 exp_pg1;
- int rc = 0;
+ int ret;
+ int rc;
unsigned long flags;
u8 port_id;
u16 parent_handle;
- u64 sas_addr_parent = 0;
+ u64 sas_addr_parent;
int i;
port_id = exp_pg0->physical_port;
parent_handle = le16_to_cpu(exp_pg0->parent_dev_hdl);
- if (leapraid_get_sas_address(adapter, parent_handle, &sas_addr_parent))
- return -1;
-
+ rc = leapraid_get_sas_address(adapter,
+ parent_handle, &sas_addr_parent);
+ if (rc)
+ return rc;
topo_node_exp = kzalloc(sizeof(*topo_node_exp), GFP_KERNEL);
if (!topo_node_exp)
- return -1;
+ return -ENOMEM;
topo_node_exp->hdl = hdl;
topo_node_exp->phys_num = exp_pg0->phy_num;
@@ -3553,17 +4152,19 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter,
topo_node_exp->card_port =
leapraid_get_port_by_id(adapter, port_id, false);
if (!topo_node_exp->card_port) {
- rc = -1;
+ rc = -EPERM;
goto out_fail;
}
dev_info(&adapter->pdev->dev,
- "add exp: sas addr=0x%016llx, hdl=0x%04x, phdl=0x%04x, phys=%d\n",
+ "add exp: saddr=0x%016llx, hdl=0x%04x, phdl=0x%04x, phy=%d\n",
(unsigned long long)topo_node_exp->sas_address,
hdl, parent_handle,
topo_node_exp->phys_num);
if (!topo_node_exp->phys_num) {
- rc = -1;
+ dev_err(&adapter->pdev->dev,
+ "%s: Invalid PHY num from exp_pg0\n", __func__);
+ rc = -EPERM;
goto out_fail;
}
@@ -3571,7 +4172,10 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter,
kcalloc(topo_node_exp->phys_num,
sizeof(struct leapraid_card_phy), GFP_KERNEL);
if (!topo_node_exp->card_phy) {
- rc = -1;
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to alloc expander phy array, count=%u\n",
+ __func__, topo_node_exp->phys_num);
+ rc = -EPERM;
goto out_fail;
}
@@ -3579,7 +4183,7 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter,
sas_port = leapraid_transport_port_add(adapter, hdl, sas_addr_parent,
topo_node_exp->card_port);
if (!sas_port) {
- rc = -1;
+ rc = -EPERM;
goto out_fail;
}
@@ -3588,31 +4192,38 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter,
for (i = 0; i < topo_node_exp->phys_num; i++) {
cfgp1->phy_number = i;
cfgp2->handle = hdl;
- if ((leapraid_op_config_page(adapter, &exp_pg1, *cfgp1, *cfgp2,
- GET_SAS_EXPANDER_PG1))) {
- rc = -1;
+ if (leapraid_op_config_page(adapter, &exp_pg1, *cfgp1, *cfgp2,
+ GET_SAS_EXPANDER_PG1)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to get exp_pg1, phy=%d\n",
+ __func__, i);
+ rc = -EPERM;
goto out_fail;
}
topo_node_exp->card_phy[i].hdl = hdl;
topo_node_exp->card_phy[i].phy_id = i;
topo_node_exp->card_phy[i].card_port =
- leapraid_get_port_by_id(adapter, port_id, false);
- if ((leapraid_transport_add_exp_phy(adapter,
- &topo_node_exp->card_phy[i],
- &exp_pg1,
- topo_node_exp->parent_dev))) {
- rc = -1;
+ leapraid_get_port_by_id(adapter, port_id, false);
+ ret = leapraid_transport_add_exp_phy(
+ adapter,
+ &topo_node_exp->card_phy[i],
+ &exp_pg1,
+ topo_node_exp->parent_dev);
+ if (ret) {
+ rc = -EPERM;
goto out_fail;
}
}
if (topo_node_exp->enc_hdl) {
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags);
enc_dev = leapraid_enc_find_by_hdl(adapter,
topo_node_exp->enc_hdl);
if (enc_dev)
topo_node_exp->enc_lid =
le64_to_cpu(enc_dev->pg0.enc_lid);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
}
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
@@ -3626,6 +4237,7 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter,
topo_node_exp->sas_address,
sas_addr_parent,
topo_node_exp->card_port);
+ kfree(topo_node_exp->card_phy);
kfree(topo_node_exp);
return rc;
}
@@ -3637,22 +4249,29 @@ static int leapraid_exp_add(struct leapraid_adapter *adapter, u16 hdl)
struct leapraid_topo_node *topo_node_exp;
struct leapraid_exp_p0 exp_pg0;
u16 parent_handle;
- u64 sas_addr, sas_addr_parent = 0;
+ u64 sas_addr, sas_addr_parent;
unsigned long flags;
u8 port_id;
- int rc = 0;
+ int rc;
- if (!hdl)
+ if (!hdl) {
+ dev_warn(&adapter->pdev->dev, "%s: Invalid hdl\n", __func__);
return -EPERM;
+ }
if (adapter->access_ctrl.shost_recovering ||
- adapter->access_ctrl.pcie_recovering)
+ adapter->access_ctrl.pcie_recovering) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed, shost_recovering=%d pcie_recovering=%d\n",
+ __func__, adapter->access_ctrl.shost_recovering,
+ adapter->access_ctrl.pcie_recovering);
return -EPERM;
+ }
cfgp1.form = LEAPRAID_SAS_EXP_CFD_PGAD_HDL;
cfgp2.handle = hdl;
- if ((leapraid_op_config_page(adapter, &exp_pg0, cfgp1, cfgp2,
- GET_SAS_EXPANDER_PG0)))
+ if (leapraid_op_config_page(adapter, &exp_pg0, cfgp1, cfgp2,
+ GET_SAS_EXPANDER_PG0))
return -EPERM;
parent_handle = le16_to_cpu(exp_pg0.parent_dev_hdl);
@@ -3663,10 +4282,14 @@ static int leapraid_exp_add(struct leapraid_adapter *adapter, u16 hdl)
if (sas_addr_parent != adapter->dev_topo.card.sas_address) {
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
topo_node_exp =
- leapraid_exp_find_by_sas_address(adapter,
+ leapraid_exp_find_by_sas_address(
+ adapter,
sas_addr_parent,
- leapraid_get_port_by_id(adapter, port_id, false));
- spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
+ leapraid_get_port_by_id(adapter,
+ port_id,
+ false));
+ spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock,
+ flags);
if (!topo_node_exp) {
rc = leapraid_exp_add(adapter, parent_handle);
if (rc != 0)
@@ -3677,7 +4300,9 @@ static int leapraid_exp_add(struct leapraid_adapter *adapter, u16 hdl)
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
sas_addr = le64_to_cpu(exp_pg0.sas_address);
topo_node_exp =
- leapraid_exp_find_by_sas_address(adapter, sas_addr,
+ leapraid_exp_find_by_sas_address(
+ adapter,
+ sas_addr,
leapraid_get_port_by_id(adapter, port_id, false));
spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
@@ -3725,7 +4350,7 @@ static void leapraid_exp_node_rm(struct leapraid_adapter *adapter,
topo_node_exp->sas_address_parent,
topo_node_exp->card_port);
dev_info(&adapter->pdev->dev,
- "removing exp: port=%d, sas addr=0x%016llx, hdl=0x%04x\n",
+ "removing exp: port=%d, SAS addr=0x%016llx, hdl=0x%04x\n",
port_id, (unsigned long long)topo_node_exp->sas_address,
topo_node_exp->hdl);
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
@@ -3757,92 +4382,6 @@ void leapraid_exp_rm(struct leapraid_adapter *adapter, u64 sas_addr,
leapraid_exp_node_rm(adapter, topo_node_exp);
}
-static void leapraid_check_device(struct leapraid_adapter *adapter,
- u64 parent_sas_address, u16 handle,
- u8 phy_number, u8 link_rate)
-{
- struct leapraid_sas_dev_p0 sas_device_pg0;
- struct leapraid_sas_dev *sas_dev = NULL;
- struct leapraid_enc_node *enclosure_dev = NULL;
- union cfg_param_1 cfgp1 = {0};
- union cfg_param_2 cfgp2 = {0};
- unsigned long flags;
- u64 sas_address;
- struct scsi_target *starget;
- struct leapraid_starget_priv *sas_target_priv_data;
- u32 device_info;
- struct leapraid_card_port *port;
-
- cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
- cfgp2.handle = handle;
- if ((leapraid_op_config_page(adapter, &sas_device_pg0, cfgp1, cfgp2,
- GET_SAS_DEVICE_PG0)))
- return;
-
- if (phy_number != sas_device_pg0.phy_num)
- return;
-
- device_info = le32_to_cpu(sas_device_pg0.dev_info);
- if (!(leapraid_is_end_dev(device_info)))
- return;
-
- spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
- sas_address = le64_to_cpu(sas_device_pg0.sas_address);
- port = leapraid_get_port_by_id(adapter, sas_device_pg0.physical_port,
- false);
- if (!port)
- goto out_unlock;
-
- sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter, sas_address,
- port);
- if (!sas_dev)
- goto out_unlock;
-
- if (unlikely(sas_dev->hdl != handle)) {
- starget = sas_dev->starget;
- sas_target_priv_data = starget->hostdata;
- starget_printk(KERN_INFO, starget,
- "hdl changed from 0x%04x to 0x%04x!\n",
- sas_dev->hdl, handle);
- sas_target_priv_data->hdl = handle;
- sas_dev->hdl = handle;
- if (le16_to_cpu(sas_device_pg0.flg) &
- LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID) {
- sas_dev->enc_level =
- sas_device_pg0.enc_level;
- memcpy(sas_dev->connector_name,
- sas_device_pg0.connector_name, 4);
- sas_dev->connector_name[4] = '\0';
- } else {
- sas_dev->enc_level = 0;
- sas_dev->connector_name[0] = '\0';
- }
- sas_dev->enc_hdl =
- le16_to_cpu(sas_device_pg0.enc_hdl);
- enclosure_dev =
- leapraid_enc_find_by_hdl(adapter, sas_dev->enc_hdl);
- if (enclosure_dev) {
- sas_dev->enc_lid =
- le64_to_cpu(enclosure_dev->pg0.enc_lid);
- }
- }
-
- if (!(le16_to_cpu(sas_device_pg0.flg) &
- LEAPRAID_SAS_DEV_P0_FLG_DEV_PRESENT))
- goto out_unlock;
-
- spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
-
- leapraid_ublk_io_dev_to_running(adapter, sas_address, port);
- goto out;
-
-out_unlock:
- spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
-out:
- if (sas_dev)
- leapraid_sdev_put(sas_dev);
-}
-
static int leapraid_internal_sas_topo_chg_evt(
struct leapraid_adapter *adapter,
struct leapraid_card_port *card_port,
@@ -3851,10 +4390,8 @@ static int leapraid_internal_sas_topo_chg_evt(
u64 sas_addr, u8 max_phys)
{
struct leapraid_evt_data_sas_topo_change_list *evt_data;
- struct leapraid_sas_dev *sas_dev;
- unsigned long flags;
u8 phy_number;
- u8 link_rate, prev_link_rate;
+ u8 link_rate;
u16 reason_code;
u16 hdl;
int i;
@@ -3876,47 +4413,15 @@ static int leapraid_internal_sas_topo_chg_evt(
LEAPRAID_EVT_SAS_TOPO_RC_MASK;
hdl = le16_to_cpu(evt_data->phy[i].attached_dev_hdl);
- if (!hdl)
+ if (!hdl ||
+ hdl > adapter->adapter_attr.features.max_dev_handle) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid device handle\n", __func__);
continue;
-
- link_rate = evt_data->phy[i].link_rate >> 4;
- prev_link_rate = evt_data->phy[i].link_rate & 0xF;
+ }
+ link_rate = evt_data->phy[i].link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT;
switch (reason_code) {
- case LEAPRAID_EVT_SAS_TOPO_RC_PHY_CHANGED:
- if (adapter->access_ctrl.shost_recovering)
- break;
-
- if (link_rate == prev_link_rate)
- break;
-
- leapraid_transport_update_links(adapter, sas_addr,
- hdl, phy_number,
- link_rate, card_port);
- if (link_rate < LEAPRAID_SAS_NEG_LINK_RATE_1_5)
- break;
-
- leapraid_check_device(adapter, sas_addr, hdl,
- phy_number, link_rate);
- spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock,
- flags);
- sas_dev =
- leapraid_hold_lock_get_sas_dev_by_hdl(
- adapter, hdl);
- spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock,
- flags);
- if (sas_dev) {
- leapraid_sdev_put(sas_dev);
- break;
- }
- if (!test_bit(hdl, (unsigned long *)adapter->dev_topo.pending_dev_add))
- break;
-
- evt_data->phy[i].phy_status &=
- LEAPRAID_EVT_SAS_TOPO_RC_CLEAR_MASK;
- evt_data->phy[i].phy_status |=
- LEAPRAID_EVT_SAS_TOPO_RC_TARG_ADDED;
- fallthrough;
-
case LEAPRAID_EVT_SAS_TOPO_RC_TARG_ADDED:
if (adapter->access_ctrl.shost_recovering)
break;
@@ -3957,7 +4462,7 @@ static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter,
return 0;
evt_data = fw_evt->evt_data;
- leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num);
+ leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num > 0);
if (fw_evt->ignore)
return 0;
@@ -3966,9 +4471,9 @@ static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter,
card_port = leapraid_get_port_by_id(adapter,
evt_data->physical_port,
false);
- if (evt_data->exp_status == LEAPRAID_EVT_SAS_TOPO_ES_ADDED)
- if (leapraid_exp_add(adapter, phdl) != 0)
- return 0;
+ if (evt_data->exp_status == LEAPRAID_EVT_SAS_TOPO_ES_ADDED &&
+ leapraid_exp_add(adapter, phdl) != 0)
+ return 0;
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
topo_node_exp = leapraid_exp_find_by_hdl(adapter, phdl);
@@ -3995,12 +4500,13 @@ static void leapraid_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
{
sdev->no_uld_attach = no_uld_attach ? 1 : 0;
sdev_printk(KERN_INFO, sdev,
- "%s raid component to upper layer\n",
+ "%s RAID component to upper layer\n",
sdev->no_uld_attach ? "hide" : "expose");
WARN_ON(scsi_device_reprobe(sdev));
}
-static void leapraid_sas_pd_add(struct leapraid_adapter *adapter,
+static void leapraid_sas_pd_add(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_ir_change *evt_data)
{
union cfg_param_1 cfgp1 = {0};
@@ -4012,20 +4518,26 @@ static void leapraid_sas_pd_add(struct leapraid_adapter *adapter,
u16 hdl;
hdl = le16_to_cpu(evt_data->phys_disk_dev_hdl);
- set_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls);
+ if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid device handle\n", __func__);
+ return;
+ }
+
+ set_bit(hdl, adapter->dev_topo.pd_hdls);
sas_dev = leapraid_get_sas_dev_by_hdl(adapter, hdl);
if (sas_dev) {
leapraid_sdev_put(sas_dev);
dev_warn(&adapter->pdev->dev,
- "dev handle 0x%x already exists\n", hdl);
+ "Dev handle 0x%x already exists\n", hdl);
return;
}
cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
cfgp2.handle = hdl;
- if ((leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1, cfgp2,
- GET_SAS_DEVICE_PG0))) {
- dev_warn(&adapter->pdev->dev, "failed to read dev page0\n");
+ if (leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1, cfgp2,
+ GET_SAS_DEVICE_PG0)) {
+ dev_warn(&adapter->pdev->dev, "Failed to read dev page0\n");
return;
}
@@ -4040,7 +4552,8 @@ static void leapraid_sas_pd_add(struct leapraid_adapter *adapter,
leapraid_add_dev(adapter, hdl);
}
-static void leapraid_sas_pd_delete(struct leapraid_adapter *adapter,
+static void leapraid_sas_pd_delete(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_ir_change *evt_data)
{
u16 hdl;
@@ -4049,7 +4562,8 @@ static void leapraid_sas_pd_delete(struct leapraid_adapter *adapter,
leapraid_sas_dev_remove_by_hdl(adapter, hdl);
}
-static void leapraid_sas_pd_hide(struct leapraid_adapter *adapter,
+static void leapraid_sas_pd_hide(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_ir_change *evt_data)
{
struct leapraid_starget_priv *starget_priv;
@@ -4057,10 +4571,15 @@ static void leapraid_sas_pd_hide(struct leapraid_adapter *adapter,
struct leapraid_sas_dev *sas_dev;
unsigned long flags;
u64 volume_wwid = 0;
- u16 volume_hdl = 0;
+ u16 volume_hdl;
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__);
+ return;
+ }
leapraid_cfg_get_volume_hdl(adapter, hdl, &volume_hdl);
if (volume_hdl)
leapraid_cfg_get_volume_wwid(adapter,
@@ -4074,21 +4593,23 @@ static void leapraid_sas_pd_hide(struct leapraid_adapter *adapter,
return;
}
- set_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls);
+ set_bit(hdl, adapter->dev_topo.pd_hdls);
if (sas_dev->starget && sas_dev->starget->hostdata) {
starget = sas_dev->starget;
starget_priv = starget->hostdata;
starget_priv->flg |= LEAPRAID_TGT_FLG_RAID_MEMBER;
sas_dev->volume_hdl = volume_hdl;
sas_dev->volume_wwid = volume_wwid;
- leapraid_sdev_put(sas_dev);
}
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 *)1, leapraid_reprobe_lun);
+ (void *)LEAPRAID_NO_ULD_ATTACH_FLAG,
+ leapraid_reprobe_lun);
}
+
+ leapraid_sdev_put(sas_dev);
}
static void leapraid_sas_pd_expose(
@@ -4103,11 +4624,17 @@ static void leapraid_sas_pd_expose(
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__);
+ return;
+ }
+
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl);
if (!sas_dev) {
dev_warn(&adapter->pdev->dev,
- "%s:%d: sas_dev not found, hdl=0x%x\n",
+ "%s:%d: sas_dev not found, hdl=0x%x\n",
__func__, __LINE__, hdl);
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
return;
@@ -4115,84 +4642,100 @@ static void leapraid_sas_pd_expose(
sas_dev->volume_hdl = 0;
sas_dev->volume_wwid = 0;
- clear_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls);
+ clear_bit(hdl, adapter->dev_topo.pd_hdls);
if (sas_dev->starget && sas_dev->starget->hostdata) {
starget = sas_dev->starget;
starget_priv = starget->hostdata;
starget_priv->flg &= ~LEAPRAID_TGT_FLG_RAID_MEMBER;
- sas_dev->led_on = false;
- leapraid_sdev_put(sas_dev);
+ sas_dev->led_on = 0;
}
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, NULL, leapraid_reprobe_lun);
+ starget_for_each_device(starget,
+ LEAPRAID_ULD_ATTACH_FLAG,
+ leapraid_reprobe_lun);
}
+
+ leapraid_sdev_put(sas_dev);
}
-static void leapraid_sas_vol_visibility(struct leapraid_adapter *adapter,
+static void leapraid_sas_vol_visibility(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_ir_change *evt_data)
{
- struct leapraid_raid_volume *raid_volume = NULL;
- struct scsi_device *sdev = NULL;
- u16 hdl = 0;
+ struct leapraid_raid_volume *raid_volume;
+ struct scsi_device *sdev;
+ bool reprobe_flg = false;
+ bool sdev_held = false;
unsigned long flags;
- u8 rc = 0;
- u8 reprobe_flg = 0;
+ u16 hdl;
+ u8 rc;
hdl = le16_to_cpu(evt_data->vol_dev_hdl);
rc = evt_data->reason_code;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_hdl(adapter, hdl);
if (!raid_volume) {
+ dev_warn(&adapter->pdev->dev,
+ "%s:%d: Volume handle 0x%x not found\n",
+ __func__, __LINE__, hdl);
+ return;
+ }
+
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ sdev = raid_volume->sdev;
+ if (!sdev) {
spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
flags);
+ leapraid_raid_volume_put(raid_volume);
dev_warn(&adapter->pdev->dev,
- "%s:%d: volume handle 0x%x not found\n",
+ "%s:%d: Volume handle 0x%x has no sdev\n",
__func__, __LINE__, hdl);
return;
}
- reprobe_flg = 0;
- sdev = raid_volume->sdev;
- if (sdev) {
- if (sdev->no_uld_attach) {
- if (rc == LEAPRAID_EVT_IR_RC_VOLUME_UNHIDE) {
- sdev->no_uld_attach = 0;
- reprobe_flg = 1;
- }
- } else {
- if (rc == LEAPRAID_EVT_IR_RC_VOLUME_HIDE) {
- sdev->no_uld_attach = 1;
- reprobe_flg = 1;
- }
- }
+ if (sdev->no_uld_attach &&
+ rc == LEAPRAID_EVT_IR_RC_VOLUME_UNHIDE) {
+ sdev->no_uld_attach = 0;
+ reprobe_flg = true;
+ } else if (!sdev->no_uld_attach &&
+ rc == LEAPRAID_EVT_IR_RC_VOLUME_HIDE) {
+ sdev->no_uld_attach = 1;
+ reprobe_flg = true;
+ }
- if (reprobe_flg) {
- if (sdev->no_uld_attach)
- sdev_printk(KERN_INFO, sdev, "hide vol\n");
- else
- sdev_printk(KERN_INFO, sdev, "unhide vol\n");
+ if (reprobe_flg && !scsi_device_get(sdev))
+ sdev_held = true;
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+ leapraid_raid_volume_put(raid_volume);
- WARN_ON(scsi_device_reprobe(sdev));
- } else {
- dev_warn(&adapter->pdev->dev,
- "%s:rc(0x%x):request matches, skipping.\n",
- __func__, rc);
- }
+ if (!reprobe_flg) {
+ dev_warn(&adapter->pdev->dev,
+ "%s:rc(0x%x): Request matches, skipping\n",
+ __func__, rc);
+ return;
+ }
- } else {
+ if (!sdev_held) {
dev_warn(&adapter->pdev->dev,
- "%s:%d: volume handle 0x%x has no sdev\n",
- __func__, __LINE__, hdl);
+ "%s: Failed to hold sdev for reprobe, hdl=0x%x\n",
+ __func__, hdl);
+ return;
}
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+ if (sdev->no_uld_attach)
+ sdev_printk(KERN_INFO, sdev, "hide vol\n");
+ else
+ sdev_printk(KERN_INFO, sdev, "unhide vol\n");
+
+ WARN_ON(scsi_device_reprobe(sdev));
+ scsi_device_put(sdev);
}
-static void leapraid_sas_volume_add(struct leapraid_adapter *adapter,
+static void leapraid_sas_volume_add(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_ir_change *evt_data)
{
struct leapraid_raid_volume *raid_volume;
@@ -4203,23 +4746,21 @@ static void leapraid_sas_volume_add(struct leapraid_adapter *adapter,
hdl = le16_to_cpu(evt_data->vol_dev_hdl);
if (leapraid_cfg_get_volume_wwid(adapter, hdl, &wwid)) {
- dev_warn(&adapter->pdev->dev, "failed to read volume page1\n");
+ dev_warn(&adapter->pdev->dev, "Failed to read volume page1\n");
return;
}
if (!wwid) {
- dev_warn(&adapter->pdev->dev, "invalid WWID(handle=0x%x)\n",
+ dev_warn(&adapter->pdev->dev, "Invalid WWID(handle=0x%x)\n",
hdl);
return;
}
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_wwid(adapter, wwid);
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
-
if (raid_volume) {
dev_warn(&adapter->pdev->dev,
- "volume handle 0x%x already exists\n", hdl);
+ "Volume handle 0x%x already exists\n", hdl);
+ leapraid_raid_volume_put(raid_volume);
return;
}
@@ -4227,6 +4768,8 @@ static void leapraid_sas_volume_add(struct leapraid_adapter *adapter,
if (!raid_volume)
return;
+ INIT_LIST_HEAD(&raid_volume->list);
+ kref_init(&raid_volume->refcnt);
raid_volume->id = adapter->dev_topo.sas_id++;
raid_volume->channel = RAID_CHANNEL;
raid_volume->hdl = hdl;
@@ -4237,52 +4780,67 @@ static void leapraid_sas_volume_add(struct leapraid_adapter *adapter,
raid_volume->id, 0))
leapraid_raid_volume_remove(adapter, raid_volume);
dev_info(&adapter->pdev->dev,
- "add raid volume: hdl=0x%x, wwid=0x%llx\n", hdl, wwid);
+ "add RAID volume: hdl=0x%x, wwid=0x%llx\n", hdl, wwid);
} else {
spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
leapraid_check_boot_dev(adapter, raid_volume, RAID_CHANNEL);
spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
flags);
}
+ leapraid_raid_volume_put(raid_volume);
}
-
-static void leapraid_sas_volume_delete(struct leapraid_adapter *adapter,
- u16 hdl)
+
+static void leapraid_sas_volume_delete_by_ptr(
+ struct leapraid_adapter *adapter,
+ struct leapraid_raid_volume *raid_volume)
{
struct leapraid_starget_priv *starget_priv;
- struct leapraid_raid_volume *raid_volume;
struct scsi_target *starget = NULL;
unsigned long flags;
+ bool in_list;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
- raid_volume = leapraid_raid_volume_find_by_hdl(adapter, hdl);
- if (!raid_volume) {
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
- flags);
- dev_warn(&adapter->pdev->dev,
- "%s:%d: volume handle 0x%x not found\n",
- __func__, __LINE__, hdl);
+ if (!raid_volume)
return;
- }
- if (raid_volume->starget) {
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ in_list = !list_empty(&raid_volume->list);
+ if (in_list && raid_volume->starget) {
starget = raid_volume->starget;
starget_priv = starget->hostdata;
- starget_priv->deleted = true;
+ if (starget_priv)
+ starget_priv->deleted = 1;
}
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+
+ if (!in_list)
+ return;
dev_info(&adapter->pdev->dev,
- "delete raid volume: hdl=0x%x, wwid=0x%llx\n",
+ "delete RAID volume: hdl=0x%x, wwid=0x%llx\n",
raid_volume->hdl, raid_volume->wwid);
- list_del(&raid_volume->list);
- kfree(raid_volume);
-
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+ leapraid_raid_volume_remove(adapter, raid_volume);
if (starget)
scsi_remove_target(&starget->dev);
}
+static void leapraid_sas_volume_delete(struct leapraid_adapter *adapter,
+ u16 hdl)
+{
+ struct leapraid_raid_volume *raid_volume;
+
+ raid_volume = leapraid_raid_volume_find_by_hdl(adapter, hdl);
+ if (!raid_volume) {
+ dev_warn(&adapter->pdev->dev,
+ "%s:%d: Volume handle 0x%x not found\n",
+ __func__, __LINE__, hdl);
+ return;
+ }
+
+ leapraid_sas_volume_delete_by_ptr(adapter, raid_volume);
+ leapraid_raid_volume_put(raid_volume);
+}
+
static void leapraid_sas_ir_chg_evt(struct leapraid_adapter *adapter,
struct leapraid_fw_evt_work *fw_evt)
{
@@ -4324,7 +4882,9 @@ static void leapraid_sas_enc_dev_stat_add_node(
{
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- struct leapraid_enc_node *enc_node = NULL;
+ struct leapraid_enc_node *enc_node;
+ struct leapraid_enc_node *enc_exist;
+ unsigned long flags;
int rc;
enc_node = kzalloc(sizeof(*enc_node), GFP_KERNEL);
@@ -4339,16 +4899,33 @@ static void leapraid_sas_enc_dev_stat_add_node(
kfree(enc_node);
return;
}
+
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags);
+ enc_exist = leapraid_enc_find_by_hdl(adapter, hdl);
+ if (enc_exist) {
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
+ kfree(enc_node);
+ return;
+ }
list_add_tail(&enc_node->list, &adapter->dev_topo.enc_list);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
}
static void leapraid_sas_enc_dev_stat_del_node(
- struct leapraid_enc_node *enc_node)
+ struct leapraid_adapter *adapter, u16 hdl)
{
- if (!enc_node)
+ struct leapraid_enc_node *enc_node;
+ unsigned long flags;
+
+ if (!hdl)
return;
- list_del(&enc_node->list);
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags);
+ enc_node = leapraid_enc_find_by_hdl(adapter, hdl);
+ if (enc_node)
+ list_del(&enc_node->list);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
+
kfree(enc_node);
}
@@ -4356,7 +4933,6 @@ static void leapraid_sas_enc_dev_stat_chg_evt(
struct leapraid_adapter *adapter,
struct leapraid_fw_evt_work *fw_evt)
{
- struct leapraid_enc_node *enc_node = NULL;
struct leapraid_evt_data_sas_enc_dev_status_change *evt_data;
u16 enc_hdl;
@@ -4365,15 +4941,13 @@ static void leapraid_sas_enc_dev_stat_chg_evt(
evt_data = fw_evt->evt_data;
enc_hdl = le16_to_cpu(evt_data->enc_hdl);
- if (enc_hdl)
- enc_node = leapraid_enc_find_by_hdl(adapter, enc_hdl);
switch (evt_data->reason_code) {
case LEAPRAID_EVT_SAS_ENCL_RC_ADDED:
- if (!enc_node)
+ if (enc_hdl)
leapraid_sas_enc_dev_stat_add_node(adapter, enc_hdl);
break;
case LEAPRAID_EVT_SAS_ENCL_RC_NOT_RESPONDING:
- leapraid_sas_enc_dev_stat_del_node(enc_node);
+ leapraid_sas_enc_dev_stat_del_node(adapter, enc_hdl);
break;
default:
break;
@@ -4390,7 +4964,11 @@ static void leapraid_remove_unresp_sas_end_dev(
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
list_for_each_entry_safe(sas_dev, sas_dev_next,
&adapter->dev_topo.sas_dev_init_list, list) {
+ if (sas_dev->rphy || sas_dev->pend_sas_rphy_add)
+ continue;
+
list_del_init(&sas_dev->list);
+ leapraid_clear_cached_boot_dev(adapter, sas_dev, 0);
leapraid_sdev_put(sas_dev);
}
list_for_each_entry_safe(sas_dev, sas_dev_next,
@@ -4398,7 +4976,7 @@ static void leapraid_remove_unresp_sas_end_dev(
if (!sas_dev->resp)
list_move_tail(&sas_dev->list, &head);
else
- sas_dev->resp = false;
+ sas_dev->resp = 0;
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -4409,23 +4987,32 @@ static void leapraid_remove_unresp_sas_end_dev(
}
dev_info(&adapter->pdev->dev,
- "unresponding sas end devices removed\n");
+ "Unresponsive SAS end devices removed\n");
}
static void leapraid_remove_unresp_raid_volumes(
struct leapraid_adapter *adapter)
{
+ unsigned long flags;
struct leapraid_raid_volume *raid_volume, *raid_volume_next;
+ LIST_HEAD(head);
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
list_for_each_entry_safe(raid_volume, raid_volume_next,
&adapter->dev_topo.raid_volume_list, list) {
if (!raid_volume->resp)
- leapraid_sas_volume_delete(adapter, raid_volume->hdl);
+ list_move_tail(&raid_volume->list, &head);
else
- raid_volume->resp = false;
+ raid_volume->resp = 0;
+ }
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+
+ list_for_each_entry_safe(raid_volume, raid_volume_next, &head, list) {
+ leapraid_sas_volume_delete_by_ptr(adapter, raid_volume);
}
+
dev_info(&adapter->pdev->dev,
- "unresponding raid volumes removed\n");
+ "Unresponsive RAID volumes removed\n");
}
static void leapraid_remove_unresp_sas_exp(struct leapraid_adapter *adapter)
@@ -4440,7 +5027,7 @@ static void leapraid_remove_unresp_sas_exp(struct leapraid_adapter *adapter)
if (!topo_node_exp->resp)
list_move_tail(&topo_node_exp->list, &head);
else
- topo_node_exp->resp = false;
+ topo_node_exp->resp = 0;
}
spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
@@ -4449,7 +5036,7 @@ static void leapraid_remove_unresp_sas_exp(struct leapraid_adapter *adapter)
leapraid_exp_node_rm(adapter, topo_node_exp);
dev_info(&adapter->pdev->dev,
- "unresponding sas expanders removed\n");
+ "Unresponsive SAS expanders removed\n");
}
static void leapraid_remove_unresp_dev(struct leapraid_adapter *adapter)
@@ -4505,25 +5092,27 @@ static void leapraid_update_dev_qdepth(struct leapraid_adapter *adapter)
{
struct leapraid_sdev_priv *sdev_priv;
struct leapraid_sas_dev *sas_dev;
+ struct leapraid_adapter_attr *attr;
struct scsi_device *sdev;
u16 qdepth;
+ attr = &adapter->adapter_attr;
shost_for_each_device(sdev, adapter->shost) {
sdev_priv = sdev->hostdata;
if (!sdev_priv || !sdev_priv->starget_priv)
continue;
sas_dev = sdev_priv->starget_priv->sas_dev;
if (sas_dev && sas_dev->dev_info & LEAPRAID_DEVTYP_SSP_TGT)
- qdepth = (sas_dev->port_type > 1) ?
- adapter->adapter_attr.wideport_max_queue_depth :
- adapter->adapter_attr.narrowport_max_queue_depth;
+ qdepth = (sas_dev->port_connection > 1) ?
+ attr->wideport_max_queue_depth :
+ attr->narrowport_max_queue_depth;
else if (sas_dev && sas_dev->dev_info &
LEAPRAID_DEVTYP_SATA_DEV)
- qdepth = adapter->adapter_attr.sata_max_queue_depth;
+ qdepth = attr->sata_max_queue_depth;
else
continue;
- leapraid_adjust_sdev_queue_depth(sdev, qdepth);
+ leapraid_change_queue_depth(sdev, qdepth);
}
}
@@ -4539,15 +5128,17 @@ static void leapraid_update_exp_links(struct leapraid_adapter *adapter,
cfgp2.handle = hdl;
for (i = 0; i < topo_node_exp->phys_num; i++) {
cfgp1.phy_number = i;
- if ((leapraid_op_config_page(adapter, &exp_p1, cfgp1, cfgp2,
- GET_SAS_EXPANDER_PG1)))
+ if (leapraid_op_config_page(adapter, &exp_p1, cfgp1, cfgp2,
+ GET_SAS_EXPANDER_PG1))
return;
- leapraid_transport_update_links(adapter,
+ leapraid_transport_update_links(
+ adapter,
topo_node_exp->sas_address,
le16_to_cpu(exp_p1.attached_dev_hdl),
i,
- exp_p1.neg_link_rate >> 4,
+ exp_p1.neg_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT,
topo_node_exp->card_port);
}
}
@@ -4562,7 +5153,7 @@ 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");
+ dev_info(&adapter->pdev->dev, "Begin scanning expanders\n");
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
@@ -4573,7 +5164,8 @@ static void leapraid_scan_exp_after_reset(struct leapraid_adapter *adapter)
port_id = exp_p0.physical_port;
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
topo_node_exp =
- leapraid_exp_find_by_sas_address(adapter,
+ leapraid_exp_find_by_sas_address(
+ adapter,
le64_to_cpu(exp_p0.sas_address),
leapraid_get_port_by_id(adapter,
port_id,
@@ -4587,14 +5179,14 @@ static void leapraid_scan_exp_after_reset(struct leapraid_adapter *adapter)
leapraid_exp_add(adapter, hdl);
dev_info(&adapter->pdev->dev,
- "add exp: hdl=0x%04x, sas addr=0x%016llx\n",
+ "add exp: hdl=0x%04x, SAS addr=0x%016llx\n",
hdl,
(unsigned long long)le64_to_cpu(
exp_p0.sas_address));
}
}
- dev_info(&adapter->pdev->dev, "expanders scan complete\n");
+ dev_info(&adapter->pdev->dev, "Expanders scan complete\n");
}
static void leapraid_scan_phy_disks_after_reset(
@@ -4611,7 +5203,7 @@ 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");
+ 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;
@@ -4644,20 +5236,25 @@ static void leapraid_scan_phy_disks_after_reset(
LEAPRAID_SAS_NEG_LINK_RATE_1_5,
leapraid_get_port_by_id(
adapter, port_id, false));
- set_bit(hdl,
- (unsigned long *)adapter->dev_topo.pd_hdls);
-
- leapraid_add_dev(adapter, hdl);
-
- dev_info(&adapter->pdev->dev,
- "add phys disk: hdl=0x%04x, sas addr=0x%016llx\n",
- hdl,
- (unsigned long long)le64_to_cpu(
- sas_dev_p0.sas_address));
+ if (!hdl || hdl >
+ adapter->adapter_attr.features.max_dev_handle) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid device handle\n",
+ __func__);
+ } else {
+ set_bit(hdl, adapter->dev_topo.pd_hdls);
+ leapraid_add_dev(adapter, hdl);
+
+ dev_info(&adapter->pdev->dev,
+ "add pd hdl=0x%04x saddr=0x%016llx\n",
+ hdl,
+ (unsigned long long)le64_to_cpu(
+ sas_dev_p0.sas_address));
+ }
}
}
- dev_info(&adapter->pdev->dev, "phys disk scan complete\n");
+ dev_info(&adapter->pdev->dev, "PHYs disk scan complete\n");
}
static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter)
@@ -4667,10 +5264,9 @@ static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter)
union cfg_param_1 cfgp1_extra = {0};
union cfg_param_2 cfgp2_extra = {0};
struct leapraid_evt_data_ir_change evt_data;
- static struct leapraid_raid_volume *raid_volume;
+ struct leapraid_raid_volume *raid_volume;
struct leapraid_raidvol_p1 *vol_p1;
struct leapraid_raidvol_p0 *vol_p0;
- unsigned long flags;
u16 hdl;
vol_p0 = kzalloc(sizeof(*vol_p0), GFP_KERNEL);
@@ -4683,21 +5279,20 @@ static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter)
return;
}
- dev_info(&adapter->pdev->dev, "begin scanning volumes\n");
+ 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,
cfgp2, GET_RAID_VOLUME_PG1);
cfgp2.handle = hdl) {
hdl = le16_to_cpu(vol_p1->dev_hdl);
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_wwid(
adapter,
le64_to_cpu(vol_p1->wwid));
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
- flags);
- if (raid_volume)
+ if (raid_volume) {
+ leapraid_raid_volume_put(raid_volume);
continue;
+ }
cfgp1_extra.size = sizeof(struct leapraid_raidvol_p0);
cfgp2_extra.handle = hdl;
@@ -4722,7 +5317,7 @@ 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");
+ dev_info(&adapter->pdev->dev, "Volumes scan complete\n");
}
static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter)
@@ -4736,7 +5331,7 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter)
u8 port_id;
dev_info(&adapter->pdev->dev,
- "begin scanning sas end devices\n");
+ "Begin scanning SAS end devices\n");
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
@@ -4744,6 +5339,13 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter)
GET_SAS_DEVICE_PG0);
cfgp2.handle = hdl) {
hdl = le16_to_cpu(sas_dev_p0.dev_hdl);
+ if (!hdl ||
+ hdl > adapter->adapter_attr.features.max_dev_handle) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid device handle\n", __func__);
+ continue;
+ }
+
if (!(leapraid_is_end_dev(le32_to_cpu(sas_dev_p0.dev_info))))
continue;
@@ -4774,21 +5376,21 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter)
false));
leapraid_add_dev(adapter, hdl);
dev_info(&adapter->pdev->dev,
- "add sas dev: hdl=0x%04x, sas addr=0x%016llx\n",
+ "Add SAS dev: hdl=0x%04x, saddr=0x%016llx\n",
hdl,
(unsigned long long)le64_to_cpu(
sas_dev_p0.sas_address));
}
}
- dev_info(&adapter->pdev->dev, "sas end devices scan complete\n");
+ 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");
+ dev_info(&adapter->pdev->dev, "Begin scanning devices\n");
- leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num);
+ leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num > 0);
leapraid_scan_exp_after_reset(adapter);
if (adapter->adapter_attr.raid_support) {
leapraid_scan_phy_disks_after_reset(adapter);
@@ -4796,11 +5398,13 @@ static void leapraid_scan_all_dev_after_reset(struct leapraid_adapter *adapter)
}
leapraid_scan_sas_dev_after_reset(adapter);
- dev_info(&adapter->pdev->dev, "devices scan complete\n");
+ dev_info(&adapter->pdev->dev, "Devices scan complete\n");
}
static void leapraid_hardreset_async_logic(struct leapraid_adapter *adapter)
{
+ unsigned long flags;
+
leapraid_remove_unresp_dev(adapter);
leapraid_del_dirty_vphy(adapter);
leapraid_del_dirty_card_port(adapter);
@@ -4809,6 +5413,10 @@ static void leapraid_hardreset_async_logic(struct leapraid_adapter *adapter)
if (adapter->scan_dev_desc.driver_loading)
leapraid_scan_dev_done(adapter);
+ spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
+ adapter->access_ctrl.shost_recover_async = 0;
+ spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
+ wake_up(&adapter->access_ctrl.shost_recover_wq);
}
static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter,
@@ -4817,15 +5425,17 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter,
{
void *req;
bool reset_flg = false;
- int rc = 0;
+ int rc;
mutex_lock(&adapter->driver_cmds.enc_cmd.mutex);
- rc = leapraid_check_adapter_is_op(adapter);
+ rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
+ __func__);
if (rc)
- goto out;
+ goto unlock;
adapter->driver_cmds.enc_cmd.status = LEAPRAID_CMD_PENDING;
- req = leapraid_get_task_desc(adapter,
+ req = leapraid_get_task_desc(
+ adapter,
adapter->driver_cmds.enc_cmd.inter_taskid);
memset(req, 0, LEAPRAID_REQUEST_SIZE);
memcpy(req, sep_req, sizeof(struct leapraid_sep_req));
@@ -4835,6 +5445,10 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter,
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);
reset_flg =
leapraid_check_reset(
adapter->driver_cmds.enc_cmd.status);
@@ -4843,17 +5457,17 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter,
}
if (adapter->driver_cmds.enc_cmd.status & LEAPRAID_CMD_REPLY_VALID)
- memcpy(sep_rep, (void *)(&adapter->driver_cmds.enc_cmd.reply),
+ memcpy(sep_rep, &adapter->driver_cmds.enc_cmd.reply,
sizeof(struct leapraid_sep_rep));
do_hard_reset:
if (reset_flg) {
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
leapraid_hard_reset_handler(adapter, FULL_RESET);
}
adapter->driver_cmds.enc_cmd.status = LEAPRAID_CMD_NOT_USED;
-out:
+unlock:
mutex_unlock(&adapter->driver_cmds.enc_cmd.mutex);
return rc;
}
@@ -4872,8 +5486,9 @@ static void leapraid_set_led(struct leapraid_adapter *adapter,
sep_req.func = LEAPRAID_FUNC_SCSI_ENC_PROCESSOR;
sep_req.act = LEAPRAID_SEP_REQ_ACT_WRITE_STATUS;
if (on) {
- sep_req.slot_status =
- cpu_to_le32(LEAPRAID_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
+ u32 status = LEAPRAID_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT;
+
+ sep_req.slot_status = cpu_to_le32(status);
sep_req.dev_hdl = cpu_to_le16(sas_dev->hdl);
sep_req.flg = LEAPRAID_SEP_REQ_FLG_DEVHDL_ADDRESS;
if (leapraid_send_enc_cmd(adapter, &sep_rep, &sep_req)) {
@@ -4881,52 +5496,75 @@ static void leapraid_set_led(struct leapraid_adapter *adapter,
return;
}
- sas_dev->led_on = true;
- if (sep_rep.adapter_status)
- leapraid_sdev_put(sas_dev);
+ sas_dev->led_on = 1;
+ leapraid_sdev_put(sas_dev);
} else {
sep_req.slot_status = 0;
sep_req.slot = cpu_to_le16(sas_dev->slot);
sep_req.dev_hdl = 0;
sep_req.enc_hdl = cpu_to_le16(sas_dev->enc_hdl);
sep_req.flg = LEAPRAID_SEP_REQ_FLG_ENCLOSURE_SLOT_ADDRESS;
- if ((leapraid_send_enc_cmd(adapter, &sep_rep, &sep_req))) {
- leapraid_sdev_put(sas_dev);
- return;
- }
+ leapraid_send_enc_cmd(adapter, &sep_rep, &sep_req);
+ }
+}
- if (sep_rep.adapter_status) {
- leapraid_sdev_put(sas_dev);
- return;
+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) {
+ spin_lock_irqsave(
+ &adapter->reset_desc.adapter_reset_lock,
+ flags);
+ adapter->access_ctrl.shost_recover_async = 0;
+ spin_unlock_irqrestore(
+ &adapter->reset_desc.adapter_reset_lock,
+ flags);
+
+ wake_up(&adapter->access_ctrl.shost_recover_wq);
+
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed, shost %d, host %d\n",
+ __func__,
+ adapter->access_ctrl.shost_recovering,
+ adapter->access_ctrl.host_removing);
+
+ 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));
}
+ return 0;
}
static void leapraid_fw_work(struct leapraid_adapter *adapter,
struct leapraid_fw_evt_work *fw_evt)
{
struct leapraid_sas_dev *sas_dev;
+ unsigned long flags;
+ spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
adapter->fw_evt_s.cur_evt = fw_evt;
+ adapter->fw_evt_s.cur_evt_task = current;
+ spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
leapraid_del_fw_evt_from_list(adapter, fw_evt);
if (adapter->access_ctrl.host_removing ||
adapter->access_ctrl.pcie_recovering) {
+ spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
leapraid_fw_evt_put(fw_evt);
adapter->fw_evt_s.cur_evt = NULL;
+ adapter->fw_evt_s.cur_evt_task = NULL;
+ spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
return;
}
switch (fw_evt->evt_type) {
- case LEAPRAID_EVT_SAS_DISCOVERY:
- {
- struct leapraid_evt_data_sas_disc *evt_data;
-
- evt_data = fw_evt->evt_data;
- if (evt_data->reason_code ==
- LEAPRAID_EVT_SAS_DISC_RC_STARTED &&
- !adapter->dev_topo.card.phys_num)
- leapraid_sas_host_add(adapter, 0);
- break;
- }
case LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST:
leapraid_sas_topo_chg_evt(adapter, fw_evt);
break;
@@ -4937,14 +5575,9 @@ static void leapraid_fw_work(struct leapraid_adapter *adapter,
leapraid_sas_enc_dev_stat_chg_evt(adapter, fw_evt);
break;
case LEAPRAID_EVT_REMOVE_DEAD_DEV:
- 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)
- goto out;
+ if (leapraid_wait_adapter_recovery(adapter))
+ goto out_cleanup;
- ssleep(1);
- }
leapraid_hardreset_async_logic(adapter);
break;
case LEAPRAID_EVT_TURN_ON_PFA_LED:
@@ -4953,14 +5586,17 @@ static void leapraid_fw_work(struct leapraid_adapter *adapter,
leapraid_set_led(adapter, sas_dev, true);
break;
case LEAPRAID_EVT_SCAN_DEV_DONE:
- adapter->scan_dev_desc.scan_start = false;
+ adapter->scan_dev_desc.scan_start = 0;
break;
default:
break;
}
-out:
+out_cleanup:
+ spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
leapraid_fw_evt_put(fw_evt);
adapter->fw_evt_s.cur_evt = NULL;
+ adapter->fw_evt_s.cur_evt_task = NULL;
+ spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
}
static void leapraid_sas_dev_stat_chg_evt(
@@ -4968,7 +5604,7 @@ static void leapraid_sas_dev_stat_chg_evt(
struct leapraid_evt_data_sas_dev_status_change *event_data)
{
struct leapraid_starget_priv *starget_priv;
- struct leapraid_sas_dev *sas_dev = NULL;
+ struct leapraid_sas_dev *sas_dev;
u64 sas_address;
unsigned long flags;
@@ -4983,26 +5619,29 @@ static void leapraid_sas_dev_stat_chg_evt(
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_address = le64_to_cpu(event_data->sas_address);
- sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter,
+ sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(
+ adapter,
sas_address,
leapraid_get_port_by_id(adapter,
event_data->physical_port,
false));
- if (sas_dev && sas_dev->starget) {
- starget_priv = sas_dev->starget->hostdata;
- if (starget_priv) {
- switch (event_data->reason_code) {
- case LEAPRAID_EVT_SAS_DEV_STAT_RC_INTERNAL_DEV_RESET:
- starget_priv->tm_busy = true;
- break;
- case LEAPRAID_EVT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
- starget_priv->tm_busy = false;
- break;
- }
+ if (!sas_dev || !sas_dev->starget)
+ goto out_unlock;
+
+ starget_priv = sas_dev->starget->hostdata;
+ if (starget_priv) {
+ switch (event_data->reason_code) {
+ case LEAPRAID_EVT_SAS_DEV_STAT_RC_INTERNAL_DEV_RESET:
+ starget_priv->tm_busy = 1;
+ break;
+ case LEAPRAID_EVT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
+ starget_priv->tm_busy = 0;
+ break;
}
}
+out_unlock:
if (sas_dev)
leapraid_sdev_put(sas_dev);
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -5015,32 +5654,45 @@ static void leapraid_set_volume_delete_flag(struct leapraid_adapter *adapter,
struct leapraid_starget_priv *sas_target_priv_data;
unsigned long flags;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_hdl(adapter, handle);
- if (raid_volume && raid_volume->starget &&
- raid_volume->starget->hostdata) {
- sas_target_priv_data = raid_volume->starget->hostdata;
- sas_target_priv_data->deleted = true;
+ if (raid_volume) {
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ if (raid_volume->starget &&
+ raid_volume->starget->hostdata) {
+ sas_target_priv_data = raid_volume->starget->hostdata;
+ sas_target_priv_data->deleted = 1;
+ }
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
+ flags);
+ leapraid_raid_volume_put(raid_volume);
}
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
}
-static void leapraid_check_ir_change_evt(struct leapraid_adapter *adapter,
+static void leapraid_check_ir_change_evt(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_ir_change *evt_data)
{
u16 phys_disk_dev_hdl;
switch (evt_data->reason_code) {
case LEAPRAID_EVT_IR_RC_VOLUME_DELETE:
- leapraid_set_volume_delete_flag(adapter,
- le16_to_cpu(evt_data->vol_dev_hdl));
+ leapraid_set_volume_delete_flag(
+ adapter,
+ le16_to_cpu(evt_data->vol_dev_hdl));
break;
case LEAPRAID_EVT_IR_RC_PD_UNHIDDEN_TO_DELETE:
phys_disk_dev_hdl =
le16_to_cpu(evt_data->phys_disk_dev_hdl);
- clear_bit(phys_disk_dev_hdl,
- (unsigned long *)adapter->dev_topo.pd_hdls);
- leapraid_tgt_rst_send(adapter, phys_disk_dev_hdl);
+ if (!phys_disk_dev_hdl ||
+ phys_disk_dev_hdl >
+ adapter->adapter_attr.features.max_dev_handle) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid device handle\n", __func__);
+ } else {
+ clear_bit(phys_disk_dev_hdl,
+ adapter->dev_topo.pd_hdls);
+ leapraid_tgt_rst_send(adapter, phys_disk_dev_hdl);
+ }
break;
}
}
@@ -5050,7 +5702,7 @@ static void leapraid_topo_del_evts_process_exp_status(
struct leapraid_evt_data_sas_topo_change_list *evt_data)
{
struct leapraid_fw_evt_work *fw_evt = NULL;
- struct leapraid_evt_data_sas_topo_change_list *loc_evt_data = NULL;
+ struct leapraid_evt_data_sas_topo_change_list *loc_evt_data;
unsigned long flags;
u16 exp_hdl;
@@ -5081,7 +5733,8 @@ static void leapraid_topo_del_evts_process_exp_status(
}
}
-static void leapraid_check_topo_del_evts(struct leapraid_adapter *adapter,
+static void leapraid_check_topo_del_evts(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_sas_topo_change_list *evt_data)
{
int reason_code;
@@ -5111,17 +5764,20 @@ static bool leapraid_async_process_evt(
switch (evt) {
case LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE:
- leapraid_sas_dev_stat_chg_evt(adapter,
+ leapraid_sas_dev_stat_chg_evt(
+ adapter,
(struct leapraid_evt_data_sas_dev_status_change
*)event_notify_rep->evt_data);
break;
case LEAPRAID_EVT_IR_CHANGE:
- leapraid_check_ir_change_evt(adapter,
+ leapraid_check_ir_change_evt(
+ adapter,
(struct leapraid_evt_data_ir_change
*)event_notify_rep->evt_data);
break;
case LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST:
- leapraid_check_topo_del_evts(adapter,
+ leapraid_check_topo_del_evts(
+ adapter,
(struct leapraid_evt_data_sas_topo_change_list
*)event_notify_rep->evt_data);
if (adapter->access_ctrl.shost_recovering) {
@@ -5129,7 +5785,6 @@ static bool leapraid_async_process_evt(
return exit_flag;
}
break;
- case LEAPRAID_EVT_SAS_DISCOVERY:
case LEAPRAID_EVT_SAS_ENCL_DEV_STATUS_CHANGE:
break;
default:
@@ -5151,7 +5806,7 @@ static void leapraid_async_evt_cb_enqueue(
if (!fw_evt)
return;
- evt_sz = le16_to_cpu(evt_notify_rep->evt_data_len) * 4;
+ evt_sz = le16_to_cpu(evt_notify_rep->evt_data_len) * sizeof(u32);
fw_evt->evt_data = kmemdup(evt_notify_rep->evt_data,
evt_sz, GFP_ATOMIC);
if (!fw_evt->evt_data) {
@@ -5240,13 +5895,63 @@ static void leapraid_scan_dev_complete(struct leapraid_adapter *adapter)
leapraid_fw_evt_put(fw_evt);
}
-static u8 leapraid_driver_cmds_done(struct leapraid_adapter *adapter,
- u16 taskid, u8 msix_index,
- u32 rep_paddr, u8 cb_idx)
+static u8 leapraid_handle_scan_cb(struct leapraid_adapter *adapter,
+ struct leapraid_driver_cmd *cmd,
+ struct leapraid_rep *rep)
+{
+ u16 status;
+
+ cmd->status &= ~LEAPRAID_CMD_PENDING;
+
+ 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;
+ }
+
+ 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,
+ struct leapraid_rep *rep,
+ u16 taskid)
+{
+ struct leapraid_scsiio_rep *scsiio_reply;
+
+ if (rep->function != LEAPRAID_FUNC_SCSIIO &&
+ rep->function != LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH)
+ return;
+
+ scsiio_reply = (struct leapraid_scsiio_rep *)rep;
+
+ if (!(scsiio_reply->scsi_state &
+ LEAPRAID_SCSI_STATE_AUTOSENSE_VALID))
+ return;
+
+ memcpy(&adapter->driver_cmds.ctl_cmd.sense,
+ leapraid_get_sense_buffer(adapter, taskid),
+ min_t(u32, SCSI_SENSE_BUFFERSIZE,
+ le32_to_cpu(scsiio_reply->sense_count)));
+}
+
+static bool leapraid_driver_cmds_done(struct leapraid_adapter *adapter,
+ u16 taskid, u8 msix_index,
+ u32 rep_paddr, u8 cb_idx)
{
struct leapraid_rep *leap_mpi_rep =
leapraid_get_reply_vaddr(adapter, rep_paddr);
struct leapraid_driver_cmd *sp_cmd, *_sp_cmd = NULL;
+ u8 reply_len;
list_for_each_entry(sp_cmd, &adapter->driver_cmds.special_cmd_list,
list)
@@ -5256,74 +5961,55 @@ static u8 leapraid_driver_cmds_done(struct leapraid_adapter *adapter,
}
if (WARN_ON(!_sp_cmd))
- return 1;
+ return true;
if (WARN_ON(_sp_cmd->status == LEAPRAID_CMD_NOT_USED))
- return 1;
+ return true;
if (WARN_ON(taskid != _sp_cmd->hp_taskid &&
taskid != _sp_cmd->taskid &&
taskid != _sp_cmd->inter_taskid))
- return 1;
-
+ return true;
_sp_cmd->status |= LEAPRAID_CMD_DONE;
if (leap_mpi_rep) {
- memcpy((void *)(&_sp_cmd->reply), leap_mpi_rep,
- leap_mpi_rep->msg_len * 4);
+ reply_len = leap_mpi_rep->msg_len * sizeof(u32);
+ if (reply_len > LEAPRAID_REPLY_SIZE)
+ reply_len = LEAPRAID_REPLY_SIZE;
+ 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) {
- u16 adapter_status;
-
- _sp_cmd->status &= ~LEAPRAID_CMD_PENDING;
- adapter_status =
- le16_to_cpu(leap_mpi_rep->adapter_status) &
- LEAPRAID_ADAPTER_STATUS_MASK;
- if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS)
- adapter->scan_dev_desc.scan_dev_failed = true;
-
- if (_sp_cmd->async_scan_dev) {
- if (adapter_status ==
- LEAPRAID_ADAPTER_STATUS_SUCCESS) {
- leapraid_scan_dev_complete(adapter);
- } else {
- adapter->scan_dev_desc.scan_start_failed =
- adapter_status;
- }
- return 1;
- }
-
- complete(&_sp_cmd->done);
- return 1;
- }
+ 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_CTL_CB_IDX) {
- struct leapraid_scsiio_rep *scsiio_reply;
-
- if (leap_mpi_rep->function ==
- LEAPRAID_FUNC_SCSIIO_REQ ||
- leap_mpi_rep->function ==
- LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH) {
- scsiio_reply =
- (struct leapraid_scsiio_rep *)leap_mpi_rep;
- if (scsiio_reply->scsi_state &
- LEAPRAID_SCSI_STATE_AUTOSENSE_VALID)
- memcpy((void *)(&adapter->driver_cmds.ctl_cmd.sense),
- leapraid_get_sense_buffer(adapter, taskid),
- min_t(u32,
- SCSI_SENSE_BUFFERSIZE,
- le32_to_cpu(scsiio_reply->sense_count)));
- }
- }
+ if (_sp_cmd->cb_idx == LEAPRAID_CTL_CB_IDX)
+ leapraid_handle_ctl_cb(adapter, leap_mpi_rep, taskid);
}
_sp_cmd->status &= ~LEAPRAID_CMD_PENDING;
complete(&_sp_cmd->done);
- return 1;
+ return true;
+}
+
+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) {
+ if (leapraid_scsiio_done(adapter, taskid, msix_idx, rep))
+ leapraid_free_taskid(adapter, taskid);
+ return;
+ }
+
+ if (leapraid_driver_cmds_done(adapter, taskid, msix_idx, rep,
+ leapraid_get_cb_idx(adapter, taskid)))
+ leapraid_free_taskid(adapter, taskid);
}
-static void leapraid_request_descript_handler(struct leapraid_adapter *adapter,
- union leapraid_rep_desc_union *rpf,
- u8 req_desc_type, u8 msix_idx)
+static void leapraid_request_descript_handler(
+ struct leapraid_adapter *adapter,
+ union leapraid_rep_desc_union *rpf,
+ u8 req_desc_type, u8 msix_idx)
{
u32 rep;
u16 taskid;
@@ -5333,50 +6019,34 @@ static void leapraid_request_descript_handler(struct leapraid_adapter *adapter,
switch (req_desc_type) {
case LEAPRAID_RPY_DESC_FLG_FP_SCSI_IO_SUCCESS:
case LEAPRAID_RPY_DESC_FLG_SCSI_IO_SUCCESS:
- if (taskid <= adapter->shost->can_queue ||
- taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid) {
- leapraid_scsiio_done(adapter, taskid, msix_idx, 0);
- } else {
- if (leapraid_driver_cmds_done(adapter, taskid,
- msix_idx, 0,
- leapraid_get_cb_idx(adapter,
- taskid)))
- leapraid_free_taskid(adapter, taskid);
- }
+ leapraid_complete_task(adapter, taskid, msix_idx, 0);
break;
case LEAPRAID_RPY_DESC_FLG_ADDRESS_REPLY:
rep = le32_to_cpu(rpf->addr_rep.rep_frame_addr);
- if (rep > ((u32)adapter->mem_desc.rep_msg_dma +
- adapter->adapter_attr.rep_msg_qd * LEAPRAID_REPLY_SIEZ) ||
- rep < ((u32)adapter->mem_desc.rep_msg_dma))
+ if (rep > (u32)adapter->mem_desc.rep_msg_dma +
+ adapter->adapter_attr.rep_msg_qd *
+ LEAPRAID_REPLY_SIZE ||
+ rep < (u32)adapter->mem_desc.rep_msg_dma)
rep = 0;
- if (taskid) {
- if (taskid <= adapter->shost->can_queue ||
- taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid) {
- leapraid_scsiio_done(adapter, taskid,
- msix_idx, rep);
- } else {
- if (leapraid_driver_cmds_done(adapter, taskid,
- msix_idx, rep,
- leapraid_get_cb_idx(adapter,
- taskid)))
- leapraid_free_taskid(adapter, taskid);
- }
- } else {
+
+ if (taskid)
+ leapraid_complete_task(adapter, taskid, msix_idx, rep);
+ else
leapraid_handle_async_event(adapter, msix_idx, rep);
- }
- if (rep) {
- adapter->rep_msg_host_idx =
- (adapter->rep_msg_host_idx ==
- (adapter->adapter_attr.rep_msg_qd - 1)) ?
- 0 : adapter->rep_msg_host_idx + 1;
- adapter->mem_desc.rep_msg_addr[adapter->rep_msg_host_idx] =
- cpu_to_le32(rep);
- wmb(); /* Make sure that all write ops are in order */
- writel(adapter->rep_msg_host_idx,
- &adapter->iomem_base->rep_msg_host_idx);
- }
+ if (!rep)
+ return;
+
+ adapter->rep_msg_host_idx =
+ (adapter->rep_msg_host_idx ==
+ (adapter->adapter_attr.rep_msg_qd - 1)) ?
+ 0 : adapter->rep_msg_host_idx + 1;
+ adapter->mem_desc.rep_msg_addr[adapter->rep_msg_host_idx] =
+ cpu_to_le32(rep);
+ wmb(); /* Make sure that all write ops are in order */
+ writel(adapter->rep_msg_host_idx,
+ &adapter->iomem_base->rep_msg_host_idx);
+
break;
default:
break;
@@ -5438,8 +6108,8 @@ int leapraid_rep_queue_handler(struct leapraid_rq *rq)
wmb(); /* Make sure that all write ops are in order */
writel(rq->rep_post_host_idx | ((msix_idx & LEAPRAID_MSIX_GROUP_MASK) <<
LEAPRAID_RPHI_MSIX_IDX_SHIFT),
- &adapter->iomem_base->rep_post_reg_idx[msix_idx /
- LEAPRAID_MSIX_GROUP_SIZE].idx);
+ &adapter->iomem_base->rep_post_reg_idx[
+ msix_idx / LEAPRAID_MSIX_GROUP_SIZE].idx);
atomic_dec(&rq->busy);
return finish_cmds;
}
@@ -5456,7 +6126,7 @@ static irqreturn_t leapraid_irq_handler(int irq, void *bus_id)
if (adapter->mask_int)
return IRQ_NONE;
- return ((leapraid_rep_queue_handler(rq) > 0) ?
+ return (leapraid_rep_queue_handler(rq) > 0 ?
IRQ_HANDLED : IRQ_NONE);
}
@@ -5484,7 +6154,8 @@ void leapraid_sync_irqs(struct leapraid_adapter *adapter, bool poll)
if (int_rq->rq.msix_idx == 0)
continue;
- synchronize_irq(pci_irq_vector(adapter->pdev, int_rq->rq.msix_idx));
+ synchronize_irq(pci_irq_vector(adapter->pdev,
+ int_rq->rq.msix_idx));
if (poll)
leapraid_rep_queue_handler(&int_rq->rq);
}
@@ -5506,16 +6177,18 @@ void leapraid_sync_irqs(struct leapraid_adapter *adapter, bool poll)
void leapraid_mq_polling_pause(struct leapraid_adapter *adapter)
{
- int iopoll_q_count =
- adapter->adapter_attr.rq_cnt -
- adapter->notification_desc.iopoll_qdex;
+ struct leapraid_notification_desc *desc;
+ int iopoll_q_count;
int qid;
+ desc = &adapter->notification_desc;
+ iopoll_q_count = adapter->adapter_attr.rq_cnt - desc->iopoll_qdex;
+
for (qid = 0; qid < iopoll_q_count; qid++)
- atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[qid].pause, 1);
+ atomic_set(&desc->blk_mq_poll_rqs[qid].pause, 1);
for (qid = 0; qid < iopoll_q_count; qid++) {
- while (atomic_read(&adapter->notification_desc.blk_mq_poll_rqs[qid].busy)) {
+ while (atomic_read(&desc->blk_mq_poll_rqs[qid].busy)) {
cpu_relax();
udelay(LEAPRAID_IO_POLL_DELAY_US);
}
@@ -5524,19 +6197,30 @@ void leapraid_mq_polling_pause(struct leapraid_adapter *adapter)
void leapraid_mq_polling_resume(struct leapraid_adapter *adapter)
{
- int iopoll_q_count =
- adapter->adapter_attr.rq_cnt -
- adapter->notification_desc.iopoll_qdex;
+ struct leapraid_notification_desc *desc;
+ int iopoll_q_count;
int qid;
+ desc = &adapter->notification_desc;
+ iopoll_q_count = adapter->adapter_attr.rq_cnt - desc->iopoll_qdex;
+
for (qid = 0; qid < iopoll_q_count; qid++)
- atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[qid].pause, 0);
+ atomic_set(&desc->blk_mq_poll_rqs[qid].pause, 0);
}
static int leapraid_unlock_host_diag(struct leapraid_adapter *adapter,
u32 *host_diag)
{
- const u32 unlock_seq[] = { 0x0, 0xF, 0x4, 0xB, 0x2, 0x7, 0xD };
+ const u32 unlock_seq[] = {
+ LEAPRAID_WRSEQ_FLUSH_KEY_VALUE,
+ LEAPRAID_WRSEQ_1ST_KEY_VALUE,
+ LEAPRAID_WRSEQ_2ND_KEY_VALUE,
+ LEAPRAID_WRSEQ_3RD_KEY_VALUE,
+ LEAPRAID_WRSEQ_4TH_KEY_VALUE,
+ LEAPRAID_WRSEQ_5TH_KEY_VALUE,
+ LEAPRAID_WRSEQ_6TH_KEY_VALUE
+ };
+
const int max_retries = LEAPRAID_UNLOCK_RETRY_LIMIT;
int retry = 0;
unsigned int i;
@@ -5553,51 +6237,46 @@ static int leapraid_unlock_host_diag(struct leapraid_adapter *adapter,
return 0;
}
- dev_err(&adapter->pdev->dev, "try host reset timeout!\n");
+ dev_err(&adapter->pdev->dev, "Try host reset timeout!\n");
return -EFAULT;
}
static int leapraid_host_diag_reset(struct leapraid_adapter *adapter)
{
u32 host_diag;
- u32 cnt;
- dev_info(&adapter->pdev->dev, "entering host diag reset!\n");
+ dev_info(&adapter->pdev->dev, "Entering host diag reset!\n");
pci_cfg_access_lock(adapter->pdev);
mutex_lock(&adapter->reset_desc.host_diag_mutex);
if (leapraid_unlock_host_diag(adapter, &host_diag))
- goto out;
+ goto out_cleanup;
writel(host_diag | LEAPRAID_DIAG_RESET,
&adapter->iomem_base->host_diag);
+ msleep(LEAPRAID_MSLEEP_EXTRA_LONG_MS);
msleep(LEAPRAID_MSLEEP_NORMAL_MS);
- for (cnt = 0; cnt < LEAPRAID_RESET_LOOP_COUNT_DEFAULT; cnt++) {
- host_diag = leapraid_readl(&adapter->iomem_base->host_diag);
- if (host_diag == LEAPRAID_INVALID_HOST_DIAG_VAL)
- goto out;
- if (!(host_diag & LEAPRAID_DIAG_RESET))
- break;
-
- msleep(LEAPRAID_RESET_POLL_INTERVAL_MS);
- }
+ host_diag = leapraid_readl(&adapter->iomem_base->host_diag);
+ if (host_diag == LEAPRAID_INVALID_HOST_DIAG_VAL ||
+ host_diag & LEAPRAID_DIAG_RESET)
+ goto out_cleanup;
- writel(host_diag & ~LEAPRAID_DIAG_HOLD_ADAPTER_RESET,
- &adapter->iomem_base->host_diag);
writel(0x0, &adapter->iomem_base->ws);
mutex_unlock(&adapter->reset_desc.host_diag_mutex);
if (!leapraid_wait_adapter_ready(adapter))
- goto out;
+ goto out_failed;
pci_cfg_access_unlock(adapter->pdev);
- dev_info(&adapter->pdev->dev, "host diag success!\n");
+ dev_info(&adapter->pdev->dev, "Host diag success!\n");
return 0;
-out:
- pci_cfg_access_unlock(adapter->pdev);
- dev_info(&adapter->pdev->dev, "host diag failed!\n");
+
+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");
return -EFAULT;
}
@@ -5607,12 +6286,12 @@ static int leapraid_find_matching_port(
{
int i;
- for (i = 0; i < count; i++) {
+ for (i = 0; i < count; i++)
if (card_port_table[i].port_id == port_id &&
card_port_table[i].sas_address == sas_addr)
return i;
- }
- return -1;
+
+ return LEAPRAID_INVALID_INDEX;
}
static u8 leapraid_fill_card_port_table(
@@ -5626,12 +6305,13 @@ static u8 leapraid_fill_card_port_table(
int i, idx;
for (i = 0; i < adapter->dev_topo.card.phys_num; i++) {
- if ((sas_iounit_p0->phy_info[i].neg_link_rate >> 4)
- < LEAPRAID_SAS_NEG_LINK_RATE_1_5)
+ if (sas_iounit_p0->phy_info[i].neg_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT <
+ LEAPRAID_SAS_NEG_LINK_RATE_1_5)
continue;
- attached_hdl =
- le16_to_cpu(sas_iounit_p0->phy_info[i].attached_dev_hdl);
+ attached_hdl = le16_to_cpu(sas_iounit_p0->phy_info[i]
+ .attached_dev_hdl);
if (leapraid_get_sas_address(adapter,
attached_hdl,
&attached_sas_addr) != 0)
@@ -5663,7 +6343,7 @@ static u8 leapraid_set_new_card_port_table_after_reset(
{
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- struct leapraid_sas_io_unit_p0 *sas_iounit_p0 = NULL;
+ struct leapraid_sas_io_unit_p0 *sas_iounit_p0;
u8 port_entry_num = 0;
u16 sz;
@@ -5675,14 +6355,14 @@ static u8 leapraid_set_new_card_port_table_after_reset(
return port_entry_num;
cfgp1.size = sz;
- if ((leapraid_op_config_page(adapter, sas_iounit_p0, cfgp1, cfgp2,
- GET_SAS_IOUNIT_PG0)) != 0)
- goto out;
+ if (leapraid_op_config_page(adapter, sas_iounit_p0, cfgp1, cfgp2,
+ GET_SAS_IOUNIT_PG0) != 0)
+ goto out_free;
port_entry_num = leapraid_fill_card_port_table(adapter,
sas_iounit_p0,
new_card_port_table);
-out:
+out_free:
kfree(sas_iounit_p0);
return port_entry_num;
}
@@ -5691,9 +6371,9 @@ static void leapraid_update_existing_port(struct leapraid_adapter *adapter,
struct leapraid_card_port *new_table,
int entry_idx, int port_entry_num)
{
- struct leapraid_card_port *matched_card_port = NULL;
+ struct leapraid_card_port *matched_card_port;
int matched_code;
- int count = 0, lcount = 0;
+ int count, lcount = 0;
u64 sas_addr;
int i;
@@ -5714,10 +6394,10 @@ static void leapraid_update_existing_port(struct leapraid_adapter *adapter,
port_entry_num);
} else if (matched_code == SAME_ADDR_ONLY) {
sas_addr = new_table[entry_idx].sas_address;
- for (i = 0; i < port_entry_num; i++) {
+ for (i = 0; i < port_entry_num; i++)
if (new_table[i].sas_address == sas_addr)
lcount++;
- }
+
if (count > 1 || lcount > 1)
return;
@@ -5739,15 +6419,24 @@ static void leapraid_update_card_port_after_reset(
struct leapraid_adapter *adapter)
{
struct leapraid_card_port *new_card_port_table;
- struct leapraid_card_port *matched_card_port = NULL;
- u8 port_entry_num = 0;
+ struct leapraid_card_port *matched_card_port;
+ u8 port_entry_num;
u8 nr_phys;
int i;
if (leapraid_get_adapter_phys(adapter, &nr_phys) || !nr_phys)
return;
+ if (!adapter->dev_topo.card.card_phy) {
+ adapter->dev_topo.card.card_phy =
+ kcalloc(nr_phys, sizeof(struct leapraid_card_phy),
+ GFP_KERNEL);
+ if (!adapter->dev_topo.card.card_phy)
+ return;
+ }
+
adapter->dev_topo.card.phys_num = nr_phys;
+
new_card_port_table = kcalloc(adapter->dev_topo.card.phys_num,
sizeof(struct leapraid_card_port),
GFP_KERNEL);
@@ -5755,21 +6444,23 @@ static void leapraid_update_card_port_after_reset(
return;
port_entry_num =
- leapraid_set_new_card_port_table_after_reset(adapter,
- new_card_port_table);
+ leapraid_set_new_card_port_table_after_reset(
+ adapter,
+ new_card_port_table);
if (!port_entry_num)
- return;
+ goto out_free_port_table;
list_for_each_entry(matched_card_port,
- &adapter->dev_topo.card_port_list, list) {
+ &adapter->dev_topo.card_port_list, list)
matched_card_port->flg |= LEAPRAID_CARD_PORT_FLG_DIRTY;
- }
matched_card_port = NULL;
for (i = 0; i < port_entry_num; i++)
leapraid_update_existing_port(adapter,
new_card_port_table,
i, port_entry_num);
+out_free_port_table:
+ kfree(new_card_port_table);
}
static bool leapraid_is_valid_vphy(
@@ -5780,13 +6471,16 @@ static bool leapraid_is_valid_vphy(
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
struct leapraid_sas_phy_p0 phy_p0;
+ u32 dev_info;
- if ((sas_io_unit_p0->phy_info[phy_index].neg_link_rate >> 4) <
+ if (sas_io_unit_p0->phy_info[phy_index].neg_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT <
LEAPRAID_SAS_NEG_LINK_RATE_1_5)
return false;
- if (!(le32_to_cpu(sas_io_unit_p0->phy_info[phy_index].controller_phy_dev_info) &
- LEAPRAID_DEVTYP_SEP))
+ dev_info = le32_to_cpu(sas_io_unit_p0->phy_info[phy_index]
+ .controller_phy_dev_info);
+ if (!(dev_info & LEAPRAID_DEVTYP_SEP))
return false;
cfgp1.phy_number = phy_index;
@@ -5819,7 +6513,7 @@ static void leapraid_update_vphy_binding(struct leapraid_adapter *adapter,
return;
may_new_card_port->port_id = may_new_port_id;
dev_err(&adapter->pdev->dev,
- "%s: new card port %p added, port=%d\n",
+ "%s: New card port %p added, port=%d\n",
__func__, may_new_card_port, may_new_port_id);
list_add_tail(&may_new_card_port->list,
&adapter->dev_topo.card_port_list);
@@ -5835,8 +6529,10 @@ static void leapraid_update_vphy_binding(struct leapraid_adapter *adapter,
sas_dev = leapraid_get_sas_dev_by_addr(adapter,
attached_sas_addr,
card_port);
- if (sas_dev)
+ if (sas_dev) {
sas_dev->card_port = may_new_card_port;
+ leapraid_sdev_put(sas_dev);
+ }
}
if (may_new_card_port->flg & LEAPRAID_CARD_PORT_FLG_DIRTY) {
@@ -5851,7 +6547,7 @@ static void leapraid_update_vphys_after_reset(struct leapraid_adapter *adapter)
{
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- struct leapraid_sas_io_unit_p0 *sas_iounit_p0 = NULL;
+ struct leapraid_sas_io_unit_p0 *sas_iounit_p0;
struct leapraid_card_port *card_port, *card_port_next;
struct leapraid_vphy *vphy, *vphy_next;
u64 attached_sas_addr;
@@ -5867,9 +6563,8 @@ static void leapraid_update_vphys_after_reset(struct leapraid_adapter *adapter)
continue;
list_for_each_entry_safe(vphy, vphy_next,
- &card_port->vphys_list, list) {
+ &card_port->vphys_list, list)
vphy->flg |= LEAPRAID_VPHY_FLG_DIRTY;
- }
}
sz = offsetof(struct leapraid_sas_io_unit_p0, phy_info) +
@@ -5880,16 +6575,17 @@ static void leapraid_update_vphys_after_reset(struct leapraid_adapter *adapter)
return;
cfgp1.size = sz;
- if ((leapraid_op_config_page(adapter, sas_iounit_p0, cfgp1, cfgp2,
- GET_SAS_IOUNIT_PG0)) != 0)
- goto out;
+ if (leapraid_op_config_page(adapter, sas_iounit_p0, cfgp1, cfgp2,
+ GET_SAS_IOUNIT_PG0) != 0)
+ goto out_free;
for (i = 0; i < adapter->dev_topo.card.phys_num; i++) {
if (!leapraid_is_valid_vphy(adapter, sas_iounit_p0, i))
continue;
attached_hdl =
- le16_to_cpu(sas_iounit_p0->phy_info[i].attached_dev_hdl);
+ le16_to_cpu(sas_iounit_p0->phy_info[i]
+ .attached_dev_hdl);
if (leapraid_get_sas_address(adapter, attached_hdl,
&attached_sas_addr) != 0)
continue;
@@ -5931,7 +6627,7 @@ static void leapraid_update_vphys_after_reset(struct leapraid_adapter *adapter)
break;
}
}
-out:
+out_free:
kfree(sas_iounit_p0);
}
@@ -5943,17 +6639,21 @@ static void leapraid_mark_all_dev_deleted(struct leapraid_adapter *adapter)
shost_for_each_device(sdev, adapter->shost) {
sdev_priv = sdev->hostdata;
if (sdev_priv && sdev_priv->starget_priv)
- sdev_priv->starget_priv->deleted = true;
+ sdev_priv->starget_priv->deleted = 1;
}
}
static void leapraid_free_enc_list(struct leapraid_adapter *adapter)
{
struct leapraid_enc_node *enc_dev, *enc_dev_next;
+ LIST_HEAD(free_list);
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags);
+ list_splice_init(&adapter->dev_topo.enc_list, &free_list);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
- list_for_each_entry_safe(enc_dev, enc_dev_next,
- &adapter->dev_topo.enc_list,
- list) {
+ list_for_each_entry_safe(enc_dev, enc_dev_next, &free_list, list) {
list_del(&enc_dev->list);
kfree(enc_dev);
}
@@ -5966,14 +6666,14 @@ static void leapraid_rebuild_enc_list_after_reset(
union cfg_param_2 cfgp2 = {0};
struct leapraid_enc_node *enc_node;
u16 enc_hdl;
+ unsigned long flags;
int rc;
leapraid_free_enc_list(adapter);
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (enc_hdl = 0xFFFF; ; enc_hdl = le16_to_cpu(enc_node->pg0.enc_hdl)) {
- enc_node = kzalloc(sizeof(*enc_node),
- GFP_KERNEL);
+ enc_node = kzalloc(sizeof(*enc_node), GFP_KERNEL);
if (!enc_node)
return;
@@ -5985,91 +6685,102 @@ static void leapraid_rebuild_enc_list_after_reset(
return;
}
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags);
list_add_tail(&enc_node->list, &adapter->dev_topo.enc_list);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
}
}
static void leapraid_mark_resp_sas_dev(struct leapraid_adapter *adapter,
struct leapraid_sas_dev_p0 *sas_dev_p0)
{
- struct leapraid_starget_priv *starget_priv = NULL;
+ struct leapraid_starget_priv *starget_priv;
struct leapraid_enc_node *enc_node = NULL;
struct leapraid_card_port *card_port;
struct leapraid_sas_dev *sas_dev;
struct scsi_target *starget;
unsigned long flags;
+ unsigned long enc_flags = 0;
+ u16 enc_hdl;
+ u64 enc_lid = 0;
card_port = leapraid_get_port_by_id(adapter, sas_dev_p0->physical_port,
false);
- if (sas_dev_p0->enc_hdl) {
- enc_node = leapraid_enc_find_by_hdl(adapter,
- le16_to_cpu(
- sas_dev_p0->enc_hdl));
+ enc_hdl = le16_to_cpu(sas_dev_p0->enc_hdl);
+ if (enc_hdl) {
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, enc_flags);
+ enc_node = leapraid_enc_find_by_hdl(adapter, enc_hdl);
+ if (enc_node)
+ enc_lid = le64_to_cpu(enc_node->pg0.enc_lid);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, enc_flags);
if (!enc_node)
dev_info(&adapter->pdev->dev,
"enc hdl 0x%04x has no matched enc dev\n",
- le16_to_cpu(sas_dev_p0->enc_hdl));
+ enc_hdl);
}
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
list_for_each_entry(sas_dev, &adapter->dev_topo.sas_dev_list, list) {
- if (sas_dev->sas_addr == le64_to_cpu(sas_dev_p0->sas_address) &&
- sas_dev->slot == le16_to_cpu(sas_dev_p0->slot) &&
- sas_dev->card_port == card_port) {
- sas_dev->resp = true;
- starget = sas_dev->starget;
- if (starget && starget->hostdata) {
- starget_priv = starget->hostdata;
- starget_priv->tm_busy = false;
- starget_priv->deleted = false;
- } else {
- starget_priv = NULL;
- }
+ if (sas_dev->sas_addr != le64_to_cpu(sas_dev_p0->sas_address) ||
+ sas_dev->slot != le16_to_cpu(sas_dev_p0->slot) ||
+ sas_dev->card_port != card_port)
+ continue;
+
+ sas_dev->resp = 1;
+ starget = sas_dev->starget;
+ if (starget && starget->hostdata) {
+ starget_priv = starget->hostdata;
+ starget_priv->tm_busy = 0;
+ starget_priv->deleted = 0;
+ } else {
+ starget_priv = NULL;
+ }
+
+ if (starget) {
+ starget_printk(
+ KERN_INFO, starget,
+ "dev: hdl=0x%04x saddr=0x%016llx port_id=%d\n",
+ sas_dev->hdl,
+ (unsigned long long)sas_dev->sas_addr,
+ sas_dev->card_port->port_id);
+ if (sas_dev->enc_hdl != 0)
+ starget_printk(
+ KERN_INFO,
+ starget,
+ "enc info: enc_lid=0x%016llx slot=%d\n",
+ (unsigned long long)sas_dev->enc_lid,
+ sas_dev->slot);
+ }
+
+ if (le16_to_cpu(sas_dev_p0->flg) &
+ LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID) {
+ sas_dev->enc_level = sas_dev_p0->enc_level;
+ memcpy(sas_dev->connector_name,
+ sas_dev_p0->connector_name,
+ LEAPRAID_SAS_DEV_P0_CON_NAME_LEN);
+ sas_dev->connector_name[
+ LEAPRAID_SAS_DEV_P0_CON_NAME_LEN] = '\0';
+ } else {
+ sas_dev->enc_level = 0;
+ sas_dev->connector_name[0] = '\0';
+ }
- if (starget) {
- starget_printk(KERN_INFO, starget,
- "dev: hdl=0x%04x, sas addr=0x%016llx, port_id=%d\n",
- sas_dev->hdl,
- (unsigned long long)sas_dev->sas_addr,
- sas_dev->card_port->port_id);
- if (sas_dev->enc_hdl != 0)
- starget_printk(KERN_INFO, starget,
- "enc info: enc_lid=0x%016llx, slot=%d\n",
- (unsigned long long)sas_dev->enc_lid,
- sas_dev->slot);
- }
+ sas_dev->enc_hdl = enc_hdl;
+ sas_dev->enc_lid = enc_lid;
- if (le16_to_cpu(sas_dev_p0->flg) &
- LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID) {
- sas_dev->enc_level = sas_dev_p0->enc_level;
- memcpy(sas_dev->connector_name,
- sas_dev_p0->connector_name, 4);
- sas_dev->connector_name[4] = '\0';
- } else {
- sas_dev->enc_level = 0;
- sas_dev->connector_name[0] = '\0';
- }
+ if (sas_dev->hdl == le16_to_cpu(sas_dev_p0->dev_hdl))
+ goto unlock;
- sas_dev->enc_hdl =
- le16_to_cpu(sas_dev_p0->enc_hdl);
- if (enc_node) {
- sas_dev->enc_lid =
- le64_to_cpu(enc_node->pg0.enc_lid);
- }
- if (sas_dev->hdl == le16_to_cpu(sas_dev_p0->dev_hdl))
- goto out;
+ dev_info(&adapter->pdev->dev,
+ "hdl changed: 0x%04x -> 0x%04x\n",
+ sas_dev->hdl, sas_dev_p0->dev_hdl);
+ sas_dev->hdl = le16_to_cpu(sas_dev_p0->dev_hdl);
+ if (starget_priv)
+ starget_priv->hdl = le16_to_cpu(sas_dev_p0->dev_hdl);
- dev_info(&adapter->pdev->dev,
- "hdl changed: 0x%04x -> 0x%04x\n",
- sas_dev->hdl, sas_dev_p0->dev_hdl);
- sas_dev->hdl = le16_to_cpu(sas_dev_p0->dev_hdl);
- if (starget_priv)
- starget_priv->hdl =
- le16_to_cpu(sas_dev_p0->dev_hdl);
- goto out;
- }
+ goto unlock;
}
-out:
+unlock:
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
}
@@ -6081,10 +6792,10 @@ static void leapraid_search_resp_sas_dev(struct leapraid_adapter *adapter)
u32 device_info;
dev_info(&adapter->pdev->dev,
- "begin searching for sas end devices\n");
+ "Begin searching for SAS end devices\n");
if (list_empty(&adapter->dev_topo.sas_dev_list))
- goto out;
+ goto exit_search;
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (cfgp2.handle = 0xFFFF;
@@ -6097,63 +6808,58 @@ static void leapraid_search_resp_sas_dev(struct leapraid_adapter *adapter)
leapraid_mark_resp_sas_dev(adapter, &sas_dev_p0);
}
-out:
+exit_search:
dev_info(&adapter->pdev->dev,
- "sas end devices searching complete\n");
+ "SAS end devices searching complete\n");
}
static void leapraid_mark_resp_raid_volume(struct leapraid_adapter *adapter,
u64 wwid, u16 hdl)
{
- struct leapraid_starget_priv *starget_priv;
struct leapraid_raid_volume *raid_volume;
+ struct leapraid_starget_priv *starget_priv = NULL;
struct scsi_target *starget;
unsigned long flags;
+ u64 volume_wwid;
+ u16 old_hdl;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
- list_for_each_entry(raid_volume,
- &adapter->dev_topo.raid_volume_list, list) {
- if (raid_volume->wwid == wwid && raid_volume->starget) {
- starget = raid_volume->starget;
- if (starget && starget->hostdata) {
- starget_priv = starget->hostdata;
- starget_priv->deleted = false;
- } else {
- starget_priv = NULL;
- }
-
- raid_volume->resp = true;
- spin_unlock_irqrestore(
- &adapter->dev_topo.raid_volume_lock,
- flags);
+ raid_volume = leapraid_raid_volume_find_by_wwid(adapter, wwid);
+ if (!raid_volume)
+ return;
- starget_printk(
- KERN_INFO, raid_volume->starget,
- "raid volume: hdl=0x%04x, wwid=0x%016llx\n",
- hdl, (unsigned long long)raid_volume->wwid);
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock,
- flags);
- if (raid_volume->hdl == hdl) {
- spin_unlock_irqrestore(
- &adapter->dev_topo.raid_volume_lock,
- flags);
- return;
- }
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ if (!raid_volume->starget) {
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
+ flags);
+ leapraid_raid_volume_put(raid_volume);
+ return;
+ }
- dev_info(&adapter->pdev->dev,
- "hdl changed: 0x%04x -> 0x%04x\n",
- raid_volume->hdl, hdl);
+ starget = raid_volume->starget;
+ if (starget->hostdata) {
+ starget_priv = starget->hostdata;
+ starget_priv->deleted = 0;
+ }
- raid_volume->hdl = hdl;
- if (starget_priv)
- starget_priv->hdl = hdl;
- spin_unlock_irqrestore(
- &adapter->dev_topo.raid_volume_lock,
- flags);
- return;
- }
+ raid_volume->resp = 1;
+ volume_wwid = raid_volume->wwid;
+ old_hdl = raid_volume->hdl;
+ if (old_hdl != hdl) {
+ raid_volume->hdl = hdl;
+ if (starget_priv)
+ starget_priv->hdl = hdl;
}
spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+
+ starget_printk(KERN_INFO, starget,
+ "raid volume: hdl=0x%04x, wwid=0x%016llx\n",
+ hdl, (unsigned long long)volume_wwid);
+ if (old_hdl != hdl)
+ dev_info(&adapter->pdev->dev,
+ "hdl changed: 0x%04x -> 0x%04x\n",
+ old_hdl, hdl);
+
+ leapraid_raid_volume_put(raid_volume);
}
static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter)
@@ -6165,17 +6871,22 @@ static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter)
struct leapraid_raidvol_p1 raidvol_p1;
struct leapraid_raidvol_p0 raidvol_p0;
struct leapraid_raidpd_p0 raidpd_p0;
+ unsigned long flags;
u16 hdl;
u8 phys_disk_num;
+ bool is_empty;
if (!adapter->adapter_attr.raid_support)
return;
dev_info(&adapter->pdev->dev,
- "begin searching for raid volumes\n");
+ "Begin searching for RAID volumes\n");
- if (list_empty(&adapter->dev_topo.raid_volume_list))
- goto out;
+ 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;
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
@@ -6206,11 +6917,16 @@ static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter)
cfgp2.form_specific = phys_disk_num) {
phys_disk_num = raidpd_p0.phys_disk_num;
hdl = le16_to_cpu(raidpd_p0.dev_hdl);
- set_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls);
+ if (!hdl ||
+ hdl > adapter->adapter_attr.features.max_dev_handle)
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid device handle\n", __func__);
+ else
+ set_bit(hdl, adapter->dev_topo.pd_hdls);
}
-out:
+exit_search:
dev_info(&adapter->pdev->dev,
- "raid volumes searching complete\n");
+ "RAID volumes searching complete\n");
}
static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter,
@@ -6226,10 +6942,17 @@ static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter,
port_id,
false);
unsigned long flags;
+ unsigned long enc_flags = 0;
+ u64 enc_lid = 0;
int i;
- if (enc_hdl)
+ if (enc_hdl) {
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, enc_flags);
enc_node = leapraid_enc_find_by_hdl(adapter, enc_hdl);
+ if (enc_node)
+ enc_lid = le64_to_cpu(enc_node->pg0.enc_lid);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, enc_flags);
+ }
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
list_for_each_entry(topo_node_exp, &adapter->dev_topo.exp_list, list) {
@@ -6237,14 +6960,11 @@ static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter,
topo_node_exp->card_port != card_port)
continue;
- topo_node_exp->resp = true;
- if (enc_node) {
- topo_node_exp->enc_lid =
- le64_to_cpu(enc_node->pg0.enc_lid);
- topo_node_exp->enc_hdl = le16_to_cpu(exp_pg0->enc_hdl);
- }
+ topo_node_exp->resp = 1;
+ topo_node_exp->enc_hdl = enc_hdl;
+ topo_node_exp->enc_lid = enc_lid;
if (topo_node_exp->hdl == hdl)
- goto out;
+ goto unlock;
dev_info(&adapter->pdev->dev,
"hdl changed: 0x%04x -> 0x%04x\n",
@@ -6252,9 +6972,9 @@ static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter,
topo_node_exp->hdl = hdl;
for (i = 0; i < topo_node_exp->phys_num; i++)
topo_node_exp->card_phy[i].hdl = hdl;
- goto out;
+ goto unlock;
}
-out:
+unlock:
spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
}
@@ -6267,10 +6987,10 @@ static void leapraid_search_resp_exp(struct leapraid_adapter *adapter)
u16 hdl;
u8 port;
- dev_info(&adapter->pdev->dev,
- "begin searching for expanders\n");
+ dev_dbg(&adapter->pdev->dev,
+ "Begin searching for expanders\n");
if (list_empty(&adapter->dev_topo.exp_list))
- goto out;
+ goto exit_search;
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
@@ -6281,16 +7001,16 @@ static void leapraid_search_resp_exp(struct leapraid_adapter *adapter)
sas_address = le64_to_cpu(exp_p0.sas_address);
port = exp_p0.physical_port;
- dev_info(&adapter->pdev->dev,
- "exp detected: hdl=0x%04x, sas=0x%016llx, port=%u",
- hdl, (unsigned long long)sas_address,
- ((adapter->adapter_attr.enable_mp) ? (port) :
- (LEAPRAID_DISABLE_MP_PORT_ID)));
+ dev_dbg(&adapter->pdev->dev,
+ "exp detected: hdl=0x%04x, sas=0x%016llx, port=%u",
+ hdl, (unsigned long long)sas_address,
+ adapter->adapter_attr.enable_mp ? port :
+ LEAPRAID_DISABLE_MP_PORT_ID);
leapraid_mark_resp_exp(adapter, &exp_p0);
}
-out:
- dev_info(&adapter->pdev->dev,
- "expander searching complete\n");
+exit_search:
+ dev_dbg(&adapter->pdev->dev,
+ "Expander searching complete\n");
}
void leapraid_wait_cmds_done(struct leapraid_adapter *adapter)
@@ -6302,7 +7022,7 @@ void leapraid_wait_cmds_done(struct leapraid_adapter *adapter)
adapter->reset_desc.pending_io_cnt = 0;
if (!leapraid_pci_active(adapter)) {
dev_err(&adapter->pdev->dev,
- "%s %s: pci error, device reset or unplugged!\n",
+ "%s %s: PCI error, device reset or unplugged!\n",
adapter->adapter_attr.name, __func__);
return;
}
@@ -6314,9 +7034,9 @@ void leapraid_wait_cmds_done(struct leapraid_adapter *adapter)
for (i = 1; i <= adapter->shost->can_queue; i++) {
io_req_tracker = leapraid_get_io_tracker_from_taskid(adapter,
i);
- if (io_req_tracker && io_req_tracker->taskid != 0)
- if (io_req_tracker->scmd)
- adapter->reset_desc.pending_io_cnt++;
+ if (io_req_tracker && io_req_tracker->taskid != 0 &&
+ io_req_tracker->scmd)
+ adapter->reset_desc.pending_io_cnt++;
}
spin_unlock_irqrestore(&adapter->dynamic_task_desc.task_lock, flags);
@@ -6324,38 +7044,37 @@ void leapraid_wait_cmds_done(struct leapraid_adapter *adapter)
return;
wait_event_timeout(adapter->reset_desc.reset_wait_queue,
- adapter->reset_desc.pending_io_cnt == 0, 10 * HZ);
+ adapter->reset_desc.pending_io_cnt == 0,
+ LEAPRAID_IO_CMD_TIMEOUT * HZ);
}
int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
enum reset_type type)
{
unsigned long flags;
+ bool wake = false;
int rc;
- if (!mutex_trylock(&adapter->reset_desc.adapter_reset_mutex)) {
- do {
- ssleep(1);
- } while (adapter->access_ctrl.shost_recovering);
- return adapter->reset_desc.adapter_reset_results;
- }
+ mutex_lock(&adapter->reset_desc.adapter_reset_mutex);
if (!leapraid_pci_active(adapter)) {
if (leapraid_pci_removed(adapter)) {
dev_info(&adapter->pdev->dev,
- "pci_dev removed, pausing polling and cleaning cmds\n");
+ "pci_dev removed, pause poll, clean cmds\n");
leapraid_mq_polling_pause(adapter);
leapraid_clean_active_scsi_cmds(adapter);
leapraid_mq_polling_resume(adapter);
}
- rc = 0;
- goto exit_pci_unavailable;
+ dev_err(&adapter->pdev->dev, "PCIe unavailable!\n");
+ mutex_unlock(&adapter->reset_desc.adapter_reset_mutex);
+ return -ENXIO;
}
- dev_info(&adapter->pdev->dev, "starting hard reset\n");
+ dev_info(&adapter->pdev->dev, "Starting hard reset\n");
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
- adapter->access_ctrl.shost_recovering = true;
+ adapter->access_ctrl.shost_recovering = 1;
+ adapter->access_ctrl.shost_recover_async = 1;
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
leapraid_wait_cmds_done(adapter);
@@ -6364,14 +7083,14 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
rc = leapraid_make_adapter_ready(adapter, type);
if (rc) {
dev_err(&adapter->pdev->dev,
- "failed to make adapter ready, rc=%d\n", rc);
- goto out;
+ "Failed to make adapter ready, rc=%d\n", rc);
+ goto out_cleanup;
}
rc = leapraid_fw_log_init(adapter);
if (rc) {
- dev_err(&adapter->pdev->dev, "firmware log init failed\n");
- goto out;
+ dev_err(&adapter->pdev->dev, "Firmware log init failed\n");
+ goto out_cleanup;
}
leapraid_clean_active_cmds(adapter);
@@ -6379,15 +7098,16 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
adapter->scan_dev_desc.scan_dev_failed) {
dev_err(&adapter->pdev->dev,
"Previous device scan failed or driver loading\n");
- adapter->access_ctrl.host_removing = true;
+ adapter->access_ctrl.host_removing = 1;
+ wake_up(&adapter->access_ctrl.recovery_waitq);
rc = -EFAULT;
- goto out;
+ goto out_cleanup;
}
rc = leapraid_make_adapter_available(adapter);
if (!rc) {
dev_info(&adapter->pdev->dev,
- "adapter is now available, rebuilding topology\n");
+ "Adapter is now available, rebuilding topology\n");
if (adapter->adapter_attr.enable_mp) {
leapraid_update_card_port_after_reset(adapter);
leapraid_update_vphys_after_reset(adapter);
@@ -6399,14 +7119,22 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
leapraid_search_resp_exp(adapter);
leapraid_hardreset_barrier(adapter);
}
-out:
- dev_info(&adapter->pdev->dev, "hard reset %s\n",
- ((rc == 0) ? "SUCCESS" : "FAILED"));
+out_cleanup:
+ dev_info(&adapter->pdev->dev, "Hard reset %s\n",
+ rc == 0 ? "SUCCESS" : "FAILED");
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
adapter->reset_desc.adapter_reset_results = rc;
- adapter->access_ctrl.shost_recovering = false;
+ adapter->access_ctrl.shost_recovering = 0;
+ wake_up(&adapter->access_ctrl.recovery_waitq);
+ if (rc) {
+ adapter->access_ctrl.shost_recover_async = 0;
+ wake = true;
+ }
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
+ if (wake)
+ wake_up(&adapter->access_ctrl.shost_recover_wq);
+
adapter->reset_desc.reset_cnt++;
mutex_unlock(&adapter->reset_desc.adapter_reset_mutex);
@@ -6414,8 +7142,6 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
leapraid_clean_active_scsi_cmds(adapter);
leapraid_mq_polling_resume(adapter);
-exit_pci_unavailable:
- dev_info(&adapter->pdev->dev, "pcie unavailable!\n");
return rc;
}
@@ -6424,31 +7150,40 @@ static int leapraid_get_adapter_features(struct leapraid_adapter *adapter)
struct leapraid_adapter_features_req leap_mpi_req;
struct leapraid_adapter_features_rep leap_mpi_rep;
u8 fw_major, fw_minor, fw_build, fw_release;
+ u32 req_sz;
+ u32 rep_sz;
u32 db;
int r;
db = leapraid_readl(&adapter->iomem_base->db);
if (db & LEAPRAID_DB_USED ||
- (db & LEAPRAID_DB_MASK) == LEAPRAID_DB_FAULT)
+ (db & LEAPRAID_DB_MASK) == LEAPRAID_DB_FAULT) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Doorbell used or fault\n", __func__);
return -EFAULT;
+ }
- if (((db & LEAPRAID_DB_MASK) != LEAPRAID_DB_READY) &&
- ((db & LEAPRAID_DB_MASK) != LEAPRAID_DB_OPERATIONAL)) {
- if (!leapraid_wait_adapter_ready(adapter))
- return -EFAULT;
+ if ((db & LEAPRAID_DB_MASK) != LEAPRAID_DB_READY &&
+ (db & LEAPRAID_DB_MASK) != LEAPRAID_DB_OPERATIONAL &&
+ !leapraid_wait_adapter_ready(adapter)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: adapter not ready\n", __func__);
+ return -EFAULT;
}
- memset(&leap_mpi_req, 0, sizeof(struct leapraid_adapter_features_req));
- memset(&leap_mpi_rep, 0, sizeof(struct leapraid_adapter_features_rep));
+ req_sz = sizeof(struct leapraid_adapter_features_req);
+ rep_sz = sizeof(struct leapraid_adapter_features_rep);
+ memset(&leap_mpi_req, 0, req_sz);
+ memset(&leap_mpi_rep, 0, rep_sz);
leap_mpi_req.func = LEAPRAID_FUNC_GET_ADAPTER_FEATURES;
r = leapraid_handshake_func(adapter,
- sizeof(struct leapraid_adapter_features_req),
+ req_sz,
(u32 *)&leap_mpi_req,
- sizeof(struct leapraid_adapter_features_rep),
+ rep_sz,
(u16 *)&leap_mpi_rep);
if (r) {
dev_err(&adapter->pdev->dev,
- "%s %s: handshake failed, r=%d\n",
+ "%s %s: Handshake failed, r=%d\n",
adapter->adapter_attr.name, __func__, r);
return r;
}
@@ -6475,19 +7210,43 @@ static int leapraid_get_adapter_features(struct leapraid_adapter *adapter)
LEAPRAID_MAX_DEV_HANDLE_DEFAULT;
adapter->adapter_attr.features.min_dev_handle =
le16_to_cpu(leap_mpi_rep.min_dev_hdl);
- if ((adapter->adapter_attr.features.adapter_caps &
- LEAPRAID_ADAPTER_FEATURES_CAP_INTEGRATED_RAID))
- adapter->adapter_attr.raid_support = true;
+ if (adapter->adapter_attr.features.adapter_caps &
+ LEAPRAID_ADAPTER_FEATURES_CAP_INTEGRATED_RAID)
+ adapter->adapter_attr.raid_support = 1;
+ adapter->adapter_attr.wideport_max_queue_depth =
+ le16_to_cpu(leap_mpi_rep.sas_wide_max_qdepth) ?
+ le16_to_cpu(leap_mpi_rep.sas_wide_max_qdepth) :
+ LEAPRAID_SAS_QUEUE_DEPTH;
+ adapter->adapter_attr.narrowport_max_queue_depth =
+ le16_to_cpu(leap_mpi_rep.sas_narrow_max_qdepth) ?
+ le16_to_cpu(leap_mpi_rep.sas_narrow_max_qdepth) :
+ LEAPRAID_SAS_QUEUE_DEPTH;
+ adapter->adapter_attr.sata_max_queue_depth =
+ leap_mpi_rep.sata_max_qdepth ?
+ leap_mpi_rep.sata_max_qdepth :
+ LEAPRAID_SATA_QUEUE_DEPTH;
+ adapter->adapter_attr.raid_volume_max_queue_depth =
+ LEAPRAID_RAID_QUEUE_DEPTH;
+ dev_info(&adapter->pdev->dev,
+ "max: wp qd=%d, np qd=%d, SATA qd=%d, raid qd=%d\n",
+ adapter->adapter_attr.wideport_max_queue_depth,
+ adapter->adapter_attr.narrowport_max_queue_depth,
+ adapter->adapter_attr.sata_max_queue_depth,
+ adapter->adapter_attr.raid_volume_max_queue_depth);
if (WARN_ON(!(adapter->adapter_attr.features.adapter_caps &
LEAPRAID_ADAPTER_FEATURES_CAP_ATOMIC_REQ)))
return -EFAULT;
adapter->adapter_attr.features.fw_version =
le32_to_cpu(leap_mpi_rep.fw_version);
- fw_major = (adapter->adapter_attr.features.fw_version >> 24) & 0xFF;
- fw_minor = (adapter->adapter_attr.features.fw_version >> 16) & 0xFF;
- fw_build = (adapter->adapter_attr.features.fw_version >> 8) & 0xFF;
- fw_release = adapter->adapter_attr.features.fw_version & 0xFF;
+ fw_major = (adapter->adapter_attr.features.fw_version >>
+ LEAPRAID_VER_MAJOR_SHIFT) & LEAPRAID_VER_MASK;
+ fw_minor = (adapter->adapter_attr.features.fw_version >>
+ LEAPRAID_VER_MINOR_SHIFT) & LEAPRAID_VER_MASK;
+ fw_build = (adapter->adapter_attr.features.fw_version >>
+ LEAPRAID_VER_BUILD_SHIFT) & LEAPRAID_VER_MASK;
+ fw_release =
+ adapter->adapter_attr.features.fw_version & LEAPRAID_VER_MASK;
dev_info(&adapter->pdev->dev,
"Firmware version: %u.%u.%u.%u (0x%08x)\n",
@@ -6499,7 +7258,7 @@ static int leapraid_get_adapter_features(struct leapraid_adapter *adapter)
"Unsupported firmware major version, requires >= 2\n");
return -EFAULT;
}
- adapter->shost->max_id = -1;
+ adapter->shost->max_id = LEAPRAID_INVALID_INITIAL_VALUE;
return 0;
}
@@ -6525,53 +7284,49 @@ static int leapraid_enable_pcie(struct leapraid_adapter *adapter)
rc = pci_enable_device(adapter->pdev);
if (rc) {
- dev_err(&adapter->pdev->dev, "failed to enable PCI device\n");
+ dev_err(&adapter->pdev->dev, "Failed to enable PCI device\n");
return rc;
}
rc = pci_request_regions(adapter->pdev, LEAPRAID_DRIVER_NAME);
if (rc) {
dev_err(&adapter->pdev->dev,
- "failed to obtain PCI resources\n");
- goto disable_pcie;
+ "Failed to obtain PCI resources\n");
+ return rc;
}
if (sizeof(dma_addr_t) > 4) {
- dma_mask = DMA_BIT_MASK(64);
- adapter->adapter_attr.use_32_dma_mask = false;
+ dma_mask = DMA_BIT_MASK(DMA_64_BITS);
+ adapter->adapter_attr.use_32_dma_mask = 0;
} else {
- dma_mask = DMA_BIT_MASK(32);
- adapter->adapter_attr.use_32_dma_mask = true;
+ dma_mask = DMA_BIT_MASK(DMA_32_BITS);
+ adapter->adapter_attr.use_32_dma_mask = 1;
}
rc = dma_set_mask_and_coherent(&adapter->pdev->dev, dma_mask);
if (rc) {
dev_err(&adapter->pdev->dev,
- "failed to set %lld DMA mask\n", dma_mask);
- goto disable_pcie;
+ "Failed to set %lld DMA mask\n", dma_mask);
+ return rc;
}
adapter->iomem_base = ioremap(pci_resource_start(adapter->pdev, 0),
sizeof(struct leapraid_reg_base));
if (!adapter->iomem_base) {
dev_err(&adapter->pdev->dev,
- "failed to map memory for controller registers\n");
- rc = -ENOMEM;
- goto disable_pcie;
+ "Failed to map memory for controller registers\n");
+ return -ENOMEM;
}
pci_set_master(adapter->pdev);
return 0;
-
-disable_pcie:
- return rc;
}
static void leapraid_cpus_on_irq(struct leapraid_adapter *adapter)
{
struct leapraid_int_rq *int_rq;
unsigned int i, base_group, this_group;
- unsigned int cpu, nr_cpus, total_msix, index = 0;
+ unsigned int cpu, nr_cpus, total_msix, index;
total_msix = adapter->notification_desc.iopoll_qdex;
nr_cpus = num_online_cpus();
@@ -6613,8 +7368,12 @@ static void leapraid_map_msix_to_cpu(struct leapraid_adapter *adapter)
int_rq = &adapter->notification_desc.int_rqs[i];
affinity_mask = pci_irq_get_affinity(adapter->pdev,
int_rq->rq.msix_idx);
- if (!affinity_mask)
- goto out;
+ if (!affinity_mask) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: IRQ affinity NULL, msix_idx=%d\n",
+ __func__, int_rq->rq.msix_idx);
+ goto out_apply_irq_affinity;
+ }
for_each_cpu_and(cpu, affinity_mask, cpu_online_mask) {
if (cpu >= adapter->notification_desc.msix_cpu_map_sz)
@@ -6624,7 +7383,7 @@ static void leapraid_map_msix_to_cpu(struct leapraid_adapter *adapter)
int_rq->rq.msix_idx;
}
}
-out:
+out_apply_irq_affinity:
leapraid_cpus_on_irq(adapter);
}
@@ -6641,27 +7400,26 @@ static void leapraid_free_irq(struct leapraid_adapter *adapter)
{
struct leapraid_int_rq *int_rq;
unsigned int i;
+ int irq;
- if (!adapter->notification_desc.int_rqs)
- return;
-
- for (i = 0; i < adapter->notification_desc.int_rqs_allocated; i++) {
+ for (i = 0; adapter->notification_desc.int_rqs &&
+ i < adapter->notification_desc.int_rqs_allocated; i++) {
int_rq = &adapter->notification_desc.int_rqs[i];
if (!int_rq)
continue;
- irq_set_affinity_hint(pci_irq_vector(adapter->pdev,
- int_rq->rq.msix_idx), NULL);
- free_irq(pci_irq_vector(adapter->pdev, int_rq->rq.msix_idx),
- &int_rq->rq);
+ irq = pci_irq_vector(adapter->pdev, int_rq->rq.msix_idx);
+ irq_set_affinity_hint(irq, NULL);
+ free_irq(irq, &int_rq->rq);
}
adapter->notification_desc.int_rqs_allocated = 0;
- if (!adapter->notification_desc.msix_enable)
- return;
+ if (adapter->notification_desc.irq_vectors_allocated) {
+ pci_free_irq_vectors(adapter->pdev);
+ adapter->notification_desc.irq_vectors_allocated = 0;
+ }
- pci_free_irq_vectors(adapter->pdev);
- adapter->notification_desc.msix_enable = false;
+ adapter->notification_desc.msix_enable = 0;
kfree(adapter->notification_desc.blk_mq_poll_rqs);
adapter->notification_desc.blk_mq_poll_rqs = NULL;
@@ -6671,16 +7429,9 @@ static void leapraid_free_irq(struct leapraid_adapter *adapter)
kfree(adapter->notification_desc.msix_cpu_map);
adapter->notification_desc.msix_cpu_map = NULL;
-}
-
-static inline int leapraid_msix_cnt(struct pci_dev *pdev)
-{
- return pci_msix_vec_count(pdev);
-}
-
-static inline int leapraid_msi_cnt(struct pci_dev *pdev)
-{
- return pci_msi_vec_count(pdev);
+ adapter->notification_desc.msix_cpu_map_sz = 0;
+ adapter->notification_desc.iopoll_qdex = 0;
+ adapter->notification_desc.iopoll_qcnt = 0;
}
static int leapraid_setup_irqs(struct leapraid_adapter *adapter)
@@ -6688,7 +7439,7 @@ static int leapraid_setup_irqs(struct leapraid_adapter *adapter)
unsigned int i;
int rc = 0;
- if (interrupt_mode == 0) {
+ if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX) {
rc = pci_alloc_irq_vectors_affinity(
adapter->pdev,
adapter->notification_desc.iopoll_qdex,
@@ -6697,22 +7448,26 @@ static int leapraid_setup_irqs(struct leapraid_adapter *adapter)
if (rc < 0) {
dev_err(&adapter->pdev->dev,
- "%d msi/msix vectors alloacted failed!\n",
+ "%d MSI/MSIX vectors allocated failed!\n",
adapter->notification_desc.iopoll_qdex);
return rc;
}
+
+ 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 == 0)
+ if (interrupt_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 == 1)
+ else if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSI)
snprintf(adapter->notification_desc.int_rqs[i].rq.name,
LEAPRAID_NAME_LENGTH, "%s%u-MSI%u",
LEAPRAID_DRIVER_NAME,
@@ -6723,6 +7478,7 @@ 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",
@@ -6754,10 +7510,12 @@ static int leapraid_setup_legacy_int(struct leapraid_adapter *adapter)
NULL);
if (rc < 0) {
dev_err(&adapter->pdev->dev,
- "legacy irq alloacted failed!\n");
+ "Legacy irq allocated failed!\n");
return rc;
}
+ adapter->notification_desc.irq_vectors_allocated = 1;
+ adapter->notification_desc.irq_mode = LEAPRAID_INTERRUPT_MODE_LEGACY;
rc = request_irq(pci_irq_vector(adapter->pdev, 0),
leapraid_irq_handler,
IRQF_SHARED,
@@ -6766,8 +7524,9 @@ static int leapraid_setup_legacy_int(struct leapraid_adapter *adapter)
if (rc) {
irq_set_affinity_hint(pci_irq_vector(adapter->pdev, 0), NULL);
pci_free_irq_vectors(adapter->pdev);
+ adapter->notification_desc.irq_vectors_allocated = 0;
dev_err(&adapter->pdev->dev,
- "Legact Int: request_irq %s failed!\n",
+ "Legacy Int: request_irq %s failed!\n",
adapter->notification_desc.int_rqs[0].rq.name);
return -EBUSY;
}
@@ -6781,8 +7540,8 @@ static int leapraid_set_legacy_int(struct leapraid_adapter *adapter)
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);
+ kzalloc(adapter->notification_desc.msix_cpu_map_sz,
+ GFP_KERNEL);
if (!adapter->notification_desc.msix_cpu_map)
return -ENOMEM;
@@ -6791,19 +7550,15 @@ static int leapraid_set_legacy_int(struct leapraid_adapter *adapter)
adapter->adapter_attr.rq_cnt;
adapter->notification_desc.iopoll_qcnt = 0;
dev_info(&adapter->pdev->dev,
- "Legacy Intr: req queue cnt=%d, intr=%d/poll=%d rep queues!\n",
+ "Legacy Intr: req queue cnt=%d intr=%d/poll=%d rep queues!\n",
adapter->adapter_attr.rq_cnt,
adapter->notification_desc.iopoll_qdex,
adapter->notification_desc.iopoll_qcnt);
adapter->notification_desc.int_rqs =
kcalloc(adapter->notification_desc.iopoll_qdex,
sizeof(struct leapraid_int_rq), GFP_KERNEL);
- if (!adapter->notification_desc.int_rqs) {
- dev_err(&adapter->pdev->dev,
- "Legacy Intr: allocate %d intr rep queues failed!\n",
- adapter->notification_desc.iopoll_qdex);
+ if (!adapter->notification_desc.int_rqs)
return -ENOMEM;
- }
rc = leapraid_setup_legacy_int(adapter);
@@ -6817,13 +7572,13 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter)
int rc, msix_cnt;
if (msix_disable == 1)
- goto legacy_int;
+ goto apply_legacy_int;
- msix_cnt = leapraid_msix_cnt(adapter->pdev);
+ 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 legacy_int;
+ dev_info(&adapter->pdev->dev, "MSIX unsupported!\n");
+ goto apply_legacy_int;
}
msix_cnt = min_t(int, msix_cnt,
@@ -6872,25 +7627,25 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter)
adapter->notification_desc.int_rqs =
kcalloc(adapter->notification_desc.iopoll_qdex,
sizeof(struct leapraid_int_rq), GFP_KERNEL);
- if (!adapter->notification_desc.int_rqs) {
- dev_err(&adapter->pdev->dev,
- "MSIx: allocate %d interrupt reply queues failed!\n",
- adapter->notification_desc.iopoll_qdex);
+ if (!adapter->notification_desc.int_rqs)
return -ENOMEM;
- }
for (i = 0; i < adapter->notification_desc.iopoll_qcnt; i++) {
adapter->notification_desc.blk_mq_poll_rqs[i].rq.adapter =
adapter;
adapter->notification_desc.blk_mq_poll_rqs[i].rq.msix_idx =
i + adapter->notification_desc.iopoll_qdex;
- atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].rq.busy, 0);
+ atomic_set(
+ &adapter->notification_desc.blk_mq_poll_rqs[i].rq.busy,
+ 0);
snprintf(adapter->notification_desc.blk_mq_poll_rqs[i].rq.name,
LEAPRAID_NAME_LENGTH,
"%s%u-MQ-Poll%u", LEAPRAID_DRIVER_NAME,
adapter->adapter_attr.id, i);
- atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].busy, 0);
- atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].pause, 0);
+ atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].busy,
+ 0);
+ atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].pause,
+ 0);
}
adapter->notification_desc.msix_cpu_map_sz =
@@ -6900,20 +7655,21 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter)
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);
- adapter->notification_desc.msix_enable = true;
+ adapter->notification_desc.msix_enable = 1;
rc = leapraid_setup_irqs(adapter);
if (rc) {
leapraid_free_irq(adapter);
- adapter->notification_desc.msix_enable = false;
- goto legacy_int;
+ adapter->notification_desc.msix_enable = 0;
+ goto apply_legacy_int;
}
return 0;
-legacy_int:
+apply_legacy_int:
rc = leapraid_set_legacy_int(adapter);
return rc;
@@ -6926,13 +7682,13 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter)
int rc, msi_cnt;
if (msix_disable == 1)
- goto legacy_int1;
+ goto apply_legacy_int;
- msi_cnt = leapraid_msi_cnt(adapter->pdev);
+ 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 legacy_int1;
+ dev_info(&adapter->pdev->dev, "MSI unsupported!\n");
+ goto apply_legacy_int;
}
msi_cnt = min_t(int, msi_cnt,
@@ -6979,10 +7735,13 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter)
PCI_IRQ_MSI | PCI_IRQ_AFFINITY, NULL);
if (rc < 0) {
dev_err(&adapter->pdev->dev,
- "%d msi vectors alloacted failed!\n",
+ "%d MSI vectors allocated failed!\n",
adapter->notification_desc.iopoll_qdex);
- goto legacy_int1;
+ leapraid_free_irq(adapter);
+ goto apply_legacy_int;
}
+ 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 =
@@ -6999,12 +7758,8 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter)
kcalloc(adapter->notification_desc.iopoll_qdex,
sizeof(struct leapraid_int_rq),
GFP_KERNEL);
- if (!adapter->notification_desc.int_rqs) {
- dev_err(&adapter->pdev->dev,
- "MSI: allocate %d interrupt reply queues failed!\n",
- adapter->notification_desc.iopoll_qdex);
+ if (!adapter->notification_desc.int_rqs)
return -ENOMEM;
- }
for (i = 0; i < adapter->notification_desc.iopoll_qcnt; i++) {
adapter->notification_desc.blk_mq_poll_rqs[i].rq.adapter =
@@ -7028,24 +7783,24 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter)
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);
+ 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);
- adapter->notification_desc.msix_enable = true;
+ adapter->notification_desc.msix_enable = 1;
rc = leapraid_setup_irqs(adapter);
if (rc) {
leapraid_free_irq(adapter);
- adapter->notification_desc.msix_enable = false;
- goto legacy_int1;
+ adapter->notification_desc.msix_enable = 0;
+ goto apply_legacy_int;
}
return 0;
-legacy_int1:
+apply_legacy_int:
rc = leapraid_set_legacy_int(adapter);
return rc;
@@ -7055,30 +7810,26 @@ static int leapraid_set_notification(struct leapraid_adapter *adapter)
{
int rc = 0;
- if (interrupt_mode == 0) {
+ if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX) {
rc = leapraid_set_msix(adapter);
if (rc)
- pr_err("%s enable MSI-X irq failed!\n", __func__);
- } else if (interrupt_mode == 1) {
+ 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)
- pr_err("%s enable MSI irq failed!\n", __func__);
- } else if (interrupt_mode == 2) {
+ 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)
- pr_err("%s enable legacy irq failed!\n", __func__);
+ dev_err(&adapter->pdev->dev,
+ "%s: Enable legacy irq failed!\n", __func__);
}
return rc;
}
-static void leapraid_disable_pcie_and_notification(
- struct leapraid_adapter *adapter)
-{
- leapraid_free_irq(adapter);
- leapraid_disable_pcie(adapter);
-}
-
int leapraid_set_pcie_and_notification(struct leapraid_adapter *adapter)
{
int rc;
@@ -7091,13 +7842,13 @@ int leapraid_set_pcie_and_notification(struct leapraid_adapter *adapter)
rc = leapraid_make_adapter_ready(adapter, PART_RESET);
if (rc) {
- dev_err(&adapter->pdev->dev, "make adapter ready failure\n");
+ dev_err(&adapter->pdev->dev, "Make adapter ready failure\n");
goto out_fail;
}
rc = leapraid_get_adapter_features(adapter);
if (rc) {
- dev_err(&adapter->pdev->dev, "get adapter feature failure\n");
+ dev_err(&adapter->pdev->dev, "Get adapter feature failure\n");
goto out_fail;
}
@@ -7110,7 +7861,8 @@ int leapraid_set_pcie_and_notification(struct leapraid_adapter *adapter)
return 0;
out_fail:
- leapraid_disable_pcie_and_notification(adapter);
+ leapraid_free_irq(adapter);
+ leapraid_disable_pcie(adapter);
return rc;
}
@@ -7121,11 +7873,13 @@ void leapraid_disable_controller(struct leapraid_adapter *adapter)
leapraid_mask_int(adapter);
- adapter->access_ctrl.shost_recovering = true;
+ adapter->access_ctrl.shost_recovering = 1;
leapraid_make_adapter_ready(adapter, PART_RESET);
- adapter->access_ctrl.shost_recovering = false;
+ adapter->access_ctrl.shost_recovering = 0;
+ wake_up(&adapter->access_ctrl.recovery_waitq);
- leapraid_disable_pcie_and_notification(adapter);
+ leapraid_free_irq(adapter);
+ leapraid_disable_pcie(adapter);
}
static int leapraid_adapter_unit_reset(struct leapraid_adapter *adapter)
@@ -7139,12 +7893,11 @@ static int leapraid_adapter_unit_reset(struct leapraid_adapter *adapter)
rc = -EFAULT;
if (!leapraid_wait_adapter_ready(adapter)) {
- rc = -EFAULT;
- goto out;
+ dev_info(&adapter->pdev->dev, "unit reset: FAILED\n");
+ return -EFAULT;
}
-out:
- dev_info(&adapter->pdev->dev, "unit reset: %s\n",
- ((rc == 0) ? "SUCCESS" : "FAILED"));
+
+ dev_info(&adapter->pdev->dev, "unit reset: SUCCESS\n");
return rc;
}
@@ -7164,13 +7917,13 @@ static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter,
while ((db & LEAPRAID_DB_MASK) != LEAPRAID_DB_READY) {
if (count++ == LEAPRAID_DB_RETRY_COUNT_MAX) {
dev_err(&adapter->pdev->dev,
- "wait adapter ready timeout\n");
+ "Wait adapter ready timeout\n");
return -EFAULT;
}
ssleep(1);
db = leapraid_readl(&adapter->iomem_base->db);
dev_info(&adapter->pdev->dev,
- "wait adapter ready, count=%d, db=0x%x\n",
+ "Wait adapter ready, count=%d, db=0x%x\n",
count, db);
}
}
@@ -7186,9 +7939,9 @@ static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter,
if (type == FULL_RESET)
goto full_reset;
- if ((db & LEAPRAID_DB_MASK) == LEAPRAID_DB_OPERATIONAL)
- if (!(leapraid_adapter_unit_reset(adapter)))
- return 0;
+ if ((db & LEAPRAID_DB_MASK) == LEAPRAID_DB_OPERATIONAL &&
+ !leapraid_adapter_unit_reset(adapter))
+ return 0;
full_reset:
rc = leapraid_host_diag_reset(adapter);
@@ -7229,12 +7982,8 @@ static int leapraid_fw_log_init(struct leapraid_adapter *adapter)
LEAPRAID_SYS_LOG_BUF_RESERVE),
&adapter->fw_log_desc.fw_log_buffer_dma,
GFP_KERNEL);
- if (!adapter->fw_log_desc.fw_log_buffer) {
- dev_err(&adapter->pdev->dev,
- "%s: log buf alloc failed.\n",
- __func__);
+ if (!adapter->fw_log_desc.fw_log_buffer)
return -ENOMEM;
- }
}
memset(&adapter_log_req, 0, sizeof(struct leapraid_adapter_log_req));
@@ -7253,7 +8002,7 @@ static int leapraid_fw_log_init(struct leapraid_adapter *adapter)
sizeof(struct leapraid_adapter_log_rep),
(u16 *)&adapter_log_rep);
if (rc != 0) {
- dev_err(&adapter->pdev->dev, "%s: handshake failed, rc=%d\n",
+ dev_err(&adapter->pdev->dev, "%s: Handshake failed, rc=%d\n",
__func__, rc);
return rc;
}
@@ -7292,7 +8041,7 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter)
if (adapter->mem_desc.rep_msg) {
dma_free_coherent(
&adapter->pdev->dev,
- adapter->adapter_attr.rep_msg_qd * LEAPRAID_REPLY_SIEZ,
+ adapter->adapter_attr.rep_msg_qd * LEAPRAID_REPLY_SIZE,
adapter->mem_desc.rep_msg,
adapter->mem_desc.rep_msg_dma);
adapter->mem_desc.rep_msg = NULL;
@@ -7310,15 +8059,19 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter)
if (adapter->mem_desc.rep_desc_seg_maint) {
for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt;
i++) {
- if (adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg) {
+ if (adapter->mem_desc.rep_desc_seg_maint[i]
+ .rep_desc_seg) {
dma_free_coherent(
&adapter->pdev->dev,
(adapter->adapter_attr.rep_desc_qd *
LEAPRAID_REP_DESC_ENTRY_SIZE) *
LEAPRAID_REP_DESC_CHUNK_SIZE,
- adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg,
- adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg_dma);
- adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg = NULL;
+ adapter->mem_desc.rep_desc_seg_maint[i]
+ .rep_desc_seg,
+ adapter->mem_desc.rep_desc_seg_maint[i]
+ .rep_desc_seg_dma);
+ adapter->mem_desc.rep_desc_seg_maint[i]
+ .rep_desc_seg = NULL;
}
}
@@ -7333,7 +8086,8 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter)
}
for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt; i++)
- kfree(adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_maint);
+ kfree(adapter->mem_desc.rep_desc_seg_maint[i]
+ .rep_desc_maint);
kfree(adapter->mem_desc.rep_desc_seg_maint);
}
@@ -7345,16 +8099,16 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter)
static inline bool leapraid_is_in_same_4g_seg(dma_addr_t start, u32 size)
{
- return (upper_32_bits(start) == upper_32_bits(start + size - 1));
+ return upper_32_bits(start) == upper_32_bits(start + size - 1);
}
int leapraid_internal_init_cmd_priv(struct leapraid_adapter *adapter,
struct leapraid_io_req_tracker *io_tracker)
{
io_tracker->chain =
- dma_pool_alloc(adapter->mem_desc.sg_chain_pool,
- GFP_KERNEL,
- &io_tracker->chain_dma);
+ dma_pool_alloc(adapter->mem_desc.sg_chain_pool,
+ GFP_KERNEL,
+ &io_tracker->chain_dma);
if (!io_tracker->chain)
return -ENOMEM;
@@ -7381,17 +8135,16 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
unsigned int i, j;
int rc;
- /* sg table size */
+ /* Scatter-gather table size. */
adapter->shost->sg_tablesize = LEAPRAID_SG_DEPTH;
if (reset_devices)
adapter->shost->sg_tablesize =
LEAPRAID_KDUMP_MIN_PHYS_SEGMENTS;
- /* high priority cmds queue depth */
- adapter->dynamic_task_desc.hp_cmd_qd = facts->hp_slot;
+ /* High-priority commands queue depth. */
adapter->dynamic_task_desc.hp_cmd_qd = LEAPRAID_FIXED_HP_CMDS;
- /* internal cmds queue depth */
+ /* Internal commands queue depth. */
adapter->dynamic_task_desc.inter_cmd_qd = LEAPRAID_FIXED_INTER_CMDS;
- /* adapter cmds total queue depth */
+ /* Adapter commands total queue depth. */
if (reset_devices)
adapter->adapter_attr.adapter_total_qd =
LEAPRAID_DEFAULT_CMD_QD_OFFSET +
@@ -7400,22 +8153,22 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
else
adapter->adapter_attr.adapter_total_qd = facts->req_slot +
adapter->dynamic_task_desc.hp_cmd_qd;
- /* reply message queue depth */
+ /* Reply message queue depth. */
adapter->adapter_attr.rep_msg_qd =
adapter->adapter_attr.adapter_total_qd +
LEAPRAID_DEFAULT_CMD_QD_OFFSET;
- /* reply descriptor queue depth */
+ /* Reply descriptor queue depth. */
adapter->adapter_attr.rep_desc_qd =
round_up(adapter->adapter_attr.adapter_total_qd +
adapter->adapter_attr.rep_msg_qd +
LEAPRAID_TASKID_OFFSET_CTRL_CMD,
LEAPRAID_REPLY_QD_ALIGNMENT);
- /* scsi cmd io depth */
+ /* SCSI command I/O depth. */
adapter->adapter_attr.io_qd =
adapter->adapter_attr.adapter_total_qd -
adapter->dynamic_task_desc.hp_cmd_qd -
adapter->dynamic_task_desc.inter_cmd_qd;
- /* scsi host can queue */
+ /* SCSI host can queue. */
adapter->shost->can_queue = adapter->adapter_attr.io_qd -
LEAPRAID_TASKID_OFFSET_SCSIIO_CMD;
adapter->driver_cmds.ctl_cmd.taskid = adapter->shost->can_queue +
@@ -7424,7 +8177,7 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
adapter->shost->can_queue +
LEAPRAID_TASKID_OFFSET_SCSIIO_CMD;
- /* allocate task descriptor */
+ /* Allocate task descriptor. */
try_again:
adapter->adapter_attr.task_desc_dma_size =
(adapter->adapter_attr.adapter_total_qd +
@@ -7435,39 +8188,31 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
adapter->adapter_attr.task_desc_dma_size,
&adapter->mem_desc.task_desc_dma,
GFP_KERNEL);
- if (!adapter->mem_desc.task_desc) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate task descriptor DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
- /* allocate chain message pool */
+ if (!adapter->mem_desc.task_desc)
+ return -ENOMEM;
+
+ /* Allocate chain message pool. */
adapter->mem_desc.sg_chain_pool_size =
LEAPRAID_DEFAULT_CHAINS_PER_IO * LEAPRAID_CHAIN_SEG_SIZE;
adapter->mem_desc.sg_chain_pool =
dma_pool_create("leapraid chain pool",
&adapter->pdev->dev,
- adapter->mem_desc.sg_chain_pool_size, 16, 0);
- if (!adapter->mem_desc.sg_chain_pool) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate chain message DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
+ adapter->mem_desc.sg_chain_pool_size,
+ LEAPRAID_DMA_ALIGN, 0);
+ if (!adapter->mem_desc.sg_chain_pool)
+ return -ENOMEM;
- /* allocate io tracker to ref scsi io */
+ /* 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) {
- rc = -ENOMEM;
- goto out;
- }
+ kcalloc(adapter->shost->can_queue, sizeof(u16), GFP_KERNEL);
+ if (!adapter->mem_desc.taskid_to_uniq_tag)
+ return -ENOMEM;
adapter->dynamic_task_desc.hp_taskid =
adapter->adapter_attr.io_qd +
LEAPRAID_HP_TASKID_OFFSET_CTL_CMD;
- /* allocate static hp taskid */
+ /* Allocate static high-priority task ID. */
adapter->driver_cmds.ctl_cmd.hp_taskid =
adapter->dynamic_task_desc.hp_taskid;
adapter->driver_cmds.tm_cmd.hp_taskid =
@@ -7488,9 +8233,6 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
adapter->driver_cmds.timestamp_sync_cmd.inter_taskid =
adapter->dynamic_task_desc.inter_taskid +
LEAPRAID_TASKID_OFFSET_TIMESTAMP_SYNC_CMD;
- adapter->driver_cmds.raid_action_cmd.inter_taskid =
- adapter->dynamic_task_desc.inter_taskid +
- LEAPRAID_TASKID_OFFSET_RAID_ACTION_CMD;
adapter->driver_cmds.enc_cmd.inter_taskid =
adapter->dynamic_task_desc.inter_taskid +
LEAPRAID_TASKID_OFFSET_ENC_CMD;
@@ -7518,64 +8260,58 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
adapter->dynamic_task_desc.inter_taskid);
/*
- * allocate sense dma, driver maintain
- * need in same 4GB segment
+ * Allocate sense data DMA buffer.
+ * Constraint: Must reside within the same 4GB segment
+ * (driver-maintained).
*/
adapter->mem_desc.sense_data =
- dma_alloc_coherent(
+ dma_alloc_coherent(
&adapter->pdev->dev,
adapter->adapter_attr.io_qd * SCSI_SENSE_BUFFERSIZE,
- &adapter->mem_desc.sense_data_dma, GFP_KERNEL);
- if (!adapter->mem_desc.sense_data) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate sense data DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
+ &adapter->mem_desc.sense_data_dma,
+ GFP_KERNEL);
+ if (!adapter->mem_desc.sense_data)
+ return -ENOMEM;
+
if (!leapraid_is_in_same_4g_seg(adapter->mem_desc.sense_data_dma,
adapter->adapter_attr.io_qd *
SCSI_SENSE_BUFFERSIZE)) {
dev_warn(&adapter->pdev->dev,
- "try 32 bit dma due to sense data is not in same 4g!\n");
+ "Try 32bit DMA: Sense not in same 4G\n");
rc = -EAGAIN;
- goto out;
+ goto out_fail;
}
- /* reply frame, need in same 4GB segment */
+ /*
+ * Allocate reply frame buffer.
+ * Constraint: Must reside in the same 4GB segment as the sense DMA.
+ */
adapter->mem_desc.rep_msg =
- dma_alloc_coherent(&adapter->pdev->dev,
- adapter->adapter_attr.rep_msg_qd *
- LEAPRAID_REPLY_SIEZ,
- &adapter->mem_desc.rep_msg_dma,
- GFP_KERNEL);
- if (!adapter->mem_desc.rep_msg) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate reply message DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
+ dma_alloc_coherent(&adapter->pdev->dev,
+ adapter->adapter_attr.rep_msg_qd *
+ LEAPRAID_REPLY_SIZE,
+ &adapter->mem_desc.rep_msg_dma,
+ GFP_KERNEL);
+ if (!adapter->mem_desc.rep_msg)
+ return -ENOMEM;
if (!leapraid_is_in_same_4g_seg(adapter->mem_desc.rep_msg_dma,
adapter->adapter_attr.rep_msg_qd *
- LEAPRAID_REPLY_SIEZ)) {
+ LEAPRAID_REPLY_SIZE)) {
dev_warn(&adapter->pdev->dev,
- "use 32 bit dma due to rep msg is not in same 4g!\n");
+ "Use 32 bit DMA due to rep msg is not in same 4g!\n");
rc = -EAGAIN;
- goto out;
+ goto out_fail;
}
- /* address of reply frame */
+ /* Address of reply frame. */
adapter->mem_desc.rep_msg_addr =
- dma_alloc_coherent(&adapter->pdev->dev,
- adapter->adapter_attr.rep_msg_qd *
- LEAPRAID_REP_MSG_ADDR_SIZE,
- &adapter->mem_desc.rep_msg_addr_dma,
- GFP_KERNEL);
- if (!adapter->mem_desc.rep_msg_addr) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate reply message address DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
+ dma_alloc_coherent(&adapter->pdev->dev,
+ adapter->adapter_attr.rep_msg_qd *
+ LEAPRAID_REP_MSG_ADDR_SIZE,
+ &adapter->mem_desc.rep_msg_addr_dma,
+ GFP_KERNEL);
+ if (!adapter->mem_desc.rep_msg_addr)
+ return -ENOMEM;
adapter->adapter_attr.rep_desc_q_seg_cnt =
DIV_ROUND_UP(adapter->adapter_attr.rq_cnt,
LEAPRAID_REP_DESC_CHUNK_SIZE);
@@ -7583,10 +8319,8 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
kcalloc(adapter->adapter_attr.rep_desc_q_seg_cnt,
sizeof(struct leapraid_rep_desc_seg_maint),
GFP_KERNEL);
- if (!adapter->mem_desc.rep_desc_seg_maint) {
- rc = -ENOMEM;
- goto out;
- }
+ if (!adapter->mem_desc.rep_desc_seg_maint)
+ return -ENOMEM;
rep_desc_q_cnt_allocated = 0;
for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt; i++) {
@@ -7594,25 +8328,20 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
kcalloc(LEAPRAID_REP_DESC_CHUNK_SIZE,
sizeof(struct leapraid_rep_desc_maint),
GFP_KERNEL);
- if (!adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_maint) {
- rc = -ENOMEM;
- goto out;
- }
+ if (!adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_maint)
+ return -ENOMEM;
adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg =
- dma_alloc_coherent(
+ dma_alloc_coherent(
&adapter->pdev->dev,
(adapter->adapter_attr.rep_desc_qd *
- LEAPRAID_REP_DESC_ENTRY_SIZE) *
+ LEAPRAID_REP_DESC_ENTRY_SIZE) *
LEAPRAID_REP_DESC_CHUNK_SIZE,
- &adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg_dma,
+ &adapter->mem_desc.rep_desc_seg_maint[i]
+ .rep_desc_seg_dma,
GFP_KERNEL);
- if (!adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate reply descriptor segment DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
+ if (!adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg)
+ return -ENOMEM;
for (j = 0; j < LEAPRAID_REP_DESC_CHUNK_SIZE; j++) {
if (rep_desc_q_cnt_allocated >=
@@ -7645,30 +8374,26 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
if (!reset_devices) {
adapter->mem_desc.rep_desc_q_arr =
- dma_alloc_coherent(
+ dma_alloc_coherent(
&adapter->pdev->dev,
adapter->adapter_attr.rq_cnt *
LEAPRAID_REP_RQ_CNT_SIZE,
&adapter->mem_desc.rep_desc_q_arr_dma,
GFP_KERNEL);
- if (!adapter->mem_desc.rep_desc_q_arr) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate reply descriptor queue array DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
+ if (!adapter->mem_desc.rep_desc_q_arr)
+ return -ENOMEM;
}
return 0;
-out:
+out_fail:
if (rc == -EAGAIN) {
leapraid_free_host_memory(adapter);
- adapter->adapter_attr.use_32_dma_mask = true;
+ adapter->adapter_attr.use_32_dma_mask = 1;
rc = dma_set_mask_and_coherent(&adapter->pdev->dev,
- DMA_BIT_MASK(32));
+ DMA_BIT_MASK(DMA_32_BITS));
if (rc) {
dev_err(&adapter->pdev->dev,
- "failed to set 32 DMA mask\n");
+ "Failed to set 32 DMA mask\n");
return rc;
}
goto try_again;
@@ -7678,12 +8403,13 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
static int leapraid_alloc_dev_topo_bitmaps(struct leapraid_adapter *adapter)
{
- adapter->dev_topo.pd_hdls_sz =
- adapter->adapter_attr.features.max_dev_handle /
- LEAPRAID_BITS_PER_BYTE;
- if (adapter->adapter_attr.features.max_dev_handle %
- LEAPRAID_BITS_PER_BYTE)
- adapter->dev_topo.pd_hdls_sz++;
+ u16 pd_hdls_sz;
+
+ pd_hdls_sz = adapter->adapter_attr.features.max_dev_handle /
+ LEAPRAID_BITS_PER_BYTE;
+ pd_hdls_sz++;
+
+ adapter->dev_topo.pd_hdls_sz = pd_hdls_sz;
adapter->dev_topo.pd_hdls =
kzalloc(adapter->dev_topo.pd_hdls_sz, GFP_KERNEL);
if (!adapter->dev_topo.pd_hdls)
@@ -7694,24 +8420,6 @@ static int leapraid_alloc_dev_topo_bitmaps(struct leapraid_adapter *adapter)
if (!adapter->dev_topo.blocking_hdls)
return -ENOMEM;
- adapter->dev_topo.pending_dev_add_sz =
- adapter->adapter_attr.features.max_dev_handle /
- LEAPRAID_BITS_PER_BYTE;
- if (adapter->adapter_attr.features.max_dev_handle %
- LEAPRAID_BITS_PER_BYTE)
- adapter->dev_topo.pending_dev_add_sz++;
- adapter->dev_topo.pending_dev_add =
- kzalloc(adapter->dev_topo.pending_dev_add_sz, GFP_KERNEL);
- if (!adapter->dev_topo.pending_dev_add)
- return -ENOMEM;
-
- adapter->dev_topo.dev_removing_sz =
- adapter->dev_topo.pending_dev_add_sz;
- adapter->dev_topo.dev_removing =
- kzalloc(adapter->dev_topo.dev_removing_sz, GFP_KERNEL);
- if (!adapter->dev_topo.dev_removing)
- return -ENOMEM;
-
return 0;
}
@@ -7719,13 +8427,11 @@ static void leapraid_free_dev_topo_bitmaps(struct leapraid_adapter *adapter)
{
kfree(adapter->dev_topo.pd_hdls);
kfree(adapter->dev_topo.blocking_hdls);
- kfree(adapter->dev_topo.pending_dev_add);
- kfree(adapter->dev_topo.dev_removing);
}
static int leapraid_init_driver_cmds(struct leapraid_adapter *adapter)
{
- u32 buffer_size = 0;
+ u32 buffer_size;
void *buffer;
INIT_LIST_HEAD(&adapter->driver_cmds.special_cmd_list);
@@ -7777,15 +8483,14 @@ static int leapraid_init_driver_cmds(struct leapraid_adapter *adapter)
return -ENOMEM;
adapter->driver_cmds.internal_scmd = buffer;
- buffer = (void *)((u8 *)buffer +
- sizeof(struct scsi_cmnd) +
- sizeof(struct leapraid_io_req_tracker));
+ buffer = (u8 *)buffer + sizeof(struct scsi_cmnd) +
+ sizeof(struct leapraid_io_req_tracker);
adapter->driver_cmds.internal_scmd->sense_buffer =
- (unsigned char *)buffer;
- buffer = (void *)((u8 *)buffer + SCSI_SENSE_BUFFERSIZE);
+ (unsigned char *)buffer;
+ buffer = (u8 *)buffer + SCSI_SENSE_BUFFERSIZE;
adapter->driver_cmds.internal_scmd->sdb.table.sgl =
- (struct scatterlist *)buffer;
- buffer = (void *)((u8 *)buffer + sizeof(struct scatterlist));
+ (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;
@@ -7828,32 +8533,34 @@ static void leapraid_init_event_mask(struct leapraid_adapter *adapter)
int i;
for (i = 0; i < LEAPRAID_EVT_MASK_COUNT; i++)
- adapter->fw_evt_s.leapraid_evt_masks[i] = -1;
- leapraid_unmask_evts(adapter, LEAPRAID_EVT_SAS_DISCOVERY);
+ adapter->fw_evt_s.leapraid_evt_masks[i] =
+ LEAPRAID_INVALID_INITIAL_VALUE;
+
leapraid_unmask_evts(adapter, LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST);
leapraid_unmask_evts(adapter, LEAPRAID_EVT_SAS_ENCL_DEV_STATUS_CHANGE);
leapraid_unmask_evts(adapter, LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE);
leapraid_unmask_evts(adapter, LEAPRAID_EVT_IR_CHANGE);
}
-static void leapraid_prepare_adp_init_req(
+static void leapraid_prepare_adapter_init_req(
struct leapraid_adapter *adapter,
struct leapraid_adapter_init_req *init_req)
{
ktime_t cur_time;
- int i;
+ int i, chunk;
u32 reply_post_free_ary_sz;
memset(init_req, 0, sizeof(struct leapraid_adapter_init_req));
init_req->func = LEAPRAID_FUNC_ADAPTER_INIT;
init_req->who_init = LEAPRAID_WHOINIT_LINUX_DRIVER;
- init_req->msg_ver = cpu_to_le16(0x0100);
- init_req->header_ver = cpu_to_le16(0x0000);
-
- init_req->driver_ver = cpu_to_le32((LEAPRAID_MAJOR_VERSION << 24) |
- (LEAPRAID_MINOR_VERSION << 16) |
- (LEAPRAID_BUILD_VERSION << 8) |
- LEAPRAID_RELEASE_VERSION);
+ init_req->msg_ver = cpu_to_le16(LEAPRAID_MSG_VERSION);
+ init_req->header_ver = cpu_to_le16(LEAPRAID_HEADER_VERSION);
+ init_req->driver_ver =
+ cpu_to_le32((LEAPRAID_MAJOR_VERSION <<
+ LEAPRAID_VER_MAJOR_SHIFT) |
+ (LEAPRAID_MINOR_VERSION << LEAPRAID_VER_MINOR_SHIFT) |
+ (LEAPRAID_BUILD_VERSION << LEAPRAID_VER_BUILD_SHIFT) |
+ LEAPRAID_RELEASE_VERSION);
if (adapter->notification_desc.msix_enable)
init_req->host_msix_vectors = adapter->adapter_attr.rq_cnt;
@@ -7877,18 +8584,13 @@ static void leapraid_prepare_adp_init_req(
memset(adapter->mem_desc.rep_desc_q_arr, 0,
reply_post_free_ary_sz);
- for (i = 0; i < adapter->adapter_attr.rq_cnt; i++) {
- adapter->mem_desc
- .rep_desc_q_arr[i]
- .rep_desc_base_addr =
- cpu_to_le64 (
- (u64)adapter->mem_desc
- .rep_desc_seg_maint[i /
- LEAPRAID_REP_DESC_CHUNK_SIZE]
- .rep_desc_maint[i %
- LEAPRAID_REP_DESC_CHUNK_SIZE]
- .rep_desc_dma);
- }
+ chunk = LEAPRAID_REP_DESC_CHUNK_SIZE;
+ for (i = 0; i < adapter->adapter_attr.rq_cnt; i++)
+ adapter->mem_desc.rep_desc_q_arr[i].rep_desc_base_addr =
+ cpu_to_le64 ((u64)adapter->mem_desc
+ .rep_desc_seg_maint[i / chunk]
+ .rep_desc_maint[i % chunk]
+ .rep_desc_dma);
init_req->msg_flg =
LEAPRAID_ADAPTER_INIT_MSGFLG_RDPQ_ARRAY_MODE;
@@ -7910,9 +8612,9 @@ static int leapraid_send_adapter_init(struct leapraid_adapter *adapter)
struct leapraid_adapter_init_req init_req;
struct leapraid_adapter_init_rep init_rep;
u16 adapter_status;
- int rc = 0;
+ int rc;
- leapraid_prepare_adp_init_req(adapter, &init_req);
+ leapraid_prepare_adapter_init_req(adapter, &init_req);
rc = leapraid_handshake_func(adapter,
sizeof(struct leapraid_adapter_init_req),
@@ -7920,7 +8622,7 @@ static int leapraid_send_adapter_init(struct leapraid_adapter *adapter)
sizeof(struct leapraid_adapter_init_rep),
(u16 *)&init_rep);
if (rc != 0) {
- dev_err(&adapter->pdev->dev, "%s: handshake failed, rc=%d\n",
+ dev_err(&adapter->pdev->dev, "%s: Handshake failed, rc=%d\n",
__func__, rc);
return rc;
}
@@ -7941,11 +8643,10 @@ static int leapraid_cfg_pages(struct leapraid_adapter *adapter)
{
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- struct leapraid_sas_io_unit_page1 *sas_io_unit_page1 = NULL;
+ struct leapraid_manufacturing_p0 manufacturing_page0;
struct leapraid_bios_page3 bios_page3;
struct leapraid_bios_page2 bios_page2;
- int rc = 0;
- int sz;
+ int rc;
rc = leapraid_op_config_page(adapter, &bios_page3, cfgp1,
cfgp2, GET_BIOS_PG3);
@@ -7957,79 +8658,49 @@ static int leapraid_cfg_pages(struct leapraid_adapter *adapter)
if (rc)
return rc;
+ rc = leapraid_op_config_page(adapter, &manufacturing_page0, cfgp1,
+ cfgp2, GET_MANUFACTURING_PG0);
+ if (rc)
+ return rc;
+
adapter->adapter_attr.bios_version =
le32_to_cpu(bios_page3.bios_version);
- adapter->adapter_attr.wideport_max_queue_depth =
- LEAPRAID_SAS_QUEUE_DEPTH;
- adapter->adapter_attr.narrowport_max_queue_depth =
- LEAPRAID_SAS_QUEUE_DEPTH;
- adapter->adapter_attr.sata_max_queue_depth =
- LEAPRAID_SATA_QUEUE_DEPTH;
-
+ 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;
- memcpy((void *)adapter->boot_devs.requested_boot_dev.pg_dev,
- (void *)&bios_page2.requested_boot_dev,
+ memcpy(adapter->boot_devs.requested_boot_dev.pg_dev,
+ &bios_page2.requested_boot_dev,
LEAPRAID_BOOT_DEV_SIZE);
adapter->boot_devs.requested_alt_boot_dev.form =
bios_page2.requested_alt_boot_dev_form;
- memcpy((void *)adapter->boot_devs.requested_alt_boot_dev.pg_dev,
- (void *)&bios_page2.requested_alt_boot_dev,
+ memcpy(adapter->boot_devs.requested_alt_boot_dev.pg_dev,
+ &bios_page2.requested_alt_boot_dev,
LEAPRAID_BOOT_DEV_SIZE);
adapter->boot_devs.current_boot_dev.form =
bios_page2.current_boot_dev_form;
- memcpy((void *)adapter->boot_devs.current_boot_dev.pg_dev,
- (void *)&bios_page2.current_boot_dev,
+ memcpy(adapter->boot_devs.current_boot_dev.pg_dev,
+ &bios_page2.current_boot_dev,
LEAPRAID_BOOT_DEV_SIZE);
-
- sz = offsetof(struct leapraid_sas_io_unit_page1, phy_info);
- sas_io_unit_page1 = kzalloc(sz, GFP_KERNEL);
- if (!sas_io_unit_page1) {
- rc = -ENOMEM;
- return rc;
- }
-
- cfgp1.size = sz;
-
- rc = leapraid_op_config_page(adapter, sas_io_unit_page1, cfgp1,
- cfgp2, GET_SAS_IOUNIT_PG1);
- if (rc)
- goto out;
-
- if (le16_to_cpu(sas_io_unit_page1->wideport_max_queue_depth))
- adapter->adapter_attr.wideport_max_queue_depth =
- le16_to_cpu(
- sas_io_unit_page1->wideport_max_queue_depth);
-
- if (le16_to_cpu(sas_io_unit_page1->narrowport_max_queue_depth))
- adapter->adapter_attr.narrowport_max_queue_depth =
- le16_to_cpu(
- sas_io_unit_page1->narrowport_max_queue_depth);
-
- if (sas_io_unit_page1->sata_max_queue_depth)
- adapter->adapter_attr.sata_max_queue_depth =
- sas_io_unit_page1->sata_max_queue_depth;
-
-out:
- kfree(sas_io_unit_page1);
- dev_info(&adapter->pdev->dev,
- "max wp qd=%d, max np qd=%d, max sata qd=%d\n",
- adapter->adapter_attr.wideport_max_queue_depth,
- adapter->adapter_attr.narrowport_max_queue_depth,
- adapter->adapter_attr.sata_max_queue_depth);
return rc;
}
static int leapraid_evt_notify(struct leapraid_adapter *adapter)
{
struct leapraid_evt_notify_req *evt_notify_req;
+ struct leapraid_evt_notify_rep *evt_notify_rep;
+ u16 adapter_status;
int rc = 0;
int i;
mutex_lock(&adapter->driver_cmds.notify_event_cmd.mutex);
adapter->driver_cmds.notify_event_cmd.status = LEAPRAID_CMD_PENDING;
evt_notify_req =
- leapraid_get_task_desc(adapter,
+ leapraid_get_task_desc(
+ adapter,
adapter->driver_cmds.notify_event_cmd.inter_taskid);
memset(evt_notify_req, 0, sizeof(struct leapraid_evt_notify_req));
evt_notify_req->func = LEAPRAID_FUNC_EVENT_NOTIFY;
@@ -8038,15 +8709,30 @@ static int leapraid_evt_notify(struct leapraid_adapter *adapter)
cpu_to_le32(adapter->fw_evt_s.leapraid_evt_masks[i]);
init_completion(&adapter->driver_cmds.notify_event_cmd.done);
leapraid_fire_task(adapter,
- adapter->driver_cmds.notify_event_cmd.inter_taskid);
+ adapter->driver_cmds.notify_event_cmd.inter_taskid);
wait_for_completion_timeout(
&adapter->driver_cmds.notify_event_cmd.done,
LEAPRAID_NOTIFY_EVENT_CMD_TIMEOUT * HZ);
+
if (!(adapter->driver_cmds.notify_event_cmd.status &
- LEAPRAID_CMD_DONE))
- if (adapter->driver_cmds.notify_event_cmd.status &
- LEAPRAID_CMD_RESET)
- rc = -EFAULT;
+ LEAPRAID_CMD_DONE)) {
+ rc = -EFAULT;
+ goto out_cleanup;
+ }
+
+ if (!(adapter->driver_cmds.notify_event_cmd.status &
+ LEAPRAID_CMD_REPLY_VALID)) {
+ rc = -EFAULT;
+ goto out_cleanup;
+ }
+
+ evt_notify_rep = (void *)&adapter->driver_cmds.notify_event_cmd.reply;
+ adapter_status = le16_to_cpu(evt_notify_rep->adapter_status) &
+ LEAPRAID_ADAPTER_STATUS_MASK;
+ if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS)
+ rc = -EFAULT;
+
+out_cleanup:
adapter->driver_cmds.notify_event_cmd.status = LEAPRAID_CMD_NOT_USED;
mutex_unlock(&adapter->driver_cmds.notify_event_cmd.mutex);
@@ -8061,51 +8747,54 @@ int leapraid_scan_dev(struct leapraid_adapter *adapter, bool async_scan_dev)
int rc = 0;
dev_info(&adapter->pdev->dev,
- "send device scan, async_scan_dev=%d!\n", async_scan_dev);
+ "Send device scan, async_scan_dev=%d!\n", async_scan_dev);
adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_PENDING;
adapter->driver_cmds.scan_dev_cmd.async_scan_dev = async_scan_dev;
- scan_dev_req = leapraid_get_task_desc(adapter,
- adapter->driver_cmds.scan_dev_cmd.inter_taskid);
+ scan_dev_req =
+ leapraid_get_task_desc(
+ adapter,
+ adapter->driver_cmds.scan_dev_cmd.inter_taskid);
memset(scan_dev_req, 0, sizeof(struct leapraid_scan_dev_req));
scan_dev_req->func = LEAPRAID_FUNC_SCAN_DEV;
if (async_scan_dev) {
- adapter->scan_dev_desc.first_scan_dev_fired = true;
- leapraid_fire_task(adapter,
+ adapter->scan_dev_desc.first_scan_dev_fired = 1;
+ leapraid_fire_task(
+ adapter,
adapter->driver_cmds.scan_dev_cmd.inter_taskid);
return 0;
}
init_completion(&adapter->driver_cmds.scan_dev_cmd.done);
leapraid_fire_task(adapter,
- adapter->driver_cmds.scan_dev_cmd.inter_taskid);
+ adapter->driver_cmds.scan_dev_cmd.inter_taskid);
wait_for_completion_timeout(&adapter->driver_cmds.scan_dev_cmd.done,
LEAPRAID_SCAN_DEV_CMD_TIMEOUT * HZ);
if (!(adapter->driver_cmds.scan_dev_cmd.status & LEAPRAID_CMD_DONE)) {
- dev_err(&adapter->pdev->dev, "device scan timeout!\n");
+ dev_err(&adapter->pdev->dev, "Device scan timeout!\n");
if (adapter->driver_cmds.scan_dev_cmd.status &
LEAPRAID_CMD_RESET)
rc = -EFAULT;
else
rc = -ETIME;
- goto out;
+ goto out_cleanup;
}
- scan_dev_rep = (void *)(&adapter->driver_cmds.scan_dev_cmd.reply);
+ scan_dev_rep = (void *)&adapter->driver_cmds.scan_dev_cmd.reply;
adapter_status =
le16_to_cpu(scan_dev_rep->adapter_status) &
LEAPRAID_ADAPTER_STATUS_MASK;
if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS) {
- dev_err(&adapter->pdev->dev, "device scan failure!\n");
+ dev_err(&adapter->pdev->dev, "Device scan failure!\n");
rc = -EFAULT;
- goto out;
+ goto out_cleanup;
}
-out:
+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"));
+ "Device scan %s\n", rc == 0 ? "SUCCESS" : "FAILED");
return rc;
}
@@ -8125,13 +8814,14 @@ static void leapraid_init_rep_msg_addr(struct leapraid_adapter *adapter)
for (i = 0, reply_address = (u32)adapter->mem_desc.rep_msg_dma;
i < adapter->adapter_attr.rep_msg_qd;
- i++, reply_address += LEAPRAID_REPLY_SIEZ) {
+ i++, reply_address += LEAPRAID_REPLY_SIZE)
adapter->mem_desc.rep_msg_addr[i] = cpu_to_le32(reply_address);
- }
}
-static void init_rep_desc(struct leapraid_rq *rq, int index,
- union leapraid_rep_desc_union *reply_post_free_contig)
+static void init_rep_desc(
+ struct leapraid_rq *rq,
+ int index,
+ union leapraid_rep_desc_union *reply_post_free_contig)
{
struct leapraid_adapter *adapter = rq->adapter;
unsigned int i;
@@ -8218,7 +8908,7 @@ static void leapraid_init_bar_idx_regs(struct leapraid_adapter *adapter)
static int leapraid_make_adapter_available(struct leapraid_adapter *adapter)
{
- int rc = 0;
+ int rc;
leapraid_init_task_tracker(adapter);
leapraid_init_rep_msg_addr(adapter);
@@ -8242,7 +8932,7 @@ static int leapraid_make_adapter_available(struct leapraid_adapter *adapter)
return rc;
if (!adapter->access_ctrl.shost_recovering) {
- adapter->scan_dev_desc.wait_scan_dev_done = true;
+ adapter->scan_dev_desc.wait_scan_dev_done = 1;
return 0;
}
@@ -8256,45 +8946,45 @@ static int leapraid_make_adapter_available(struct leapraid_adapter *adapter)
int leapraid_ctrl_init(struct leapraid_adapter *adapter)
{
u32 cap;
- int rc = 0;
+ int rc;
rc = leapraid_set_pcie_and_notification(adapter);
if (rc)
- goto out_free_resources;
+ goto out_free;
pci_set_drvdata(adapter->pdev, adapter->shost);
pcie_capability_read_dword(adapter->pdev, PCI_EXP_DEVCAP, &cap);
- if (cap & PCI_EXP_DEVCAP_EXT_TAG) {
+ if (cap & PCI_EXP_DEVCAP_EXT_TAG)
pcie_capability_set_word(adapter->pdev, PCI_EXP_DEVCTL,
PCI_EXP_DEVCTL_EXT_TAG);
- }
rc = leapraid_fw_log_init(adapter);
if (rc) {
- dev_err(&adapter->pdev->dev, "fw log init failure\n");
- goto out_free_resources;
+ dev_err(&adapter->pdev->dev, "FW log init failure\n");
+ goto out_free;
}
rc = leapraid_request_host_memory(adapter);
if (rc) {
- dev_err(&adapter->pdev->dev, "request host memory failure\n");
- goto out_free_resources;
+ dev_err(&adapter->pdev->dev, "Request host memory failure\n");
+ goto out_free;
}
init_waitqueue_head(&adapter->reset_desc.reset_wait_queue);
+ init_waitqueue_head(&adapter->access_ctrl.shost_recover_wq);
rc = leapraid_alloc_dev_topo_bitmaps(adapter);
if (rc) {
- dev_err(&adapter->pdev->dev, "alloc topo bitmaps failure\n");
- goto out_free_resources;
+ dev_err(&adapter->pdev->dev, "Alloc topo bitmaps failure\n");
+ goto out_free;
}
rc = leapraid_init_driver_cmds(adapter);
if (rc) {
- dev_err(&adapter->pdev->dev, "init driver cmds failure\n");
- goto out_free_resources;
+ dev_err(&adapter->pdev->dev, "Init driver cmds failure\n");
+ goto out_free;
}
leapraid_init_event_mask(adapter);
@@ -8302,14 +8992,23 @@ int leapraid_ctrl_init(struct leapraid_adapter *adapter)
rc = leapraid_make_adapter_available(adapter);
if (rc) {
dev_err(&adapter->pdev->dev,
- "make adapter available failure\n");
- goto out_free_resources;
+ "Make adapter available failure\n");
+ goto out_free;
}
+
+ leapraid_overheat_init(adapter);
+ if (!adapter->overheat_desc.fault_overheat_wq) {
+ rc = -ENOMEM;
+ goto out_free;
+ }
+
return 0;
-out_free_resources:
- adapter->access_ctrl.host_removing = true;
+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);
@@ -8319,9 +9018,11 @@ int leapraid_ctrl_init(struct leapraid_adapter *adapter)
void leapraid_remove_ctrl(struct leapraid_adapter *adapter)
{
+ leapraid_overheat_cleanup(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);
diff --git a/drivers/scsi/leapraid/leapraid_func.h b/drivers/scsi/leapraid/leapraid_func.h
index f7072d078315..df61bc2e994a 100644
--- a/drivers/scsi/leapraid/leapraid_func.h
+++ b/drivers/scsi/leapraid/leapraid_func.h
@@ -1,16 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Copyright (C) 2025 LeapIO Tech Inc.
+ * Copyright (C) 2026 LeapIO Tech Inc.
*
- * LeapRAID Storage and RAID Controller driver.
+ * LeapRAID storage and RAID controller driver.
*/
-
#ifndef LEAPRAID_FUNC_H_INCLUDED
#define LEAPRAID_FUNC_H_INCLUDED
#include <linux/pci.h>
#include <linux/aer.h>
#include <linux/poll.h>
+#include <linux/atomic.h>
#include <linux/errno.h>
#include <linux/ktime.h>
#include <linux/delay.h>
@@ -28,9 +28,9 @@
#include "leapraid.h"
#include <linux/blk-mq-pci.h>
-/* some requset and reply buffer size */
+/* Request and reply buffer size. */
#define LEAPRAID_REQUEST_SIZE 128
-#define LEAPRAID_REPLY_SIEZ 128
+#define LEAPRAID_REPLY_SIZE 128
#define LEAPRAID_CHAIN_SEG_SIZE 128
#define LEAPRAID_MAX_SGES_IN_CHAIN 7
#define LEAPRAID_DEFAULT_CHAINS_PER_IO 19
@@ -45,61 +45,68 @@
#define LEAPRAID_SYS_LOG_BUF_SIZE 0x200000
#define LEAPRAID_SYS_LOG_BUF_RESERVE 0x1000
-/* Driver version and name */
+/* Driver version and name. */
#define LEAPRAID_DRIVER_NAME "LeapRAID"
#define LEAPRAID_NAME_LENGTH 48
+#define LEAPRAID_BOARD_NAME_LENGTH 17
#define LEAPRAID_AUTHOR "LeapIO Inc."
#define LEAPRAID_DESCRIPTION "LeapRAID Driver"
-#define LEAPRAID_DRIVER_VERSION "2.00.00.06"
+#define LEAPRAID_DRIVER_VERSION "2.00.01.02"
#define LEAPRAID_MAJOR_VERSION 2
#define LEAPRAID_MINOR_VERSION 00
-#define LEAPRAID_BUILD_VERSION 00
-#define LEAPRAID_RELEASE_VERSION 06
+#define LEAPRAID_BUILD_VERSION 01
+#define LEAPRAID_RELEASE_VERSION 02
+#define LEAPRAID_MSG_VERSION 0x1021
+#define LEAPRAID_HEADER_VERSION 0x0000
-/* Device ID */
+/* Device ID. */
#define LEAPRAID_VENDOR_ID 0xD405
#define LEAPRAID_DEVID_HBA 0x8200
-#define LEAPRAID_DEVID_RAID 0x8201
+#define LEAPRAID_SUBVENDOR_ID 0xD405
+#define LEAPRAID_SUBDEVID_HBA 0x8200
#define LEAPRAID_PCI_VENDOR_ID_MASK 0xFFFF
- /* RAID virtual channel ID */
+ /* RAID virtual channel ID. */
#define RAID_CHANNEL 1
-/* Scatter/Gather (SG) segment limits */
+/* Scatter-gather (SG) segment limits. */
#define LEAPRAID_MAX_PHYS_SEGMENTS SG_CHUNK_SIZE
#define LEAPRAID_KDUMP_MIN_PHYS_SEGMENTS 32
#define LEAPRAID_SG_DEPTH LEAPRAID_MAX_PHYS_SEGMENTS
-/* firmware / config page operations */
+/* Firmware and config page operations. */
#define LEAPRAID_SET_PARAMETER_SYNC_TIMESTAMP 0x81
#define LEAPRAID_CFG_REQ_RETRY_TIMES 2
-/* Hardware access helpers*/
+/* Hardware access helpers. */
#define leapraid_readl(addr) readl(addr)
#define leapraid_check_reset(status) \
(!((status) & LEAPRAID_CMD_RESET))
-/* Polling intervals */
+/* 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 */
+/* Init mask. */
#define LEAPRAID_RESET_IRQ_MASK 0x40000000
#define LEAPRAID_REPLY_INT_MASK 0x00000008
#define LEAPRAID_TO_SYS_DB_MASK 0x00000001
-/* queue depth */
+/* Queue depth. */
#define LEAPRAID_SATA_QUEUE_DEPTH 32
-#define LEAPRAID_SAS_QUEUE_DEPTH 254
-#define LEAPRAID_RAID_QUEUE_DEPTH 128
+#define LEAPRAID_SAS_QUEUE_DEPTH 64
+#define LEAPRAID_RAID_QUEUE_DEPTH 64
+
+/* 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 8192
-#define LEAPRAID_DEF_MAX_SECTORS 32767
+/* SCSI device and queue limits. */
+#define LEAPRAID_MAX_SECTORS 2048
#define LEAPRAID_MAX_CDB_LEN 32
#define LEAPRAID_MAX_LUNS 16384
#define LEAPRAID_CAN_QUEUE_MIN 1
@@ -107,136 +114,166 @@
#define LEAPRAID_CMD_PER_LUN 128
#define LEAPRAID_MAX_SEGMENT_SIZE 0xffffffff
-/* SCSI sense and ASC/ASCQ and disk geometry configuration */
+/* SCSI sense and ASC/ASCQ and disk geometry configuration. */
#define DESC_FORMAT_THRESHOLD 0x72
#define SENSE_KEY_MASK 0x0F
#define SCSI_SENSE_RESPONSE_CODE_MASK 0x7F
#define ASC_FAILURE_PREDICTION_THRESHOLD_EXCEEDED 0x5D
-#define LEAPRAID_LARGE_DISK_THRESHOLD 0x200000UL /* in sectors, 1GB */
+#define LEAPRAID_LARGE_DISK_THRESHOLD 0x200000UL
#define LEAPRAID_LARGE_DISK_HEADS 255
#define LEAPRAID_LARGE_DISK_SECTORS 63
#define LEAPRAID_SMALL_DISK_HEADS 64
#define LEAPRAID_SMALL_DISK_SECTORS 32
-/* SMP (Serial Management Protocol) */
+/* 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
-/* SCSI ASC/ASCQ definitions */
+/* SCSI ASC/ASCQ definitions. */
#define LEAPRAID_SCSI_ASCQ_DEFAULT 0x00
#define LEAPRAID_SCSI_ASC_POWER_ON_RESET 0x29
#define LEAPRAID_SCSI_ASC_INVALID_CMD_CODE 0x20
#define LEAPRAID_SCSI_ASCQ_POWER_ON_RESET 0x07
-/* ---- VPD Page 0x89 (ATA Information) ---- */
+/* VPD Page 0x89 (ATA Information). */
#define LEAPRAID_VPD_PAGE_ATA_INFO 0x89
#define LEAPRAID_VPD_PG89_MAX_LEN 255
#define LEAPRAID_VPD_PG89_MIN_LEN 214
-/* Byte index for NCQ support flag in VPD Page 0x89 */
+/* Byte index for NCQ support flag in VPD page 0x89. */
#define LEAPRAID_VPD_PG89_NCQ_BYTE_IDX 213
#define LEAPRAID_VPD_PG89_NCQ_BIT_SHIFT 4
#define LEAPRAID_VPD_PG89_NCQ_BIT_MASK 0x1
-/* readiness polling: max retries, sleep µs between */
+/* Readiness polling: max retries, sleep µs between. */
#define LEAPRAID_ADAPTER_READY_MAX_RETRY 15000
#define LEAPRAID_ADAPTER_READY_SLEEP_MIN_US 1000
#define LEAPRAID_ADAPTER_READY_SLEEP_MAX_US 1100
-/* Doorbell wait parameters */
+/* Doorbell wait parameters. */
#define LEAPRAID_DB_WAIT_MAX_RETRY 20000
#define LEAPRAID_DB_WAIT_DELAY_US 500
-/* Basic data size definitions */
+/* Basic data size definitions. */
#define LEAPRAID_DWORDS_BYTE_SIZE 4
#define LEAPRAID_WORD_BYTE_SIZE 2
-/* SGL threshold and chain offset*/
+/* SGL threshold and chain offset. */
#define LEAPRAID_SGL_INLINE_THRESHOLD 2
#define LEAPRAID_CHAIN_OFFSET_DWORDS 7
-/* MSI-X group size and mask */
+/* MSI-X group size and mask. */
#define LEAPRAID_MSIX_GROUP_SIZE 8
#define LEAPRAID_MSIX_GROUP_MASK 7
-/* basic constants and limits */
+/* 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 */
+/* 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
+#define LEAPRAID_WRSEQ_3RD_KEY_VALUE 0xB
+#define LEAPRAID_WRSEQ_4TH_KEY_VALUE 0x2
+#define LEAPRAID_WRSEQ_5TH_KEY_VALUE 0x7
+#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_LONG_MS 256
#define LEAPRAID_MSLEEP_EXTRA_LONG_MS 500
#define LEAPRAID_IO_POLL_DELAY_US 500
-/* controller reset loop parameters */
-#define LEAPRAID_RESET_LOOP_COUNT_REF (300000 / 256)
-#define LEAPRAID_RESET_LOOP_COUNT_DEFAULT 10000
-#define LEAPRAID_RESET_POLL_INTERVAL_MS 500
-
-/* Device / Volume configuration */
+/* Device/Volume configuration. */
#define LEAPRAID_MAX_VOLUMES_DEFAULT 32
#define LEAPRAID_MAX_DEV_HANDLE_DEFAULT 2048
#define LEAPRAID_INVALID_DEV_HANDLE 0xFFFF
-/* cmd queue depth */
+/* 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 */
+/* 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_CFG_OP_CMD 1
#define LEAPRAID_TASKID_OFFSET_TRANSPORT_CMD 2
#define LEAPRAID_TASKID_OFFSET_TIMESTAMP_SYNC_CMD 3
-#define LEAPRAID_TASKID_OFFSET_RAID_ACTION_CMD 4
-#define LEAPRAID_TASKID_OFFSET_ENC_CMD 5
-#define LEAPRAID_TASKID_OFFSET_NOTIFY_EVENT_CMD 6
+#define LEAPRAID_TASKID_OFFSET_ENC_CMD 4
+#define LEAPRAID_TASKID_OFFSET_NOTIFY_EVENT_CMD 5
-/* task id offset for high-priority */
+/* Task ID offset for high-priority. */
#define LEAPRAID_HP_TASKID_OFFSET_CTL_CMD 0
#define LEAPRAID_HP_TASKID_OFFSET_TM_CMD 1
-/* Event / Boot configuration */
+/* Event/Boot configuration. */
#define LEAPRAID_EVT_MASK_COUNT 4
#define LEAPRAID_BOOT_DEV_SIZE 24
-/* logsense command definitions */
+/* Commands timeout. */
+#define LEAPRAID_UNIFIED_TIMEOUT 30
+#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 5
+#define LEAPRAID_LOGSENSE_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT
#define LEAPRAID_LOGSENSE_SMART_CODE 0x5D
-/* cmd timeout */
-#define LEAPRAID_DRIVER_SCSIIO_CMD_TIMEOUT LEAPRAID_LOGSENSE_TIMEOUT
-#define LEAPRAID_CFG_OP_TIMEOUT 15
-#define LEAPRAID_CTL_CMD_TIMEOUT 10
-#define LEAPRAID_SCAN_DEV_CMD_TIMEOUT 300
-#define LEAPRAID_TIMESTAMP_SYNC_CMD_TIMEOUT 10
-#define LEAPRAID_RAID_ACTION_CMD_TIMEOUT 10
-#define LEAPRAID_ENC_CMD_TIMEOUT 10
-#define LEAPRAID_NOTIFY_EVENT_CMD_TIMEOUT 30
-#define LEAPRAID_TM_CMD_TIMEOUT 30
-#define LEAPRAID_TRANSPORT_CMD_TIMEOUT 10
+/* Host DMA cap. */
+#define DMA_32_BITS 32
+#define DMA_64_BITS 64
+#define LEAPRAID_DMA_ALIGN 16
+
+/* Values used to represent an invalid. */
+#define LEAPRAID_INVALID_INDEX -1
+#define LEAPRAID_INVALID_MSIX_VECTORS -1
+#define LEAPRAID_INVALID_INITIAL_VALUE -1
+#define LEAPRAID_OPERATION_FAILED -1
+
+/* Version shift and mask. */
+#define LEAPRAID_VER_MAJOR_SHIFT 24
+#define LEAPRAID_VER_MINOR_SHIFT 16
+#define LEAPRAID_VER_BUILD_SHIFT 8
+#define LEAPRAID_VER_MASK 0xFF
+
+/* Interrupt type. */
+#define LEAPRAID_INTERRUPT_MODE_MSIX 0
+#define LEAPRAID_INTERRUPT_MODE_MSI 1
+#define LEAPRAID_INTERRUPT_MODE_LEGACY 2
+
+/* SMP link reset. */
+#define SMP_PHY_CONTROL_LINK_RESET 0x01
+#define SMP_PHY_CONTROL_HARD_RESET 0x02
+#define SMP_PHY_CONTROL_DISABLE 0x03
/**
- * struct leapraid_adapter_features - Features and
- * capabilities of a LeapRAID adapter
+ * struct leapraid_adapter_features - Adapter features/capabilities.
*
- * @req_slot: Number of request slots supported by the adapter
- * @hp_slot: Number of high-priority slots supported by the adapter
- * @adapter_caps: Adapter capabilities
- * @fw_version: Firmware version of the adapter
- * @max_dev_handle: Maximum device supported by the adapter
+ * @req_slot: Number of request slots supported by the adapter.
+ * @hp_slot: Number of high-priority slots supported by the adapter.
+ * @adapter_caps: Adapter capabilities.
+ * @fw_version: Firmware version of the adapter.
+ * @max_dev_handle: Maximum device handle supported by the adapter.
+ * @min_dev_handle: Minimum device handle supported by the adapter.
*/
struct leapraid_adapter_features {
u16 req_slot;
@@ -252,32 +289,35 @@ struct leapraid_adapter_features {
/**
* struct leapraid_adapter_attr - Adapter attributes and capabilities
*
- * @id: Adapter identifier
- * @raid_support: Indicates if RAID is supported
- * @bios_version: Version of the adapter BIOS
- * @enable_mp: Indicates if multipath (MP) support is enabled
- * @wideport_max_queue_depth: Maximum queue depth for wide ports
- * @narrowport_max_queue_depth: Maximum queue depth for narrow ports
- * @sata_max_queue_depth: Maximum queue depth for SATA
- * @features: Detailed features of the adapter
- * @adapter_total_qd: Total queue depth available on the adapter
- * @io_qd: Queue depth allocated for I/O operations
- * @rep_msg_qd: Queue depth for reply messages
- * @rep_desc_qd: Queue depth for reply descriptors
- * @rep_desc_q_seg_cnt: Number of segments in a reply descriptor queue
- * @rq_cnt: Number of request queues
- * @task_desc_dma_size: Size of task descriptor DMA memory
- * @use_32_dma_mask: Indicates if 32-bit DMA mask is used
- * @name: Adapter name string
+ * @id: Adapter identifier.
+ * @raid_support: Indicates if RAID is supported.
+ * @bios_version: Version of the adapter BIOS.
+ * @enable_mp: Indicates if multipath (MP) support is enabled.
+ * @wideport_max_queue_depth: Maximum queue depth for wide ports.
+ * @narrowport_max_queue_depth: Maximum queue depth for narrow ports.
+ * @sata_max_queue_depth: Maximum queue depth for SATA.
+ * @raid_volume_max_queue_depth: Maximum queue depth for RAID volumes.
+ * @features: Detailed features of the adapter.
+ * @adapter_total_qd: Total queue depth available on the adapter.
+ * @io_qd: Queue depth allocated for I/O operations.
+ * @rep_msg_qd: Queue depth for reply messages.
+ * @rep_desc_qd: Queue depth for reply descriptors.
+ * @rep_desc_q_seg_cnt: Number of segments in a reply descriptor queue.
+ * @rq_cnt: Number of request queues.
+ * @task_desc_dma_size: Size of task descriptor DMA memory.
+ * @use_32_dma_mask: Indicates if 32-bit DMA mask is used.
+ * @name: Adapter name string.
+ * @board_name: Board name retrieved from manufacturing page 0.
*/
struct leapraid_adapter_attr {
u8 id;
- bool raid_support;
+ u8 raid_support;
u32 bios_version;
- bool enable_mp;
+ u8 enable_mp;
u32 wideport_max_queue_depth;
u32 narrowport_max_queue_depth;
u32 sata_max_queue_depth;
+ u32 raid_volume_max_queue_depth;
struct leapraid_adapter_features features;
u32 adapter_total_qd;
u32 io_qd;
@@ -286,20 +326,20 @@ struct leapraid_adapter_attr {
u32 rep_desc_q_seg_cnt;
u16 rq_cnt;
u32 task_desc_dma_size;
- bool use_32_dma_mask;
+ u8 use_32_dma_mask;
char name[LEAPRAID_NAME_LENGTH];
+ char board_name[LEAPRAID_BOARD_NAME_LENGTH];
};
/**
- * struct leapraid_io_req_tracker - Track a SCSI I/O request
- * for the adapter
+ * struct leapraid_io_req_tracker - Track a SCSI I/O request for the adapter
*
- * @taskid: Unique task ID for this I/O request
- * @scmd: Pointer to the associated SCSI command
- * @chain_list: List of chain frames associated with this request
- * @msix_io: MSI-X vector assigned to this I/O request
- * @chain: Pointer to the chain memory for this request
- * @chain_dma: DMA address of the chain memory
+ * @taskid: Unique task ID for this I/O request.
+ * @scmd: Pointer to the associated SCSI command.
+ * @chain_list: List of chain frames associated with this request.
+ * @msix_io: MSI-X vector assigned to this I/O request.
+ * @chain: Pointer to the chain memory for this request.
+ * @chain_dma: DMA address of the chain memory.
*/
struct leapraid_io_req_tracker {
u16 taskid;
@@ -313,9 +353,9 @@ struct leapraid_io_req_tracker {
/**
* struct leapraid_task_tracker - Tracks a task in the adapter
*
- * @taskid: Unique task ID for this tracker
- * @cb_idx: Callback index associated with this task
- * @tracker_list: Linked list node to chain this tracker in lists
+ * @taskid: Unique task ID for this tracker.
+ * @cb_idx: Callback index associated with this task.
+ * @tracker_list: Linked list node to chain this tracker in lists.
*/
struct leapraid_task_tracker {
u16 taskid;
@@ -324,11 +364,10 @@ struct leapraid_task_tracker {
};
/**
- * struct leapraid_rep_desc_maint - Maintains reply descriptor
- * memory
+ * struct leapraid_rep_desc_maint - Maintains reply descriptor memory
*
- * @rep_desc: Pointer to the reply descriptor
- * @rep_desc_dma: DMA address of the reply descriptor
+ * @rep_desc: Pointer to the reply descriptor.
+ * @rep_desc_dma: DMA address of the reply descriptor.
*/
struct leapraid_rep_desc_maint {
union leapraid_rep_desc_union *rep_desc;
@@ -336,12 +375,12 @@ struct leapraid_rep_desc_maint {
};
/**
- * struct leapraid_rep_desc_seg_maint - Maintains reply descriptor
- * segment memory
+ * struct leapraid_rep_desc_seg_maint -
+ * Maintains reply descriptor segment memory
*
- * @rep_desc_seg: Pointer to the reply descriptor segment
- * @rep_desc_seg_dma: DMA address of the reply descriptor segment
- * @rep_desc_maint: Pointer to the main reply descriptor structure
+ * @rep_desc_seg: Pointer to the reply descriptor segment.
+ * @rep_desc_seg_dma: DMA address of the reply descriptor segment.
+ * @rep_desc_maint: Pointer to the main reply descriptor structure.
*/
struct leapraid_rep_desc_seg_maint {
void *rep_desc_seg;
@@ -352,20 +391,20 @@ struct leapraid_rep_desc_seg_maint {
/**
* struct leapraid_mem_desc - Memory descriptor for LeapRAID adapter
*
- * @task_desc: Pointer to task descriptor
- * @task_desc_dma: DMA address of task descriptor
- * @sg_chain_pool: DMA pool for SGL chain allocations
- * @sg_chain_pool_size: Size of the sg_chain_pool
- * @taskid_to_uniq_tag: Mapping from task ID to unique tag
- * @sense_data: Buffer for SCSI sense data
- * @sense_data_dma: DMA address of sense_data buffer
- * @rep_msg: Buffer for reply message
- * @rep_msg_dma: DMA address of reply message buffer
- * @rep_msg_addr: Pointer to reply message address
- * @rep_msg_addr_dma: DMA address of reply message address
- * @rep_desc_seg_maint: Pointer to reply descriptor segment
- * @rep_desc_q_arr: Pointer to reply descriptor queue array
- * @rep_desc_q_arr_dma: DMA address of reply descriptor queue array
+ * @task_desc: Pointer to task descriptor.
+ * @task_desc_dma: DMA address of task descriptor.
+ * @sg_chain_pool: DMA pool for SGL chain allocations.
+ * @sg_chain_pool_size: Size of the sg_chain_pool.
+ * @taskid_to_uniq_tag: Mapping from task ID to unique tag.
+ * @sense_data: Buffer for SCSI sense data.
+ * @sense_data_dma: DMA address of sense_data buffer.
+ * @rep_msg: Buffer for reply message.
+ * @rep_msg_dma: DMA address of reply message buffer.
+ * @rep_msg_addr: Pointer to reply message address.
+ * @rep_msg_addr_dma: DMA address of reply message address.
+ * @rep_desc_seg_maint: Pointer to reply descriptor segment.
+ * @rep_desc_q_arr: Pointer to reply descriptor queue array.
+ * @rep_desc_q_arr_dma: DMA address of reply descriptor queue array.
*/
struct leapraid_mem_desc {
void *task_desc;
@@ -384,31 +423,30 @@ struct leapraid_mem_desc {
dma_addr_t rep_desc_q_arr_dma;
};
-#define LEAPRAID_FIXED_INTER_CMDS 7
-#define LEAPRAID_FIXED_HP_CMDS 2
-#define LEAPRAID_INTER_HP_CMDS_DIF \
- (LEAPRAID_FIXED_INTER_CMDS - LEAPRAID_FIXED_HP_CMDS)
+/* internal cmd description */
+#define LEAPRAID_FIXED_INTER_CMDS 6
+#define LEAPRAID_FIXED_HP_CMDS 2
-#define LEAPRAID_CMD_NOT_USED 0x8000
-#define LEAPRAID_CMD_DONE 0x0001
-#define LEAPRAID_CMD_PENDING 0x0002
-#define LEAPRAID_CMD_REPLY_VALID 0x0004
-#define LEAPRAID_CMD_RESET 0x0008
+#define LEAPRAID_CMD_NOT_USED 0x8000
+#define LEAPRAID_CMD_DONE 0x0001
+#define LEAPRAID_CMD_PENDING 0x0002
+#define LEAPRAID_CMD_REPLY_VALID 0x0004
+#define LEAPRAID_CMD_RESET 0x0008
/**
* enum LEAPRAID_CB_INDEX - Callback index for LeapRAID driver
*
- * @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
- * @LEAPRAID_CTL_CB_IDX: Control callback index
- * @LEAPRAID_TM_CB_IDX: Task management callback index
+ * @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.
+ * @LEAPRAID_CTL_CB_IDX: Control callback index.
+ * @LEAPRAID_TM_CB_IDX: Task management callback index.
*/
enum LEAPRAID_CB_INDEX {
LEAPRAID_SCAN_DEV_CB_IDX = 0x1,
@@ -425,10 +463,25 @@ enum LEAPRAID_CB_INDEX {
LEAPRAID_NUM_CB_IDXS
};
+/**
+ * struct leapraid_default_reply - Default reply frame buffer
+ * @pad: Raw reply data buffer returned by firmware.
+ *
+ * This structure represents a generic reply frame used by the firmware
+ * when no specific reply format is required. The buffer size is defined
+ * by LEAPRAID_REPLY_SIZE and stores the raw reply data.
+ */
struct leapraid_default_reply {
- u8 pad[LEAPRAID_REPLY_SIEZ];
+ u8 pad[LEAPRAID_REPLY_SIZE];
};
+/**
+ * struct leapraid_sense_buffer - SCSI sense data buffer
+ * @pad: Buffer used to store sense data returned by a SCSI command.
+ *
+ * This buffer holds the sense data provided by a device.The size is
+ * defined by SCSI_SENSE_BUFFERSIZE.
+ */
struct leapraid_sense_buffer {
u8 pad[SCSI_SENSE_BUFFERSIZE];
};
@@ -436,17 +489,17 @@ struct leapraid_sense_buffer {
/**
* struct leapraid_driver_cmd - Driver command tracking structure
*
- * @reply: Default reply structure returned by the adapter
- * @done: Completion object used to signal command completion
- * @status: Status code returned by the firmware
- * @taskid: Unique task identifier for this command
- * @hp_taskid: Task identifier for high-priority commands
- * @inter_taskid: Task identifier for internal commands
- * @cb_idx: Callback index used to identify completion context
- * @async_scan_dev: True if this command is for asynchronous device scan
- * @sense: Sense buffer holding error information from device
- * @mutex: Mutex to protect access to this command structure
- * @list: List node for linking driver commands into lists
+ * @reply: Default reply structure returned by the adapter.
+ * @done: Completion object used to signal command completion.
+ * @status: Status code returned by the firmware.
+ * @taskid: Unique task identifier for this command.
+ * @hp_taskid: Task identifier for high-priority commands.
+ * @inter_taskid: Task identifier for internal commands.
+ * @cb_idx: Callback index used to identify completion context.
+ * @async_scan_dev: True if this command is for asynchronous device scan.
+ * @sense: Sense buffer holding error information from device.
+ * @mutex: Mutex to protect access to this command structure.
+ * @list: List node for linking driver commands into lists.
*/
struct leapraid_driver_cmd {
struct leapraid_default_reply reply;
@@ -456,27 +509,27 @@ struct leapraid_driver_cmd {
u16 hp_taskid;
u16 inter_taskid;
u8 cb_idx;
- bool async_scan_dev;
+ u8 async_scan_dev;
struct leapraid_sense_buffer sense;
- struct mutex mutex;
+ struct mutex mutex; /* Mutex for driver cmd */
struct list_head list;
};
/**
* struct leapraid_driver_cmds - Collection of driver command objects
*
- * @special_cmd_list: List head for tracking special driver commands
- * @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
+ * @special_cmd_list: List head for tracking special driver commands.
+ * @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;
@@ -496,14 +549,14 @@ struct leapraid_driver_cmds {
/**
* struct leapraid_dynamic_task_desc - Dynamic task descriptor
*
- * @task_lock: Spinlock to protect concurrent access
- * @hp_taskid: Current high-priority task ID
- * @hp_cmd_qd: Fixed command queue depth for high-priority tasks
- * @inter_taskid: Current internal task ID
- * @inter_cmd_qd: Fixed command queue depth for internal tasks
+ * @task_lock: Spinlock to protect concurrent access.
+ * @hp_taskid: Current high-priority task ID.
+ * @hp_cmd_qd: Fixed command queue depth for high-priority tasks.
+ * @inter_taskid: Current internal task ID.
+ * @inter_cmd_qd: Fixed command queue depth for internal tasks.
*/
struct leapraid_dynamic_task_desc {
- spinlock_t task_lock;
+ spinlock_t task_lock; /* protects dynamic task */
u16 hp_taskid;
u16 hp_cmd_qd;
u16 inter_taskid;
@@ -513,14 +566,14 @@ struct leapraid_dynamic_task_desc {
/**
* struct leapraid_fw_evt_work - Firmware event work structure
*
- * @list: Linked list node for queuing the work
- * @adapter: Pointer to the associated LeapRAID adapter
- * @work: Work structure used by the kernel workqueue
- * @refcnt: Reference counter for managing the lifetime of this work
- * @evt_data: Pointer to firmware event data
- * @dev_handle: Device handle associated with the event
- * @evt_type: Type of firmware event
- * @ignore: Flag indicating whether the event should be ignored
+ * @list: Linked list node for queuing the work.
+ * @adapter: Pointer to the associated LeapRAID adapter.
+ * @work: Work structure used by the kernel workqueue.
+ * @refcnt: Reference counter for managing the lifetime of this work.
+ * @evt_data: Pointer to firmware event data.
+ * @dev_handle: Device handle associated with the event.
+ * @evt_type: Type of firmware event.
+ * @ignore: Flag indicating whether the event should be ignored.
*/
struct leapraid_fw_evt_work {
struct list_head list;
@@ -536,33 +589,35 @@ struct leapraid_fw_evt_work {
/**
* struct leapraid_fw_evt_struct - Firmware event handling structure
*
- * @fw_evt_name: Name of the firmware event
- * @fw_evt_thread: Workqueue used for processing firmware events
- * @fw_evt_lock: Spinlock protecting access to the firmware event list
- * @fw_evt_list: Linked list of pending firmware events
- * @cur_evt: Pointer to the currently processing firmware event
- * @fw_evt_cleanup: Flag indicating whether cleanup of events is in progress
- * @leapraid_evt_masks: Array of event masks for filtering firmware events
+ * @fw_evt_name: Name of the firmware event.
+ * @fw_evt_thread: Workqueue used for processing firmware events.
+ * @fw_evt_lock: Spinlock protecting access to the firmware event list.
+ * @fw_evt_list: Linked list of pending firmware events.
+ * @cur_evt: Pointer to the currently processing firmware event.
+ * @cur_evt_task: Task currently executing @cur_evt work.
+ * @fw_evt_cleanup: Flag indicating whether cleanup of events is in progress.
+ * @leapraid_evt_masks: Array of event masks for filtering firmware events.
*/
struct leapraid_fw_evt_struct {
char fw_evt_name[48];
struct workqueue_struct *fw_evt_thread;
- spinlock_t fw_evt_lock;
+ spinlock_t fw_evt_lock; /* protects firmware event */
struct list_head fw_evt_list;
struct leapraid_fw_evt_work *cur_evt;
- int fw_evt_cleanup;
+ struct task_struct *cur_evt_task;
+ u8 fw_evt_cleanup;
u32 leapraid_evt_masks[4];
};
/**
* struct leapraid_rq - Represents a LeapRAID request queue
*
- * @adapter: Pointer to the associated LeapRAID adapter
- * @msix_idx: MSI-X vector index used by this queue
- * @rep_post_host_idx: Index of the last processed reply descriptor
- * @rep_desc: Pointer to the reply descriptor associated with this queue
- * @name: Name of the request queue
- * @busy: Atomic counter indicating if the queue is busy
+ * @adapter: Pointer to the associated LeapRAID adapter.
+ * @msix_idx: MSI-X vector index used by this queue.
+ * @rep_post_host_idx: Index of the last processed reply descriptor.
+ * @rep_desc: Pointer to the reply descriptor associated with this queue.
+ * @name: Name of the request queue.
+ * @busy: Atomic counter indicating if the queue is busy.
*/
struct leapraid_rq {
struct leapraid_adapter *adapter;
@@ -576,8 +631,8 @@ struct leapraid_rq {
/**
* struct leapraid_int_rq - Internal request queue for a CPU
*
- * @affinity_hint: CPU affinity mask for the queue
- * @rq: Underlying LeapRAID request queue structure
+ * @affinity_hint: CPU affinity mask for the queue.
+ * @rq: Underlying LeapRAID request queue structure.
*/
struct leapraid_int_rq {
cpumask_var_t affinity_hint;
@@ -587,9 +642,9 @@ struct leapraid_int_rq {
/**
* struct leapraid_blk_mq_poll_rq - Polling request for LeapRAID blk-mq
*
- * @busy: Atomic flag indicating request is being processed
- * @pause: Atomic flag to temporarily suspend polling
- * @rq: The underlying LeapRAID request structure
+ * @busy: Atomic flag indicating request is being processed.
+ * @pause: Atomic flag to temporarily suspend polling.
+ * @rq: The underlying LeapRAID request structure.
*/
struct leapraid_blk_mq_poll_rq {
atomic_t busy;
@@ -598,22 +653,25 @@ struct leapraid_blk_mq_poll_rq {
};
/**
- * struct leapraid_notification_desc - Notification
- * descriptor for LeapRAID
+ * struct leapraid_notification_desc - Notification descriptor for LeapRAID
*
- * @iopoll_qdex: Index of the I/O polling queue
- * @iopoll_qcnt: Count of I/O polling queues
- * @msix_enable: Flag indicating MSI-X is enabled
- * @msix_cpu_map: CPU map for MSI-X interrupts
- * @msix_cpu_map_sz: Size of the MSI-X 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
+ * @iopoll_qdex: Index of the I/O polling queue.
+ * @iopoll_qcnt: Count of I/O polling queues.
+ * @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.
+ * @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.
*/
struct leapraid_notification_desc {
u32 iopoll_qdex;
u32 iopoll_qcnt;
- bool msix_enable;
+ u8 msix_enable;
+ u8 irq_vectors_allocated;
+ u8 irq_mode;
u8 *msix_cpu_map;
u32 msix_cpu_map_sz;
struct leapraid_int_rq *int_rqs;
@@ -621,82 +679,104 @@ struct leapraid_notification_desc {
struct leapraid_blk_mq_poll_rq *blk_mq_poll_rqs;
};
+/**
+ * struct leapraid_overheat_desc - Overheat descriptor for LeapRAID
+ *
+ * @fault_overheat_wq: Workqueue for adapter thermal overheat operations.
+ * @fault_overheat_work: Work structure for thermal overheat.
+ * @thermal_alert: Flag indicating if adapter thermal alert is active.
+ * @fault_overheat_wq_name: Name of the fault overheat workqueue.
+ */
+struct leapraid_overheat_desc {
+ struct workqueue_struct *fault_overheat_wq;
+ struct work_struct fault_overheat_work;
+ atomic_t thermal_alert;
+ char fault_overheat_wq_name[48];
+};
+
/**
* struct leapraid_reset_desc - Reset descriptor for LeapRAID
*
- * @fault_reset_wq: Workqueue for fault reset operations
- * @fault_reset_work: Delayed work structure for fault reset
- * @fault_reset_wq_name: Name of the fault reset workqueue
- * @host_diag_mutex: Mutex for host diagnostic operations
- * @adapter_reset_lock: Spinlock for adapter reset operations
- * @adapter_reset_mutex: Mutex for adapter reset operations
- * @adapter_link_resetting: Flag indicating if adapter link is resetting
- * @adapter_reset_results: Results of the adapter reset operation
- * @pending_io_cnt: Count of pending I/O operations
- * @reset_wait_queue: Wait queue for reset operations
- * @reset_cnt: Counter for reset operations
+ * @fault_reset_wq: Workqueue for fault reset operations.
+ * @fault_reset_work: Delayed work structure for fault reset.
+ * @fault_reset_wq_name: Name of the fault reset workqueue.
+ * @host_diag_mutex: Mutex for host diagnostic operations.
+ * @adapter_reset_lock: Spinlock for adapter reset operations.
+ * @adapter_reset_mutex: Mutex for adapter reset operations.
+ * @adapter_link_resetting: Flag indicating if adapter link is resetting.
+ * @adapter_reset_results: Results of the adapter reset operation.
+ * @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;
struct delayed_work fault_reset_work;
char fault_reset_wq_name[48];
- struct mutex host_diag_mutex;
- spinlock_t adapter_reset_lock;
- struct mutex adapter_reset_mutex;
- bool adapter_link_resetting;
+ struct mutex host_diag_mutex; /* Mutex for operations. */
+ spinlock_t adapter_reset_lock; /* Protects adapter reset state. */
+ struct mutex adapter_reset_mutex; /* Serializes adapter reset. */
+ u8 adapter_link_resetting;
int adapter_reset_results;
int pending_io_cnt;
wait_queue_head_t reset_wait_queue;
u32 reset_cnt;
+ u32 last_reset_cnt;
};
/**
- * struct leapraid_scan_dev_desc - Scan device descriptor
- * for LeapRAID
+ * struct leapraid_scan_dev_desc - Scan device descriptor for LeapRAID
*
- * @wait_scan_dev_done: Flag indicating if scan device operation is done
- * @driver_loading: Flag indicating if driver is loading
- * @first_scan_dev_fired: Flag indicating if first scan device operation fired
- * @scan_dev_failed: Flag indicating if scan device operation failed
- * @scan_start: Flag indicating if scan operation started
- * @scan_start_failed: Count of failed scan start operations
+ * @wait_scan_dev_done: Flag indicating if scan device operation is done.
+ * @driver_loading: Flag indicating if driver is loading.
+ * @first_scan_dev_fired: Flag indicating if first scan device operation fired.
+ * @scan_dev_failed: Flag indicating if scan device operation failed.
+ * @scan_start: Flag indicating if scan operation started.
+ * @scan_start_failed: Count of failed scan start operations.
*/
struct leapraid_scan_dev_desc {
- bool wait_scan_dev_done;
- bool driver_loading;
- bool first_scan_dev_fired;
- bool scan_dev_failed;
- bool scan_start;
+ u8 wait_scan_dev_done;
+ u8 driver_loading;
+ wait_queue_head_t wait_driver_loading;
+ u8 first_scan_dev_fired;
+ u8 scan_dev_failed;
+ u8 scan_start;
u16 scan_start_failed;
};
/**
* struct leapraid_access_ctrl - Access control structure for LeapRAID
*
- * @pci_access_lock: Mutex for PCI access control
- * @adapter_thermal_alert: Flag indicating if adapter thermal alert is active
- * @shost_recovering: Flag indicating if host is recovering
- * @host_removing: Flag indicating if host is being removed
- * @pcie_recovering: Flag indicating if PCIe is recovering
+ * @pci_access_lock: Mutex for PCI access control.
+ * @shost_recovering: Flag indicating if host is recovering.
+ * @shost_recover_async: Flag indicating if host is recovering
+ * and the 0xFFFF event.
+ * @shost_recover_wq: Wait queue for threads waiting on shost_recover_async.
+ * @host_removing: Flag indicating if host is being removed.
+ * @pcie_recovering: Flag indicating if PCIe is recovering.
*/
struct leapraid_access_ctrl {
- struct mutex pci_access_lock;
- bool adapter_thermal_alert;
- bool shost_recovering;
- bool host_removing;
- bool pcie_recovering;
+ struct mutex pci_access_lock; /* serializes PCI register access. */
+ u8 shost_recovering;
+ wait_queue_head_t recovery_waitq;
+ u8 shost_recover_async;
+ wait_queue_head_t shost_recover_wq;
+ u8 host_removing;
+ u8 pcie_recovering;
};
/**
* struct leapraid_fw_log_desc - Firmware log descriptor for LeapRAID
*
- * @fw_log_buffer: Buffer for firmware log data
- * @fw_log_buffer_dma: DMA address of the firmware log buffer
- * @fw_log_wq_name: Name of the firmware log workqueue
- * @fw_log_wq: Workqueue for firmware log operations
- * @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
+ * @fw_log_buffer: Buffer for firmware log data.
+ * @fw_log_buffer_dma: DMA address of the firmware log buffer.
+ * @fw_log_wq_name: Name of the firmware log workqueue.
+ * @fw_log_wq: Workqueue for firmware log operations.
+ * @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.
*/
struct leapraid_fw_log_desc {
u8 *fw_log_buffer;
@@ -706,6 +786,7 @@ 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];
};
#define LEAPRAID_CARD_PORT_FLG_DIRTY 0x01
@@ -714,13 +795,13 @@ struct leapraid_fw_log_desc {
/**
* struct leapraid_card_port - Card port structure for LeapRAID
*
- * @list: List head for card port
- * @vphys_list: List head for virtual phy list
- * @port_id: Port ID
- * @sas_address: SAS address
- * @phy_mask: Mask of phy
- * @vphys_mask: Mask of virtual phy
- * @flg: Flags for the port
+ * @list: List head for card port.
+ * @vphys_list: List head for virtual PHY list.
+ * @port_id: Port ID.
+ * @sas_address: SAS address.
+ * @phy_mask: Mask of PHY.
+ * @vphys_mask: Mask of virtual PHY.
+ * @flg: Flags for the port.
*/
struct leapraid_card_port {
struct list_head list;
@@ -733,18 +814,18 @@ struct leapraid_card_port {
};
/**
- * struct leapraid_card_phy - Card phy structure for LeapRAID
+ * struct leapraid_card_phy - Card PHY structure for LeapRAID
*
- * @port_siblings: List head for port siblings
- * @card_port: Pointer to the card port
- * @identify: SAS identify structure
- * @remote_identify: Remote SAS identify structure
- * @phy: SAS phy structure
- * @phy_id: Phy ID
- * @hdl: Handle for the port
- * @attached_hdl: Handle for the attached port
- * @phy_is_assigned: Flag indicating if phy is assigned
- * @vphy: Flag indicating if virtual phy
+ * @port_siblings: List head for port siblings.
+ * @card_port: Pointer to the card port.
+ * @identify: SAS identify structure.
+ * @remote_identify: Remote SAS identify structure.
+ * @phy: SAS PHY structure.
+ * @phy_id: PHY ID.
+ * @hdl: Handle for the port.
+ * @attached_hdl: Handle for the attached port.
+ * @phy_is_assigned: Flag indicating if PHY is assigned.
+ * @vphy: Flag indicating if virtual PHY.
*/
struct leapraid_card_phy {
struct list_head port_siblings;
@@ -755,26 +836,26 @@ struct leapraid_card_phy {
u8 phy_id;
u16 hdl;
u16 attached_hdl;
- bool phy_is_assigned;
- bool vphy;
+ u8 phy_is_assigned;
+ u8 vphy;
};
/**
* struct leapraid_topo_node - SAS topology node for LeapRAID
*
- * @list: List head for linking nodes
- * @sas_port_list: List of SAS ports
- * @card_port: Associated card port
- * @card_phy: Associated card PHY
- * @rphy: SAS remote PHY device
- * @parent_dev: Parent device pointer
- * @sas_address: SAS address of this node
- * @sas_address_parent: Parent node's SAS address
- * @phys_num: Number of physical links
- * @hdl: Handle identifier
- * @enc_hdl: Enclosure handle
- * @enc_lid: Enclosure logical identifier
- * @resp: Response status flag
+ * @list: List head for linking nodes.
+ * @sas_port_list: List of SAS ports.
+ * @card_port: Associated card port.
+ * @card_phy: Associated card PHY.
+ * @rphy: SAS remote PHY device.
+ * @parent_dev: Parent device pointer.
+ * @sas_address: SAS address of this node.
+ * @sas_address_parent: Parent node's SAS address.
+ * @phys_num: Number of physical links.
+ * @hdl: Handle identifier.
+ * @enc_hdl: Enclosure handle.
+ * @enc_lid: Enclosure logical identifier.
+ * @resp: Response status flag.
*/
struct leapraid_topo_node {
struct list_head list;
@@ -789,32 +870,32 @@ struct leapraid_topo_node {
u16 hdl;
u16 enc_hdl;
u64 enc_lid;
- bool resp;
+ u8 resp;
};
/**
* struct leapraid_dev_topo - LeapRAID device topology management structure
*
- * @topo_node_lock: Spinlock for protecting topology node operations
- * @sas_dev_lock: Spinlock for SAS device list access
- * @raid_volume_lock: Spinlock for RAID volume list access
- * @sas_id: SAS domain identifier
- * @card: Main card topology node
- * @exp_list: List of expander devices
- * @enc_list: List of enclosure devices
- * @sas_dev_list: List of SAS devices
- * @sas_dev_init_list: List of SAS devices being initialized
- * @raid_volume_list: List of RAID volumes
- * @card_port_list: List of card ports
- * @pd_hdls: Array of physical disk handles
- * @dev_removing: Array tracking devices being removed
- * @pending_dev_add: Array tracking devices pending addition
- * @blocking_hdls: Array of blocking handles
+ * @topo_node_lock: Spinlock for protecting topology node operations.
+ * @sas_dev_lock: Spinlock for SAS device list access.
+ * @raid_volume_lock: Spinlock for RAID volume list access.
+ * @enc_lock: Spinlock for enclosure device list access.
+ * @sas_id: SAS domain identifier.
+ * @card: Main card topology node.
+ * @exp_list: List of expander devices.
+ * @enc_list: List of enclosure devices.
+ * @sas_dev_list: List of SAS devices.
+ * @sas_dev_init_list: List of SAS devices being initialized.
+ * @raid_volume_list: List of RAID volumes.
+ * @card_port_list: List of card ports.
+ * @pd_hdls: Array of physical disk handles.
+ * @blocking_hdls: Array of blocking handles.
*/
struct leapraid_dev_topo {
- spinlock_t topo_node_lock;
- spinlock_t sas_dev_lock;
- spinlock_t raid_volume_lock;
+ spinlock_t topo_node_lock; /* Protects topology node. */
+ spinlock_t sas_dev_lock; /* Protects SAS device list access. */
+ spinlock_t raid_volume_lock; /* Protects RAID volume list access. */
+ spinlock_t enc_lock; /* Protects enclosure device list access. */
int sas_id;
struct leapraid_topo_node card;
struct list_head exp_list;
@@ -824,21 +905,17 @@ struct leapraid_dev_topo {
struct list_head raid_volume_list;
struct list_head card_port_list;
u16 pd_hdls_sz;
- void *pd_hdls;
- void *blocking_hdls;
- u16 pending_dev_add_sz;
- void *pending_dev_add;
- u16 dev_removing_sz;
- void *dev_removing;
+ unsigned long *pd_hdls;
+ unsigned long *blocking_hdls;
};
/**
* struct leapraid_boot_dev - Boot device structure for LeapRAID
*
- * @dev: Device pointer
- * @chnl: Channel number
- * @form: Form factor
- * @pg_dev: Config page device content
+ * @dev: Device pointer.
+ * @chnl: Channel number.
+ * @form: Form factor.
+ * @pg_dev: Config page device content.
*/
struct leapraid_boot_dev {
void *dev;
@@ -849,11 +926,14 @@ struct leapraid_boot_dev {
/**
* struct leapraid_boot_devs - Boot device management structure
- * @requested_boot_dev: Requested primary boot device
- * @requested_alt_boot_dev: Requested alternate boot device
- * @current_boot_dev: Currently active boot device
+ *
+ * @lock: Spinlock protecting boot device cache access.
+ * @requested_boot_dev: Requested primary boot device.
+ * @requested_alt_boot_dev: Requested alternate boot device.
+ * @current_boot_dev: Currently active boot device.
*/
struct leapraid_boot_devs {
+ spinlock_t lock; /* protects boot dev */
struct leapraid_boot_dev requested_boot_dev;
struct leapraid_boot_dev requested_alt_boot_dev;
struct leapraid_boot_dev current_boot_dev;
@@ -861,9 +941,10 @@ struct leapraid_boot_devs {
/**
* 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
+ *
+ * @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;
@@ -873,26 +954,28 @@ struct leapraid_smart_poll_desc {
/**
* struct leapraid_adapter - Main LeapRAID adapter structure
- * @list: List head for adapter management
- * @shost: SCSI host structure
- * @pdev: PCI device structure
- * @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
- * @dynamic_task_desc: Dynamic task descriptor
- * @fw_evt_s: Firmware event structure
- * @notification_desc: Notification descriptor
- * @reset_desc: Reset descriptor
- * @scan_dev_desc: Device scan descriptor
- * @access_ctrl: Access control
- * @fw_log_desc: Firmware log descriptor
- * @dev_topo: Device topology
- * @boot_devs: Boot devices
- * @smart_poll_desc: SMART polling descriptor
+ *
+ * @list: List head for adapter management.
+ * @shost: SCSI host structure.
+ * @pdev: PCI device structure.
+ * @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.
+ * @dynamic_task_desc: Dynamic task descriptor.
+ * @fw_evt_s: Firmware event structure.
+ * @notification_desc: Notification descriptor.
+ * @reset_desc: Reset descriptor.
+ * @scan_dev_desc: Device scan descriptor.
+ * @access_ctrl: Access control.
+ * @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 {
struct list_head list;
@@ -900,7 +983,7 @@ struct leapraid_adapter {
struct pci_dev *pdev;
struct leapraid_reg_base __iomem *iomem_base;
u32 rep_msg_host_idx;
- bool mask_int;
+ u8 mask_int;
u32 timestamp_sync_cnt;
struct leapraid_adapter_attr adapter_attr;
@@ -916,6 +999,7 @@ struct leapraid_adapter {
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;
};
union cfg_param_1 {
@@ -932,6 +1016,7 @@ union cfg_param_2 {
enum config_page_action {
GET_BIOS_PG2,
GET_BIOS_PG3,
+ GET_MANUFACTURING_PG0,
GET_SAS_DEVICE_PG0,
GET_SAS_IOUNIT_PG0,
GET_SAS_IOUNIT_PG1,
@@ -946,8 +1031,9 @@ enum config_page_action {
/**
* struct leapraid_enc_node - Enclosure node structure
- * @list: List head for enclosure management
- * @pg0: Enclosure page 0 data
+ *
+ * @list: List head for enclosure management.
+ * @pg0: Enclosure page 0 data.
*/
struct leapraid_enc_node {
struct list_head list;
@@ -956,20 +1042,23 @@ struct leapraid_enc_node {
/**
* struct leapraid_raid_volume - RAID volume structure
- * @list: List head for volume management
- * @starget: SCSI target structure
- * @sdev: SCSI device structure
- * @id: Volume ID
- * @channel: SCSI channel
- * @wwid: World Wide Identifier
- * @hdl: Volume handle
- * @vol_type: Volume type
- * @pd_num: Number of physical disks
- * @resp: Response status
- * @dev_info: Device information
+ *
+ * @list: List head for volume management.
+ * @refcnt: Reference count.
+ * @starget: SCSI target structure.
+ * @sdev: SCSI device structure.
+ * @id: Volume ID.
+ * @channel: SCSI channel.
+ * @wwid: World wide Identifier.
+ * @hdl: Volume handle.
+ * @vol_type: Volume type.
+ * @pd_num: Number of physical disks.
+ * @resp: Response status.
+ * @dev_info: Device information.
*/
struct leapraid_raid_volume {
struct list_head list;
+ struct kref refcnt;
struct scsi_target *starget;
struct scsi_device *sdev;
unsigned int id;
@@ -982,20 +1071,31 @@ struct leapraid_raid_volume {
u32 dev_info;
};
+static inline void leapraid_raid_volume_free(struct kref *ref)
+{
+ kfree(container_of(ref, struct leapraid_raid_volume, refcnt));
+}
+
+#define leapraid_raid_volume_get(volume) \
+ kref_get(&(volume)->refcnt)
+#define leapraid_raid_volume_put(volume) \
+ kref_put(&(volume)->refcnt, leapraid_raid_volume_free)
+
#define LEAPRAID_TGT_FLG_RAID_MEMBER 0x01
#define LEAPRAID_TGT_FLG_VOLUME 0x02
#define LEAPRAID_NO_ULD_ATTACH 1
/**
* struct leapraid_starget_priv - SCSI target private data
- * @starget: SCSI target structure
- * @sas_address: SAS address
- * @hdl: Device handle
- * @num_luns: Number of LUNs
- * @flg: Flags
- * @deleted: Deletion flag
- * @tm_busy: Task management busy flag
- * @card_port: Associated card port
- * @sas_dev: SAS device structure
+ *
+ * @starget: SCSI target structure.
+ * @sas_address: SAS address.
+ * @hdl: Device handle.
+ * @num_luns: Number of LUNs.
+ * @flg: Flags.
+ * @deleted: Deletion flag.
+ * @tm_busy: Task management busy flag.
+ * @card_port: Associated card port.
+ * @sas_dev: SAS device structure.
*/
struct leapraid_starget_priv {
struct scsi_target *starget;
@@ -1003,8 +1103,8 @@ struct leapraid_starget_priv {
u16 hdl;
int num_luns;
u32 flg;
- bool deleted;
- bool tm_busy;
+ u8 deleted;
+ u8 tm_busy;
struct leapraid_card_port *card_port;
struct leapraid_sas_dev *sas_dev;
};
@@ -1012,50 +1112,52 @@ struct leapraid_starget_priv {
#define LEAPRAID_DEVICE_FLG_INIT 0x01
/**
* struct leapraid_sdev_priv - SCSI device private data
- * @starget_priv: Associated target private data
- * @lun: Logical Unit Number
- * @flg: Flags
- * @block: Block flag
- * @deleted: Deletion flag
- * @sep: SEP flag
+ *
+ * @starget_priv: Associated target private data.
+ * @lun: Logical Unit Number.
+ * @flg: Flags.
+ * @block: Block flag.
+ * @deleted: Deletion flag.
+ * @sep: SEP flag.
*/
struct leapraid_sdev_priv {
struct leapraid_starget_priv *starget_priv;
unsigned int lun;
u32 flg;
- bool ncq;
- bool block;
- bool deleted;
- bool sep;
+ u8 ncq;
+ u8 block;
+ u8 deleted;
+ u8 sep;
};
/**
* struct leapraid_sas_dev - SAS device structure
- * @list: List head for device management
- * @starget: SCSI target structure
- * @card_port: Associated card port
- * @rphy: SAS remote PHY
- * @refcnt: Reference count
- * @id: Device ID
- * @channel: SCSI channel
- * @slot: Slot number
- * @phy: PHY identifier
- * @resp: Response status
- * @led_on: LED state
- * @sas_addr: SAS address
- * @dev_name: Device name
- * @hdl: Device handle
- * @parent_sas_addr: Parent SAS address
- * @enc_hdl: Enclosure handle
- * @enc_lid: Enclosure logical ID
- * @volume_hdl: Volume handle
- * @volume_wwid: Volume WWID
- * @dev_info: Device information
- * @pend_sas_rphy_add: Pending SAS rphy addition flag
- * @enc_level: Enclosure level
- * @port_type: Port type
- * @connector_name: Connector name
- * @support_smart: SMART support flag
+ *
+ * @list: List head for device management.
+ * @starget: SCSI target structure.
+ * @card_port: Associated card port.
+ * @rphy: SAS remote PHY.
+ * @refcnt: Reference count.
+ * @id: Device ID.
+ * @channel: SCSI channel.
+ * @slot: Slot number.
+ * @phy: PHY identifier.
+ * @resp: Response status.
+ * @led_on: LED state.
+ * @sas_addr: SAS address.
+ * @dev_name: Device name.
+ * @hdl: Device handle.
+ * @parent_sas_addr: Parent SAS address.
+ * @enc_hdl: Enclosure handle.
+ * @enc_lid: Enclosure logical ID.
+ * @volume_hdl: Volume handle.
+ * @volume_wwid: Volume WWID.
+ * @dev_info: Device information.
+ * @pend_sas_rphy_add: Pending SAS remote PHY addition flag.
+ * @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;
@@ -1067,8 +1169,8 @@ struct leapraid_sas_dev {
unsigned int channel;
u16 slot;
u8 phy;
- bool resp;
- bool led_on;
+ u8 resp;
+ u8 led_on;
u64 sas_addr;
u64 dev_name;
u16 hdl;
@@ -1080,9 +1182,9 @@ struct leapraid_sas_dev {
u32 dev_info;
u8 pend_sas_rphy_add;
u8 enc_level;
- u8 port_type;
- u8 connector_name[5];
- bool support_smart;
+ 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)
@@ -1093,15 +1195,19 @@ static inline void leapraid_sdev_free(struct kref *ref)
#define leapraid_sdev_get(sdev) kref_get(&(sdev)->refcnt)
#define leapraid_sdev_put(sdev) kref_put(&(sdev)->refcnt, leapraid_sdev_free)
+void leapraid_boot_dev_get(void *dev, u32 chnl);
+void leapraid_boot_dev_put(void *dev, u32 chnl);
+
/**
* struct leapraid_sas_port - SAS port structure
- * @port_list: List head for port management
- * @phy_list: List of PHYs in this port
- * @port: SAS port structure
- * @card_port: Associated card port
- * @remote_identify: Remote device identification
- * @rphy: SAS remote PHY
- * @phys_num: Number of PHYs in this port
+ *
+ * @port_list: List head for port management.
+ * @phy_list: List of PHYs in this port.
+ * @port: SAS port structure.
+ * @card_port: Associated card port.
+ * @remote_identify: Remote device identification.
+ * @rphy: SAS remote PHY.
+ * @phys_num: Number of PHYs in this port.
*/
struct leapraid_sas_port {
struct list_head port_list;
@@ -1116,10 +1222,11 @@ struct leapraid_sas_port {
#define LEAPRAID_VPHY_FLG_DIRTY 0x01
/**
* struct leapraid_vphy - Virtual PHY structure
- * @list: List head for PHY management
- * @sas_address: SAS address
- * @phy_mask: PHY mask
- * @flg: Flags
+ *
+ * @list: List head for PHY management.
+ * @sas_address: SAS address.
+ * @phy_mask: PHY mask.
+ * @flg: Flags.
*/
struct leapraid_vphy {
struct list_head list;
@@ -1128,23 +1235,44 @@ struct leapraid_vphy {
u8 flg;
};
+/**
+ * struct leapraid_tgt_rst_list - Target reset tracking entry
+ * @list: List node used to link reset entries.
+ * @handle: Device handle of the target being reset.
+ * @state: Current state of the target reset operation.
+ *
+ * Each entry represents a target device that is undergoing or has
+ * undergone a target reset operation.
+ */
struct leapraid_tgt_rst_list {
struct list_head list;
u16 handle;
u16 state;
};
-struct leapraid_sc_list {
- struct list_head list;
- u16 handle;
-};
-
+/**
+ * struct sense_info - Parsed SCSI sense information
+ * @sense_key: Sense key extracted from sense data.
+ * @asc: Additional Sense Code (ASC).
+ * @ascq: Additional Sense Code Qualifier (ASCQ).
+ *
+ * This structure stores key fields parsed from SCSI sense data to
+ * simplify error handling and reporting.
+ */
struct sense_info {
u8 sense_key;
u8 asc;
u8 ascq;
};
+/**
+ * struct leapraid_fw_log_info - Firmware log position information
+ * @user_position: Current log read position used by the driver.
+ * @adapter_position: Current log write position maintained by firmware.
+ *
+ * This structure tracks firmware log buffer positions used for retrieving
+ * log entries from the adapter.
+ */
struct leapraid_fw_log_info {
u32 user_position;
u32 adapter_position;
@@ -1152,8 +1280,9 @@ struct leapraid_fw_log_info {
/**
* enum reset_type - Reset type enumeration
- * @FULL_RESET: Full hardware reset
- * @PART_RESET: Partial reset
+ *
+ * @FULL_RESET: Full hardware reset.
+ * @PART_RESET: Partial reset.
*/
enum reset_type {
FULL_RESET,
@@ -1175,22 +1304,23 @@ enum leapraid_port_checking_state {
/**
* struct leapraid_card_port_feature - Card port feature
- * @dirty_flg: Dirty flag indicator
- * @same_addr: Same address flag
- * @exact_phy: Exact PHY match flag
- * @phy_overlap: PHY overlap bitmap
- * @same_port: Same port flag
- * @cur_chking_old_port: Current checking old port
- * @expected_old_port: Expected old port
- * @same_addr_port_count: Same address port count
- * @checking_state: Port checking state
+ *
+ * @dirty_flg: Dirty flag indicator.
+ * @same_addr: Same address flag.
+ * @exact_phy: Exact PHY match flag.
+ * @phy_overlap: PHY overlap bitmap.
+ * @same_port: Same port flag.
+ * @cur_chking_old_port: Current checking old port.
+ * @expected_old_port: Expected old port.
+ * @same_addr_port_count: Same address port count.
+ * @checking_state: Port checking state.
*/
struct leapraid_card_port_feature {
u8 dirty_flg;
- bool same_addr;
- bool exact_phy;
+ u8 same_addr;
+ u8 exact_phy;
u32 phy_overlap;
- bool same_port;
+ u8 same_port;
struct leapraid_card_port *cur_chking_old_port;
struct leapraid_card_port *expected_old_port;
int same_addr_port_count;
@@ -1225,7 +1355,7 @@ struct leapraid_rep_manu_reply {
u8 vendor_identification[SAS_EXPANDER_VENDOR_ID_LEN];
u8 product_identification[SAS_EXPANDER_PRODUCT_ID_LEN];
u8 product_revision_level[SAS_EXPANDER_PRODUCT_REV_LEN];
- u8 component_vendor_identification[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
+ u8 comp_vendor_identification[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
u16 component_id;
u8 component_revision_level;
u8 r3;
@@ -1234,20 +1364,21 @@ struct leapraid_rep_manu_reply {
/**
* 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
+ *
+ * @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;
- bool raid_member;
+ u8 raid_member;
enum dma_data_direction dir;
u32 data_length;
void *data_buffer;
@@ -1274,7 +1405,8 @@ void leapraid_mask_int(struct leapraid_adapter *adapter);
void leapraid_unmask_int(struct leapraid_adapter *adapter);
u32 leapraid_get_adapter_state(struct leapraid_adapter *adapter);
bool leapraid_pci_removed(struct leapraid_adapter *adapter);
-int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter);
+int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter, int wait,
+ const char *caller);
void *leapraid_get_task_desc(struct leapraid_adapter *adapter, u16 taskid);
void *leapraid_get_sense_buffer(struct leapraid_adapter *adapter, u16 taskid);
__le32 leapraid_get_sense_buffer_dma(struct leapraid_adapter *adapter,
@@ -1286,11 +1418,11 @@ u16 leapraid_alloc_scsiio_taskid(struct leapraid_adapter *adapter,
void leapraid_free_taskid(struct leapraid_adapter *adapter, u16 taskid);
struct leapraid_io_req_tracker *leapraid_get_io_tracker_from_taskid(
struct leapraid_adapter *adapter, u16 taskid);
-struct leapraid_io_req_tracker *leapraid_get_scmd_priv(struct scsi_cmnd *scmd);
struct scsi_cmnd *leapraid_get_scmd_from_taskid(
struct leapraid_adapter *adapter, u16 taskid);
int leapraid_scan_dev(struct leapraid_adapter *adapter, bool async_scan_dev);
void leapraid_scan_dev_done(struct leapraid_adapter *adapter);
+void leapraid_cleanup_lists(struct leapraid_adapter *adapter);
void leapraid_wait_cmds_done(struct leapraid_adapter *adapter);
void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter);
void leapraid_sync_irqs(struct leapraid_adapter *adapter, bool poll);
@@ -1307,14 +1439,16 @@ int leapraid_issue_locked_tm(struct leapraid_adapter *adapter, u16 handle,
int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 handle,
uint channel, uint id, uint lun, u8 type,
u16 taskid_task, u8 tr_method);
-u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
- u8 msix_index, u32 rep);
+bool leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
+ u8 msix_index, u32 rep);
int leapraid_get_volume_cap(struct leapraid_adapter *adapter,
struct leapraid_raid_volume *raid_volume);
-int leapraid_internal_init_cmd_priv(struct leapraid_adapter *adapter,
- struct leapraid_io_req_tracker *io_tracker);
-int leapraid_internal_exit_cmd_priv(struct leapraid_adapter *adapter,
- struct leapraid_io_req_tracker *io_tracker);
+int leapraid_internal_init_cmd_priv(
+ struct leapraid_adapter *adapter,
+ struct leapraid_io_req_tracker *io_tracker);
+int 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);
bool leapraid_scmd_find_by_lun(struct leapraid_adapter *adapter,
uint id, unsigned int lun, uint channel);
@@ -1383,10 +1517,13 @@ 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_adjust_sdev_queue_depth(struct scsi_device *sdev, int qdepth);
+void leapraid_log_req_context(struct leapraid_adapter *adapter,
+ const void *req_data);
+
+int leapraid_change_queue_depth(struct scsi_device *sdev, int qdepth);
int leapraid_ctl_release(struct inode *inode, struct file *filep);
-void leapraid_ctl_init(void);
+int leapraid_ctl_init(void);
void leapraid_ctl_exit(void);
extern struct sas_function_template leapraid_transport_functions;
@@ -1409,17 +1546,20 @@ void leapraid_transport_update_links(struct leapraid_adapter *adapter,
u64 sas_address, u16 handle,
u8 phy_number, u8 link_rate,
struct leapraid_card_port *card_port);
-void leapraid_transport_detach_phy_to_port(struct leapraid_adapter *adapter,
- struct leapraid_topo_node *topo_node,
- struct leapraid_card_phy *card_phy);
-void leapraid_transport_attach_phy_to_port(struct leapraid_adapter *adapter,
- struct leapraid_topo_node *sas_node,
- struct leapraid_card_phy *card_phy,
- u64 sas_address,
- struct leapraid_card_port *card_port);
+void leapraid_transport_detach_phy_to_port(
+ struct leapraid_adapter *adapter,
+ struct leapraid_topo_node *topo_node,
+ struct leapraid_card_phy *card_phy);
+void leapraid_transport_attach_phy_to_port(
+ struct leapraid_adapter *adapter,
+ struct leapraid_topo_node *sas_node,
+ struct leapraid_card_phy *card_phy,
+ 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);
diff --git a/drivers/scsi/leapraid/leapraid_os.c b/drivers/scsi/leapraid/leapraid_os.c
index f8354c68ab71..c60c5d80c7b3 100644
--- a/drivers/scsi/leapraid/leapraid_os.c
+++ b/drivers/scsi/leapraid/leapraid_os.c
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2025 LeapIO Tech Inc.
+ * Copyright (C) 2026 LeapIO Tech Inc.
*
- * LeapRAID Storage and RAID Controller driver.
+ * LeapRAID storage and RAID controller driver.
*/
-
#include <linux/module.h>
#include "leapraid_func.h"
@@ -18,16 +17,16 @@ MODULE_DESCRIPTION(LEAPRAID_DESCRIPTION);
MODULE_LICENSE("GPL");
MODULE_VERSION(LEAPRAID_DRIVER_VERSION);
-static int leapraid_ids;
+static atomic_t leapraid_ids = ATOMIC_INIT(0);
static int open_pcie_trace = 1;
module_param(open_pcie_trace, int, 0644);
-MODULE_PARM_DESC(open_pcie_trace, "open_pcie_trace: default=1(open)/0(close)");
+MODULE_PARM_DESC(open_pcie_trace, "Default=1(open)/0(close)");
static int enable_mp = 1;
module_param(enable_mp, int, 0444);
MODULE_PARM_DESC(enable_mp,
- "enable multipath on target device. default=1(enable)");
+ "Enable multipath on target device. default=1(enable)");
static inline void leapraid_get_sense_data(char *sense,
struct sense_info *data)
@@ -46,14 +45,9 @@ static inline void leapraid_get_sense_data(char *sense,
}
}
-static struct Scsi_Host *pdev_to_shost(struct pci_dev *pdev)
-{
- return pci_get_drvdata(pdev);
-}
-
static struct leapraid_adapter *pdev_to_adapter(struct pci_dev *pdev)
{
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
if (!shost)
return NULL;
@@ -61,18 +55,13 @@ static struct leapraid_adapter *pdev_to_adapter(struct pci_dev *pdev)
return shost_priv(shost);
}
-struct leapraid_io_req_tracker *leapraid_get_scmd_priv(struct scsi_cmnd *scmd)
-{
- return scsi_cmd_priv(scmd);
-}
-
void leapraid_set_tm_flg(struct leapraid_adapter *adapter, u16 hdl)
{
struct leapraid_sdev_priv *sdev_priv;
struct scsi_device *sdev;
bool skip = false;
- /* don't break out of the loop */
+ /* Iterate over all devices. */
shost_for_each_device(sdev, adapter->shost) {
if (skip)
continue;
@@ -82,7 +71,7 @@ void leapraid_set_tm_flg(struct leapraid_adapter *adapter, u16 hdl)
continue;
if (sdev_priv->starget_priv->hdl == hdl) {
- sdev_priv->starget_priv->tm_busy = true;
+ sdev_priv->starget_priv->tm_busy = 1;
skip = true;
}
}
@@ -94,7 +83,7 @@ void leapraid_clear_tm_flg(struct leapraid_adapter *adapter, u16 hdl)
struct scsi_device *sdev;
bool skip = false;
- /* don't break out of the loop */
+ /* Iterate over all devices. */
shost_for_each_device(sdev, adapter->shost) {
if (skip)
continue;
@@ -104,7 +93,7 @@ void leapraid_clear_tm_flg(struct leapraid_adapter *adapter, u16 hdl)
continue;
if (sdev_priv->starget_priv->hdl == hdl) {
- sdev_priv->starget_priv->tm_busy = false;
+ sdev_priv->starget_priv->tm_busy = 0;
skip = true;
}
}
@@ -136,21 +125,19 @@ static int leapraid_tm_cmd_map_status(struct leapraid_adapter *adapter,
}
}
- if (taskid_task == adapter->driver_cmds.driver_scsiio_cmd.taskid) {
- if ((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.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) {
- if ((adapter->driver_cmds.ctl_cmd.status &
- LEAPRAID_CMD_DONE) ||
- (adapter->driver_cmds.ctl_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 ||
+ adapter->driver_cmds.ctl_cmd.status &
+ LEAPRAID_CMD_NOT_USED))
+ rc = SUCCESS;
return rc;
}
@@ -197,7 +184,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
struct leapraid_scsi_tm_req *scsi_tm_req;
struct leapraid_scsiio_req *scsiio_req;
struct leapraid_io_req_tracker *io_req_tracker = NULL;
- u16 msix_task = 0;
+ u16 msix_task;
bool issue_reset = false;
u32 db;
int rc;
@@ -208,7 +195,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
adapter->access_ctrl.host_removing ||
adapter->access_ctrl.pcie_recovering) {
dev_info(&adapter->pdev->dev,
- "%s %s: host is recovering, skip tm command!\n",
+ "%s %s: Host is recovering, skip tm command!\n",
__func__, adapter->adapter_attr.name);
return FAILED;
}
@@ -216,24 +203,25 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
db = leapraid_readl(&adapter->iomem_base->db);
if (db & LEAPRAID_DB_USED) {
dev_info(&adapter->pdev->dev,
- "%s unexpected db status, issuing hard reset!\n",
+ "%s Unexpected db status, issuing hard reset!\n",
adapter->adapter_attr.name);
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
- return (!rc) ? SUCCESS : FAILED;
+ return !rc ? SUCCESS : FAILED;
}
if ((db & LEAPRAID_DB_MASK) == LEAPRAID_DB_FAULT) {
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
- return (!rc) ? SUCCESS : FAILED;
+ return !rc ? SUCCESS : FAILED;
}
if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK)
- io_req_tracker = leapraid_get_io_tracker_from_taskid(adapter,
- target_taskid);
+ io_req_tracker =
+ leapraid_get_io_tracker_from_taskid(adapter,
+ target_taskid);
adapter->driver_cmds.tm_cmd.status = LEAPRAID_CMD_PENDING;
scsi_tm_req =
@@ -241,7 +229,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
adapter->driver_cmds.tm_cmd.hp_taskid);
leapraid_build_tm_req(scsi_tm_req, hdl, lun, type, tr_method,
target_taskid);
- memset((void *)(&adapter->driver_cmds.tm_cmd.reply), 0,
+ memset(&adapter->driver_cmds.tm_cmd.reply, 0,
sizeof(struct leapraid_scsi_tm_rep));
leapraid_set_tm_flg(adapter, hdl);
init_completion(&adapter->driver_cmds.tm_cmd.done);
@@ -257,16 +245,20 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
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);
issue_reset =
leapraid_check_reset(
adapter->driver_cmds.tm_cmd.status);
if (issue_reset) {
dev_info(&adapter->pdev->dev,
- "%s:%d call hard_reset\n",
+ "%s:%d: call hard_reset\n",
__func__, __LINE__);
rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
- rc = (!rc) ? SUCCESS : FAILED;
- goto out;
+ rc = !rc ? SUCCESS : FAILED;
+ goto out_cleanup;
}
}
@@ -276,15 +268,15 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
case LEAPRAID_TM_TASKTYPE_TARGET_RESET:
case LEAPRAID_TM_TASKTYPE_ABRT_TASK_SET:
case LEAPRAID_TM_TASKTYPE_LOGICAL_UNIT_RESET:
- rc = leapraid_tm_post_processing(adapter, hdl, channel, id, lun,
- type, target_taskid);
+ rc = leapraid_tm_post_processing(adapter, hdl, channel, id,
+ lun, type, target_taskid);
break;
case LEAPRAID_TM_TASKTYPE_ABORT_TASK:
rc = SUCCESS;
scsiio_req = leapraid_get_task_desc(adapter, target_taskid);
if (le16_to_cpu(scsiio_req->dev_hdl) != hdl)
break;
- dev_err(&adapter->pdev->dev, "%s abort failed, hdl=0x%04x\n",
+ dev_err(&adapter->pdev->dev, "%s: Abort failed, hdl=0x%04x\n",
adapter->adapter_attr.name, hdl);
rc = FAILED;
break;
@@ -296,7 +288,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
break;
}
-out:
+out_cleanup:
leapraid_clear_tm_flg(adapter, hdl);
adapter->driver_cmds.tm_cmd.status = LEAPRAID_CMD_NOT_USED;
return rc;
@@ -327,20 +319,25 @@ void leapraid_smart_fault_detect(struct leapraid_adapter *adapter, u16 hdl)
sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl);
if (!sas_dev) {
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
- goto out;
+ return;
}
starget = sas_dev->starget;
- starget_priv = starget->hostdata;
- if ((starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER) ||
- (starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME)) {
+ starget_priv = starget ? starget->hostdata : NULL;
+ if (!starget_priv) {
+ spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
+ goto release_sdev;
+ }
+
+ if (starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER ||
+ starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME) {
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
- goto out;
+ goto release_sdev;
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
leapraid_async_turn_on_led(adapter, hdl);
-out:
+release_sdev:
if (sas_dev)
leapraid_sdev_put(sas_dev);
}
@@ -417,7 +414,8 @@ static void leapraid_handle_success_status(
scmd->result = DID_RESET << LEAPRAID_SCSI_HOST_SHIFT;
}
-static void leapraid_scsiio_done_dispatch(struct leapraid_adapter *adapter,
+static void leapraid_scsiio_done_dispatch(
+ struct leapraid_adapter *adapter,
struct leapraid_scsiio_rep *scsiio_rep,
struct leapraid_sdev_priv *sdev_priv,
struct scsi_cmnd *scmd,
@@ -439,9 +437,8 @@ static void leapraid_scsiio_done_dispatch(struct leapraid_adapter *adapter,
xfer_cnt == 0 &&
(scsi_status == LEAPRAID_SCSI_STATUS_BUSY ||
scsi_status == LEAPRAID_SCSI_STATUS_RESERVATION_CONFLICT ||
- scsi_status == LEAPRAID_SCSI_STATUS_TASK_SET_FULL)) {
+ scsi_status == LEAPRAID_SCSI_STATUS_TASK_SET_FULL))
adapter_status = LEAPRAID_ADAPTER_STATUS_SUCCESS;
- }
switch (adapter_status) {
case LEAPRAID_ADAPTER_STATUS_SCSI_DEVICE_NOT_THERE:
@@ -513,7 +510,7 @@ static void leapraid_scsiio_done_dispatch(struct leapraid_adapter *adapter,
scsi_print_command(scmd);
dev_warn(&adapter->pdev->dev,
- "scsiio warn: hdl=0x%x, status are: 0x%x, 0x%x, 0x%x\n",
+ "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);
@@ -523,24 +520,23 @@ static void leapraid_scsiio_done_dispatch(struct leapraid_adapter *adapter,
sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
le32_to_cpu(scsiio_rep->sense_count));
if (scsi_normalize_sense(scmd->sense_buffer, sz,
- &sshdr)) {
+ &sshdr))
dev_warn(&adapter->pdev->dev,
- "sense: key=0x%x asc=0x%x ascq=0x%x\n",
+ "Sense: key=0x%x asc=0x%x ascq=0x%x\n",
sshdr.sense_key, sshdr.asc,
sshdr.ascq);
- } else {
+ else
dev_warn(&adapter->pdev->dev,
- "sense: invalid sense data\n");
- }
+ "Sense: Invalid sense data\n");
}
}
-u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
- u8 msix_index, u32 rep)
+bool leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
+ u8 msix_index, u32 rep)
{
- struct leapraid_scsiio_rep *scsiio_rep = NULL;
- struct leapraid_sdev_priv *sdev_priv = NULL;
- struct scsi_cmnd *scmd = NULL;
+ struct leapraid_scsiio_rep *scsiio_rep;
+ struct leapraid_sdev_priv *sdev_priv;
+ struct scsi_cmnd *scmd;
u32 response_code = 0;
if (likely(taskid != adapter->driver_cmds.driver_scsiio_cmd.taskid))
@@ -548,12 +544,12 @@ u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
else
scmd = adapter->driver_cmds.internal_scmd;
if (!scmd)
- return 1;
+ return true;
scsiio_rep = leapraid_get_reply_vaddr(adapter, rep);
if (!scsiio_rep) {
scmd->result = DID_OK << LEAPRAID_SCSI_HOST_SHIFT;
- goto out;
+ goto out_scsiio_done;
}
sdev_priv = scmd->device->hostdata;
@@ -561,7 +557,7 @@ u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
!sdev_priv->starget_priv ||
sdev_priv->starget_priv->deleted) {
scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT;
- goto out;
+ goto out_scsiio_done;
}
if (scsiio_rep->scsi_state & LEAPRAID_SCSI_STATE_RESPONSE_INFO_VALID)
@@ -571,33 +567,51 @@ u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
leapraid_scsiio_done_dispatch(adapter, scsiio_rep, sdev_priv, scmd,
taskid, response_code);
-out:
+out_scsiio_done:
scsi_dma_unmap(scmd);
- if (unlikely(taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid)) {
+ 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 0;
+ return false;
}
leapraid_free_taskid(adapter, taskid);
scsi_done(scmd);
- return 0;
+ return false;
}
static void leapraid_probe_raid(struct leapraid_adapter *adapter)
{
- struct leapraid_raid_volume *raid_volume, *raid_volume_next;
+ struct leapraid_raid_volume *raid_volume, *next_raid_volume;
+ unsigned long flags;
+ LIST_HEAD(head);
int rc;
- list_for_each_entry_safe(raid_volume, raid_volume_next,
- &adapter->dev_topo.raid_volume_list, list) {
- if (raid_volume->starget)
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ list_splice_init(&adapter->dev_topo.raid_volume_list, &head);
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+
+ list_for_each_entry_safe(raid_volume, next_raid_volume, &head, list) {
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ list_move_tail(&raid_volume->list,
+ &adapter->dev_topo.raid_volume_list);
+ if (raid_volume->starget) {
+ spin_unlock_irqrestore(
+ &adapter->dev_topo.raid_volume_lock, flags);
continue;
+ }
+
+ leapraid_raid_volume_get(raid_volume);
+ spin_unlock_irqrestore(
+ &adapter->dev_topo.raid_volume_lock, flags);
rc = scsi_add_device(adapter->shost, RAID_CHANNEL,
raid_volume->id, 0);
if (rc)
leapraid_raid_volume_remove(adapter, raid_volume);
+
+ leapraid_raid_volume_put(raid_volume);
}
}
@@ -626,7 +640,6 @@ static void leapraid_probe_sas(struct leapraid_adapter *adapter)
sas_dev = leapraid_get_next_sas_dev_from_init_list(adapter);
if (!sas_dev)
break;
-
added = leapraid_transport_port_add(adapter,
sas_dev->hdl,
sas_dev->parent_sas_addr,
@@ -654,32 +667,52 @@ static void leapraid_probe_sas(struct leapraid_adapter *adapter)
}
}
-static bool leapraid_get_boot_dev(struct leapraid_boot_dev *boot_dev,
+static bool leapraid_get_boot_dev(struct leapraid_adapter *adapter,
+ struct leapraid_boot_dev *boot_dev,
void **pdev, u32 *pchnl)
{
- if (boot_dev->dev) {
- *pdev = boot_dev->dev;
- *pchnl = boot_dev->chnl;
- return true;
+ unsigned long flags;
+ void *dev;
+ u32 chnl;
+
+ spin_lock_irqsave(&adapter->boot_devs.lock, flags);
+ if (!boot_dev->dev) {
+ spin_unlock_irqrestore(&adapter->boot_devs.lock, flags);
+ return false;
}
- return false;
+
+ dev = boot_dev->dev;
+ chnl = boot_dev->chnl;
+ leapraid_boot_dev_get(dev, chnl);
+ spin_unlock_irqrestore(&adapter->boot_devs.lock, flags);
+
+ *pdev = dev;
+ *pchnl = chnl;
+ return true;
}
static void leapraid_probe_boot_dev(struct leapraid_adapter *adapter)
{
+ struct leapraid_raid_volume *raid_volume;
+ struct leapraid_sas_dev *sas_dev;
+ struct leapraid_sas_port *sport;
+ unsigned long flags;
void *dev = NULL;
u32 chnl;
- if (leapraid_get_boot_dev(&adapter->boot_devs.requested_boot_dev, &dev,
- &chnl))
+ if (leapraid_get_boot_dev(adapter,
+ &adapter->boot_devs.requested_boot_dev,
+ &dev, &chnl))
goto boot_dev_found;
- if (leapraid_get_boot_dev(&adapter->boot_devs.requested_alt_boot_dev,
+ if (leapraid_get_boot_dev(adapter,
+ &adapter->boot_devs.requested_alt_boot_dev,
&dev, &chnl))
goto boot_dev_found;
- if (leapraid_get_boot_dev(&adapter->boot_devs.current_boot_dev, &dev,
- &chnl))
+ if (leapraid_get_boot_dev(adapter,
+ &adapter->boot_devs.current_boot_dev,
+ &dev, &chnl))
goto boot_dev_found;
return;
@@ -687,12 +720,10 @@ static void leapraid_probe_boot_dev(struct leapraid_adapter *adapter)
boot_dev_found:
switch (chnl) {
case RAID_CHANNEL:
- {
- struct leapraid_raid_volume *raid_volume =
- (struct leapraid_raid_volume *)dev;
+ raid_volume = dev;
if (raid_volume->starget)
- return;
+ break;
/* TODO eedp */
@@ -700,16 +731,11 @@ static void leapraid_probe_boot_dev(struct leapraid_adapter *adapter)
raid_volume->id, 0))
leapraid_raid_volume_remove(adapter, raid_volume);
break;
- }
default:
- {
- struct leapraid_sas_dev *sas_dev =
- (struct leapraid_sas_dev *)dev;
- struct leapraid_sas_port *sas_port;
- unsigned long flags;
+ sas_dev = dev;
if (sas_dev->starget)
- return;
+ break;
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
list_move_tail(&sas_dev->list,
@@ -717,16 +743,17 @@ static void leapraid_probe_boot_dev(struct leapraid_adapter *adapter)
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
if (!sas_dev->card_port)
- return;
+ break;
- sas_port = leapraid_transport_port_add(adapter, sas_dev->hdl,
- sas_dev->parent_sas_addr,
- sas_dev->card_port);
- if (!sas_port)
+ sport = leapraid_transport_port_add(adapter, sas_dev->hdl,
+ sas_dev->parent_sas_addr,
+ sas_dev->card_port);
+ if (!sport)
leapraid_sas_dev_remove(adapter, sas_dev);
break;
}
- }
+
+ leapraid_boot_dev_put(dev, chnl);
}
static void leapraid_probe_devices(struct leapraid_adapter *adapter)
@@ -744,69 +771,23 @@ static void leapraid_probe_devices(struct leapraid_adapter *adapter)
void leapraid_scan_dev_done(struct leapraid_adapter *adapter)
{
if (adapter->scan_dev_desc.wait_scan_dev_done) {
- adapter->scan_dev_desc.wait_scan_dev_done = false;
+ adapter->scan_dev_desc.wait_scan_dev_done = 0;
leapraid_probe_devices(adapter);
}
+ adapter->scan_dev_desc.scan_start = 0;
+
leapraid_check_scheduled_fault_start(adapter);
leapraid_fw_log_start(adapter);
- adapter->scan_dev_desc.driver_loading = false;
+ adapter->scan_dev_desc.driver_loading = 0;
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
leapraid_smart_polling_start(adapter);
}
-static void leapraid_ir_shutdown(struct leapraid_adapter *adapter)
-{
- struct leapraid_raid_act_req *raid_act_req;
- struct leapraid_raid_act_rep *raid_act_rep;
- struct leapraid_driver_cmd *raid_action_cmd;
-
- if (!adapter || !adapter->adapter_attr.raid_support)
- return;
-
- if (list_empty(&adapter->dev_topo.raid_volume_list))
- return;
-
- if (leapraid_pci_removed(adapter))
- return;
-
- raid_action_cmd = &adapter->driver_cmds.raid_action_cmd;
-
- mutex_lock(&raid_action_cmd->mutex);
- raid_action_cmd->status = LEAPRAID_CMD_PENDING;
-
- raid_act_req = leapraid_get_task_desc(adapter,
- raid_action_cmd->inter_taskid);
- memset(raid_act_req, 0, sizeof(struct leapraid_raid_act_req));
- raid_act_req->func = LEAPRAID_FUNC_RAID_ACTION;
- raid_act_req->act = LEAPRAID_RAID_ACT_SYSTEM_SHUTDOWN_INITIATED;
-
- dev_info(&adapter->pdev->dev, "ir shutdown start\n");
- init_completion(&raid_action_cmd->done);
- leapraid_fire_task(adapter, raid_action_cmd->inter_taskid);
- wait_for_completion_timeout(&raid_action_cmd->done,
- LEAPRAID_RAID_ACTION_CMD_TIMEOUT * HZ);
-
- if (!(raid_action_cmd->status & LEAPRAID_CMD_DONE)) {
- dev_err(&adapter->pdev->dev,
- "%s: timeout waiting for ir shutdown\n", __func__);
- goto out;
- }
-
- if (raid_action_cmd->status & LEAPRAID_CMD_REPLY_VALID) {
- raid_act_rep = (void *)(&raid_action_cmd->reply);
- dev_info(&adapter->pdev->dev,
- "ir shutdown done, adapter status=0x%04x\n",
- le16_to_cpu(raid_act_rep->adapter_status));
- }
-
-out:
- raid_action_cmd->status = LEAPRAID_CMD_NOT_USED;
- mutex_unlock(&raid_action_cmd->mutex);
-}
-
static const struct pci_device_id leapraid_pci_table[] = {
- { PCI_DEVICE(LEAPRAID_VENDOR_ID, LEAPRAID_DEVID_HBA) },
- { PCI_DEVICE(LEAPRAID_VENDOR_ID, LEAPRAID_DEVID_RAID) },
+ { PCI_DEVICE_SUB(LEAPRAID_VENDOR_ID, LEAPRAID_DEVID_HBA,
+ LEAPRAID_SUBVENDOR_ID,
+ LEAPRAID_SUBDEVID_HBA) },
{ 0, }
};
@@ -816,7 +797,7 @@ static inline bool leapraid_is_scmd_permitted(struct leapraid_adapter *adapter,
u8 opcode;
if (adapter->access_ctrl.pcie_recovering ||
- adapter->access_ctrl.adapter_thermal_alert)
+ atomic_read(&adapter->overheat_desc.thermal_alert))
return false;
if (adapter->access_ctrl.host_removing) {
@@ -826,8 +807,8 @@ static inline bool leapraid_is_scmd_permitted(struct leapraid_adapter *adapter,
opcode = scmd->cmnd[0];
if (opcode == SYNCHRONIZE_CACHE || opcode == START_STOP)
return true;
- else
- return false;
+
+ return false;
}
return true;
}
@@ -854,28 +835,33 @@ static bool leapraid_should_queuecommand(struct leapraid_adapter *adapter,
scsi_build_sense(scmd, 0, UNIT_ATTENTION,
LEAPRAID_SCSI_ASC_POWER_ON_RESET,
LEAPRAID_SCSI_ASCQ_POWER_ON_RESET);
- goto done_out;
+ goto scsiio_done;
}
if (adapter->access_ctrl.shost_recovering ||
adapter->reset_desc.adapter_link_resetting) {
*rc = SCSI_MLQUEUE_HOST_BUSY;
- goto out;
- } else if (starget_priv->deleted || sdev_priv->deleted) {
+ return false;
+ }
+
+ if (starget_priv->deleted || sdev_priv->deleted)
goto no_connect;
- } else if (starget_priv->tm_busy || sdev_priv->block) {
+
+ if (starget_priv->tm_busy || sdev_priv->block) {
*rc = SCSI_MLQUEUE_DEVICE_BUSY;
- goto out;
+ return false;
}
return true;
no_connect:
scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT;
-done_out:
+scsiio_done:
if (likely(scmd != adapter->driver_cmds.internal_scmd))
scsi_done(scmd);
-out:
+ else
+ *rc = LEAPRAID_OPERATION_FAILED;
+
return false;
}
@@ -903,12 +889,14 @@ static u32 build_scsiio_req_control(struct scsi_cmnd *scmd,
IOPRIO_CLASS_RT))
control |= LEAPRAID_SCSIIO_CTRL_CMDPRI;
if (scmd->cmd_len == 32)
- control |= 4 << LEAPRAID_SCSIIO_CTRL_ADDCDBLEN_SHIFT;
+ control |= LEAPRAID_SCSIIO_CTRL_CDB_32BYTE <<
+ LEAPRAID_SCSIIO_CTRL_CDB_LEN_SHIFT;
return control;
}
-int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
+int leapraid_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmd)
{
struct leapraid_adapter *adapter = shost_priv(scmd->device->host);
struct leapraid_sdev_priv *sdev_priv = scmd->device->hostdata;
@@ -920,7 +908,7 @@ int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
int rc = 0;
if (!leapraid_should_queuecommand(adapter, sdev_priv, scmd, &rc))
- goto out;
+ return rc;
starget_priv = sdev_priv->starget_priv;
hdl = starget_priv->hdl;
@@ -932,11 +920,11 @@ int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
taskid = leapraid_alloc_scsiio_taskid(adapter, scmd);
scsiio_req = leapraid_get_task_desc(adapter, taskid);
- scsiio_req->func = LEAPRAID_FUNC_SCSIIO_REQ;
+ scsiio_req->func = LEAPRAID_FUNC_SCSIIO;
if (sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER)
- scsiio_req->func = LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH;
+ scsiio_req->func = LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH;
else
- scsiio_req->func = LEAPRAID_FUNC_SCSIIO_REQ;
+ scsiio_req->func = LEAPRAID_FUNC_SCSIIO;
scsiio_req->dev_hdl = cpu_to_le16(hdl);
scsiio_req->data_len = cpu_to_le32(scsi_bufflen(scmd));
@@ -954,23 +942,21 @@ int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
if (scsiio_req->data_len) {
if (leapraid_build_scmd_ieee_sg(adapter, scmd, taskid)) {
leapraid_free_taskid(adapter, taskid);
- rc = SCSI_MLQUEUE_HOST_BUSY;
- goto out;
+ return SCSI_MLQUEUE_HOST_BUSY;
}
} else {
leapraid_build_ieee_nodata_sg(adapter, &scsiio_req->sgl);
}
- if (likely(scsiio_req->func == LEAPRAID_FUNC_SCSIIO_REQ)) {
+ if (likely(scsiio_req->func == LEAPRAID_FUNC_SCSIIO))
leapraid_fire_scsi_io(adapter, taskid,
- le16_to_cpu(scsiio_req->dev_hdl));
- } else {
+ le16_to_cpu(scsiio_req->dev_hdl));
+ else
leapraid_fire_task(adapter, taskid);
- }
+
dev_dbg(&adapter->pdev->dev,
"LEAPRAID_SCSIIO: Send Descriptor taskid %d, req type 0x%x\n",
taskid, scsiio_req->func);
-out:
return rc;
}
@@ -980,7 +966,7 @@ static int leapraid_init_cmd_priv(struct Scsi_Host *shost,
struct leapraid_adapter *adapter = shost_priv(shost);
struct leapraid_io_req_tracker *io_tracker;
- io_tracker = leapraid_get_scmd_priv(scmd);
+ io_tracker = scsi_cmd_priv(scmd);
leapraid_internal_init_cmd_priv(adapter, io_tracker);
return 0;
@@ -992,7 +978,7 @@ static int leapraid_exit_cmd_priv(struct Scsi_Host *shost,
struct leapraid_adapter *adapter = shost_priv(shost);
struct leapraid_io_req_tracker *io_tracker;
- io_tracker = leapraid_get_scmd_priv(scmd);
+ io_tracker = scsi_cmd_priv(scmd);
leapraid_internal_exit_cmd_priv(adapter, io_tracker);
return 0;
@@ -1016,9 +1002,9 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd,
scsi_print_command(scmd);
if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK) {
- io_req_tracker = leapraid_get_scmd_priv(scmd);
+ io_req_tracker = scsi_cmd_priv(scmd);
dev_info(&adapter->pdev->dev,
- "EH ABORT: scmd=0x%p, pending=%u ms, tout=%u ms, req tag=%d\n",
+ "EH ABORT: scmd=0x%p, pend=%ums, tout=%ums, tag=%d\n",
scmd,
jiffies_to_msecs(jiffies - scmd->jiffies_at_alloc),
(scsi_cmd_to_rq(scmd)->timeout / HZ) * 1000,
@@ -1031,48 +1017,47 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd,
"EH %s failed: %s scmd=0x%p\n", str,
(adapter->access_ctrl.host_removing ?
"shost removing!" : "pci_dev removed!"), scmd);
- if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK)
- if (io_req_tracker && io_req_tracker->taskid)
- leapraid_free_taskid(adapter,
- io_req_tracker->taskid);
+ if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK &&
+ io_req_tracker && io_req_tracker->taskid)
+ leapraid_free_taskid(adapter, io_req_tracker->taskid);
scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT;
#ifdef FAST_IO_FAIL
rc = FAST_IO_FAIL;
#else
rc = FAILED;
#endif
- goto out;
+ goto out_eh_done;
}
sdev_priv = scmd->device->hostdata;
if (!sdev_priv || !sdev_priv->starget_priv) {
dev_warn(&adapter->pdev->dev,
- "EH %s: sdev or starget gone, scmd=0x%p\n",
+ "EH %s: SAS dev or starget gone, scmd=0x%p\n",
str, scmd);
scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT;
scsi_done(scmd);
rc = SUCCESS;
- goto out;
+ goto out_eh_done;
}
if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK) {
if (!io_req_tracker) {
dev_warn(&adapter->pdev->dev,
- "EH ABORT: no io tracker, scmd 0x%p\n", scmd);
+ "EH ABORT: No I/O tracker, scmd 0x%p\n", scmd);
scmd->result = DID_RESET << LEAPRAID_SCSI_HOST_SHIFT;
rc = SUCCESS;
- goto out;
+ goto out_eh_done;
}
if (sdev_priv->starget_priv->flg &
LEAPRAID_TGT_FLG_RAID_MEMBER ||
sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME) {
dev_err(&adapter->pdev->dev,
- "EH ABORT: skip RAID/VOLUME target, scmd=0x%p\n",
+ "EH ABORT: Skip RAID/VOLUME, scmd=0x%p\n",
scmd);
scmd->result = DID_RESET << LEAPRAID_SCSI_HOST_SHIFT;
rc = FAILED;
- goto out;
+ goto out_eh_done;
}
hdl = sdev_priv->starget_priv->hdl;
@@ -1090,11 +1075,11 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd,
if (!hdl) {
dev_err(&adapter->pdev->dev,
- "EH %s failed: target handle is 0, scmd=0x%p\n",
+ "EH %s failed: Target handle 0, scmd=0x%p\n",
str, scmd);
scmd->result = DID_RESET << LEAPRAID_SCSI_HOST_SHIFT;
rc = FAILED;
- goto out;
+ goto out_eh_done;
}
}
@@ -1102,24 +1087,27 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd,
"EH issue TM: type=%s, scmd=0x%p, hdl=0x%x\n",
str, scmd, hdl);
- rc = leapraid_issue_locked_tm(adapter, hdl, scmd->device->channel,
- scmd->device->id,
- (type == LEAPRAID_TM_TASKTYPE_TARGET_RESET ?
- 0 : scmd->device->lun),
- type,
- (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK ?
- io_req_tracker->taskid : 0),
- LEAPRAID_TM_MSGFLAGS_LINK_RESET);
-
-out:
+ rc = leapraid_issue_locked_tm(
+ adapter,
+ hdl,
+ scmd->device->channel,
+ scmd->device->id,
+ (type == LEAPRAID_TM_TASKTYPE_TARGET_RESET ?
+ 0 : scmd->device->lun),
+ type,
+ (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK ?
+ io_req_tracker->taskid : 0),
+ LEAPRAID_TM_MSGFLAGS_LINK_RESET);
+
+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);
+ rc == SUCCESS ? "success" : "failed", scmd);
} else {
dev_info(&adapter->pdev->dev,
"EH %s result: %s, scmd=0x%p\n",
- str, ((rc == SUCCESS) ? "success" : "failed"), scmd);
+ str, rc == SUCCESS ? "success" : "failed", scmd);
if (sas_dev)
leapraid_sdev_put(sas_dev);
}
@@ -1162,19 +1150,19 @@ static int leapraid_eh_host_reset_handler(struct scsi_cmnd *scmd)
(adapter->access_ctrl.host_removing ?
"shost removing!" : "driver loading!"), scmd);
rc = FAILED;
- goto out;
+ goto out_host_reset_done;
}
- dev_info(&adapter->pdev->dev, "%s:%d issuing hard reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: Issuing hard reset\n",
__func__, __LINE__);
if (leapraid_hard_reset_handler(adapter, FULL_RESET) < 0)
rc = FAILED;
else
rc = SUCCESS;
-out:
+out_host_reset_done:
dev_info(&adapter->pdev->dev, "EH HOST RESET result: %s, scmd=0x%p\n",
- ((rc == SUCCESS) ? "success" : "failed"), scmd);
+ rc == SUCCESS ? "success" : "failed", scmd);
return rc;
}
@@ -1200,30 +1188,35 @@ static int leapraid_slave_alloc(struct scsi_device *sdev)
stgt_priv->num_luns++;
sdev_priv->starget_priv = stgt_priv;
sdev->hostdata = sdev_priv;
- if ((stgt_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER))
+ if (stgt_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER)
sdev->no_uld_attach = LEAPRAID_NO_ULD_ATTACH;
shost = dev_to_shost(&tgt->dev);
adapter = shost_priv(shost);
if (tgt->channel == RAID_CHANNEL) {
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_id(adapter,
tgt->id,
tgt->channel);
- if (raid_volume)
+ if (raid_volume) {
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock,
+ flags);
raid_volume->sdev = sdev;
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
- flags);
+ spin_unlock_irqrestore(
+ &adapter->dev_topo.raid_volume_lock, flags);
+ leapraid_raid_volume_put(raid_volume);
+ }
}
if (!(stgt_priv->flg & LEAPRAID_TGT_FLG_VOLUME)) {
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
- sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter,
- stgt_priv->sas_address,
- stgt_priv->card_port);
+ sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(
+ adapter,
+ stgt_priv->sas_address,
+ stgt_priv->card_port);
if (sas_dev && !sas_dev->starget) {
sdev_printk(KERN_INFO, sdev,
- "%s: assign starget to sas_dev\n", __func__);
+ "%s: Assign starget to sas_dev\n",
+ __func__);
sas_dev->starget = tgt;
}
@@ -1241,7 +1234,6 @@ static int leapraid_slave_cfg_volume(struct scsi_device *sdev)
struct leapraid_raid_volume *raid_volume;
struct leapraid_starget_priv *starget_priv;
struct leapraid_sdev_priv *sdev_priv;
- unsigned long flags;
int qd;
u16 hdl;
@@ -1249,37 +1241,38 @@ static int leapraid_slave_cfg_volume(struct scsi_device *sdev)
starget_priv = sdev_priv->starget_priv;
hdl = starget_priv->hdl;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_hdl(adapter, hdl);
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
if (!raid_volume) {
sdev_printk(KERN_WARNING, sdev,
- "%s: raid_volume not found, hdl=0x%x\n",
+ "%s: RAID volume not found, hdl=0x%x\n",
__func__, hdl);
return 1;
}
if (leapraid_get_volume_cap(adapter, raid_volume)) {
sdev_printk(KERN_ERR, sdev,
- "%s: failed to get volume cap, hdl=0x%x\n",
+ "%s: Failed to get volume cap, hdl=0x%x\n",
__func__, hdl);
+ leapraid_raid_volume_put(raid_volume);
return 1;
}
qd = (raid_volume->dev_info & LEAPRAID_DEVTYP_SSP_TGT) ?
- LEAPRAID_SAS_QUEUE_DEPTH : LEAPRAID_SATA_QUEUE_DEPTH;
+ adapter->adapter_attr.narrowport_max_queue_depth :
+ adapter->adapter_attr.sata_max_queue_depth;
if (raid_volume->vol_type != LEAPRAID_VOL_TYPE_RAID0)
- qd = LEAPRAID_RAID_QUEUE_DEPTH;
+ qd = adapter->adapter_attr.raid_volume_max_queue_depth;
sdev_printk(KERN_INFO, sdev,
- "raid volume: hdl=0x%04x, wwid=0x%016llx\n",
+ "RAID volume: hdl=0x%04x, wwid=0x%016llx\n",
raid_volume->hdl, (unsigned long long)raid_volume->wwid);
if (shost->max_sectors > LEAPRAID_MAX_SECTORS)
blk_queue_max_hw_sectors(sdev->request_queue,
LEAPRAID_MAX_SECTORS);
- leapraid_adjust_sdev_queue_depth(sdev, qd);
+ leapraid_change_queue_depth(sdev, qd);
+ leapraid_raid_volume_put(raid_volume);
return 0;
}
@@ -1297,13 +1290,14 @@ static int leapraid_slave_configure_extra(struct scsi_device *sdev,
sdev_priv = sdev->hostdata;
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
*is_target_ssp = false;
- sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter,
- sdev_priv->starget_priv->sas_address,
- sdev_priv->starget_priv->card_port);
+ sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(
+ adapter,
+ sdev_priv->starget_priv->sas_address,
+ sdev_priv->starget_priv->card_port);
if (!sas_dev) {
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
sdev_printk(KERN_WARNING, sdev,
- "%s: sas_dev not found, sas=0x%llx\n",
+ "%s: SAS dev not found, sas=0x%llx\n",
__func__, sdev_priv->starget_priv->sas_address);
return 1;
}
@@ -1312,18 +1306,18 @@ static int leapraid_slave_configure_extra(struct scsi_device *sdev,
sas_dev->volume_hdl = vol_hdl;
sas_dev->volume_wwid = volume_wwid;
if (sas_dev->dev_info & LEAPRAID_DEVTYP_SSP_TGT) {
- *qd = (sas_dev->port_type > 1) ?
+ *qd = (sas_dev->port_connection > 1) ?
adapter->adapter_attr.wideport_max_queue_depth :
adapter->adapter_attr.narrowport_max_queue_depth;
*is_target_ssp = true;
if (sas_dev->dev_info & LEAPRAID_DEVTYP_SEP)
- sdev_priv->sep = true;
+ sdev_priv->sep = 1;
} else {
*qd = adapter->adapter_attr.sata_max_queue_depth;
}
sdev_printk(KERN_INFO, sdev,
- "sdev: dev name=0x%016llx, sas addr=0x%016llx\n",
+ "device name=0x%016llx, SAS addr=0x%016llx\n",
(unsigned long long)sas_dev->dev_name,
(unsigned long long)sas_dev->sas_addr);
leapraid_sdev_put(sas_dev);
@@ -1354,7 +1348,7 @@ static int leapraid_slave_configure(struct scsi_device *sdev)
if (starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER) {
if (leapraid_cfg_get_volume_hdl(adapter, hdl, &vol_hdl)) {
sdev_printk(KERN_WARNING, sdev,
- "%s: get volume hdl failed, hdl=0x%x\n",
+ "%s: Get volume hdl failed, hdl=0x%x\n",
__func__, hdl);
return 1;
}
@@ -1362,7 +1356,7 @@ static int leapraid_slave_configure(struct scsi_device *sdev)
if (vol_hdl && leapraid_cfg_get_volume_wwid(adapter, vol_hdl,
&volume_wwid)) {
sdev_printk(KERN_WARNING, sdev,
- "%s: get wwid failed, volume_hdl=0x%x\n",
+ "%s: Get wwid failed, volume_hdl=0x%x\n",
__func__, vol_hdl);
return 1;
}
@@ -1375,7 +1369,7 @@ static int leapraid_slave_configure(struct scsi_device *sdev)
return 1;
}
- leapraid_adjust_sdev_queue_depth(sdev, qd);
+ leapraid_change_queue_depth(sdev, qd);
if (is_target_ssp)
sas_read_port_mode_page(sdev);
@@ -1422,17 +1416,19 @@ static int leapraid_target_alloc_raid(struct scsi_target *tgt)
struct leapraid_adapter *adapter = shost_priv(shost);
unsigned long flags;
- starget_priv = (struct leapraid_starget_priv *)tgt->hostdata;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ starget_priv = tgt->hostdata;
raid_volume = leapraid_raid_volume_find_by_id(adapter, tgt->id,
tgt->channel);
if (raid_volume) {
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
starget_priv->hdl = raid_volume->hdl;
starget_priv->sas_address = raid_volume->wwid;
starget_priv->flg |= LEAPRAID_TGT_FLG_VOLUME;
raid_volume->starget = tgt;
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
+ flags);
+ leapraid_raid_volume_put(raid_volume);
}
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
return 0;
}
@@ -1447,12 +1443,13 @@ static int leapraid_target_alloc_sas(struct scsi_target *tgt)
shost = dev_to_shost(&tgt->dev);
adapter = shost_priv(shost);
- starget_priv = (struct leapraid_starget_priv *)tgt->hostdata;
+ starget_priv = tgt->hostdata;
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
rphy = dev_to_rphy(tgt->dev.parent);
- sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(adapter,
- rphy->identify.sas_address,
- rphy);
+ sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(
+ adapter,
+ rphy->identify.sas_address,
+ rphy);
if (sas_dev) {
starget_priv->sas_dev = sas_dev;
starget_priv->card_port = sas_dev->card_port;
@@ -1461,8 +1458,10 @@ static int leapraid_target_alloc_sas(struct scsi_target *tgt)
sas_dev->channel = tgt->channel;
sas_dev->id = tgt->id;
sas_dev->starget = tgt;
- if (test_bit(sas_dev->hdl,
- (unsigned long *)adapter->dev_topo.pd_hdls))
+ if (sas_dev->hdl &&
+ sas_dev->hdl <=
+ adapter->adapter_attr.features.max_dev_handle &&
+ test_bit(sas_dev->hdl, adapter->dev_topo.pd_hdls))
starget_priv->flg |= LEAPRAID_TGT_FLG_RAID_MEMBER;
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -1494,14 +1493,16 @@ static void leapraid_target_destroy_raid(struct scsi_target *tgt)
struct leapraid_adapter *adapter = shost_priv(shost);
unsigned long flags;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_id(adapter, tgt->id,
tgt->channel);
if (raid_volume) {
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume->starget = NULL;
raid_volume->sdev = NULL;
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
+ flags);
+ leapraid_raid_volume_put(raid_volume);
}
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
}
static void leapraid_target_destroy_sas(struct scsi_target *tgt)
@@ -1543,12 +1544,12 @@ static void leapraid_target_destroy(struct scsi_target *tgt)
if (tgt->channel == RAID_CHANNEL) {
leapraid_target_destroy_raid(tgt);
- goto out;
+ goto out_free;
}
leapraid_target_destroy_sas(tgt);
-out:
+out_free:
kfree(starget_priv);
tgt->hostdata = NULL;
}
@@ -1569,24 +1570,27 @@ static bool leapraid_scan_check_status(struct leapraid_adapter *adapter,
if (adapter->driver_cmds.scan_dev_cmd.status & LEAPRAID_CMD_RESET) {
dev_err(&adapter->pdev->dev,
- "device scan: aborted due to reset\n");
+ "Device scan: Aborted due to reset\n");
adapter->driver_cmds.scan_dev_cmd.status =
LEAPRAID_CMD_NOT_USED;
- adapter->scan_dev_desc.driver_loading = false;
+ adapter->scan_dev_desc.driver_loading = 0;
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
return true;
}
if (adapter->scan_dev_desc.scan_start_failed) {
dev_err(&adapter->pdev->dev,
- "device scan: failed with adapter_status=0x%08x\n",
+ "Device scan: Failed with adapter_status=0x%08x\n",
adapter->scan_dev_desc.scan_start_failed);
- adapter->scan_dev_desc.driver_loading = false;
- adapter->scan_dev_desc.wait_scan_dev_done = false;
- adapter->access_ctrl.host_removing = true;
+ adapter->scan_dev_desc.driver_loading = 0;
+ 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");
+ 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;
@@ -1601,8 +1605,9 @@ static int leapraid_scan_finished(struct Scsi_Host *shost, unsigned long time)
adapter->driver_cmds.scan_dev_cmd.status =
LEAPRAID_CMD_NOT_USED;
dev_err(&adapter->pdev->dev,
- "device scan: failed with timeout 300s\n");
- adapter->scan_dev_desc.driver_loading = false;
+ "Device scan: Failed with timeout 300s\n");
+ adapter->scan_dev_desc.driver_loading = 0;
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
return 1;
}
@@ -1612,10 +1617,12 @@ static int leapraid_scan_finished(struct Scsi_Host *shost, unsigned long time)
if (need_hard_reset) {
adapter->driver_cmds.scan_dev_cmd.status =
LEAPRAID_CMD_NOT_USED;
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
- if (leapraid_hard_reset_handler(adapter, PART_RESET))
- adapter->scan_dev_desc.driver_loading = false;
+ if (leapraid_hard_reset_handler(adapter, PART_RESET)) {
+ adapter->scan_dev_desc.driver_loading = 0;
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
+ }
}
return 1;
@@ -1625,18 +1632,88 @@ static void leapraid_scan_start(struct Scsi_Host *shost)
{
struct leapraid_adapter *adapter = shost_priv(shost);
- adapter->scan_dev_desc.scan_start = true;
+ adapter->scan_dev_desc.scan_start = 1;
leapraid_scan_dev(adapter, true);
}
+static u32 leapraid_get_raid_qd(struct leapraid_adapter *adapter,
+ const struct leapraid_raid_volume *raid_volume,
+ bool default_qd)
+{
+ const struct leapraid_adapter_attr *attr = &adapter->adapter_attr;
+
+ if (raid_volume->vol_type != LEAPRAID_VOL_TYPE_RAID0)
+ return default_qd ? LEAPRAID_RAID_QUEUE_DEPTH :
+ attr->raid_volume_max_queue_depth;
+
+ if (raid_volume->dev_info & LEAPRAID_DEVTYP_SSP_TGT)
+ return default_qd ? LEAPRAID_SAS_QUEUE_DEPTH :
+ attr->narrowport_max_queue_depth;
+
+ return default_qd ? LEAPRAID_SATA_QUEUE_DEPTH :
+ attr->sata_max_queue_depth;
+}
+
static int leapraid_calc_max_queue_depth(struct scsi_device *sdev, int qdepth)
{
struct Scsi_Host *shost;
+ struct leapraid_adapter *adapter;
+ struct leapraid_starget_priv *starget_priv;
+ struct leapraid_sdev_priv *sdev_priv;
+ struct leapraid_raid_volume *raid_volume;
+ struct leapraid_sas_dev *sas_dev;
int max_depth;
+ u32 default_qdepth = 0;
+ u32 fw_qdepth = 0;
shost = sdev->host;
+ adapter = shost_priv(shost);
max_depth = shost->can_queue;
+ sdev_priv = sdev->hostdata;
+ if (!sdev_priv)
+ goto out_tag_check;
+
+ starget_priv = sdev_priv->starget_priv;
+ if (!starget_priv)
+ goto out_tag_check;
+
+ if (starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME) {
+ raid_volume = leapraid_raid_volume_find_by_hdl(
+ adapter, starget_priv->hdl);
+ if (raid_volume) {
+ default_qdepth = leapraid_get_raid_qd(
+ adapter, raid_volume, true);
+ fw_qdepth = leapraid_get_raid_qd(
+ adapter, raid_volume, false);
+ leapraid_raid_volume_put(raid_volume);
+ }
+ goto out_limit_check;
+ }
+
+ sas_dev = leapraid_get_sas_dev_from_tgt(adapter, starget_priv);
+ if (sas_dev) {
+ if (sas_dev->dev_info & LEAPRAID_DEVTYP_SSP_TGT) {
+ default_qdepth = LEAPRAID_SAS_QUEUE_DEPTH;
+ fw_qdepth = (sas_dev->port_connection > 1) ?
+ adapter->adapter_attr.wideport_max_queue_depth :
+ adapter->adapter_attr.narrowport_max_queue_depth;
+ }
+ if (sas_dev->dev_info & LEAPRAID_DEVTYP_SATA_DEV) {
+ default_qdepth = LEAPRAID_SATA_QUEUE_DEPTH;
+ fw_qdepth = adapter->adapter_attr.sata_max_queue_depth;
+ }
+ leapraid_sdev_put(sas_dev);
+ }
+
+out_limit_check:
+ if (fw_qdepth > shost->can_queue && default_qdepth)
+ fw_qdepth = default_qdepth;
+
+ if (fw_qdepth)
+ max_depth = min_t(int, max_depth, fw_qdepth);
+
+out_tag_check:
if (!sdev->tagged_supported)
max_depth = 1;
@@ -1646,18 +1723,13 @@ static int leapraid_calc_max_queue_depth(struct scsi_device *sdev, int qdepth)
return qdepth;
}
-static int leapraid_change_queue_depth(struct scsi_device *sdev, int qdepth)
+int leapraid_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
qdepth = leapraid_calc_max_queue_depth(sdev, qdepth);
scsi_change_queue_depth(sdev, qdepth);
return sdev->queue_depth;
}
-void leapraid_adjust_sdev_queue_depth(struct scsi_device *sdev, int qdepth)
-{
- leapraid_change_queue_depth(sdev, qdepth);
-}
-
static void leapraid_map_queues(struct Scsi_Host *shost)
{
struct leapraid_adapter *adapter;
@@ -1669,7 +1741,7 @@ static void leapraid_map_queues(struct Scsi_Host *shost)
adapter = (struct leapraid_adapter *)shost->hostdata;
if (shost->nr_hw_queues == 1)
- goto out;
+ return;
msix_queue_count = adapter->notification_desc.iopoll_qdex;
poll_queue_count = adapter->adapter_attr.rq_cnt - msix_queue_count;
@@ -1683,7 +1755,7 @@ static void leapraid_map_queues(struct Scsi_Host *shost)
case HCTX_TYPE_DEFAULT:
queue_map->nr_queues = msix_queue_count;
queue_map->queue_offset = queue_offset;
- BUG_ON(!queue_map->nr_queues);
+ WARN_ON_ONCE(!queue_map->nr_queues);
blk_mq_pci_map_queues(queue_map, adapter->pdev, 0);
break;
case HCTX_TYPE_POLL:
@@ -1698,9 +1770,6 @@ static void leapraid_map_queues(struct Scsi_Host *shost)
}
queue_offset += queue_map->nr_queues;
}
-
-out:
- return;
}
int leapraid_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num)
@@ -1711,13 +1780,13 @@ int leapraid_blk_mq_poll(struct Scsi_Host *shost, unsigned int queue_num)
int num_entries;
int qid = queue_num - adapter->notification_desc.iopoll_qdex;
- if (atomic_read(&adapter->notification_desc.blk_mq_poll_rqs[qid].pause) ||
- !atomic_add_unless(&adapter->notification_desc.blk_mq_poll_rqs[qid].busy, 1, 1))
+ blk_mq_poll_rq = &adapter->notification_desc.blk_mq_poll_rqs[qid];
+ if (atomic_read(&blk_mq_poll_rq->pause) ||
+ !atomic_add_unless(&blk_mq_poll_rq->busy, 1, 1))
return 0;
- blk_mq_poll_rq = &adapter->notification_desc.blk_mq_poll_rqs[qid];
num_entries = leapraid_rep_queue_handler(&blk_mq_poll_rq->rq);
- atomic_dec(&adapter->notification_desc.blk_mq_poll_rqs[qid].busy);
+ atomic_dec(&blk_mq_poll_rq->busy);
return num_entries;
}
@@ -1725,8 +1794,8 @@ static int leapraid_bios_param(struct scsi_device *sdev,
struct block_device *bdev,
sector_t capacity, int geom[])
{
- int heads = 0;
- int sectors = 0;
+ int heads;
+ int sectors;
sector_t cylinders;
if (scsi_partsize(bdev, capacity, geom))
@@ -1770,12 +1839,23 @@ static ssize_t host_sas_address_show(struct device *cdev,
(unsigned long long)adapter->dev_topo.card.sas_address);
}
+static ssize_t board_name_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct leapraid_adapter *adapter = shost_priv(shost);
+
+ return sysfs_emit(buf, "%s\n", adapter->adapter_attr.board_name);
+}
+
static DEVICE_ATTR_RO(fw_queue_depth);
static DEVICE_ATTR_RO(host_sas_address);
+static DEVICE_ATTR_RO(board_name);
static struct attribute *leapraid_shost_attrs[] = {
&dev_attr_fw_queue_depth.attr,
&dev_attr_host_sas_address.attr,
+ &dev_attr_board_name.attr,
NULL,
};
@@ -1786,9 +1866,17 @@ static ssize_t sas_address_show(struct device *dev,
{
struct scsi_device *sdev = to_scsi_device(dev);
struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata;
+ u64 sas_address;
- return sysfs_emit(buf, "0x%016llx\n",
- (unsigned long long)sas_device_priv_data->starget_priv->sas_address);
+ 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;
+ }
+
+ sas_address = sas_device_priv_data->starget_priv->sas_address;
+
+ return sysfs_emit(buf, "0x%016llx\n", (unsigned long long)sas_address);
}
static ssize_t sas_device_handle_show(struct device *dev,
@@ -1797,6 +1885,12 @@ static ssize_t sas_device_handle_show(struct device *dev,
struct scsi_device *sdev = to_scsi_device(dev);
struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata;
+ 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;
+ }
+
return sysfs_emit(buf, "0x%04x\n",
sas_device_priv_data->starget_priv->hdl);
}
@@ -1807,6 +1901,12 @@ static ssize_t sas_ncq_show(struct device *dev, struct device_attribute *attr,
struct scsi_device *sdev = to_scsi_device(dev);
struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data) {
+ dev_err(&sdev->sdev_gendev,
+ "%s: Invalid sdev_priv\n", __func__);
+ return -EINVAL;
+ }
+
return sysfs_emit(buf, "%d\n", sas_device_priv_data->ncq);
}
@@ -1817,17 +1917,30 @@ static ssize_t sas_ncq_store(struct device *dev,
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 = 0;
- bool ncq_supported = false;
+ int ncq_op;
+ bool ncq_supported;
+
+ if (!sas_device_priv_data) {
+ dev_err(&sdev->sdev_gendev,
+ "%s: Invalid sdev_priv\n", __func__);
+ return -EINVAL;
+ }
if (kstrtoint(buf, 0, &ncq_op))
- goto out;
+ 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);
+ 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();
- goto out;
+ return -EINVAL;
}
ncq_supported = (vpd_pg89->data[LEAPRAID_VPD_PG89_NCQ_BYTE_IDX] >>
@@ -1836,9 +1949,7 @@ static ssize_t sas_ncq_store(struct device *dev,
rcu_read_unlock();
if (ncq_supported)
sas_device_priv_data->ncq = ncq_op;
- return strlen(buf);
-out:
- return -EINVAL;
+ return count;
}
static DEVICE_ATTR_RO(sas_address);
@@ -1881,7 +1992,7 @@ static struct scsi_host_template leapraid_driver_template = {
.can_queue = LEAPRAID_CAN_QUEUE_MIN,
.this_id = LEAPRAID_THIS_ID_NONE,
.sg_tablesize = LEAPRAID_SG_DEPTH,
- .max_sectors = LEAPRAID_DEF_MAX_SECTORS,
+ .max_sectors = LEAPRAID_MAX_SECTORS,
.max_segment_size = LEAPRAID_MAX_SEGMENT_SIZE,
.cmd_per_lun = LEAPRAID_CMD_PER_LUN,
.shost_groups = leapraid_shost_groups,
@@ -1901,6 +2012,8 @@ static void leapraid_lock_init(struct leapraid_adapter *adapter)
spin_lock_init(&adapter->dev_topo.topo_node_lock);
spin_lock_init(&adapter->fw_evt_s.fw_evt_lock);
spin_lock_init(&adapter->dev_topo.raid_volume_lock);
+ spin_lock_init(&adapter->dev_topo.enc_lock);
+ spin_lock_init(&adapter->boot_devs.lock);
}
static void leapraid_list_init(struct leapraid_adapter *adapter)
@@ -1917,19 +2030,24 @@ static void leapraid_list_init(struct leapraid_adapter *adapter)
static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
- struct leapraid_adapter *adapter = NULL;
- struct Scsi_Host *shost = NULL;
- int iopoll_q_count = 0;
+ struct leapraid_adapter *adapter;
+ struct Scsi_Host *shost;
+ int iopoll_q_count;
int rc;
shost = scsi_host_alloc(&leapraid_driver_template,
sizeof(struct leapraid_adapter));
- if (!shost)
+ if (!shost) {
+ dev_err(&pdev->dev,
+ "%s: SCSI host alloc failed\n", __func__);
return -ENODEV;
+ }
adapter = shost_priv(shost);
memset(adapter, 0, sizeof(struct leapraid_adapter));
- adapter->adapter_attr.id = leapraid_ids++;
+
+ init_waitqueue_head(&adapter->access_ctrl.recovery_waitq);
+ adapter->adapter_attr.id = atomic_inc_return(&leapraid_ids) - 1;
adapter->adapter_attr.enable_mp = enable_mp;
@@ -1944,8 +2062,8 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
adapter->fw_log_desc.open_pcie_trace = open_pcie_trace;
leapraid_lock_init(adapter);
leapraid_list_init(adapter);
- sprintf(adapter->adapter_attr.name, "%s%d",
- LEAPRAID_DRIVER_NAME, adapter->adapter_attr.id);
+ snprintf(adapter->adapter_attr.name, LEAPRAID_NAME_LENGTH, "%s%d",
+ LEAPRAID_DRIVER_NAME, adapter->adapter_attr.id);
shost->max_cmd_len = LEAPRAID_MAX_CDB_LEN;
shost->max_lun = LEAPRAID_MAX_LUNS;
@@ -1959,13 +2077,18 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
adapter->fw_evt_s.fw_evt_thread =
alloc_ordered_workqueue(adapter->fw_evt_s.fw_evt_name, 0);
if (!adapter->fw_evt_s.fw_evt_thread) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to create fw event workqueue\n", __func__);
rc = -ENODEV;
goto evt_wq_fail;
}
shost->host_tagset = 1;
- adapter->scan_dev_desc.driver_loading = true;
- if ((leapraid_ctrl_init(adapter))) {
+ init_waitqueue_head(&adapter->scan_dev_desc.wait_driver_loading);
+ adapter->scan_dev_desc.driver_loading = 1;
+ if (leapraid_ctrl_init(adapter)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Adapter init failed\n", __func__);
rc = -ENODEV;
goto ctrl_init_fail;
}
@@ -1977,15 +2100,14 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
adapter->notification_desc.iopoll_qdex;
shost->nr_maps = iopoll_q_count ? 3 : 1;
dev_info(&adapter->pdev->dev,
- "max scsi io cmds %d shared with nr_hw_queues=%d\n",
+ "Max scsi I/O cmds %d shared with nr_hw_queues=%d\n",
shost->can_queue, shost->nr_hw_queues);
}
rc = scsi_add_host(shost, &pdev->dev);
if (rc) {
- spin_lock(&leapraid_adapter_lock);
- list_del(&adapter->list);
- spin_unlock(&leapraid_adapter_lock);
+ dev_err(&pdev->dev,
+ "%s: SCSI host add failed\n", __func__);
goto scsi_add_shost_fail;
}
@@ -1995,6 +2117,7 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
scsi_add_shost_fail:
leapraid_remove_ctrl(adapter);
ctrl_init_fail:
+ leapraid_overheat_cleanup(adapter);
destroy_workqueue(adapter->fw_evt_s.fw_evt_thread);
evt_wq_fail:
spin_lock(&leapraid_adapter_lock);
@@ -2004,7 +2127,7 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return rc;
}
-static void leapraid_cleanup_lists(struct leapraid_adapter *adapter)
+void leapraid_cleanup_lists(struct leapraid_adapter *adapter)
{
struct leapraid_raid_volume *raid_volume, *next_raid_volume;
struct leapraid_starget_priv *starget_priv_data;
@@ -2016,12 +2139,14 @@ static void leapraid_cleanup_lists(struct leapraid_adapter *adapter)
&adapter->dev_topo.raid_volume_list, list) {
if (raid_volume->starget) {
starget_priv_data = raid_volume->starget->hostdata;
- starget_priv_data->deleted = true;
+ if (starget_priv_data)
+ starget_priv_data->deleted = 1;
scsi_remove_target(&raid_volume->starget->dev);
}
- pr_info("removing hdl=0x%04x, wwid=0x%016llx\n",
- raid_volume->hdl,
- (unsigned long long)raid_volume->wwid);
+ dev_info(&adapter->pdev->dev,
+ "removing hdl=0x%04x, wwid=0x%016llx\n",
+ raid_volume->hdl,
+ (unsigned long long)raid_volume->wwid);
leapraid_raid_volume_remove(adapter, raid_volume);
}
@@ -2030,16 +2155,18 @@ static void leapraid_cleanup_lists(struct leapraid_adapter *adapter)
port_list) {
if (leapraid_port->remote_identify.device_type ==
SAS_END_DEVICE)
- leapraid_sas_dev_remove_by_sas_address(adapter,
+ leapraid_sas_dev_remove_by_sas_address(
+ adapter,
leapraid_port->remote_identify.sas_address,
leapraid_port->card_port);
else if (leapraid_port->remote_identify.device_type ==
SAS_EDGE_EXPANDER_DEVICE ||
leapraid_port->remote_identify.device_type ==
SAS_FANOUT_EXPANDER_DEVICE)
- leapraid_exp_rm(adapter,
- leapraid_port->remote_identify.sas_address,
- leapraid_port->card_port);
+ leapraid_exp_rm(
+ adapter,
+ leapraid_port->remote_identify.sas_address,
+ leapraid_port->card_port);
}
list_for_each_entry_safe(port, port_next,
@@ -2064,27 +2191,26 @@ static void leapraid_cleanup_lists(struct leapraid_adapter *adapter)
static void leapraid_remove(struct pci_dev *pdev)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct workqueue_struct *wq;
unsigned long flags;
if (!shost || !adapter) {
- dev_err(&pdev->dev, "unable to remove!\n");
+ dev_err(&pdev->dev, "Unable to remove!\n");
return;
}
- while (adapter->scan_dev_desc.driver_loading)
- ssleep(1);
-
- while (adapter->access_ctrl.shost_recovering)
- ssleep(1);
+ wait_event(adapter->scan_dev_desc.wait_driver_loading,
+ !adapter->scan_dev_desc.driver_loading);
+ wait_event(adapter->scan_dev_desc.wait_driver_loading,
+ !atomic_read(&adapter->overheat_desc.thermal_alert));
- adapter->access_ctrl.host_removing = true;
+ adapter->access_ctrl.host_removing = 1;
+ wake_up(&adapter->access_ctrl.recovery_waitq);
leapraid_wait_cmds_done(adapter);
leapraid_smart_polling_stop(adapter);
- leapraid_free_internal_scsi_cmd(adapter);
if (leapraid_pci_removed(adapter)) {
leapraid_mq_polling_pause(adapter);
@@ -2099,7 +2225,6 @@ static void leapraid_remove(struct pci_dev *pdev)
if (wq)
destroy_workqueue(wq);
- leapraid_ir_shutdown(adapter);
sas_remove_host(shost);
leapraid_cleanup_lists(adapter);
leapraid_remove_ctrl(adapter);
@@ -2112,18 +2237,20 @@ static void leapraid_remove(struct pci_dev *pdev)
static void leapraid_shutdown(struct pci_dev *pdev)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct workqueue_struct *wq;
unsigned long flags;
if (!shost || !adapter) {
- dev_err(&pdev->dev, "unable to shutdown!\n");
+ dev_err(&pdev->dev, "Unable to shutdown!\n");
return;
}
- adapter->access_ctrl.host_removing = true;
+ 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);
leapraid_fw_log_stop(adapter);
spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
wq = adapter->fw_evt_s.fw_evt_thread;
@@ -2132,7 +2259,6 @@ static void leapraid_shutdown(struct pci_dev *pdev)
if (wq)
destroy_workqueue(wq);
- leapraid_ir_shutdown(adapter);
leapraid_disable_controller(adapter);
}
@@ -2140,29 +2266,31 @@ static pci_ers_result_t leapraid_pci_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
if (!shost || !adapter) {
- dev_err(&pdev->dev, "failed to error detected for device\n");
+ dev_err(&pdev->dev, "Failed to error detected for device\n");
return PCI_ERS_RESULT_DISCONNECT;
}
- pr_err("%s: pci error detected, state=%d\n",
- adapter->adapter_attr.name, state);
+ dev_err(&pdev->dev, "%s: PCI error detected, state=%d\n",
+ adapter->adapter_attr.name, state);
switch (state) {
case pci_channel_io_normal:
return PCI_ERS_RESULT_CAN_RECOVER;
case pci_channel_io_frozen:
- adapter->access_ctrl.pcie_recovering = true;
+ 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);
return PCI_ERS_RESULT_NEED_RESET;
case pci_channel_io_perm_failure:
- adapter->access_ctrl.pcie_recovering = true;
+ 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);
@@ -2177,15 +2305,15 @@ static pci_ers_result_t leapraid_pci_error_detected(struct pci_dev *pdev,
static pci_ers_result_t leapraid_pci_mmio_enabled(struct pci_dev *pdev)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
if (!shost || !adapter) {
dev_err(&pdev->dev,
- "failed to enable mmio for device\n");
+ "Failed to enable mmio for device\n");
return PCI_ERS_RESULT_DISCONNECT;
}
- dev_info(&pdev->dev, "%s: pci error mmio enabled\n",
+ dev_info(&pdev->dev, "%s: PCI error mmio enabled\n",
adapter->adapter_attr.name);
return PCI_ERS_RESULT_RECOVERED;
@@ -2194,43 +2322,47 @@ static pci_ers_result_t leapraid_pci_mmio_enabled(struct pci_dev *pdev)
static pci_ers_result_t leapraid_pci_slot_reset(struct pci_dev *pdev)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
int rc;
if (!shost || !adapter) {
dev_err(&pdev->dev,
- "failed to slot reset for device\n");
+ "Failed to slot reset for device\n");
return PCI_ERS_RESULT_DISCONNECT;
}
- dev_err(&pdev->dev, "%s pci error slot reset\n",
+ dev_err(&pdev->dev, "%s PCI error slot reset\n",
adapter->adapter_attr.name);
- adapter->access_ctrl.pcie_recovering = false;
+ adapter->access_ctrl.pcie_recovering = 0;
adapter->pdev = pdev;
pci_restore_state(pdev);
- if (leapraid_set_pcie_and_notification(adapter))
+ if (leapraid_set_pcie_and_notification(adapter)) {
+ dev_err(&pdev->dev,
+ "%s: Failed to set PCIe state and notification\n",
+ __func__);
return PCI_ERS_RESULT_DISCONNECT;
+ }
- dev_info(&pdev->dev, "%s: hard reset triggered by pci slot reset\n",
+ 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",
+ 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");
+ adapter->adapter_attr.name, rc == 0 ? "success" : "failed");
- return (rc == 0) ? PCI_ERS_RESULT_RECOVERED :
+ return rc == 0 ? PCI_ERS_RESULT_RECOVERED :
PCI_ERS_RESULT_DISCONNECT;
}
static void leapraid_pci_resume(struct pci_dev *pdev)
{
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
if (!shost || !adapter) {
- dev_err(&pdev->dev, "failed to resume\n");
+ dev_err(&pdev->dev, "Failed to resume\n");
return;
}
@@ -2254,23 +2386,23 @@ static struct pci_error_handlers leapraid_err_handler = {
static int leapraid_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
pci_power_t device_state;
if (!shost || !adapter) {
dev_err(&pdev->dev,
- "suspend failed, invalid host or adapter\n");
+ "Suspend failed, invalid host or adapter\n");
return -ENXIO;
}
+ leapraid_overheat_cleanup(adapter);
leapraid_smart_polling_stop(adapter);
leapraid_check_scheduled_fault_stop(adapter);
leapraid_fw_log_stop(adapter);
scsi_block_requests(shost);
device_state = pci_choose_state(pdev, state);
- leapraid_ir_shutdown(adapter);
- dev_info(&pdev->dev, "entering PCI power state D%d, (slot=%s)\n",
+ dev_info(&pdev->dev, "Entering PCI power state D%d, (slot=%s)\n",
device_state, pci_name(pdev));
pci_save_state(pdev);
@@ -2282,18 +2414,18 @@ static int leapraid_suspend(struct pci_dev *pdev, pm_message_t state)
static int leapraid_resume(struct pci_dev *pdev)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
pci_power_t device_state = pdev->current_state;
int rc;
if (!shost || !adapter) {
dev_err(&pdev->dev,
- "resume failed, invalid host or adapter\n");
+ "Resume failed, invalid host or adapter\n");
return -ENXIO;
}
dev_info(&pdev->dev,
- "resuming device %s, previous state D%d\n",
+ "Resuming device %s, previous state D%d\n",
pci_name(pdev), device_state);
pci_set_power_state(pdev, PCI_D0);
@@ -2301,12 +2433,22 @@ static int leapraid_resume(struct pci_dev *pdev)
pci_restore_state(pdev);
adapter->pdev = pdev;
rc = leapraid_set_pcie_and_notification(adapter);
- if (rc)
+ if (rc) {
+ dev_err(&pdev->dev,
+ "%s: Failed to set PCIe state and notification\n",
+ __func__);
return rc;
+ }
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
- leapraid_hard_reset_handler(adapter, PART_RESET);
+ rc = leapraid_hard_reset_handler(adapter, PART_RESET);
+ if (rc) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Hard reset failed during resume, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
scsi_unblock_requests(shost);
leapraid_check_scheduled_fault_start(adapter);
leapraid_fw_log_start(adapter);
@@ -2332,29 +2474,37 @@ static int __init leapraid_init(void)
{
int error;
- pr_info("%s version %s loaded\n", LEAPRAID_DRIVER_NAME,
- LEAPRAID_DRIVER_VERSION);
+ pr_info("%s initializing\n", LEAPRAID_DRIVER_NAME);
leapraid_transport_template =
sas_attach_transport(&leapraid_transport_functions);
- if (!leapraid_transport_template)
+ if (!leapraid_transport_template) {
+ pr_err("%s: Failed to attach SAS transport\n",
+ LEAPRAID_DRIVER_NAME);
return -ENODEV;
-
- leapraid_ids = 0;
-
- leapraid_ctl_init();
+ }
error = pci_register_driver(&leapraid_driver);
- if (error)
+ if (error) {
+ pr_err("%s: PCI driver registration failed: %d\n",
+ LEAPRAID_DRIVER_NAME, error);
+ sas_release_transport(leapraid_transport_template);
+ return error;
+ }
+
+ error = leapraid_ctl_init();
+ if (error) {
+ pci_unregister_driver(&leapraid_driver);
sas_release_transport(leapraid_transport_template);
+ return error;
+ }
- return error;
+ return 0;
}
static void __exit leapraid_exit(void)
{
- pr_info("leapraid version %s unloading\n",
- LEAPRAID_DRIVER_VERSION);
+ pr_info("%s exiting\n", LEAPRAID_DRIVER_NAME);
leapraid_ctl_exit();
pci_unregister_driver(&leapraid_driver);
diff --git a/drivers/scsi/leapraid/leapraid_transport.c b/drivers/scsi/leapraid/leapraid_transport.c
index d224449732a3..738bc55df416 100644
--- a/drivers/scsi/leapraid/leapraid_transport.c
+++ b/drivers/scsi/leapraid/leapraid_transport.c
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2025 LeapIO Tech Inc.
+ * Copyright (C) 2026 LeapIO Tech Inc.
*
- * LeapRAID Storage and RAID Controller driver.
+ * LeapRAID storage and RAID controller driver.
*/
-
#include <scsi/scsi_host.h>
#include "leapraid_func.h"
@@ -16,10 +15,8 @@ static struct leapraid_topo_node *leapraid_transport_topo_node_by_sas_addr(
{
if (adapter->dev_topo.card.sas_address == sas_addr)
return &adapter->dev_topo.card;
- else
- return leapraid_exp_find_by_sas_address(adapter,
- sas_addr,
- card_port);
+
+ return leapraid_exp_find_by_sas_address(adapter, sas_addr, card_port);
}
static u8 leapraid_get_port_id_by_expander(struct leapraid_adapter *adapter,
@@ -49,7 +46,8 @@ static u8 leapraid_get_port_id_by_end_dev(struct leapraid_adapter *adapter,
u8 port_id = 0xFF;
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
- sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(adapter,
+ sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(
+ adapter,
rphy->identify.sas_address,
rphy);
if (sas_dev) {
@@ -131,10 +129,9 @@ static enum sas_linkrate leapraid_transport_convert_phy_link_rate(u8 link_rate)
},
};
- for (i = 0; i < ARRAY_SIZE(linkrate_table); i++) {
+ for (i = 0; i < ARRAY_SIZE(linkrate_table); i++)
if (linkrate_table[i].in == link_rate)
return linkrate_table[i].out;
- }
return SAS_LINK_RATE_UNKNOWN;
}
@@ -192,7 +189,7 @@ static void leapraid_set_identify_protocol_flags(u32 dev_info,
};
for (i = 0; i < ARRAY_SIZE(mappings); i++)
- if ((dev_info & mappings[i].mask) && mappings[i].target)
+ if (dev_info & mappings[i].mask && mappings[i].target)
*mappings[i].target |= mappings[i].protocol;
}
@@ -207,13 +204,19 @@ static int leapraid_transport_set_identify(struct leapraid_adapter *adapter,
if ((adapter->access_ctrl.shost_recovering &&
!adapter->scan_dev_desc.driver_loading) ||
- adapter->access_ctrl.pcie_recovering)
+ adapter->access_ctrl.pcie_recovering) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed, shost_recovering=%d pcie_recovering=%d\n",
+ __func__,
+ adapter->access_ctrl.shost_recovering,
+ adapter->access_ctrl.pcie_recovering);
return -EFAULT;
+ }
cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
cfgp2.handle = hdl;
- if ((leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1,
- cfgp2, GET_SAS_DEVICE_PG0)))
+ if (leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1,
+ cfgp2, GET_SAS_DEVICE_PG0))
return -ENXIO;
memset(identify, 0, sizeof(struct sas_identify));
@@ -248,27 +251,34 @@ static void leapraid_transport_exp_set_edev(struct leapraid_adapter *adapter,
struct leapraid_smp_passthrough_rep *smp_passthrough_rep;
struct leapraid_rep_manu_reply *rep_manu_reply;
u8 *component_id;
- ssize_t __maybe_unused ret;
smp_passthrough_rep =
- (void *)(&adapter->driver_cmds.transport_cmd.reply);
+ (void *)&adapter->driver_cmds.transport_cmd.reply;
if (le16_to_cpu(smp_passthrough_rep->resp_data_len) !=
sizeof(struct leapraid_rep_manu_reply))
return;
rep_manu_reply = data_out + sizeof(struct leapraid_rep_manu_request);
- ret = strscpy(edev->vendor_id, rep_manu_reply->vendor_identification,
- SAS_EXPANDER_VENDOR_ID_LEN);
- ret = strscpy(edev->product_id, rep_manu_reply->product_identification,
- SAS_EXPANDER_PRODUCT_ID_LEN);
- ret = strscpy(edev->product_rev,
- rep_manu_reply->product_revision_level,
- SAS_EXPANDER_PRODUCT_REV_LEN);
+
+ memcpy(edev->vendor_id, rep_manu_reply->vendor_identification,
+ SAS_EXPANDER_VENDOR_ID_LEN);
+ edev->vendor_id[SAS_EXPANDER_VENDOR_ID_LEN] = '\0';
+
+ memcpy(edev->product_id, rep_manu_reply->product_identification,
+ SAS_EXPANDER_PRODUCT_ID_LEN);
+ edev->product_id[SAS_EXPANDER_PRODUCT_ID_LEN] = '\0';
+
+ memcpy(edev->product_rev, rep_manu_reply->product_revision_level,
+ SAS_EXPANDER_PRODUCT_REV_LEN);
+ edev->product_rev[SAS_EXPANDER_PRODUCT_REV_LEN] = '\0';
+
edev->level = rep_manu_reply->sas_format & 1;
if (edev->level) {
- ret = strscpy(edev->component_vendor_id,
- rep_manu_reply->component_vendor_identification,
- SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
+ memcpy(edev->component_vendor_id,
+ rep_manu_reply->comp_vendor_identification,
+ SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
+ edev->component_vendor_id[
+ SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN] = '\0';
component_id = (u8 *)&rep_manu_reply->component_id;
edev->component_id = component_id[0] << 8 | component_id[1];
@@ -291,18 +301,24 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
size_t c2h_size;
size_t h2c_size;
void *psge;
- int rc = 0;
+ int rc;
if (adapter->access_ctrl.shost_recovering ||
adapter->access_ctrl.pcie_recovering) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed, shost_recovering=%d pcie_recovering=%d\n",
+ __func__,
+ adapter->access_ctrl.shost_recovering,
+ adapter->access_ctrl.pcie_recovering);
return -EFAULT;
}
mutex_lock(&adapter->driver_cmds.transport_cmd.mutex);
adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_PENDING;
- rc = leapraid_check_adapter_is_op(adapter);
+ rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
+ __func__);
if (rc)
- goto out;
+ goto out_cleanup;
h2c_size = sizeof(struct leapraid_rep_manu_request);
c2h_size = sizeof(struct leapraid_rep_manu_reply);
@@ -312,7 +328,7 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
GFP_ATOMIC);
if (!data_out) {
rc = -ENOMEM;
- goto out;
+ goto out_cleanup;
}
rep_manu_request = data_out;
@@ -323,8 +339,9 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
rep_manu_request->request_length = 0;
smp_passthrough_req =
- leapraid_get_task_desc(adapter,
- adapter->driver_cmds.transport_cmd.inter_taskid);
+ leapraid_get_task_desc(
+ adapter,
+ adapter->driver_cmds.transport_cmd.inter_taskid);
memset(smp_passthrough_req, 0,
sizeof(struct leapraid_smp_passthrough_req));
smp_passthrough_req->func = LEAPRAID_FUNC_SMP_PASSTHROUGH;
@@ -342,11 +359,13 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
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)) {
+ rc = -ETIMEDOUT;
dev_err(&adapter->pdev->dev,
- "%s: smp passthrough to exp timeout\n",
- __func__);
+ "%s: SMP passthrough timeout, st=0x%x\n",
+ __func__, adapter->driver_cmds.transport_cmd.status);
+ leapraid_log_req_context(adapter, smp_passthrough_req);
if (!(adapter->driver_cmds.transport_cmd.status &
- LEAPRAID_CMD_RESET))
+ LEAPRAID_CMD_RESET))
issue_reset = true;
goto hard_reset;
@@ -358,11 +377,11 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
hard_reset:
if (issue_reset) {
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
- leapraid_hard_reset_handler(adapter, FULL_RESET);
+ rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
}
-out:
+out_cleanup:
adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_NOT_USED;
if (data_out)
dma_free_coherent(&adapter->pdev->dev, h2c_size + c2h_size,
@@ -376,13 +395,14 @@ static void leapraid_transport_del_port(struct leapraid_adapter *adapter,
struct leapraid_sas_port *sas_port)
{
dev_info(&sas_port->port->dev,
- "remove port: sas addr=0x%016llx\n",
+ "Remove port: SAS addr=0x%016llx\n",
(unsigned long long)sas_port->remote_identify.sas_address);
switch (sas_port->remote_identify.device_type) {
case SAS_END_DEVICE:
- leapraid_sas_dev_remove_by_sas_address(adapter,
- sas_port->remote_identify.sas_address,
- sas_port->card_port);
+ leapraid_sas_dev_remove_by_sas_address(
+ adapter,
+ sas_port->remote_identify.sas_address,
+ sas_port->card_port);
break;
case SAS_EDGE_EXPANDER_DEVICE:
case SAS_FANOUT_EXPANDER_DEVICE:
@@ -399,13 +419,13 @@ static void leapraid_transport_del_phy(struct leapraid_adapter *adapter,
struct leapraid_card_phy *card_phy)
{
dev_info(&card_phy->phy->dev,
- "remove phy: sas addr=0x%016llx, phy=%d\n",
+ "Remove PHY: SAS addr=0x%016llx, phy=%d\n",
(unsigned long long)sas_port->remote_identify.sas_address,
card_phy->phy_id);
list_del(&card_phy->port_siblings);
sas_port->phys_num--;
sas_port_delete_phy(sas_port->port, card_phy->phy);
- card_phy->phy_is_assigned = false;
+ card_phy->phy_is_assigned = 0;
}
static void leapraid_transport_add_phy(struct leapraid_adapter *adapter,
@@ -413,16 +433,17 @@ static void leapraid_transport_add_phy(struct leapraid_adapter *adapter,
struct leapraid_card_phy *card_phy)
{
dev_info(&card_phy->phy->dev,
- "add phy: sas addr=0x%016llx, phy=%d\n",
+ "Add PHY: SAS addr=0x%016llx, phy=%d\n",
(unsigned long long)sas_port->remote_identify.sas_address,
card_phy->phy_id);
list_add_tail(&card_phy->port_siblings, &sas_port->phy_list);
sas_port->phys_num++;
sas_port_add_phy(sas_port->port, card_phy->phy);
- card_phy->phy_is_assigned = true;
+ card_phy->phy_is_assigned = 1;
}
-void leapraid_transport_attach_phy_to_port(struct leapraid_adapter *adapter,
+void leapraid_transport_attach_phy_to_port(
+ struct leapraid_adapter *adapter,
struct leapraid_topo_node *topo_node,
struct leapraid_card_phy *card_phy,
u64 sas_address,
@@ -454,7 +475,8 @@ void leapraid_transport_attach_phy_to_port(struct leapraid_adapter *adapter,
}
}
-void leapraid_transport_detach_phy_to_port(struct leapraid_adapter *adapter,
+void leapraid_transport_detach_phy_to_port(
+ struct leapraid_adapter *adapter,
struct leapraid_topo_node *topo_node,
struct leapraid_card_phy *target_card_phy)
{
@@ -482,7 +504,8 @@ void leapraid_transport_detach_phy_to_port(struct leapraid_adapter *adapter,
}
}
-static void leapraid_detach_phy_from_old_port(struct leapraid_adapter *adapter,
+static void leapraid_detach_phy_from_old_port(
+ struct leapraid_adapter *adapter,
struct leapraid_topo_node *topo_node,
u64 sas_address,
struct leapraid_card_port *card_port)
@@ -495,9 +518,10 @@ static void leapraid_detach_phy_from_old_port(struct leapraid_adapter *adapter,
topo_node->card_phy[i].card_port != card_port)
continue;
if (topo_node->card_phy[i].phy_is_assigned)
- leapraid_transport_detach_phy_to_port(adapter,
- topo_node,
- &topo_node->card_phy[i]);
+ leapraid_transport_detach_phy_to_port(
+ adapter,
+ topo_node,
+ &topo_node->card_phy[i]);
}
}
@@ -512,8 +536,11 @@ static struct leapraid_sas_port *leapraid_prepare_sas_port(
unsigned long flags;
sas_port = kzalloc(sizeof(*sas_port), GFP_KERNEL);
- if (!sas_port)
+ if (!sas_port) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed alloc sas_port\n", __func__);
return NULL;
+ }
INIT_LIST_HEAD(&sas_port->port_list);
INIT_LIST_HEAD(&sas_port->phy_list);
@@ -526,27 +553,30 @@ static struct leapraid_sas_port *leapraid_prepare_sas_port(
if (!topo_node) {
dev_err(&adapter->pdev->dev,
- "%s: failed to find parent node for sas addr 0x%016llx!\n",
+ "%s: Failed to locate parent for SAS 0x%016llx!\n",
__func__, sas_address);
- kfree(sas_port);
- return NULL;
+ goto out_cleanup;
}
if (leapraid_transport_set_identify(adapter, handle,
- &sas_port->remote_identify)) {
- kfree(sas_port);
- return NULL;
- }
+ &sas_port->remote_identify))
+ goto out_cleanup;
if (sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
- kfree(sas_port);
- return NULL;
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed, device type is SAS_PHY_UNUSED\n",
+ __func__);
+ goto out_cleanup;
}
sas_port->card_port = card_port;
*out_topo_node = topo_node;
return sas_port;
+
+out_cleanup:
+ kfree(sas_port);
+ return NULL;
}
static int leapraid_bind_phys_and_vphy(struct leapraid_adapter *adapter,
@@ -576,12 +606,12 @@ static int leapraid_bind_phys_and_vphy(struct leapraid_adapter *adapter,
vphy = leapraid_get_vphy_by_phy(card_port, i);
if (!vphy)
- return -1;
+ return LEAPRAID_OPERATION_FAILED;
}
}
*out_vphy = vphy;
- return sas_port->phys_num ? 0 : -1;
+ return sas_port->phys_num ? 0 : LEAPRAID_OPERATION_FAILED;
}
static struct sas_rphy *leapraid_create_and_register_rphy(
@@ -596,26 +626,42 @@ static struct sas_rphy *leapraid_create_and_register_rphy(
struct sas_port *port;
struct sas_rphy *rphy;
- if (!topo_node->parent_dev)
- return NULL;
+ if (sas_port->remote_identify.device_type == SAS_END_DEVICE) {
+ sas_dev = leapraid_get_sas_dev_by_addr(
+ adapter,
+ sas_port->remote_identify.sas_address,
+ card_port);
+ if (!sas_dev)
+ return NULL;
+ sas_dev->pend_sas_rphy_add = 1;
+ }
+
+ if (!topo_node->parent_dev) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: topo_node parent device is NULL\n", __func__);
+ goto cleanup_sas_dev;
+ }
port = sas_port_alloc_num(topo_node->parent_dev);
- if (sas_port_add(port))
- return NULL;
+ if (!port) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to allocate SAS port\n", __func__);
+ goto cleanup_sas_dev;
+ }
+
+ if (sas_port_add(port)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to add SAS port\n", __func__);
+ goto out_delete_port;
+ }
list_for_each_entry(card_phy, &sas_port->phy_list, port_siblings) {
sas_port_add_phy(port, card_phy->phy);
- card_phy->phy_is_assigned = true;
+ card_phy->phy_is_assigned = 1;
card_phy->card_port = card_port;
}
- if (sas_port->remote_identify.device_type == SAS_END_DEVICE) {
- sas_dev = leapraid_get_sas_dev_by_addr(adapter,
- sas_port->remote_identify.sas_address,
- card_port);
- if (!sas_dev)
- return NULL;
- sas_dev->pend_sas_rphy_add = 1;
+ if (sas_dev) {
rphy = sas_end_device_alloc(port);
sas_dev->rphy = rphy;
@@ -625,28 +671,63 @@ static struct sas_rphy *leapraid_create_and_register_rphy(
else
vphy->sas_address = sas_dev->sas_addr;
}
-
} else {
- rphy = sas_expander_alloc(port,
- sas_port->remote_identify.device_type);
+ rphy = sas_expander_alloc(
+ port,
+ sas_port->remote_identify.device_type);
if (topo_node->hdl <= adapter->dev_topo.card.phys_num)
card_port->sas_address =
sas_port->remote_identify.sas_address;
}
+ if (!rphy) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to allocate RPHY\n", __func__);
+ goto cleanup_card_phy;
+ }
+
rphy->identify = sas_port->remote_identify;
- if (sas_rphy_add(rphy))
+ if (sas_rphy_add(rphy)) {
dev_err(&adapter->pdev->dev,
- "%s: failed to add rphy\n", __func__);
+ "%s: Failed to add RPHY\n", __func__);
+ if (sas_dev)
+ sas_dev->rphy = NULL;
+
+ sas_rphy_free(rphy);
+ goto cleanup_card_phy;
+ }
+ sas_port->port = port;
if (sas_dev) {
sas_dev->pend_sas_rphy_add = 0;
leapraid_sdev_put(sas_dev);
}
- sas_port->port = port;
return rphy;
+
+cleanup_card_phy:
+ if (topo_node->hdl <= adapter->dev_topo.card.phys_num) {
+ if (!vphy)
+ card_port->sas_address = 0;
+ else
+ vphy->sas_address = 0;
+ }
+
+ list_for_each_entry(card_phy, &sas_port->phy_list, port_siblings) {
+ card_phy->phy_is_assigned = 0;
+ card_phy->card_port = NULL;
+ }
+
+out_delete_port:
+ sas_port_delete(port);
+
+cleanup_sas_dev:
+ if (sas_dev) {
+ sas_dev->pend_sas_rphy_add = 0;
+ leapraid_sdev_put(sas_dev);
+ }
+ return NULL;
}
struct leapraid_sas_port *leapraid_transport_port_add(
@@ -656,35 +737,45 @@ struct leapraid_sas_port *leapraid_transport_port_add(
{
struct leapraid_card_phy *card_phy, *card_phy_next;
struct leapraid_topo_node *topo_node = NULL;
- struct leapraid_sas_port *sas_port = NULL;
+ struct leapraid_sas_port *sas_port;
struct leapraid_vphy *vphy = NULL;
- struct sas_rphy *rphy = NULL;
+ struct sas_rphy *rphy;
unsigned long flags;
- if (!card_port)
+ if (!card_port) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid card_port\n", __func__);
return NULL;
+ }
sas_port = leapraid_prepare_sas_port(adapter, hdl, sas_address,
card_port, &topo_node);
if (!sas_port)
return NULL;
- leapraid_detach_phy_from_old_port(adapter,
- topo_node,
- sas_port->remote_identify.sas_address,
- card_port);
+ leapraid_detach_phy_from_old_port(
+ adapter,
+ topo_node,
+ sas_port->remote_identify.sas_address,
+ card_port);
if (leapraid_bind_phys_and_vphy(adapter, sas_port, topo_node,
- card_port, &vphy))
+ card_port, &vphy)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to bind phy to vphy\n", __func__);
goto out_fail;
+ }
rphy = leapraid_create_and_register_rphy(adapter, sas_port, topo_node,
card_port, vphy);
- if (!rphy)
+ if (!rphy) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to create rphy\n", __func__);
goto out_fail;
+ }
dev_info(&rphy->dev,
- "%s: added dev: hdl=0x%04x, sas addr=0x%016llx\n",
+ "%s: Added dev: hdl=0x%04x, SAS addr=0x%016llx\n",
__func__, hdl,
(unsigned long long)sas_port->remote_identify.sas_address);
@@ -695,20 +786,27 @@ struct leapraid_sas_port *leapraid_transport_port_add(
spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
if (sas_port->remote_identify.device_type ==
- LEAPRAID_DEVTYP_EDGE_EXPANDER ||
+ SAS_EDGE_EXPANDER_DEVICE ||
sas_port->remote_identify.device_type ==
- LEAPRAID_DEVTYP_FANOUT_EXPANDER)
- leapraid_transport_exp_report_manu(adapter,
- sas_port->remote_identify.sas_address,
- rphy_to_expander_device(rphy),
- card_port->port_id);
+ SAS_FANOUT_EXPANDER_DEVICE)
+ leapraid_transport_exp_report_manu(
+ adapter,
+ sas_port->remote_identify.sas_address,
+ rphy_to_expander_device(rphy),
+ card_port->port_id);
return sas_port;
out_fail:
list_for_each_entry_safe(card_phy, card_phy_next,
- &sas_port->phy_list, port_siblings)
- list_del(&card_phy->port_siblings);
+ &sas_port->phy_list, port_siblings) {
+ if (topo_node->hdl <= adapter->dev_topo.card.phys_num &&
+ !card_phy->vphy)
+ card_port->phy_mask &= ~BIT(card_phy->phy_id);
+
+ list_del_init(&card_phy->port_siblings);
+ }
+
kfree(sas_port);
return NULL;
}
@@ -750,10 +848,10 @@ static void leapraid_cleanup_card_port_and_vphys(
if (vphy->sas_address != sas_address)
continue;
- dev_info(&adapter->pdev->dev,
- "%s: remove vphy: %p from port: %p, port_id=%d\n",
- __func__, vphy, remove_card_port,
- remove_card_port->port_id);
+ dev_dbg(&adapter->pdev->dev,
+ "%s: Remove vphy=%p from port=%p port_id=%d\n",
+ __func__, vphy, remove_card_port,
+ remove_card_port->port_id);
remove_card_port->vphys_mask &= ~vphy->phy_mask;
list_del(&vphy->list);
@@ -762,11 +860,11 @@ static void leapraid_cleanup_card_port_and_vphys(
if (!remove_card_port->vphys_mask &&
!remove_card_port->sas_address) {
- dev_info(&adapter->pdev->dev,
- "%s: remove empty hba_port: %p, port_id=%d\n",
- __func__,
- remove_card_port,
- remove_card_port->port_id);
+ dev_dbg(&adapter->pdev->dev,
+ "%s: Remove empty hba_port: %p, port_id=%d\n",
+ __func__,
+ remove_card_port,
+ remove_card_port->port_id);
list_del(&remove_card_port->list);
kfree(remove_card_port);
remove_card_port = NULL;
@@ -782,15 +880,15 @@ static void leapraid_cleanup_card_port_and_vphys(
continue;
if (!remove_card_port->vphys_mask) {
- dev_info(&adapter->pdev->dev,
- "%s: remove hba_port: %p, port_id=%d\n",
- __func__, card_port, card_port->port_id);
+ dev_dbg(&adapter->pdev->dev,
+ "%s: Remove hba_port: %p, port_id=%d\n",
+ __func__, card_port, card_port->port_id);
list_del(&card_port->list);
kfree(card_port);
} else {
- dev_info(&adapter->pdev->dev,
- "%s: clear sas_address of hba_port: %p, port_id=%d\n",
- __func__, card_port, card_port->port_id);
+ dev_dbg(&adapter->pdev->dev,
+ "Clear sas_address of port=%p, port_id=%d\n",
+ card_port, card_port->port_id);
remove_card_port->sas_address = 0;
}
break;
@@ -802,22 +900,23 @@ static void leapraid_clear_topo_node_phys(struct leapraid_topo_node *topo_node,
{
int i;
- for (i = 0; i < topo_node->phys_num; i++) {
+ for (i = 0; i < topo_node->phys_num; i++)
if (topo_node->card_phy[i].remote_identify.sas_address ==
sas_address) {
memset(&topo_node->card_phy[i].remote_identify, 0,
sizeof(struct sas_identify));
- topo_node->card_phy[i].vphy = false;
+ topo_node->card_phy[i].vphy = 0;
}
- }
}
-void leapraid_transport_port_remove(struct leapraid_adapter *adapter,
- u64 sas_address, u64 sas_address_parent,
+void leapraid_transport_port_remove(
+ struct leapraid_adapter *adapter,
+ u64 sas_address,
+ u64 sas_address_parent,
struct leapraid_card_port *remove_card_port)
{
struct leapraid_card_phy *card_phy, *card_phy_next;
- struct leapraid_sas_port *sas_port = NULL;
+ struct leapraid_sas_port *sas_port;
struct leapraid_topo_node *topo_node;
unsigned long flags;
bool found = false;
@@ -855,7 +954,7 @@ void leapraid_transport_port_remove(struct leapraid_adapter *adapter,
list_for_each_entry_safe(card_phy, card_phy_next,
&sas_port->phy_list, port_siblings) {
- card_phy->phy_is_assigned = false;
+ card_phy->phy_is_assigned = 0;
if (!adapter->access_ctrl.host_removing)
sas_port_delete_phy(sas_port->port, card_phy->phy);
@@ -865,9 +964,9 @@ void leapraid_transport_port_remove(struct leapraid_adapter *adapter,
if (!adapter->access_ctrl.host_removing)
sas_port_delete(sas_port->port);
- dev_info(&adapter->pdev->dev,
- "%s: removed sas_port for sas addr=0x%016llx\n",
- __func__, (unsigned long long)sas_address);
+ dev_dbg(&adapter->pdev->dev,
+ "%s: Removed sas_port for SAS addr=0x%016llx\n",
+ __func__, (unsigned long long)sas_address);
kfree(sas_port);
}
@@ -902,9 +1001,11 @@ static void leapraid_init_sas_or_exp_phy(struct leapraid_adapter *adapter,
LEAPRAID_SAS_HWRATE_MIN_RATE_MASK);
phy->maximum_linkrate_hw = phy_pg0 ?
leapraid_transport_convert_phy_link_rate(
- phy_pg0->hw_link_rate >> 4) :
+ phy_pg0->hw_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) :
leapraid_transport_convert_phy_link_rate(
- exp_pg1->hw_link_rate >> 4);
+ exp_pg1->hw_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT);
phy->minimum_linkrate = phy_pg0 ?
leapraid_transport_convert_phy_link_rate(
phy_pg0->p_link_rate &
@@ -914,9 +1015,11 @@ static void leapraid_init_sas_or_exp_phy(struct leapraid_adapter *adapter,
LEAPRAID_SAS_PRATE_MIN_RATE_MASK);
phy->maximum_linkrate = phy_pg0 ?
leapraid_transport_convert_phy_link_rate(
- phy_pg0->p_link_rate >> 4) :
+ phy_pg0->p_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) :
leapraid_transport_convert_phy_link_rate(
- exp_pg1->p_link_rate >> 4);
+ exp_pg1->p_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT);
phy->hostdata = card_phy->card_port;
}
@@ -926,30 +1029,33 @@ void leapraid_transport_add_card_phy(struct leapraid_adapter *adapter,
struct device *parent_dev)
{
struct sas_phy *phy;
+ int ret;
INIT_LIST_HEAD(&card_phy->port_siblings);
phy = sas_phy_alloc(parent_dev, card_phy->phy_id);
if (!phy) {
dev_err(&adapter->pdev->dev,
- "%s sas_phy_alloc failed!\n", __func__);
+ "%s: sas_phy_alloc failed!\n", __func__);
return;
}
- if ((leapraid_transport_set_identify(adapter, card_phy->hdl,
- &card_phy->identify))) {
+ if (leapraid_transport_set_identify(adapter, card_phy->hdl,
+ &card_phy->identify)) {
dev_err(&adapter->pdev->dev,
- "%s set phy handle identify failed!\n", __func__);
+ "%s: Set PHY handle identify failed!\n", __func__);
sas_phy_free(phy);
return;
}
card_phy->attached_hdl = le16_to_cpu(phy_pg0->attached_dev_hdl);
if (card_phy->attached_hdl) {
- if (leapraid_transport_set_identify(adapter,
- card_phy->attached_hdl,
- &card_phy->remote_identify)) {
+ ret = leapraid_transport_set_identify(
+ adapter,
+ card_phy->attached_hdl,
+ &card_phy->remote_identify);
+ if (ret) {
dev_err(&adapter->pdev->dev,
- "%s set phy attached handle identify failed!\n",
+ "%s: Set PHY attached hdl identify failed!\n",
__func__);
sas_phy_free(phy);
return;
@@ -958,7 +1064,9 @@ void leapraid_transport_add_card_phy(struct leapraid_adapter *adapter,
leapraid_init_sas_or_exp_phy(adapter, card_phy, phy, phy_pg0, NULL);
- if ((sas_phy_add(phy))) {
+ if (sas_phy_add(phy)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: SAS PHY add failed!\n", __func__);
sas_phy_free(phy);
return;
}
@@ -972,38 +1080,41 @@ int leapraid_transport_add_exp_phy(struct leapraid_adapter *adapter,
struct device *parent_dev)
{
struct sas_phy *phy;
+ int ret;
INIT_LIST_HEAD(&card_phy->port_siblings);
phy = sas_phy_alloc(parent_dev, card_phy->phy_id);
if (!phy) {
dev_err(&adapter->pdev->dev,
- "%s sas_phy_alloc failed!\n", __func__);
+ "%s: sas_phy_alloc failed!\n", __func__);
return -EFAULT;
}
- if ((leapraid_transport_set_identify(adapter, card_phy->hdl,
- &card_phy->identify))) {
+ if (leapraid_transport_set_identify(adapter, card_phy->hdl,
+ &card_phy->identify)) {
dev_err(&adapter->pdev->dev,
- "%s set phy hdl identify failed!\n", __func__);
+ "%s: Set PHY hdl identify failed!\n", __func__);
sas_phy_free(phy);
return -EFAULT;
}
card_phy->attached_hdl = le16_to_cpu(exp_pg1->attached_dev_hdl);
if (card_phy->attached_hdl) {
- if (leapraid_transport_set_identify(adapter,
- card_phy->attached_hdl,
- &card_phy->remote_identify)) {
- dev_err(&adapter->pdev->dev,
- "%s set phy attached hdl identify failed!\n",
- __func__);
- sas_phy_free(phy);
- }
+ ret = leapraid_transport_set_identify(
+ adapter,
+ card_phy->attached_hdl,
+ &card_phy->remote_identify);
+ if (ret)
+ dev_warn(&adapter->pdev->dev,
+ "%s: Set PHY attached hdl identify failed!\n",
+ __func__);
}
leapraid_init_sas_or_exp_phy(adapter, card_phy, phy, NULL, exp_pg1);
- if ((sas_phy_add(phy))) {
+ if (sas_phy_add(phy)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: SAS PHY add failed!\n", __func__);
sas_phy_free(phy);
return -EFAULT;
}
@@ -1012,13 +1123,14 @@ int leapraid_transport_add_exp_phy(struct leapraid_adapter *adapter,
return 0;
}
-void leapraid_transport_update_links(struct leapraid_adapter *adapter,
+void leapraid_transport_update_links(
+ struct leapraid_adapter *adapter,
u64 sas_address, u16 hdl, u8 phy_index,
u8 link_rate, struct leapraid_card_port *target_card_port)
{
struct leapraid_topo_node *topo_node;
struct leapraid_card_phy *card_phy;
- struct leapraid_card_port *card_port = NULL;
+ struct leapraid_card_port *card_port;
unsigned long flags;
if (adapter->access_ctrl.shost_recovering ||
@@ -1053,10 +1165,12 @@ void leapraid_transport_update_links(struct leapraid_adapter *adapter,
BIT(card_phy->phy_id);
}
}
- leapraid_transport_attach_phy_to_port(adapter, topo_node,
- card_phy,
- card_phy->remote_identify.sas_address,
- target_card_port);
+ leapraid_transport_attach_phy_to_port(
+ adapter,
+ topo_node,
+ card_phy,
+ card_phy->remote_identify.sas_address,
+ target_card_port);
} else {
memset(&card_phy->remote_identify, 0,
sizeof(struct sas_identify));
@@ -1079,8 +1193,12 @@ static int leapraid_dma_map_buffer(struct device *dev, struct bsg_buffer *buf,
*dma_len = buf->payload_len;
} else {
- if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
+ if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL)) {
+ dev_err(dev,
+ "%s: Failed to map sg buffer for dma\n",
+ __func__);
return -ENOMEM;
+ }
*dma_addr = sg_dma_address(buf->sg_list);
*dma_len = sg_dma_len(buf->sg_list);
@@ -1106,11 +1224,11 @@ static void leapraid_build_smp_task(struct leapraid_adapter *adapter,
dma_addr_t c2h_dma_addr, size_t c2h_size)
{
struct leapraid_smp_passthrough_req *smp_passthrough_req;
+ u16 inter_taskid;
void *psge;
- 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(*smp_passthrough_req));
smp_passthrough_req->func = LEAPRAID_FUNC_SMP_PASSTHROUGH;
@@ -1130,30 +1248,36 @@ static void leapraid_build_smp_task(struct leapraid_adapter *adapter,
static int leapraid_send_smp_req(struct leapraid_adapter *adapter)
{
- dev_info(&adapter->pdev->dev,
- "%s: sending smp request\n", __func__);
+ const struct leapraid_smp_passthrough_req *smp_passthrough_req;
+
+ 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);
init_completion(&adapter->driver_cmds.transport_cmd.done);
leapraid_fire_task(adapter,
adapter->driver_cmds.transport_cmd.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\n", __func__);
+ 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);
if (!(adapter->driver_cmds.transport_cmd.status &
LEAPRAID_CMD_RESET)) {
- dev_info(&adapter->pdev->dev,
- "%s:%d call hard_reset\n",
- __func__, __LINE__);
+ dev_dbg(&adapter->pdev->dev,
+ "%s:%d: call hard_reset\n",
+ __func__, __LINE__);
leapraid_hard_reset_handler(adapter, FULL_RESET);
return -ETIMEDOUT;
}
}
- dev_info(&adapter->pdev->dev, "%s: smp request complete\n", __func__);
+ dev_dbg(&adapter->pdev->dev, "%s: SMP request complete\n", __func__);
if (!(adapter->driver_cmds.transport_cmd.status &
LEAPRAID_CMD_REPLY_VALID)) {
dev_err(&adapter->pdev->dev,
- "%s: smp request no reply\n", __func__);
+ "%s: SMP request no reply\n", __func__);
return -ENXIO;
}
@@ -1167,10 +1291,10 @@ static void leapraid_handle_smp_rep(struct leapraid_adapter *adapter,
struct leapraid_smp_passthrough_rep *smp_passthrough_rep;
smp_passthrough_rep =
- (void *)(&adapter->driver_cmds.transport_cmd.reply);
+ (void *)&adapter->driver_cmds.transport_cmd.reply;
- dev_info(&adapter->pdev->dev, "%s: response data len=%d\n",
- __func__, le16_to_cpu(smp_passthrough_rep->resp_data_len));
+ dev_dbg(&adapter->pdev->dev, "%s: Response data len=%d\n",
+ __func__, le16_to_cpu(smp_passthrough_rep->resp_data_len));
memcpy(job->reply, smp_passthrough_rep, sizeof(*smp_passthrough_rep));
job->reply_len = sizeof(*smp_passthrough_rep);
@@ -1198,13 +1322,19 @@ static void leapraid_transport_smp_handler(struct bsg_job *job,
if (adapter->access_ctrl.shost_recovering ||
adapter->access_ctrl.pcie_recovering) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed, shost_recovering=%d pcie_recovering=%d\n",
+ __func__,
+ adapter->access_ctrl.shost_recovering,
+ adapter->access_ctrl.pcie_recovering);
rc = -EFAULT;
- goto done;
+ goto exit_bsg_job;
}
- rc = mutex_lock_interruptible(&adapter->driver_cmds.transport_cmd.mutex);
+ rc = mutex_lock_interruptible(&adapter->driver_cmds
+ .transport_cmd.mutex);
if (rc)
- goto done;
+ goto exit_bsg_job;
adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_PENDING;
rc = leapraid_dma_map_buffer(&adapter->pdev->dev,
@@ -1223,7 +1353,8 @@ static void leapraid_transport_smp_handler(struct bsg_job *job,
if (rc)
goto free_req_buf;
- rc = leapraid_check_adapter_is_op(adapter);
+ rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
+ __func__);
if (rc)
goto free_rep_buf;
@@ -1245,7 +1376,7 @@ static void leapraid_transport_smp_handler(struct bsg_job *job,
release_lock:
adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_NOT_USED;
mutex_unlock(&adapter->driver_cmds.transport_cmd.mutex);
-done:
+exit_bsg_job:
bsg_job_done(job, rc, reslen);
}
--
2.25.1
2
1
From: Dongdong Hao <doubled(a)leap-io-kernel.com>
LeapIO inclusion
category: feature
bugzilla: https://atomgit.com/openeuler/kernel/issues/9234
------------------------------------------
leapraid driver changes from v2.0.0.6 to v2.0.1.2.
This update includes:
- overheat handling rework
- reset flow stabilization
- improved timeout diagnostics
- sysfs enhancement
- topology and transport error-path fixes
- memory leak/UAF/reference leak fixes
- mmap/ioctl validation fixes
- improved queue depth handling
- improved interrupt and resource cleanup logic
The update also fixes several race conditions and improves
overall driver robustness under reset, topology change,
and controller abnormal scenarios.
Signed-off-by: Dongdong Hao <doubled(a)leap-io-kernel.com>
---
drivers/scsi/leapraid/Kconfig | 2 +-
drivers/scsi/leapraid/leapraid.h | 1335 +++---
drivers/scsi/leapraid/leapraid_app.c | 529 +--
drivers/scsi/leapraid/leapraid_func.c | 4237 ++++++++++++--------
drivers/scsi/leapraid/leapraid_func.h | 1086 ++---
drivers/scsi/leapraid/leapraid_os.c | 889 ++--
drivers/scsi/leapraid/leapraid_transport.c | 485 ++-
7 files changed, 4859 insertions(+), 3704 deletions(-)
diff --git a/drivers/scsi/leapraid/Kconfig b/drivers/scsi/leapraid/Kconfig
index b539183b24a7..f4ece78f80d3 100644
--- a/drivers/scsi/leapraid/Kconfig
+++ b/drivers/scsi/leapraid/Kconfig
@@ -5,7 +5,7 @@ config SCSI_LEAPRAID
depends on PCI && SCSI
select SCSI_SAS_ATTRS
help
- This driver supports LeapIO PCIe-based Storage
+ This driver supports LeapIO PCIe-based storage
and RAID controllers.
<http://www.leap-io.com>
diff --git a/drivers/scsi/leapraid/leapraid.h b/drivers/scsi/leapraid/leapraid.h
index 77bb93b79254..2a99417143ad 100644
--- a/drivers/scsi/leapraid/leapraid.h
+++ b/drivers/scsi/leapraid/leapraid.h
@@ -1,13 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Copyright (C) 2025 LeapIO Tech Inc.
+ * Copyright (C) 2026 LeapIO Tech Inc.
*
- * LeapRAID Storage and RAID Controller driver.
+ * LeapRAID storage and RAID controller driver.
*/
#ifndef LEAPRAID_H
#define LEAPRAID_H
-/* doorbell register definitions */
+/* Doorbell register definitions. */
#define LEAPRAID_DB_RESET 0x00000000
#define LEAPRAID_DB_READY 0x10000000
#define LEAPRAID_DB_OPERATIONAL 0x20000000
@@ -22,55 +22,60 @@
#define LEAPRAID_DB_FUNC_SHIFT 24
#define LEAPRAID_DB_ADD_DWORDS_SHIFT 16
-/* maximum number of retries waiting for doorbell to become ready */
+/* Maximum number of retries waiting for doorbell to become ready. */
#define LEAPRAID_DB_RETRY_COUNT_MAX 10
-/* maximum number of retries waiting for doorbell to become operational */
-#define LEAPRAID_DB_WAIT_OPERATIONAL 10
-/* sleep interval (in seconds) between doorbell polls */
+/* 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 30
+/* Maximum number of retries waiting for host to end recovery. */
+#define LEAPRAID_WAIT_SHOST_RECOVERY 400
-/* diagnostic register definitions */
+/* Diagnostic register definitions. */
#define LEAPRAID_DIAG_WRITE_ENABLE 0x00000080
#define LEAPRAID_DIAG_RESET 0x00000004
-#define LEAPRAID_DIAG_HOLD_ADAPTER_RESET 0x00000002
-/* interrupt status register definitions */
+/* Interrupt status register definitions. */
#define LEAPRAID_HOST2ADAPTER_DB_STATUS 0x80000000
#define LEAPRAID_ADAPTER2HOST_DB_STATUS 0x00000001
-/* the number of debug register */
+/* The number of debug register. */
#define LEAPRAID_DEBUGLOG_SZ_MAX 16
+#define LEAPRAID_DEBUGLOG_DWORDS_PER_LINE 4
-/* reply post host register defines */
+/* Reply post host register definitions. */
#define REP_POST_HOST_IDX_REG_CNT 16
#define LEAPRAID_RPHI_MSIX_IDX_SHIFT 24
-/* vphy flags */
+/* Virtual PHY flags. */
#define LEAPRAID_SAS_PHYINFO_VPHY 0x00001000
-/* linux driver init fw */
+/* Linux driver init firmware. */
#define LEAPRAID_WHOINIT_LINUX_DRIVER 0x04
-/* rdpq array mode */
+/* Reply descriptor post queue array mode. */
#define LEAPRAID_ADAPTER_INIT_MSGFLG_RDPQ_ARRAY_MODE 0x01
-/* request description flags */
+/* Request description flags. */
#define LEAPRAID_REQ_DESC_FLG_SCSI_IO 0x00
#define LEAPRAID_REQ_DESC_FLG_HPR 0x06
#define LEAPRAID_REQ_DESC_FLG_DFLT_TYPE 0x08
-/* reply description flags */
+/* Reply description flags. */
#define LEAPRAID_RPY_DESC_FLG_TYPE_MASK 0x0F
#define LEAPRAID_RPY_DESC_FLG_SCSI_IO_SUCCESS 0x00
#define LEAPRAID_RPY_DESC_FLG_ADDRESS_REPLY 0x01
#define LEAPRAID_RPY_DESC_FLG_FP_SCSI_IO_SUCCESS 0x06
#define LEAPRAID_RPY_DESC_FLG_UNUSED 0x0F
-/* MPI functions */
-#define LEAPRAID_FUNC_SCSIIO_REQ 0x00
+/* Request and reply messages share the same set of function codes.
+ *
+ * Note: SCSIIO (SCSI I/O) represents SCSI I/O operations and is used
+ * consistently throughout the driver for all SCSI command handling.
+ */
+#define LEAPRAID_FUNC_SCSIIO 0x00
#define LEAPRAID_FUNC_SCSI_TMF 0x01
#define LEAPRAID_FUNC_ADAPTER_INIT 0x02
#define LEAPRAID_FUNC_GET_ADAPTER_FEATURES 0x03
@@ -79,17 +84,16 @@
#define LEAPRAID_FUNC_EVENT_NOTIFY 0x07
#define LEAPRAID_FUNC_FW_DOWNLOAD 0x09
#define LEAPRAID_FUNC_FW_UPLOAD 0x12
-#define LEAPRAID_FUNC_RAID_ACTION 0x15
-#define LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH 0x16
+#define LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH 0x16
#define LEAPRAID_FUNC_SCSI_ENC_PROCESSOR 0x18
#define LEAPRAID_FUNC_SMP_PASSTHROUGH 0x1A
#define LEAPRAID_FUNC_SAS_IO_UNIT_CTRL 0x1B
-#define LEAPRAID_FUNC_SATA_PASSTHROUGH 0x1C
+#define LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH 0x1C
#define LEAPRAID_FUNC_ADAPTER_UNIT_RESET 0x40
#define LEAPRAID_FUNC_HANDSHAKE 0x42
#define LEAPRAID_FUNC_LOGBUF_INIT 0x57
-/* adapter status values */
+/* Adapter status values. */
#define LEAPRAID_ADAPTER_STATUS_MASK 0x7FFF
#define LEAPRAID_ADAPTER_STATUS_SUCCESS 0x0000
#define LEAPRAID_ADAPTER_STATUS_BUSY 0x0002
@@ -113,7 +117,7 @@
#define LEAPRAID_ADAPTER_STATUS_SCSI_ADAPTER_TERMINATED 0x004B
#define LEAPRAID_ADAPTER_STATUS_SCSI_EXT_TERMINATED 0x004C
-/* sge flags */
+/* SGE flags. */
#define LEAPRAID_SGE_FLG_LAST_ONE 0x80
#define LEAPRAID_SGE_FLG_EOB 0x40
#define LEAPRAID_SGE_FLG_EOL 0x01
@@ -129,15 +133,19 @@
#define LEAPRAID_IEEE_SGE_FLG_CHAIN_ONE 0x80
#define LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR 0x00
-#define LEAPRAID_SGE_OFFSET_SIZE 4
+#define LEAPRAID_SGE_NO_DATA_ADDR -1
+#define LEAPRAID_SGE_OFFSET_SIZE 4
-/* page and ext page type */
+/* The type of page. */
#define LEAPRAID_CFG_PT_IO_UNIT 0x00
#define LEAPRAID_CFG_PT_ADAPTER 0x01
#define LEAPRAID_CFG_PT_BIOS 0x02
#define LEAPRAID_CFG_PT_RAID_VOLUME 0x08
+#define LEAPRAID_CFG_PT_MANUFACTURING 0x09
#define LEAPRAID_CFG_PT_RAID_PHYSDISK 0x0A
#define LEAPRAID_CFG_PT_EXTENDED 0x0F
+
+/* The type of extended page. */
#define LEAPRAID_CFG_EXTPT_SAS_IO_UNIT 0x10
#define LEAPRAID_CFG_EXTPT_SAS_EXP 0x11
#define LEAPRAID_CFG_EXTPT_SAS_DEV 0x12
@@ -145,7 +153,7 @@
#define LEAPRAID_CFG_EXTPT_ENC 0x15
#define LEAPRAID_CFG_EXTPT_RAID_CONFIG 0x16
-/* config page address */
+/* Config page address. */
#define LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP 0x00000000
#define LEAPRAID_SAS_ENC_CFG_PGAD_HDL 0x10000000
#define LEAPRAID_SAS_DEV_CFG_PGAD_HDL 0x20000000
@@ -156,51 +164,55 @@
#define LEAPRAID_SAS_PHY_CFG_PGAD_PHY_NUMBER 0x00000000
#define LEAPRAID_PHYSDISK_CFG_PGAD_PHYSDISKNUM 0x10000000
-/* config page operations */
+/* Config page operations. */
#define LEAPRAID_CFG_ACT_PAGE_HEADER 0x00
#define LEAPRAID_CFG_ACT_PAGE_READ_CUR 0x01
#define LEAPRAID_CFG_ACT_PAGE_WRITE_CUR 0x02
-/* bios pages */
+/* BIOS page number. */
#define LEAPRAID_CFG_PAGE_NUM_BIOS2 0x2
#define LEAPRAID_CFG_PAGE_NUM_BIOS3 0x3
-/* sas device pages */
+/* Manufacturing page number. */
+#define LEAPRAID_CFG_PAGE_NUM_MANU0 0x0
+
+/* SAS device page number. */
#define LEAPRAID_CFG_PAGE_NUM_DEV0 0x0
-/* sas device page 0 flags */
+/* 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
-/* sas IO unit pages */
+/* SAS I/O unit page number. */
#define LEAPRAID_CFG_PAGE_NUM_IOUNIT0 0x0
#define LEAPRAID_CFG_PAGE_NUM_IOUNIT1 0x1
-/* sas expander pages */
+/* SAS expander page number. */
#define LEAPRAID_CFG_PAGE_NUM_EXP0 0x0
#define LEAPRAID_CFG_PAGE_NUM_EXP1 0x1
-/* sas enclosure page */
+/* SAS enclosure page number. */
#define LEAPRAID_CFG_PAGE_NUM_ENC0 0x0
-/* sas phy page */
+/* SAS PHY page number. */
#define LEAPRAID_CFG_PAGE_NUM_PHY0 0x0
-/* raid volume pages */
+/* RAID volume page number. */
#define LEAPRAID_CFG_PAGE_NUM_VOL0 0x0
#define LEAPRAID_CFG_PAGE_NUM_VOL1 0x1
-/* physical disk page */
+/* Physical disk page number. */
#define LEAPRAID_CFG_PAGE_NUM_PD0 0x0
-/* adapter page */
+/* Adapter page number. */
#define LEAPRAID_CFG_PAGE_NUM_ADAPTER1 0x1
#define LEAPRAID_CFG_UNIT_SIZE 4
-/* raid volume type and state */
+/* Raid volume type and state. */
#define LEAPRAID_VOL_STATE_MISSING 0x00
#define LEAPRAID_VOL_STATE_FAILED 0x01
#define LEAPRAID_VOL_STATE_INITIALIZING 0x02
@@ -213,17 +225,17 @@
#define LEAPRAID_VOL_TYPE_RAID10 0x05
#define LEAPRAID_VOL_TYPE_UNKNOWN 0xFF
-/* raid volume element flags */
+/* Raid volume element flags. */
#define LEAPRAID_RAIDCFG_P0_EFLG_MASK_ELEMENT_TYPE 0x000F
#define LEAPRAID_RAIDCFG_P0_EFLG_VOL_PHYS_DISK_ELEMENT 0x0001
#define LEAPRAID_RAIDCFG_P0_EFLG_HOT_SPARE_ELEMENT 0x0002
#define LEAPRAID_RAIDCFG_P0_EFLG_OCE_ELEMENT 0x0003
-/* raid action */
+/* Raid action. */
#define LEAPRAID_RAID_ACT_SYSTEM_SHUTDOWN_INITIATED 0x20
#define LEAPRAID_RAID_ACT_PHYSDISK_HIDDEN 0x24
-/* sas negotiated link rates */
+/* SAS negotiated link rates. */
#define LEAPRAID_SAS_NEG_LINK_RATE_MASK_PHYSICAL 0x0F
#define LEAPRAID_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE 0x00
#define LEAPRAID_SAS_NEG_LINK_RATE_PHY_DISABLED 0x01
@@ -231,6 +243,7 @@
#define LEAPRAID_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE 0x03
#define LEAPRAID_SAS_NEG_LINK_RATE_PORT_SELECTOR 0x04
#define LEAPRAID_SAS_NEG_LINK_RATE_SMP_RESETTING 0x05
+#define LEAPRAID_SAS_NEG_LINK_RATE_SHIFT 4
#define LEAPRAID_SAS_NEG_LINK_RATE_1_5 0x08
#define LEAPRAID_SAS_NEG_LINK_RATE_3_0 0x09
@@ -240,8 +253,11 @@
#define LEAPRAID_SAS_PRATE_MIN_RATE_MASK 0x0F
#define LEAPRAID_SAS_HWRATE_MIN_RATE_MASK 0x0F
-/* scsi IO control bits */
-#define LEAPRAID_SCSIIO_CTRL_ADDCDBLEN_SHIFT 26
+/*
+ * Control flags for a SCSI I/O Request.
+ */
+#define LEAPRAID_SCSIIO_CTRL_CDB_32BYTE 4
+#define LEAPRAID_SCSIIO_CTRL_CDB_LEN_SHIFT 26
#define LEAPRAID_SCSIIO_CTRL_NODATATRANSFER 0x00000000
#define LEAPRAID_SCSIIO_CTRL_WRITE 0x01000000
#define LEAPRAID_SCSIIO_CTRL_READ 0x02000000
@@ -250,7 +266,7 @@
#define LEAPRAID_SCSIIO_CTRL_ORDEREDQ 0x00000200
#define LEAPRAID_SCSIIO_CTRL_CMDPRI 0x00000800
-/* scsi state and status */
+/* SCSI state and status. */
#define LEAPRAID_SCSI_STATUS_BUSY 0x08
#define LEAPRAID_SCSI_STATUS_RESERVATION_CONFLICT 0x18
#define LEAPRAID_SCSI_STATUS_TASK_SET_FULL 0x28
@@ -261,7 +277,7 @@
#define LEAPRAID_SCSI_STATE_AUTOSENSE_FAILED 0x02
#define LEAPRAID_SCSI_STATE_AUTOSENSE_VALID 0x01
-/* scsi task management defines */
+/* SCSI task management defines. */
#define LEAPRAID_TM_TASKTYPE_ABORT_TASK 0x01
#define LEAPRAID_TM_TASKTYPE_ABRT_TASK_SET 0x02
#define LEAPRAID_TM_TASKTYPE_TARGET_RESET 0x03
@@ -277,21 +293,20 @@
#define LEAPRAID_TM_RSP_TM_SUCCEEDED 0x08
#define LEAPRAID_TM_RSP_IO_QUEUED_ON_ADAPTER 0x80
-/* scsi sep request defines */
+/* SCSI enclosure processor request defines. */
#define LEAPRAID_SEP_REQ_ACT_WRITE_STATUS 0x00
#define LEAPRAID_SEP_REQ_FLG_DEVHDL_ADDRESS 0x00
#define LEAPRAID_SEP_REQ_FLG_ENCLOSURE_SLOT_ADDRESS 0x01
#define LEAPRAID_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT 0x00000040
-/* the capabilities of the adapter */
+/* 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 */
+/* Event code definitions for the firmware. */
#define LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE 0x000F
-#define LEAPRAID_EVT_SAS_DISCOVERY 0x0016
#define LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST 0x001C
#define LEAPRAID_EVT_SAS_ENCL_DEV_STATUS_CHANGE 0x001D
#define LEAPRAID_EVT_IR_CHANGE 0x0020
@@ -303,7 +318,7 @@
#define LEAPRAID_EVT_SAS_DEV_STAT_RC_INTERNAL_DEV_RESET 0x08
#define LEAPRAID_EVT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET 0x0E
-/* raid configuration change event */
+/* RAID configuration change event. */
#define LEAPRAID_EVT_IR_RC_VOLUME_ADD 0x01
#define LEAPRAID_EVT_IR_RC_VOLUME_DELETE 0x02
#define LEAPRAID_EVT_IR_RC_PD_HIDDEN_TO_ADD 0x03
@@ -313,27 +328,25 @@
#define LEAPRAID_EVT_IR_RC_VOLUME_HIDE 0x0A
#define LEAPRAID_EVT_IR_RC_VOLUME_UNHIDE 0x0B
-/* sas topology change event */
+/* SAS topology change event. */
#define LEAPRAID_EVT_SAS_TOPO_ES_NO_EXPANDER 0x00
#define LEAPRAID_EVT_SAS_TOPO_ES_ADDED 0x01
#define LEAPRAID_EVT_SAS_TOPO_ES_NOT_RESPONDING 0x02
#define LEAPRAID_EVT_SAS_TOPO_ES_RESPONDING 0x03
#define LEAPRAID_EVT_SAS_TOPO_RC_MASK 0x0F
-#define LEAPRAID_EVT_SAS_TOPO_RC_CLEAR_MASK 0xF0
#define LEAPRAID_EVT_SAS_TOPO_RC_TARG_ADDED 0x01
#define LEAPRAID_EVT_SAS_TOPO_RC_TARG_NOT_RESPONDING 0x02
-#define LEAPRAID_EVT_SAS_TOPO_RC_PHY_CHANGED 0x03
-/* sas discovery event defines */
+/* 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 */
+/* Enclosure device status change event. */
#define LEAPRAID_EVT_SAS_ENCL_RC_ADDED 0x01
#define LEAPRAID_EVT_SAS_ENCL_RC_NOT_RESPONDING 0x02
-/* device type and identifiers */
+/* Device type and identifiers. */
#define LEAPRAID_DEVTYP_SEP 0x00004000
#define LEAPRAID_DEVTYP_SSP_TGT 0x00000400
#define LEAPRAID_DEVTYP_STP_TGT 0x00000200
@@ -350,12 +363,12 @@
#define LEAPRAID_DEVTYP_EDGE_EXPANDER 0x00000002
#define LEAPRAID_DEVTYP_FANOUT_EXPANDER 0x00000003
-/* sas control operation */
+/* SAS control operation. */
#define LEAPRAID_SAS_OP_PHY_LINK_RESET 0x06
#define LEAPRAID_SAS_OP_PHY_HARD_RESET 0x07
#define LEAPRAID_SAS_OP_SET_PARAMETER 0x0F
-/* boot device defines */
+/* Boot device defines */
#define LEAPRAID_BOOTDEV_FORM_MASK 0x0F
#define LEAPRAID_BOOTDEV_FORM_NONE 0x00
#define LEAPRAID_BOOTDEV_FORM_SAS_WWID 0x05
@@ -365,21 +378,21 @@
/**
* struct leapraid_reg_base - Register layout of the LeapRAID controller
*
- * @db: Doorbell register used to signal commands or status to firmware
- * @ws: Write sequence register for synchronizing doorbell operations
- * @host_diag: Diagnostic register used for status or debug reporting
- * @r1: Reserved
- * @host_int_status: Interrupt status register reporting active interrupts
- * @host_int_mask: Interrupt mask register enabling or disabling sources
- * @r2: Reserved
- * @rep_msg_host_idx: Reply message index for the next available reply slot
- * @r3: Reserved
- * @debug_log: DebugLog registers for firmware debug and diagnostic output
- * @r4: Reserved
- * @atomic_req_desc_post: Atomic register for single descriptor posting
- * @adapter_log_buf_pos: Adapter log buffer write position
- * @host_log_buf_pos: Host log buffer write position
- * @r5: Reserved
+ * @db: Doorbell register used to signal commands or status to firmware.
+ * @ws: Write sequence register for synchronizing doorbell operations.
+ * @host_diag: Diagnostic register used for status or debug reporting.
+ * @r1: Reserved.
+ * @host_int_status: Interrupt status register reporting active interrupts.
+ * @host_int_mask: Interrupt mask register enabling or disabling sources.
+ * @r2: Reserved.
+ * @rep_msg_host_idx: Reply message index for the next available reply slot.
+ * @r3: Reserved.
+ * @debug_log: DebugLog registers for firmware debug and diagnostic output.
+ * @r4: Reserved.
+ * @atomic_req_desc_post: Atomic register for single descriptor posting.
+ * @adapter_log_buf_pos: Adapter log buffer write position.
+ * @host_log_buf_pos: Host log buffer write position.
+ * @r5: Reserved.
* @rep_post_reg_idx: Array of reply post index registers, one per queue.
* The number of entries is defined by
* REP_POST_HOST_IDX_REG_CNT.
@@ -411,9 +424,9 @@ struct leapraid_reg_base {
/**
* struct leapraid_atomic_req_desc - Atomic request descriptor
*
- * @flg: Descriptor flag indicating the type of request (e.g. SCSI I/O)
- * @msix_idx: MSI-X vector index used for interrupt routing
- * @taskid: Unique task identifier associated with this request
+ * @flg: Descriptor flag indicating the type of request (e.g. SCSI I/O).
+ * @msix_idx: MSI-X vector index used for interrupt routing.
+ * @taskid: Unique task identifier associated with this request.
*/
struct leapraid_atomic_req_desc {
u8 flg;
@@ -424,23 +437,23 @@ struct leapraid_atomic_req_desc {
/**
* union leapraid_rep_desc_union - Unified reply descriptor format
*
- * @dflt_rep: Default reply descriptor containing basic completion info
- * @dflt_rep.rep_flg: Reply flag indicating reply type or status
- * @dflt_rep.msix_idx: MSI-X index for interrupt routing
- * @dflt_rep.taskid: Task identifier matching the submitted request
- * @r1: Reserved
+ * @dflt_rep: Default reply descriptor containing basic completion info.
+ * @dflt_rep.rep_flg: Reply flag indicating reply type or status.
+ * @dflt_rep.msix_idx: MSI-X index for interrupt routing.
+ * @dflt_rep.taskid: Task identifier matching the submitted request.
+ * @r1: Reserved.
*
* @addr_rep: Address reply descriptor used when firmware returns a
- * memory address associated with the reply
- * @addr_rep.rep_flg: Reply flag indicating reply type or status
- * @addr_rep.msix_idx: MSI-X index for interrupt routing
- * @addr_rep.taskid: Task identifier matching the submitted request
- * @addr_rep.rep_frame_addr: Physical address of the reply frame
+ * memory address associated with the reply.
+ * @addr_rep.rep_flg: Reply flag indicating reply type or status.
+ * @addr_rep.msix_idx: MSI-X index for interrupt routing.
+ * @addr_rep.taskid: Task identifier matching the submitted request.
+ * @addr_rep.rep_frame_addr: Physical address of the reply frame.
*
- * @words: Raw 64-bit representation of the reply descriptor
- * @u: Alternative access using 32-bit low/high words
- * @u.low: Lower 32 bits of the descriptor
- * @u.high: Upper 32 bits of the descriptor
+ * @words: Raw 64-bit representation of the reply descriptor.
+ * @u: Alternative access using 32-bit low/high words.
+ * @u.low: Lower 32 bits of the descriptor.
+ * @u.high: Upper 32 bits of the descriptor.
*/
union leapraid_rep_desc_union {
struct leapraid_rep_desc {
@@ -465,10 +478,10 @@ union leapraid_rep_desc_union {
/**
* struct leapraid_req - Generic request header
*
- * @func_dep1: Function-dependent parameter (low 16 bits)
- * @r1: Reserved
- * @func: Function code identifying the command type
- * @r2: Reserved
+ * @func_dep1: Function-dependent parameter (low 16 bits).
+ * @r1: Reserved.
+ * @func: Function code identifying the command type.
+ * @r2: Reserved.
*/
struct leapraid_req {
__le16 func_dep1;
@@ -480,12 +493,12 @@ struct leapraid_req {
/**
* struct leapraid_rep - Generic reply header
*
- * @r1: Reserved
- * @msg_len: Length of the reply message in bytes
- * @function: Function code corresponding to the request
- * @r2: Reserved
- * @adapter_status: Status code reported by the adapter
- * @r3: Reserved
+ * @r1: Reserved.
+ * @msg_len: Length of the reply message in bytes.
+ * @function: Function code corresponding to the request.
+ * @r2: Reserved.
+ * @adapter_status: Status code reported by the adapter.
+ * @r3: Reserved.
*/
struct leapraid_rep {
u8 r1[2];
@@ -499,8 +512,8 @@ struct leapraid_rep {
/**
* struct leapraid_sge_simple32 - 32-bit simple scatter-gather entry
*
- * @flg_and_len: Combined field for flags and segment length
- * @addr: 32-bit physical address of the data buffer
+ * @flg_and_len: Combined field for flags and segment length.
+ * @addr: 32-bit physical address of the data buffer.
*/
struct leapraid_sge_simple32 {
__le32 flg_and_len;
@@ -510,8 +523,8 @@ struct leapraid_sge_simple32 {
/**
* struct leapraid_sge_simple64 - 64-bit simple scatter-gather entry
*
- * @flg_and_len: Combined field for flags and segment length
- * @addr: 64-bit physical address of the data buffer
+ * @flg_and_len: Combined field for flags and segment length.
+ * @addr: 64-bit physical address of the data buffer.
*/
struct leapraid_sge_simple64 {
__le32 flg_and_len;
@@ -521,9 +534,9 @@ struct leapraid_sge_simple64 {
/**
* struct leapraid_sge_simple_union - Unified 32/64-bit SGE representation
*
- * @flg_and_len: Combined field for flags and segment length
- * @u.addr32: 32-bit address field
- * @u.addr64: 64-bit address field
+ * @flg_and_len: Combined field for flags and segment length.
+ * @u.addr32: 32-bit address field.
+ * @u.addr64: 64-bit address field.
*/
struct leapraid_sge_simple_union {
__le32 flg_and_len;
@@ -536,11 +549,11 @@ struct leapraid_sge_simple_union {
/**
* struct leapraid_sge_chain_union - Chained scatter-gather entry
*
- * @len: Length of the chain descriptor
- * @next_chain_offset: Offset to the next SGE chain
- * @flg: Flags indicating chain or termination properties
- * @u.addr32: 32-bit physical address
- * @u.addr64: 64-bit physical address
+ * @len: Length of the chain descriptor.
+ * @next_chain_offset: Offset to the next SGE chain.
+ * @flg: Flags indicating chain or termination properties.
+ * @u.addr32: 32-bit physical address.
+ * @u.addr64: 64-bit physical address.
*/
struct leapraid_sge_chain_union {
__le16 len;
@@ -555,8 +568,8 @@ struct leapraid_sge_chain_union {
/**
* struct leapraid_ieee_sge_simple32 - IEEE 32-bit simple SGE format
*
- * @addr: 32-bit physical address of the data buffer
- * @flg_and_len: Combined field for flags and data length
+ * @addr: 32-bit physical address of the data buffer.
+ * @flg_and_len: Combined field for flags and data length.
*/
struct leapraid_ieee_sge_simple32 {
__le32 addr;
@@ -566,10 +579,10 @@ struct leapraid_ieee_sge_simple32 {
/**
* struct leapraid_ieee_sge_simple64 - IEEE 64-bit simple SGE format
*
- * @addr: 64-bit physical address of the data buffer
- * @len: Length of the data segment
- * @r1: Reserved
- * @flg: Flags indicating transfer properties
+ * @addr: 64-bit physical address of the data buffer.
+ * @len: Length of the data segment.
+ * @r1: Reserved.
+ * @flg: Flags indicating transfer properties.
*/
struct leapraid_ieee_sge_simple64 {
__le64 addr;
@@ -581,8 +594,8 @@ struct leapraid_ieee_sge_simple64 {
/**
* union leapraid_ieee_sge_simple_union - Unified IEEE SGE format
*
- * @simple32: IEEE 32-bit simple SGE entry
- * @simple64: IEEE 64-bit simple SGE entry
+ * @simple32: IEEE 32-bit simple SGE entry.
+ * @simple64: IEEE 64-bit simple SGE entry.
*/
union leapraid_ieee_sge_simple_union {
struct leapraid_ieee_sge_simple32 simple32;
@@ -592,8 +605,8 @@ union leapraid_ieee_sge_simple_union {
/**
* union leapraid_ieee_sge_chain_union - Unified IEEE SGE chain format
*
- * @chain32: IEEE 32-bit chain SGE entry
- * @chain64: IEEE 64-bit chain SGE entry
+ * @chain32: IEEE 32-bit chain SGE entry.
+ * @chain64: IEEE 64-bit chain SGE entry.
*/
union leapraid_ieee_sge_chain_union {
struct leapraid_ieee_sge_simple32 chain32;
@@ -603,11 +616,11 @@ union leapraid_ieee_sge_chain_union {
/**
* struct leapraid_chain64_ieee_sg - 64-bit IEEE chain SGE descriptor
*
- * @addr: Physical address of the next chain segment
- * @len: Length of the current SGE
- * @r1: Reserved
- * @next_chain_offset: Offset to the next chain element
- * @flg: Flags that describe SGE attributes
+ * @addr: Physical address of the next chain segment.
+ * @len: Length of the current SGE.
+ * @r1: Reserved.
+ * @next_chain_offset: Offset to the next chain element.
+ * @flg: Flags that describe SGE attributes.
*/
struct leapraid_chain64_ieee_sg {
__le64 addr;
@@ -620,8 +633,8 @@ struct leapraid_chain64_ieee_sg {
/**
* union leapraid_ieee_sge_io_union - IEEE-style SGE union for I/O
*
- * @ieee_simple: Simple IEEE SGE descriptor
- * @ieee_chain: IEEE chain SGE descriptor
+ * @ieee_simple: Simple IEEE SGE descriptor.
+ * @ieee_chain: IEEE chain SGE descriptor.
*/
union leapraid_ieee_sge_io_union {
struct leapraid_ieee_sge_simple64 ieee_simple;
@@ -631,25 +644,25 @@ union leapraid_ieee_sge_io_union {
/**
* union leapraid_simple_sge_union - Union of simple SGE descriptors
*
- * @leapio_simple: LeapIO-style simple SGE
- * @ieee_simple: IEEE-style simple SGE
+ * @leapraid_simple: LeapRAID simple SGE.
+ * @ieee_simple: IEEE-style simple SGE.
*/
union leapraid_simple_sge_union {
- struct leapraid_sge_simple_union leapio_simple;
+ struct leapraid_sge_simple_union leapraid_simple;
union leapraid_ieee_sge_simple_union ieee_simple;
};
/**
* union leapraid_sge_io_union - Combined SGE union for all I/O types
*
- * @leapio_simple: LeapIO simple SGE format
- * @leapio_chain: LeapIO chain SGE format
- * @ieee_simple: IEEE simple SGE format
- * @ieee_chain: IEEE chain SGE format
+ * @leapraid_simple: LeapRAID simple SGE format.
+ * @leapraid_chain: LeapRAID chain SGE format.
+ * @ieee_simple: IEEE simple SGE format.
+ * @ieee_chain: IEEE chain SGE format.
*/
union leapraid_sge_io_union {
- struct leapraid_sge_simple_union leapio_simple;
- struct leapraid_sge_chain_union leapio_chain;
+ struct leapraid_sge_simple_union leapraid_simple;
+ struct leapraid_sge_chain_union leapraid_chain;
union leapraid_ieee_sge_simple_union ieee_simple;
union leapraid_ieee_sge_chain_union ieee_chain;
};
@@ -657,10 +670,10 @@ union leapraid_sge_io_union {
/**
* struct leapraid_cfg_pg_header - Standard configuration page header
*
- * @r1: Reserved
- * @page_len: Length of the page in 4-byte units
- * @page_num: Page number
- * @page_type: Page type
+ * @r1: Reserved.
+ * @page_len: Length of the page in 4-byte units.
+ * @page_num: Page number.
+ * @page_type: Page type.
*/
struct leapraid_cfg_pg_header {
u8 r1;
@@ -672,13 +685,13 @@ struct leapraid_cfg_pg_header {
/**
* struct leapraid_cfg_ext_pg_header - Extended configuration page header
*
- * @r1: Reserved
- * @r2: Reserved
- * @page_num: Page number
- * @page_type: Page type
- * @ext_page_len: Extended page length
- * @ext_page_type: Extended page type
- * @r3: Reserved
+ * @r1: Reserved.
+ * @r2: Reserved.
+ * @page_num: Page number.
+ * @page_type: Page type.
+ * @ext_page_len: Extended page length.
+ * @ext_page_type: Extended page type.
+ * @r3: Reserved.
*/
struct leapraid_cfg_ext_pg_header {
u8 r1;
@@ -693,17 +706,17 @@ struct leapraid_cfg_ext_pg_header {
/**
* struct leapraid_cfg_req - Configuration request message
*
- * @action: Requested action type
- * @sgl_flag: SGL flag field
- * @chain_offset: Offset to next chain SGE
- * @func: Function code
- * @ext_page_len: Extended page length
- * @ext_page_type: Extended page type
- * @msg_flag: Message flags
- * @r1: Reserved
- * @header: Configuration page header
- * @page_addr: Address of the page buffer
- * @page_buf_sge: SGE describing the page buffer
+ * @action: Requested action type.
+ * @sgl_flag: SGL flag field.
+ * @chain_offset: Offset to next chain SGE.
+ * @func: Function code.
+ * @ext_page_len: Extended page length.
+ * @ext_page_type: Extended page type.
+ * @msg_flag: Message flags.
+ * @r1: Reserved.
+ * @header: Configuration page header.
+ * @page_addr: Address of the page buffer.
+ * @page_buf_sge: SGE describing the page buffer.
*/
struct leapraid_cfg_req {
u8 action;
@@ -722,17 +735,17 @@ struct leapraid_cfg_req {
/**
* struct leapraid_cfg_rep - Configuration reply message
*
- * @action: Action type from the request
- * @r1: Reserved
- * @msg_len: Message length in bytes
- * @func: Function code
- * @ext_page_len: Extended page length
- * @ext_page_type: Extended page type
- * @msg_flag: Message flags
- * @r2: Reserved
- * @adapter_status: Adapter status code
- * @r3: Reserved
- * @header: Configuration page header
+ * @action: Action type from the request.
+ * @r1: Reserved.
+ * @msg_len: Message length in bytes.
+ * @func: Function code.
+ * @ext_page_len: Extended page length.
+ * @ext_page_type: Extended page type.
+ * @msg_flag: Message flags.
+ * @r2: Reserved.
+ * @adapter_status: Adapter status code.
+ * @r3: Reserved.
+ * @header: Configuration page header.
*/
struct leapraid_cfg_rep {
u8 action;
@@ -751,9 +764,9 @@ struct leapraid_cfg_rep {
/**
* struct leapraid_boot_dev_format_sas_wwid - Boot device identified by wwid
*
- * @sas_addr: SAS address of the device
- * @lun: Logical unit number
- * @r1: Reserved
+ * @sas_addr: SAS address of the device.
+ * @lun: Logical unit number.
+ * @r1: Reserved.
*/
struct leapraid_boot_dev_format_sas_wwid {
__le64 sas_addr;
@@ -764,10 +777,10 @@ struct leapraid_boot_dev_format_sas_wwid {
/**
* struct leapraid_boot_dev_format_enc_slot - identified by enclosure
*
- * @enc_lid: Enclosure logical ID
- * @r1: Reserved
- * @slot_num: Slot number in the enclosure
- * @r2: Reserved
+ * @enc_lid: Enclosure logical ID.
+ * @r1: Reserved.
+ * @slot_num: Slot number in the enclosure.
+ * @r2: Reserved.
*/
struct leapraid_boot_dev_format_enc_slot {
__le64 enc_lid;
@@ -779,9 +792,9 @@ struct leapraid_boot_dev_format_enc_slot {
/**
* struct leapraid_boot_dev_format_dev_name - Boot device by device name
*
- * @dev_name: Device name identifier
- * @lun: Logical unit number
- * @r1: Reserved
+ * @dev_name: Device name identifier.
+ * @lun: Logical unit number.
+ * @r1: Reserved.
*/
struct leapraid_boot_dev_format_dev_name {
__le64 dev_name;
@@ -792,9 +805,9 @@ struct leapraid_boot_dev_format_dev_name {
/**
* union leapraid_boot_dev_format - Boot device format union
*
- * @sas_wwid: Format using SAS WWID and LUN
- * @enc_slot: Format using enclosure slot and ID
- * @dev_name: Format using device name and LUN
+ * @sas_wwid: Format using SAS WWID and LUN.
+ * @enc_slot: Format using enclosure slot and ID.
+ * @dev_name: Format using device name and LUN.
*/
union leapraid_boot_dev_format {
struct leapraid_boot_dev_format_sas_wwid sas_wwid;
@@ -802,20 +815,39 @@ union leapraid_boot_dev_format {
struct leapraid_boot_dev_format_dev_name dev_name;
};
+/**
+ * struct leapraid_manufacturing_p0 - Manufacturing configuration page 0
+ *
+ * @header: Configuration page header.
+ * @chip_name: Chip name as a 16-byte ASCII string.
+ * @chip_revision: Chip revision as an 8-byte ASCII string.
+ * @board_name: Board name as a 16-byte ASCII string.
+ * @board_assembly: Board assembly as a 16-byte ASCII string.
+ * @board_tracer_number: Board tracer number as a 16-byte ASCII string.
+ */
+struct leapraid_manufacturing_p0 {
+ struct leapraid_cfg_pg_header header;
+ u8 chip_name[16];
+ u8 chip_revision[8];
+ u8 board_name[16];
+ u8 board_assembly[16];
+ u8 board_tracer_number[16];
+};
+
/**
* struct leapraid_bios_page2 - BIOS configuration page 2
*
- * @header: Configuration page header
- * @r1: Reserved
- * @requested_boot_dev_form: Format type of the requested boot device
- * @r2: Reserved
- * @requested_boot_dev: Boot device requested by BIOS or user
- * @requested_alt_boot_dev_form: Format of the alternate boot device
- * @r3: Reserved
- * @requested_alt_boot_dev: Alternate boot device requested
- * @current_boot_dev_form: Format type of the active boot device
- * @r4: Reserved
- * @current_boot_dev: Currently active boot device in use
+ * @header: Configuration page header.
+ * @r1: Reserved.
+ * @requested_boot_dev_form: Format type of the requested boot device.
+ * @r2: Reserved.
+ * @requested_boot_dev: Boot device requested by BIOS or user.
+ * @requested_alt_boot_dev_form: Format of the alternate boot device.
+ * @r3: Reserved.
+ * @requested_alt_boot_dev: Alternate boot device requested.
+ * @current_boot_dev_form: Format type of the active boot device.
+ * @r4: Reserved.
+ * @current_boot_dev: Currently active boot device in use.
*/
struct leapraid_bios_page2 {
struct leapraid_cfg_pg_header header;
@@ -834,10 +866,10 @@ struct leapraid_bios_page2 {
/**
* struct leapraid_bios_page3 - BIOS configuration page 3
*
- * @header: Configuration page header
- * @r1: Reserved
- * @bios_version: BIOS firmware version number
- * @r2: Reserved
+ * @header: Configuration page header.
+ * @r1: Reserved.
+ * @bios_version: BIOS firmware version number.
+ * @r2: Reserved.
*/
struct leapraid_bios_page3 {
struct leapraid_cfg_pg_header header;
@@ -849,9 +881,9 @@ struct leapraid_bios_page3 {
/**
* struct leapraid_raidvol0_phys_disk - Physical disk in RAID volume
*
- * @r1: Reserved
- * @phys_disk_num: Physical disk number within the RAID volume
- * @r2: Reserved
+ * @r1: Reserved.
+ * @phys_disk_num: Physical disk number within the RAID volume.
+ * @r2: Reserved.
*/
struct leapraid_raidvol0_phys_disk {
u8 r1[2];
@@ -862,14 +894,14 @@ struct leapraid_raidvol0_phys_disk {
/**
* struct leapraid_raidvol_p0 - RAID volume configuration page 0
*
- * @header: Configuration page header
- * @dev_hdl: Device handle for the RAID volume
- * @volume_state: State of the RAID volume
- * @volume_type: RAID type
- * @r1: Reserved
- * @num_phys_disks: Number of physical disks in the volume
- * @r2: Reserved
- * @phys_disk: Array of physical disks in this volume
+ * @header: Configuration page header.
+ * @dev_hdl: Device handle for the RAID volume.
+ * @volume_state: State of the RAID volume.
+ * @volume_type: RAID type.
+ * @r1: Reserved.
+ * @num_phys_disks: Number of physical disks in the volume.
+ * @r2: Reserved.
+ * @phys_disk: Array of physical disks in this volume.
*/
struct leapraid_raidvol_p0 {
struct leapraid_cfg_pg_header header;
@@ -885,11 +917,11 @@ struct leapraid_raidvol_p0 {
/**
* struct leapraid_raidvol_p1 - RAID volume configuration page 1
*
- * @header: Configuration page header
- * @dev_hdl: Device handle of the RAID volume
- * @r1: Reserved
- * @wwid: World-wide identifier for the volume
- * @r2: Reserved
+ * @header: Configuration page header.
+ * @dev_hdl: Device handle of the RAID volume.
+ * @r1: Reserved.
+ * @wwid: World-wide identifier for the volume.
+ * @r2: Reserved.
*/
struct leapraid_raidvol_p1 {
struct leapraid_cfg_pg_header header;
@@ -902,11 +934,11 @@ struct leapraid_raidvol_p1 {
/**
* struct leapraid_raidpd_p0 - Physical disk configuration page 0
*
- * @header: Configuration page header
- * @dev_hdl: Device handle of the physical disk
- * @r1: Reserved
- * @phys_disk_num: Physical disk number
- * @r2: Reserved
+ * @header: Configuration page header.
+ * @dev_hdl: Device handle of the physical disk.
+ * @r1: Reserved.
+ * @phys_disk_num: Physical disk number.
+ * @r2: Reserved.
*/
struct leapraid_raidpd_p0 {
struct leapraid_cfg_pg_header header;
@@ -919,14 +951,14 @@ struct leapraid_raidpd_p0 {
/**
* struct leapraid_sas_io_unit0_phy_info - PHY info for SAS I/O unit
*
- * @port: Port number the PHY belongs to
- * @port_flg: Flags describing port status
- * @phy_flg: Flags describing PHY status
- * @neg_link_rate: Negotiated link rate of the PHY
- * @controller_phy_dev_info: Controller PHY device info
- * @attached_dev_hdl: Handle of attached device
- * @controller_dev_hdl: Handle of the controller device
- * @r1: Reserved
+ * @port: Port number the PHY belongs to.
+ * @port_flg: Flags describing port status.
+ * @phy_flg: Flags describing PHY status.
+ * @neg_link_rate: Negotiated link rate of the PHY.
+ * @controller_phy_dev_info: Controller PHY device info.
+ * @attached_dev_hdl: Handle of attached device.
+ * @controller_dev_hdl: Handle of the controller device.
+ * @r1: Reserved.
*/
struct leapraid_sas_io_unit0_phy_info {
u8 port;
@@ -942,11 +974,11 @@ struct leapraid_sas_io_unit0_phy_info {
/**
* struct leapraid_sas_io_unit_p0 - SAS I/O unit configuration page 0
*
- * @header: Extended configuration page header
- * @r1: Reserved
- * @phy_num: Number of PHYs in this unit
- * @r2: Reserved
- * @phy_info: Array of PHY information
+ * @header: Extended configuration page header.
+ * @r1: Reserved.
+ * @phy_num: Number of PHYs in this unit.
+ * @r2: Reserved.
+ * @phy_info: Array of PHY information.
*/
struct leapraid_sas_io_unit_p0 {
struct leapraid_cfg_ext_pg_header header;
@@ -956,54 +988,20 @@ struct leapraid_sas_io_unit_p0 {
struct leapraid_sas_io_unit0_phy_info phy_info[];
};
-/**
- * struct leapraid_sas_io_unit1_phy_info - Placeholder for SAS unit page 1 PHY
- *
- * @r1: Reserved
- */
-struct leapraid_sas_io_unit1_phy_info {
- u8 r1[12];
-};
-
-/**
- * struct leapraid_sas_io_unit_page1 - SAS I/O unit configuration page 1
- *
- * @header: Extended configuration page header
- * @r1: Reserved
- * @narrowport_max_queue_depth: Maximum queue depth for narrow ports
- * @r2: Reserved
- * @wideport_max_queue_depth: Maximum queue depth for wide ports
- * @r3: Reserved
- * @sata_max_queue_depth: Maximum SATA queue depth
- * @r4: Reserved
- * @phy_info: Array of PHY info structures
- */
-struct leapraid_sas_io_unit_page1 {
- struct leapraid_cfg_ext_pg_header header;
- u8 r1[2];
- __le16 narrowport_max_queue_depth;
- u8 r2[2];
- __le16 wideport_max_queue_depth;
- u8 r3;
- u8 sata_max_queue_depth;
- u8 r4[2];
- struct leapraid_sas_io_unit1_phy_info phy_info[];
-};
-
/**
* struct leapraid_exp_p0 - SAS expander page 0
*
- * @header: Extended page header
- * @physical_port: Physical port number
- * @r1: Reserved
- * @enc_hdl: Enclosure handle
- * @sas_address: SAS address of the expander
- * @r2: Reserved
- * @dev_hdl: Device handle of this expander
- * @parent_dev_hdl: Device handle of parent expander
- * @r3: Reserved
- * @phy_num: Number of PHYs
- * @r4: Reserved
+ * @header: Extended page header.
+ * @physical_port: Physical port number.
+ * @r1: Reserved.
+ * @enc_hdl: Enclosure handle.
+ * @sas_address: SAS address of the expander.
+ * @r2: Reserved.
+ * @dev_hdl: Device handle of this expander.
+ * @parent_dev_hdl: Device handle of parent expander.
+ * @r3: Reserved.
+ * @phy_num: Number of PHYs.
+ * @r4: Reserved.
*/
struct leapraid_exp_p0 {
struct leapraid_cfg_ext_pg_header header;
@@ -1022,14 +1020,14 @@ struct leapraid_exp_p0 {
/**
* struct leapraid_exp_p1 - SAS expander page 1
*
- * @header: Extended page header
- * @r1: Reserved
- * @p_link_rate: PHY link rate
- * @hw_link_rate: Hardware supported link rate
- * @attached_dev_hdl: Attached device handle
- * @r2: Reserved
- * @neg_link_rate: Negotiated link rate
- * @r3: Reserved
+ * @header: Extended page header.
+ * @r1: Reserved.
+ * @p_link_rate: PHY link rate.
+ * @hw_link_rate: Hardware supported link rate.
+ * @attached_dev_hdl: Attached device handle.
+ * @r2: Reserved.
+ * @neg_link_rate: Negotiated link rate.
+ * @r3: Reserved.
*/
struct leapraid_exp_p1 {
struct leapraid_cfg_ext_pg_header header;
@@ -1045,25 +1043,25 @@ struct leapraid_exp_p1 {
/**
* struct leapraid_sas_dev_p0 - SAS device page 0
*
- * @header: Extended configuration page header
- * @slot: Slot number
- * @enc_hdl: Enclosure handle
- * @sas_address: SAS address
- * @parent_dev_hdl: Parent device handle
- * @phy_num: Number of PHYs
- * @r1: Reserved
- * @dev_hdl: Device handle
- * @r2: Reserved
- * @dev_info: Device information
- * @flg: Flags
- * @physical_port: Physical port number
- * @max_port_connections: Maximum port connections
- * @dev_name: Device name
- * @port_groups: Number of port groups
- * @r3: Reserved
- * @enc_level: Enclosure level
- * @connector_name: Connector identifier
- * @r4: Reserved
+ * @header: Extended configuration page header.
+ * @slot: Slot number.
+ * @enc_hdl: Enclosure handle.
+ * @sas_address: SAS address.
+ * @parent_dev_hdl: Parent device handle.
+ * @phy_num: Number of PHYs.
+ * @r1: Reserved.
+ * @dev_hdl: Device handle.
+ * @r2: Reserved.
+ * @dev_info: Device information.
+ * @flg: Flags.
+ * @physical_port: Physical port number.
+ * @max_port_connections: Maximum port connections.
+ * @dev_name: Device name.
+ * @port_groups: Number of port groups.
+ * @r3: Reserved.
+ * @enc_level: Enclosure level.
+ * @connector_name: Connector identifier.
+ * @r4: Reserved.
*/
struct leapraid_sas_dev_p0 {
struct leapraid_cfg_ext_pg_header header;
@@ -1083,23 +1081,23 @@ struct leapraid_sas_dev_p0 {
u8 port_groups;
u8 r3[2];
u8 enc_level;
- u8 connector_name[4];
+ u8 connector_name[LEAPRAID_SAS_DEV_P0_CON_NAME_LEN];
u8 r4[4];
} __packed __aligned(4);
/**
* struct leapraid_sas_phy_p0 - SAS PHY configuration page 0
*
- * @header: Extended configuration page header
- * @r1: Reserved
- * @attached_dev_hdl: Handle of attached device
- * @r2: Reserved
- * @p_link_rate: PHY link rate
- * @hw_link_rate: Hardware supported link rate
- * @r3: Reserved
- * @phy_info: PHY information
- * @neg_link_rate: Negotiated link rate
- * @r4: Reserved
+ * @header: Extended configuration page header.
+ * @r1: Reserved.
+ * @attached_dev_hdl: Handle of attached device.
+ * @r2: Reserved.
+ * @p_link_rate: PHY link rate.
+ * @hw_link_rate: Hardware supported link rate.
+ * @r3: Reserved.
+ * @phy_info: PHY information.
+ * @neg_link_rate: Negotiated link rate.
+ * @r4: Reserved.
*/
struct leapraid_sas_phy_p0 {
struct leapraid_cfg_ext_pg_header header;
@@ -1117,12 +1115,12 @@ struct leapraid_sas_phy_p0 {
/**
* struct leapraid_enc_p0 - SAS enclosure page 0
*
- * @header: Extended configuration page header
- * @r1: Reserved
- * @enc_lid: Enclosure logical ID
- * @r2: Reserved
- * @enc_hdl: Enclosure handle
- * @r3: Reserved
+ * @header: Extended configuration page header.
+ * @r1: Reserved.
+ * @enc_lid: Enclosure logical ID.
+ * @r2: Reserved.
+ * @enc_hdl: Enclosure handle.
+ * @r3: Reserved.
*/
struct leapraid_enc_p0 {
struct leapraid_cfg_ext_pg_header header;
@@ -1136,10 +1134,10 @@ struct leapraid_enc_p0 {
/**
* struct leapraid_raid_cfg_p0_element - RAID configuration element
*
- * @element_flg: Element flags
- * @vol_dev_hdl: Volume device handle
- * @r1: Reserved
- * @phys_disk_dev_hdl: Physical disk device handle
+ * @element_flg: Element flags.
+ * @vol_dev_hdl: Volume device handle.
+ * @r1: Reserved.
+ * @phys_disk_dev_hdl: Physical disk device handle.
*/
struct leapraid_raid_cfg_p0_element {
__le16 element_flg;
@@ -1151,13 +1149,13 @@ struct leapraid_raid_cfg_p0_element {
/**
* struct leapraid_raid_cfg_p0 - RAID configuration page 0
*
- * @header: Extended configuration page header
- * @r1: Reserved
- * @cfg_num: Configuration number
- * @r2: Reserved
- * @elements_num: Number of RAID elements
- * @r3: Reserved
- * @cfg_element: Array of RAID elements
+ * @header: Extended configuration page header.
+ * @r1: Reserved.
+ * @cfg_num: Configuration number.
+ * @r2: Reserved.
+ * @elements_num: Number of RAID elements.
+ * @r3: Reserved.
+ * @cfg_element: Array of RAID elements.
*/
struct leapraid_raid_cfg_p0 {
struct leapraid_cfg_ext_pg_header header;
@@ -1172,8 +1170,8 @@ struct leapraid_raid_cfg_p0 {
/**
* union leapraid_mpi_scsi_io_cdb_union - SCSI I/O CDB or simple SGE
*
- * @cdb32: 32-byte SCSI command descriptor block
- * @sge: Simple SGE format
+ * @cdb32: 32-byte SCSI command descriptor block.
+ * @sge: Simple SGE format.
*/
union leapraid_mpi_scsi_io_cdb_union {
u8 cdb32[32];
@@ -1183,32 +1181,32 @@ union leapraid_mpi_scsi_io_cdb_union {
/**
* struct leapraid_mpi_scsiio_req - MPI SCSI I/O request
*
- * @dev_hdl: Device handle for the target
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @r1: Reserved
- * @msg_flg: Message flags
- * @r2: Reserved
- * @sense_buffer_low_add: Lower 32-bit address of sense buffer
- * @dma_flag: DMA flags
- * @r3: Reserved
- * @sense_buffer_len: Sense buffer length
- * @r4: Reserved
- * @sgl_offset0..3: SGL offsets
- * @skip_count: Bytes to skip before transfer
- * @data_len: Length of data transfer
- * @bi_dir_data_len: Bi-directional transfer length
- * @io_flg: I/O flags
- * @eedp_flag: EEDP flags
- * @eedp_block_size: EEDP block size
- * @r5: Reserved
- * @secondary_ref_tag: Secondary reference tag
- * @secondary_app_tag: Secondary application tag
- * @app_tag_trans_mask: Application tag mask
- * @lun: Logical Unit Number
- * @ctrl: Control flags
- * @cdb: SCSI Command Descriptor Block or simple SGE
- * @sgl: Scatter-gather list
+ * @dev_hdl: Device handle for the target.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @r1: Reserved.
+ * @msg_flg: Message flags.
+ * @r2: Reserved.
+ * @sense_buffer_low_add: Lower 32-bit address of sense buffer.
+ * @dma_flag: DMA flags.
+ * @r3: Reserved.
+ * @sense_buffer_len: Sense buffer length.
+ * @r4: Reserved.
+ * @sgl_offset0..3: SGL offsets.
+ * @skip_count: Bytes to skip before transfer.
+ * @data_len: Length of data transfer.
+ * @bi_dir_data_len: Bi-directional transfer length.
+ * @io_flg: I/O flags.
+ * @eedp_flag: End-to-end data protection flags.
+ * @eedp_block_size: End-to-end data protection block size.
+ * @r5: Reserved.
+ * @secondary_ref_tag: Secondary reference tag.
+ * @secondary_app_tag: Secondary application tag.
+ * @app_tag_trans_mask: Application tag mask.
+ * @lun: Logical Unit Number.
+ * @ctrl: Control flags.
+ * @cdb: SCSI Command Descriptor Block or simple SGE.
+ * @sgl: Scatter-gather list.
*/
struct leapraid_mpi_scsiio_req {
__le16 dev_hdl;
@@ -1245,8 +1243,8 @@ struct leapraid_mpi_scsiio_req {
/**
* union leapraid_scsi_io_cdb_union - SCSI I/O CDB or IEEE simple SGE
*
- * @cdb32: 32-byte SCSI CDB
- * @sge: IEEE simple 64-bit SGE
+ * @cdb32: 32-byte SCSI CDB.
+ * @sge: IEEE simple 64-bit SGE.
*/
union leapraid_scsi_io_cdb_union {
u8 cdb32[32];
@@ -1256,32 +1254,32 @@ union leapraid_scsi_io_cdb_union {
/**
* struct leapraid_scsiio_req - SCSI I/O request
*
- * @dev_hdl: Device handle
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @r1: Reserved
- * @msg_flg: Message flags
- * @r2: Reserved
- * @sense_buffer_low_add: Lower 32-bit address of sense buffer
- * @dma_flag: DMA flag
- * @r3: Reserved
- * @sense_buffer_len: Sense buffer length
- * @r4: Reserved
- * @sgl_offset0-3: SGL offsets
- * @skip_count: Bytes to skip before transfer
- * @data_len: Length of data transfer
- * @bi_dir_data_len: Bi-directional transfer length
- * @io_flg: I/O flags
- * @eedp_flag: EEDP flags
- * @eedp_block_size: EEDP block size
- * @r5: Reserved
- * @secondary_ref_tag: Secondary reference tag
- * @secondary_app_tag: Secondary application tag
- * @app_tag_trans_mask: Application tag mask
- * @lun: Logical Unit Number
- * @ctrl: Control flags
- * @cdb: SCSI Command Descriptor Block or simple SGE
- * @sgl: Scatter-gather list
+ * @dev_hdl: Device handle.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @r1: Reserved.
+ * @msg_flg: Message flags.
+ * @r2: Reserved.
+ * @sense_buffer_low_add: Lower 32-bit address of sense buffer.
+ * @dma_flag: DMA flag.
+ * @r3: Reserved.
+ * @sense_buffer_len: Sense buffer length.
+ * @r4: Reserved.
+ * @sgl_offset0-3: SGL offsets.
+ * @skip_count: Bytes to skip before transfer.
+ * @data_len: Length of data transfer.
+ * @bi_dir_data_len: Bi-directional transfer length.
+ * @io_flg: I/O flags.
+ * @eedp_flag: End-to-end data protection flags.
+ * @eedp_block_size: End-to-end data protection block size.
+ * @r5: Reserved.
+ * @secondary_ref_tag: Secondary reference tag.
+ * @secondary_app_tag: Secondary application tag.
+ * @app_tag_trans_mask: Application tag mask.
+ * @lun: Logical Unit Number.
+ * @ctrl: Control flags.
+ * @cdb: SCSI Command Descriptor Block or simple SGE.
+ * @sgl: Scatter-gather list.
*/
struct leapraid_scsiio_req {
__le16 dev_hdl;
@@ -1318,23 +1316,23 @@ struct leapraid_scsiio_req {
/**
* struct leapraid_scsiio_rep - SCSI I/O response
*
- * @dev_hdl: Device handle
- * @msg_len: Length of response message
- * @func: Function code
- * @r1: Reserved
- * @msg_flg: Message flags
- * @r2: Reserved
- * @scsi_status: SCSI status
- * @scsi_state: SCSI state
- * @adapter_status: Adapter status
- * @r3: Reserved
- * @transfer_count: Number of bytes transferred
- * @sense_count: Number of sense bytes
- * @resp_info: Additional response info
- * @task_tag: Task identifier
- * @scsi_status_qualifier: SCSI status qualifier
- * @bi_dir_trans_count: Bi-directional transfer count
- * @r4: Reserved
+ * @dev_hdl: Device handle.
+ * @msg_len: Length of response message.
+ * @func: Function code.
+ * @r1: Reserved.
+ * @msg_flg: Message flags.
+ * @r2: Reserved.
+ * @scsi_status: SCSI status.
+ * @scsi_state: SCSI state.
+ * @adapter_status: Adapter status.
+ * @r3: Reserved.
+ * @transfer_count: Number of bytes transferred.
+ * @sense_count: Number of sense bytes.
+ * @resp_info: Additional response info.
+ * @task_tag: Task identifier.
+ * @scsi_status_qualifier: SCSI status qualifier.
+ * @bi_dir_trans_count: Bi-directional transfer count.
+ * @r4: Reserved.
*/
struct leapraid_scsiio_rep {
__le16 dev_hdl;
@@ -1359,18 +1357,18 @@ struct leapraid_scsiio_rep {
/**
* struct leapraid_scsi_tm_req - SCSI Task Management request
*
- * @dev_hdl: Device handle
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @r1: Reserved
- * @task_type: Task management function type
- * @r2: Reserved
- * @msg_flg: Message flags
- * @r3: Reserved
- * @lun: Logical Unit Number
- * @r4: Reserved
- * @task_mid: Task identifier
- * @r5: Reserved
+ * @dev_hdl: Device handle.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @r1: Reserved.
+ * @task_type: Task management function type.
+ * @r2: Reserved.
+ * @msg_flg: Message flags.
+ * @r3: Reserved.
+ * @lun: Logical Unit Number.
+ * @r4: Reserved.
+ * @task_mid: Task identifier.
+ * @r5: Reserved.
*/
struct leapraid_scsi_tm_req {
__le16 dev_hdl;
@@ -1390,18 +1388,18 @@ struct leapraid_scsi_tm_req {
/**
* struct leapraid_scsi_tm_rep - SCSI Task Management response
*
- * @dev_hdl: Device handle
- * @msg_len: Length of response message
- * @func: Function code
- * @resp_code: Response code
- * @task_type: Task management type
- * @r1: Reserved
- * @msg_flag: Message flags
- * @r2: Reserved
- * @adapter_status: Adapter status
- * @r3: Reserved
- * @termination_count: Count of terminated tasks
- * @response_info: Additional response info
+ * @dev_hdl: Device handle.
+ * @msg_len: Length of response message.
+ * @func: Function code.
+ * @resp_code: Response code.
+ * @task_type: Task management type.
+ * @r1: Reserved.
+ * @msg_flag: Message flags.
+ * @r2: Reserved.
+ * @adapter_status: Adapter status.
+ * @r3: Reserved.
+ * @termination_count: Count of terminated tasks.
+ * @response_info: Additional response info.
*/
struct leapraid_scsi_tm_rep {
__le16 dev_hdl;
@@ -1421,18 +1419,18 @@ struct leapraid_scsi_tm_rep {
/**
* struct leapraid_sep_req - SEP (SCSI Enclosure Processor) request
*
- * @dev_hdl: Device handle
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @act: Action to perform
- * @flg: Flags
- * @r1: Reserved
- * @msg_flag: Message flags
- * @r2: Reserved
- * @slot_status: Slot status
- * @r3: Reserved
- * @slot: Slot number
- * @enc_hdl: Enclosure handle
+ * @dev_hdl: Device handle.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @act: Action to perform.
+ * @flg: Flags.
+ * @r1: Reserved.
+ * @msg_flag: Message flags.
+ * @r2: Reserved.
+ * @slot_status: Slot status.
+ * @r3: Reserved.
+ * @slot: Slot number.
+ * @enc_hdl: Enclosure handle.
*/
struct leapraid_sep_req {
__le16 dev_hdl;
@@ -1452,19 +1450,19 @@ struct leapraid_sep_req {
/**
* struct leapraid_sep_rep - SEP response
*
- * @dev_hdl: Device handle
- * @msg_len: Message length
- * @func: Function code
- * @act: Action performed
- * @flg: Flags
- * @msg_flag: Message flags
- * @r1: Reserved
- * @adapter_status: Adapter status
- * @r2: Reserved
- * @slot_status: Slot status
- * @r3: Reserved
- * @slot: Slot number
- * @enc_hdl: Enclosure handle
+ * @dev_hdl: Device handle.
+ * @msg_len: Message length.
+ * @func: Function code.
+ * @act: Action performed.
+ * @flg: Flags.
+ * @msg_flag: Message flags.
+ * @r1: Reserved.
+ * @adapter_status: Adapter status.
+ * @r2: Reserved.
+ * @slot_status: Slot status.
+ * @r3: Reserved.
+ * @slot: Slot number.
+ * @enc_hdl: Enclosure handle.
*/
struct leapraid_sep_rep {
__le16 dev_hdl;
@@ -1486,29 +1484,29 @@ struct leapraid_sep_rep {
/**
* struct leapraid_adapter_init_req - Adapter initialization request
*
- * @who_init: Initiator of the initialization
- * @r1: Reserved
- * @chain_offset: Chain offset
- * @func: Function code
- * @r2: Reserved
- * @msg_flg: Message flags
- * @r3: Reserved
- * @msg_ver: Message version
- * @header_ver: Header version
- * @host_buf_addr: Host buffer address (non adapter-ref)
- * @r4: Reserved
- * @host_buf_size: Host buffer size (non adapter-ref)
- * @host_msix_vectors: Number of host MSI-X vectors
- * @r6: Reserved
- * @req_frame_size: Request frame size
- * @rep_desc_qd: Reply descriptor queue depth
- * @rep_msg_qd: Reply message queue depth
- * @sense_buffer_add_high: High 32-bit of sense buffer address
- * @rep_msg_dma_high: High 32-bit of reply message DMA address
- * @task_desc_base_addr: Base address of task descriptors
- * @rep_desc_q_arr_addr: Address of reply descriptor queue array
- * @rep_msg_addr_dma: Reply message DMA address
- * @time_stamp: Timestamp
+ * @who_init: Initiator of the initialization.
+ * @r1: Reserved.
+ * @chain_offset: Chain offset.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @msg_flg: Message flags.
+ * @r3: Reserved.
+ * @msg_ver: Message version.
+ * @header_ver: Header version.
+ * @host_buf_addr: Host buffer address (non adapter-ref).
+ * @r4: Reserved.
+ * @host_buf_size: Host buffer size (non adapter-ref).
+ * @host_msix_vectors: Number of host MSI-X vectors.
+ * @r6: Reserved.
+ * @req_frame_size: Request frame size.
+ * @rep_desc_qd: Reply descriptor queue depth.
+ * @rep_msg_qd: Reply message queue depth.
+ * @sense_buffer_add_high: High 32-bit of sense buffer address.
+ * @rep_msg_dma_high: High 32-bit of reply message DMA address.
+ * @task_desc_base_addr: Base address of task descriptors.
+ * @rep_desc_q_arr_addr: Address of reply descriptor queue array.
+ * @rep_msg_addr_dma: Reply message DMA address.
+ * @time_stamp: Timestamp.
*/
struct leapraid_adapter_init_req {
u8 who_init;
@@ -1539,8 +1537,8 @@ struct leapraid_adapter_init_req {
/**
* struct leapraid_rep_desc_q_arr - Reply descriptor queue array
*
- * @rep_desc_base_addr: Base address of the reply descriptors
- * @r1: Reserved
+ * @rep_desc_base_addr: Base address of the reply descriptors.
+ * @r1: Reserved.
*/
struct leapraid_rep_desc_q_arr {
__le64 rep_desc_base_addr;
@@ -1550,15 +1548,15 @@ struct leapraid_rep_desc_q_arr {
/**
* struct leapraid_adapter_init_rep - Adapter initialization reply
*
- * @who_init: Initiator of the initialization
- * @r1: Reserved
- * @msg_len: Length of reply message
- * @func: Function code
- * @r2: Reserved
- * @msg_flag: Message flags
- * @r3: Reserved
- * @adapter_status: Adapter status
- * @r4: Reserved
+ * @who_init: Initiator of the initialization.
+ * @r1: Reserved.
+ * @msg_len: Length of reply message.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @msg_flag: Message flags.
+ * @r3: Reserved.
+ * @adapter_status: Adapter status.
+ * @r4: Reserved.
*/
struct leapraid_adapter_init_rep {
u8 who_init;
@@ -1575,15 +1573,15 @@ struct leapraid_adapter_init_rep {
/**
* struct leapraid_adapter_log_req - Adapter log request
*
- * @action: Action code
- * @type: Log type
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * r1: Reserved
- * @msg_flag: Message flags
- * r2: Reserved
- * @mbox: Mailbox for command-specific parameters
- * @sge: Scatter-gather entry for data buffer
+ * @action: Action code.
+ * @type: Log type.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * r1: Reserved.
+ * @msg_flag: Message flags.
+ * r2: Reserved.
+ * @mbox: Mailbox for command-specific parameters.
+ * @sge: Scatter-gather entry for data buffer.
*/
struct leapraid_adapter_log_req {
u8 action;
@@ -1604,14 +1602,14 @@ struct leapraid_adapter_log_req {
/**
* struct leapraid_adapter_log_rep - Adapter log reply
*
- * @action: Action code echoed
- * @type: Log type echoed
- * @msg_len: Length of message
- * @func: Function code
- * @r1: Reserved
- * @msg_flag: Message flags
- * @r2: Reserved
- * @adapter_status: Status returned by adapter
+ * @action: Action code echoed.
+ * @type: Log type echoed.
+ * @msg_len: Length of message.
+ * @func: Function code.
+ * @r1: Reserved.
+ * @msg_flag: Message flags.
+ * @r2: Reserved.
+ * @adapter_status: Status returned by adapter.
*/
struct leapraid_adapter_log_rep {
u8 action;
@@ -1627,12 +1625,12 @@ struct leapraid_adapter_log_rep {
/**
* struct leapraid_adapter_features_req - Request adapter features
*
- * @r1: Reserved
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @r2: Reserved
- * @msg_flag: Message flags
- * @r3: Reserved
+ * @r1: Reserved.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @msg_flag: Message flags.
+ * @r3: Reserved.
*/
struct leapraid_adapter_features_req {
u8 r1[2];
@@ -1646,32 +1644,32 @@ struct leapraid_adapter_features_req {
/**
* struct leapraid_adapter_features_rep - Adapter features reply
*
- * @msg_ver: Message version
- * @msg_len: Length of reply message
- * @func: Function code
- * @header_ver: Header version
- * @r1: Reserved
- * @msg_flag: Message flags
- * @r2: Reserved
- * @adapter_status: Adapter status
- * @r3: Reserved
- * @who_init: Who initialized the adapter
- * @r4: Reserved
- * @max_msix_vectors: Max MSI-X vectors supported
- * @req_slot: Number of request slots
- * @r5: Reserved
- * @adapter_caps: Adapter capabilities
- * @fw_version: Firmware version
- * @sas_wide_max_qdepth: Max wide SAS queue depth
- * @sas_narrow_max_qdepth: Max narrow SAS queue depth
- * @r6: Reserved
- * @hp_slot: Number of high-priority slots
- * @r7: Reserved
- * @max_volumes: Maximum supported volumes
- * @max_dev_hdl: Maximum device handle
- * @r8: Reserved
- * @min_dev_hdl: Minimum device handle
- * @r9: Reserved
+ * @msg_ver: Message version.
+ * @msg_len: Length of reply message.
+ * @func: Function code.
+ * @header_ver: Header version.
+ * @r1: Reserved.
+ * @msg_flag: Message flags.
+ * @r2: Reserved.
+ * @adapter_status: Adapter status.
+ * @r3: Reserved.
+ * @who_init: Who initialized the adapter.
+ * @r4: Reserved.
+ * @max_msix_vectors: Max MSI-X vectors supported.
+ * @req_slot: Number of request slots.
+ * @r5: Reserved.
+ * @adapter_caps: Adapter capabilities.
+ * @fw_version: Firmware version.
+ * @sas_wide_max_qdepth: Max wide SAS queue depth.
+ * @sas_narrow_max_qdepth: Max narrow SAS queue depth.
+ * @r6: Reserved.
+ * @hp_slot: Number of high-priority slots.
+ * @r7: Reserved.
+ * @max_volumes: Maximum supported volumes.
+ * @max_dev_hdl: Maximum device handle.
+ * @r8: Reserved.
+ * @min_dev_hdl: Minimum device handle.
+ * @r9: Reserved.
*/
struct leapraid_adapter_features_rep {
u16 msg_ver;
@@ -1706,12 +1704,12 @@ struct leapraid_adapter_features_rep {
/**
* struct leapraid_scan_dev_req - Request to scan devices
*
- * @r1: Reserved
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @r2: Reserved
- * @msg_flag: Message flags
- * @r3: Reserved
+ * @r1: Reserved.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @msg_flag: Message flags.
+ * @r3: Reserved.
*/
struct leapraid_scan_dev_req {
u8 r1[2];
@@ -1725,14 +1723,14 @@ struct leapraid_scan_dev_req {
/**
* struct leapraid_scan_dev_rep - Scan devices reply
*
- * @r1: Reserved
- * @msg_len: Length of message
- * @func: Function code
- * @r2: Reserved
- * @msg_flag: Message flags
- * @r3: Reserved
- * @adapter_status: Adapter status
- * @r4: Reserved
+ * @r1: Reserved.
+ * @msg_len: Length of message.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @msg_flag: Message flags.
+ * @r3: Reserved.
+ * @adapter_status: Adapter status.
+ * @r4: Reserved.
*/
struct leapraid_scan_dev_rep {
u8 r1[2];
@@ -1748,14 +1746,14 @@ struct leapraid_scan_dev_rep {
/**
* struct leapraid_evt_notify_req - Event notification request
*
- * @r1: Reserved
- * @chain_offset: Offset for chained SGE
- * @func: Function code
- * @r2: Reserved
- * @msg_flag: Message flags
- * @r3: Reserved
- * @evt_masks: Event masks to enable notifications
- * @r4: Reserved
+ * @r1: Reserved.
+ * @chain_offset: Offset for chained SGE.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @msg_flag: Message flags.
+ * @r3: Reserved.
+ * @evt_masks: Event masks to enable notifications.
+ * @r4: Reserved.
*/
struct leapraid_evt_notify_req {
u8 r1[2];
@@ -1771,18 +1769,18 @@ struct leapraid_evt_notify_req {
/**
* struct leapraid_evt_notify_rep - Event notification reply
*
- * @evt_data_len: Length of event data
- * @msg_len: Length of message
- * @func: Function code
- * @r1: Reserved
- * @r2: Reserved
- * @msg_flag: Message flags
- * @r3: Reserved
- * @adapter_status: Adapter status
- * @r4: Reserved
- * @evt: Event code
- * @r5: Reserved
- * @evt_data: Event data array
+ * @evt_data_len: Length of event data.
+ * @msg_len: Length of message.
+ * @func: Function code.
+ * @r1: Reserved.
+ * @r2: Reserved.
+ * @msg_flag: Message flags.
+ * @r3: Reserved.
+ * @adapter_status: Adapter status.
+ * @r4: Reserved.
+ * @evt: Event code.
+ * @r5: Reserved.
+ * @evt_data: Event data array.
*/
struct leapraid_evt_notify_rep {
__le16 evt_data_len;
@@ -1802,14 +1800,14 @@ struct leapraid_evt_notify_rep {
/**
* struct leapraid_evt_data_sas_dev_status_change - SAS device status change
*
- * @task_tag: Task identifier
- * @reason_code: Reason for status change
- * @physical_port: Physical port number
- * @r1: Reserved
- * @dev_hdl: Device handle
- * @r2: Reserved
- * @sas_address: SAS address of device
- * @lun: Logical Unit Number
+ * @task_tag: Task identifier.
+ * @reason_code: Reason for status change.
+ * @physical_port: Physical port number.
+ * @r1: Reserved.
+ * @dev_hdl: Device handle.
+ * @r2: Reserved.
+ * @sas_address: SAS address of device.
+ * @lun: Logical unit Number.
*/
struct leapraid_evt_data_sas_dev_status_change {
__le16 task_tag;
@@ -1824,11 +1822,11 @@ struct leapraid_evt_data_sas_dev_status_change {
/**
* struct leapraid_evt_data_ir_change - IR (Integrated RAID) change event data
*
- * @r1: Reserved
- * @reason_code: Reason for IR change
- * @r2: Reserved
- * @vol_dev_hdl: Volume device handle
- * @phys_disk_dev_hdl: Physical disk device handle
+ * @r1: Reserved.
+ * @reason_code: Reason for IR change.
+ * @r2: Reserved.
+ * @vol_dev_hdl: Volume device handle.
+ * @phys_disk_dev_hdl: Physical disk device handle.
*/
struct leapraid_evt_data_ir_change {
u8 r1;
@@ -1841,10 +1839,10 @@ struct leapraid_evt_data_ir_change {
/**
* struct leapraid_evt_data_sas_disc - SAS discovery event data
*
- * @r1: Reserved
- * @reason_code: Reason for discovery event
- * @physical_port: Physical port number where event occurred
- * @r2: Reserved
+ * @r1: Reserved.
+ * @reason_code: Reason for discovery event.
+ * @physical_port: Physical port number where event occurred.
+ * @r2: Reserved.
*/
struct leapraid_evt_data_sas_disc {
u8 r1;
@@ -1856,9 +1854,9 @@ struct leapraid_evt_data_sas_disc {
/**
* struct leapraid_evt_sas_topo_phy_entry - SAS topology PHY entry
*
- * @attached_dev_hdl: Device handle attached to PHY
- * @link_rate: Current link rate
- * @phy_status: PHY status flags
+ * @attached_dev_hdl: Device handle attached to PHY.
+ * @link_rate: Current link rate.
+ * @phy_status: PHY status flags.
*/
struct leapraid_evt_sas_topo_phy_entry {
__le16 attached_dev_hdl;
@@ -1869,15 +1867,15 @@ struct leapraid_evt_sas_topo_phy_entry {
/**
* struct leapraid_evt_data_sas_topo_change_list - SAS topology change list
*
- * @encl_hdl: Enclosure handle
- * @exp_dev_hdl: Expander device handle
- * @num_phys: Number of PHYs in this entry
- * @r1: Reserved
- * @entry_num: Entry index
- * @start_phy_num: Start PHY number
- * @exp_status: Expander status
- * @physical_port: Physical port number
- * @phy: Array of SAS PHY entries
+ * @encl_hdl: Enclosure handle.
+ * @exp_dev_hdl: Expander device handle.
+ * @num_phys: Number of PHYs in this entry.
+ * @r1: Reserved.
+ * @entry_num: Entry index.
+ * @start_phy_num: Start PHY number.
+ * @exp_status: Expander status.
+ * @physical_port: Physical port number.
+ * @phy: Array of SAS PHY entries.
*/
struct leapraid_evt_data_sas_topo_change_list {
__le16 encl_hdl;
@@ -1892,15 +1890,16 @@ struct leapraid_evt_data_sas_topo_change_list {
};
/**
- * struct leapraid_evt_data_sas_enc_dev_status_change - SAS enclosure device status
+ * struct leapraid_evt_data_sas_enc_dev_status_change -
+ * SAS enclosure device status
*
- * @enc_hdl: Enclosure handle
- * @reason_code: Reason code for status change
- * @physical_port: Physical port number
- * @encl_logical_id: Enclosure logical ID
- * @num_slots: Number of slots in enclosure
- * @start_slot: First affected slot
- * @phy_bits: Bitmap of affected PHYs
+ * @enc_hdl: Enclosure handle.
+ * @reason_code: Reason code for status change.
+ * @physical_port: Physical port number.
+ * @encl_logical_id: Enclosure logical ID.
+ * @num_slots: Number of slots in enclosure.
+ * @start_slot: First affected slot.
+ * @phy_bits: Bitmap of affected PHYs.
*/
struct leapraid_evt_data_sas_enc_dev_status_change {
__le16 enc_hdl;
@@ -1913,21 +1912,21 @@ struct leapraid_evt_data_sas_enc_dev_status_change {
};
/**
- * struct leapraid_io_unit_ctrl_req - IO unit control request
+ * struct leapraid_io_unit_ctrl_req - I/O unit control request
*
- * @op: Operation code
- * @r1: Reserved
- * @chain_offset: SGE chain offset
- * @func: Function code
- * @dev_hdl: Device handle
- * @adapter_para: Adapter parameter selector
- * @msg_flag: Message flags
- * @r2: Reserved
- * @phy_num: PHY number
- * @r3: Reserved
- * @adapter_para_value: Value for adapter parameter
- * @adapter_para_value2: Optional second parameter value
- * @r4: Reserved
+ * @op: Operation code.
+ * @r1: Reserved.
+ * @chain_offset: SGE chain offset.
+ * @func: Function code.
+ * @dev_hdl: Device handle.
+ * @adapter_para: Adapter parameter selector.
+ * @msg_flag: Message flags.
+ * @r2: Reserved.
+ * @phy_num: PHY number.
+ * @r3: Reserved.
+ * @adapter_para_value: Value for adapter parameter.
+ * @adapter_para_value2: Optional second parameter value.
+ * @r4: Reserved.
*/
struct leapraid_io_unit_ctrl_req {
u8 op;
@@ -1946,13 +1945,13 @@ struct leapraid_io_unit_ctrl_req {
};
/**
- * struct leapraid_io_unit_ctrl_rep - IO unit control reply
+ * struct leapraid_io_unit_ctrl_rep - I/O unit control reply
*
- * @op: Operation code echoed
- * @r1: Reserved
- * @func: Function code
- * @dev_hdl: Device handle
- * @r2: Reserved
+ * @op: Operation code echoed.
+ * @r1: Reserved.
+ * @func: Function code.
+ * @dev_hdl: Device handle.
+ * @r2: Reserved.
*/
struct leapraid_io_unit_ctrl_rep {
u8 op;
@@ -1965,13 +1964,13 @@ struct leapraid_io_unit_ctrl_rep {
/**
* struct leapraid_raid_act_req - RAID action request
*
- * @act: RAID action code
- * @r1: Reserved
- * @func: Function code
- * @r2: Reserved
- * @phys_disk_num: Number of physical disks involved
- * @r3: Reserved
- * @action_data_sge: SGE describing action-specific data
+ * @act: RAID action code.
+ * @r1: Reserved.
+ * @func: Function code.
+ * @r2: Reserved.
+ * @phys_disk_num: Number of physical disks involved.
+ * @r3: Reserved.
+ * @action_data_sge: SGE describing action-specific data.
*/
struct leapraid_raid_act_req {
u8 act;
@@ -1986,13 +1985,13 @@ struct leapraid_raid_act_req {
/**
* struct leapraid_raid_act_rep - RAID action reply
*
- * @act: RAID action code echoed
- * @r1: Reserved
- * @func: Function code
- * @vol_dev_hdl: Volume device handle
+ * @act: RAID action code echoed.
+ * @r1: Reserved.
+ * @func: Function code.
+ * @vol_dev_hdl: Volume device handle.
* @r2: Reserved
- * @adapter_status: Status returned by adapter
- * @r3: Reserved
+ * @adapter_status: Status returned by adapter.
+ * @r3: Reserved.
*/
struct leapraid_raid_act_rep {
u8 act;
@@ -2007,15 +2006,15 @@ struct leapraid_raid_act_rep {
/**
* struct leapraid_smp_passthrough_req - SMP passthrough request
*
- * @passthrough_flg: Passthrough flags
- * @physical_port: Target PHY port
- * @r1: Reserved
- * @func: Function code
- * @req_data_len: Request data length
- * @r2: Reserved
- * @sas_address: SAS address of target device
- * @r3: Reserved
- * @sgl: Scatter-gather list describing request buffer
+ * @passthrough_flg: Passthrough flags.
+ * @physical_port: Target PHY port.
+ * @r1: Reserved.
+ * @func: Function code.
+ * @req_data_len: Request data length.
+ * @r2: Reserved.
+ * @sas_address: SAS address of target device.
+ * @r3: Reserved.
+ * @sgl: Scatter-gather list describing request buffer.
*/
struct leapraid_smp_passthrough_req {
u8 passthrough_flg;
@@ -2032,14 +2031,14 @@ struct leapraid_smp_passthrough_req {
/**
* struct leapraid_smp_passthrough_rep - SMP passthrough reply
*
- * @passthrough_flg: Passthrough flags echoed
- * @physical_port: Target PHY port
- * @r1: Reserved
- * @func: Function code
- * @resp_data_len: Length of response data
- * @r2: Reserved
- * @adapter_status: Adapter status
- * @r3: Reserved
+ * @passthrough_flg: Passthrough flags echoed.
+ * @physical_port: Target PHY port.
+ * @r1: Reserved.
+ * @func: Function code.
+ * @resp_data_len: Length of response data.
+ * @r2: Reserved.
+ * @adapter_status: Adapter status.
+ * @r3: Reserved.
*/
struct leapraid_smp_passthrough_rep {
u8 passthrough_flg;
@@ -2053,13 +2052,13 @@ struct leapraid_smp_passthrough_rep {
};
/**
- * struct leapraid_sas_io_unit_ctrl_req - SAS IO unit control request
+ * struct leapraid_sas_io_unit_ctrl_req - SAS I/O unit control request
*
- * @op: Operation code
- * @r1: Reserved
- * @func: Function code
- * @dev_hdl: Device handle
- * @r2: Reserved
+ * @op: Operation code.
+ * @r1: Reserved.
+ * @func: Function code.
+ * @dev_hdl: Device handle.
+ * @r2: Reserved.
*/
struct leapraid_sas_io_unit_ctrl_req {
u8 op;
diff --git a/drivers/scsi/leapraid/leapraid_app.c b/drivers/scsi/leapraid/leapraid_app.c
index f838bd5aa20e..25ec57c2ce4b 100644
--- a/drivers/scsi/leapraid/leapraid_app.c
+++ b/drivers/scsi/leapraid/leapraid_app.c
@@ -1,23 +1,22 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2025 LeapIO Tech Inc.
+ * Copyright (C) 2026 LeapIO Tech Inc.
*
- * LeapRAID Storage and RAID Controller driver.
+ * LeapRAID storage and RAID controller driver.
*/
-
#include <linux/compat.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include "leapraid_func.h"
-/* ioctl device file */
+/* IOCTL device file name. */
#define LEAPRAID_DEV_NAME "leapraid_ctl"
-/* ioctl version */
+/* IOCTL version. */
#define LEAPRAID_IOCTL_VERSION 0x07
-/* ioctl command */
+/* IOCTL commands. */
#define LEAPRAID_ADAPTER_INFO 17
#define LEAPRAID_COMMAND 20
#define LEAPRAID_EVENTQUERY 21
@@ -25,9 +24,10 @@
/**
* struct leapraid_ioctl_header - IOCTL command header
- * @adapter_id : Adapter identifier
- * @port_number: Port identifier
- * @max_data_size: Maximum data size for transfer
+ *
+ * @adapter_id : Adapter identifier.
+ * @port_number: Port identifier.
+ * @max_data_size: Maximum data size for transfer.
*/
struct leapraid_ioctl_header {
u32 adapter_id;
@@ -37,7 +37,8 @@ struct leapraid_ioctl_header {
/**
* struct leapraid_ioctl_diag_reset - Diagnostic reset request
- * @hdr: Common IOCTL header
+ *
+ * @hdr: Common IOCTL header.
*/
struct leapraid_ioctl_diag_reset {
struct leapraid_ioctl_header hdr;
@@ -45,12 +46,13 @@ struct leapraid_ioctl_diag_reset {
/**
* struct leapraid_ioctl_pci_info - PCI device information
- * @u: Union holding PCI bus/device/function information
- * @u.bits.dev: PCI device number
- * @u.bits.func: PCI function number
- * @u.bits.bus: PCI bus number
- * @u.word: Combined representation of PCI BDF
- * @seg_id: PCI segment identifier
+ *
+ * @u: Union holding PCI bus/device/function information.
+ * @u.bits.dev: PCI device number.
+ * @u.bits.func: PCI function number.
+ * @u.bits.bus: PCI bus number.
+ * @u.word: Combined representation of PCI BDF.
+ * @seg_id: PCI segment identifier.
*/
struct leapraid_ioctl_pci_info {
union {
@@ -66,21 +68,22 @@ struct leapraid_ioctl_pci_info {
/**
* struct leapraid_ioctl_adapter_info - Adapter information for IOCTL
- * @hdr: IOCTL header
- * @adapter_type: Adapter type identifier
- * @port_number: Port number
- * @pci_id: PCI device ID
- * @revision: Revision number
- * @sub_dev: Subsystem device ID
- * @sub_vendor: Subsystem vendor ID
- * @r0: Reserved
- * @fw_ver: Firmware version
- * @bios_ver: BIOS version
- * @driver_ver: Driver version
- * @r1: Reserved
- * @scsi_id: SCSI ID
- * @r2: Reserved
- * @pci_info: PCI information structure
+ *
+ * @hdr: IOCTL header.
+ * @adapter_type: Adapter type identifier.
+ * @port_number: Port number.
+ * @pci_id: PCI device ID.
+ * @revision: Revision number.
+ * @sub_dev: Subsystem device ID.
+ * @sub_vendor: Subsystem vendor ID.
+ * @r0: Reserved.
+ * @fw_ver: Firmware version.
+ * @bios_ver: BIOS version.
+ * @driver_ver: Driver version.
+ * @r1: Reserved.
+ * @scsi_id: SCSI ID.
+ * @r2: Reserved.
+ * @pci_info: PCI information structure.
*/
struct leapraid_ioctl_adapter_info {
struct leapraid_ioctl_header hdr;
@@ -102,18 +105,19 @@ struct leapraid_ioctl_adapter_info {
/**
* struct leapraid_ioctl_command - IOCTL command structure
- * @hdr: IOCTL header
- * @timeout: Command timeout
- * @rep_msg_buf_ptr: User pointer to reply message buffer
- * @c2h_buf_ptr: User pointer to card-to-host data buffer
- * @h2c_buf_ptr: User pointer to host-to-card data buffer
- * @sense_data_ptr: User pointer to sense data buffer
- * @max_rep_bytes: Maximum reply bytes
- * @c2h_size: Card-to-host data size
- * @h2c_size: Host-to-card data size
- * @max_sense_bytes: Maximum sense data bytes
- * @data_sge_offset: Data SGE offset
- * @mf: Message frame data (flexible array)
+ *
+ * @hdr: IOCTL header.
+ * @timeout: Command timeout.
+ * @rep_msg_buf_ptr: User pointer to reply message buffer.
+ * @c2h_buf_ptr: User pointer to card-to-host data buffer.
+ * @h2c_buf_ptr: User pointer to host-to-card data buffer.
+ * @sense_data_ptr: User pointer to sense data buffer.
+ * @max_rep_bytes: Maximum reply bytes.
+ * @c2h_size: Card-to-host data size.
+ * @h2c_size: Host-to-card data size.
+ * @max_sense_bytes: Maximum sense data bytes.
+ * @data_sge_offset: Data SGE offset.
+ * @mf: Message frame data (flexible array).
*/
struct leapraid_ioctl_command {
struct leapraid_ioctl_header hdr;
@@ -146,39 +150,38 @@ static struct leapraid_adapter *leapraid_ctl_lookup_adapter(int adapter_id)
return NULL;
}
-static void leapraid_cli_scsiio_cmd(struct leapraid_adapter *adapter,
- struct leapraid_req *ctl_sp_mpi_req, u16 taskid,
+static void leapraid_ctl_scsiio_cmd(struct leapraid_adapter *adapter,
+ void *ctl_sp_mpi_req,
+ u16 taskid,
dma_addr_t h2c_dma_addr, size_t h2c_size,
dma_addr_t c2h_dma_addr, size_t c2h_size,
u16 dev_hdl, void *psge)
{
- struct leapraid_mpi_scsiio_req *scsiio_request =
- (struct leapraid_mpi_scsiio_req *)ctl_sp_mpi_req;
+ struct leapraid_mpi_scsiio_req *scsiio_request = ctl_sp_mpi_req;
scsiio_request->sense_buffer_len = SCSI_SENSE_BUFFERSIZE;
scsiio_request->sense_buffer_low_add =
- leapraid_get_sense_buffer_dma(adapter, taskid);
- memset((void *)(&adapter->driver_cmds.ctl_cmd.sense),
+ leapraid_get_sense_buffer_dma(adapter, taskid);
+ memset(&adapter->driver_cmds.ctl_cmd.sense,
0, SCSI_SENSE_BUFFERSIZE);
leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr,
h2c_size, c2h_dma_addr, c2h_size);
- if (scsiio_request->func == LEAPRAID_FUNC_SCSIIO_REQ)
+ if (scsiio_request->func == LEAPRAID_FUNC_SCSIIO)
leapraid_fire_scsi_io(adapter, taskid, dev_hdl);
else
leapraid_fire_task(adapter, taskid);
}
-static void leapraid_ctl_smp_passthrough_cmd(struct leapraid_adapter *adapter,
- struct leapraid_req *ctl_sp_mpi_req,
- u16 taskid,
- dma_addr_t h2c_dma_addr,
- size_t h2c_size,
- dma_addr_t c2h_dma_addr,
- size_t c2h_size,
- void *psge, void *h2c)
+static int leapraid_ctl_smp_passthrough_cmd(struct leapraid_adapter *adapter,
+ void *ctl_sp_req,
+ u16 taskid,
+ dma_addr_t h2c_dma_addr,
+ size_t h2c_size,
+ dma_addr_t c2h_dma_addr,
+ size_t c2h_size,
+ void *psge, void *h2c)
{
- struct leapraid_smp_passthrough_req *smp_pt_req =
- (struct leapraid_smp_passthrough_req *)ctl_sp_mpi_req;
+ struct leapraid_smp_passthrough_req *smp_pt_req = ctl_sp_req;
u8 *data;
if (!adapter->adapter_attr.enable_mp)
@@ -188,83 +191,49 @@ static void leapraid_ctl_smp_passthrough_cmd(struct leapraid_adapter *adapter,
else
data = h2c;
- if (data[1] == LEAPRAID_SMP_FN_REPORT_PHY_ERR_LOG &&
- (data[10] == 1 || data[10] == 2))
- adapter->reset_desc.adapter_link_resetting = true;
+ if (!(smp_pt_req->passthrough_flg & LEAPRAID_SMP_PT_FLAG_SGL_PTR) &&
+ h2c_size <= 10) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Invalid request size=%zu\n",
+ __func__, h2c_size);
+ return -EINVAL;
+ }
+
+ if (data[1] == SMP_PHY_CONTROL &&
+ (data[10] == SMP_PHY_CONTROL_LINK_RESET ||
+ data[10] == SMP_PHY_CONTROL_HARD_RESET))
+ adapter->reset_desc.adapter_link_resetting = 1;
+
leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr,
h2c_size, c2h_dma_addr, c2h_size);
leapraid_fire_task(adapter, taskid);
+ return 0;
}
-static void leapraid_ctl_fire_ieee_cmd(struct leapraid_adapter *adapter,
- dma_addr_t h2c_dma_addr,
- size_t h2c_size,
- dma_addr_t c2h_dma_addr,
- size_t c2h_size,
- void *psge, u16 taskid)
-{
- leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size,
- c2h_dma_addr, c2h_size);
- leapraid_fire_task(adapter, taskid);
-}
-
-static void leapraid_ctl_sata_passthrough_cmd(struct leapraid_adapter *adapter,
+static void leapraid_ctl_sas_io_unit_ctrl_cmd(struct leapraid_adapter *adapter,
+ void *ctl_sp_req,
dma_addr_t h2c_dma_addr,
size_t h2c_size,
dma_addr_t c2h_dma_addr,
size_t c2h_size,
void *psge, u16 taskid)
{
- leapraid_ctl_fire_ieee_cmd(adapter, h2c_dma_addr,
- h2c_size, c2h_dma_addr,
- c2h_size, psge, taskid);
-}
-
-static void leapraid_ctl_load_fw_cmd(struct leapraid_adapter *adapter,
- dma_addr_t h2c_dma_addr, size_t h2c_size,
- dma_addr_t c2h_dma_addr, size_t c2h_size,
- void *psge, u16 taskid)
-{
- leapraid_ctl_fire_ieee_cmd(adapter, h2c_dma_addr,
- h2c_size, c2h_dma_addr,
- c2h_size, psge, taskid);
-}
+ struct leapraid_sas_io_unit_ctrl_req *sas_io_unit_ctl_req = ctl_sp_req;
-static void leapraid_ctl_fire_mpi_cmd(struct leapraid_adapter *adapter,
- dma_addr_t h2c_dma_addr, size_t h2c_size,
- dma_addr_t c2h_dma_addr, size_t c2h_size,
- void *psge, u16 taskid)
-{
+ if (sas_io_unit_ctl_req->op == LEAPRAID_SAS_OP_PHY_HARD_RESET ||
+ sas_io_unit_ctl_req->op == LEAPRAID_SAS_OP_PHY_LINK_RESET)
+ adapter->reset_desc.adapter_link_resetting = 1;
leapraid_build_mpi_sg(adapter, psge, h2c_dma_addr,
h2c_size, c2h_dma_addr, c2h_size);
leapraid_fire_task(adapter, taskid);
}
-static void leapraid_ctl_sas_io_unit_ctrl_cmd(struct leapraid_adapter *adapter,
- struct leapraid_req *ctl_sp_mpi_req,
- dma_addr_t h2c_dma_addr,
- size_t h2c_size,
- dma_addr_t c2h_dma_addr,
- size_t c2h_size,
- void *psge, u16 taskid)
+static int leapraid_ctl_do_command(struct leapraid_adapter *adapter,
+ struct leapraid_ioctl_command *karg,
+ void __user *mf)
{
- struct leapraid_sas_io_unit_ctrl_req *sas_io_unit_ctrl_req =
- (struct leapraid_sas_io_unit_ctrl_req *)ctl_sp_mpi_req;
-
- if (sas_io_unit_ctrl_req->op == LEAPRAID_SAS_OP_PHY_HARD_RESET ||
- sas_io_unit_ctrl_req->op == LEAPRAID_SAS_OP_PHY_LINK_RESET)
- adapter->reset_desc.adapter_link_resetting = true;
- leapraid_ctl_fire_mpi_cmd(adapter, h2c_dma_addr,
- h2c_size, c2h_dma_addr,
- c2h_size, psge, taskid);
-}
-
-static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
- struct leapraid_ioctl_command *karg,
- void __user *mf)
-{
- struct leapraid_req *leap_mpi_req = NULL;
- struct leapraid_req *ctl_sp_mpi_req = NULL;
+ struct leapraid_req *leap_mpi_req;
+ struct leapraid_req *ctl_sp_mpi_req;
u16 taskid;
void *h2c = NULL;
size_t h2c_size = 0;
@@ -277,74 +246,88 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
u16 dev_hdl = LEAPRAID_INVALID_DEV_HANDLE;
bool issue_reset = false;
u32 sz;
- long rc = 0;
+ int rc;
- rc = leapraid_check_adapter_is_op(adapter);
+ rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
+ __func__);
if (rc)
- goto out;
+ return rc;
leap_mpi_req = kzalloc(LEAPRAID_REQUEST_SIZE, GFP_KERNEL);
- if (!leap_mpi_req) {
- rc = -ENOMEM;
- goto out;
- }
+ if (!leap_mpi_req)
+ return -ENOMEM;
- if (karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE > LEAPRAID_REQUEST_SIZE ||
- karg->data_sge_offset > ((UINT_MAX) / LEAPRAID_SGE_OFFSET_SIZE)) {
+ if (karg->data_sge_offset > (UINT_MAX / LEAPRAID_SGE_OFFSET_SIZE) ||
+ karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE >
+ LEAPRAID_REQUEST_SIZE) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Invalid data_sge_offset=%u\n",
+ __func__, karg->data_sge_offset);
rc = -EINVAL;
- goto out;
+ goto out_cleanup;
}
if (copy_from_user(leap_mpi_req, mf,
karg->data_sge_offset * LEAPRAID_SGE_OFFSET_SIZE)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy request message from user\n",
+ __func__);
rc = -EFAULT;
- goto out;
+ goto out_cleanup;
}
taskid = adapter->driver_cmds.ctl_cmd.taskid;
adapter->driver_cmds.ctl_cmd.status = LEAPRAID_CMD_PENDING;
- memset((void *)(&adapter->driver_cmds.ctl_cmd.reply), 0,
- LEAPRAID_REPLY_SIEZ);
+ 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);
- if (ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO_REQ ||
- ctl_sp_mpi_req->func == LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH ||
- ctl_sp_mpi_req->func == LEAPRAID_FUNC_SATA_PASSTHROUGH) {
+ if (ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO ||
+ ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH ||
+ ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH) {
dev_hdl = le16_to_cpu(ctl_sp_mpi_req->func_dep1);
- if (!dev_hdl || dev_hdl > adapter->adapter_attr.features.max_dev_handle) {
+ if (!dev_hdl ||
+ dev_hdl > adapter->adapter_attr.features.max_dev_handle) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Invalid device handle\n", __func__);
rc = -EINVAL;
- goto out;
+ goto out_cleanup;
}
}
- if (WARN_ON(ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSI_TMF))
- return -EINVAL;
+ if (WARN_ON(ctl_sp_mpi_req->func == LEAPRAID_FUNC_SCSI_TMF)) {
+ rc = -EINVAL;
+ 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_ATOMIC);
+ &h2c_dma_addr, GFP_KERNEL);
if (!h2c) {
rc = -ENOMEM;
- goto out;
+ goto out_cleanup;
}
if (copy_from_user(h2c, karg->h2c_buf_ptr, h2c_size)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy h2c from user\n",
+ __func__);
rc = -EFAULT;
- goto out;
+ goto out_cleanup;
}
}
if (c2h_size) {
- c2h = dma_alloc_coherent(&adapter->pdev->dev,
- c2h_size, &c2h_dma_addr, GFP_ATOMIC);
+ c2h = dma_alloc_coherent(&adapter->pdev->dev, c2h_size,
+ &c2h_dma_addr, GFP_KERNEL);
if (!c2h) {
rc = -ENOMEM;
- goto out;
+ goto out_cleanup;
}
}
@@ -353,13 +336,9 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
init_completion(&adapter->driver_cmds.ctl_cmd.done);
switch (ctl_sp_mpi_req->func) {
- case LEAPRAID_FUNC_SCSIIO_REQ:
- case LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH:
- if (test_bit(dev_hdl, (unsigned long *)adapter->dev_topo.dev_removing)) {
- rc = -EINVAL;
- goto out;
- }
- leapraid_cli_scsiio_cmd(adapter, ctl_sp_mpi_req, taskid,
+ case LEAPRAID_FUNC_SCSIIO:
+ case LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH:
+ leapraid_ctl_scsiio_cmd(adapter, ctl_sp_mpi_req, taskid,
h2c_dma_addr, h2c_size,
c2h_dma_addr, c2h_size,
dev_hdl, psge);
@@ -367,28 +346,26 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
case LEAPRAID_FUNC_SMP_PASSTHROUGH:
if (!h2c) {
rc = -EINVAL;
- goto out;
+ goto out_cleanup;
}
- leapraid_ctl_smp_passthrough_cmd(adapter,
- ctl_sp_mpi_req, taskid,
- h2c_dma_addr, h2c_size,
- c2h_dma_addr, c2h_size,
- psge, h2c);
+ rc = leapraid_ctl_smp_passthrough_cmd(adapter,
+ ctl_sp_mpi_req, taskid,
+ h2c_dma_addr, h2c_size,
+ c2h_dma_addr, c2h_size,
+ psge, h2c);
+ if (rc)
+ goto out_cleanup;
break;
- case LEAPRAID_FUNC_SATA_PASSTHROUGH:
- if (test_bit(dev_hdl, (unsigned long *)adapter->dev_topo.dev_removing)) {
- rc = -EINVAL;
- goto out;
- }
- leapraid_ctl_sata_passthrough_cmd(adapter, h2c_dma_addr,
- h2c_size, c2h_dma_addr,
- c2h_size, psge, taskid);
+ case LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH:
+ leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size,
+ c2h_dma_addr, c2h_size);
+ leapraid_fire_task(adapter, taskid);
break;
case LEAPRAID_FUNC_FW_DOWNLOAD:
case LEAPRAID_FUNC_FW_UPLOAD:
- leapraid_ctl_load_fw_cmd(adapter, h2c_dma_addr,
- h2c_size, c2h_dma_addr,
- c2h_size, psge, taskid);
+ leapraid_build_ieee_sg(adapter, psge, h2c_dma_addr, h2c_size,
+ c2h_dma_addr, c2h_size);
+ leapraid_fire_task(adapter, taskid);
break;
case LEAPRAID_FUNC_SAS_IO_UNIT_CTRL:
leapraid_ctl_sas_io_unit_ctrl_cmd(adapter, ctl_sp_mpi_req,
@@ -397,23 +374,27 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
psge, taskid);
break;
default:
- leapraid_ctl_fire_mpi_cmd(adapter, h2c_dma_addr,
- h2c_size, c2h_dma_addr,
- c2h_size, psge, taskid);
+ leapraid_build_mpi_sg(adapter, psge, h2c_dma_addr,
+ h2c_size, c2h_dma_addr, c2h_size);
+ leapraid_fire_task(adapter, taskid);
break;
}
timeout = karg->timeout;
if (timeout < LEAPRAID_CTL_CMD_TIMEOUT)
timeout = LEAPRAID_CTL_CMD_TIMEOUT;
- wait_for_completion_timeout(&adapter->driver_cmds.ctl_cmd.done,
- timeout * HZ);
+ if (!wait_for_completion_timeout(&adapter->driver_cmds.ctl_cmd.done,
+ timeout * HZ)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: ctl_cmd timeout, status=0x%x\n",
+ __func__, adapter->driver_cmds.ctl_cmd.status);
+ }
if ((leap_mpi_req->func == LEAPRAID_FUNC_SMP_PASSTHROUGH ||
leap_mpi_req->func == LEAPRAID_FUNC_SAS_IO_UNIT_CTRL) &&
- adapter->reset_desc.adapter_link_resetting) {
- adapter->reset_desc.adapter_link_resetting = false;
- }
+ adapter->reset_desc.adapter_link_resetting)
+ adapter->reset_desc.adapter_link_resetting = 0;
+
if (!(adapter->driver_cmds.ctl_cmd.status & LEAPRAID_CMD_DONE)) {
issue_reset =
leapraid_check_reset(
@@ -421,57 +402,66 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
goto reset;
}
- if (c2h_size) {
- if (copy_to_user(karg->c2h_buf_ptr, c2h, c2h_size)) {
- rc = -ENODATA;
- goto out;
- }
+ if (c2h_size && copy_to_user(karg->c2h_buf_ptr, c2h, c2h_size)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy c2h to user\n", __func__);
+ rc = -ENODATA;
+ goto out_cleanup;
}
if (karg->max_rep_bytes) {
- sz = min_t(u32, karg->max_rep_bytes, LEAPRAID_REPLY_SIEZ);
+ sz = min_t(u32, karg->max_rep_bytes, LEAPRAID_REPLY_SIZE);
if (copy_to_user(karg->rep_msg_buf_ptr,
- (void *)&adapter->driver_cmds.ctl_cmd.reply,
+ &adapter->driver_cmds.ctl_cmd.reply,
sz)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy reply to user\n",
+ __func__);
rc = -ENODATA;
- goto out;
+ goto out_cleanup;
}
}
if (karg->max_sense_bytes &&
- (leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO_REQ ||
- leap_mpi_req->func == LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH)) {
+ (leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO ||
+ leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH)) {
if (!karg->sense_data_ptr)
- goto out;
+ goto out_cleanup;
sz = min_t(u32, karg->max_sense_bytes, SCSI_SENSE_BUFFERSIZE);
if (copy_to_user(karg->sense_data_ptr,
- (void *)&adapter->driver_cmds.ctl_cmd.sense,
+ &adapter->driver_cmds.ctl_cmd.sense,
sz)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy sense data to user\n",
+ __func__);
rc = -ENODATA;
- goto out;
+ goto out_cleanup;
}
}
reset:
if (issue_reset) {
rc = -ENODATA;
- if (leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO_REQ ||
- leap_mpi_req->func == LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH ||
- leap_mpi_req->func == LEAPRAID_FUNC_SATA_PASSTHROUGH) {
+ if (leap_mpi_req->func == LEAPRAID_FUNC_SCSIIO ||
+ leap_mpi_req->func ==
+ LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH ||
+ leap_mpi_req->func ==
+ LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH) {
dev_err(&adapter->pdev->dev,
- "fire tgt reset: hdl=0x%04x\n",
+ "Fire tgt reset, hdl=0x%04x\n",
le16_to_cpu(leap_mpi_req->func_dep1));
- leapraid_issue_locked_tm(adapter,
+ leapraid_issue_locked_tm(
+ adapter,
le16_to_cpu(leap_mpi_req->func_dep1), 0, 0, 0,
LEAPRAID_TM_TASKTYPE_TARGET_RESET, taskid,
LEAPRAID_TM_MSGFLAGS_LINK_RESET);
} else {
dev_info(&adapter->pdev->dev,
- "%s:%d call hard_reset\n",
+ "%s:%d: call hard_reset\n",
__func__, __LINE__);
leapraid_hard_reset_handler(adapter, FULL_RESET);
}
}
-out:
+out_cleanup:
if (c2h)
dma_free_coherent(&adapter->pdev->dev, c2h_size,
c2h, c2h_dma_addr);
@@ -483,12 +473,12 @@ static long leapraid_ctl_do_command(struct leapraid_adapter *adapter,
return rc;
}
-static long leapraid_ctl_get_adapter_info(struct leapraid_adapter *adapter,
- void __user *arg)
+static int leapraid_ctl_get_adapter_info(struct leapraid_adapter *adapter,
+ void __user *arg)
{
struct leapraid_ioctl_adapter_info *karg;
- ssize_t __maybe_unused ret;
u8 revision;
+ int rc = 0;
karg = kzalloc(sizeof(*karg), GFP_KERNEL);
if (!karg)
@@ -504,80 +494,98 @@ static long leapraid_ctl_get_adapter_info(struct leapraid_adapter *adapter,
karg->pci_info.u.bits.func = PCI_FUNC(adapter->pdev->devfn);
karg->pci_info.seg_id = pci_domain_nr(adapter->pdev->bus);
karg->fw_ver = adapter->adapter_attr.features.fw_version;
- ret = strscpy(karg->driver_ver, LEAPRAID_DRIVER_NAME,
- sizeof(karg->driver_ver));
- strcat(karg->driver_ver, "-");
- strcat(karg->driver_ver, LEAPRAID_DRIVER_VERSION);
+
+ snprintf(karg->driver_ver, sizeof(karg->driver_ver), "%s-%s",
+ LEAPRAID_DRIVER_NAME, LEAPRAID_DRIVER_VERSION);
+
karg->adapter_type = LEAPRAID_IOCTL_VERSION;
karg->bios_ver = adapter->adapter_attr.bios_version;
if (copy_to_user(arg, karg,
sizeof(struct leapraid_ioctl_adapter_info))) {
- kfree(karg);
- return -EFAULT;
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy info to user\n", __func__);
+ rc = -EFAULT;
+ goto free_buf;
}
+free_buf:
kfree(karg);
- return 0;
+ return rc;
}
-static long leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd,
- void __user *arg, u8 compat)
+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;
- long rc = -ENOIOCTLCMD;
- int count;
-
- if (copy_from_user(&ioctl_header, (char __user *)arg,
- sizeof(struct leapraid_ioctl_header)))
+ struct leapraid_ioctl_command __user *uarg;
+ struct leapraid_ioctl_command karg;
+ int rc = -ENOIOCTLCMD;
+
+ if (copy_from_user(&ioctl_header, arg,
+ sizeof(struct leapraid_ioctl_header))) {
+ pr_err("%s:%s: Failed to copy header from user\n",
+ LEAPRAID_DRIVER_NAME, __func__);
return -EFAULT;
+ }
adapter = leapraid_ctl_lookup_adapter(ioctl_header.adapter_id);
if (!adapter)
return -EFAULT;
+ if (atomic_read(&adapter->overheat_desc.thermal_alert)) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed, thermal_alert=%d\n",
+ __func__,
+ atomic_read(&adapter->overheat_desc.thermal_alert));
+ return -EFAULT;
+ }
+
mutex_lock(&adapter->access_ctrl.pci_access_lock);
- rc = leapraid_check_adapter_is_op(adapter);
+ rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_LONG,
+ __func__);
if (rc)
- goto out;
+ goto unlock;
- count = LEAPRAID_WAIT_SHOST_RECOVERY;
- while (count--) {
- if (!adapter->access_ctrl.shost_recovering)
- break;
- ssleep(1);
+ if (!wait_event_timeout(adapter->access_ctrl.shost_recover_wq,
+ !adapter->access_ctrl.shost_recover_async,
+ LEAPRAID_WAIT_SHOST_RECOVERY * HZ)) {
+ dev_warn(&adapter->pdev->dev,
+ "Timeout waiting for shost recovery async\n");
+ rc = -EAGAIN;
+ goto unlock;
}
- if (adapter->access_ctrl.shost_recovering ||
- adapter->access_ctrl.pcie_recovering ||
+ if (adapter->access_ctrl.pcie_recovering ||
adapter->scan_dev_desc.driver_loading ||
adapter->access_ctrl.host_removing) {
rc = -EAGAIN;
- goto out;
+ goto unlock;
}
if (file->f_flags & O_NONBLOCK) {
if (!mutex_trylock(&adapter->driver_cmds.ctl_cmd.mutex)) {
rc = -EAGAIN;
- goto out;
+ goto unlock;
}
- } else if (mutex_lock_interruptible(&adapter->driver_cmds.ctl_cmd.mutex)) {
+ } else if (mutex_lock_interruptible(&adapter->driver_cmds
+ .ctl_cmd.mutex)) {
rc = -ERESTARTSYS;
- goto out;
+ goto unlock;
}
switch (_IOC_NR(cmd)) {
case LEAPRAID_ADAPTER_INFO:
- if (_IOC_SIZE(cmd) == sizeof(struct leapraid_ioctl_adapter_info))
+ if (_IOC_SIZE(cmd) ==
+ sizeof(struct leapraid_ioctl_adapter_info))
rc = leapraid_ctl_get_adapter_info(adapter, arg);
break;
case LEAPRAID_COMMAND:
- {
- struct leapraid_ioctl_command __user *uarg;
- struct leapraid_ioctl_command karg;
-
if (copy_from_user(&karg, arg, sizeof(karg))) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to copy data from user\n",
+ __func__);
rc = -EFAULT;
break;
}
@@ -591,61 +599,77 @@ static long leapraid_ctl_ioctl_main(struct file *file, unsigned int cmd,
uarg = arg;
rc = leapraid_ctl_do_command(adapter, &karg,
&uarg->mf);
+ if (rc)
+ dev_warn(&adapter->pdev->dev,
+ "%s: IOCTL cmd failed rc=%d\n",
+ __func__, rc);
}
break;
- }
case LEAPRAID_EVENTQUERY:
case LEAPRAID_EVENTREPORT:
rc = 0;
break;
default:
- pr_err("unknown ioctl opcode=0x%08x\n", cmd);
+ dev_err(&adapter->pdev->dev,
+ "Unknown IOCTL opcode=0x%08x\n", cmd);
break;
}
mutex_unlock(&adapter->driver_cmds.ctl_cmd.mutex);
-out:
+unlock:
mutex_unlock(&adapter->access_ctrl.pci_access_lock);
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, 0);
+ return leapraid_ctl_ioctl_main(file, cmd, (void __user *)arg);
}
static int leapraid_fw_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct leapraid_adapter *adapter;
+ /* Userspace passes the adapter ID via vma->vm_pgoff. */
+ u32 adapter_id = vma->vm_pgoff;
unsigned long length;
- unsigned long pfn;
+ int rc;
length = vma->vm_end - vma->vm_start;
- adapter = list_first_entry(&leapraid_adapter_list,
- struct leapraid_adapter, list);
+ adapter = leapraid_ctl_lookup_adapter(adapter_id);
+ if (!adapter) {
+ pr_err("%s: No adapter found!\n", __func__);
+ return -EINVAL;
+ }
if (length > (LEAPRAID_SYS_LOG_BUF_SIZE +
LEAPRAID_SYS_LOG_BUF_RESERVE)) {
dev_err(&adapter->pdev->dev,
- "requested mapping size is too large!\n");
+ "Requested mapping size is too large!\n");
return -EINVAL;
}
if (!adapter->fw_log_desc.fw_log_buffer) {
- dev_err(&adapter->pdev->dev, "no log buffer!\n");
+ dev_err(&adapter->pdev->dev, "No log buffer!\n");
return -EINVAL;
}
- pfn = virt_to_phys(adapter->fw_log_desc.fw_log_buffer) >> PAGE_SHIFT;
+ vma->vm_pgoff = 0;
- if (remap_pfn_range(vma, vma->vm_start, pfn, length,
- vma->vm_page_prot)) {
+ rc = dma_mmap_coherent(&adapter->pdev->dev, vma,
+ adapter->fw_log_desc.fw_log_buffer,
+ adapter->fw_log_desc.fw_log_buffer_dma,
+ length);
+ if (rc) {
dev_err(&adapter->pdev->dev,
- "failed to map memory to user space!\n");
- return -EAGAIN;
+ "Failed to map memory to user space!\n");
+ return rc;
}
return 0;
@@ -655,6 +679,7 @@ 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 = {
@@ -663,10 +688,14 @@ static struct miscdevice leapraid_ctl_dev = {
.fops = &leapraid_ctl_fops,
};
-void leapraid_ctl_init(void)
+int leapraid_ctl_init(void)
{
- if (misc_register(&leapraid_ctl_dev) < 0)
- pr_err("%s can't register misc device\n", LEAPRAID_DRIVER_NAME);
+ if (misc_register(&leapraid_ctl_dev) < 0) {
+ pr_err("%s Can't register misc device\n",
+ LEAPRAID_DRIVER_NAME);
+ return -ENODEV;
+ }
+ return 0;
}
void leapraid_ctl_exit(void)
diff --git a/drivers/scsi/leapraid/leapraid_func.c b/drivers/scsi/leapraid/leapraid_func.c
index 5dfe95a8dd84..01096664d122 100644
--- a/drivers/scsi/leapraid/leapraid_func.c
+++ b/drivers/scsi/leapraid/leapraid_func.c
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2025 LeapIO Tech Inc.
+ * Copyright (C) 2026 LeapIO Tech Inc.
*
- * LeapRAID Storage and RAID Controller driver.
+ * LeapRAID storage and RAID controller driver.
*/
-
#include <linux/module.h>
#include "leapraid_func.h"
@@ -22,11 +21,12 @@ MODULE_PARM_DESC(smart_poll,
static int interrupt_mode;
module_param(interrupt_mode, int, 0444);
MODULE_PARM_DESC(interrupt_mode,
- "intr mode: 0 for MSI-X, 1 for MSI, 2 for legacy. (default=0)");
+ "intr mode: 0 is MSI-X, 1 is MSI, 2 is legacy. (default=0)");
+
-static int max_msix_vectors = -1;
+static int max_msix_vectors = LEAPRAID_INVALID_MSIX_VECTORS;
module_param(max_msix_vectors, int, 0444);
-MODULE_PARM_DESC(max_msix_vectors, " max msix vectors");
+MODULE_PARM_DESC(max_msix_vectors, "max msix vectors");
static void leapraid_remove_device(struct leapraid_adapter *adapter,
struct leapraid_sas_dev *sas_dev);
@@ -35,11 +35,48 @@ static void leapraid_set_led(struct leapraid_adapter *adapter,
static void leapraid_ublk_io_dev(struct leapraid_adapter *adapter,
u64 sas_address,
struct leapraid_card_port *port);
+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 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)
+{
+ struct leapraid_reg_base __iomem *iomem_base = adapter->iomem_base;
+ u32 debug_log[LEAPRAID_DEBUGLOG_SZ_MAX];
+ bool changed = false;
+ int i;
+
+ 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]);
+}
static inline bool leapraid_is_end_dev(u32 dev_type)
{
return (dev_type & LEAPRAID_DEVTYP_END_DEV) &&
@@ -53,12 +90,14 @@ bool leapraid_pci_removed(struct leapraid_adapter *adapter)
struct pci_dev *pdev = adapter->pdev;
u32 vendor_id;
- if (pci_bus_read_config_dword(pdev->bus, pdev->devfn, PCI_VENDOR_ID,
+ if (pci_bus_read_config_dword(pdev->bus,
+ pdev->devfn,
+ PCI_VENDOR_ID,
&vendor_id))
return true;
- return ((vendor_id & LEAPRAID_PCI_VENDOR_ID_MASK) !=
- LEAPRAID_VENDOR_ID);
+ return (vendor_id & LEAPRAID_PCI_VENDOR_ID_MASK) !=
+ LEAPRAID_VENDOR_ID;
}
static bool leapraid_pci_active(struct leapraid_adapter *adapter)
@@ -78,14 +117,14 @@ void *leapraid_get_reply_vaddr(struct leapraid_adapter *adapter, u32 rep_paddr)
void *leapraid_get_task_desc(struct leapraid_adapter *adapter, u16 taskid)
{
- return (void *)(adapter->mem_desc.task_desc +
- (taskid * LEAPRAID_REQUEST_SIZE));
+ return adapter->mem_desc.task_desc +
+ taskid * LEAPRAID_REQUEST_SIZE;
}
void *leapraid_get_sense_buffer(struct leapraid_adapter *adapter, u16 taskid)
{
- return (void *)(adapter->mem_desc.sense_data +
- ((taskid - 1) * SCSI_SENSE_BUFFERSIZE));
+ return adapter->mem_desc.sense_data +
+ (taskid - 1) * SCSI_SENSE_BUFFERSIZE;
}
__le32 leapraid_get_sense_buffer_dma(struct leapraid_adapter *adapter,
@@ -99,7 +138,7 @@ void leapraid_mask_int(struct leapraid_adapter *adapter)
{
u32 reg;
- adapter->mask_int = true;
+ adapter->mask_int = 1;
reg = leapraid_readl(&adapter->iomem_base->host_int_mask);
reg |= LEAPRAID_TO_SYS_DB_MASK + LEAPRAID_REPLY_INT_MASK +
LEAPRAID_RESET_IRQ_MASK;
@@ -114,35 +153,59 @@ void leapraid_unmask_int(struct leapraid_adapter *adapter)
reg = leapraid_readl(&adapter->iomem_base->host_int_mask);
reg &= ~LEAPRAID_REPLY_INT_MASK;
writel(reg, &adapter->iomem_base->host_int_mask);
- adapter->mask_int = false;
+ adapter->mask_int = 0;
}
-static void leapraid_flush_io_and_panic(struct leapraid_adapter *adapter)
+static void leapraid_overheat_suspend(struct leapraid_adapter *adapter)
{
- adapter->access_ctrl.adapter_thermal_alert = true;
- leapraid_smart_polling_stop(adapter);
- leapraid_fw_log_stop(adapter);
- leapraid_mq_polling_pause(adapter);
- leapraid_clean_active_scsi_cmds(adapter);
+ struct workqueue_struct *wq;
+ struct Scsi_Host *shost;
+ struct pci_dev *pdev;
+
+ if (!adapter)
+ return;
+
+ pdev = adapter->pdev;
+ shost = pci_get_drvdata(pdev);
+
+ if (!shost) {
+ dev_warn(&pdev->dev,
+ "Overheat suspend failed, invalid host or adapter\n");
+ return;
+ }
+
+ wq = adapter->overheat_desc.fault_overheat_wq;
+ if (!wq)
+ return;
+
+ if (atomic_cmpxchg(&adapter->overheat_desc.thermal_alert, 0, 1))
+ return;
+
+ queue_work(wq, &adapter->overheat_desc.fault_overheat_work);
}
-static void leapraid_check_panic_needed(struct leapraid_adapter *adapter,
- u32 db, u32 adapter_state)
+static void leapraid_stop_adapter_on_fault(struct leapraid_adapter *adapter,
+ u32 db)
{
- bool fault_1 = adapter_state == LEAPRAID_DB_MASK;
- bool fault_2 = (adapter_state == LEAPRAID_DB_FAULT) &&
- ((db & LEAPRAID_DB_DATA_MASK) == LEAPRAID_DB_OVER_TEMPERATURE);
+ u32 adapter_state = db & LEAPRAID_DB_MASK;
+ bool fault_1 = false;
+ bool fault_2 = false;
+
+ fault_1 = adapter_state == LEAPRAID_DB_MASK;
+ fault_2 = adapter_state == LEAPRAID_DB_FAULT &&
+ (db & LEAPRAID_DB_DATA_MASK) == LEAPRAID_DB_OVER_TEMPERATURE;
if (!fault_1 && !fault_2)
return;
if (fault_1)
- pr_err("%s, doorbell status 0xFFFF!\n", __func__);
+ dev_err(&adapter->pdev->dev,
+ "%s: Doorbell status 0xFFFF!\n", __func__);
else
- pr_err("%s, adapter overheating detected!\n", __func__);
+ dev_err(&adapter->pdev->dev,
+ "%s: Adapter overheating detected!\n", __func__);
- leapraid_flush_io_and_panic(adapter);
- panic("%s overheating detected, panic now!!!\n", __func__);
+ leapraid_overheat_suspend(adapter);
}
u32 leapraid_get_adapter_state(struct leapraid_adapter *adapter)
@@ -152,38 +215,40 @@ u32 leapraid_get_adapter_state(struct leapraid_adapter *adapter)
db = leapraid_readl(&adapter->iomem_base->db);
adapter_state = db & LEAPRAID_DB_MASK;
- leapraid_check_panic_needed(adapter, db, adapter_state);
+ leapraid_stop_adapter_on_fault(adapter, db);
return adapter_state;
}
static bool leapraid_wait_adapter_ready(struct leapraid_adapter *adapter)
{
u32 cur_state;
- u32 cnt = LEAPRAID_ADAPTER_READY_MAX_RETRY;
+ u32 cnt;
- do {
+ for (cnt = LEAPRAID_ADAPTER_READY_MAX_RETRY; cnt > 0; cnt--) {
cur_state = leapraid_get_adapter_state(adapter);
+
if (cur_state == LEAPRAID_DB_READY)
return true;
if (cur_state == LEAPRAID_DB_FAULT)
break;
usleep_range(LEAPRAID_ADAPTER_READY_SLEEP_MIN_US,
LEAPRAID_ADAPTER_READY_SLEEP_MAX_US);
- } while (--cnt);
+ }
return false;
}
static int leapraid_db_wait_int_host(struct leapraid_adapter *adapter)
{
- u32 cnt = LEAPRAID_DB_WAIT_MAX_RETRY;
+ u32 cnt;
- do {
+ for (cnt = LEAPRAID_DB_WAIT_MAX_RETRY; cnt > 0; cnt--) {
if (leapraid_readl(&adapter->iomem_base->host_int_status) &
LEAPRAID_ADAPTER2HOST_DB_STATUS)
return 0;
+
udelay(LEAPRAID_DB_WAIT_DELAY_US);
- } while (--cnt);
+ }
return -EFAULT;
}
@@ -194,25 +259,26 @@ static int leapraid_db_wait_ack_and_clear_int(struct leapraid_adapter *adapter)
u32 int_status;
u32 cnt;
- cnt = LEAPRAID_ADAPTER_READY_MAX_RETRY;
- do {
+ for (cnt = LEAPRAID_ADAPTER_READY_MAX_RETRY; cnt > 0; cnt--) {
int_status =
leapraid_readl(&adapter->iomem_base->host_int_status);
- if (!(int_status & LEAPRAID_HOST2ADAPTER_DB_STATUS)) {
+
+ if (int_status == 0xFFFFFFFF)
+ return -EFAULT;
+
+ if (!(int_status & LEAPRAID_HOST2ADAPTER_DB_STATUS))
return 0;
- } else if (int_status & LEAPRAID_ADAPTER2HOST_DB_STATUS) {
+
+ if (int_status & LEAPRAID_ADAPTER2HOST_DB_STATUS) {
adapter_state = leapraid_get_adapter_state(adapter);
if (adapter_state == LEAPRAID_DB_FAULT)
return -EFAULT;
- } else if (int_status == 0xFFFFFFFF) {
- goto out;
}
usleep_range(LEAPRAID_ADAPTER_READY_SLEEP_MIN_US,
LEAPRAID_ADAPTER_READY_SLEEP_MAX_US);
- } while (--cnt);
+ }
-out:
return -EFAULT;
}
@@ -222,8 +288,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
{
int failed, i;
- if ((leapraid_readl(&adapter->iomem_base->db) &
- LEAPRAID_DB_USED)) {
+ if (leapraid_readl(&adapter->iomem_base->db) & LEAPRAID_DB_USED) {
dev_err(&adapter->pdev->dev, "doorbell used\n");
return -EFAULT;
}
@@ -238,7 +303,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
&adapter->iomem_base->db);
if (leapraid_db_wait_int_host(adapter)) {
- dev_err(&adapter->pdev->dev, "%d:wait db interrupt timeout\n",
+ dev_err(&adapter->pdev->dev, "%d: Wait db interrupt timeout\n",
__LINE__);
return -EFAULT;
}
@@ -246,7 +311,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
writel(0, &adapter->iomem_base->host_int_status);
if (leapraid_db_wait_ack_and_clear_int(adapter)) {
- dev_err(&adapter->pdev->dev, "%d:wait ack failure\n",
+ dev_err(&adapter->pdev->dev, "%d: Wait ack failure\n",
__LINE__);
return -EFAULT;
}
@@ -254,12 +319,12 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
for (i = 0, failed = 0;
i < req_bytes / LEAPRAID_DWORDS_BYTE_SIZE && !failed;
i++) {
- writel((u32)(req[i]), &adapter->iomem_base->db);
+ writel((u32)req[i], &adapter->iomem_base->db);
if (leapraid_db_wait_ack_and_clear_int(adapter))
failed = 1;
}
if (failed) {
- dev_err(&adapter->pdev->dev, "%d:wait ack failure\n",
+ dev_err(&adapter->pdev->dev, "%d: Wait ack failure\n",
__LINE__);
return -EFAULT;
}
@@ -267,7 +332,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
for (i = 0; i < rep_bytes / LEAPRAID_WORD_BYTE_SIZE; i++) {
if (leapraid_db_wait_int_host(adapter)) {
dev_err(&adapter->pdev->dev,
- "%d:wait db interrupt timeout\n", __LINE__);
+ "%d: Wait db interrupt timeout\n", __LINE__);
return -EFAULT;
}
rep[i] = (u16)(leapraid_readl(&adapter->iomem_base->db)
@@ -276,7 +341,7 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
}
if (leapraid_db_wait_int_host(adapter)) {
- dev_err(&adapter->pdev->dev, "%d:wait db interrupt timeout\n",
+ dev_err(&adapter->pdev->dev, "%d: Wait db interrupt timeout\n",
__LINE__);
return -EFAULT;
}
@@ -286,28 +351,32 @@ static int leapraid_handshake_func(struct leapraid_adapter *adapter,
return 0;
}
-int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter)
+int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter, int wait,
+ const char *caller)
{
- int wait_count = LEAPRAID_DB_WAIT_OPERATIONAL;
+ int wait_count;
- do {
- if (leapraid_pci_removed(adapter))
+ for (wait_count = wait; wait_count > 0; wait_count--) {
+ if (leapraid_pci_removed(adapter)) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: PCI device removed\n", __func__);
return -EFAULT;
+ }
if (leapraid_get_adapter_state(adapter) ==
LEAPRAID_DB_OPERATIONAL)
return 0;
- dev_info(&adapter->pdev->dev,
- "waiting for adapter to become op status(cnt=%d)\n",
- LEAPRAID_DB_WAIT_OPERATIONAL - wait_count);
+ dev_dbg(&adapter->pdev->dev,
+ "%s: Wait for adapter to become op status(cnt=%d)\n",
+ caller, wait - wait_count);
ssleep(1);
- } while (--wait_count);
+ }
dev_err(&adapter->pdev->dev,
- "adapter failed to become op state, last state=%d\n",
- leapraid_get_adapter_state(adapter));
+ "%s: Adapter failed to become op state, last state=%d\n",
+ caller, leapraid_get_adapter_state(adapter));
return -EFAULT;
}
@@ -325,7 +394,7 @@ struct leapraid_io_req_tracker *leapraid_get_io_tracker_from_taskid(
scmd = leapraid_get_scmd_from_taskid(adapter, taskid);
if (scmd)
- return leapraid_get_scmd_priv(scmd);
+ return (struct leapraid_io_req_tracker *)scmd->host_scribble;
return NULL;
}
@@ -350,7 +419,8 @@ static u8 leapraid_get_cb_idx(struct leapraid_adapter *adapter, u16 taskid)
}
struct scsi_cmnd *leapraid_get_scmd_from_taskid(
- struct leapraid_adapter *adapter, u16 taskid)
+ struct leapraid_adapter *adapter,
+ u16 taskid)
{
struct leapraid_scsiio_req *leap_mpi_req;
struct leapraid_io_req_tracker *st;
@@ -367,7 +437,7 @@ struct scsi_cmnd *leapraid_get_scmd_from_taskid(
scmd = scsi_host_find_tag(adapter->shost, uniq_tag);
if (scmd) {
- st = leapraid_get_scmd_priv(scmd);
+ st = (struct leapraid_io_req_tracker *)scmd->host_scribble;
if (st && st->taskid == taskid)
return scmd;
}
@@ -383,8 +453,8 @@ u16 leapraid_alloc_scsiio_taskid(struct leapraid_adapter *adapter,
u32 tag = scmd->request->tag;
scmd->host_scribble =
- (unsigned char *)(&adapter->mem_desc.io_tracker[tag]);
- request = leapraid_get_scmd_priv(scmd);
+ (unsigned char *)&adapter->mem_desc.io_tracker[tag];
+ request = (struct leapraid_io_req_tracker *)scmd->host_scribble;
taskid = tag + 1;
request->taskid = taskid;
request->scmd = scmd;
@@ -401,8 +471,9 @@ static void leapraid_check_pending_io(struct leapraid_adapter *adapter)
}
}
-static void leapraid_clear_io_tracker(struct leapraid_adapter *adapter,
- struct leapraid_io_req_tracker *io_tracker)
+static void leapraid_clear_io_tracker(
+ struct leapraid_adapter *adapter,
+ struct leapraid_io_req_tracker *io_tracker)
{
if (!io_tracker)
return;
@@ -416,17 +487,18 @@ static void leapraid_clear_io_tracker(struct leapraid_adapter *adapter,
static bool leapraid_is_fixed_taskid(struct leapraid_adapter *adapter,
u16 taskid)
{
- return (taskid == adapter->driver_cmds.ctl_cmd.taskid ||
- taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid ||
- taskid == adapter->driver_cmds.tm_cmd.hp_taskid ||
- taskid == adapter->driver_cmds.ctl_cmd.hp_taskid ||
- taskid == adapter->driver_cmds.scan_dev_cmd.inter_taskid ||
- taskid == adapter->driver_cmds.timestamp_sync_cmd.inter_taskid ||
- taskid == adapter->driver_cmds.raid_action_cmd.inter_taskid ||
- taskid == adapter->driver_cmds.transport_cmd.inter_taskid ||
- taskid == adapter->driver_cmds.cfg_op_cmd.inter_taskid ||
- taskid == adapter->driver_cmds.enc_cmd.inter_taskid ||
- taskid == adapter->driver_cmds.notify_event_cmd.inter_taskid);
+ 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 ||
+ taskid == driver_cmds->notify_event_cmd.inter_taskid);
}
void leapraid_free_taskid(struct leapraid_adapter *adapter, u16 taskid)
@@ -516,6 +588,7 @@ void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter)
{
struct leapraid_io_req_tracker *io_tracker;
struct scsi_cmnd *scmd;
+ void *task_desc;
u16 taskid;
for (taskid = 1; taskid <= adapter->shost->can_queue; taskid++) {
@@ -523,15 +596,17 @@ void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter)
if (!scmd)
continue;
- io_tracker = leapraid_get_scmd_priv(scmd);
+ io_tracker = (struct leapraid_io_req_tracker *)scmd->host_scribble;
if (io_tracker && io_tracker->taskid == 0)
continue;
scsi_dma_unmap(scmd);
+ task_desc = leapraid_get_task_desc(adapter, taskid);
+ memset(task_desc, 0, LEAPRAID_REQUEST_SIZE);
leapraid_clear_io_tracker(adapter, io_tracker);
if (!leapraid_pci_active(adapter) ||
adapter->reset_desc.adapter_reset_results != 0 ||
- adapter->access_ctrl.adapter_thermal_alert ||
+ atomic_read(&adapter->overheat_desc.thermal_alert) ||
adapter->access_ctrl.host_removing)
scmd->result = DID_NO_CONNECT << 16;
else
@@ -540,36 +615,37 @@ void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter)
}
}
-static void leapraid_clean_active_driver_cmd(
- struct leapraid_driver_cmd *driver_cmd)
+static void leapraid_clean_active_driver_cmd(struct leapraid_driver_cmd *cmd)
{
- if (driver_cmd->status & LEAPRAID_CMD_PENDING) {
- driver_cmd->status |= LEAPRAID_CMD_RESET;
- complete(&driver_cmd->done);
+ if (cmd->status & LEAPRAID_CMD_PENDING) {
+ cmd->status |= LEAPRAID_CMD_RESET;
+ complete(&cmd->done);
}
}
static void leapraid_clean_active_driver_cmds(struct leapraid_adapter *adapter)
{
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.timestamp_sync_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.raid_action_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.driver_scsiio_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.tm_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.transport_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.enc_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.notify_event_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.cfg_op_cmd);
- leapraid_clean_active_driver_cmd(&adapter->driver_cmds.ctl_cmd);
-
- if (adapter->driver_cmds.scan_dev_cmd.status & LEAPRAID_CMD_PENDING) {
- adapter->scan_dev_desc.scan_dev_failed = true;
- adapter->driver_cmds.scan_dev_cmd.status |= LEAPRAID_CMD_RESET;
+ 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);
+ leapraid_clean_active_driver_cmd(&driver_cmds->notify_event_cmd);
+ leapraid_clean_active_driver_cmd(&driver_cmds->cfg_op_cmd);
+ leapraid_clean_active_driver_cmd(&driver_cmds->ctl_cmd);
+
+ if (driver_cmds->scan_dev_cmd.status & LEAPRAID_CMD_PENDING) {
+ adapter->scan_dev_desc.scan_dev_failed = 1;
+ driver_cmds->scan_dev_cmd.status |= LEAPRAID_CMD_RESET;
if (adapter->scan_dev_desc.driver_loading) {
adapter->scan_dev_desc.scan_start_failed =
LEAPRAID_ADAPTER_STATUS_INTERNAL_ERROR;
- adapter->scan_dev_desc.scan_start = false;
+ adapter->scan_dev_desc.scan_start = 0;
} else {
- complete(&adapter->driver_cmds.scan_dev_cmd.done);
+ complete(&driver_cmds->scan_dev_cmd.done);
}
}
}
@@ -577,10 +653,6 @@ static void leapraid_clean_active_driver_cmds(struct leapraid_adapter *adapter)
static void leapraid_clean_active_cmds(struct leapraid_adapter *adapter)
{
leapraid_clean_active_driver_cmds(adapter);
- memset(adapter->dev_topo.pending_dev_add, 0,
- adapter->dev_topo.pending_dev_add_sz);
- memset(adapter->dev_topo.dev_removing, 0,
- adapter->dev_topo.dev_removing_sz);
leapraid_clean_active_fw_evt(adapter);
leapraid_clean_active_scsi_cmds(adapter);
}
@@ -589,9 +661,9 @@ static void leapraid_tgt_not_responding(struct leapraid_adapter *adapter,
u16 hdl)
{
struct leapraid_starget_priv *starget_priv = NULL;
- struct leapraid_sas_dev *sas_dev = NULL;
+ struct leapraid_sas_dev *sas_dev;
unsigned long flags = 0;
- u32 adapter_state = 0;
+ u32 adapter_state;
if (adapter->access_ctrl.pcie_recovering)
return;
@@ -600,15 +672,15 @@ static void leapraid_tgt_not_responding(struct leapraid_adapter *adapter,
if (adapter_state != LEAPRAID_DB_OPERATIONAL)
return;
- if (test_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls))
+ if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle ||
+ test_bit(hdl, adapter->dev_topo.pd_hdls))
return;
- clear_bit(hdl, (unsigned long *)adapter->dev_topo.pending_dev_add);
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl);
if (sas_dev && sas_dev->starget && sas_dev->starget->hostdata) {
starget_priv = sas_dev->starget->hostdata;
- starget_priv->deleted = true;
+ starget_priv->deleted = 1;
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -622,9 +694,9 @@ static void leapraid_tgt_not_responding(struct leapraid_adapter *adapter,
static void leapraid_tgt_rst_send(struct leapraid_adapter *adapter, u16 hdl)
{
struct leapraid_starget_priv *starget_priv = NULL;
- struct leapraid_sas_dev *sas_dev = NULL;
- struct leapraid_card_port *port = NULL;
- u64 sas_address = 0;
+ struct leapraid_sas_dev *sas_dev;
+ struct leapraid_card_port *port;
+ u64 sas_address;
unsigned long flags;
u32 adapter_state;
@@ -635,15 +707,15 @@ static void leapraid_tgt_rst_send(struct leapraid_adapter *adapter, u16 hdl)
if (adapter_state != LEAPRAID_DB_OPERATIONAL)
return;
- if (test_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls))
+ if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle ||
+ test_bit(hdl, adapter->dev_topo.pd_hdls))
return;
- clear_bit(hdl, (unsigned long *)adapter->dev_topo.pending_dev_add);
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl);
if (sas_dev && sas_dev->starget && sas_dev->starget->hostdata) {
starget_priv = sas_dev->starget->hostdata;
- starget_priv->deleted = true;
+ starget_priv->deleted = 1;
sas_address = sas_dev->sas_addr;
port = sas_dev->card_port;
}
@@ -657,26 +729,30 @@ static void leapraid_tgt_rst_send(struct leapraid_adapter *adapter, u16 hdl)
leapraid_sdev_put(sas_dev);
}
-static inline void leapraid_single_mpi_sg_append(struct leapraid_adapter *adapter,
- void *sge, u32 flag_and_len,
- dma_addr_t dma_addr)
+static inline void leapraid_single_mpi_sg_append(
+ struct leapraid_adapter *adapter,
+ void *sge,
+ u32 flag_and_len,
+ dma_addr_t dma_addr)
{
if (adapter->adapter_attr.use_32_dma_mask) {
- ((struct leapraid_sge_simple32 *)sge)->flg_and_len =
+ struct leapraid_sge_simple32 *sge32 = sge;
+
+ sge32->flg_and_len =
cpu_to_le32(flag_and_len |
(LEAPRAID_SGE_FLG_32 |
LEAPRAID_SGE_FLG_SYSTEM_ADDR) <<
LEAPRAID_SGE_FLG_SHIFT);
- ((struct leapraid_sge_simple32 *)sge)->addr =
- cpu_to_le32(dma_addr);
+ sge32->addr = cpu_to_le32(dma_addr);
} else {
- ((struct leapraid_sge_simple64 *)sge)->flg_and_len =
+ struct leapraid_sge_simple64 *sge64 = sge;
+
+ sge64->flg_and_len =
cpu_to_le32(flag_and_len |
(LEAPRAID_SGE_FLG_64 |
LEAPRAID_SGE_FLG_SYSTEM_ADDR) <<
LEAPRAID_SGE_FLG_SHIFT);
- ((struct leapraid_sge_simple64 *)sge)->addr =
- cpu_to_le64(dma_addr);
+ sge64->addr = cpu_to_le64(dma_addr);
}
}
@@ -685,11 +761,12 @@ static inline void leapraid_single_ieee_sg_append(void *sge, u8 flag,
u32 len,
dma_addr_t dma_addr)
{
- ((struct leapraid_chain64_ieee_sg *)sge)->flg = flag;
- ((struct leapraid_chain64_ieee_sg *)sge)->next_chain_offset =
- next_chain_offset;
- ((struct leapraid_chain64_ieee_sg *)sge)->len = cpu_to_le32(len);
- ((struct leapraid_chain64_ieee_sg *)sge)->addr = cpu_to_le64(dma_addr);
+ struct leapraid_chain64_ieee_sg *ieee_sg = sge;
+
+ ieee_sg->flg = flag;
+ ieee_sg->next_chain_offset = next_chain_offset;
+ ieee_sg->len = cpu_to_le32(len);
+ ieee_sg->addr = cpu_to_le64(dma_addr);
}
static void leapraid_build_nodata_mpi_sg(struct leapraid_adapter *adapter,
@@ -697,12 +774,12 @@ static void leapraid_build_nodata_mpi_sg(struct leapraid_adapter *adapter,
{
leapraid_single_mpi_sg_append(adapter,
sge,
- (u32)((LEAPRAID_SGE_FLG_LAST_ONE |
- LEAPRAID_SGE_FLG_EOB |
- LEAPRAID_SGE_FLG_EOL |
- LEAPRAID_SGE_FLG_SIMPLE_ONE) <<
- LEAPRAID_SGE_FLG_SHIFT),
- -1);
+ (LEAPRAID_SGE_FLG_LAST_ONE |
+ LEAPRAID_SGE_FLG_EOB |
+ LEAPRAID_SGE_FLG_EOL |
+ LEAPRAID_SGE_FLG_SIMPLE_ONE) <<
+ LEAPRAID_SGE_FLG_SHIFT,
+ LEAPRAID_SGE_NO_DATA_ADDR);
}
void leapraid_build_mpi_sg(struct leapraid_adapter *adapter, void *sge,
@@ -753,7 +830,7 @@ void leapraid_build_mpi_sg(struct leapraid_adapter *adapter, void *sge,
c2h_size,
c2h_dma_addr);
} else {
- return leapraid_build_nodata_mpi_sg(adapter, sge);
+ leapraid_build_nodata_mpi_sg(adapter, sge);
}
}
@@ -763,7 +840,9 @@ void leapraid_build_ieee_nodata_sg(struct leapraid_adapter *adapter, void *sge)
(LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR |
LEAPRAID_IEEE_SGE_FLG_EOL),
- 0, 0, -1);
+ 0,
+ 0,
+ LEAPRAID_SGE_NO_DATA_ADDR);
}
int leapraid_build_scmd_ieee_sg(struct leapraid_adapter *adapter,
@@ -781,7 +860,7 @@ int leapraid_build_scmd_ieee_sg(struct leapraid_adapter *adapter,
u32 chain_offset_in_cur_seg;
u32 chain_len_in_cur_seg;
- io_tracker = leapraid_get_scmd_priv(scmd);
+ io_tracker = (struct leapraid_io_req_tracker *)scmd->host_scribble;
scsiio_req = leapraid_get_task_desc(adapter, taskid);
scmd_sg_cur = scsi_sglist(scmd);
sg_entries_left = scsi_dma_map(scmd);
@@ -819,7 +898,8 @@ int leapraid_build_scmd_ieee_sg(struct leapraid_adapter *adapter,
if (chain_offset_in_cur_seg)
chain_len_in_cur_seg += LEAPRAID_IEEE_SGE64_ENTRY_SIZE;
- leapraid_single_ieee_sg_append(sg_entry_cur,
+ leapraid_single_ieee_sg_append(
+ sg_entry_cur,
LEAPRAID_IEEE_SGE_FLG_CHAIN_ONE |
LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR,
chain_offset_in_cur_seg, chain_len_in_cur_seg,
@@ -829,7 +909,8 @@ int leapraid_build_scmd_ieee_sg(struct leapraid_adapter *adapter,
goto fill_last_seg;
while (sg_entries_in_cur_seg) {
- leapraid_single_ieee_sg_append(sg_entry_cur,
+ leapraid_single_ieee_sg_append(
+ sg_entry_cur,
LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR,
0, sg_dma_len(scmd_sg_cur),
@@ -866,39 +947,44 @@ void leapraid_build_ieee_sg(struct leapraid_adapter *adapter, void *sge,
dma_addr_t h2c_dma_addr, size_t h2c_size,
dma_addr_t c2h_dma_addr, size_t c2h_size)
{
+ u32 base_flag;
+ u32 flag;
+
+ base_flag = LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
+ LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR;
+
if (h2c_size && !c2h_size) {
+ flag = base_flag | LEAPRAID_IEEE_SGE_FLG_EOL;
+
leapraid_single_ieee_sg_append(sge,
- LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
- LEAPRAID_IEEE_SGE_FLG_EOL |
- LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR,
+ flag,
0,
h2c_size,
h2c_dma_addr);
} else if (!h2c_size && c2h_size) {
+ flag = base_flag | LEAPRAID_IEEE_SGE_FLG_EOL;
+
leapraid_single_ieee_sg_append(sge,
- LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
- LEAPRAID_IEEE_SGE_FLG_EOL |
- LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR,
+ flag,
0,
c2h_size,
c2h_dma_addr);
} else if (h2c_size && c2h_size) {
leapraid_single_ieee_sg_append(sge,
- LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
- LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR,
+ base_flag,
0,
h2c_size,
h2c_dma_addr);
sge += LEAPRAID_IEEE_SGE64_ENTRY_SIZE;
+
+ flag = base_flag | LEAPRAID_IEEE_SGE_FLG_EOL;
leapraid_single_ieee_sg_append(sge,
- LEAPRAID_IEEE_SGE_FLG_SIMPLE_ONE |
- LEAPRAID_IEEE_SGE_FLG_SYSTEM_ADDR |
- LEAPRAID_IEEE_SGE_FLG_EOL,
+ flag,
0,
c2h_size,
c2h_dma_addr);
} else {
- return leapraid_build_ieee_nodata_sg(adapter, sge);
+ leapraid_build_ieee_nodata_sg(adapter, sge);
}
}
@@ -952,8 +1038,11 @@ static struct leapraid_card_port *leapraid_get_port_by_id(
if (unlikely(!adapter->adapter_attr.enable_mp)) {
port = kzalloc(sizeof(*port), GFP_ATOMIC);
- if (!port)
+ if (!port) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed to alloc port\n", __func__);
return NULL;
+ }
port->port_id = LEAPRAID_DISABLE_MP_PORT_ID;
list_add_tail(&port->list, &adapter->dev_topo.card_port_list);
@@ -980,7 +1069,8 @@ struct leapraid_vphy *leapraid_get_vphy_by_phy(struct leapraid_card_port *port,
}
struct leapraid_sas_dev *leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(
- struct leapraid_adapter *adapter, u64 sas_address,
+ struct leapraid_adapter *adapter,
+ u64 sas_address,
struct sas_rphy *rphy)
{
struct leapraid_sas_dev *sas_dev;
@@ -1010,8 +1100,10 @@ struct leapraid_sas_dev *leapraid_hold_lock_get_sas_dev_by_addr(
{
struct leapraid_sas_dev *sas_dev;
- if (!port)
+ if (!port) {
+ dev_warn(&adapter->pdev->dev, "%s: Invalid port\n", __func__);
return NULL;
+ }
assert_spin_locked(&adapter->dev_topo.sas_dev_lock);
list_for_each_entry(sas_dev, &adapter->dev_topo.sas_dev_list, list)
@@ -1039,8 +1131,10 @@ struct leapraid_sas_dev *leapraid_get_sas_dev_by_addr(
struct leapraid_sas_dev *sas_dev;
unsigned long flags;
- if (!port)
+ if (!port) {
+ dev_warn(&adapter->pdev->dev, "%s: Invalid port\n", __func__);
return NULL;
+ }
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter, sas_address,
@@ -1089,8 +1183,11 @@ void leapraid_sas_dev_remove(struct leapraid_adapter *adapter,
unsigned long flags;
bool del_from_list;
- if (!sas_dev)
+ if (!sas_dev) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid SAS device\n", __func__);
return;
+ }
del_from_list = false;
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
@@ -1100,8 +1197,10 @@ void leapraid_sas_dev_remove(struct leapraid_adapter *adapter,
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
- if (del_from_list)
+ if (del_from_list) {
+ leapraid_clear_cached_boot_dev(adapter, sas_dev, 0);
leapraid_sdev_put(sas_dev);
+ }
}
static void leapraid_sas_dev_remove_by_hdl(struct leapraid_adapter *adapter,
@@ -1117,12 +1216,10 @@ static void leapraid_sas_dev_remove_by_hdl(struct leapraid_adapter *adapter,
del_from_list = false;
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl);
- if (sas_dev) {
- if (!list_empty(&sas_dev->list)) {
- list_del_init(&sas_dev->list);
- del_from_list = true;
- leapraid_sdev_put(sas_dev);
- }
+ if (sas_dev && (!list_empty(&sas_dev->list))) {
+ list_del_init(&sas_dev->list);
+ del_from_list = true;
+ leapraid_sdev_put(sas_dev);
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -1147,12 +1244,10 @@ void leapraid_sas_dev_remove_by_sas_address(struct leapraid_adapter *adapter,
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter, sas_address,
port);
- if (sas_dev) {
- if (!list_empty(&sas_dev->list)) {
- list_del_init(&sas_dev->list);
- del_from_list = true;
- leapraid_sdev_put(sas_dev);
- }
+ if (sas_dev && (!list_empty(&sas_dev->list))) {
+ list_del_init(&sas_dev->list);
+ del_from_list = true;
+ leapraid_sdev_put(sas_dev);
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -1166,14 +1261,19 @@ struct leapraid_raid_volume *leapraid_raid_volume_find_by_id(
struct leapraid_adapter *adapter, uint id, uint channel)
{
struct leapraid_raid_volume *raid_volume;
+ unsigned long flags;
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
list_for_each_entry(raid_volume, &adapter->dev_topo.raid_volume_list,
list) {
- if (raid_volume->id == id &&
- raid_volume->channel == channel) {
+ if (raid_volume->id == id && raid_volume->channel == channel) {
+ leapraid_raid_volume_get(raid_volume);
+ spin_unlock_irqrestore(
+ &adapter->dev_topo.raid_volume_lock, flags);
return raid_volume;
}
}
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
return NULL;
}
@@ -1182,12 +1282,19 @@ struct leapraid_raid_volume *leapraid_raid_volume_find_by_hdl(
struct leapraid_adapter *adapter, u16 hdl)
{
struct leapraid_raid_volume *raid_volume;
+ unsigned long flags;
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
list_for_each_entry(raid_volume, &adapter->dev_topo.raid_volume_list,
list) {
- if (raid_volume->hdl == hdl)
+ if (raid_volume->hdl == hdl) {
+ leapraid_raid_volume_get(raid_volume);
+ spin_unlock_irqrestore(
+ &adapter->dev_topo.raid_volume_lock, flags);
return raid_volume;
+ }
}
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
return NULL;
}
@@ -1196,12 +1303,19 @@ static struct leapraid_raid_volume *leapraid_raid_volume_find_by_wwid(
struct leapraid_adapter *adapter, u64 wwid)
{
struct leapraid_raid_volume *raid_volume;
+ unsigned long flags;
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
list_for_each_entry(raid_volume, &adapter->dev_topo.raid_volume_list,
list) {
- if (raid_volume->wwid == wwid)
+ if (raid_volume->wwid == wwid) {
+ leapraid_raid_volume_get(raid_volume);
+ spin_unlock_irqrestore(
+ &adapter->dev_topo.raid_volume_lock, flags);
return raid_volume;
+ }
}
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
return NULL;
}
@@ -1212,6 +1326,7 @@ static void leapraid_raid_volume_add(struct leapraid_adapter *adapter,
unsigned long flags;
spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ leapraid_raid_volume_get(raid_volume);
list_add_tail(&raid_volume->list, &adapter->dev_topo.raid_volume_list);
spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
}
@@ -1220,11 +1335,24 @@ void leapraid_raid_volume_remove(struct leapraid_adapter *adapter,
struct leapraid_raid_volume *raid_volume)
{
unsigned long flags;
+ bool del_from_list = false;
+
+ if (!raid_volume) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid RAID volume\n", __func__);
+ return;
+ }
spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
- list_del(&raid_volume->list);
- kfree(raid_volume);
+ if (!list_empty(&raid_volume->list)) {
+ list_del_init(&raid_volume->list);
+ del_from_list = true;
+ }
spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+
+ leapraid_clear_cached_boot_dev(adapter, raid_volume, RAID_CHANNEL);
+ if (del_from_list)
+ leapraid_raid_volume_put(raid_volume);
}
static struct leapraid_enc_node *leapraid_enc_find_by_hdl(
@@ -1232,10 +1360,9 @@ static struct leapraid_enc_node *leapraid_enc_find_by_hdl(
{
struct leapraid_enc_node *enc_dev;
- list_for_each_entry(enc_dev, &adapter->dev_topo.enc_list, list) {
+ list_for_each_entry(enc_dev, &adapter->dev_topo.enc_list, list)
if (le16_to_cpu(enc_dev->pg0.enc_hdl) == hdl)
return enc_dev;
- }
return NULL;
}
@@ -1246,15 +1373,19 @@ struct leapraid_topo_node *leapraid_exp_find_by_sas_address(
{
struct leapraid_topo_node *sas_exp;
- if (!port)
+ if (!port) {
+ dev_warn(&adapter->pdev->dev, "%s: Invalid port\n", __func__);
return NULL;
+ }
- list_for_each_entry(sas_exp, &adapter->dev_topo.exp_list, list) {
+ list_for_each_entry(sas_exp, &adapter->dev_topo.exp_list, list)
if (sas_exp->sas_address == sas_address &&
sas_exp->card_port == port)
return sas_exp;
- }
+ dev_warn(&adapter->pdev->dev,
+ "%s: No expander found for SAS addr=0x%016llx port=%p\n",
+ __func__, (unsigned long long)sas_address, port);
return NULL;
}
@@ -1301,10 +1432,9 @@ static struct leapraid_topo_node *leapraid_exp_find_by_hdl(
{
struct leapraid_topo_node *sas_exp;
- list_for_each_entry(sas_exp, &adapter->dev_topo.exp_list, list) {
+ list_for_each_entry(sas_exp, &adapter->dev_topo.exp_list, list)
if (sas_exp->hdl == hdl)
return sas_exp;
- }
return NULL;
}
@@ -1332,7 +1462,7 @@ static enum leapraid_card_port_checking_flg leapraid_get_card_port_feature(
return CARD_PORT_FURTHER_CHECKING_NEEDED;
}
-static int leapraid_process_card_port_feature(
+static bool leapraid_process_card_port_feature(
struct leapraid_card_port_feature *feature)
{
struct leapraid_card_port *old_card_port;
@@ -1341,8 +1471,10 @@ static int leapraid_process_card_port_feature(
if (feature->exact_phy) {
feature->checking_state = SAME_PORT_WITH_NOTHING_CHANGED;
feature->expected_old_port = old_card_port;
- return 1;
- } else if (feature->phy_overlap) {
+ return true;
+ }
+
+ if (feature->phy_overlap) {
if (feature->same_port) {
feature->checking_state =
SAME_PORT_WITH_PARTIALLY_CHANGED_PHYS;
@@ -1353,21 +1485,20 @@ static int leapraid_process_card_port_feature(
SAME_ADDR_WITH_PARTIALLY_CHANGED_PHYS;
feature->expected_old_port = old_card_port;
}
- } else {
- if (feature->checking_state !=
- SAME_PORT_WITH_PARTIALLY_CHANGED_PHYS &&
- feature->checking_state !=
- SAME_ADDR_WITH_PARTIALLY_CHANGED_PHYS) {
- feature->checking_state = SAME_ADDR_ONLY;
- feature->expected_old_port = old_card_port;
- feature->same_addr_port_count++;
- }
+ } else if (feature->checking_state !=
+ SAME_PORT_WITH_PARTIALLY_CHANGED_PHYS &&
+ feature->checking_state !=
+ SAME_ADDR_WITH_PARTIALLY_CHANGED_PHYS) {
+ feature->checking_state = SAME_ADDR_ONLY;
+ feature->expected_old_port = old_card_port;
+ feature->same_addr_port_count++;
}
- return 0;
+ return false;
}
-static int leapraid_check_card_port(struct leapraid_adapter *adapter,
+static int leapraid_check_card_port(
+ struct leapraid_adapter *adapter,
struct leapraid_card_port *card_port,
struct leapraid_card_port **expected_card_port,
int *count)
@@ -1413,7 +1544,8 @@ static void leapraid_del_phy_part_of_anther_port(
continue;
if (card_port_table[i].phy_mask & BIT(offset)) {
- leapraid_transport_detach_phy_to_port(adapter,
+ leapraid_transport_detach_phy_to_port(
+ adapter,
card_topo_node,
&card_topo_node->card_phy[offset]);
found = true;
@@ -1433,7 +1565,7 @@ static void leapraid_add_or_del_phys_from_existing_port(
{
struct leapraid_topo_node *card_topo_node;
u32 phy_mask_diff;
- u32 offset = 0;
+ u32 offset;
card_topo_node = &adapter->dev_topo.card;
phy_mask_diff = card_port->phy_mask ^
@@ -1451,12 +1583,15 @@ static void leapraid_add_or_del_phys_from_existing_port(
}
if (card_topo_node->card_phy[offset].phy_is_assigned)
- leapraid_transport_detach_phy_to_port(adapter,
+ leapraid_transport_detach_phy_to_port(
+ adapter,
card_topo_node,
&card_topo_node->card_phy[offset]);
- leapraid_transport_attach_phy_to_port(adapter,
- card_topo_node, &card_topo_node->card_phy[offset],
+ leapraid_transport_attach_phy_to_port(
+ adapter,
+ card_topo_node,
+ &card_topo_node->card_phy[offset],
card_port->sas_address,
card_port);
}
@@ -1471,7 +1606,8 @@ struct leapraid_sas_dev *leapraid_get_next_sas_dev_from_init_list(
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
if (!list_empty(&adapter->dev_topo.sas_dev_init_list)) {
sas_dev = list_first_entry(&adapter->dev_topo.sas_dev_init_list,
- struct leapraid_sas_dev, list);
+ struct leapraid_sas_dev,
+ list);
leapraid_sdev_get(sas_dev);
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -1483,37 +1619,66 @@ static bool leapraid_check_boot_dev_internal(u64 sas_address, u64 dev_name,
struct leapraid_boot_dev *boot_dev,
u8 form)
{
+ struct leapraid_boot_dev_format_sas_wwid *wwid;
+ struct leapraid_boot_dev_format_enc_slot *es;
+ struct leapraid_boot_dev_format_dev_name *dn;
+ void *pg_dev;
+
if (!boot_dev)
return false;
+ pg_dev = boot_dev->pg_dev;
switch (form & LEAPRAID_BOOTDEV_FORM_MASK) {
case LEAPRAID_BOOTDEV_FORM_SAS_WWID:
+ wwid = pg_dev;
+
if (!sas_address)
return false;
- return sas_address ==
- le64_to_cpu(((struct leapraid_boot_dev_format_sas_wwid *)(
- boot_dev->pg_dev))->sas_addr);
+ return sas_address == le64_to_cpu(wwid->sas_addr);
case LEAPRAID_BOOTDEV_FORM_ENC_SLOT:
+ es = pg_dev;
+
if (!enc_lid)
return false;
- return (enc_lid == le64_to_cpu(((struct leapraid_boot_dev_format_enc_slot *)(
- boot_dev->pg_dev))->enc_lid) &&
- slot == le16_to_cpu(((struct leapraid_boot_dev_format_enc_slot *)(
- boot_dev->pg_dev))->slot_num));
+ return (enc_lid == le64_to_cpu(es->enc_lid) &&
+ slot == le16_to_cpu(es->slot_num));
case LEAPRAID_BOOTDEV_FORM_DEV_NAME:
+ dn = pg_dev;
+
if (!dev_name)
return false;
- return dev_name == le64_to_cpu(((struct leapraid_boot_dev_format_dev_name *)(
- boot_dev->pg_dev))->dev_name);
+ return dev_name == le64_to_cpu(dn->dev_name);
case LEAPRAID_BOOTDEV_FORM_NONE:
default:
return false;
}
}
+void leapraid_boot_dev_get(void *dev, u32 chnl)
+{
+ if (!dev)
+ return;
+
+ if (chnl == RAID_CHANNEL)
+ leapraid_raid_volume_get((struct leapraid_raid_volume *)dev);
+ else
+ leapraid_sdev_get((struct leapraid_sas_dev *)dev);
+}
+
+void leapraid_boot_dev_put(void *dev, u32 chnl)
+{
+ if (!dev)
+ return;
+
+ if (chnl == RAID_CHANNEL)
+ leapraid_raid_volume_put((struct leapraid_raid_volume *)dev);
+ else
+ leapraid_sdev_put((struct leapraid_sas_dev *)dev);
+}
+
static void leapraid_try_set_boot_dev(struct leapraid_boot_dev *boot_dev,
u64 sas_addr, u64 dev_name,
u64 enc_lid, u16 slot,
@@ -1528,15 +1693,56 @@ static void leapraid_try_set_boot_dev(struct leapraid_boot_dev *boot_dev,
slot, boot_dev,
boot_dev->form);
if (matched) {
+ leapraid_boot_dev_get(dev, chnl);
boot_dev->dev = dev;
boot_dev->chnl = chnl;
}
}
+static void leapraid_clear_boot_dev(struct leapraid_adapter *adapter,
+ struct leapraid_boot_dev *boot_dev,
+ void *dev, u32 chnl)
+{
+ void *cached_dev;
+ u32 cached_chnl;
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->boot_devs.lock, flags);
+ if (boot_dev->dev != dev || boot_dev->chnl != chnl)
+ goto out_unlock;
+
+ cached_dev = boot_dev->dev;
+ cached_chnl = boot_dev->chnl;
+ boot_dev->dev = NULL;
+ boot_dev->chnl = 0;
+ spin_unlock_irqrestore(&adapter->boot_devs.lock, flags);
+ leapraid_boot_dev_put(cached_dev, cached_chnl);
+ return;
+
+out_unlock:
+ spin_unlock_irqrestore(&adapter->boot_devs.lock, flags);
+}
+
+static void leapraid_clear_cached_boot_dev(struct leapraid_adapter *adapter,
+ void *dev, u32 chnl)
+{
+ leapraid_clear_boot_dev(adapter,
+ &adapter->boot_devs.requested_boot_dev,
+ dev, chnl);
+ leapraid_clear_boot_dev(adapter,
+ &adapter->boot_devs.requested_alt_boot_dev,
+ dev, chnl);
+ leapraid_clear_boot_dev(adapter,
+ &adapter->boot_devs.current_boot_dev,
+ dev, chnl);
+}
+
static void leapraid_check_boot_dev(struct leapraid_adapter *adapter,
void *dev, u32 chnl)
{
- u64 sas_addr = 0;
+ struct leapraid_raid_volume *raid_volume;
+ struct leapraid_sas_dev *sas_dev;
+ u64 sas_addr;
u64 dev_name = 0;
u64 enc_lid = 0;
u16 slot = 0;
@@ -1546,24 +1752,17 @@ static void leapraid_check_boot_dev(struct leapraid_adapter *adapter,
switch (chnl) {
case RAID_CHANNEL:
- {
- struct leapraid_raid_volume *raid_volume =
- (struct leapraid_raid_volume *)dev;
-
+ raid_volume = dev;
sas_addr = raid_volume->wwid;
break;
- }
default:
- {
- struct leapraid_sas_dev *sas_dev =
- (struct leapraid_sas_dev *)dev;
+ sas_dev = dev;
sas_addr = sas_dev->sas_addr;
dev_name = sas_dev->dev_name;
enc_lid = sas_dev->enc_lid;
slot = sas_dev->slot;
break;
}
- }
leapraid_try_set_boot_dev(&adapter->boot_devs.requested_boot_dev,
sas_addr, dev_name, enc_lid,
@@ -1576,17 +1775,272 @@ static void leapraid_check_boot_dev(struct leapraid_adapter *adapter,
slot, dev, chnl);
}
-static void leapraid_build_and_fire_cfg_req(struct leapraid_adapter *adapter,
+static const char *leapraid_func_name(u8 func)
+{
+ switch (func) {
+ case LEAPRAID_FUNC_SCSIIO:
+ return "SCSIIO";
+ case LEAPRAID_FUNC_SCSI_TMF:
+ return "SCSI_TMF";
+ case LEAPRAID_FUNC_ADAPTER_INIT:
+ return "ADAPTER_INIT";
+ case LEAPRAID_FUNC_GET_ADAPTER_FEATURES:
+ return "GET_ADAPTER_FEATURES";
+ case LEAPRAID_FUNC_CONFIG_OP:
+ return "CONFIG_OP";
+ case LEAPRAID_FUNC_SCAN_DEV:
+ return "SCAN_DEV";
+ case LEAPRAID_FUNC_EVENT_NOTIFY:
+ return "EVENT_NOTIFY";
+ case LEAPRAID_FUNC_FW_DOWNLOAD:
+ return "FW_DOWNLOAD";
+ case LEAPRAID_FUNC_FW_UPLOAD:
+ return "FW_UPLOAD";
+ case LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH:
+ return "SCSIIO_RAID_PASSTHROUGH";
+ case LEAPRAID_FUNC_SCSI_ENC_PROCESSOR:
+ return "SCSI_ENC_PROCESSOR";
+ case LEAPRAID_FUNC_SMP_PASSTHROUGH:
+ return "SMP_PASSTHROUGH";
+ case LEAPRAID_FUNC_SAS_IO_UNIT_CTRL:
+ return "SAS_IO_UNIT_CTRL";
+ case LEAPRAID_FUNC_SCSIIO_SATA_PASSTHROUGH:
+ return "SCSIIO_SATA_PASSTHROUGH";
+ case LEAPRAID_FUNC_ADAPTER_UNIT_RESET:
+ return "ADAPTER_UNIT_RESET";
+ case LEAPRAID_FUNC_HANDSHAKE:
+ return "HANDSHAKE";
+ case LEAPRAID_FUNC_LOGBUF_INIT:
+ return "LOGBUF_INIT";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char *leapraid_cfg_action_name(u8 action)
+{
+ switch (action) {
+ case LEAPRAID_CFG_ACT_PAGE_HEADER:
+ return "PAGE_HEADER";
+ case LEAPRAID_CFG_ACT_PAGE_READ_CUR:
+ return "PAGE_READ_CUR";
+ case LEAPRAID_CFG_ACT_PAGE_WRITE_CUR:
+ return "PAGE_WRITE_CUR";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char *leapraid_cfg_page_type_name(u8 page_type)
+{
+ switch (page_type) {
+ case LEAPRAID_CFG_PT_IO_UNIT:
+ return "IO_UNIT";
+ case LEAPRAID_CFG_PT_ADAPTER:
+ return "ADAPTER";
+ case LEAPRAID_CFG_PT_BIOS:
+ return "BIOS";
+ case LEAPRAID_CFG_PT_RAID_VOLUME:
+ return "RAID_VOLUME";
+ case LEAPRAID_CFG_PT_MANUFACTURING:
+ return "MANUFACTURING";
+ case LEAPRAID_CFG_PT_RAID_PHYSDISK:
+ return "RAID_PHYSDISK";
+ case LEAPRAID_CFG_PT_EXTENDED:
+ return "EXTENDED";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char *leapraid_cfg_ext_page_type_name(u8 ext_page_type)
+{
+ switch (ext_page_type) {
+ case LEAPRAID_CFG_EXTPT_SAS_IO_UNIT:
+ return "SAS_IO_UNIT";
+ case LEAPRAID_CFG_EXTPT_SAS_EXP:
+ return "SAS_EXPANDER";
+ case LEAPRAID_CFG_EXTPT_SAS_DEV:
+ return "SAS_DEVICE";
+ case LEAPRAID_CFG_EXTPT_SAS_PHY:
+ return "SAS_PHY";
+ case LEAPRAID_CFG_EXTPT_ENC:
+ return "ENCLOSURE";
+ case LEAPRAID_CFG_EXTPT_RAID_CONFIG:
+ return "RAID_CONFIG";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char *leapraid_sep_action_name(u8 action)
+{
+ switch (action) {
+ case LEAPRAID_SEP_REQ_ACT_WRITE_STATUS:
+ return "WRITE_STATUS";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static const char *leapraid_sas_op_name(u8 op)
+{
+ switch (op) {
+ case LEAPRAID_SAS_OP_PHY_LINK_RESET:
+ return "PHY_LINK_RESET";
+ case LEAPRAID_SAS_OP_PHY_HARD_RESET:
+ return "PHY_HARD_RESET";
+ case LEAPRAID_SAS_OP_SET_PARAMETER:
+ return "SET_PARAMETER";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+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) {
+ case LEAPRAID_TM_TASKTYPE_ABORT_TASK:
+ return "ABORT_TASK";
+ case LEAPRAID_TM_TASKTYPE_ABRT_TASK_SET:
+ return "ABORT_TASK_SET";
+ case LEAPRAID_TM_TASKTYPE_TARGET_RESET:
+ return "TARGET_RESET";
+ case LEAPRAID_TM_TASKTYPE_LOGICAL_UNIT_RESET:
+ return "LOGICAL_UNIT_RESET";
+ case LEAPRAID_TM_TASKTYPE_CLEAR_TASK_SET:
+ return "CLEAR_TASK_SET";
+ case LEAPRAID_TM_TASKTYPE_QUERY_TASK:
+ return "QUERY_TASK";
+ case LEAPRAID_TM_TASKTYPE_CLEAR_ACA:
+ return "CLEAR_ACA";
+ case LEAPRAID_TM_TASKTYPE_QUERY_TASK_SET:
+ return "QUERY_TASK_SET";
+ case LEAPRAID_TM_TASKTYPE_QUERY_ASYNC_EVENT:
+ return "QUERY_ASYNC_EVENT";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+void leapraid_log_req_context(struct leapraid_adapter *adapter,
+ const void *req_data)
+{
+ const struct leapraid_req *req = req_data;
+
+ if (!adapter || !adapter->pdev || !req_data)
+ return;
+
+ switch (req->func) {
+ case LEAPRAID_FUNC_CONFIG_OP: {
+ 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->action,
+ leapraid_cfg_action_name(cfg_req->action));
+ dev_err(&adapter->pdev->dev,
+ "cfg-req: page_type=0x%02x(%s) page_num=%u\n",
+ cfg_req->header.page_type,
+ leapraid_cfg_page_type_name(cfg_req->header.page_type),
+ cfg_req->header.page_num);
+ if (cfg_req->header.page_type == LEAPRAID_CFG_PT_EXTENDED)
+ dev_err(&adapter->pdev->dev,
+ "cfg-req: ext_page_type=0x%02x(%s)\n",
+ cfg_req->ext_page_type,
+ leapraid_cfg_ext_page_type_name(
+ cfg_req->ext_page_type));
+ dev_err(&adapter->pdev->dev, "cfg-req: page_addr=0x%08x\n",
+ le32_to_cpu(cfg_req->page_addr));
+ break;
+ }
+ case LEAPRAID_FUNC_SCSI_TMF: {
+ 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),
+ 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",
+ le16_to_cpu(tm_req->dev_hdl),
+ le16_to_cpu(tm_req->task_mid));
+ break;
+ }
+ case LEAPRAID_FUNC_SCSI_ENC_PROCESSOR: {
+ 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_req->act,
+ leapraid_sep_action_name(sep_req->act));
+ dev_err(&adapter->pdev->dev,
+ "sep: dev_hdl=0x%04x slot=%u enc_hdl=0x%04x\n",
+ le16_to_cpu(sep_req->dev_hdl),
+ le16_to_cpu(sep_req->slot),
+ le16_to_cpu(sep_req->enc_hdl));
+ break;
+ }
+ case LEAPRAID_FUNC_SAS_IO_UNIT_CTRL: {
+ 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),
+ 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",
+ le16_to_cpu(io_req->dev_hdl),
+ io_req->adapter_para,
+ leapraid_io_param_name(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_req->physical_port,
+ le16_to_cpu(smp_req->req_data_len));
+ dev_err(&adapter->pdev->dev, "transport: 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));
+ break;
+ }
+}
+
+static void leapraid_build_and_fire_cfg_req(
+ struct leapraid_adapter *adapter,
struct leapraid_cfg_req *leap_mpi_cfgp_req,
struct leapraid_cfg_rep *leap_mpi_cfgp_rep)
{
struct leapraid_cfg_req *local_leap_cfg_req;
memset(leap_mpi_cfgp_rep, 0, sizeof(struct leapraid_cfg_rep));
- memset((void *)(&adapter->driver_cmds.cfg_op_cmd.reply), 0,
+ 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,
+ local_leap_cfg_req = leapraid_get_task_desc(
+ adapter,
adapter->driver_cmds.cfg_op_cmd.inter_taskid);
memcpy(local_leap_cfg_req, leap_mpi_cfgp_req,
sizeof(struct leapraid_cfg_req));
@@ -1614,17 +2068,18 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter,
if (retry_cnt) {
if (retry_cnt > LEAPRAID_CFG_REQ_RETRY_TIMES) {
rc = -EFAULT;
- goto out;
+ goto out_cleanup;
}
dev_warn(&adapter->pdev->dev,
- "cfg-req: retry request, cnt=%u\n", retry_cnt);
+ "cfg-req: Retry request, cnt=%u\n", retry_cnt);
}
- rc = leapraid_check_adapter_is_op(adapter);
+ rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
+ __func__);
if (rc) {
dev_err(&adapter->pdev->dev,
- "cfg-req: adapter not operational\n");
- goto out;
+ "cfg-req: Adapter not operational\n");
+ goto out_cleanup;
}
leapraid_build_and_fire_cfg_req(adapter, leap_mpi_cfgp_req,
@@ -1634,44 +2089,47 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter,
if (adapter->driver_cmds.cfg_op_cmd.status &
LEAPRAID_CMD_RESET) {
dev_warn(&adapter->pdev->dev,
- "cfg-req: cmd gg due to hard reset\n");
+ "cfg-req: CMD fail due to hard reset\n");
goto retry;
}
if (adapter->access_ctrl.shost_recovering ||
adapter->access_ctrl.pcie_recovering) {
dev_err(&adapter->pdev->dev,
- "cfg-req: cmd not done during %s, skip reset\n",
+ "cfg-req: pending in %s, status=0x%x\n",
adapter->access_ctrl.shost_recovering ?
- "shost recovery" : "pcie recovery");
+ "shost recovery" : "pcie recovery",
+ adapter->driver_cmds.cfg_op_cmd.status);
+ leapraid_log_req_context(adapter, leap_mpi_cfgp_req);
issue_reset = false;
rc = -EFAULT;
} else {
dev_err(&adapter->pdev->dev,
- "cfg-req: cmd timeout, issuing hard reset\n");
+ "cfg-req: timeout, status=0x%x, reset\n",
+ adapter->driver_cmds.cfg_op_cmd.status);
+ leapraid_log_req_context(adapter, leap_mpi_cfgp_req);
issue_reset = true;
}
- goto out;
+ goto out_cleanup;
}
if (adapter->driver_cmds.cfg_op_cmd.status &
LEAPRAID_CMD_REPLY_VALID) {
memcpy(leap_mpi_cfgp_rep,
- (void *)(&adapter->driver_cmds.cfg_op_cmd.reply),
+ &adapter->driver_cmds.cfg_op_cmd.reply,
sizeof(struct leapraid_cfg_rep));
adapter_status = le16_to_cpu(
leap_mpi_cfgp_rep->adapter_status) &
LEAPRAID_ADAPTER_STATUS_MASK;
- if (adapter_status == LEAPRAID_ADAPTER_STATUS_SUCCESS) {
- if (target_cfg_pg && real_cfg_pg_addr &&
- target_real_cfg_pg_sz)
- if (leap_mpi_cfgp_req->action ==
- LEAPRAID_CFG_ACT_PAGE_READ_CUR)
- memcpy(target_cfg_pg,
- real_cfg_pg_addr,
- target_real_cfg_pg_sz);
- } else {
+ if (adapter_status == LEAPRAID_ADAPTER_STATUS_SUCCESS &&
+ target_cfg_pg && real_cfg_pg_addr &&
+ target_real_cfg_pg_sz &&
+ leap_mpi_cfgp_req->action ==
+ LEAPRAID_CFG_ACT_PAGE_READ_CUR)
+ memcpy(target_cfg_pg, real_cfg_pg_addr,
+ target_real_cfg_pg_sz);
+ if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS) {
if (adapter_status !=
LEAPRAID_ADAPTER_STATUS_CONFIG_INVALID_PAGE)
dev_err(&adapter->pdev->dev,
@@ -1680,30 +2138,30 @@ static int leapraid_req_cfg_func(struct leapraid_adapter *adapter,
rc = -EFAULT;
}
} else {
- dev_err(&adapter->pdev->dev, "cfg-rep: reply invalid\n");
+ dev_err(&adapter->pdev->dev, "cfg-rep: Reply invalid\n");
rc = -EFAULT;
}
-out:
+out_cleanup:
adapter->driver_cmds.cfg_op_cmd.status = LEAPRAID_CMD_NOT_USED;
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,
- "%s:%d cfg-req: failure, issuing reset\n",
+ "%s:%d cfg-req: Failure, issuing reset\n",
__func__, __LINE__);
leapraid_hard_reset_handler(adapter, FULL_RESET);
- rc = -EFAULT;
} else {
dev_warn(&adapter->pdev->dev,
- "cfg-req: cmd gg during init, skip reset\n");
- rc = -EFAULT;
+ "cfg-req: CMD fail in init, skip reset\n");
}
+ rc = -EFAULT;
}
return rc;
}
-static int leapraid_request_cfg_pg_header(struct leapraid_adapter *adapter,
+static int leapraid_request_cfg_pg_header(
+ struct leapraid_adapter *adapter,
struct leapraid_cfg_req *leap_mpi_cfgp_req,
struct leapraid_cfg_rep *leap_mpi_cfgp_rep)
{
@@ -1729,8 +2187,8 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
{
struct leapraid_cfg_req leap_mpi_cfgp_req;
struct leapraid_cfg_rep leap_mpi_cfgp_rep;
- u16 real_cfg_pg_sz = 0;
- void *real_cfg_pg_addr = NULL;
+ u16 real_cfg_pg_sz;
+ void *real_cfg_pg_addr;
dma_addr_t real_cfg_pg_dma = 0;
u32 __page_size;
int rc;
@@ -1752,6 +2210,13 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
LEAPRAID_CFG_PAGE_NUM_BIOS2;
__page_size = sizeof(struct leapraid_bios_page2);
break;
+ case GET_MANUFACTURING_PG0:
+ leap_mpi_cfgp_req.header.page_type =
+ LEAPRAID_CFG_PT_MANUFACTURING;
+ leap_mpi_cfgp_req.header.page_num =
+ LEAPRAID_CFG_PAGE_NUM_MANU0;
+ __page_size = sizeof(struct leapraid_manufacturing_p0);
+ break;
case GET_SAS_DEVICE_PG0:
leap_mpi_cfgp_req.header.page_type = LEAPRAID_CFG_PT_EXTENDED;
leap_mpi_cfgp_req.ext_page_type = LEAPRAID_CFG_EXTPT_SAS_DEV;
@@ -1818,9 +2283,8 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
break;
default:
dev_err(&adapter->pdev->dev,
- "unsupported config page action=%d!\n", cfg_op);
- rc = -EINVAL;
- goto out;
+ "Unsupported config page action=%d!\n", cfg_op);
+ return -EINVAL;
}
leapraid_build_nodata_mpi_sg(adapter,
@@ -1830,8 +2294,8 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
&leap_mpi_cfgp_rep);
if (rc) {
dev_err(&adapter->pdev->dev,
- "cfg-req: header failed rc=%dn", rc);
- goto out;
+ "cfg-req: Header failed rc=%dn", rc);
+ return rc;
}
if (cfg_op == GET_SAS_DEVICE_PG0 ||
@@ -1867,17 +2331,14 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
leap_mpi_cfgp_req.ext_page_type = leap_mpi_cfgp_rep.ext_page_type;
real_cfg_pg_sz = (leap_mpi_cfgp_req.header.page_len) ?
- leap_mpi_cfgp_req.header.page_len * 4 :
- le16_to_cpu(leap_mpi_cfgp_rep.ext_page_len) * 4;
+ leap_mpi_cfgp_req.header.page_len * sizeof(u32) :
+ le16_to_cpu(leap_mpi_cfgp_rep.ext_page_len) * sizeof(u32);
real_cfg_pg_addr = dma_alloc_coherent(&adapter->pdev->dev,
real_cfg_pg_sz,
&real_cfg_pg_dma,
GFP_KERNEL);
- if (!real_cfg_pg_addr) {
- dev_err(&adapter->pdev->dev, "cfg-req: dma alloc failed\n");
- rc = -ENOMEM;
- goto out;
- }
+ if (!real_cfg_pg_addr)
+ return -ENOMEM;
if (leap_mpi_cfgp_req.action == LEAPRAID_CFG_ACT_PAGE_WRITE_CUR) {
leapraid_single_mpi_sg_append(adapter,
@@ -1914,12 +2375,11 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
real_cfg_pg_addr,
min_t(u16, real_cfg_pg_sz, __page_size));
if (rc) {
- u32 adapter_status;
+ u32 status;
- adapter_status = le16_to_cpu(leap_mpi_cfgp_rep.adapter_status) &
- LEAPRAID_ADAPTER_STATUS_MASK;
- if (adapter_status !=
- LEAPRAID_ADAPTER_STATUS_CONFIG_INVALID_PAGE)
+ status = le16_to_cpu(leap_mpi_cfgp_rep.adapter_status) &
+ LEAPRAID_ADAPTER_STATUS_MASK;
+ if (status != LEAPRAID_ADAPTER_STATUS_CONFIG_INVALID_PAGE)
dev_err(&adapter->pdev->dev,
"cfg-req: rc=%d, pg_info: 0x%x, 0x%x, %d\n",
rc, leap_mpi_cfgp_req.header.page_type,
@@ -1932,10 +2392,52 @@ int leapraid_op_config_page(struct leapraid_adapter *adapter,
real_cfg_pg_sz,
real_cfg_pg_addr,
real_cfg_pg_dma);
-out:
+
return rc;
}
+static int leapraid_cfg_find_vol_in_page(
+ struct leapraid_raid_cfg_p0 *raid_cfg_p0,
+ u16 pd_hdl, u16 *vol_hdl)
+{
+ u16 elements = raid_cfg_p0->elements_num;
+ int i;
+
+ for (i = 0; i < elements; i++) {
+ struct leapraid_raid_cfg_p0_element *elem;
+ u16 type;
+
+ elem = &raid_cfg_p0->cfg_element[i];
+
+ type = le16_to_cpu(elem->element_flg) &
+ LEAPRAID_RAIDCFG_P0_EFLG_MASK_ELEMENT_TYPE;
+
+ switch (type) {
+ case LEAPRAID_RAIDCFG_P0_EFLG_VOL_PHYS_DISK_ELEMENT:
+ case LEAPRAID_RAIDCFG_P0_EFLG_OCE_ELEMENT: {
+ 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;
+
+ default:
+ break;
+ }
+ }
+
+ return -ENOENT;
+}
+
static int leapraid_cfg_get_volume_hdl_dispatch(
struct leapraid_adapter *adapter,
struct leapraid_cfg_req *cfg_req,
@@ -1946,13 +2448,11 @@ static int leapraid_cfg_get_volume_hdl_dispatch(
u16 raid_cfg_p0_sz,
u16 pd_hdl, u16 *vol_hdl)
{
- u16 phys_disk_dev_hdl;
u16 adapter_status;
- u16 element_type;
int config_num;
- int rc, i;
+ int rc;
- config_num = 0xff;
+ config_num = 0xFF;
while (true) {
cfg_req->page_addr =
cpu_to_le32(config_num +
@@ -1973,35 +2473,14 @@ static int leapraid_cfg_get_volume_hdl_dispatch(
}
if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS)
- return -1;
-
- for (i = 0; i < raid_cfg_p0->elements_num; i++) {
- element_type =
- le16_to_cpu(raid_cfg_p0->cfg_element[i].element_flg) &
- LEAPRAID_RAIDCFG_P0_EFLG_MASK_ELEMENT_TYPE;
-
- switch (element_type) {
- case LEAPRAID_RAIDCFG_P0_EFLG_VOL_PHYS_DISK_ELEMENT:
- case LEAPRAID_RAIDCFG_P0_EFLG_OCE_ELEMENT:
- phys_disk_dev_hdl =
- le16_to_cpu(raid_cfg_p0->cfg_element[i]
- .phys_disk_dev_hdl);
- if (phys_disk_dev_hdl == pd_hdl) {
- *vol_hdl =
- le16_to_cpu
- (raid_cfg_p0->cfg_element[i]
- .vol_dev_hdl);
- return 0;
- }
- break;
+ return LEAPRAID_OPERATION_FAILED;
+
+ rc = leapraid_cfg_find_vol_in_page(raid_cfg_p0,
+ pd_hdl,
+ vol_hdl);
+ if (rc != -ENOENT)
+ return rc;
- case LEAPRAID_RAIDCFG_P0_EFLG_HOT_SPARE_ELEMENT:
- *vol_hdl = 0;
- return 0;
- default:
- break;
- }
- }
config_num = raid_cfg_p0->cfg_num;
}
return 0;
@@ -2010,12 +2489,12 @@ static int leapraid_cfg_get_volume_hdl_dispatch(
int leapraid_cfg_get_volume_hdl(struct leapraid_adapter *adapter,
u16 pd_hdl, u16 *vol_hdl)
{
- struct leapraid_raid_cfg_p0 *raid_cfg_p0 = NULL;
+ struct leapraid_raid_cfg_p0 *raid_cfg_p0;
struct leapraid_cfg_req cfg_req;
struct leapraid_cfg_rep cfg_rep;
dma_addr_t real_cfg_pg_dma = 0;
- void *real_cfg_pg_addr = NULL;
- u16 real_cfg_pg_sz = 0;
+ void *real_cfg_pg_addr;
+ u16 real_cfg_pg_sz;
int rc, raid_cfg_p0_sz;
*vol_hdl = 0;
@@ -2029,16 +2508,14 @@ int leapraid_cfg_get_volume_hdl(struct leapraid_adapter *adapter,
leapraid_build_nodata_mpi_sg(adapter, &cfg_req.page_buf_sge);
rc = leapraid_request_cfg_pg_header(adapter, &cfg_req, &cfg_rep);
if (rc)
- goto out;
+ return rc;
cfg_req.action = LEAPRAID_CFG_ACT_PAGE_READ_CUR;
raid_cfg_p0_sz = le16_to_cpu(cfg_rep.ext_page_len) *
LEAPRAID_CFG_UNIT_SIZE;
raid_cfg_p0 = kmalloc(raid_cfg_p0_sz, GFP_KERNEL);
- if (!raid_cfg_p0) {
- rc = -1;
- goto out;
- }
+ if (!raid_cfg_p0)
+ return -ENOMEM;
real_cfg_pg_sz = (cfg_req.header.page_len) ?
cfg_req.header.page_len * LEAPRAID_CFG_UNIT_SIZE :
@@ -2049,7 +2526,7 @@ int leapraid_cfg_get_volume_hdl(struct leapraid_adapter *adapter,
GFP_KERNEL);
if (!real_cfg_pg_addr) {
rc = -ENOMEM;
- goto out;
+ goto out_free;
}
memset(raid_cfg_p0, 0, raid_cfg_p0_sz);
@@ -2073,7 +2550,7 @@ int leapraid_cfg_get_volume_hdl(struct leapraid_adapter *adapter,
raid_cfg_p0_sz,
pd_hdl, vol_hdl);
-out:
+out_free:
if (real_cfg_pg_addr)
dma_free_coherent(&adapter->pdev->dev,
real_cfg_pg_sz, real_cfg_pg_addr,
@@ -2088,7 +2565,7 @@ static int leapraid_get_adapter_phys(struct leapraid_adapter *adapter,
struct leapraid_sas_io_unit_p0 sas_io_unit_page0;
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- int rc = 0;
+ int rc;
*nr_phys = 0;
cfgp1.size = sizeof(struct leapraid_sas_io_unit_p0);
@@ -2141,7 +2618,8 @@ int leapraid_cfg_get_volume_wwid(struct leapraid_adapter *adapter,
return rc;
}
-static int leapraid_get_sas_io_unit_page0(struct leapraid_adapter *adapter,
+static int leapraid_get_sas_io_unit_page0(
+ struct leapraid_adapter *adapter,
struct leapraid_sas_io_unit_p0 *sas_io_unit_p0,
u16 sas_iou_pg0_sz)
{
@@ -2163,8 +2641,8 @@ static int leapraid_get_sas_address(struct leapraid_adapter *adapter,
*sas_address = 0;
cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
cfgp2.handle = hdl;
- if ((leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1,
- cfgp2, GET_SAS_DEVICE_PG0)))
+ if (leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1,
+ cfgp2, GET_SAS_DEVICE_PG0))
return -ENXIO;
if (hdl <= adapter->dev_topo.card.phys_num &&
@@ -2186,9 +2664,10 @@ int leapraid_get_volume_cap(struct leapraid_adapter *adapter,
struct leapraid_raidpd_p0 raidpd_p0;
u8 num_pds;
u16 sz;
+ int rc = 0;
- if ((leapraid_cfg_get_number_pds(adapter, raid_volume->hdl,
- &num_pds)) || !num_pds)
+ if (leapraid_cfg_get_number_pds(adapter, raid_volume->hdl,
+ &num_pds) || !num_pds)
return -EFAULT;
raid_volume->pd_num = num_pds;
@@ -2196,14 +2675,14 @@ int leapraid_get_volume_cap(struct leapraid_adapter *adapter,
(num_pds * sizeof(struct leapraid_raidvol0_phys_disk));
raidvol_p0 = kzalloc(sz, GFP_KERNEL);
if (!raidvol_p0)
- return -EFAULT;
+ return -ENOMEM;
cfgp1.size = sz;
cfgp2.handle = raid_volume->hdl;
- if ((leapraid_op_config_page(adapter, raidvol_p0, cfgp1, cfgp2,
- GET_RAID_VOLUME_PG0))) {
- kfree(raidvol_p0);
- return -EFAULT;
+ if (leapraid_op_config_page(adapter, raidvol_p0, cfgp1, cfgp2,
+ GET_RAID_VOLUME_PG0)) {
+ rc = -EFAULT;
+ goto out_cleanup;
}
raid_volume->vol_type = raidvol_p0->volume_type;
@@ -2214,14 +2693,28 @@ int leapraid_get_volume_cap(struct leapraid_adapter *adapter,
cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
cfgp2.handle = le16_to_cpu(raidpd_p0.dev_hdl);
if (!(leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1,
- cfgp2, GET_SAS_DEVICE_PG0))) {
+ cfgp2, GET_SAS_DEVICE_PG0)))
raid_volume->dev_info =
le32_to_cpu(sas_dev_p0.dev_info);
- }
}
+out_cleanup:
kfree(raidvol_p0);
- return 0;
+ return rc;
+}
+
+static bool leapraid_should_skip_poll_work(struct leapraid_adapter *adapter)
+{
+ unsigned long flags;
+ bool skip;
+
+ spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
+ skip = adapter->access_ctrl.shost_recovering ||
+ adapter->access_ctrl.pcie_recovering ||
+ adapter->access_ctrl.host_removing;
+ spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
+
+ return skip;
}
static void leapraid_fw_log_work(struct work_struct *work)
@@ -2229,26 +2722,34 @@ static void leapraid_fw_log_work(struct work_struct *work)
struct leapraid_adapter *adapter = container_of(work,
struct leapraid_adapter, fw_log_desc.fw_log_work.work);
struct leapraid_fw_log_info *infom;
+ struct leapraid_reg_base __iomem *iomem_base;
unsigned long flags;
- infom = (struct leapraid_fw_log_info *)(adapter->fw_log_desc.fw_log_buffer +
- LEAPRAID_SYS_LOG_BUF_SIZE);
+ if (leapraid_should_skip_poll_work(adapter))
+ goto scheduled_timer;
+
+ infom = (struct leapraid_fw_log_info *)
+ (adapter->fw_log_desc.fw_log_buffer +
+ LEAPRAID_SYS_LOG_BUF_SIZE);
+ iomem_base = adapter->iomem_base;
if (adapter->fw_log_desc.fw_log_init_flag == 0) {
infom->user_position =
- leapraid_readl(&adapter->iomem_base->host_log_buf_pos);
+ leapraid_readl(&iomem_base->host_log_buf_pos);
infom->adapter_position =
- leapraid_readl(&adapter->iomem_base->adapter_log_buf_pos);
+ leapraid_readl(&iomem_base->adapter_log_buf_pos);
adapter->fw_log_desc.fw_log_init_flag++;
}
- writel(infom->user_position, &adapter->iomem_base->host_log_buf_pos);
+ writel(infom->user_position, &iomem_base->host_log_buf_pos);
infom->adapter_position =
- leapraid_readl(&adapter->iomem_base->adapter_log_buf_pos);
+ leapraid_readl(&iomem_base->adapter_log_buf_pos);
+scheduled_timer:
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
if (adapter->fw_log_desc.fw_log_wq)
- queue_delayed_work(adapter->fw_log_desc.fw_log_wq,
+ queue_delayed_work(
+ adapter->fw_log_desc.fw_log_wq,
&adapter->fw_log_desc.fw_log_work,
msecs_to_jiffies(LEAPRAID_PCIE_LOG_POLLING_INTERVAL));
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
@@ -2267,7 +2768,8 @@ void leapraid_fw_log_stop(struct leapraid_adapter *adapter)
adapter->fw_log_desc.fw_log_wq = NULL;
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
if (wq) {
- if (!cancel_delayed_work_sync(&adapter->fw_log_desc.fw_log_work))
+ if (!cancel_delayed_work_sync(&adapter->fw_log_desc
+ .fw_log_work))
flush_workqueue(wq);
destroy_workqueue(wq);
}
@@ -2297,7 +2799,8 @@ void leapraid_fw_log_start(struct leapraid_adapter *adapter)
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
if (adapter->fw_log_desc.fw_log_wq)
- queue_delayed_work(adapter->fw_log_desc.fw_log_wq,
+ queue_delayed_work(
+ adapter->fw_log_desc.fw_log_wq,
&adapter->fw_log_desc.fw_log_work,
msecs_to_jiffies(LEAPRAID_PCIE_LOG_POLLING_INTERVAL));
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
@@ -2308,12 +2811,13 @@ 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 = 0;
+ 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,
+ 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;
@@ -2328,18 +2832,27 @@ static void leapraid_timestamp_sync(struct leapraid_adapter *adapter)
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);
- wait_for_completion_timeout(&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))
+ 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",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
leapraid_hard_reset_handler(adapter, FULL_RESET);
}
@@ -2348,20 +2861,6 @@ static void leapraid_timestamp_sync(struct leapraid_adapter *adapter)
mutex_unlock(&adapter->driver_cmds.timestamp_sync_cmd.mutex);
}
-static bool leapraid_should_skip_fault_check(struct leapraid_adapter *adapter)
-{
- unsigned long flags;
- bool skip;
-
- spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
- skip = adapter->access_ctrl.shost_recovering ||
- adapter->access_ctrl.pcie_recovering ||
- adapter->access_ctrl.host_removing;
- spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
-
- return skip;
-}
-
static void leapraid_check_scheduled_fault_work(struct work_struct *work)
{
struct leapraid_adapter *adapter;
@@ -2372,16 +2871,16 @@ static void leapraid_check_scheduled_fault_work(struct work_struct *work)
adapter = container_of(work, struct leapraid_adapter,
reset_desc.fault_reset_work.work);
- if (leapraid_should_skip_fault_check(adapter))
+ if (leapraid_should_skip_poll_work(adapter))
goto scheduled_timer;
adapter_state = leapraid_get_adapter_state(adapter);
if (adapter_state != LEAPRAID_DB_OPERATIONAL) {
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
- dev_warn(&adapter->pdev->dev, "%s: hard reset: %s\n",
- __func__, (rc == 0) ? "success" : "failed");
+ 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)
@@ -2397,7 +2896,8 @@ static void leapraid_check_scheduled_fault_work(struct work_struct *work)
scheduled_timer:
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
if (adapter->reset_desc.fault_reset_wq)
- queue_delayed_work(adapter->reset_desc.fault_reset_wq,
+ queue_delayed_work(
+ adapter->reset_desc.fault_reset_wq,
&adapter->reset_desc.fault_reset_work,
msecs_to_jiffies(LEAPRAID_FAULT_POLLING_INTERVAL));
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
@@ -2422,14 +2922,15 @@ void leapraid_check_scheduled_fault_start(struct leapraid_adapter *adapter)
adapter->reset_desc.fault_reset_wq_name);
if (!adapter->reset_desc.fault_reset_wq) {
dev_err(&adapter->pdev->dev,
- "create single thread workqueue failed!\n");
+ "Create single thread workqueue failed!\n");
return;
}
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
if (adapter->reset_desc.fault_reset_wq)
- queue_delayed_work(adapter->reset_desc.fault_reset_wq,
- &adapter->reset_desc.fault_reset_work,
+ queue_delayed_work(
+ adapter->reset_desc.fault_reset_wq,
+ &adapter->reset_desc.fault_reset_work,
msecs_to_jiffies(LEAPRAID_FAULT_POLLING_INTERVAL));
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
}
@@ -2456,17 +2957,24 @@ static bool leapraid_ready_for_scsi_io(struct leapraid_adapter *adapter,
u16 hdl)
{
if (adapter->access_ctrl.pcie_recovering ||
- adapter->access_ctrl.shost_recovering)
- return false;
-
- if (leapraid_check_adapter_is_op(adapter))
+ 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 (hdl == LEAPRAID_INVALID_DEV_HANDLE)
+ if (leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
+ __func__))
return false;
- if (test_bit(hdl, (unsigned long *)adapter->dev_topo.dev_removing))
+ if (hdl == LEAPRAID_INVALID_DEV_HANDLE) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Device handle is invalid\n", __func__);
return false;
+ }
return true;
}
@@ -2475,13 +2983,13 @@ 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 = 0;
- u8 sdev_flg = 0;
+ dma_addr_t dma_addr;
bool issue_reset = false;
- int rc = 0;
+ int rc;
if (WARN_ON(!adapter->driver_cmds.internal_scmd))
return -EINVAL;
@@ -2492,23 +3000,28 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter,
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;
+ goto out_cleanup;
}
adapter->driver_cmds.driver_scsiio_cmd.status = LEAPRAID_CMD_PENDING;
- __shost_for_each_device(sdev, adapter->shost) {
+ 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) {
- sdev_flg = 1;
+ target_sdev = sdev;
break;
}
}
- if (!sdev_flg) {
+ if (!target_sdev) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Device not found\n", __func__);
rc = -ENXIO;
- goto out;
+ goto out_cleanup;
}
if (cmd_desc->data_length) {
@@ -2517,7 +3030,7 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter,
&dma_addr, GFP_ATOMIC);
if (!dma_buffer) {
rc = -ENOMEM;
- goto out;
+ goto out_cleanup;
}
if (cmd_desc->dir == DMA_TO_DEVICE)
memcpy(dma_buffer, cmd_desc->data_buffer,
@@ -2525,7 +3038,7 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter,
}
scmd = adapter->driver_cmds.internal_scmd;
- scmd->device = sdev;
+ 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;
@@ -2538,11 +3051,14 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter,
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;
+ goto out_cleanup;
}
- wait_for_completion_timeout(&adapter->driver_cmds.driver_scsiio_cmd.done,
+ wait_for_completion_timeout(&adapter->driver_cmds
+ .driver_scsiio_cmd.done,
cmd_desc->time_out * HZ);
if (!(adapter->driver_cmds.driver_scsiio_cmd.status &
@@ -2564,15 +3080,22 @@ static int leapraid_dispatch_scsi_io(struct leapraid_adapter *adapter,
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_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:
+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);
+ 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;
@@ -2582,7 +3105,8 @@ static int leapraid_dispatch_logsense(struct leapraid_adapter *adapter,
u16 hdl, u32 lun)
{
struct leapraid_scsi_cmd_desc *desc;
- int rc = 0;
+ char *buf;
+ int rc;
desc = kzalloc(sizeof(*desc), GFP_KERNEL);
if (!desc)
@@ -2596,7 +3120,7 @@ static int leapraid_dispatch_logsense(struct leapraid_adapter *adapter,
desc->cdb[0] = LOG_SENSE;
desc->cdb[2] = LEAPRAID_LOGSENSE_CDB_CODE;
desc->cdb[8] = desc->data_length;
- desc->raid_member = false;
+ desc->raid_member = 0;
desc->time_out = LEAPRAID_LOGSENSE_TIMEOUT;
desc->data_buffer = kzalloc(desc->data_length, GFP_KERNEL);
@@ -2606,11 +3130,10 @@ static int leapraid_dispatch_logsense(struct leapraid_adapter *adapter,
}
rc = leapraid_dispatch_scsi_io(adapter, desc);
- if (!rc) {
- if (((char *)desc->data_buffer)[8] ==
- LEAPRAID_LOGSENSE_SMART_CODE)
- leapraid_smart_fault_detect(adapter, hdl);
- }
+ buf = desc->data_buffer;
+
+ if (!rc && buf[8] == LEAPRAID_LOGSENSE_SMART_CODE)
+ leapraid_smart_fault_detect(adapter, hdl);
kfree(desc->data_buffer);
kfree(desc);
@@ -2622,31 +3145,32 @@ 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 = NULL;
+ struct leapraid_sas_dev *sas_dev;
if (!sdev_priv || !sdev_priv->starget_priv->card_port)
- goto out;
+ return false;
- sas_dev = leapraid_get_sas_dev_by_addr(adapter,
- sdev_priv->starget_priv->sas_address,
- sdev_priv->starget_priv->card_port);
+ 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;
+ goto out_fail;
if (reset_flg)
- sas_dev->led_on = false;
+ sas_dev->led_on = 0;
else if (sas_dev->led_on)
- goto out;
+ goto out_fail;
- if ((sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER) ||
- (sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME) ||
+ 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;
+ goto out_fail;
leapraid_sdev_put(sas_dev);
return true;
-out:
+out_fail:
if (sas_dev)
leapraid_sdev_put(sas_dev);
return false;
@@ -2659,16 +3183,21 @@ static void leapraid_sata_smart_poll_work(struct work_struct *work)
smart_poll_desc.smart_poll_work.work);
struct scsi_device *sdev;
struct leapraid_sdev_priv *sdev_priv;
- static u32 reset_cnt;
bool reset_flg = false;
- if (leapraid_check_adapter_is_op(adapter))
- goto out;
+ 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;
- reset_flg = (reset_cnt < adapter->reset_desc.reset_cnt);
- reset_cnt = adapter->reset_desc.reset_cnt;
+ adapter->reset_desc.last_reset_cnt = adapter->reset_desc.reset_cnt;
- __shost_for_each_device(sdev, adapter->shost) {
+ 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,
@@ -2676,11 +3205,12 @@ static void leapraid_sata_smart_poll_work(struct work_struct *work)
sdev_priv->lun);
}
-out:
+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));
+ 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)
@@ -2709,20 +3239,118 @@ void leapraid_smart_polling_start(struct leapraid_adapter *adapter)
void leapraid_smart_polling_stop(struct leapraid_adapter *adapter)
{
struct workqueue_struct *wq;
+ struct leapraid_smart_poll_desc *desc;
- if (!adapter->smart_poll_desc.smart_poll_wq)
+ desc = &adapter->smart_poll_desc;
+ if (!desc->smart_poll_wq)
return;
- wq = adapter->smart_poll_desc.smart_poll_wq;
- adapter->smart_poll_desc.smart_poll_wq = NULL;
+ wq = desc->smart_poll_wq;
+ desc->smart_poll_wq = NULL;
if (wq) {
- if (!cancel_delayed_work_sync(&adapter->smart_poll_desc.smart_poll_work))
+ 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;
+ struct leapraid_adapter *adapter;
+ struct workqueue_struct *wq;
+ struct Scsi_Host *shost;
+ struct pci_dev *pdev;
+ unsigned long flags;
+
+ desc = container_of(work, struct leapraid_overheat_desc,
+ fault_overheat_work);
+ adapter = container_of(desc, struct leapraid_adapter, overheat_desc);
+ pdev = adapter->pdev;
+ shost = pci_get_drvdata(pdev);
+
+ if (!shost) {
+ dev_err(&pdev->dev,
+ "Overheat processing failed: invalid host/adapter\n");
+ atomic_set(&adapter->overheat_desc.thermal_alert, 0);
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
+ return;
+ }
+
+ if (adapter->access_ctrl.host_removing) {
+ atomic_set(&adapter->overheat_desc.thermal_alert, 0);
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
+ return;
+ }
+
+ adapter->access_ctrl.host_removing = 1;
+ adapter->access_ctrl.shost_recover_async = 0;
+ 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);
+
+ leapraid_clean_active_cmds(adapter);
+ spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
+ wq = adapter->fw_evt_s.fw_evt_thread;
+ adapter->fw_evt_s.fw_evt_thread = NULL;
+ spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
+ if (wq)
+ destroy_workqueue(wq);
+
+ sas_remove_host(shost);
+ leapraid_cleanup_lists(adapter);
+ atomic_set(&adapter->overheat_desc.thermal_alert, 0);
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
+ dev_err(&pdev->dev, "%s: Suspend adapter due to overheat\n", __func__);
+}
+
+static void leapraid_overheat_init(struct leapraid_adapter *adapter)
+{
+ if (adapter->overheat_desc.fault_overheat_wq)
+ return;
+
+ atomic_set(&adapter->overheat_desc.thermal_alert, 0);
+ snprintf(adapter->overheat_desc.fault_overheat_wq_name,
+ sizeof(adapter->overheat_desc.fault_overheat_wq_name),
+ "driver_%s%u_overheat",
+ LEAPRAID_DRIVER_NAME,
+ adapter->adapter_attr.id);
+ adapter->overheat_desc.fault_overheat_wq =
+ create_singlethread_workqueue(
+ adapter->overheat_desc.fault_overheat_wq_name);
+ if (!adapter->overheat_desc.fault_overheat_wq) {
+ dev_err(&adapter->pdev->dev,
+ "Failed to create overheat workqueue\n");
+ return;
+ }
+
+ INIT_WORK(&adapter->overheat_desc.fault_overheat_work,
+ leapraid_overheat_work);
+}
+
+void leapraid_overheat_cleanup(struct leapraid_adapter *adapter)
+{
+ struct workqueue_struct *wq;
+
+ wq = xchg(&adapter->overheat_desc.fault_overheat_wq, NULL);
+ if (!wq)
+ return;
+
+ cancel_work_sync(&adapter->overheat_desc.fault_overheat_work);
+ destroy_workqueue(wq);
+}
+
static void leapraid_fw_work(struct leapraid_adapter *adapter,
struct leapraid_fw_evt_work *fw_evt);
@@ -2807,7 +3435,6 @@ static struct leapraid_fw_evt_work *leapraid_next_fw_evt(
fw_evt = list_first_entry(&adapter->fw_evt_s.fw_evt_list,
struct leapraid_fw_evt_work, list);
list_del_init(&fw_evt->list);
- leapraid_fw_evt_put(fw_evt);
}
spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
return fw_evt;
@@ -2816,56 +3443,65 @@ static struct leapraid_fw_evt_work *leapraid_next_fw_evt(
void leapraid_clean_active_fw_evt(struct leapraid_adapter *adapter)
{
struct leapraid_fw_evt_work *fw_evt;
- bool rc = false;
+ unsigned long flags;
+ bool in_fw_evt_context;
+ bool rc;
if ((list_empty(&adapter->fw_evt_s.fw_evt_list) &&
!adapter->fw_evt_s.cur_evt) || !adapter->fw_evt_s.fw_evt_thread)
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;
- while ((fw_evt = leapraid_next_fw_evt(adapter)) ||
- (fw_evt = adapter->fw_evt_s.cur_evt)) {
- if (fw_evt == adapter->fw_evt_s.cur_evt &&
- adapter->fw_evt_s.cur_evt->evt_type !=
- LEAPRAID_EVT_REMOVE_DEAD_DEV) {
- adapter->fw_evt_s.cur_evt = NULL;
- continue;
- }
-
+ while ((fw_evt = leapraid_next_fw_evt(adapter))) {
rc = cancel_work_sync(&fw_evt->work);
-
if (rc)
leapraid_fw_evt_put(fw_evt);
+ leapraid_fw_evt_put(fw_evt);
}
+
+ spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
+ fw_evt = adapter->fw_evt_s.cur_evt;
+ if (fw_evt) {
+ in_fw_evt_context = adapter->fw_evt_s.cur_evt_task == current;
+ leapraid_fw_evt_get(fw_evt);
+ }
+ spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
+ if (fw_evt) {
+ if (!in_fw_evt_context)
+ cancel_work_sync(&fw_evt->work);
+ leapraid_fw_evt_put(fw_evt);
+ }
+
adapter->fw_evt_s.fw_evt_cleanup = 0;
}
static void leapraid_internal_dev_ublk(struct scsi_device *sdev,
struct leapraid_sdev_priv *sdev_priv)
{
- int rc = 0;
+ int rc;
sdev_printk(KERN_WARNING, sdev,
- "hdl 0x%04x: now internal unblkg dev\n",
+ "hdl 0x%04x: Now internal unblkg dev\n",
sdev_priv->starget_priv->hdl);
- sdev_priv->block = false;
+ sdev_priv->block = 0;
rc = scsi_internal_device_unblock_nowait(sdev, SDEV_RUNNING);
if (rc == -EINVAL) {
sdev_printk(KERN_WARNING, sdev,
"hdl 0x%04x: unblkg failed, rc=%d\n",
sdev_priv->starget_priv->hdl, rc);
- sdev_priv->block = true;
+ sdev_priv->block = 1;
rc = scsi_internal_device_block_nowait(sdev);
if (rc)
sdev_printk(KERN_WARNING, sdev,
- "hdl 0x%04x: blkg failed: earlier unblkg err, rc=%d\n",
+ "hdl 0x%04x: Earlier ublkg err, rc=%d\n",
sdev_priv->starget_priv->hdl, rc);
- sdev_priv->block = false;
+ sdev_priv->block = 0;
rc = scsi_internal_device_unblock_nowait(sdev, SDEV_RUNNING);
if (rc)
sdev_printk(KERN_WARNING, sdev,
@@ -2874,38 +3510,6 @@ static void leapraid_internal_dev_ublk(struct scsi_device *sdev,
}
}
-static void leapraid_internal_ublk_io_dev_to_running(struct scsi_device *sdev)
-{
- struct leapraid_sdev_priv *sdev_priv;
-
- sdev_priv = sdev->hostdata;
- sdev_priv->block = false;
- scsi_internal_device_unblock_nowait(sdev, SDEV_RUNNING);
- sdev_printk(KERN_WARNING, sdev, "%s: ublk hdl 0x%04x\n",
- __func__, sdev_priv->starget_priv->hdl);
-}
-
-static void leapraid_ublk_io_dev_to_running(
- struct leapraid_adapter *adapter, u64 sas_addr,
- struct leapraid_card_port *card_port)
-{
- struct leapraid_sdev_priv *sdev_priv;
- struct scsi_device *sdev;
-
- shost_for_each_device(sdev, adapter->shost) {
- sdev_priv = sdev->hostdata;
- if (!sdev_priv)
- continue;
-
- if (sdev_priv->starget_priv->sas_address != sas_addr ||
- sdev_priv->starget_priv->card_port != card_port)
- continue;
-
- if (sdev_priv->block)
- leapraid_internal_ublk_io_dev_to_running(sdev);
- }
-}
-
static void leapraid_ublk_io_dev(struct leapraid_adapter *adapter,
u64 sas_addr,
struct leapraid_card_port *card_port)
@@ -2957,15 +3561,15 @@ static void leapraid_ublk_io_all_dev(struct leapraid_adapter *adapter)
}
}
-static void __maybe_unused leapraid_internal_dev_blk(
+static void leapraid_internal_dev_blk(
struct scsi_device *sdev,
struct leapraid_sdev_priv *sdev_priv)
{
- int rc = 0;
+ int rc;
- sdev_printk(KERN_INFO, sdev, "internal blkg hdl 0x%04x\n",
+ sdev_printk(KERN_INFO, sdev, "Internal blkg hdl 0x%04x\n",
sdev_priv->starget_priv->hdl);
- sdev_priv->block = true;
+ sdev_priv->block = 1;
rc = scsi_internal_device_block_nowait(sdev);
if (rc == -EINVAL)
sdev_printk(KERN_WARNING, sdev,
@@ -2973,42 +3577,6 @@ static void __maybe_unused leapraid_internal_dev_blk(
rc, sdev_priv->starget_priv->hdl);
}
-static void __maybe_unused leapraid_blkio_dev(struct leapraid_adapter *adapter,
- u16 hdl)
-{
- struct leapraid_sdev_priv *sdev_priv;
- struct leapraid_sas_dev *sas_dev;
- struct scsi_device *sdev;
-
- sas_dev = leapraid_get_sas_dev_by_hdl(adapter, hdl);
- shost_for_each_device(sdev, adapter->shost) {
- sdev_priv = sdev->hostdata;
- if (!sdev_priv)
- continue;
-
- if (sdev_priv->starget_priv->hdl != hdl)
- continue;
-
- if (sdev_priv->block)
- continue;
-
- if (sas_dev && sas_dev->pend_sas_rphy_add)
- continue;
-
- if (sdev_priv->sep) {
- sdev_printk(KERN_INFO, sdev,
- "sep hdl 0x%04x skip blkg\n",
- sdev_priv->starget_priv->hdl);
- continue;
- }
-
- leapraid_internal_dev_blk(sdev, sdev_priv);
- }
-
- if (sas_dev)
- leapraid_sdev_put(sas_dev);
-}
-
static void leapraid_imm_blkio_to_end_dev(struct leapraid_adapter *adapter,
struct leapraid_sas_port *sas_port)
{
@@ -3040,8 +3608,7 @@ static void leapraid_imm_blkio_to_end_dev(struct leapraid_adapter *adapter,
if (sdev_priv->sep) {
sdev_printk(KERN_INFO, sdev,
- "%s skip dev blk for sep hdl 0x%04x\n",
- __func__,
+ "skip dev blk: sep hdl 0x%04x\n",
sdev_priv->starget_priv->hdl);
continue;
}
@@ -3062,10 +3629,8 @@ static void leapraid_imm_blkio_set_end_dev_blk_hdls(
list_for_each_entry(sas_port,
&topo_node_exp->sas_port_list, port_list) {
- if (sas_port->remote_identify.device_type ==
- SAS_END_DEVICE) {
+ if (sas_port->remote_identify.device_type == SAS_END_DEVICE)
leapraid_imm_blkio_to_end_dev(adapter, sas_port);
- }
}
}
@@ -3087,7 +3652,7 @@ static void leapraid_imm_blkio_to_sib_exp(
sas_port->remote_identify.device_type ==
SAS_FANOUT_EXPANDER_DEVICE) {
topo_node_exp_sib =
- leapraid_exp_find_by_sas_address(
+ leapraid_exp_find_by_sas_address(
adapter,
sas_port->remote_identify.sas_address,
sas_port->card_port);
@@ -3126,17 +3691,15 @@ static void leapraid_report_sdev_directly(struct leapraid_adapter *adapter,
if (!sas_dev->starget) {
if (!adapter->scan_dev_desc.driver_loading) {
- leapraid_transport_port_remove(adapter,
- sas_dev->sas_addr,
- sas_dev->parent_sas_addr,
- sas_dev->card_port);
+ leapraid_transport_port_remove(
+ adapter,
+ sas_dev->sas_addr,
+ sas_dev->parent_sas_addr,
+ sas_dev->card_port);
leapraid_sas_dev_remove(adapter, sas_dev);
}
return;
}
-
- clear_bit(sas_dev->hdl,
- (unsigned long *)adapter->dev_topo.pending_dev_add);
}
static struct leapraid_sas_dev *leapraid_init_sas_dev(
@@ -3147,6 +3710,7 @@ static struct leapraid_sas_dev *leapraid_init_sas_dev(
{
struct leapraid_sas_dev *sas_dev;
struct leapraid_enc_node *enc_dev;
+ unsigned long flags;
sas_dev = kzalloc(sizeof(*sas_dev), GFP_KERNEL);
if (!sas_dev)
@@ -3161,28 +3725,32 @@ static struct leapraid_sas_dev *leapraid_init_sas_dev(
sas_dev->phy = sas_dev_pg0->phy_num;
sas_dev->enc_hdl = le16_to_cpu(sas_dev_pg0->enc_hdl);
sas_dev->dev_name = le64_to_cpu(sas_dev_pg0->dev_name);
- sas_dev->port_type = sas_dev_pg0->max_port_connections;
+ 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;
- memcpy(sas_dev->connector_name, sas_dev_pg0->connector_name, 4);
- sas_dev->connector_name[4] = '\0';
+ memcpy(sas_dev->connector_name,
+ sas_dev_pg0->connector_name,
+ LEAPRAID_SAS_DEV_P0_CON_NAME_LEN);
+ sas_dev->connector_name[LEAPRAID_SAS_DEV_P0_CON_NAME_LEN] =
+ '\0';
} else {
sas_dev->enc_level = 0;
sas_dev->connector_name[0] = '\0';
}
- if (le16_to_cpu(sas_dev_pg0->enc_hdl)) {
- enc_dev = leapraid_enc_find_by_hdl(adapter,
- le16_to_cpu(sas_dev_pg0->enc_hdl));
- sas_dev->enc_lid = enc_dev ?
- le64_to_cpu(enc_dev->pg0.enc_lid) : 0;
+ if (sas_dev->enc_hdl) {
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags);
+ enc_dev = leapraid_enc_find_by_hdl(adapter, sas_dev->enc_hdl);
+ if (enc_dev)
+ sas_dev->enc_lid = le64_to_cpu(enc_dev->pg0.enc_lid);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
}
dev_info(&adapter->pdev->dev,
- "add dev: hdl=0x%0x, sas addr=0x%016llx, port_type=0x%0x\n",
- hdl, sas_dev->sas_addr, sas_dev->port_type);
+ "add dev: hdl=0x%x, SAS addr=0x%016llx, port connect=0x%x\n",
+ hdl, sas_dev->sas_addr, sas_dev->port_connection);
return sas_dev;
}
@@ -3202,15 +3770,14 @@ static void leapraid_add_dev(struct leapraid_adapter *adapter, u16 hdl)
cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
cfgp2.handle = hdl;
- if ((leapraid_op_config_page(adapter, &sas_dev_pg0,
- cfgp1, cfgp2, GET_SAS_DEVICE_PG0)))
+ if (leapraid_op_config_page(adapter, &sas_dev_pg0,
+ cfgp1, cfgp2, GET_SAS_DEVICE_PG0))
return;
dev_info = le32_to_cpu(sas_dev_pg0.dev_info);
if (!(leapraid_is_end_dev(dev_info)))
return;
- set_bit(hdl, (unsigned long *)adapter->dev_topo.pending_dev_add);
sas_addr = le64_to_cpu(sas_dev_pg0.sas_address);
if (!(le16_to_cpu(sas_dev_pg0.flg) &
LEAPRAID_SAS_DEV_P0_FLG_DEV_PRESENT))
@@ -3223,8 +3790,6 @@ static void leapraid_add_dev(struct leapraid_adapter *adapter, u16 hdl)
sas_dev = leapraid_get_sas_dev_by_addr(adapter, sas_addr, card_port);
if (sas_dev) {
- clear_bit(hdl,
- (unsigned long *)adapter->dev_topo.pending_dev_add);
leapraid_sdev_put(sas_dev);
return;
}
@@ -3239,6 +3804,7 @@ static void leapraid_add_dev(struct leapraid_adapter *adapter, u16 hdl)
dev_info);
if (!sas_dev)
return;
+
if (adapter->scan_dev_desc.wait_scan_dev_done) {
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
leapraid_sdev_get(sas_dev);
@@ -3253,6 +3819,7 @@ static void leapraid_add_dev(struct leapraid_adapter *adapter, u16 hdl)
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
leapraid_report_sdev_directly(adapter, sas_dev);
}
+ leapraid_sdev_put(sas_dev);
}
static void leapraid_remove_device(struct leapraid_adapter *adapter,
@@ -3260,14 +3827,15 @@ static void leapraid_remove_device(struct leapraid_adapter *adapter,
{
struct leapraid_starget_priv *starget_priv;
+ leapraid_clear_cached_boot_dev(adapter, sas_dev, 0);
if (sas_dev->led_on) {
leapraid_set_led(adapter, sas_dev, false);
- sas_dev->led_on = false;
+ sas_dev->led_on = 0;
}
if (sas_dev->starget && sas_dev->starget->hostdata) {
starget_priv = sas_dev->starget->hostdata;
- starget_priv->deleted = true;
+ starget_priv->deleted = 1;
leapraid_ublk_io_dev(adapter,
sas_dev->sas_addr, sas_dev->card_port);
starget_priv->hdl = LEAPRAID_INVALID_DEV_HANDLE;
@@ -3279,12 +3847,13 @@ static void leapraid_remove_device(struct leapraid_adapter *adapter,
sas_dev->card_port);
dev_info(&adapter->pdev->dev,
- "remove dev: hdl=0x%04x, sas addr=0x%016llx\n",
+ "remove dev: hdl=0x%04x, SAS addr=0x%016llx\n",
sas_dev->hdl, (unsigned long long)sas_dev->sas_addr);
}
-static struct leapraid_vphy *leapraid_alloc_vphy(struct leapraid_adapter *adapter,
- u8 port_id, u8 phy_num)
+static struct leapraid_vphy *leapraid_alloc_vphy(
+ struct leapraid_adapter *adapter,
+ u8 port_id, u8 phy_num)
{
struct leapraid_card_port *port;
struct leapraid_vphy *vphy;
@@ -3296,7 +3865,6 @@ static struct leapraid_vphy *leapraid_alloc_vphy(struct leapraid_adapter *adapte
vphy = leapraid_get_vphy_by_phy(port, phy_num);
if (vphy)
return vphy;
-
vphy = kzalloc(sizeof(*vphy), GFP_KERNEL);
if (!vphy)
return NULL;
@@ -3310,46 +3878,157 @@ static struct leapraid_vphy *leapraid_alloc_vphy(struct leapraid_adapter *adapte
return vphy;
}
-static int leapraid_add_port_to_card_port_list(struct leapraid_adapter *adapter,
- u8 port_id, bool refresh)
+static int leapraid_add_port_to_card_port_list(
+ struct leapraid_adapter *adapter,
+ u8 port_id, bool refresh)
{
struct leapraid_card_port *card_port;
card_port = leapraid_get_port_by_id(adapter, port_id, false);
if (card_port)
return 0;
-
card_port = kzalloc(sizeof(*card_port), GFP_KERNEL);
if (!card_port)
return -ENOMEM;
card_port->port_id = port_id;
- dev_info(&adapter->pdev->dev,
- "port: %d is added to card_port list\n",
- card_port->port_id);
+ dev_dbg(&adapter->pdev->dev,
+ "port: %d is added to card_port list\n",
+ card_port->port_id);
- if (refresh)
- if (adapter->access_ctrl.shost_recovering)
- card_port->flg = LEAPRAID_CARD_PORT_FLG_NEW;
+ if (refresh && adapter->access_ctrl.shost_recovering)
+ card_port->flg = LEAPRAID_CARD_PORT_FLG_NEW;
list_add_tail(&card_port->list, &adapter->dev_topo.card_port_list);
return 0;
}
+static int leapraid_add_card_phy(struct leapraid_adapter *adapter,
+ struct leapraid_sas_io_unit_p0 *iou,
+ int i)
+{
+ struct leapraid_sas_phy_p0 phy_pg0;
+ union cfg_param_1 cfgp1 = {0};
+ union cfg_param_2 cfgp2 = {0};
+ struct leapraid_topo_node *card = &adapter->dev_topo.card;
+ u8 port_id;
+
+ cfgp1.phy_number = i;
+
+ if (leapraid_op_config_page(adapter, &phy_pg0,
+ cfgp1, cfgp2, GET_PHY_PG0))
+ return -EINVAL;
+
+ port_id = iou->phy_info[i].port;
+
+ if (leapraid_add_port_to_card_port_list(adapter, port_id, false))
+ return -EINVAL;
+
+ if ((le32_to_cpu(phy_pg0.phy_info) &
+ LEAPRAID_SAS_PHYINFO_VPHY) &&
+ ((phy_pg0.neg_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) >=
+ LEAPRAID_SAS_NEG_LINK_RATE_1_5)) {
+ if (!leapraid_alloc_vphy(adapter, port_id, i))
+ return -ENOMEM;
+
+ card->card_phy[i].vphy = 1;
+ }
+
+ card->card_phy[i].hdl = card->hdl;
+ card->card_phy[i].phy_id = i;
+ card->card_phy[i].card_port =
+ leapraid_get_port_by_id(adapter, port_id, false);
+
+ leapraid_transport_add_card_phy(adapter,
+ &card->card_phy[i],
+ &phy_pg0,
+ card->parent_dev);
+
+ return 0;
+}
+
+static int leapraid_refresh_card_phy(struct leapraid_adapter *adapter,
+ struct leapraid_sas_io_unit_p0 *iou,
+ int i)
+{
+ struct leapraid_topo_node *card = &adapter->dev_topo.card;
+ struct leapraid_sas_phy_p0 phy_pg0;
+ union cfg_param_1 cfgp1 = {0};
+ union cfg_param_2 cfgp2 = {0};
+ u16 attached_hdl;
+ u32 dev_info;
+ u8 link_rate;
+ u8 port_id;
+
+ link_rate = iou->phy_info[i].neg_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT;
+ port_id = iou->phy_info[i].port;
+ if (leapraid_add_port_to_card_port_list(adapter, port_id, true))
+ return -EINVAL;
+
+ dev_info = le32_to_cpu(iou->phy_info[i].controller_phy_dev_info);
+ if (dev_info & LEAPRAID_DEVTYP_SEP &&
+ link_rate >= LEAPRAID_SAS_NEG_LINK_RATE_1_5) {
+ cfgp1.phy_number = i;
+
+ if (leapraid_op_config_page(adapter, &phy_pg0,
+ cfgp1, cfgp2, GET_PHY_PG0))
+ 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;
+ }
+
+ card->card_phy[i].hdl = card->hdl;
+
+ attached_hdl = le16_to_cpu(iou->phy_info[i].attached_dev_hdl);
+ if (attached_hdl && link_rate < LEAPRAID_SAS_NEG_LINK_RATE_1_5)
+ link_rate = LEAPRAID_SAS_NEG_LINK_RATE_1_5;
+
+ card->card_phy[i].card_port =
+ leapraid_get_port_by_id(adapter, port_id, false);
+
+ if (!card->card_phy[i].phy) {
+ cfgp1.phy_number = i;
+ if (leapraid_op_config_page(adapter, &phy_pg0,
+ cfgp1, cfgp2, GET_PHY_PG0))
+ return 0;
+
+ card->card_phy[i].phy_id = i;
+
+ leapraid_transport_add_card_phy(adapter,
+ &card->card_phy[i],
+ &phy_pg0,
+ card->parent_dev);
+ return 0;
+ }
+
+ leapraid_transport_update_links(adapter,
+ card->sas_address,
+ attached_hdl,
+ i,
+ link_rate,
+ card->card_phy[i].card_port);
+
+ return 0;
+}
+
static void leapraid_sas_host_add(struct leapraid_adapter *adapter,
bool refresh)
{
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- struct leapraid_sas_phy_p0 phy_pg0;
struct leapraid_sas_dev_p0 sas_dev_pg0;
struct leapraid_enc_p0 enc_pg0;
struct leapraid_sas_io_unit_p0 *sas_iou_pg0;
u16 sas_iou_pg0_sz;
- u16 attached_hdl;
u8 phys_num;
- u8 port_id;
- u8 link_rate;
int i;
+ int rc;
if (!refresh) {
if (leapraid_get_adapter_phys(adapter, &phys_num) || !phys_num)
@@ -3364,128 +4043,46 @@ static void leapraid_sas_host_add(struct leapraid_adapter *adapter,
adapter->dev_topo.card.phys_num = phys_num;
}
- sas_iou_pg0_sz = offsetof(struct leapraid_sas_io_unit_p0, phy_info) +
- (adapter->dev_topo.card.phys_num *
- sizeof(struct leapraid_sas_io_unit0_phy_info));
+ sas_iou_pg0_sz =
+ offsetof(struct leapraid_sas_io_unit_p0, phy_info) +
+ (adapter->dev_topo.card.phys_num *
+ sizeof(struct leapraid_sas_io_unit0_phy_info));
sas_iou_pg0 = kzalloc(sas_iou_pg0_sz, GFP_KERNEL);
if (!sas_iou_pg0)
- goto out;
+ return;
if (leapraid_get_sas_io_unit_page0(adapter,
sas_iou_pg0,
sas_iou_pg0_sz))
- goto out;
+ goto out_free;
adapter->dev_topo.card.parent_dev = &adapter->shost->shost_gendev;
adapter->dev_topo.card.hdl =
le16_to_cpu(sas_iou_pg0->phy_info[0].controller_dev_hdl);
for (i = 0; i < adapter->dev_topo.card.phys_num; i++) {
- if (!refresh) { /* add */
- cfgp1.phy_number = i;
- if (leapraid_op_config_page(adapter, &phy_pg0, cfgp1,
- cfgp2, GET_PHY_PG0))
- goto out;
-
- port_id = sas_iou_pg0->phy_info[i].port;
- if (leapraid_add_port_to_card_port_list(adapter,
- port_id,
- false))
- goto out;
-
- if ((le32_to_cpu(phy_pg0.phy_info) &
- LEAPRAID_SAS_PHYINFO_VPHY) &&
- (phy_pg0.neg_link_rate >> 4) >=
- LEAPRAID_SAS_NEG_LINK_RATE_1_5) {
- if (!leapraid_alloc_vphy(adapter, port_id, i))
- goto out;
- adapter->dev_topo.card.card_phy[i].vphy = true;
- }
-
- adapter->dev_topo.card.card_phy[i].hdl =
- adapter->dev_topo.card.hdl;
- adapter->dev_topo.card.card_phy[i].phy_id = i;
- adapter->dev_topo.card.card_phy[i].card_port =
- leapraid_get_port_by_id(adapter,
- port_id,
- false);
- leapraid_transport_add_card_phy(
- adapter,
- &adapter->dev_topo.card.card_phy[i],
- &phy_pg0, adapter->dev_topo.card.parent_dev);
- } else { /* refresh */
- link_rate = sas_iou_pg0->phy_info[i].neg_link_rate >> 4;
- port_id = sas_iou_pg0->phy_info[i].port;
- if (leapraid_add_port_to_card_port_list(adapter,
- port_id,
- true))
- goto out;
-
- if (le32_to_cpu(sas_iou_pg0->phy_info[i]
- .controller_phy_dev_info) &
- LEAPRAID_DEVTYP_SEP &&
- link_rate >= LEAPRAID_SAS_NEG_LINK_RATE_1_5) {
- cfgp1.phy_number = i;
- if ((leapraid_op_config_page(adapter, &phy_pg0,
- cfgp1, cfgp2,
- GET_PHY_PG0)))
- continue;
-
- if ((le32_to_cpu(phy_pg0.phy_info) &
- LEAPRAID_SAS_PHYINFO_VPHY)) {
- if (!leapraid_alloc_vphy(adapter,
- port_id,
- i))
- goto out;
- adapter->dev_topo.card.card_phy[i].vphy = true;
- }
- }
-
- adapter->dev_topo.card.card_phy[i].hdl =
- adapter->dev_topo.card.hdl;
- attached_hdl =
- le16_to_cpu(sas_iou_pg0->phy_info[i].attached_dev_hdl);
- if (attached_hdl && link_rate < LEAPRAID_SAS_NEG_LINK_RATE_1_5)
- link_rate = LEAPRAID_SAS_NEG_LINK_RATE_1_5;
-
- adapter->dev_topo.card.card_phy[i].card_port =
- leapraid_get_port_by_id(adapter,
- port_id,
- false);
- if (!adapter->dev_topo.card.card_phy[i].phy) {
- cfgp1.phy_number = i;
- if ((leapraid_op_config_page(adapter, &phy_pg0,
- cfgp1, cfgp2,
- GET_PHY_PG0)))
- continue;
-
- adapter->dev_topo.card.card_phy[i].phy_id = i;
- leapraid_transport_add_card_phy(adapter,
- &adapter->dev_topo.card.card_phy[i],
- &phy_pg0,
- adapter->dev_topo.card.parent_dev);
- continue;
- }
-
- leapraid_transport_update_links(adapter,
- adapter->dev_topo.card.sas_address,
- attached_hdl, i, link_rate,
- adapter->dev_topo.card.card_phy[i].card_port);
- }
+ if (!refresh) /* add */
+ rc = leapraid_add_card_phy(adapter, sas_iou_pg0, i);
+ else /* refresh */
+ rc = leapraid_refresh_card_phy(adapter,
+ sas_iou_pg0,
+ i);
+ if (rc)
+ goto out_free;
}
if (!refresh) {
cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
cfgp2.handle = adapter->dev_topo.card.hdl;
- if ((leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1,
- cfgp2, GET_SAS_DEVICE_PG0)))
- goto out;
+ if (leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1,
+ cfgp2, GET_SAS_DEVICE_PG0))
+ goto out_free;
adapter->dev_topo.card.enc_hdl =
le16_to_cpu(sas_dev_pg0.enc_hdl);
adapter->dev_topo.card.sas_address =
le64_to_cpu(sas_dev_pg0.sas_address);
dev_info(&adapter->pdev->dev,
- "add host: devhdl=0x%04x, sas addr=0x%016llx, phynums=%d\n",
+ "add host: hdl=0x%04x, SAS addr=0x%016llx, phy=%d\n",
adapter->dev_topo.card.hdl,
(unsigned long long)adapter->dev_topo.card.sas_address,
adapter->dev_topo.card.phys_num);
@@ -3500,7 +4097,7 @@ static void leapraid_sas_host_add(struct leapraid_adapter *adapter,
le64_to_cpu(enc_pg0.enc_lid);
}
}
-out:
+out_free:
kfree(sas_iou_pg0);
}
@@ -3514,22 +4111,24 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter,
struct leapraid_sas_port *sas_port = NULL;
struct leapraid_enc_node *enc_dev;
struct leapraid_exp_p1 exp_pg1;
- int rc = 0;
+ int ret;
+ int rc;
unsigned long flags;
u8 port_id;
u16 parent_handle;
- u64 sas_addr_parent = 0;
+ u64 sas_addr_parent;
int i;
port_id = exp_pg0->physical_port;
parent_handle = le16_to_cpu(exp_pg0->parent_dev_hdl);
- if (leapraid_get_sas_address(adapter, parent_handle, &sas_addr_parent))
- return -1;
-
+ rc = leapraid_get_sas_address(adapter,
+ parent_handle, &sas_addr_parent);
+ if (rc)
+ return rc;
topo_node_exp = kzalloc(sizeof(*topo_node_exp), GFP_KERNEL);
if (!topo_node_exp)
- return -1;
+ return -ENOMEM;
topo_node_exp->hdl = hdl;
topo_node_exp->phys_num = exp_pg0->phy_num;
@@ -3538,17 +4137,19 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter,
topo_node_exp->card_port =
leapraid_get_port_by_id(adapter, port_id, false);
if (!topo_node_exp->card_port) {
- rc = -1;
+ rc = -EPERM;
goto out_fail;
}
dev_info(&adapter->pdev->dev,
- "add exp: sas addr=0x%016llx, hdl=0x%04x, phdl=0x%04x, phys=%d\n",
+ "add exp: saddr=0x%016llx, hdl=0x%04x, phdl=0x%04x, phy=%d\n",
(unsigned long long)topo_node_exp->sas_address,
hdl, parent_handle,
topo_node_exp->phys_num);
if (!topo_node_exp->phys_num) {
- rc = -1;
+ dev_err(&adapter->pdev->dev,
+ "%s: Invalid PHY num from exp_pg0\n", __func__);
+ rc = -EPERM;
goto out_fail;
}
@@ -3556,7 +4157,10 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter,
kcalloc(topo_node_exp->phys_num,
sizeof(struct leapraid_card_phy), GFP_KERNEL);
if (!topo_node_exp->card_phy) {
- rc = -1;
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to alloc expander phy array, count=%u\n",
+ __func__, topo_node_exp->phys_num);
+ rc = -EPERM;
goto out_fail;
}
@@ -3564,7 +4168,7 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter,
sas_port = leapraid_transport_port_add(adapter, hdl, sas_addr_parent,
topo_node_exp->card_port);
if (!sas_port) {
- rc = -1;
+ rc = -EPERM;
goto out_fail;
}
@@ -3573,31 +4177,38 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter,
for (i = 0; i < topo_node_exp->phys_num; i++) {
cfgp1->phy_number = i;
cfgp2->handle = hdl;
- if ((leapraid_op_config_page(adapter, &exp_pg1, *cfgp1, *cfgp2,
- GET_SAS_EXPANDER_PG1))) {
- rc = -1;
+ if (leapraid_op_config_page(adapter, &exp_pg1, *cfgp1, *cfgp2,
+ GET_SAS_EXPANDER_PG1)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to get exp_pg1, phy=%d\n",
+ __func__, i);
+ rc = -EPERM;
goto out_fail;
}
topo_node_exp->card_phy[i].hdl = hdl;
topo_node_exp->card_phy[i].phy_id = i;
topo_node_exp->card_phy[i].card_port =
- leapraid_get_port_by_id(adapter, port_id, false);
- if ((leapraid_transport_add_exp_phy(adapter,
- &topo_node_exp->card_phy[i],
- &exp_pg1,
- topo_node_exp->parent_dev))) {
- rc = -1;
+ leapraid_get_port_by_id(adapter, port_id, false);
+ ret = leapraid_transport_add_exp_phy(
+ adapter,
+ &topo_node_exp->card_phy[i],
+ &exp_pg1,
+ topo_node_exp->parent_dev);
+ if (ret) {
+ rc = -EPERM;
goto out_fail;
}
}
if (topo_node_exp->enc_hdl) {
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags);
enc_dev = leapraid_enc_find_by_hdl(adapter,
topo_node_exp->enc_hdl);
if (enc_dev)
topo_node_exp->enc_lid =
le64_to_cpu(enc_dev->pg0.enc_lid);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
}
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
@@ -3611,6 +4222,7 @@ static int leapraid_internal_exp_add(struct leapraid_adapter *adapter,
topo_node_exp->sas_address,
sas_addr_parent,
topo_node_exp->card_port);
+ kfree(topo_node_exp->card_phy);
kfree(topo_node_exp);
return rc;
}
@@ -3622,22 +4234,29 @@ static int leapraid_exp_add(struct leapraid_adapter *adapter, u16 hdl)
struct leapraid_topo_node *topo_node_exp;
struct leapraid_exp_p0 exp_pg0;
u16 parent_handle;
- u64 sas_addr, sas_addr_parent = 0;
+ u64 sas_addr, sas_addr_parent;
unsigned long flags;
u8 port_id;
- int rc = 0;
+ int rc;
- if (!hdl)
+ if (!hdl) {
+ dev_warn(&adapter->pdev->dev, "%s: Invalid hdl\n", __func__);
return -EPERM;
+ }
if (adapter->access_ctrl.shost_recovering ||
- adapter->access_ctrl.pcie_recovering)
+ adapter->access_ctrl.pcie_recovering) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed, shost_recovering=%d pcie_recovering=%d\n",
+ __func__, adapter->access_ctrl.shost_recovering,
+ adapter->access_ctrl.pcie_recovering);
return -EPERM;
+ }
cfgp1.form = LEAPRAID_SAS_EXP_CFD_PGAD_HDL;
cfgp2.handle = hdl;
- if ((leapraid_op_config_page(adapter, &exp_pg0, cfgp1, cfgp2,
- GET_SAS_EXPANDER_PG0)))
+ if (leapraid_op_config_page(adapter, &exp_pg0, cfgp1, cfgp2,
+ GET_SAS_EXPANDER_PG0))
return -EPERM;
parent_handle = le16_to_cpu(exp_pg0.parent_dev_hdl);
@@ -3648,10 +4267,14 @@ static int leapraid_exp_add(struct leapraid_adapter *adapter, u16 hdl)
if (sas_addr_parent != adapter->dev_topo.card.sas_address) {
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
topo_node_exp =
- leapraid_exp_find_by_sas_address(adapter,
+ leapraid_exp_find_by_sas_address(
+ adapter,
sas_addr_parent,
- leapraid_get_port_by_id(adapter, port_id, false));
- spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
+ leapraid_get_port_by_id(adapter,
+ port_id,
+ false));
+ spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock,
+ flags);
if (!topo_node_exp) {
rc = leapraid_exp_add(adapter, parent_handle);
if (rc != 0)
@@ -3662,7 +4285,9 @@ static int leapraid_exp_add(struct leapraid_adapter *adapter, u16 hdl)
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
sas_addr = le64_to_cpu(exp_pg0.sas_address);
topo_node_exp =
- leapraid_exp_find_by_sas_address(adapter, sas_addr,
+ leapraid_exp_find_by_sas_address(
+ adapter,
+ sas_addr,
leapraid_get_port_by_id(adapter, port_id, false));
spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
@@ -3710,7 +4335,7 @@ static void leapraid_exp_node_rm(struct leapraid_adapter *adapter,
topo_node_exp->sas_address_parent,
topo_node_exp->card_port);
dev_info(&adapter->pdev->dev,
- "removing exp: port=%d, sas addr=0x%016llx, hdl=0x%04x\n",
+ "removing exp: port=%d, SAS addr=0x%016llx, hdl=0x%04x\n",
port_id, (unsigned long long)topo_node_exp->sas_address,
topo_node_exp->hdl);
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
@@ -3742,92 +4367,6 @@ void leapraid_exp_rm(struct leapraid_adapter *adapter, u64 sas_addr,
leapraid_exp_node_rm(adapter, topo_node_exp);
}
-static void leapraid_check_device(struct leapraid_adapter *adapter,
- u64 parent_sas_address, u16 handle,
- u8 phy_number, u8 link_rate)
-{
- struct leapraid_sas_dev_p0 sas_device_pg0;
- struct leapraid_sas_dev *sas_dev = NULL;
- struct leapraid_enc_node *enclosure_dev = NULL;
- union cfg_param_1 cfgp1 = {0};
- union cfg_param_2 cfgp2 = {0};
- unsigned long flags;
- u64 sas_address;
- struct scsi_target *starget;
- struct leapraid_starget_priv *sas_target_priv_data;
- u32 device_info;
- struct leapraid_card_port *port;
-
- cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
- cfgp2.handle = handle;
- if ((leapraid_op_config_page(adapter, &sas_device_pg0, cfgp1, cfgp2,
- GET_SAS_DEVICE_PG0)))
- return;
-
- if (phy_number != sas_device_pg0.phy_num)
- return;
-
- device_info = le32_to_cpu(sas_device_pg0.dev_info);
- if (!(leapraid_is_end_dev(device_info)))
- return;
-
- spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
- sas_address = le64_to_cpu(sas_device_pg0.sas_address);
- port = leapraid_get_port_by_id(adapter, sas_device_pg0.physical_port,
- false);
- if (!port)
- goto out_unlock;
-
- sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter, sas_address,
- port);
- if (!sas_dev)
- goto out_unlock;
-
- if (unlikely(sas_dev->hdl != handle)) {
- starget = sas_dev->starget;
- sas_target_priv_data = starget->hostdata;
- starget_printk(KERN_INFO, starget,
- "hdl changed from 0x%04x to 0x%04x!\n",
- sas_dev->hdl, handle);
- sas_target_priv_data->hdl = handle;
- sas_dev->hdl = handle;
- if (le16_to_cpu(sas_device_pg0.flg) &
- LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID) {
- sas_dev->enc_level =
- sas_device_pg0.enc_level;
- memcpy(sas_dev->connector_name,
- sas_device_pg0.connector_name, 4);
- sas_dev->connector_name[4] = '\0';
- } else {
- sas_dev->enc_level = 0;
- sas_dev->connector_name[0] = '\0';
- }
- sas_dev->enc_hdl =
- le16_to_cpu(sas_device_pg0.enc_hdl);
- enclosure_dev =
- leapraid_enc_find_by_hdl(adapter, sas_dev->enc_hdl);
- if (enclosure_dev) {
- sas_dev->enc_lid =
- le64_to_cpu(enclosure_dev->pg0.enc_lid);
- }
- }
-
- if (!(le16_to_cpu(sas_device_pg0.flg) &
- LEAPRAID_SAS_DEV_P0_FLG_DEV_PRESENT))
- goto out_unlock;
-
- spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
-
- leapraid_ublk_io_dev_to_running(adapter, sas_address, port);
- goto out;
-
-out_unlock:
- spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
-out:
- if (sas_dev)
- leapraid_sdev_put(sas_dev);
-}
-
static int leapraid_internal_sas_topo_chg_evt(
struct leapraid_adapter *adapter,
struct leapraid_card_port *card_port,
@@ -3836,10 +4375,8 @@ static int leapraid_internal_sas_topo_chg_evt(
u64 sas_addr, u8 max_phys)
{
struct leapraid_evt_data_sas_topo_change_list *evt_data;
- struct leapraid_sas_dev *sas_dev;
- unsigned long flags;
u8 phy_number;
- u8 link_rate, prev_link_rate;
+ u8 link_rate;
u16 reason_code;
u16 hdl;
int i;
@@ -3861,47 +4398,15 @@ static int leapraid_internal_sas_topo_chg_evt(
LEAPRAID_EVT_SAS_TOPO_RC_MASK;
hdl = le16_to_cpu(evt_data->phy[i].attached_dev_hdl);
- if (!hdl)
+ if (!hdl ||
+ hdl > adapter->adapter_attr.features.max_dev_handle) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid device handle\n", __func__);
continue;
-
- link_rate = evt_data->phy[i].link_rate >> 4;
- prev_link_rate = evt_data->phy[i].link_rate & 0xF;
+ }
+ link_rate = evt_data->phy[i].link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT;
switch (reason_code) {
- case LEAPRAID_EVT_SAS_TOPO_RC_PHY_CHANGED:
- if (adapter->access_ctrl.shost_recovering)
- break;
-
- if (link_rate == prev_link_rate)
- break;
-
- leapraid_transport_update_links(adapter, sas_addr,
- hdl, phy_number,
- link_rate, card_port);
- if (link_rate < LEAPRAID_SAS_NEG_LINK_RATE_1_5)
- break;
-
- leapraid_check_device(adapter, sas_addr, hdl,
- phy_number, link_rate);
- spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock,
- flags);
- sas_dev =
- leapraid_hold_lock_get_sas_dev_by_hdl(
- adapter, hdl);
- spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock,
- flags);
- if (sas_dev) {
- leapraid_sdev_put(sas_dev);
- break;
- }
- if (!test_bit(hdl, (unsigned long *)adapter->dev_topo.pending_dev_add))
- break;
-
- evt_data->phy[i].phy_status &=
- LEAPRAID_EVT_SAS_TOPO_RC_CLEAR_MASK;
- evt_data->phy[i].phy_status |=
- LEAPRAID_EVT_SAS_TOPO_RC_TARG_ADDED;
- fallthrough;
-
case LEAPRAID_EVT_SAS_TOPO_RC_TARG_ADDED:
if (adapter->access_ctrl.shost_recovering)
break;
@@ -3942,7 +4447,7 @@ static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter,
return 0;
evt_data = fw_evt->evt_data;
- leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num);
+ leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num > 0);
if (fw_evt->ignore)
return 0;
@@ -3951,9 +4456,9 @@ static int leapraid_sas_topo_chg_evt(struct leapraid_adapter *adapter,
card_port = leapraid_get_port_by_id(adapter,
evt_data->physical_port,
false);
- if (evt_data->exp_status == LEAPRAID_EVT_SAS_TOPO_ES_ADDED)
- if (leapraid_exp_add(adapter, phdl) != 0)
- return 0;
+ if (evt_data->exp_status == LEAPRAID_EVT_SAS_TOPO_ES_ADDED &&
+ leapraid_exp_add(adapter, phdl) != 0)
+ return 0;
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
topo_node_exp = leapraid_exp_find_by_hdl(adapter, phdl);
@@ -3980,12 +4485,13 @@ static void leapraid_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
{
sdev->no_uld_attach = no_uld_attach ? 1 : 0;
sdev_printk(KERN_INFO, sdev,
- "%s raid component to upper layer\n",
+ "%s RAID component to upper layer\n",
sdev->no_uld_attach ? "hide" : "expose");
WARN_ON(scsi_device_reprobe(sdev));
}
-static void leapraid_sas_pd_add(struct leapraid_adapter *adapter,
+static void leapraid_sas_pd_add(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_ir_change *evt_data)
{
union cfg_param_1 cfgp1 = {0};
@@ -3997,20 +4503,26 @@ static void leapraid_sas_pd_add(struct leapraid_adapter *adapter,
u16 hdl;
hdl = le16_to_cpu(evt_data->phys_disk_dev_hdl);
- set_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls);
+ if (!hdl || hdl > adapter->adapter_attr.features.max_dev_handle) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid device handle\n", __func__);
+ return;
+ }
+
+ set_bit(hdl, adapter->dev_topo.pd_hdls);
sas_dev = leapraid_get_sas_dev_by_hdl(adapter, hdl);
if (sas_dev) {
leapraid_sdev_put(sas_dev);
dev_warn(&adapter->pdev->dev,
- "dev handle 0x%x already exists\n", hdl);
+ "Dev handle 0x%x already exists\n", hdl);
return;
}
cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
cfgp2.handle = hdl;
- if ((leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1, cfgp2,
- GET_SAS_DEVICE_PG0))) {
- dev_warn(&adapter->pdev->dev, "failed to read dev page0\n");
+ if (leapraid_op_config_page(adapter, &sas_dev_p0, cfgp1, cfgp2,
+ GET_SAS_DEVICE_PG0)) {
+ dev_warn(&adapter->pdev->dev, "Failed to read dev page0\n");
return;
}
@@ -4025,7 +4537,8 @@ static void leapraid_sas_pd_add(struct leapraid_adapter *adapter,
leapraid_add_dev(adapter, hdl);
}
-static void leapraid_sas_pd_delete(struct leapraid_adapter *adapter,
+static void leapraid_sas_pd_delete(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_ir_change *evt_data)
{
u16 hdl;
@@ -4034,7 +4547,8 @@ static void leapraid_sas_pd_delete(struct leapraid_adapter *adapter,
leapraid_sas_dev_remove_by_hdl(adapter, hdl);
}
-static void leapraid_sas_pd_hide(struct leapraid_adapter *adapter,
+static void leapraid_sas_pd_hide(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_ir_change *evt_data)
{
struct leapraid_starget_priv *starget_priv;
@@ -4042,10 +4556,15 @@ static void leapraid_sas_pd_hide(struct leapraid_adapter *adapter,
struct leapraid_sas_dev *sas_dev;
unsigned long flags;
u64 volume_wwid = 0;
- u16 volume_hdl = 0;
+ u16 volume_hdl;
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__);
+ return;
+ }
leapraid_cfg_get_volume_hdl(adapter, hdl, &volume_hdl);
if (volume_hdl)
leapraid_cfg_get_volume_wwid(adapter,
@@ -4059,21 +4578,23 @@ static void leapraid_sas_pd_hide(struct leapraid_adapter *adapter,
return;
}
- set_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls);
+ set_bit(hdl, adapter->dev_topo.pd_hdls);
if (sas_dev->starget && sas_dev->starget->hostdata) {
starget = sas_dev->starget;
starget_priv = starget->hostdata;
starget_priv->flg |= LEAPRAID_TGT_FLG_RAID_MEMBER;
sas_dev->volume_hdl = volume_hdl;
sas_dev->volume_wwid = volume_wwid;
- leapraid_sdev_put(sas_dev);
}
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 *)1, leapraid_reprobe_lun);
+ (void *)LEAPRAID_NO_ULD_ATTACH_FLAG,
+ leapraid_reprobe_lun);
}
+
+ leapraid_sdev_put(sas_dev);
}
static void leapraid_sas_pd_expose(
@@ -4088,11 +4609,17 @@ static void leapraid_sas_pd_expose(
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__);
+ return;
+ }
+
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl);
if (!sas_dev) {
dev_warn(&adapter->pdev->dev,
- "%s:%d: sas_dev not found, hdl=0x%x\n",
+ "%s:%d: sas_dev not found, hdl=0x%x\n",
__func__, __LINE__, hdl);
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
return;
@@ -4100,84 +4627,100 @@ static void leapraid_sas_pd_expose(
sas_dev->volume_hdl = 0;
sas_dev->volume_wwid = 0;
- clear_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls);
+ clear_bit(hdl, adapter->dev_topo.pd_hdls);
if (sas_dev->starget && sas_dev->starget->hostdata) {
starget = sas_dev->starget;
starget_priv = starget->hostdata;
starget_priv->flg &= ~LEAPRAID_TGT_FLG_RAID_MEMBER;
- sas_dev->led_on = false;
- leapraid_sdev_put(sas_dev);
+ sas_dev->led_on = 0;
}
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, NULL, leapraid_reprobe_lun);
+ starget_for_each_device(starget,
+ LEAPRAID_ULD_ATTACH_FLAG,
+ leapraid_reprobe_lun);
}
+
+ leapraid_sdev_put(sas_dev);
}
-static void leapraid_sas_vol_visibility(struct leapraid_adapter *adapter,
+static void leapraid_sas_vol_visibility(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_ir_change *evt_data)
{
- struct leapraid_raid_volume *raid_volume = NULL;
- struct scsi_device *sdev = NULL;
- u16 hdl = 0;
+ struct leapraid_raid_volume *raid_volume;
+ struct scsi_device *sdev;
+ bool reprobe_flg = false;
+ bool sdev_held = false;
unsigned long flags;
- u8 rc = 0;
- u8 reprobe_flg = 0;
+ u16 hdl;
+ u8 rc;
hdl = le16_to_cpu(evt_data->vol_dev_hdl);
rc = evt_data->reason_code;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_hdl(adapter, hdl);
if (!raid_volume) {
+ dev_warn(&adapter->pdev->dev,
+ "%s:%d: Volume handle 0x%x not found\n",
+ __func__, __LINE__, hdl);
+ return;
+ }
+
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ sdev = raid_volume->sdev;
+ if (!sdev) {
spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
flags);
+ leapraid_raid_volume_put(raid_volume);
dev_warn(&adapter->pdev->dev,
- "%s:%d: volume handle 0x%x not found\n",
+ "%s:%d: Volume handle 0x%x has no sdev\n",
__func__, __LINE__, hdl);
return;
}
- reprobe_flg = 0;
- sdev = raid_volume->sdev;
- if (sdev) {
- if (sdev->no_uld_attach) {
- if (rc == LEAPRAID_EVT_IR_RC_VOLUME_UNHIDE) {
- sdev->no_uld_attach = 0;
- reprobe_flg = 1;
- }
- } else {
- if (rc == LEAPRAID_EVT_IR_RC_VOLUME_HIDE) {
- sdev->no_uld_attach = 1;
- reprobe_flg = 1;
- }
- }
+ if (sdev->no_uld_attach &&
+ rc == LEAPRAID_EVT_IR_RC_VOLUME_UNHIDE) {
+ sdev->no_uld_attach = 0;
+ reprobe_flg = true;
+ } else if (!sdev->no_uld_attach &&
+ rc == LEAPRAID_EVT_IR_RC_VOLUME_HIDE) {
+ sdev->no_uld_attach = 1;
+ reprobe_flg = true;
+ }
- if (reprobe_flg) {
- if (sdev->no_uld_attach)
- sdev_printk(KERN_INFO, sdev, "hide vol\n");
- else
- sdev_printk(KERN_INFO, sdev, "unhide vol\n");
+ if (reprobe_flg && !scsi_device_get(sdev))
+ sdev_held = true;
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+ leapraid_raid_volume_put(raid_volume);
- WARN_ON(scsi_device_reprobe(sdev));
- } else {
- dev_warn(&adapter->pdev->dev,
- "%s:rc(0x%x):request matches, skipping.\n",
- __func__, rc);
- }
+ if (!reprobe_flg) {
+ dev_warn(&adapter->pdev->dev,
+ "%s:rc(0x%x): Request matches, skipping\n",
+ __func__, rc);
+ return;
+ }
- } else {
+ if (!sdev_held) {
dev_warn(&adapter->pdev->dev,
- "%s:%d: volume handle 0x%x has no sdev\n",
- __func__, __LINE__, hdl);
+ "%s: Failed to hold sdev for reprobe, hdl=0x%x\n",
+ __func__, hdl);
+ return;
}
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+ if (sdev->no_uld_attach)
+ sdev_printk(KERN_INFO, sdev, "hide vol\n");
+ else
+ sdev_printk(KERN_INFO, sdev, "unhide vol\n");
+
+ WARN_ON(scsi_device_reprobe(sdev));
+ scsi_device_put(sdev);
}
-static void leapraid_sas_volume_add(struct leapraid_adapter *adapter,
+static void leapraid_sas_volume_add(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_ir_change *evt_data)
{
struct leapraid_raid_volume *raid_volume;
@@ -4188,23 +4731,21 @@ static void leapraid_sas_volume_add(struct leapraid_adapter *adapter,
hdl = le16_to_cpu(evt_data->vol_dev_hdl);
if (leapraid_cfg_get_volume_wwid(adapter, hdl, &wwid)) {
- dev_warn(&adapter->pdev->dev, "failed to read volume page1\n");
+ dev_warn(&adapter->pdev->dev, "Failed to read volume page1\n");
return;
}
if (!wwid) {
- dev_warn(&adapter->pdev->dev, "invalid WWID(handle=0x%x)\n",
+ dev_warn(&adapter->pdev->dev, "Invalid WWID(handle=0x%x)\n",
hdl);
return;
}
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_wwid(adapter, wwid);
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
-
if (raid_volume) {
dev_warn(&adapter->pdev->dev,
- "volume handle 0x%x already exists\n", hdl);
+ "Volume handle 0x%x already exists\n", hdl);
+ leapraid_raid_volume_put(raid_volume);
return;
}
@@ -4212,6 +4753,8 @@ static void leapraid_sas_volume_add(struct leapraid_adapter *adapter,
if (!raid_volume)
return;
+ INIT_LIST_HEAD(&raid_volume->list);
+ kref_init(&raid_volume->refcnt);
raid_volume->id = adapter->dev_topo.sas_id++;
raid_volume->channel = RAID_CHANNEL;
raid_volume->hdl = hdl;
@@ -4222,50 +4765,65 @@ static void leapraid_sas_volume_add(struct leapraid_adapter *adapter,
raid_volume->id, 0))
leapraid_raid_volume_remove(adapter, raid_volume);
dev_info(&adapter->pdev->dev,
- "add raid volume: hdl=0x%x, wwid=0x%llx\n", hdl, wwid);
+ "add RAID volume: hdl=0x%x, wwid=0x%llx\n", hdl, wwid);
} else {
spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
leapraid_check_boot_dev(adapter, raid_volume, RAID_CHANNEL);
spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
flags);
}
+ leapraid_raid_volume_put(raid_volume);
+}
+
+static void leapraid_sas_volume_delete_by_ptr(
+ struct leapraid_adapter *adapter,
+ struct leapraid_raid_volume *raid_volume)
+{
+ struct leapraid_starget_priv *starget_priv;
+ struct scsi_target *starget = NULL;
+ unsigned long flags;
+ bool in_list;
+
+ if (!raid_volume)
+ return;
+
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ in_list = !list_empty(&raid_volume->list);
+ if (in_list && raid_volume->starget) {
+ starget = raid_volume->starget;
+ starget_priv = starget->hostdata;
+ if (starget_priv)
+ starget_priv->deleted = 1;
+ }
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+
+ if (!in_list)
+ return;
+
+ dev_info(&adapter->pdev->dev,
+ "delete RAID volume: hdl=0x%x, wwid=0x%llx\n",
+ raid_volume->hdl, raid_volume->wwid);
+ leapraid_raid_volume_remove(adapter, raid_volume);
+
+ if (starget)
+ scsi_remove_target(&starget->dev);
}
static void leapraid_sas_volume_delete(struct leapraid_adapter *adapter,
u16 hdl)
{
- struct leapraid_starget_priv *starget_priv;
struct leapraid_raid_volume *raid_volume;
- struct scsi_target *starget = NULL;
- unsigned long flags;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_hdl(adapter, hdl);
if (!raid_volume) {
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
- flags);
dev_warn(&adapter->pdev->dev,
- "%s:%d: volume handle 0x%x not found\n",
+ "%s:%d: Volume handle 0x%x not found\n",
__func__, __LINE__, hdl);
return;
}
- if (raid_volume->starget) {
- starget = raid_volume->starget;
- starget_priv = starget->hostdata;
- starget_priv->deleted = true;
- }
-
- dev_info(&adapter->pdev->dev,
- "delete raid volume: hdl=0x%x, wwid=0x%llx\n",
- raid_volume->hdl, raid_volume->wwid);
- list_del(&raid_volume->list);
- kfree(raid_volume);
-
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
-
- if (starget)
- scsi_remove_target(&starget->dev);
+ leapraid_sas_volume_delete_by_ptr(adapter, raid_volume);
+ leapraid_raid_volume_put(raid_volume);
}
static void leapraid_sas_ir_chg_evt(struct leapraid_adapter *adapter,
@@ -4309,7 +4867,9 @@ static void leapraid_sas_enc_dev_stat_add_node(
{
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- struct leapraid_enc_node *enc_node = NULL;
+ struct leapraid_enc_node *enc_node;
+ struct leapraid_enc_node *enc_exist;
+ unsigned long flags;
int rc;
enc_node = kzalloc(sizeof(*enc_node), GFP_KERNEL);
@@ -4324,16 +4884,33 @@ static void leapraid_sas_enc_dev_stat_add_node(
kfree(enc_node);
return;
}
+
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags);
+ enc_exist = leapraid_enc_find_by_hdl(adapter, hdl);
+ if (enc_exist) {
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
+ kfree(enc_node);
+ return;
+ }
list_add_tail(&enc_node->list, &adapter->dev_topo.enc_list);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
}
static void leapraid_sas_enc_dev_stat_del_node(
- struct leapraid_enc_node *enc_node)
+ struct leapraid_adapter *adapter, u16 hdl)
{
- if (!enc_node)
+ struct leapraid_enc_node *enc_node;
+ unsigned long flags;
+
+ if (!hdl)
return;
- list_del(&enc_node->list);
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags);
+ enc_node = leapraid_enc_find_by_hdl(adapter, hdl);
+ if (enc_node)
+ list_del(&enc_node->list);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
+
kfree(enc_node);
}
@@ -4341,7 +4918,6 @@ static void leapraid_sas_enc_dev_stat_chg_evt(
struct leapraid_adapter *adapter,
struct leapraid_fw_evt_work *fw_evt)
{
- struct leapraid_enc_node *enc_node = NULL;
struct leapraid_evt_data_sas_enc_dev_status_change *evt_data;
u16 enc_hdl;
@@ -4350,15 +4926,13 @@ static void leapraid_sas_enc_dev_stat_chg_evt(
evt_data = fw_evt->evt_data;
enc_hdl = le16_to_cpu(evt_data->enc_hdl);
- if (enc_hdl)
- enc_node = leapraid_enc_find_by_hdl(adapter, enc_hdl);
switch (evt_data->reason_code) {
case LEAPRAID_EVT_SAS_ENCL_RC_ADDED:
- if (!enc_node)
+ if (enc_hdl)
leapraid_sas_enc_dev_stat_add_node(adapter, enc_hdl);
break;
case LEAPRAID_EVT_SAS_ENCL_RC_NOT_RESPONDING:
- leapraid_sas_enc_dev_stat_del_node(enc_node);
+ leapraid_sas_enc_dev_stat_del_node(adapter, enc_hdl);
break;
default:
break;
@@ -4375,7 +4949,11 @@ static void leapraid_remove_unresp_sas_end_dev(
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
list_for_each_entry_safe(sas_dev, sas_dev_next,
&adapter->dev_topo.sas_dev_init_list, list) {
+ if (sas_dev->rphy || sas_dev->pend_sas_rphy_add)
+ continue;
+
list_del_init(&sas_dev->list);
+ leapraid_clear_cached_boot_dev(adapter, sas_dev, 0);
leapraid_sdev_put(sas_dev);
}
list_for_each_entry_safe(sas_dev, sas_dev_next,
@@ -4383,7 +4961,7 @@ static void leapraid_remove_unresp_sas_end_dev(
if (!sas_dev->resp)
list_move_tail(&sas_dev->list, &head);
else
- sas_dev->resp = false;
+ sas_dev->resp = 0;
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -4394,23 +4972,32 @@ static void leapraid_remove_unresp_sas_end_dev(
}
dev_info(&adapter->pdev->dev,
- "unresponding sas end devices removed\n");
+ "Unresponsive SAS end devices removed\n");
}
static void leapraid_remove_unresp_raid_volumes(
struct leapraid_adapter *adapter)
{
+ unsigned long flags;
struct leapraid_raid_volume *raid_volume, *raid_volume_next;
+ LIST_HEAD(head);
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
list_for_each_entry_safe(raid_volume, raid_volume_next,
&adapter->dev_topo.raid_volume_list, list) {
if (!raid_volume->resp)
- leapraid_sas_volume_delete(adapter, raid_volume->hdl);
+ list_move_tail(&raid_volume->list, &head);
else
- raid_volume->resp = false;
+ raid_volume->resp = 0;
+ }
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+
+ list_for_each_entry_safe(raid_volume, raid_volume_next, &head, list) {
+ leapraid_sas_volume_delete_by_ptr(adapter, raid_volume);
}
+
dev_info(&adapter->pdev->dev,
- "unresponding raid volumes removed\n");
+ "Unresponsive RAID volumes removed\n");
}
static void leapraid_remove_unresp_sas_exp(struct leapraid_adapter *adapter)
@@ -4425,7 +5012,7 @@ static void leapraid_remove_unresp_sas_exp(struct leapraid_adapter *adapter)
if (!topo_node_exp->resp)
list_move_tail(&topo_node_exp->list, &head);
else
- topo_node_exp->resp = false;
+ topo_node_exp->resp = 0;
}
spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
@@ -4434,7 +5021,7 @@ static void leapraid_remove_unresp_sas_exp(struct leapraid_adapter *adapter)
leapraid_exp_node_rm(adapter, topo_node_exp);
dev_info(&adapter->pdev->dev,
- "unresponding sas expanders removed\n");
+ "Unresponsive SAS expanders removed\n");
}
static void leapraid_remove_unresp_dev(struct leapraid_adapter *adapter)
@@ -4490,25 +5077,27 @@ static void leapraid_update_dev_qdepth(struct leapraid_adapter *adapter)
{
struct leapraid_sdev_priv *sdev_priv;
struct leapraid_sas_dev *sas_dev;
+ struct leapraid_adapter_attr *attr;
struct scsi_device *sdev;
u16 qdepth;
+ attr = &adapter->adapter_attr;
shost_for_each_device(sdev, adapter->shost) {
sdev_priv = sdev->hostdata;
if (!sdev_priv || !sdev_priv->starget_priv)
continue;
sas_dev = sdev_priv->starget_priv->sas_dev;
if (sas_dev && sas_dev->dev_info & LEAPRAID_DEVTYP_SSP_TGT)
- qdepth = (sas_dev->port_type > 1) ?
- adapter->adapter_attr.wideport_max_queue_depth :
- adapter->adapter_attr.narrowport_max_queue_depth;
+ qdepth = (sas_dev->port_connection > 1) ?
+ attr->wideport_max_queue_depth :
+ attr->narrowport_max_queue_depth;
else if (sas_dev && sas_dev->dev_info &
LEAPRAID_DEVTYP_SATA_DEV)
- qdepth = adapter->adapter_attr.sata_max_queue_depth;
+ qdepth = attr->sata_max_queue_depth;
else
continue;
- leapraid_adjust_sdev_queue_depth(sdev, qdepth);
+ leapraid_change_queue_depth(sdev, qdepth);
}
}
@@ -4524,15 +5113,17 @@ static void leapraid_update_exp_links(struct leapraid_adapter *adapter,
cfgp2.handle = hdl;
for (i = 0; i < topo_node_exp->phys_num; i++) {
cfgp1.phy_number = i;
- if ((leapraid_op_config_page(adapter, &exp_p1, cfgp1, cfgp2,
- GET_SAS_EXPANDER_PG1)))
+ if (leapraid_op_config_page(adapter, &exp_p1, cfgp1, cfgp2,
+ GET_SAS_EXPANDER_PG1))
return;
- leapraid_transport_update_links(adapter,
+ leapraid_transport_update_links(
+ adapter,
topo_node_exp->sas_address,
le16_to_cpu(exp_p1.attached_dev_hdl),
i,
- exp_p1.neg_link_rate >> 4,
+ exp_p1.neg_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT,
topo_node_exp->card_port);
}
}
@@ -4547,7 +5138,7 @@ 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");
+ dev_info(&adapter->pdev->dev, "Begin scanning expanders\n");
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
@@ -4558,7 +5149,8 @@ static void leapraid_scan_exp_after_reset(struct leapraid_adapter *adapter)
port_id = exp_p0.physical_port;
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
topo_node_exp =
- leapraid_exp_find_by_sas_address(adapter,
+ leapraid_exp_find_by_sas_address(
+ adapter,
le64_to_cpu(exp_p0.sas_address),
leapraid_get_port_by_id(adapter,
port_id,
@@ -4572,14 +5164,14 @@ static void leapraid_scan_exp_after_reset(struct leapraid_adapter *adapter)
leapraid_exp_add(adapter, hdl);
dev_info(&adapter->pdev->dev,
- "add exp: hdl=0x%04x, sas addr=0x%016llx\n",
+ "add exp: hdl=0x%04x, SAS addr=0x%016llx\n",
hdl,
(unsigned long long)le64_to_cpu(
exp_p0.sas_address));
}
}
- dev_info(&adapter->pdev->dev, "expanders scan complete\n");
+ dev_info(&adapter->pdev->dev, "Expanders scan complete\n");
}
static void leapraid_scan_phy_disks_after_reset(
@@ -4596,7 +5188,7 @@ 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");
+ 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;
@@ -4629,20 +5221,25 @@ static void leapraid_scan_phy_disks_after_reset(
LEAPRAID_SAS_NEG_LINK_RATE_1_5,
leapraid_get_port_by_id(
adapter, port_id, false));
- set_bit(hdl,
- (unsigned long *)adapter->dev_topo.pd_hdls);
-
- leapraid_add_dev(adapter, hdl);
-
- dev_info(&adapter->pdev->dev,
- "add phys disk: hdl=0x%04x, sas addr=0x%016llx\n",
- hdl,
- (unsigned long long)le64_to_cpu(
- sas_dev_p0.sas_address));
+ if (!hdl || hdl >
+ adapter->adapter_attr.features.max_dev_handle) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid device handle\n",
+ __func__);
+ } else {
+ set_bit(hdl, adapter->dev_topo.pd_hdls);
+ leapraid_add_dev(adapter, hdl);
+
+ dev_info(&adapter->pdev->dev,
+ "add pd hdl=0x%04x saddr=0x%016llx\n",
+ hdl,
+ (unsigned long long)le64_to_cpu(
+ sas_dev_p0.sas_address));
+ }
}
}
- dev_info(&adapter->pdev->dev, "phys disk scan complete\n");
+ dev_info(&adapter->pdev->dev, "PHYs disk scan complete\n");
}
static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter)
@@ -4652,10 +5249,9 @@ static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter)
union cfg_param_1 cfgp1_extra = {0};
union cfg_param_2 cfgp2_extra = {0};
struct leapraid_evt_data_ir_change evt_data;
- static struct leapraid_raid_volume *raid_volume;
+ struct leapraid_raid_volume *raid_volume;
struct leapraid_raidvol_p1 *vol_p1;
struct leapraid_raidvol_p0 *vol_p0;
- unsigned long flags;
u16 hdl;
vol_p0 = kzalloc(sizeof(*vol_p0), GFP_KERNEL);
@@ -4668,21 +5264,20 @@ static void leapraid_scan_vol_after_reset(struct leapraid_adapter *adapter)
return;
}
- dev_info(&adapter->pdev->dev, "begin scanning volumes\n");
+ 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,
cfgp2, GET_RAID_VOLUME_PG1);
cfgp2.handle = hdl) {
hdl = le16_to_cpu(vol_p1->dev_hdl);
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_wwid(
adapter,
le64_to_cpu(vol_p1->wwid));
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
- flags);
- if (raid_volume)
+ if (raid_volume) {
+ leapraid_raid_volume_put(raid_volume);
continue;
+ }
cfgp1_extra.size = sizeof(struct leapraid_raidvol_p0);
cfgp2_extra.handle = hdl;
@@ -4707,7 +5302,7 @@ 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");
+ dev_info(&adapter->pdev->dev, "Volumes scan complete\n");
}
static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter)
@@ -4721,7 +5316,7 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter)
u8 port_id;
dev_info(&adapter->pdev->dev,
- "begin scanning sas end devices\n");
+ "Begin scanning SAS end devices\n");
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
@@ -4729,6 +5324,13 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter)
GET_SAS_DEVICE_PG0);
cfgp2.handle = hdl) {
hdl = le16_to_cpu(sas_dev_p0.dev_hdl);
+ if (!hdl ||
+ hdl > adapter->adapter_attr.features.max_dev_handle) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid device handle\n", __func__);
+ continue;
+ }
+
if (!(leapraid_is_end_dev(le32_to_cpu(sas_dev_p0.dev_info))))
continue;
@@ -4759,21 +5361,21 @@ static void leapraid_scan_sas_dev_after_reset(struct leapraid_adapter *adapter)
false));
leapraid_add_dev(adapter, hdl);
dev_info(&adapter->pdev->dev,
- "add sas dev: hdl=0x%04x, sas addr=0x%016llx\n",
+ "Add SAS dev: hdl=0x%04x, saddr=0x%016llx\n",
hdl,
(unsigned long long)le64_to_cpu(
sas_dev_p0.sas_address));
}
}
- dev_info(&adapter->pdev->dev, "sas end devices scan complete\n");
+ 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");
+ dev_info(&adapter->pdev->dev, "Begin scanning devices\n");
- leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num);
+ leapraid_sas_host_add(adapter, adapter->dev_topo.card.phys_num > 0);
leapraid_scan_exp_after_reset(adapter);
if (adapter->adapter_attr.raid_support) {
leapraid_scan_phy_disks_after_reset(adapter);
@@ -4781,11 +5383,13 @@ static void leapraid_scan_all_dev_after_reset(struct leapraid_adapter *adapter)
}
leapraid_scan_sas_dev_after_reset(adapter);
- dev_info(&adapter->pdev->dev, "devices scan complete\n");
+ dev_info(&adapter->pdev->dev, "Devices scan complete\n");
}
static void leapraid_hardreset_async_logic(struct leapraid_adapter *adapter)
{
+ unsigned long flags;
+
leapraid_remove_unresp_dev(adapter);
leapraid_del_dirty_vphy(adapter);
leapraid_del_dirty_card_port(adapter);
@@ -4794,6 +5398,10 @@ static void leapraid_hardreset_async_logic(struct leapraid_adapter *adapter)
if (adapter->scan_dev_desc.driver_loading)
leapraid_scan_dev_done(adapter);
+ spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
+ adapter->access_ctrl.shost_recover_async = 0;
+ spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
+ wake_up(&adapter->access_ctrl.shost_recover_wq);
}
static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter,
@@ -4802,15 +5410,17 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter,
{
void *req;
bool reset_flg = false;
- int rc = 0;
+ int rc;
mutex_lock(&adapter->driver_cmds.enc_cmd.mutex);
- rc = leapraid_check_adapter_is_op(adapter);
+ rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
+ __func__);
if (rc)
- goto out;
+ goto unlock;
adapter->driver_cmds.enc_cmd.status = LEAPRAID_CMD_PENDING;
- req = leapraid_get_task_desc(adapter,
+ req = leapraid_get_task_desc(
+ adapter,
adapter->driver_cmds.enc_cmd.inter_taskid);
memset(req, 0, LEAPRAID_REQUEST_SIZE);
memcpy(req, sep_req, sizeof(struct leapraid_sep_req));
@@ -4820,6 +5430,10 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter,
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);
reset_flg =
leapraid_check_reset(
adapter->driver_cmds.enc_cmd.status);
@@ -4828,17 +5442,17 @@ static int leapraid_send_enc_cmd(struct leapraid_adapter *adapter,
}
if (adapter->driver_cmds.enc_cmd.status & LEAPRAID_CMD_REPLY_VALID)
- memcpy(sep_rep, (void *)(&adapter->driver_cmds.enc_cmd.reply),
+ memcpy(sep_rep, &adapter->driver_cmds.enc_cmd.reply,
sizeof(struct leapraid_sep_rep));
do_hard_reset:
if (reset_flg) {
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
leapraid_hard_reset_handler(adapter, FULL_RESET);
}
adapter->driver_cmds.enc_cmd.status = LEAPRAID_CMD_NOT_USED;
-out:
+unlock:
mutex_unlock(&adapter->driver_cmds.enc_cmd.mutex);
return rc;
}
@@ -4857,8 +5471,9 @@ static void leapraid_set_led(struct leapraid_adapter *adapter,
sep_req.func = LEAPRAID_FUNC_SCSI_ENC_PROCESSOR;
sep_req.act = LEAPRAID_SEP_REQ_ACT_WRITE_STATUS;
if (on) {
- sep_req.slot_status =
- cpu_to_le32(LEAPRAID_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
+ u32 status = LEAPRAID_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT;
+
+ sep_req.slot_status = cpu_to_le32(status);
sep_req.dev_hdl = cpu_to_le16(sas_dev->hdl);
sep_req.flg = LEAPRAID_SEP_REQ_FLG_DEVHDL_ADDRESS;
if (leapraid_send_enc_cmd(adapter, &sep_rep, &sep_req)) {
@@ -4866,52 +5481,75 @@ static void leapraid_set_led(struct leapraid_adapter *adapter,
return;
}
- sas_dev->led_on = true;
- if (sep_rep.adapter_status)
- leapraid_sdev_put(sas_dev);
+ sas_dev->led_on = 1;
+ leapraid_sdev_put(sas_dev);
} else {
sep_req.slot_status = 0;
sep_req.slot = cpu_to_le16(sas_dev->slot);
sep_req.dev_hdl = 0;
sep_req.enc_hdl = cpu_to_le16(sas_dev->enc_hdl);
sep_req.flg = LEAPRAID_SEP_REQ_FLG_ENCLOSURE_SLOT_ADDRESS;
- if ((leapraid_send_enc_cmd(adapter, &sep_rep, &sep_req))) {
- leapraid_sdev_put(sas_dev);
- return;
- }
+ leapraid_send_enc_cmd(adapter, &sep_rep, &sep_req);
+ }
+}
- if (sep_rep.adapter_status) {
- leapraid_sdev_put(sas_dev);
- return;
+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) {
+ spin_lock_irqsave(
+ &adapter->reset_desc.adapter_reset_lock,
+ flags);
+ adapter->access_ctrl.shost_recover_async = 0;
+ spin_unlock_irqrestore(
+ &adapter->reset_desc.adapter_reset_lock,
+ flags);
+
+ wake_up(&adapter->access_ctrl.shost_recover_wq);
+
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed, shost %d, host %d\n",
+ __func__,
+ adapter->access_ctrl.shost_recovering,
+ adapter->access_ctrl.host_removing);
+
+ 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));
}
+ return 0;
}
static void leapraid_fw_work(struct leapraid_adapter *adapter,
struct leapraid_fw_evt_work *fw_evt)
{
struct leapraid_sas_dev *sas_dev;
+ unsigned long flags;
+ spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
adapter->fw_evt_s.cur_evt = fw_evt;
+ adapter->fw_evt_s.cur_evt_task = current;
+ spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
leapraid_del_fw_evt_from_list(adapter, fw_evt);
if (adapter->access_ctrl.host_removing ||
adapter->access_ctrl.pcie_recovering) {
+ spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
leapraid_fw_evt_put(fw_evt);
adapter->fw_evt_s.cur_evt = NULL;
+ adapter->fw_evt_s.cur_evt_task = NULL;
+ spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
return;
}
switch (fw_evt->evt_type) {
- case LEAPRAID_EVT_SAS_DISCOVERY:
- {
- struct leapraid_evt_data_sas_disc *evt_data;
-
- evt_data = fw_evt->evt_data;
- if (evt_data->reason_code ==
- LEAPRAID_EVT_SAS_DISC_RC_STARTED &&
- !adapter->dev_topo.card.phys_num)
- leapraid_sas_host_add(adapter, 0);
- break;
- }
case LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST:
leapraid_sas_topo_chg_evt(adapter, fw_evt);
break;
@@ -4922,14 +5560,9 @@ static void leapraid_fw_work(struct leapraid_adapter *adapter,
leapraid_sas_enc_dev_stat_chg_evt(adapter, fw_evt);
break;
case LEAPRAID_EVT_REMOVE_DEAD_DEV:
- 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)
- goto out;
+ if (leapraid_wait_adapter_recovery(adapter))
+ goto out_cleanup;
- ssleep(1);
- }
leapraid_hardreset_async_logic(adapter);
break;
case LEAPRAID_EVT_TURN_ON_PFA_LED:
@@ -4938,14 +5571,17 @@ static void leapraid_fw_work(struct leapraid_adapter *adapter,
leapraid_set_led(adapter, sas_dev, true);
break;
case LEAPRAID_EVT_SCAN_DEV_DONE:
- adapter->scan_dev_desc.scan_start = false;
+ adapter->scan_dev_desc.scan_start = 0;
break;
default:
break;
}
-out:
+out_cleanup:
+ spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
leapraid_fw_evt_put(fw_evt);
adapter->fw_evt_s.cur_evt = NULL;
+ adapter->fw_evt_s.cur_evt_task = NULL;
+ spin_unlock_irqrestore(&adapter->fw_evt_s.fw_evt_lock, flags);
}
static void leapraid_sas_dev_stat_chg_evt(
@@ -4953,7 +5589,7 @@ static void leapraid_sas_dev_stat_chg_evt(
struct leapraid_evt_data_sas_dev_status_change *event_data)
{
struct leapraid_starget_priv *starget_priv;
- struct leapraid_sas_dev *sas_dev = NULL;
+ struct leapraid_sas_dev *sas_dev;
u64 sas_address;
unsigned long flags;
@@ -4968,26 +5604,29 @@ static void leapraid_sas_dev_stat_chg_evt(
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
sas_address = le64_to_cpu(event_data->sas_address);
- sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter,
+ sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(
+ adapter,
sas_address,
leapraid_get_port_by_id(adapter,
event_data->physical_port,
false));
- if (sas_dev && sas_dev->starget) {
- starget_priv = sas_dev->starget->hostdata;
- if (starget_priv) {
- switch (event_data->reason_code) {
- case LEAPRAID_EVT_SAS_DEV_STAT_RC_INTERNAL_DEV_RESET:
- starget_priv->tm_busy = true;
- break;
- case LEAPRAID_EVT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
- starget_priv->tm_busy = false;
- break;
- }
+ if (!sas_dev || !sas_dev->starget)
+ goto out_unlock;
+
+ starget_priv = sas_dev->starget->hostdata;
+ if (starget_priv) {
+ switch (event_data->reason_code) {
+ case LEAPRAID_EVT_SAS_DEV_STAT_RC_INTERNAL_DEV_RESET:
+ starget_priv->tm_busy = 1;
+ break;
+ case LEAPRAID_EVT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
+ starget_priv->tm_busy = 0;
+ break;
}
}
+out_unlock:
if (sas_dev)
leapraid_sdev_put(sas_dev);
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -5000,32 +5639,45 @@ static void leapraid_set_volume_delete_flag(struct leapraid_adapter *adapter,
struct leapraid_starget_priv *sas_target_priv_data;
unsigned long flags;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_hdl(adapter, handle);
- if (raid_volume && raid_volume->starget &&
- raid_volume->starget->hostdata) {
- sas_target_priv_data = raid_volume->starget->hostdata;
- sas_target_priv_data->deleted = true;
+ if (raid_volume) {
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ if (raid_volume->starget &&
+ raid_volume->starget->hostdata) {
+ sas_target_priv_data = raid_volume->starget->hostdata;
+ sas_target_priv_data->deleted = 1;
+ }
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
+ flags);
+ leapraid_raid_volume_put(raid_volume);
}
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
}
-static void leapraid_check_ir_change_evt(struct leapraid_adapter *adapter,
+static void leapraid_check_ir_change_evt(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_ir_change *evt_data)
{
u16 phys_disk_dev_hdl;
switch (evt_data->reason_code) {
case LEAPRAID_EVT_IR_RC_VOLUME_DELETE:
- leapraid_set_volume_delete_flag(adapter,
- le16_to_cpu(evt_data->vol_dev_hdl));
+ leapraid_set_volume_delete_flag(
+ adapter,
+ le16_to_cpu(evt_data->vol_dev_hdl));
break;
case LEAPRAID_EVT_IR_RC_PD_UNHIDDEN_TO_DELETE:
phys_disk_dev_hdl =
le16_to_cpu(evt_data->phys_disk_dev_hdl);
- clear_bit(phys_disk_dev_hdl,
- (unsigned long *)adapter->dev_topo.pd_hdls);
- leapraid_tgt_rst_send(adapter, phys_disk_dev_hdl);
+ if (!phys_disk_dev_hdl ||
+ phys_disk_dev_hdl >
+ adapter->adapter_attr.features.max_dev_handle) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid device handle\n", __func__);
+ } else {
+ clear_bit(phys_disk_dev_hdl,
+ adapter->dev_topo.pd_hdls);
+ leapraid_tgt_rst_send(adapter, phys_disk_dev_hdl);
+ }
break;
}
}
@@ -5035,7 +5687,7 @@ static void leapraid_topo_del_evts_process_exp_status(
struct leapraid_evt_data_sas_topo_change_list *evt_data)
{
struct leapraid_fw_evt_work *fw_evt = NULL;
- struct leapraid_evt_data_sas_topo_change_list *loc_evt_data = NULL;
+ struct leapraid_evt_data_sas_topo_change_list *loc_evt_data;
unsigned long flags;
u16 exp_hdl;
@@ -5066,7 +5718,8 @@ static void leapraid_topo_del_evts_process_exp_status(
}
}
-static void leapraid_check_topo_del_evts(struct leapraid_adapter *adapter,
+static void leapraid_check_topo_del_evts(
+ struct leapraid_adapter *adapter,
struct leapraid_evt_data_sas_topo_change_list *evt_data)
{
int reason_code;
@@ -5096,17 +5749,20 @@ static bool leapraid_async_process_evt(
switch (evt) {
case LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE:
- leapraid_sas_dev_stat_chg_evt(adapter,
+ leapraid_sas_dev_stat_chg_evt(
+ adapter,
(struct leapraid_evt_data_sas_dev_status_change
*)event_notify_rep->evt_data);
break;
case LEAPRAID_EVT_IR_CHANGE:
- leapraid_check_ir_change_evt(adapter,
+ leapraid_check_ir_change_evt(
+ adapter,
(struct leapraid_evt_data_ir_change
*)event_notify_rep->evt_data);
break;
case LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST:
- leapraid_check_topo_del_evts(adapter,
+ leapraid_check_topo_del_evts(
+ adapter,
(struct leapraid_evt_data_sas_topo_change_list
*)event_notify_rep->evt_data);
if (adapter->access_ctrl.shost_recovering) {
@@ -5114,7 +5770,6 @@ static bool leapraid_async_process_evt(
return exit_flag;
}
break;
- case LEAPRAID_EVT_SAS_DISCOVERY:
case LEAPRAID_EVT_SAS_ENCL_DEV_STATUS_CHANGE:
break;
default:
@@ -5136,7 +5791,7 @@ static void leapraid_async_evt_cb_enqueue(
if (!fw_evt)
return;
- evt_sz = le16_to_cpu(evt_notify_rep->evt_data_len) * 4;
+ evt_sz = le16_to_cpu(evt_notify_rep->evt_data_len) * sizeof(u32);
fw_evt->evt_data = kmemdup(evt_notify_rep->evt_data,
evt_sz, GFP_ATOMIC);
if (!fw_evt->evt_data) {
@@ -5225,13 +5880,63 @@ static void leapraid_scan_dev_complete(struct leapraid_adapter *adapter)
leapraid_fw_evt_put(fw_evt);
}
-static u8 leapraid_driver_cmds_done(struct leapraid_adapter *adapter,
- u16 taskid, u8 msix_index,
- u32 rep_paddr, u8 cb_idx)
+static u8 leapraid_handle_scan_cb(struct leapraid_adapter *adapter,
+ struct leapraid_driver_cmd *cmd,
+ struct leapraid_rep *rep)
+{
+ u16 status;
+
+ cmd->status &= ~LEAPRAID_CMD_PENDING;
+
+ 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;
+ }
+
+ 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,
+ struct leapraid_rep *rep,
+ u16 taskid)
+{
+ struct leapraid_scsiio_rep *scsiio_reply;
+
+ if (rep->function != LEAPRAID_FUNC_SCSIIO &&
+ rep->function != LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH)
+ return;
+
+ scsiio_reply = (struct leapraid_scsiio_rep *)rep;
+
+ if (!(scsiio_reply->scsi_state &
+ LEAPRAID_SCSI_STATE_AUTOSENSE_VALID))
+ return;
+
+ memcpy(&adapter->driver_cmds.ctl_cmd.sense,
+ leapraid_get_sense_buffer(adapter, taskid),
+ min_t(u32, SCSI_SENSE_BUFFERSIZE,
+ le32_to_cpu(scsiio_reply->sense_count)));
+}
+
+static bool leapraid_driver_cmds_done(struct leapraid_adapter *adapter,
+ u16 taskid, u8 msix_index,
+ u32 rep_paddr, u8 cb_idx)
{
struct leapraid_rep *leap_mpi_rep =
leapraid_get_reply_vaddr(adapter, rep_paddr);
struct leapraid_driver_cmd *sp_cmd, *_sp_cmd = NULL;
+ u8 reply_len;
list_for_each_entry(sp_cmd, &adapter->driver_cmds.special_cmd_list,
list)
@@ -5241,74 +5946,55 @@ static u8 leapraid_driver_cmds_done(struct leapraid_adapter *adapter,
}
if (WARN_ON(!_sp_cmd))
- return 1;
+ return true;
if (WARN_ON(_sp_cmd->status == LEAPRAID_CMD_NOT_USED))
- return 1;
+ return true;
if (WARN_ON(taskid != _sp_cmd->hp_taskid &&
taskid != _sp_cmd->taskid &&
taskid != _sp_cmd->inter_taskid))
- return 1;
-
+ return true;
_sp_cmd->status |= LEAPRAID_CMD_DONE;
if (leap_mpi_rep) {
- memcpy((void *)(&_sp_cmd->reply), leap_mpi_rep,
- leap_mpi_rep->msg_len * 4);
+ reply_len = leap_mpi_rep->msg_len * sizeof(u32);
+ if (reply_len > LEAPRAID_REPLY_SIZE)
+ reply_len = LEAPRAID_REPLY_SIZE;
+ 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) {
- u16 adapter_status;
-
- _sp_cmd->status &= ~LEAPRAID_CMD_PENDING;
- adapter_status =
- le16_to_cpu(leap_mpi_rep->adapter_status) &
- LEAPRAID_ADAPTER_STATUS_MASK;
- if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS)
- adapter->scan_dev_desc.scan_dev_failed = true;
-
- if (_sp_cmd->async_scan_dev) {
- if (adapter_status ==
- LEAPRAID_ADAPTER_STATUS_SUCCESS) {
- leapraid_scan_dev_complete(adapter);
- } else {
- adapter->scan_dev_desc.scan_start_failed =
- adapter_status;
- }
- return 1;
- }
-
- complete(&_sp_cmd->done);
- return 1;
- }
+ 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_CTL_CB_IDX) {
- struct leapraid_scsiio_rep *scsiio_reply;
-
- if (leap_mpi_rep->function ==
- LEAPRAID_FUNC_SCSIIO_REQ ||
- leap_mpi_rep->function ==
- LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH) {
- scsiio_reply =
- (struct leapraid_scsiio_rep *)leap_mpi_rep;
- if (scsiio_reply->scsi_state &
- LEAPRAID_SCSI_STATE_AUTOSENSE_VALID)
- memcpy((void *)(&adapter->driver_cmds.ctl_cmd.sense),
- leapraid_get_sense_buffer(adapter, taskid),
- min_t(u32,
- SCSI_SENSE_BUFFERSIZE,
- le32_to_cpu(scsiio_reply->sense_count)));
- }
- }
+ if (_sp_cmd->cb_idx == LEAPRAID_CTL_CB_IDX)
+ leapraid_handle_ctl_cb(adapter, leap_mpi_rep, taskid);
}
_sp_cmd->status &= ~LEAPRAID_CMD_PENDING;
complete(&_sp_cmd->done);
- return 1;
+ return true;
}
-static void leapraid_request_descript_handler(struct leapraid_adapter *adapter,
- union leapraid_rep_desc_union *rpf,
- u8 req_desc_type, u8 msix_idx)
+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) {
+ if (leapraid_scsiio_done(adapter, taskid, msix_idx, rep))
+ leapraid_free_taskid(adapter, taskid);
+ return;
+ }
+
+ if (leapraid_driver_cmds_done(adapter, taskid, msix_idx, rep,
+ leapraid_get_cb_idx(adapter, taskid)))
+ leapraid_free_taskid(adapter, taskid);
+}
+
+static void leapraid_request_descript_handler(
+ struct leapraid_adapter *adapter,
+ union leapraid_rep_desc_union *rpf,
+ u8 req_desc_type, u8 msix_idx)
{
u32 rep;
u16 taskid;
@@ -5318,50 +6004,34 @@ static void leapraid_request_descript_handler(struct leapraid_adapter *adapter,
switch (req_desc_type) {
case LEAPRAID_RPY_DESC_FLG_FP_SCSI_IO_SUCCESS:
case LEAPRAID_RPY_DESC_FLG_SCSI_IO_SUCCESS:
- if (taskid <= adapter->shost->can_queue ||
- taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid) {
- leapraid_scsiio_done(adapter, taskid, msix_idx, 0);
- } else {
- if (leapraid_driver_cmds_done(adapter, taskid,
- msix_idx, 0,
- leapraid_get_cb_idx(adapter,
- taskid)))
- leapraid_free_taskid(adapter, taskid);
- }
+ leapraid_complete_task(adapter, taskid, msix_idx, 0);
break;
case LEAPRAID_RPY_DESC_FLG_ADDRESS_REPLY:
rep = le32_to_cpu(rpf->addr_rep.rep_frame_addr);
- if (rep > ((u32)adapter->mem_desc.rep_msg_dma +
- adapter->adapter_attr.rep_msg_qd * LEAPRAID_REPLY_SIEZ) ||
- rep < ((u32)adapter->mem_desc.rep_msg_dma))
+ if (rep > (u32)adapter->mem_desc.rep_msg_dma +
+ adapter->adapter_attr.rep_msg_qd *
+ LEAPRAID_REPLY_SIZE ||
+ rep < (u32)adapter->mem_desc.rep_msg_dma)
rep = 0;
- if (taskid) {
- if (taskid <= adapter->shost->can_queue ||
- taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid) {
- leapraid_scsiio_done(adapter, taskid,
- msix_idx, rep);
- } else {
- if (leapraid_driver_cmds_done(adapter, taskid,
- msix_idx, rep,
- leapraid_get_cb_idx(adapter,
- taskid)))
- leapraid_free_taskid(adapter, taskid);
- }
- } else {
+
+ if (taskid)
+ leapraid_complete_task(adapter, taskid, msix_idx, rep);
+ else
leapraid_handle_async_event(adapter, msix_idx, rep);
- }
- if (rep) {
- adapter->rep_msg_host_idx =
- (adapter->rep_msg_host_idx ==
- (adapter->adapter_attr.rep_msg_qd - 1)) ?
- 0 : adapter->rep_msg_host_idx + 1;
- adapter->mem_desc.rep_msg_addr[adapter->rep_msg_host_idx] =
- cpu_to_le32(rep);
- wmb(); /* Make sure that all write ops are in order */
- writel(adapter->rep_msg_host_idx,
- &adapter->iomem_base->rep_msg_host_idx);
- }
+ if (!rep)
+ return;
+
+ adapter->rep_msg_host_idx =
+ (adapter->rep_msg_host_idx ==
+ (adapter->adapter_attr.rep_msg_qd - 1)) ?
+ 0 : adapter->rep_msg_host_idx + 1;
+ adapter->mem_desc.rep_msg_addr[adapter->rep_msg_host_idx] =
+ cpu_to_le32(rep);
+ wmb(); /* Make sure that all write ops are in order */
+ writel(adapter->rep_msg_host_idx,
+ &adapter->iomem_base->rep_msg_host_idx);
+
break;
default:
break;
@@ -5423,8 +6093,8 @@ int leapraid_rep_queue_handler(struct leapraid_rq *rq)
wmb(); /* Make sure that all write ops are in order */
writel(rq->rep_post_host_idx | ((msix_idx & LEAPRAID_MSIX_GROUP_MASK) <<
LEAPRAID_RPHI_MSIX_IDX_SHIFT),
- &adapter->iomem_base->rep_post_reg_idx[msix_idx /
- LEAPRAID_MSIX_GROUP_SIZE].idx);
+ &adapter->iomem_base->rep_post_reg_idx[
+ msix_idx / LEAPRAID_MSIX_GROUP_SIZE].idx);
atomic_dec(&rq->busy);
return finish_cmds;
}
@@ -5441,7 +6111,7 @@ static irqreturn_t leapraid_irq_handler(int irq, void *bus_id)
if (adapter->mask_int)
return IRQ_NONE;
- return ((leapraid_rep_queue_handler(rq) > 0) ?
+ return (leapraid_rep_queue_handler(rq) > 0 ?
IRQ_HANDLED : IRQ_NONE);
}
@@ -5469,7 +6139,8 @@ void leapraid_sync_irqs(struct leapraid_adapter *adapter, bool poll)
if (int_rq->rq.msix_idx == 0)
continue;
- synchronize_irq(pci_irq_vector(adapter->pdev, int_rq->rq.msix_idx));
+ synchronize_irq(pci_irq_vector(adapter->pdev,
+ int_rq->rq.msix_idx));
if (poll)
leapraid_rep_queue_handler(&int_rq->rq);
}
@@ -5491,16 +6162,18 @@ void leapraid_sync_irqs(struct leapraid_adapter *adapter, bool poll)
void leapraid_mq_polling_pause(struct leapraid_adapter *adapter)
{
- int iopoll_q_count =
- adapter->adapter_attr.rq_cnt -
- adapter->notification_desc.iopoll_qdex;
+ struct leapraid_notification_desc *desc;
+ int iopoll_q_count;
int qid;
+ desc = &adapter->notification_desc;
+ iopoll_q_count = adapter->adapter_attr.rq_cnt - desc->iopoll_qdex;
+
for (qid = 0; qid < iopoll_q_count; qid++)
- atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[qid].pause, 1);
+ atomic_set(&desc->blk_mq_poll_rqs[qid].pause, 1);
for (qid = 0; qid < iopoll_q_count; qid++) {
- while (atomic_read(&adapter->notification_desc.blk_mq_poll_rqs[qid].busy)) {
+ while (atomic_read(&desc->blk_mq_poll_rqs[qid].busy)) {
cpu_relax();
udelay(LEAPRAID_IO_POLL_DELAY_US);
}
@@ -5509,19 +6182,30 @@ void leapraid_mq_polling_pause(struct leapraid_adapter *adapter)
void leapraid_mq_polling_resume(struct leapraid_adapter *adapter)
{
- int iopoll_q_count =
- adapter->adapter_attr.rq_cnt -
- adapter->notification_desc.iopoll_qdex;
+ struct leapraid_notification_desc *desc;
+ int iopoll_q_count;
int qid;
+ desc = &adapter->notification_desc;
+ iopoll_q_count = adapter->adapter_attr.rq_cnt - desc->iopoll_qdex;
+
for (qid = 0; qid < iopoll_q_count; qid++)
- atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[qid].pause, 0);
+ atomic_set(&desc->blk_mq_poll_rqs[qid].pause, 0);
}
static int leapraid_unlock_host_diag(struct leapraid_adapter *adapter,
u32 *host_diag)
{
- const u32 unlock_seq[] = { 0x0, 0xF, 0x4, 0xB, 0x2, 0x7, 0xD };
+ const u32 unlock_seq[] = {
+ LEAPRAID_WRSEQ_FLUSH_KEY_VALUE,
+ LEAPRAID_WRSEQ_1ST_KEY_VALUE,
+ LEAPRAID_WRSEQ_2ND_KEY_VALUE,
+ LEAPRAID_WRSEQ_3RD_KEY_VALUE,
+ LEAPRAID_WRSEQ_4TH_KEY_VALUE,
+ LEAPRAID_WRSEQ_5TH_KEY_VALUE,
+ LEAPRAID_WRSEQ_6TH_KEY_VALUE
+ };
+
const int max_retries = LEAPRAID_UNLOCK_RETRY_LIMIT;
int retry = 0;
unsigned int i;
@@ -5538,51 +6222,46 @@ static int leapraid_unlock_host_diag(struct leapraid_adapter *adapter,
return 0;
}
- dev_err(&adapter->pdev->dev, "try host reset timeout!\n");
+ dev_err(&adapter->pdev->dev, "Try host reset timeout!\n");
return -EFAULT;
}
static int leapraid_host_diag_reset(struct leapraid_adapter *adapter)
{
u32 host_diag;
- u32 cnt;
- dev_info(&adapter->pdev->dev, "entering host diag reset!\n");
+ dev_info(&adapter->pdev->dev, "Entering host diag reset!\n");
pci_cfg_access_lock(adapter->pdev);
mutex_lock(&adapter->reset_desc.host_diag_mutex);
if (leapraid_unlock_host_diag(adapter, &host_diag))
- goto out;
+ goto out_cleanup;
writel(host_diag | LEAPRAID_DIAG_RESET,
&adapter->iomem_base->host_diag);
+ msleep(LEAPRAID_MSLEEP_EXTRA_LONG_MS);
msleep(LEAPRAID_MSLEEP_NORMAL_MS);
- for (cnt = 0; cnt < LEAPRAID_RESET_LOOP_COUNT_DEFAULT; cnt++) {
- host_diag = leapraid_readl(&adapter->iomem_base->host_diag);
- if (host_diag == LEAPRAID_INVALID_HOST_DIAG_VAL)
- goto out;
-
- if (!(host_diag & LEAPRAID_DIAG_RESET))
- break;
- msleep(LEAPRAID_RESET_POLL_INTERVAL_MS);
- }
+ host_diag = leapraid_readl(&adapter->iomem_base->host_diag);
+ if (host_diag == LEAPRAID_INVALID_HOST_DIAG_VAL ||
+ host_diag & LEAPRAID_DIAG_RESET)
+ goto out_cleanup;
- writel(host_diag & ~LEAPRAID_DIAG_HOLD_ADAPTER_RESET,
- &adapter->iomem_base->host_diag);
writel(0x0, &adapter->iomem_base->ws);
mutex_unlock(&adapter->reset_desc.host_diag_mutex);
if (!leapraid_wait_adapter_ready(adapter))
- goto out;
+ goto out_failed;
pci_cfg_access_unlock(adapter->pdev);
- dev_info(&adapter->pdev->dev, "host diag success!\n");
+ dev_info(&adapter->pdev->dev, "Host diag success!\n");
return 0;
-out:
- pci_cfg_access_unlock(adapter->pdev);
- dev_info(&adapter->pdev->dev, "host diag failed!\n");
+
+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");
return -EFAULT;
}
@@ -5592,12 +6271,12 @@ static int leapraid_find_matching_port(
{
int i;
- for (i = 0; i < count; i++) {
+ for (i = 0; i < count; i++)
if (card_port_table[i].port_id == port_id &&
card_port_table[i].sas_address == sas_addr)
return i;
- }
- return -1;
+
+ return LEAPRAID_INVALID_INDEX;
}
static u8 leapraid_fill_card_port_table(
@@ -5611,12 +6290,13 @@ static u8 leapraid_fill_card_port_table(
int i, idx;
for (i = 0; i < adapter->dev_topo.card.phys_num; i++) {
- if ((sas_iounit_p0->phy_info[i].neg_link_rate >> 4)
- < LEAPRAID_SAS_NEG_LINK_RATE_1_5)
+ if (sas_iounit_p0->phy_info[i].neg_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT <
+ LEAPRAID_SAS_NEG_LINK_RATE_1_5)
continue;
- attached_hdl =
- le16_to_cpu(sas_iounit_p0->phy_info[i].attached_dev_hdl);
+ attached_hdl = le16_to_cpu(sas_iounit_p0->phy_info[i]
+ .attached_dev_hdl);
if (leapraid_get_sas_address(adapter,
attached_hdl,
&attached_sas_addr) != 0)
@@ -5648,7 +6328,7 @@ static u8 leapraid_set_new_card_port_table_after_reset(
{
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- struct leapraid_sas_io_unit_p0 *sas_iounit_p0 = NULL;
+ struct leapraid_sas_io_unit_p0 *sas_iounit_p0;
u8 port_entry_num = 0;
u16 sz;
@@ -5660,14 +6340,14 @@ static u8 leapraid_set_new_card_port_table_after_reset(
return port_entry_num;
cfgp1.size = sz;
- if ((leapraid_op_config_page(adapter, sas_iounit_p0, cfgp1, cfgp2,
- GET_SAS_IOUNIT_PG0)) != 0)
- goto out;
+ if (leapraid_op_config_page(adapter, sas_iounit_p0, cfgp1, cfgp2,
+ GET_SAS_IOUNIT_PG0) != 0)
+ goto out_free;
port_entry_num = leapraid_fill_card_port_table(adapter,
sas_iounit_p0,
new_card_port_table);
-out:
+out_free:
kfree(sas_iounit_p0);
return port_entry_num;
}
@@ -5676,9 +6356,9 @@ static void leapraid_update_existing_port(struct leapraid_adapter *adapter,
struct leapraid_card_port *new_table,
int entry_idx, int port_entry_num)
{
- struct leapraid_card_port *matched_card_port = NULL;
+ struct leapraid_card_port *matched_card_port;
int matched_code;
- int count = 0, lcount = 0;
+ int count, lcount = 0;
u64 sas_addr;
int i;
@@ -5699,10 +6379,10 @@ static void leapraid_update_existing_port(struct leapraid_adapter *adapter,
port_entry_num);
} else if (matched_code == SAME_ADDR_ONLY) {
sas_addr = new_table[entry_idx].sas_address;
- for (i = 0; i < port_entry_num; i++) {
+ for (i = 0; i < port_entry_num; i++)
if (new_table[i].sas_address == sas_addr)
lcount++;
- }
+
if (count > 1 || lcount > 1)
return;
@@ -5724,15 +6404,24 @@ static void leapraid_update_card_port_after_reset(
struct leapraid_adapter *adapter)
{
struct leapraid_card_port *new_card_port_table;
- struct leapraid_card_port *matched_card_port = NULL;
- u8 port_entry_num = 0;
+ struct leapraid_card_port *matched_card_port;
+ u8 port_entry_num;
u8 nr_phys;
int i;
if (leapraid_get_adapter_phys(adapter, &nr_phys) || !nr_phys)
return;
+ if (!adapter->dev_topo.card.card_phy) {
+ adapter->dev_topo.card.card_phy =
+ kcalloc(nr_phys, sizeof(struct leapraid_card_phy),
+ GFP_KERNEL);
+ if (!adapter->dev_topo.card.card_phy)
+ return;
+ }
+
adapter->dev_topo.card.phys_num = nr_phys;
+
new_card_port_table = kcalloc(adapter->dev_topo.card.phys_num,
sizeof(struct leapraid_card_port),
GFP_KERNEL);
@@ -5740,21 +6429,23 @@ static void leapraid_update_card_port_after_reset(
return;
port_entry_num =
- leapraid_set_new_card_port_table_after_reset(adapter,
- new_card_port_table);
+ leapraid_set_new_card_port_table_after_reset(
+ adapter,
+ new_card_port_table);
if (!port_entry_num)
- return;
+ goto out_free_port_table;
list_for_each_entry(matched_card_port,
- &adapter->dev_topo.card_port_list, list) {
+ &adapter->dev_topo.card_port_list, list)
matched_card_port->flg |= LEAPRAID_CARD_PORT_FLG_DIRTY;
- }
matched_card_port = NULL;
for (i = 0; i < port_entry_num; i++)
leapraid_update_existing_port(adapter,
new_card_port_table,
i, port_entry_num);
+out_free_port_table:
+ kfree(new_card_port_table);
}
static bool leapraid_is_valid_vphy(
@@ -5765,13 +6456,16 @@ static bool leapraid_is_valid_vphy(
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
struct leapraid_sas_phy_p0 phy_p0;
+ u32 dev_info;
- if ((sas_io_unit_p0->phy_info[phy_index].neg_link_rate >> 4) <
+ if (sas_io_unit_p0->phy_info[phy_index].neg_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT <
LEAPRAID_SAS_NEG_LINK_RATE_1_5)
return false;
- if (!(le32_to_cpu(sas_io_unit_p0->phy_info[phy_index].controller_phy_dev_info) &
- LEAPRAID_DEVTYP_SEP))
+ dev_info = le32_to_cpu(sas_io_unit_p0->phy_info[phy_index]
+ .controller_phy_dev_info);
+ if (!(dev_info & LEAPRAID_DEVTYP_SEP))
return false;
cfgp1.phy_number = phy_index;
@@ -5804,7 +6498,7 @@ static void leapraid_update_vphy_binding(struct leapraid_adapter *adapter,
return;
may_new_card_port->port_id = may_new_port_id;
dev_err(&adapter->pdev->dev,
- "%s: new card port %p added, port=%d\n",
+ "%s: New card port %p added, port=%d\n",
__func__, may_new_card_port, may_new_port_id);
list_add_tail(&may_new_card_port->list,
&adapter->dev_topo.card_port_list);
@@ -5820,8 +6514,10 @@ static void leapraid_update_vphy_binding(struct leapraid_adapter *adapter,
sas_dev = leapraid_get_sas_dev_by_addr(adapter,
attached_sas_addr,
card_port);
- if (sas_dev)
+ if (sas_dev) {
sas_dev->card_port = may_new_card_port;
+ leapraid_sdev_put(sas_dev);
+ }
}
if (may_new_card_port->flg & LEAPRAID_CARD_PORT_FLG_DIRTY) {
@@ -5836,7 +6532,7 @@ static void leapraid_update_vphys_after_reset(struct leapraid_adapter *adapter)
{
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- struct leapraid_sas_io_unit_p0 *sas_iounit_p0 = NULL;
+ struct leapraid_sas_io_unit_p0 *sas_iounit_p0;
struct leapraid_card_port *card_port, *card_port_next;
struct leapraid_vphy *vphy, *vphy_next;
u64 attached_sas_addr;
@@ -5852,9 +6548,8 @@ static void leapraid_update_vphys_after_reset(struct leapraid_adapter *adapter)
continue;
list_for_each_entry_safe(vphy, vphy_next,
- &card_port->vphys_list, list) {
+ &card_port->vphys_list, list)
vphy->flg |= LEAPRAID_VPHY_FLG_DIRTY;
- }
}
sz = offsetof(struct leapraid_sas_io_unit_p0, phy_info) +
@@ -5865,16 +6560,17 @@ static void leapraid_update_vphys_after_reset(struct leapraid_adapter *adapter)
return;
cfgp1.size = sz;
- if ((leapraid_op_config_page(adapter, sas_iounit_p0, cfgp1, cfgp2,
- GET_SAS_IOUNIT_PG0)) != 0)
- goto out;
+ if (leapraid_op_config_page(adapter, sas_iounit_p0, cfgp1, cfgp2,
+ GET_SAS_IOUNIT_PG0) != 0)
+ goto out_free;
for (i = 0; i < adapter->dev_topo.card.phys_num; i++) {
if (!leapraid_is_valid_vphy(adapter, sas_iounit_p0, i))
continue;
attached_hdl =
- le16_to_cpu(sas_iounit_p0->phy_info[i].attached_dev_hdl);
+ le16_to_cpu(sas_iounit_p0->phy_info[i]
+ .attached_dev_hdl);
if (leapraid_get_sas_address(adapter, attached_hdl,
&attached_sas_addr) != 0)
continue;
@@ -5916,7 +6612,7 @@ static void leapraid_update_vphys_after_reset(struct leapraid_adapter *adapter)
break;
}
}
-out:
+out_free:
kfree(sas_iounit_p0);
}
@@ -5928,17 +6624,21 @@ static void leapraid_mark_all_dev_deleted(struct leapraid_adapter *adapter)
shost_for_each_device(sdev, adapter->shost) {
sdev_priv = sdev->hostdata;
if (sdev_priv && sdev_priv->starget_priv)
- sdev_priv->starget_priv->deleted = true;
+ sdev_priv->starget_priv->deleted = 1;
}
}
static void leapraid_free_enc_list(struct leapraid_adapter *adapter)
{
struct leapraid_enc_node *enc_dev, *enc_dev_next;
+ LIST_HEAD(free_list);
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags);
+ list_splice_init(&adapter->dev_topo.enc_list, &free_list);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
- list_for_each_entry_safe(enc_dev, enc_dev_next,
- &adapter->dev_topo.enc_list,
- list) {
+ list_for_each_entry_safe(enc_dev, enc_dev_next, &free_list, list) {
list_del(&enc_dev->list);
kfree(enc_dev);
}
@@ -5951,14 +6651,14 @@ static void leapraid_rebuild_enc_list_after_reset(
union cfg_param_2 cfgp2 = {0};
struct leapraid_enc_node *enc_node;
u16 enc_hdl;
+ unsigned long flags;
int rc;
leapraid_free_enc_list(adapter);
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (enc_hdl = 0xFFFF; ; enc_hdl = le16_to_cpu(enc_node->pg0.enc_hdl)) {
- enc_node = kzalloc(sizeof(*enc_node),
- GFP_KERNEL);
+ enc_node = kzalloc(sizeof(*enc_node), GFP_KERNEL);
if (!enc_node)
return;
@@ -5970,91 +6670,102 @@ static void leapraid_rebuild_enc_list_after_reset(
return;
}
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, flags);
list_add_tail(&enc_node->list, &adapter->dev_topo.enc_list);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, flags);
}
}
static void leapraid_mark_resp_sas_dev(struct leapraid_adapter *adapter,
struct leapraid_sas_dev_p0 *sas_dev_p0)
{
- struct leapraid_starget_priv *starget_priv = NULL;
+ struct leapraid_starget_priv *starget_priv;
struct leapraid_enc_node *enc_node = NULL;
struct leapraid_card_port *card_port;
struct leapraid_sas_dev *sas_dev;
struct scsi_target *starget;
unsigned long flags;
+ unsigned long enc_flags = 0;
+ u16 enc_hdl;
+ u64 enc_lid = 0;
card_port = leapraid_get_port_by_id(adapter, sas_dev_p0->physical_port,
false);
- if (sas_dev_p0->enc_hdl) {
- enc_node = leapraid_enc_find_by_hdl(adapter,
- le16_to_cpu(
- sas_dev_p0->enc_hdl));
+ enc_hdl = le16_to_cpu(sas_dev_p0->enc_hdl);
+ if (enc_hdl) {
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, enc_flags);
+ enc_node = leapraid_enc_find_by_hdl(adapter, enc_hdl);
+ if (enc_node)
+ enc_lid = le64_to_cpu(enc_node->pg0.enc_lid);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, enc_flags);
if (!enc_node)
dev_info(&adapter->pdev->dev,
"enc hdl 0x%04x has no matched enc dev\n",
- le16_to_cpu(sas_dev_p0->enc_hdl));
+ enc_hdl);
}
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
list_for_each_entry(sas_dev, &adapter->dev_topo.sas_dev_list, list) {
- if (sas_dev->sas_addr == le64_to_cpu(sas_dev_p0->sas_address) &&
- sas_dev->slot == le16_to_cpu(sas_dev_p0->slot) &&
- sas_dev->card_port == card_port) {
- sas_dev->resp = true;
- starget = sas_dev->starget;
- if (starget && starget->hostdata) {
- starget_priv = starget->hostdata;
- starget_priv->tm_busy = false;
- starget_priv->deleted = false;
- } else {
- starget_priv = NULL;
- }
+ if (sas_dev->sas_addr != le64_to_cpu(sas_dev_p0->sas_address) ||
+ sas_dev->slot != le16_to_cpu(sas_dev_p0->slot) ||
+ sas_dev->card_port != card_port)
+ continue;
- if (starget) {
- starget_printk(KERN_INFO, starget,
- "dev: hdl=0x%04x, sas addr=0x%016llx, port_id=%d\n",
- sas_dev->hdl,
- (unsigned long long)sas_dev->sas_addr,
- sas_dev->card_port->port_id);
- if (sas_dev->enc_hdl != 0)
- starget_printk(KERN_INFO, starget,
- "enc info: enc_lid=0x%016llx, slot=%d\n",
- (unsigned long long)sas_dev->enc_lid,
- sas_dev->slot);
- }
+ sas_dev->resp = 1;
+ starget = sas_dev->starget;
+ if (starget && starget->hostdata) {
+ starget_priv = starget->hostdata;
+ starget_priv->tm_busy = 0;
+ starget_priv->deleted = 0;
+ } else {
+ starget_priv = NULL;
+ }
- if (le16_to_cpu(sas_dev_p0->flg) &
- LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID) {
- sas_dev->enc_level = sas_dev_p0->enc_level;
- memcpy(sas_dev->connector_name,
- sas_dev_p0->connector_name, 4);
- sas_dev->connector_name[4] = '\0';
- } else {
- sas_dev->enc_level = 0;
- sas_dev->connector_name[0] = '\0';
- }
+ if (starget) {
+ starget_printk(
+ KERN_INFO, starget,
+ "dev: hdl=0x%04x saddr=0x%016llx port_id=%d\n",
+ sas_dev->hdl,
+ (unsigned long long)sas_dev->sas_addr,
+ sas_dev->card_port->port_id);
+ if (sas_dev->enc_hdl != 0)
+ starget_printk(
+ KERN_INFO,
+ starget,
+ "enc info: enc_lid=0x%016llx slot=%d\n",
+ (unsigned long long)sas_dev->enc_lid,
+ sas_dev->slot);
+ }
+
+ if (le16_to_cpu(sas_dev_p0->flg) &
+ LEAPRAID_SAS_DEV_P0_FLG_ENC_LEVEL_VALID) {
+ sas_dev->enc_level = sas_dev_p0->enc_level;
+ memcpy(sas_dev->connector_name,
+ sas_dev_p0->connector_name,
+ LEAPRAID_SAS_DEV_P0_CON_NAME_LEN);
+ sas_dev->connector_name[
+ LEAPRAID_SAS_DEV_P0_CON_NAME_LEN] = '\0';
+ } else {
+ sas_dev->enc_level = 0;
+ sas_dev->connector_name[0] = '\0';
+ }
+
+ sas_dev->enc_hdl = enc_hdl;
+ sas_dev->enc_lid = enc_lid;
- sas_dev->enc_hdl =
- le16_to_cpu(sas_dev_p0->enc_hdl);
- if (enc_node) {
- sas_dev->enc_lid =
- le64_to_cpu(enc_node->pg0.enc_lid);
- }
- if (sas_dev->hdl == le16_to_cpu(sas_dev_p0->dev_hdl))
- goto out;
+ if (sas_dev->hdl == le16_to_cpu(sas_dev_p0->dev_hdl))
+ goto unlock;
- dev_info(&adapter->pdev->dev,
- "hdl changed: 0x%04x -> 0x%04x\n",
- sas_dev->hdl, sas_dev_p0->dev_hdl);
- sas_dev->hdl = le16_to_cpu(sas_dev_p0->dev_hdl);
- if (starget_priv)
- starget_priv->hdl =
- le16_to_cpu(sas_dev_p0->dev_hdl);
- goto out;
- }
+ dev_info(&adapter->pdev->dev,
+ "hdl changed: 0x%04x -> 0x%04x\n",
+ sas_dev->hdl, sas_dev_p0->dev_hdl);
+ sas_dev->hdl = le16_to_cpu(sas_dev_p0->dev_hdl);
+ if (starget_priv)
+ starget_priv->hdl = le16_to_cpu(sas_dev_p0->dev_hdl);
+
+ goto unlock;
}
-out:
+unlock:
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
}
@@ -6066,10 +6777,10 @@ static void leapraid_search_resp_sas_dev(struct leapraid_adapter *adapter)
u32 device_info;
dev_info(&adapter->pdev->dev,
- "begin searching for sas end devices\n");
+ "Begin searching for SAS end devices\n");
if (list_empty(&adapter->dev_topo.sas_dev_list))
- goto out;
+ goto exit_search;
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (cfgp2.handle = 0xFFFF;
@@ -6082,63 +6793,58 @@ static void leapraid_search_resp_sas_dev(struct leapraid_adapter *adapter)
leapraid_mark_resp_sas_dev(adapter, &sas_dev_p0);
}
-out:
+exit_search:
dev_info(&adapter->pdev->dev,
- "sas end devices searching complete\n");
+ "SAS end devices searching complete\n");
}
static void leapraid_mark_resp_raid_volume(struct leapraid_adapter *adapter,
u64 wwid, u16 hdl)
{
- struct leapraid_starget_priv *starget_priv;
struct leapraid_raid_volume *raid_volume;
+ struct leapraid_starget_priv *starget_priv = NULL;
struct scsi_target *starget;
unsigned long flags;
+ u64 volume_wwid;
+ u16 old_hdl;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
- list_for_each_entry(raid_volume,
- &adapter->dev_topo.raid_volume_list, list) {
- if (raid_volume->wwid == wwid && raid_volume->starget) {
- starget = raid_volume->starget;
- if (starget && starget->hostdata) {
- starget_priv = starget->hostdata;
- starget_priv->deleted = false;
- } else {
- starget_priv = NULL;
- }
-
- raid_volume->resp = true;
- spin_unlock_irqrestore(
- &adapter->dev_topo.raid_volume_lock,
- flags);
+ raid_volume = leapraid_raid_volume_find_by_wwid(adapter, wwid);
+ if (!raid_volume)
+ return;
- starget_printk(
- KERN_INFO, raid_volume->starget,
- "raid volume: hdl=0x%04x, wwid=0x%016llx\n",
- hdl, (unsigned long long)raid_volume->wwid);
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock,
- flags);
- if (raid_volume->hdl == hdl) {
- spin_unlock_irqrestore(
- &adapter->dev_topo.raid_volume_lock,
- flags);
- return;
- }
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ if (!raid_volume->starget) {
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
+ flags);
+ leapraid_raid_volume_put(raid_volume);
+ return;
+ }
- dev_info(&adapter->pdev->dev,
- "hdl changed: 0x%04x -> 0x%04x\n",
- raid_volume->hdl, hdl);
+ starget = raid_volume->starget;
+ if (starget->hostdata) {
+ starget_priv = starget->hostdata;
+ starget_priv->deleted = 0;
+ }
- raid_volume->hdl = hdl;
- if (starget_priv)
- starget_priv->hdl = hdl;
- spin_unlock_irqrestore(
- &adapter->dev_topo.raid_volume_lock,
- flags);
- return;
- }
+ raid_volume->resp = 1;
+ volume_wwid = raid_volume->wwid;
+ old_hdl = raid_volume->hdl;
+ if (old_hdl != hdl) {
+ raid_volume->hdl = hdl;
+ if (starget_priv)
+ starget_priv->hdl = hdl;
}
spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+
+ starget_printk(KERN_INFO, starget,
+ "raid volume: hdl=0x%04x, wwid=0x%016llx\n",
+ hdl, (unsigned long long)volume_wwid);
+ if (old_hdl != hdl)
+ dev_info(&adapter->pdev->dev,
+ "hdl changed: 0x%04x -> 0x%04x\n",
+ old_hdl, hdl);
+
+ leapraid_raid_volume_put(raid_volume);
}
static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter)
@@ -6150,17 +6856,22 @@ static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter)
struct leapraid_raidvol_p1 raidvol_p1;
struct leapraid_raidvol_p0 raidvol_p0;
struct leapraid_raidpd_p0 raidpd_p0;
+ unsigned long flags;
u16 hdl;
u8 phys_disk_num;
+ bool is_empty;
if (!adapter->adapter_attr.raid_support)
return;
dev_info(&adapter->pdev->dev,
- "begin searching for raid volumes\n");
+ "Begin searching for RAID volumes\n");
- if (list_empty(&adapter->dev_topo.raid_volume_list))
- goto out;
+ 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;
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
@@ -6191,11 +6902,16 @@ static void leapraid_search_resp_raid_volume(struct leapraid_adapter *adapter)
cfgp2.form_specific = phys_disk_num) {
phys_disk_num = raidpd_p0.phys_disk_num;
hdl = le16_to_cpu(raidpd_p0.dev_hdl);
- set_bit(hdl, (unsigned long *)adapter->dev_topo.pd_hdls);
+ if (!hdl ||
+ hdl > adapter->adapter_attr.features.max_dev_handle)
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid device handle\n", __func__);
+ else
+ set_bit(hdl, adapter->dev_topo.pd_hdls);
}
-out:
+exit_search:
dev_info(&adapter->pdev->dev,
- "raid volumes searching complete\n");
+ "RAID volumes searching complete\n");
}
static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter,
@@ -6211,10 +6927,17 @@ static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter,
port_id,
false);
unsigned long flags;
+ unsigned long enc_flags = 0;
+ u64 enc_lid = 0;
int i;
- if (enc_hdl)
+ if (enc_hdl) {
+ spin_lock_irqsave(&adapter->dev_topo.enc_lock, enc_flags);
enc_node = leapraid_enc_find_by_hdl(adapter, enc_hdl);
+ if (enc_node)
+ enc_lid = le64_to_cpu(enc_node->pg0.enc_lid);
+ spin_unlock_irqrestore(&adapter->dev_topo.enc_lock, enc_flags);
+ }
spin_lock_irqsave(&adapter->dev_topo.topo_node_lock, flags);
list_for_each_entry(topo_node_exp, &adapter->dev_topo.exp_list, list) {
@@ -6222,14 +6945,11 @@ static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter,
topo_node_exp->card_port != card_port)
continue;
- topo_node_exp->resp = true;
- if (enc_node) {
- topo_node_exp->enc_lid =
- le64_to_cpu(enc_node->pg0.enc_lid);
- topo_node_exp->enc_hdl = le16_to_cpu(exp_pg0->enc_hdl);
- }
+ topo_node_exp->resp = 1;
+ topo_node_exp->enc_hdl = enc_hdl;
+ topo_node_exp->enc_lid = enc_lid;
if (topo_node_exp->hdl == hdl)
- goto out;
+ goto unlock;
dev_info(&adapter->pdev->dev,
"hdl changed: 0x%04x -> 0x%04x\n",
@@ -6237,9 +6957,9 @@ static void leapraid_mark_resp_exp(struct leapraid_adapter *adapter,
topo_node_exp->hdl = hdl;
for (i = 0; i < topo_node_exp->phys_num; i++)
topo_node_exp->card_phy[i].hdl = hdl;
- goto out;
+ goto unlock;
}
-out:
+unlock:
spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
}
@@ -6252,10 +6972,10 @@ static void leapraid_search_resp_exp(struct leapraid_adapter *adapter)
u16 hdl;
u8 port;
- dev_info(&adapter->pdev->dev,
- "begin searching for expanders\n");
+ dev_dbg(&adapter->pdev->dev,
+ "Begin searching for expanders\n");
if (list_empty(&adapter->dev_topo.exp_list))
- goto out;
+ goto exit_search;
cfgp1.form = LEAPRAID_SAS_CFG_PGAD_GET_NEXT_LOOP;
for (hdl = 0xFFFF, cfgp2.handle = hdl;
@@ -6266,16 +6986,16 @@ static void leapraid_search_resp_exp(struct leapraid_adapter *adapter)
sas_address = le64_to_cpu(exp_p0.sas_address);
port = exp_p0.physical_port;
- dev_info(&adapter->pdev->dev,
- "exp detected: hdl=0x%04x, sas=0x%016llx, port=%u",
- hdl, (unsigned long long)sas_address,
- ((adapter->adapter_attr.enable_mp) ? (port) :
- (LEAPRAID_DISABLE_MP_PORT_ID)));
+ dev_dbg(&adapter->pdev->dev,
+ "exp detected: hdl=0x%04x, sas=0x%016llx, port=%u",
+ hdl, (unsigned long long)sas_address,
+ adapter->adapter_attr.enable_mp ? port :
+ LEAPRAID_DISABLE_MP_PORT_ID);
leapraid_mark_resp_exp(adapter, &exp_p0);
}
-out:
- dev_info(&adapter->pdev->dev,
- "expander searching complete\n");
+exit_search:
+ dev_dbg(&adapter->pdev->dev,
+ "Expander searching complete\n");
}
void leapraid_wait_cmds_done(struct leapraid_adapter *adapter)
@@ -6287,7 +7007,7 @@ void leapraid_wait_cmds_done(struct leapraid_adapter *adapter)
adapter->reset_desc.pending_io_cnt = 0;
if (!leapraid_pci_active(adapter)) {
dev_err(&adapter->pdev->dev,
- "%s %s: pci error, device reset or unplugged!\n",
+ "%s %s: PCI error, device reset or unplugged!\n",
adapter->adapter_attr.name, __func__);
return;
}
@@ -6299,9 +7019,9 @@ void leapraid_wait_cmds_done(struct leapraid_adapter *adapter)
for (i = 1; i <= adapter->shost->can_queue; i++) {
io_req_tracker = leapraid_get_io_tracker_from_taskid(adapter,
i);
- if (io_req_tracker && io_req_tracker->taskid != 0)
- if (io_req_tracker->scmd)
- adapter->reset_desc.pending_io_cnt++;
+ if (io_req_tracker && io_req_tracker->taskid != 0 &&
+ io_req_tracker->scmd)
+ adapter->reset_desc.pending_io_cnt++;
}
spin_unlock_irqrestore(&adapter->dynamic_task_desc.task_lock, flags);
@@ -6309,38 +7029,37 @@ void leapraid_wait_cmds_done(struct leapraid_adapter *adapter)
return;
wait_event_timeout(adapter->reset_desc.reset_wait_queue,
- adapter->reset_desc.pending_io_cnt == 0, 10 * HZ);
+ adapter->reset_desc.pending_io_cnt == 0,
+ LEAPRAID_IO_CMD_TIMEOUT * HZ);
}
int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
enum reset_type type)
{
unsigned long flags;
+ bool wake = false;
int rc;
- if (!mutex_trylock(&adapter->reset_desc.adapter_reset_mutex)) {
- do {
- ssleep(1);
- } while (adapter->access_ctrl.shost_recovering);
- return adapter->reset_desc.adapter_reset_results;
- }
+ mutex_lock(&adapter->reset_desc.adapter_reset_mutex);
if (!leapraid_pci_active(adapter)) {
if (leapraid_pci_removed(adapter)) {
dev_info(&adapter->pdev->dev,
- "pci_dev removed, pausing polling and cleaning cmds\n");
+ "pci_dev removed, pause poll, clean cmds\n");
leapraid_mq_polling_pause(adapter);
leapraid_clean_active_scsi_cmds(adapter);
leapraid_mq_polling_resume(adapter);
}
- rc = 0;
- goto exit_pci_unavailable;
+ dev_err(&adapter->pdev->dev, "PCIe unavailable!\n");
+ mutex_unlock(&adapter->reset_desc.adapter_reset_mutex);
+ return -ENXIO;
}
- dev_info(&adapter->pdev->dev, "starting hard reset\n");
+ dev_info(&adapter->pdev->dev, "Starting hard reset\n");
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
- adapter->access_ctrl.shost_recovering = true;
+ adapter->access_ctrl.shost_recovering = 1;
+ adapter->access_ctrl.shost_recover_async = 1;
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
leapraid_wait_cmds_done(adapter);
@@ -6349,14 +7068,14 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
rc = leapraid_make_adapter_ready(adapter, type);
if (rc) {
dev_err(&adapter->pdev->dev,
- "failed to make adapter ready, rc=%d\n", rc);
- goto out;
+ "Failed to make adapter ready, rc=%d\n", rc);
+ goto out_cleanup;
}
rc = leapraid_fw_log_init(adapter);
if (rc) {
- dev_err(&adapter->pdev->dev, "firmware log init failed\n");
- goto out;
+ dev_err(&adapter->pdev->dev, "Firmware log init failed\n");
+ goto out_cleanup;
}
leapraid_clean_active_cmds(adapter);
@@ -6364,15 +7083,16 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
adapter->scan_dev_desc.scan_dev_failed) {
dev_err(&adapter->pdev->dev,
"Previous device scan failed or driver loading\n");
- adapter->access_ctrl.host_removing = true;
+ adapter->access_ctrl.host_removing = 1;
+ wake_up(&adapter->access_ctrl.recovery_waitq);
rc = -EFAULT;
- goto out;
+ goto out_cleanup;
}
rc = leapraid_make_adapter_available(adapter);
if (!rc) {
dev_info(&adapter->pdev->dev,
- "adapter is now available, rebuilding topology\n");
+ "Adapter is now available, rebuilding topology\n");
if (adapter->adapter_attr.enable_mp) {
leapraid_update_card_port_after_reset(adapter);
leapraid_update_vphys_after_reset(adapter);
@@ -6384,14 +7104,22 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
leapraid_search_resp_exp(adapter);
leapraid_hardreset_barrier(adapter);
}
-out:
- dev_info(&adapter->pdev->dev, "hard reset %s\n",
- ((rc == 0) ? "SUCCESS" : "FAILED"));
+out_cleanup:
+ dev_info(&adapter->pdev->dev, "Hard reset %s\n",
+ rc == 0 ? "SUCCESS" : "FAILED");
spin_lock_irqsave(&adapter->reset_desc.adapter_reset_lock, flags);
adapter->reset_desc.adapter_reset_results = rc;
- adapter->access_ctrl.shost_recovering = false;
+ adapter->access_ctrl.shost_recovering = 0;
+ wake_up(&adapter->access_ctrl.recovery_waitq);
+ if (rc) {
+ adapter->access_ctrl.shost_recover_async = 0;
+ wake = true;
+ }
spin_unlock_irqrestore(&adapter->reset_desc.adapter_reset_lock, flags);
+ if (wake)
+ wake_up(&adapter->access_ctrl.shost_recover_wq);
+
adapter->reset_desc.reset_cnt++;
mutex_unlock(&adapter->reset_desc.adapter_reset_mutex);
@@ -6399,8 +7127,6 @@ int leapraid_hard_reset_handler(struct leapraid_adapter *adapter,
leapraid_clean_active_scsi_cmds(adapter);
leapraid_mq_polling_resume(adapter);
-exit_pci_unavailable:
- dev_info(&adapter->pdev->dev, "pcie unavailable!\n");
return rc;
}
@@ -6409,31 +7135,40 @@ static int leapraid_get_adapter_features(struct leapraid_adapter *adapter)
struct leapraid_adapter_features_req leap_mpi_req;
struct leapraid_adapter_features_rep leap_mpi_rep;
u8 fw_major, fw_minor, fw_build, fw_release;
+ u32 req_sz;
+ u32 rep_sz;
u32 db;
int r;
db = leapraid_readl(&adapter->iomem_base->db);
if (db & LEAPRAID_DB_USED ||
- (db & LEAPRAID_DB_MASK) == LEAPRAID_DB_FAULT)
+ (db & LEAPRAID_DB_MASK) == LEAPRAID_DB_FAULT) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Doorbell used or fault\n", __func__);
return -EFAULT;
+ }
- if (((db & LEAPRAID_DB_MASK) != LEAPRAID_DB_READY) &&
- ((db & LEAPRAID_DB_MASK) != LEAPRAID_DB_OPERATIONAL)) {
- if (!leapraid_wait_adapter_ready(adapter))
- return -EFAULT;
+ if ((db & LEAPRAID_DB_MASK) != LEAPRAID_DB_READY &&
+ (db & LEAPRAID_DB_MASK) != LEAPRAID_DB_OPERATIONAL &&
+ !leapraid_wait_adapter_ready(adapter)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: adapter not ready\n", __func__);
+ return -EFAULT;
}
- memset(&leap_mpi_req, 0, sizeof(struct leapraid_adapter_features_req));
- memset(&leap_mpi_rep, 0, sizeof(struct leapraid_adapter_features_rep));
+ req_sz = sizeof(struct leapraid_adapter_features_req);
+ rep_sz = sizeof(struct leapraid_adapter_features_rep);
+ memset(&leap_mpi_req, 0, req_sz);
+ memset(&leap_mpi_rep, 0, rep_sz);
leap_mpi_req.func = LEAPRAID_FUNC_GET_ADAPTER_FEATURES;
r = leapraid_handshake_func(adapter,
- sizeof(struct leapraid_adapter_features_req),
+ req_sz,
(u32 *)&leap_mpi_req,
- sizeof(struct leapraid_adapter_features_rep),
+ rep_sz,
(u16 *)&leap_mpi_rep);
if (r) {
dev_err(&adapter->pdev->dev,
- "%s %s: handshake failed, r=%d\n",
+ "%s %s: Handshake failed, r=%d\n",
adapter->adapter_attr.name, __func__, r);
return r;
}
@@ -6460,19 +7195,43 @@ static int leapraid_get_adapter_features(struct leapraid_adapter *adapter)
LEAPRAID_MAX_DEV_HANDLE_DEFAULT;
adapter->adapter_attr.features.min_dev_handle =
le16_to_cpu(leap_mpi_rep.min_dev_hdl);
- if ((adapter->adapter_attr.features.adapter_caps &
- LEAPRAID_ADAPTER_FEATURES_CAP_INTEGRATED_RAID))
- adapter->adapter_attr.raid_support = true;
+ if (adapter->adapter_attr.features.adapter_caps &
+ LEAPRAID_ADAPTER_FEATURES_CAP_INTEGRATED_RAID)
+ adapter->adapter_attr.raid_support = 1;
+ adapter->adapter_attr.wideport_max_queue_depth =
+ le16_to_cpu(leap_mpi_rep.sas_wide_max_qdepth) ?
+ le16_to_cpu(leap_mpi_rep.sas_wide_max_qdepth) :
+ LEAPRAID_SAS_QUEUE_DEPTH;
+ adapter->adapter_attr.narrowport_max_queue_depth =
+ le16_to_cpu(leap_mpi_rep.sas_narrow_max_qdepth) ?
+ le16_to_cpu(leap_mpi_rep.sas_narrow_max_qdepth) :
+ LEAPRAID_SAS_QUEUE_DEPTH;
+ adapter->adapter_attr.sata_max_queue_depth =
+ leap_mpi_rep.sata_max_qdepth ?
+ leap_mpi_rep.sata_max_qdepth :
+ LEAPRAID_SATA_QUEUE_DEPTH;
+ adapter->adapter_attr.raid_volume_max_queue_depth =
+ LEAPRAID_RAID_QUEUE_DEPTH;
+ dev_info(&adapter->pdev->dev,
+ "max: wp qd=%d, np qd=%d, SATA qd=%d, raid qd=%d\n",
+ adapter->adapter_attr.wideport_max_queue_depth,
+ adapter->adapter_attr.narrowport_max_queue_depth,
+ adapter->adapter_attr.sata_max_queue_depth,
+ adapter->adapter_attr.raid_volume_max_queue_depth);
if (WARN_ON(!(adapter->adapter_attr.features.adapter_caps &
LEAPRAID_ADAPTER_FEATURES_CAP_ATOMIC_REQ)))
return -EFAULT;
adapter->adapter_attr.features.fw_version =
le32_to_cpu(leap_mpi_rep.fw_version);
- fw_major = (adapter->adapter_attr.features.fw_version >> 24) & 0xFF;
- fw_minor = (adapter->adapter_attr.features.fw_version >> 16) & 0xFF;
- fw_build = (adapter->adapter_attr.features.fw_version >> 8) & 0xFF;
- fw_release = adapter->adapter_attr.features.fw_version & 0xFF;
+ fw_major = (adapter->adapter_attr.features.fw_version >>
+ LEAPRAID_VER_MAJOR_SHIFT) & LEAPRAID_VER_MASK;
+ fw_minor = (adapter->adapter_attr.features.fw_version >>
+ LEAPRAID_VER_MINOR_SHIFT) & LEAPRAID_VER_MASK;
+ fw_build = (adapter->adapter_attr.features.fw_version >>
+ LEAPRAID_VER_BUILD_SHIFT) & LEAPRAID_VER_MASK;
+ fw_release =
+ adapter->adapter_attr.features.fw_version & LEAPRAID_VER_MASK;
dev_info(&adapter->pdev->dev,
"Firmware version: %u.%u.%u.%u (0x%08x)\n",
@@ -6484,7 +7243,7 @@ static int leapraid_get_adapter_features(struct leapraid_adapter *adapter)
"Unsupported firmware major version, requires >= 2\n");
return -EFAULT;
}
- adapter->shost->max_id = -1;
+ adapter->shost->max_id = LEAPRAID_INVALID_INITIAL_VALUE;
return 0;
}
@@ -6511,54 +7270,50 @@ static int leapraid_enable_pcie(struct leapraid_adapter *adapter)
rc = pci_enable_device(adapter->pdev);
if (rc) {
- dev_err(&adapter->pdev->dev, "failed to enable PCI device\n");
+ dev_err(&adapter->pdev->dev, "Failed to enable PCI device\n");
return rc;
}
rc = pci_request_regions(adapter->pdev, LEAPRAID_DRIVER_NAME);
if (rc) {
dev_err(&adapter->pdev->dev,
- "failed to obtain PCI resources\n");
- goto disable_pcie;
+ "Failed to obtain PCI resources\n");
+ return rc;
}
if (sizeof(dma_addr_t) > 4) {
- dma_mask = DMA_BIT_MASK(64);
- adapter->adapter_attr.use_32_dma_mask = false;
+ dma_mask = DMA_BIT_MASK(DMA_64_BITS);
+ adapter->adapter_attr.use_32_dma_mask = 0;
} else {
- dma_mask = DMA_BIT_MASK(32);
- adapter->adapter_attr.use_32_dma_mask = true;
+ dma_mask = DMA_BIT_MASK(DMA_32_BITS);
+ adapter->adapter_attr.use_32_dma_mask = 1;
}
rc = dma_set_mask_and_coherent(&adapter->pdev->dev, dma_mask);
if (rc) {
dev_err(&adapter->pdev->dev,
- "failed to set %lld DMA mask\n", dma_mask);
- goto disable_pcie;
+ "Failed to set %lld DMA mask\n", dma_mask);
+ return rc;
}
adapter->iomem_base = ioremap(pci_resource_start(adapter->pdev, 0),
sizeof(struct leapraid_reg_base));
if (!adapter->iomem_base) {
dev_err(&adapter->pdev->dev,
- "failed to map memory for controller registers\n");
- rc = -ENOMEM;
- goto disable_pcie;
+ "Failed to map memory for controller registers\n");
+ return -ENOMEM;
}
pci_enable_pcie_error_reporting(adapter->pdev);
pci_set_master(adapter->pdev);
return 0;
-
-disable_pcie:
- return rc;
}
static void leapraid_cpus_on_irq(struct leapraid_adapter *adapter)
{
struct leapraid_int_rq *int_rq;
unsigned int i, base_group, this_group;
- unsigned int cpu, nr_cpus, total_msix, index = 0;
+ unsigned int cpu, nr_cpus, total_msix, index;
total_msix = adapter->notification_desc.iopoll_qdex;
nr_cpus = num_online_cpus();
@@ -6600,8 +7355,12 @@ static void leapraid_map_msix_to_cpu(struct leapraid_adapter *adapter)
int_rq = &adapter->notification_desc.int_rqs[i];
affinity_mask = pci_irq_get_affinity(adapter->pdev,
int_rq->rq.msix_idx);
- if (!affinity_mask)
- goto out;
+ if (!affinity_mask) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: IRQ affinity NULL, msix_idx=%d\n",
+ __func__, int_rq->rq.msix_idx);
+ goto out_apply_irq_affinity;
+ }
for_each_cpu_and(cpu, affinity_mask, cpu_online_mask) {
if (cpu >= adapter->notification_desc.msix_cpu_map_sz)
@@ -6611,7 +7370,7 @@ static void leapraid_map_msix_to_cpu(struct leapraid_adapter *adapter)
int_rq->rq.msix_idx;
}
}
-out:
+out_apply_irq_affinity:
leapraid_cpus_on_irq(adapter);
}
@@ -6628,27 +7387,26 @@ static void leapraid_free_irq(struct leapraid_adapter *adapter)
{
struct leapraid_int_rq *int_rq;
unsigned int i;
+ int irq;
- if (!adapter->notification_desc.int_rqs)
- return;
-
- for (i = 0; i < adapter->notification_desc.int_rqs_allocated; i++) {
+ for (i = 0; adapter->notification_desc.int_rqs &&
+ i < adapter->notification_desc.int_rqs_allocated; i++) {
int_rq = &adapter->notification_desc.int_rqs[i];
if (!int_rq)
continue;
- irq_set_affinity_hint(pci_irq_vector(adapter->pdev,
- int_rq->rq.msix_idx), NULL);
- free_irq(pci_irq_vector(adapter->pdev, int_rq->rq.msix_idx),
- &int_rq->rq);
+ irq = pci_irq_vector(adapter->pdev, int_rq->rq.msix_idx);
+ irq_set_affinity_hint(irq, NULL);
+ free_irq(irq, &int_rq->rq);
}
adapter->notification_desc.int_rqs_allocated = 0;
- if (!adapter->notification_desc.msix_enable)
- return;
+ if (adapter->notification_desc.irq_vectors_allocated) {
+ pci_free_irq_vectors(adapter->pdev);
+ adapter->notification_desc.irq_vectors_allocated = 0;
+ }
- pci_free_irq_vectors(adapter->pdev);
- adapter->notification_desc.msix_enable = false;
+ adapter->notification_desc.msix_enable = 0;
kfree(adapter->notification_desc.blk_mq_poll_rqs);
adapter->notification_desc.blk_mq_poll_rqs = NULL;
@@ -6658,16 +7416,9 @@ static void leapraid_free_irq(struct leapraid_adapter *adapter)
kfree(adapter->notification_desc.msix_cpu_map);
adapter->notification_desc.msix_cpu_map = NULL;
-}
-
-static inline int leapraid_msix_cnt(struct pci_dev *pdev)
-{
- return pci_msix_vec_count(pdev);
-}
-
-static inline int leapraid_msi_cnt(struct pci_dev *pdev)
-{
- return pci_msi_vec_count(pdev);
+ adapter->notification_desc.msix_cpu_map_sz = 0;
+ adapter->notification_desc.iopoll_qdex = 0;
+ adapter->notification_desc.iopoll_qcnt = 0;
}
static int leapraid_setup_irqs(struct leapraid_adapter *adapter)
@@ -6675,7 +7426,7 @@ static int leapraid_setup_irqs(struct leapraid_adapter *adapter)
unsigned int i;
int rc = 0;
- if (interrupt_mode == 0) {
+ if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX) {
rc = pci_alloc_irq_vectors_affinity(
adapter->pdev,
adapter->notification_desc.iopoll_qdex,
@@ -6684,22 +7435,26 @@ static int leapraid_setup_irqs(struct leapraid_adapter *adapter)
if (rc < 0) {
dev_err(&adapter->pdev->dev,
- "%d msi/msix vectors alloacted failed!\n",
+ "%d MSI/MSIX vectors allocated failed!\n",
adapter->notification_desc.iopoll_qdex);
return rc;
}
+
+ 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 == 0)
+ if (interrupt_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 == 1)
+ else if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSI)
snprintf(adapter->notification_desc.int_rqs[i].rq.name,
LEAPRAID_NAME_LENGTH, "%s%u-MSI%u",
LEAPRAID_DRIVER_NAME,
@@ -6710,6 +7465,7 @@ 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",
@@ -6741,10 +7497,12 @@ static int leapraid_setup_legacy_int(struct leapraid_adapter *adapter)
NULL);
if (rc < 0) {
dev_err(&adapter->pdev->dev,
- "legacy irq alloacted failed!\n");
+ "Legacy irq allocated failed!\n");
return rc;
}
+ adapter->notification_desc.irq_vectors_allocated = 1;
+ adapter->notification_desc.irq_mode = LEAPRAID_INTERRUPT_MODE_LEGACY;
rc = request_irq(pci_irq_vector(adapter->pdev, 0),
leapraid_irq_handler,
IRQF_SHARED,
@@ -6753,8 +7511,9 @@ static int leapraid_setup_legacy_int(struct leapraid_adapter *adapter)
if (rc) {
irq_set_affinity_hint(pci_irq_vector(adapter->pdev, 0), NULL);
pci_free_irq_vectors(adapter->pdev);
+ adapter->notification_desc.irq_vectors_allocated = 0;
dev_err(&adapter->pdev->dev,
- "Legact Int: request_irq %s failed!\n",
+ "Legacy Int: request_irq %s failed!\n",
adapter->notification_desc.int_rqs[0].rq.name);
return -EBUSY;
}
@@ -6768,8 +7527,8 @@ static int leapraid_set_legacy_int(struct leapraid_adapter *adapter)
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);
+ kzalloc(adapter->notification_desc.msix_cpu_map_sz,
+ GFP_KERNEL);
if (!adapter->notification_desc.msix_cpu_map)
return -ENOMEM;
@@ -6778,19 +7537,15 @@ static int leapraid_set_legacy_int(struct leapraid_adapter *adapter)
adapter->adapter_attr.rq_cnt;
adapter->notification_desc.iopoll_qcnt = 0;
dev_info(&adapter->pdev->dev,
- "Legacy Intr: req queue cnt=%d, intr=%d/poll=%d rep queues!\n",
+ "Legacy Intr: req queue cnt=%d intr=%d/poll=%d rep queues!\n",
adapter->adapter_attr.rq_cnt,
adapter->notification_desc.iopoll_qdex,
adapter->notification_desc.iopoll_qcnt);
adapter->notification_desc.int_rqs =
kcalloc(adapter->notification_desc.iopoll_qdex,
sizeof(struct leapraid_int_rq), GFP_KERNEL);
- if (!adapter->notification_desc.int_rqs) {
- dev_err(&adapter->pdev->dev,
- "Legacy Intr: allocate %d intr rep queues failed!\n",
- adapter->notification_desc.iopoll_qdex);
+ if (!adapter->notification_desc.int_rqs)
return -ENOMEM;
- }
rc = leapraid_setup_legacy_int(adapter);
@@ -6804,13 +7559,13 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter)
int rc, msix_cnt;
if (msix_disable == 1)
- goto legacy_int;
+ goto apply_legacy_int;
- msix_cnt = leapraid_msix_cnt(adapter->pdev);
+ 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 legacy_int;
+ dev_info(&adapter->pdev->dev, "MSIX unsupported!\n");
+ goto apply_legacy_int;
}
msix_cnt = min_t(int, msix_cnt,
@@ -6852,25 +7607,25 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter)
adapter->notification_desc.int_rqs =
kcalloc(adapter->notification_desc.iopoll_qdex,
sizeof(struct leapraid_int_rq), GFP_KERNEL);
- if (!adapter->notification_desc.int_rqs) {
- dev_err(&adapter->pdev->dev,
- "MSIx: allocate %d interrupt reply queues failed!\n",
- adapter->notification_desc.iopoll_qdex);
+ if (!adapter->notification_desc.int_rqs)
return -ENOMEM;
- }
for (i = 0; i < adapter->notification_desc.iopoll_qcnt; i++) {
adapter->notification_desc.blk_mq_poll_rqs[i].rq.adapter =
adapter;
adapter->notification_desc.blk_mq_poll_rqs[i].rq.msix_idx =
i + adapter->notification_desc.iopoll_qdex;
- atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].rq.busy, 0);
+ atomic_set(
+ &adapter->notification_desc.blk_mq_poll_rqs[i].rq.busy,
+ 0);
snprintf(adapter->notification_desc.blk_mq_poll_rqs[i].rq.name,
LEAPRAID_NAME_LENGTH,
"%s%u-MQ-Poll%u", LEAPRAID_DRIVER_NAME,
adapter->adapter_attr.id, i);
- atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].busy, 0);
- atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].pause, 0);
+ atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].busy,
+ 0);
+ atomic_set(&adapter->notification_desc.blk_mq_poll_rqs[i].pause,
+ 0);
}
adapter->notification_desc.msix_cpu_map_sz =
@@ -6880,20 +7635,21 @@ static int leapraid_set_msix(struct leapraid_adapter *adapter)
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);
- adapter->notification_desc.msix_enable = true;
+ adapter->notification_desc.msix_enable = 1;
rc = leapraid_setup_irqs(adapter);
if (rc) {
leapraid_free_irq(adapter);
- adapter->notification_desc.msix_enable = false;
- goto legacy_int;
+ adapter->notification_desc.msix_enable = 0;
+ goto apply_legacy_int;
}
return 0;
-legacy_int:
+apply_legacy_int:
rc = leapraid_set_legacy_int(adapter);
return rc;
@@ -6906,13 +7662,13 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter)
int rc, msi_cnt;
if (msix_disable == 1)
- goto legacy_int1;
+ goto apply_legacy_int;
- msi_cnt = leapraid_msi_cnt(adapter->pdev);
+ 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 legacy_int1;
+ dev_info(&adapter->pdev->dev, "MSI unsupported!\n");
+ goto apply_legacy_int;
}
msi_cnt = min_t(int, msi_cnt,
@@ -6952,10 +7708,13 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter)
PCI_IRQ_MSI | PCI_IRQ_AFFINITY, NULL);
if (rc < 0) {
dev_err(&adapter->pdev->dev,
- "%d msi vectors alloacted failed!\n",
+ "%d MSI vectors allocated failed!\n",
adapter->notification_desc.iopoll_qdex);
- goto legacy_int1;
+ leapraid_free_irq(adapter);
+ goto apply_legacy_int;
}
+ 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 =
@@ -6972,12 +7731,8 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter)
kcalloc(adapter->notification_desc.iopoll_qdex,
sizeof(struct leapraid_int_rq),
GFP_KERNEL);
- if (!adapter->notification_desc.int_rqs) {
- dev_err(&adapter->pdev->dev,
- "MSI: allocate %d interrupt reply queues failed!\n",
- adapter->notification_desc.iopoll_qdex);
+ if (!adapter->notification_desc.int_rqs)
return -ENOMEM;
- }
for (i = 0; i < adapter->notification_desc.iopoll_qcnt; i++) {
adapter->notification_desc.blk_mq_poll_rqs[i].rq.adapter =
@@ -7001,24 +7756,24 @@ static int leapraid_set_msi(struct leapraid_adapter *adapter)
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);
+ 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);
- adapter->notification_desc.msix_enable = true;
+ adapter->notification_desc.msix_enable = 1;
rc = leapraid_setup_irqs(adapter);
if (rc) {
leapraid_free_irq(adapter);
- adapter->notification_desc.msix_enable = false;
- goto legacy_int1;
+ adapter->notification_desc.msix_enable = 0;
+ goto apply_legacy_int;
}
return 0;
-legacy_int1:
+apply_legacy_int:
rc = leapraid_set_legacy_int(adapter);
return rc;
@@ -7028,30 +7783,26 @@ static int leapraid_set_notification(struct leapraid_adapter *adapter)
{
int rc = 0;
- if (interrupt_mode == 0) {
+ if (interrupt_mode == LEAPRAID_INTERRUPT_MODE_MSIX) {
rc = leapraid_set_msix(adapter);
if (rc)
- pr_err("%s enable MSI-X irq failed!\n", __func__);
- } else if (interrupt_mode == 1) {
+ 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)
- pr_err("%s enable MSI irq failed!\n", __func__);
- } else if (interrupt_mode == 2) {
+ 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)
- pr_err("%s enable legacy irq failed!\n", __func__);
+ dev_err(&adapter->pdev->dev,
+ "%s: Enable legacy irq failed!\n", __func__);
}
return rc;
}
-static void leapraid_disable_pcie_and_notification(
- struct leapraid_adapter *adapter)
-{
- leapraid_free_irq(adapter);
- leapraid_disable_pcie(adapter);
-}
-
int leapraid_set_pcie_and_notification(struct leapraid_adapter *adapter)
{
int rc;
@@ -7064,13 +7815,13 @@ int leapraid_set_pcie_and_notification(struct leapraid_adapter *adapter)
rc = leapraid_make_adapter_ready(adapter, PART_RESET);
if (rc) {
- dev_err(&adapter->pdev->dev, "make adapter ready failure\n");
+ dev_err(&adapter->pdev->dev, "Make adapter ready failure\n");
goto out_fail;
}
rc = leapraid_get_adapter_features(adapter);
if (rc) {
- dev_err(&adapter->pdev->dev, "get adapter feature failure\n");
+ dev_err(&adapter->pdev->dev, "Get adapter feature failure\n");
goto out_fail;
}
@@ -7083,7 +7834,8 @@ int leapraid_set_pcie_and_notification(struct leapraid_adapter *adapter)
return 0;
out_fail:
- leapraid_disable_pcie_and_notification(adapter);
+ leapraid_free_irq(adapter);
+ leapraid_disable_pcie(adapter);
return rc;
}
@@ -7094,11 +7846,13 @@ void leapraid_disable_controller(struct leapraid_adapter *adapter)
leapraid_mask_int(adapter);
- adapter->access_ctrl.shost_recovering = true;
+ adapter->access_ctrl.shost_recovering = 1;
leapraid_make_adapter_ready(adapter, PART_RESET);
- adapter->access_ctrl.shost_recovering = false;
+ adapter->access_ctrl.shost_recovering = 0;
+ wake_up(&adapter->access_ctrl.recovery_waitq);
- leapraid_disable_pcie_and_notification(adapter);
+ leapraid_free_irq(adapter);
+ leapraid_disable_pcie(adapter);
}
static int leapraid_adapter_unit_reset(struct leapraid_adapter *adapter)
@@ -7112,12 +7866,11 @@ static int leapraid_adapter_unit_reset(struct leapraid_adapter *adapter)
rc = -EFAULT;
if (!leapraid_wait_adapter_ready(adapter)) {
- rc = -EFAULT;
- goto out;
+ dev_info(&adapter->pdev->dev, "unit reset: FAILED\n");
+ return -EFAULT;
}
-out:
- dev_info(&adapter->pdev->dev, "unit reset: %s\n",
- ((rc == 0) ? "SUCCESS" : "FAILED"));
+
+ dev_info(&adapter->pdev->dev, "unit reset: SUCCESS\n");
return rc;
}
@@ -7137,13 +7890,13 @@ static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter,
while ((db & LEAPRAID_DB_MASK) != LEAPRAID_DB_READY) {
if (count++ == LEAPRAID_DB_RETRY_COUNT_MAX) {
dev_err(&adapter->pdev->dev,
- "wait adapter ready timeout\n");
+ "Wait adapter ready timeout\n");
return -EFAULT;
}
ssleep(1);
db = leapraid_readl(&adapter->iomem_base->db);
dev_info(&adapter->pdev->dev,
- "wait adapter ready, count=%d, db=0x%x\n",
+ "Wait adapter ready, count=%d, db=0x%x\n",
count, db);
}
}
@@ -7159,9 +7912,9 @@ static int leapraid_make_adapter_ready(struct leapraid_adapter *adapter,
if (type == FULL_RESET)
goto full_reset;
- if ((db & LEAPRAID_DB_MASK) == LEAPRAID_DB_OPERATIONAL)
- if (!(leapraid_adapter_unit_reset(adapter)))
- return 0;
+ if ((db & LEAPRAID_DB_MASK) == LEAPRAID_DB_OPERATIONAL &&
+ !leapraid_adapter_unit_reset(adapter))
+ return 0;
full_reset:
rc = leapraid_host_diag_reset(adapter);
@@ -7202,12 +7955,8 @@ static int leapraid_fw_log_init(struct leapraid_adapter *adapter)
LEAPRAID_SYS_LOG_BUF_RESERVE),
&adapter->fw_log_desc.fw_log_buffer_dma,
GFP_KERNEL);
- if (!adapter->fw_log_desc.fw_log_buffer) {
- dev_err(&adapter->pdev->dev,
- "%s: log buf alloc failed.\n",
- __func__);
+ if (!adapter->fw_log_desc.fw_log_buffer)
return -ENOMEM;
- }
}
memset(&adapter_log_req, 0, sizeof(struct leapraid_adapter_log_req));
@@ -7226,7 +7975,7 @@ static int leapraid_fw_log_init(struct leapraid_adapter *adapter)
sizeof(struct leapraid_adapter_log_rep),
(u16 *)&adapter_log_rep);
if (rc != 0) {
- dev_err(&adapter->pdev->dev, "%s: handshake failed, rc=%d\n",
+ dev_err(&adapter->pdev->dev, "%s: Handshake failed, rc=%d\n",
__func__, rc);
return rc;
}
@@ -7265,7 +8014,7 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter)
if (adapter->mem_desc.rep_msg) {
dma_free_coherent(
&adapter->pdev->dev,
- adapter->adapter_attr.rep_msg_qd * LEAPRAID_REPLY_SIEZ,
+ adapter->adapter_attr.rep_msg_qd * LEAPRAID_REPLY_SIZE,
adapter->mem_desc.rep_msg,
adapter->mem_desc.rep_msg_dma);
adapter->mem_desc.rep_msg = NULL;
@@ -7283,15 +8032,19 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter)
if (adapter->mem_desc.rep_desc_seg_maint) {
for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt;
i++) {
- if (adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg) {
+ if (adapter->mem_desc.rep_desc_seg_maint[i]
+ .rep_desc_seg) {
dma_free_coherent(
&adapter->pdev->dev,
(adapter->adapter_attr.rep_desc_qd *
LEAPRAID_REP_DESC_ENTRY_SIZE) *
LEAPRAID_REP_DESC_CHUNK_SIZE,
- adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg,
- adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg_dma);
- adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg = NULL;
+ adapter->mem_desc.rep_desc_seg_maint[i]
+ .rep_desc_seg,
+ adapter->mem_desc.rep_desc_seg_maint[i]
+ .rep_desc_seg_dma);
+ adapter->mem_desc.rep_desc_seg_maint[i]
+ .rep_desc_seg = NULL;
}
}
@@ -7306,7 +8059,8 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter)
}
for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt; i++)
- kfree(adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_maint);
+ kfree(adapter->mem_desc.rep_desc_seg_maint[i]
+ .rep_desc_maint);
kfree(adapter->mem_desc.rep_desc_seg_maint);
}
@@ -7324,16 +8078,16 @@ static void leapraid_free_host_memory(struct leapraid_adapter *adapter)
static inline bool leapraid_is_in_same_4g_seg(dma_addr_t start, u32 size)
{
- return (upper_32_bits(start) == upper_32_bits(start + size - 1));
+ return upper_32_bits(start) == upper_32_bits(start + size - 1);
}
int leapraid_internal_init_cmd_priv(struct leapraid_adapter *adapter,
struct leapraid_io_req_tracker *io_tracker)
{
io_tracker->chain =
- dma_pool_alloc(adapter->mem_desc.sg_chain_pool,
- GFP_KERNEL,
- &io_tracker->chain_dma);
+ dma_pool_alloc(adapter->mem_desc.sg_chain_pool,
+ GFP_KERNEL,
+ &io_tracker->chain_dma);
if (!io_tracker->chain)
return -ENOMEM;
@@ -7360,17 +8114,16 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
unsigned int i, j;
int rc;
- /* sg table size */
+ /* Scatter-gather table size. */
adapter->shost->sg_tablesize = LEAPRAID_SG_DEPTH;
if (reset_devices)
adapter->shost->sg_tablesize =
LEAPRAID_KDUMP_MIN_PHYS_SEGMENTS;
- /* high priority cmds queue depth */
- adapter->dynamic_task_desc.hp_cmd_qd = facts->hp_slot;
+ /* High-priority commands queue depth. */
adapter->dynamic_task_desc.hp_cmd_qd = LEAPRAID_FIXED_HP_CMDS;
- /* internal cmds queue depth */
+ /* Internal commands queue depth. */
adapter->dynamic_task_desc.inter_cmd_qd = LEAPRAID_FIXED_INTER_CMDS;
- /* adapter cmds total queue depth */
+ /* Adapter commands total queue depth. */
if (reset_devices)
adapter->adapter_attr.adapter_total_qd =
LEAPRAID_DEFAULT_CMD_QD_OFFSET +
@@ -7379,22 +8132,22 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
else
adapter->adapter_attr.adapter_total_qd = facts->req_slot +
adapter->dynamic_task_desc.hp_cmd_qd;
- /* reply message queue depth */
+ /* Reply message queue depth. */
adapter->adapter_attr.rep_msg_qd =
adapter->adapter_attr.adapter_total_qd +
LEAPRAID_DEFAULT_CMD_QD_OFFSET;
- /* reply descriptor queue depth */
+ /* Reply descriptor queue depth. */
adapter->adapter_attr.rep_desc_qd =
round_up(adapter->adapter_attr.adapter_total_qd +
adapter->adapter_attr.rep_msg_qd +
LEAPRAID_TASKID_OFFSET_CTRL_CMD,
LEAPRAID_REPLY_QD_ALIGNMENT);
- /* scsi cmd io depth */
+ /* SCSI command I/O depth. */
adapter->adapter_attr.io_qd =
adapter->adapter_attr.adapter_total_qd -
adapter->dynamic_task_desc.hp_cmd_qd -
adapter->dynamic_task_desc.inter_cmd_qd;
- /* scsi host can queue */
+ /* SCSI host can queue. */
adapter->shost->can_queue = adapter->adapter_attr.io_qd -
LEAPRAID_TASKID_OFFSET_SCSIIO_CMD;
adapter->driver_cmds.ctl_cmd.taskid = adapter->shost->can_queue +
@@ -7403,7 +8156,7 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
adapter->shost->can_queue +
LEAPRAID_TASKID_OFFSET_SCSIIO_CMD;
- /* allocate task descriptor */
+ /* Allocate task descriptor. */
try_again:
adapter->adapter_attr.task_desc_dma_size =
(adapter->adapter_attr.adapter_total_qd +
@@ -7414,49 +8167,41 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
adapter->adapter_attr.task_desc_dma_size,
&adapter->mem_desc.task_desc_dma,
GFP_KERNEL);
- if (!adapter->mem_desc.task_desc) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate task descriptor DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
- /* allocate chain message pool */
+ if (!adapter->mem_desc.task_desc)
+ return -ENOMEM;
+
+ /* Allocate chain message pool. */
adapter->mem_desc.sg_chain_pool_size =
LEAPRAID_DEFAULT_CHAINS_PER_IO * LEAPRAID_CHAIN_SEG_SIZE;
adapter->mem_desc.sg_chain_pool =
dma_pool_create("leapraid chain pool",
&adapter->pdev->dev,
- adapter->mem_desc.sg_chain_pool_size, 16, 0);
- if (!adapter->mem_desc.sg_chain_pool) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate chain message DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
+ adapter->mem_desc.sg_chain_pool_size,
+ LEAPRAID_DMA_ALIGN, 0);
+ if (!adapter->mem_desc.sg_chain_pool)
+ return -ENOMEM;
- /* allocate io tracker to ref scsi io */
+ /* Allocate I/O tracker to SCSI I/O. */
adapter->mem_desc.io_tracker =
kcalloc(adapter->shost->can_queue,
sizeof(struct leapraid_io_req_tracker),
GFP_KERNEL);
- if (!adapter->mem_desc.io_tracker) {
- rc = -ENOMEM;
- goto out;
- }
+ if (!adapter->mem_desc.io_tracker)
+ return -ENOMEM;
for (i = 0; (int)i < adapter->shost->can_queue; i++) {
rc = leapraid_internal_init_cmd_priv(
adapter,
adapter->mem_desc.io_tracker + i);
if (rc)
- goto out;
+ goto out_fail;
}
adapter->dynamic_task_desc.hp_taskid =
adapter->adapter_attr.io_qd +
LEAPRAID_HP_TASKID_OFFSET_CTL_CMD;
- /* allocate static hp taskid */
+ /* Allocate static high-priority task ID. */
adapter->driver_cmds.ctl_cmd.hp_taskid =
adapter->dynamic_task_desc.hp_taskid;
adapter->driver_cmds.tm_cmd.hp_taskid =
@@ -7477,9 +8222,6 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
adapter->driver_cmds.timestamp_sync_cmd.inter_taskid =
adapter->dynamic_task_desc.inter_taskid +
LEAPRAID_TASKID_OFFSET_TIMESTAMP_SYNC_CMD;
- adapter->driver_cmds.raid_action_cmd.inter_taskid =
- adapter->dynamic_task_desc.inter_taskid +
- LEAPRAID_TASKID_OFFSET_RAID_ACTION_CMD;
adapter->driver_cmds.enc_cmd.inter_taskid =
adapter->dynamic_task_desc.inter_taskid +
LEAPRAID_TASKID_OFFSET_ENC_CMD;
@@ -7507,64 +8249,58 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
adapter->dynamic_task_desc.inter_taskid);
/*
- * allocate sense dma, driver maintain
- * need in same 4GB segment
+ * Allocate sense data DMA buffer.
+ * Constraint: Must reside within the same 4GB segment
+ * (driver-maintained).
*/
adapter->mem_desc.sense_data =
- dma_alloc_coherent(
+ dma_alloc_coherent(
&adapter->pdev->dev,
adapter->adapter_attr.io_qd * SCSI_SENSE_BUFFERSIZE,
- &adapter->mem_desc.sense_data_dma, GFP_KERNEL);
- if (!adapter->mem_desc.sense_data) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate sense data DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
+ &adapter->mem_desc.sense_data_dma,
+ GFP_KERNEL);
+ if (!adapter->mem_desc.sense_data)
+ return -ENOMEM;
+
if (!leapraid_is_in_same_4g_seg(adapter->mem_desc.sense_data_dma,
adapter->adapter_attr.io_qd *
SCSI_SENSE_BUFFERSIZE)) {
dev_warn(&adapter->pdev->dev,
- "try 32 bit dma due to sense data is not in same 4g!\n");
+ "Try 32bit DMA: Sense not in same 4G\n");
rc = -EAGAIN;
- goto out;
+ goto out_fail;
}
- /* reply frame, need in same 4GB segment */
+ /*
+ * Allocate reply frame buffer.
+ * Constraint: Must reside in the same 4GB segment as the sense DMA.
+ */
adapter->mem_desc.rep_msg =
- dma_alloc_coherent(&adapter->pdev->dev,
- adapter->adapter_attr.rep_msg_qd *
- LEAPRAID_REPLY_SIEZ,
- &adapter->mem_desc.rep_msg_dma,
- GFP_KERNEL);
- if (!adapter->mem_desc.rep_msg) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate reply message DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
+ dma_alloc_coherent(&adapter->pdev->dev,
+ adapter->adapter_attr.rep_msg_qd *
+ LEAPRAID_REPLY_SIZE,
+ &adapter->mem_desc.rep_msg_dma,
+ GFP_KERNEL);
+ if (!adapter->mem_desc.rep_msg)
+ return -ENOMEM;
if (!leapraid_is_in_same_4g_seg(adapter->mem_desc.rep_msg_dma,
adapter->adapter_attr.rep_msg_qd *
- LEAPRAID_REPLY_SIEZ)) {
+ LEAPRAID_REPLY_SIZE)) {
dev_warn(&adapter->pdev->dev,
- "use 32 bit dma due to rep msg is not in same 4g!\n");
+ "Use 32 bit DMA due to rep msg is not in same 4g!\n");
rc = -EAGAIN;
- goto out;
+ goto out_fail;
}
- /* address of reply frame */
+ /* Address of reply frame. */
adapter->mem_desc.rep_msg_addr =
- dma_alloc_coherent(&adapter->pdev->dev,
- adapter->adapter_attr.rep_msg_qd *
- LEAPRAID_REP_MSG_ADDR_SIZE,
- &adapter->mem_desc.rep_msg_addr_dma,
- GFP_KERNEL);
- if (!adapter->mem_desc.rep_msg_addr) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate reply message address DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
+ dma_alloc_coherent(&adapter->pdev->dev,
+ adapter->adapter_attr.rep_msg_qd *
+ LEAPRAID_REP_MSG_ADDR_SIZE,
+ &adapter->mem_desc.rep_msg_addr_dma,
+ GFP_KERNEL);
+ if (!adapter->mem_desc.rep_msg_addr)
+ return -ENOMEM;
adapter->adapter_attr.rep_desc_q_seg_cnt =
DIV_ROUND_UP(adapter->adapter_attr.rq_cnt,
LEAPRAID_REP_DESC_CHUNK_SIZE);
@@ -7572,10 +8308,8 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
kcalloc(adapter->adapter_attr.rep_desc_q_seg_cnt,
sizeof(struct leapraid_rep_desc_seg_maint),
GFP_KERNEL);
- if (!adapter->mem_desc.rep_desc_seg_maint) {
- rc = -ENOMEM;
- goto out;
- }
+ if (!adapter->mem_desc.rep_desc_seg_maint)
+ return -ENOMEM;
rep_desc_q_cnt_allocated = 0;
for (i = 0; i < adapter->adapter_attr.rep_desc_q_seg_cnt; i++) {
@@ -7583,25 +8317,20 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
kcalloc(LEAPRAID_REP_DESC_CHUNK_SIZE,
sizeof(struct leapraid_rep_desc_maint),
GFP_KERNEL);
- if (!adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_maint) {
- rc = -ENOMEM;
- goto out;
- }
+ if (!adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_maint)
+ return -ENOMEM;
adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg =
- dma_alloc_coherent(
+ dma_alloc_coherent(
&adapter->pdev->dev,
(adapter->adapter_attr.rep_desc_qd *
- LEAPRAID_REP_DESC_ENTRY_SIZE) *
+ LEAPRAID_REP_DESC_ENTRY_SIZE) *
LEAPRAID_REP_DESC_CHUNK_SIZE,
- &adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg_dma,
+ &adapter->mem_desc.rep_desc_seg_maint[i]
+ .rep_desc_seg_dma,
GFP_KERNEL);
- if (!adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate reply descriptor segment DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
+ if (!adapter->mem_desc.rep_desc_seg_maint[i].rep_desc_seg)
+ return -ENOMEM;
for (j = 0; j < LEAPRAID_REP_DESC_CHUNK_SIZE; j++) {
if (rep_desc_q_cnt_allocated >=
@@ -7634,30 +8363,26 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
if (!reset_devices) {
adapter->mem_desc.rep_desc_q_arr =
- dma_alloc_coherent(
+ dma_alloc_coherent(
&adapter->pdev->dev,
adapter->adapter_attr.rq_cnt *
LEAPRAID_REP_RQ_CNT_SIZE,
&adapter->mem_desc.rep_desc_q_arr_dma,
GFP_KERNEL);
- if (!adapter->mem_desc.rep_desc_q_arr) {
- dev_err(&adapter->pdev->dev,
- "failed to allocate reply descriptor queue array DMA!\n");
- rc = -ENOMEM;
- goto out;
- }
+ if (!adapter->mem_desc.rep_desc_q_arr)
+ return -ENOMEM;
}
return 0;
-out:
+out_fail:
if (rc == -EAGAIN) {
leapraid_free_host_memory(adapter);
- adapter->adapter_attr.use_32_dma_mask = true;
+ adapter->adapter_attr.use_32_dma_mask = 1;
rc = dma_set_mask_and_coherent(&adapter->pdev->dev,
- DMA_BIT_MASK(32));
+ DMA_BIT_MASK(DMA_32_BITS));
if (rc) {
dev_err(&adapter->pdev->dev,
- "failed to set 32 DMA mask\n");
+ "Failed to set 32 DMA mask\n");
return rc;
}
goto try_again;
@@ -7667,12 +8392,13 @@ static int leapraid_request_host_memory(struct leapraid_adapter *adapter)
static int leapraid_alloc_dev_topo_bitmaps(struct leapraid_adapter *adapter)
{
- adapter->dev_topo.pd_hdls_sz =
- adapter->adapter_attr.features.max_dev_handle /
- LEAPRAID_BITS_PER_BYTE;
- if (adapter->adapter_attr.features.max_dev_handle %
- LEAPRAID_BITS_PER_BYTE)
- adapter->dev_topo.pd_hdls_sz++;
+ u16 pd_hdls_sz;
+
+ pd_hdls_sz = adapter->adapter_attr.features.max_dev_handle /
+ LEAPRAID_BITS_PER_BYTE;
+ pd_hdls_sz++;
+
+ adapter->dev_topo.pd_hdls_sz = pd_hdls_sz;
adapter->dev_topo.pd_hdls =
kzalloc(adapter->dev_topo.pd_hdls_sz, GFP_KERNEL);
if (!adapter->dev_topo.pd_hdls)
@@ -7683,24 +8409,6 @@ static int leapraid_alloc_dev_topo_bitmaps(struct leapraid_adapter *adapter)
if (!adapter->dev_topo.blocking_hdls)
return -ENOMEM;
- adapter->dev_topo.pending_dev_add_sz =
- adapter->adapter_attr.features.max_dev_handle /
- LEAPRAID_BITS_PER_BYTE;
- if (adapter->adapter_attr.features.max_dev_handle %
- LEAPRAID_BITS_PER_BYTE)
- adapter->dev_topo.pending_dev_add_sz++;
- adapter->dev_topo.pending_dev_add =
- kzalloc(adapter->dev_topo.pending_dev_add_sz, GFP_KERNEL);
- if (!adapter->dev_topo.pending_dev_add)
- return -ENOMEM;
-
- adapter->dev_topo.dev_removing_sz =
- adapter->dev_topo.pending_dev_add_sz;
- adapter->dev_topo.dev_removing =
- kzalloc(adapter->dev_topo.dev_removing_sz, GFP_KERNEL);
- if (!adapter->dev_topo.dev_removing)
- return -ENOMEM;
-
return 0;
}
@@ -7708,13 +8416,11 @@ static void leapraid_free_dev_topo_bitmaps(struct leapraid_adapter *adapter)
{
kfree(adapter->dev_topo.pd_hdls);
kfree(adapter->dev_topo.blocking_hdls);
- kfree(adapter->dev_topo.pending_dev_add);
- kfree(adapter->dev_topo.dev_removing);
}
static int leapraid_init_driver_cmds(struct leapraid_adapter *adapter)
{
- u32 buffer_size = 0;
+ u32 buffer_size;
void *buffer;
INIT_LIST_HEAD(&adapter->driver_cmds.special_cmd_list);
@@ -7767,15 +8473,14 @@ static int leapraid_init_driver_cmds(struct leapraid_adapter *adapter)
return -ENOMEM;
adapter->driver_cmds.internal_scmd = buffer;
- buffer = (void *)((u8 *)buffer +
- sizeof(struct scsi_cmnd) +
- sizeof(struct leapraid_io_req_tracker));
+ buffer = (u8 *)buffer + sizeof(struct scsi_cmnd) +
+ sizeof(struct leapraid_io_req_tracker);
adapter->driver_cmds.internal_scmd->sense_buffer =
- (unsigned char *)buffer;
- buffer = (void *)((u8 *)buffer + SCSI_SENSE_BUFFERSIZE);
+ (unsigned char *)buffer;
+ buffer = (u8 *)buffer + SCSI_SENSE_BUFFERSIZE;
adapter->driver_cmds.internal_scmd->sdb.table.sgl =
- (struct scatterlist *)buffer;
- buffer = (void *)((u8 *)buffer + sizeof(struct scatterlist));
+ (struct scatterlist *)buffer;
+ buffer = (u8 *)buffer + sizeof(struct scatterlist);
adapter->driver_cmds.internal_scmd->cmnd = buffer;
adapter->driver_cmds.internal_scmd->host_scribble =
(unsigned char *)(adapter->driver_cmds.internal_scmd + 1);
@@ -7821,32 +8526,34 @@ static void leapraid_init_event_mask(struct leapraid_adapter *adapter)
int i;
for (i = 0; i < LEAPRAID_EVT_MASK_COUNT; i++)
- adapter->fw_evt_s.leapraid_evt_masks[i] = -1;
- leapraid_unmask_evts(adapter, LEAPRAID_EVT_SAS_DISCOVERY);
+ adapter->fw_evt_s.leapraid_evt_masks[i] =
+ LEAPRAID_INVALID_INITIAL_VALUE;
+
leapraid_unmask_evts(adapter, LEAPRAID_EVT_SAS_TOPO_CHANGE_LIST);
leapraid_unmask_evts(adapter, LEAPRAID_EVT_SAS_ENCL_DEV_STATUS_CHANGE);
leapraid_unmask_evts(adapter, LEAPRAID_EVT_SAS_DEV_STATUS_CHANGE);
leapraid_unmask_evts(adapter, LEAPRAID_EVT_IR_CHANGE);
}
-static void leapraid_prepare_adp_init_req(
+static void leapraid_prepare_adapter_init_req(
struct leapraid_adapter *adapter,
struct leapraid_adapter_init_req *init_req)
{
ktime_t cur_time;
- int i;
+ int i, chunk;
u32 reply_post_free_ary_sz;
memset(init_req, 0, sizeof(struct leapraid_adapter_init_req));
init_req->func = LEAPRAID_FUNC_ADAPTER_INIT;
init_req->who_init = LEAPRAID_WHOINIT_LINUX_DRIVER;
- init_req->msg_ver = cpu_to_le16(0x0100);
- init_req->header_ver = cpu_to_le16(0x0000);
-
- init_req->driver_ver = cpu_to_le32((LEAPRAID_MAJOR_VERSION << 24) |
- (LEAPRAID_MINOR_VERSION << 16) |
- (LEAPRAID_BUILD_VERSION << 8) |
- LEAPRAID_RELEASE_VERSION);
+ init_req->msg_ver = cpu_to_le16(LEAPRAID_MSG_VERSION);
+ init_req->header_ver = cpu_to_le16(LEAPRAID_HEADER_VERSION);
+ init_req->driver_ver =
+ cpu_to_le32((LEAPRAID_MAJOR_VERSION <<
+ LEAPRAID_VER_MAJOR_SHIFT) |
+ (LEAPRAID_MINOR_VERSION << LEAPRAID_VER_MINOR_SHIFT) |
+ (LEAPRAID_BUILD_VERSION << LEAPRAID_VER_BUILD_SHIFT) |
+ LEAPRAID_RELEASE_VERSION);
if (adapter->notification_desc.msix_enable)
init_req->host_msix_vectors = adapter->adapter_attr.rq_cnt;
@@ -7870,18 +8577,13 @@ static void leapraid_prepare_adp_init_req(
memset(adapter->mem_desc.rep_desc_q_arr, 0,
reply_post_free_ary_sz);
- for (i = 0; i < adapter->adapter_attr.rq_cnt; i++) {
- adapter->mem_desc
- .rep_desc_q_arr[i]
- .rep_desc_base_addr =
- cpu_to_le64 (
- (u64)adapter->mem_desc
- .rep_desc_seg_maint[i /
- LEAPRAID_REP_DESC_CHUNK_SIZE]
- .rep_desc_maint[i %
- LEAPRAID_REP_DESC_CHUNK_SIZE]
- .rep_desc_dma);
- }
+ chunk = LEAPRAID_REP_DESC_CHUNK_SIZE;
+ for (i = 0; i < adapter->adapter_attr.rq_cnt; i++)
+ adapter->mem_desc.rep_desc_q_arr[i].rep_desc_base_addr =
+ cpu_to_le64 ((u64)adapter->mem_desc
+ .rep_desc_seg_maint[i / chunk]
+ .rep_desc_maint[i % chunk]
+ .rep_desc_dma);
init_req->msg_flg =
LEAPRAID_ADAPTER_INIT_MSGFLG_RDPQ_ARRAY_MODE;
@@ -7903,9 +8605,9 @@ static int leapraid_send_adapter_init(struct leapraid_adapter *adapter)
struct leapraid_adapter_init_req init_req;
struct leapraid_adapter_init_rep init_rep;
u16 adapter_status;
- int rc = 0;
+ int rc;
- leapraid_prepare_adp_init_req(adapter, &init_req);
+ leapraid_prepare_adapter_init_req(adapter, &init_req);
rc = leapraid_handshake_func(adapter,
sizeof(struct leapraid_adapter_init_req),
@@ -7913,7 +8615,7 @@ static int leapraid_send_adapter_init(struct leapraid_adapter *adapter)
sizeof(struct leapraid_adapter_init_rep),
(u16 *)&init_rep);
if (rc != 0) {
- dev_err(&adapter->pdev->dev, "%s: handshake failed, rc=%d\n",
+ dev_err(&adapter->pdev->dev, "%s: Handshake failed, rc=%d\n",
__func__, rc);
return rc;
}
@@ -7934,11 +8636,10 @@ static int leapraid_cfg_pages(struct leapraid_adapter *adapter)
{
union cfg_param_1 cfgp1 = {0};
union cfg_param_2 cfgp2 = {0};
- struct leapraid_sas_io_unit_page1 *sas_io_unit_page1 = NULL;
+ struct leapraid_manufacturing_p0 manufacturing_page0;
struct leapraid_bios_page3 bios_page3;
struct leapraid_bios_page2 bios_page2;
- int rc = 0;
- int sz;
+ int rc;
rc = leapraid_op_config_page(adapter, &bios_page3, cfgp1,
cfgp2, GET_BIOS_PG3);
@@ -7950,79 +8651,49 @@ static int leapraid_cfg_pages(struct leapraid_adapter *adapter)
if (rc)
return rc;
+ rc = leapraid_op_config_page(adapter, &manufacturing_page0, cfgp1,
+ cfgp2, GET_MANUFACTURING_PG0);
+ if (rc)
+ return rc;
+
adapter->adapter_attr.bios_version =
le32_to_cpu(bios_page3.bios_version);
- adapter->adapter_attr.wideport_max_queue_depth =
- LEAPRAID_SAS_QUEUE_DEPTH;
- adapter->adapter_attr.narrowport_max_queue_depth =
- LEAPRAID_SAS_QUEUE_DEPTH;
- adapter->adapter_attr.sata_max_queue_depth =
- LEAPRAID_SATA_QUEUE_DEPTH;
-
+ 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;
- memcpy((void *)adapter->boot_devs.requested_boot_dev.pg_dev,
- (void *)&bios_page2.requested_boot_dev,
+ memcpy(adapter->boot_devs.requested_boot_dev.pg_dev,
+ &bios_page2.requested_boot_dev,
LEAPRAID_BOOT_DEV_SIZE);
adapter->boot_devs.requested_alt_boot_dev.form =
bios_page2.requested_alt_boot_dev_form;
- memcpy((void *)adapter->boot_devs.requested_alt_boot_dev.pg_dev,
- (void *)&bios_page2.requested_alt_boot_dev,
+ memcpy(adapter->boot_devs.requested_alt_boot_dev.pg_dev,
+ &bios_page2.requested_alt_boot_dev,
LEAPRAID_BOOT_DEV_SIZE);
adapter->boot_devs.current_boot_dev.form =
bios_page2.current_boot_dev_form;
- memcpy((void *)adapter->boot_devs.current_boot_dev.pg_dev,
- (void *)&bios_page2.current_boot_dev,
+ memcpy(adapter->boot_devs.current_boot_dev.pg_dev,
+ &bios_page2.current_boot_dev,
LEAPRAID_BOOT_DEV_SIZE);
-
- sz = offsetof(struct leapraid_sas_io_unit_page1, phy_info);
- sas_io_unit_page1 = kzalloc(sz, GFP_KERNEL);
- if (!sas_io_unit_page1) {
- rc = -ENOMEM;
- return rc;
- }
-
- cfgp1.size = sz;
-
- rc = leapraid_op_config_page(adapter, sas_io_unit_page1, cfgp1,
- cfgp2, GET_SAS_IOUNIT_PG1);
- if (rc)
- goto out;
-
- if (le16_to_cpu(sas_io_unit_page1->wideport_max_queue_depth))
- adapter->adapter_attr.wideport_max_queue_depth =
- le16_to_cpu(
- sas_io_unit_page1->wideport_max_queue_depth);
-
- if (le16_to_cpu(sas_io_unit_page1->narrowport_max_queue_depth))
- adapter->adapter_attr.narrowport_max_queue_depth =
- le16_to_cpu(
- sas_io_unit_page1->narrowport_max_queue_depth);
-
- if (sas_io_unit_page1->sata_max_queue_depth)
- adapter->adapter_attr.sata_max_queue_depth =
- sas_io_unit_page1->sata_max_queue_depth;
-
-out:
- kfree(sas_io_unit_page1);
- dev_info(&adapter->pdev->dev,
- "max wp qd=%d, max np qd=%d, max sata qd=%d\n",
- adapter->adapter_attr.wideport_max_queue_depth,
- adapter->adapter_attr.narrowport_max_queue_depth,
- adapter->adapter_attr.sata_max_queue_depth);
return rc;
}
static int leapraid_evt_notify(struct leapraid_adapter *adapter)
{
struct leapraid_evt_notify_req *evt_notify_req;
+ struct leapraid_evt_notify_rep *evt_notify_rep;
+ u16 adapter_status;
int rc = 0;
int i;
mutex_lock(&adapter->driver_cmds.notify_event_cmd.mutex);
adapter->driver_cmds.notify_event_cmd.status = LEAPRAID_CMD_PENDING;
evt_notify_req =
- leapraid_get_task_desc(adapter,
+ leapraid_get_task_desc(
+ adapter,
adapter->driver_cmds.notify_event_cmd.inter_taskid);
memset(evt_notify_req, 0, sizeof(struct leapraid_evt_notify_req));
evt_notify_req->func = LEAPRAID_FUNC_EVENT_NOTIFY;
@@ -8031,15 +8702,30 @@ static int leapraid_evt_notify(struct leapraid_adapter *adapter)
cpu_to_le32(adapter->fw_evt_s.leapraid_evt_masks[i]);
init_completion(&adapter->driver_cmds.notify_event_cmd.done);
leapraid_fire_task(adapter,
- adapter->driver_cmds.notify_event_cmd.inter_taskid);
+ adapter->driver_cmds.notify_event_cmd.inter_taskid);
wait_for_completion_timeout(
&adapter->driver_cmds.notify_event_cmd.done,
LEAPRAID_NOTIFY_EVENT_CMD_TIMEOUT * HZ);
+
if (!(adapter->driver_cmds.notify_event_cmd.status &
- LEAPRAID_CMD_DONE))
- if (adapter->driver_cmds.notify_event_cmd.status &
- LEAPRAID_CMD_RESET)
- rc = -EFAULT;
+ LEAPRAID_CMD_DONE)) {
+ rc = -EFAULT;
+ goto out_cleanup;
+ }
+
+ if (!(adapter->driver_cmds.notify_event_cmd.status &
+ LEAPRAID_CMD_REPLY_VALID)) {
+ rc = -EFAULT;
+ goto out_cleanup;
+ }
+
+ evt_notify_rep = (void *)&adapter->driver_cmds.notify_event_cmd.reply;
+ adapter_status = le16_to_cpu(evt_notify_rep->adapter_status) &
+ LEAPRAID_ADAPTER_STATUS_MASK;
+ if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS)
+ rc = -EFAULT;
+
+out_cleanup:
adapter->driver_cmds.notify_event_cmd.status = LEAPRAID_CMD_NOT_USED;
mutex_unlock(&adapter->driver_cmds.notify_event_cmd.mutex);
@@ -8054,51 +8740,54 @@ int leapraid_scan_dev(struct leapraid_adapter *adapter, bool async_scan_dev)
int rc = 0;
dev_info(&adapter->pdev->dev,
- "send device scan, async_scan_dev=%d!\n", async_scan_dev);
+ "Send device scan, async_scan_dev=%d!\n", async_scan_dev);
adapter->driver_cmds.scan_dev_cmd.status = LEAPRAID_CMD_PENDING;
adapter->driver_cmds.scan_dev_cmd.async_scan_dev = async_scan_dev;
- scan_dev_req = leapraid_get_task_desc(adapter,
- adapter->driver_cmds.scan_dev_cmd.inter_taskid);
+ scan_dev_req =
+ leapraid_get_task_desc(
+ adapter,
+ adapter->driver_cmds.scan_dev_cmd.inter_taskid);
memset(scan_dev_req, 0, sizeof(struct leapraid_scan_dev_req));
scan_dev_req->func = LEAPRAID_FUNC_SCAN_DEV;
if (async_scan_dev) {
- adapter->scan_dev_desc.first_scan_dev_fired = true;
- leapraid_fire_task(adapter,
+ adapter->scan_dev_desc.first_scan_dev_fired = 1;
+ leapraid_fire_task(
+ adapter,
adapter->driver_cmds.scan_dev_cmd.inter_taskid);
return 0;
}
init_completion(&adapter->driver_cmds.scan_dev_cmd.done);
leapraid_fire_task(adapter,
- adapter->driver_cmds.scan_dev_cmd.inter_taskid);
+ adapter->driver_cmds.scan_dev_cmd.inter_taskid);
wait_for_completion_timeout(&adapter->driver_cmds.scan_dev_cmd.done,
LEAPRAID_SCAN_DEV_CMD_TIMEOUT * HZ);
if (!(adapter->driver_cmds.scan_dev_cmd.status & LEAPRAID_CMD_DONE)) {
- dev_err(&adapter->pdev->dev, "device scan timeout!\n");
+ dev_err(&adapter->pdev->dev, "Device scan timeout!\n");
if (adapter->driver_cmds.scan_dev_cmd.status &
LEAPRAID_CMD_RESET)
rc = -EFAULT;
else
rc = -ETIME;
- goto out;
+ goto out_cleanup;
}
- scan_dev_rep = (void *)(&adapter->driver_cmds.scan_dev_cmd.reply);
+ scan_dev_rep = (void *)&adapter->driver_cmds.scan_dev_cmd.reply;
adapter_status =
le16_to_cpu(scan_dev_rep->adapter_status) &
LEAPRAID_ADAPTER_STATUS_MASK;
if (adapter_status != LEAPRAID_ADAPTER_STATUS_SUCCESS) {
- dev_err(&adapter->pdev->dev, "device scan failure!\n");
+ dev_err(&adapter->pdev->dev, "Device scan failure!\n");
rc = -EFAULT;
- goto out;
+ goto out_cleanup;
}
-out:
+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"));
+ "Device scan %s\n", rc == 0 ? "SUCCESS" : "FAILED");
return rc;
}
@@ -8125,13 +8814,14 @@ static void leapraid_init_rep_msg_addr(struct leapraid_adapter *adapter)
for (i = 0, reply_address = (u32)adapter->mem_desc.rep_msg_dma;
i < adapter->adapter_attr.rep_msg_qd;
- i++, reply_address += LEAPRAID_REPLY_SIEZ) {
+ i++, reply_address += LEAPRAID_REPLY_SIZE)
adapter->mem_desc.rep_msg_addr[i] = cpu_to_le32(reply_address);
- }
}
-static void init_rep_desc(struct leapraid_rq *rq, int index,
- union leapraid_rep_desc_union *reply_post_free_contig)
+static void init_rep_desc(
+ struct leapraid_rq *rq,
+ int index,
+ union leapraid_rep_desc_union *reply_post_free_contig)
{
struct leapraid_adapter *adapter = rq->adapter;
unsigned int i;
@@ -8218,7 +8908,7 @@ static void leapraid_init_bar_idx_regs(struct leapraid_adapter *adapter)
static int leapraid_make_adapter_available(struct leapraid_adapter *adapter)
{
- int rc = 0;
+ int rc;
leapraid_init_task_tracker(adapter);
leapraid_init_rep_msg_addr(adapter);
@@ -8242,7 +8932,7 @@ static int leapraid_make_adapter_available(struct leapraid_adapter *adapter)
return rc;
if (!adapter->access_ctrl.shost_recovering) {
- adapter->scan_dev_desc.wait_scan_dev_done = true;
+ adapter->scan_dev_desc.wait_scan_dev_done = 1;
return 0;
}
@@ -8256,45 +8946,45 @@ static int leapraid_make_adapter_available(struct leapraid_adapter *adapter)
int leapraid_ctrl_init(struct leapraid_adapter *adapter)
{
u32 cap;
- int rc = 0;
+ int rc;
rc = leapraid_set_pcie_and_notification(adapter);
if (rc)
- goto out_free_resources;
+ goto out_free;
pci_set_drvdata(adapter->pdev, adapter->shost);
pcie_capability_read_dword(adapter->pdev, PCI_EXP_DEVCAP, &cap);
- if (cap & PCI_EXP_DEVCAP_EXT_TAG) {
+ if (cap & PCI_EXP_DEVCAP_EXT_TAG)
pcie_capability_set_word(adapter->pdev, PCI_EXP_DEVCTL,
PCI_EXP_DEVCTL_EXT_TAG);
- }
rc = leapraid_fw_log_init(adapter);
if (rc) {
- dev_err(&adapter->pdev->dev, "fw log init failure\n");
- goto out_free_resources;
+ dev_err(&adapter->pdev->dev, "FW log init failure\n");
+ goto out_free;
}
rc = leapraid_request_host_memory(adapter);
if (rc) {
- dev_err(&adapter->pdev->dev, "request host memory failure\n");
- goto out_free_resources;
+ dev_err(&adapter->pdev->dev, "Request host memory failure\n");
+ goto out_free;
}
init_waitqueue_head(&adapter->reset_desc.reset_wait_queue);
+ init_waitqueue_head(&adapter->access_ctrl.shost_recover_wq);
rc = leapraid_alloc_dev_topo_bitmaps(adapter);
if (rc) {
- dev_err(&adapter->pdev->dev, "alloc topo bitmaps failure\n");
- goto out_free_resources;
+ dev_err(&adapter->pdev->dev, "Alloc topo bitmaps failure\n");
+ goto out_free;
}
rc = leapraid_init_driver_cmds(adapter);
if (rc) {
- dev_err(&adapter->pdev->dev, "init driver cmds failure\n");
- goto out_free_resources;
+ dev_err(&adapter->pdev->dev, "Init driver cmds failure\n");
+ goto out_free;
}
leapraid_init_event_mask(adapter);
@@ -8302,14 +8992,23 @@ int leapraid_ctrl_init(struct leapraid_adapter *adapter)
rc = leapraid_make_adapter_available(adapter);
if (rc) {
dev_err(&adapter->pdev->dev,
- "make adapter available failure\n");
- goto out_free_resources;
+ "Make adapter available failure\n");
+ goto out_free;
}
+
+ leapraid_overheat_init(adapter);
+ if (!adapter->overheat_desc.fault_overheat_wq) {
+ rc = -ENOMEM;
+ goto out_free;
+ }
+
return 0;
-out_free_resources:
- adapter->access_ctrl.host_removing = true;
+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);
@@ -8319,9 +9018,11 @@ int leapraid_ctrl_init(struct leapraid_adapter *adapter)
void leapraid_remove_ctrl(struct leapraid_adapter *adapter)
{
+ leapraid_overheat_cleanup(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);
diff --git a/drivers/scsi/leapraid/leapraid_func.h b/drivers/scsi/leapraid/leapraid_func.h
index 15293922aefa..359802578586 100644
--- a/drivers/scsi/leapraid/leapraid_func.h
+++ b/drivers/scsi/leapraid/leapraid_func.h
@@ -1,16 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Copyright (C) 2025 LeapIO Tech Inc.
+ * Copyright (C) 2026 LeapIO Tech Inc.
*
- * LeapRAID Storage and RAID Controller driver.
+ * LeapRAID storage and RAID controller driver.
*/
-
#ifndef LEAPRAID_FUNC_H_INCLUDED
#define LEAPRAID_FUNC_H_INCLUDED
#include <linux/pci.h>
#include <linux/aer.h>
#include <linux/poll.h>
+#include <linux/atomic.h>
#include <linux/errno.h>
#include <linux/ktime.h>
#include <linux/delay.h>
@@ -27,9 +27,9 @@
#include "leapraid.h"
-/* some requset and reply buffer size */
+/* Request and reply buffer size. */
#define LEAPRAID_REQUEST_SIZE 128
-#define LEAPRAID_REPLY_SIEZ 128
+#define LEAPRAID_REPLY_SIZE 128
#define LEAPRAID_CHAIN_SEG_SIZE 128
#define LEAPRAID_MAX_SGES_IN_CHAIN 7
#define LEAPRAID_DEFAULT_CHAINS_PER_IO 19
@@ -44,61 +44,68 @@
#define LEAPRAID_SYS_LOG_BUF_SIZE 0x200000
#define LEAPRAID_SYS_LOG_BUF_RESERVE 0x1000
-/* Driver version and name */
+/* Driver version and name. */
#define LEAPRAID_DRIVER_NAME "LeapRAID"
#define LEAPRAID_NAME_LENGTH 48
+#define LEAPRAID_BOARD_NAME_LENGTH 17
#define LEAPRAID_AUTHOR "LeapIO Inc."
#define LEAPRAID_DESCRIPTION "LeapRAID Driver"
-#define LEAPRAID_DRIVER_VERSION "2.00.00.06"
+#define LEAPRAID_DRIVER_VERSION "2.00.01.02"
#define LEAPRAID_MAJOR_VERSION 2
#define LEAPRAID_MINOR_VERSION 00
-#define LEAPRAID_BUILD_VERSION 00
-#define LEAPRAID_RELEASE_VERSION 06
+#define LEAPRAID_BUILD_VERSION 01
+#define LEAPRAID_RELEASE_VERSION 02
+#define LEAPRAID_MSG_VERSION 0x1021
+#define LEAPRAID_HEADER_VERSION 0x0000
-/* Device ID */
+/* Device ID. */
#define LEAPRAID_VENDOR_ID 0xD405
#define LEAPRAID_DEVID_HBA 0x8200
-#define LEAPRAID_DEVID_RAID 0x8201
+#define LEAPRAID_SUBVENDOR_ID 0xD405
+#define LEAPRAID_SUBDEVID_HBA 0x8200
#define LEAPRAID_PCI_VENDOR_ID_MASK 0xFFFF
- /* RAID virtual channel ID */
+ /* RAID virtual channel ID. */
#define RAID_CHANNEL 1
-/* Scatter/Gather (SG) segment limits */
+/* Scatter-gather (SG) segment limits. */
#define LEAPRAID_MAX_PHYS_SEGMENTS SG_CHUNK_SIZE
#define LEAPRAID_KDUMP_MIN_PHYS_SEGMENTS 32
#define LEAPRAID_SG_DEPTH LEAPRAID_MAX_PHYS_SEGMENTS
-/* firmware / config page operations */
+/* Firmware and config page operations. */
#define LEAPRAID_SET_PARAMETER_SYNC_TIMESTAMP 0x81
#define LEAPRAID_CFG_REQ_RETRY_TIMES 2
-/* Hardware access helpers*/
+/* Hardware access helpers. */
#define leapraid_readl(addr) readl(addr)
#define leapraid_check_reset(status) \
(!((status) & LEAPRAID_CMD_RESET))
-/* Polling intervals */
+/* 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 */
+/* Init mask. */
#define LEAPRAID_RESET_IRQ_MASK 0x40000000
#define LEAPRAID_REPLY_INT_MASK 0x00000008
#define LEAPRAID_TO_SYS_DB_MASK 0x00000001
-/* queue depth */
+/* Queue depth. */
#define LEAPRAID_SATA_QUEUE_DEPTH 32
-#define LEAPRAID_SAS_QUEUE_DEPTH 254
-#define LEAPRAID_RAID_QUEUE_DEPTH 128
+#define LEAPRAID_SAS_QUEUE_DEPTH 64
+#define LEAPRAID_RAID_QUEUE_DEPTH 64
+
+/* 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 8192
-#define LEAPRAID_DEF_MAX_SECTORS 32767
+/* SCSI device and queue limits. */
+#define LEAPRAID_MAX_SECTORS 2048
#define LEAPRAID_MAX_CDB_LEN 32
#define LEAPRAID_MAX_LUNS 16384
#define LEAPRAID_CAN_QUEUE_MIN 1
@@ -106,136 +113,166 @@
#define LEAPRAID_CMD_PER_LUN 128
#define LEAPRAID_MAX_SEGMENT_SIZE 0xffffffff
-/* SCSI sense and ASC/ASCQ and disk geometry configuration */
+/* SCSI sense and ASC/ASCQ and disk geometry configuration. */
#define DESC_FORMAT_THRESHOLD 0x72
#define SENSE_KEY_MASK 0x0F
#define SCSI_SENSE_RESPONSE_CODE_MASK 0x7F
#define ASC_FAILURE_PREDICTION_THRESHOLD_EXCEEDED 0x5D
-#define LEAPRAID_LARGE_DISK_THRESHOLD 0x200000UL /* in sectors, 1GB */
+#define LEAPRAID_LARGE_DISK_THRESHOLD 0x200000UL
#define LEAPRAID_LARGE_DISK_HEADS 255
#define LEAPRAID_LARGE_DISK_SECTORS 63
#define LEAPRAID_SMALL_DISK_HEADS 64
#define LEAPRAID_SMALL_DISK_SECTORS 32
-/* SMP (Serial Management Protocol) */
+/* 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
-/* SCSI ASC/ASCQ definitions */
+/* SCSI ASC/ASCQ definitions. */
#define LEAPRAID_SCSI_ASCQ_DEFAULT 0x00
#define LEAPRAID_SCSI_ASC_POWER_ON_RESET 0x29
#define LEAPRAID_SCSI_ASC_INVALID_CMD_CODE 0x20
#define LEAPRAID_SCSI_ASCQ_POWER_ON_RESET 0x07
-/* ---- VPD Page 0x89 (ATA Information) ---- */
+/* VPD Page 0x89 (ATA Information). */
#define LEAPRAID_VPD_PAGE_ATA_INFO 0x89
#define LEAPRAID_VPD_PG89_MAX_LEN 255
#define LEAPRAID_VPD_PG89_MIN_LEN 214
-/* Byte index for NCQ support flag in VPD Page 0x89 */
+/* Byte index for NCQ support flag in VPD page 0x89. */
#define LEAPRAID_VPD_PG89_NCQ_BYTE_IDX 213
#define LEAPRAID_VPD_PG89_NCQ_BIT_SHIFT 4
#define LEAPRAID_VPD_PG89_NCQ_BIT_MASK 0x1
-/* readiness polling: max retries, sleep µs between */
+/* Readiness polling: max retries, sleep µs between. */
#define LEAPRAID_ADAPTER_READY_MAX_RETRY 15000
#define LEAPRAID_ADAPTER_READY_SLEEP_MIN_US 1000
#define LEAPRAID_ADAPTER_READY_SLEEP_MAX_US 1100
-/* Doorbell wait parameters */
+/* Doorbell wait parameters. */
#define LEAPRAID_DB_WAIT_MAX_RETRY 20000
#define LEAPRAID_DB_WAIT_DELAY_US 500
-/* Basic data size definitions */
+/* Basic data size definitions. */
#define LEAPRAID_DWORDS_BYTE_SIZE 4
#define LEAPRAID_WORD_BYTE_SIZE 2
-/* SGL threshold and chain offset*/
+/* SGL threshold and chain offset. */
#define LEAPRAID_SGL_INLINE_THRESHOLD 2
#define LEAPRAID_CHAIN_OFFSET_DWORDS 7
-/* MSI-X group size and mask */
+/* MSI-X group size and mask. */
#define LEAPRAID_MSIX_GROUP_SIZE 8
#define LEAPRAID_MSIX_GROUP_MASK 7
-/* basic constants and limits */
+/* 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 */
+/* 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
+#define LEAPRAID_WRSEQ_3RD_KEY_VALUE 0xB
+#define LEAPRAID_WRSEQ_4TH_KEY_VALUE 0x2
+#define LEAPRAID_WRSEQ_5TH_KEY_VALUE 0x7
+#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_LONG_MS 256
#define LEAPRAID_MSLEEP_EXTRA_LONG_MS 500
#define LEAPRAID_IO_POLL_DELAY_US 500
-/* controller reset loop parameters */
-#define LEAPRAID_RESET_LOOP_COUNT_REF (300000 / 256)
-#define LEAPRAID_RESET_LOOP_COUNT_DEFAULT 10000
-#define LEAPRAID_RESET_POLL_INTERVAL_MS 500
-
-/* Device / Volume configuration */
+/* Device/Volume configuration. */
#define LEAPRAID_MAX_VOLUMES_DEFAULT 32
#define LEAPRAID_MAX_DEV_HANDLE_DEFAULT 2048
#define LEAPRAID_INVALID_DEV_HANDLE 0xFFFF
-/* cmd queue depth */
+/* 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 */
+/* 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_CFG_OP_CMD 1
#define LEAPRAID_TASKID_OFFSET_TRANSPORT_CMD 2
#define LEAPRAID_TASKID_OFFSET_TIMESTAMP_SYNC_CMD 3
-#define LEAPRAID_TASKID_OFFSET_RAID_ACTION_CMD 4
-#define LEAPRAID_TASKID_OFFSET_ENC_CMD 5
-#define LEAPRAID_TASKID_OFFSET_NOTIFY_EVENT_CMD 6
+#define LEAPRAID_TASKID_OFFSET_ENC_CMD 4
+#define LEAPRAID_TASKID_OFFSET_NOTIFY_EVENT_CMD 5
-/* task id offset for high-priority */
+/* Task ID offset for high-priority. */
#define LEAPRAID_HP_TASKID_OFFSET_CTL_CMD 0
#define LEAPRAID_HP_TASKID_OFFSET_TM_CMD 1
-/* Event / Boot configuration */
+/* Event/Boot configuration. */
#define LEAPRAID_EVT_MASK_COUNT 4
#define LEAPRAID_BOOT_DEV_SIZE 24
-/* logsense command definitions */
+/* Commands timeout. */
+#define LEAPRAID_UNIFIED_TIMEOUT 30
+#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 5
+#define LEAPRAID_LOGSENSE_TIMEOUT LEAPRAID_UNIFIED_TIMEOUT
#define LEAPRAID_LOGSENSE_SMART_CODE 0x5D
-/* cmd timeout */
-#define LEAPRAID_DRIVER_SCSIIO_CMD_TIMEOUT LEAPRAID_LOGSENSE_TIMEOUT
-#define LEAPRAID_CFG_OP_TIMEOUT 15
-#define LEAPRAID_CTL_CMD_TIMEOUT 10
-#define LEAPRAID_SCAN_DEV_CMD_TIMEOUT 300
-#define LEAPRAID_TIMESTAMP_SYNC_CMD_TIMEOUT 10
-#define LEAPRAID_RAID_ACTION_CMD_TIMEOUT 10
-#define LEAPRAID_ENC_CMD_TIMEOUT 10
-#define LEAPRAID_NOTIFY_EVENT_CMD_TIMEOUT 30
-#define LEAPRAID_TM_CMD_TIMEOUT 30
-#define LEAPRAID_TRANSPORT_CMD_TIMEOUT 10
+/* Host DMA cap. */
+#define DMA_32_BITS 32
+#define DMA_64_BITS 64
+#define LEAPRAID_DMA_ALIGN 16
+
+/* Values used to represent an invalid. */
+#define LEAPRAID_INVALID_INDEX -1
+#define LEAPRAID_INVALID_MSIX_VECTORS -1
+#define LEAPRAID_INVALID_INITIAL_VALUE -1
+#define LEAPRAID_OPERATION_FAILED -1
+
+/* Version shift and mask. */
+#define LEAPRAID_VER_MAJOR_SHIFT 24
+#define LEAPRAID_VER_MINOR_SHIFT 16
+#define LEAPRAID_VER_BUILD_SHIFT 8
+#define LEAPRAID_VER_MASK 0xFF
+
+/* Interrupt type. */
+#define LEAPRAID_INTERRUPT_MODE_MSIX 0
+#define LEAPRAID_INTERRUPT_MODE_MSI 1
+#define LEAPRAID_INTERRUPT_MODE_LEGACY 2
+
+/* SMP link reset. */
+#define SMP_PHY_CONTROL_LINK_RESET 0x01
+#define SMP_PHY_CONTROL_HARD_RESET 0x02
+#define SMP_PHY_CONTROL_DISABLE 0x03
/**
- * struct leapraid_adapter_features - Features and
- * capabilities of a LeapRAID adapter
+ * struct leapraid_adapter_features - Adapter features/capabilities.
*
- * @req_slot: Number of request slots supported by the adapter
- * @hp_slot: Number of high-priority slots supported by the adapter
- * @adapter_caps: Adapter capabilities
- * @fw_version: Firmware version of the adapter
- * @max_dev_handle: Maximum device supported by the adapter
+ * @req_slot: Number of request slots supported by the adapter.
+ * @hp_slot: Number of high-priority slots supported by the adapter.
+ * @adapter_caps: Adapter capabilities.
+ * @fw_version: Firmware version of the adapter.
+ * @max_dev_handle: Maximum device handle supported by the adapter.
+ * @min_dev_handle: Minimum device handle supported by the adapter.
*/
struct leapraid_adapter_features {
u16 req_slot;
@@ -251,32 +288,35 @@ struct leapraid_adapter_features {
/**
* struct leapraid_adapter_attr - Adapter attributes and capabilities
*
- * @id: Adapter identifier
- * @raid_support: Indicates if RAID is supported
- * @bios_version: Version of the adapter BIOS
- * @enable_mp: Indicates if multipath (MP) support is enabled
- * @wideport_max_queue_depth: Maximum queue depth for wide ports
- * @narrowport_max_queue_depth: Maximum queue depth for narrow ports
- * @sata_max_queue_depth: Maximum queue depth for SATA
- * @features: Detailed features of the adapter
- * @adapter_total_qd: Total queue depth available on the adapter
- * @io_qd: Queue depth allocated for I/O operations
- * @rep_msg_qd: Queue depth for reply messages
- * @rep_desc_qd: Queue depth for reply descriptors
- * @rep_desc_q_seg_cnt: Number of segments in a reply descriptor queue
- * @rq_cnt: Number of request queues
- * @task_desc_dma_size: Size of task descriptor DMA memory
- * @use_32_dma_mask: Indicates if 32-bit DMA mask is used
- * @name: Adapter name string
+ * @id: Adapter identifier.
+ * @raid_support: Indicates if RAID is supported.
+ * @bios_version: Version of the adapter BIOS.
+ * @enable_mp: Indicates if multipath (MP) support is enabled.
+ * @wideport_max_queue_depth: Maximum queue depth for wide ports.
+ * @narrowport_max_queue_depth: Maximum queue depth for narrow ports.
+ * @sata_max_queue_depth: Maximum queue depth for SATA.
+ * @raid_volume_max_queue_depth: Maximum queue depth for RAID volumes.
+ * @features: Detailed features of the adapter.
+ * @adapter_total_qd: Total queue depth available on the adapter.
+ * @io_qd: Queue depth allocated for I/O operations.
+ * @rep_msg_qd: Queue depth for reply messages.
+ * @rep_desc_qd: Queue depth for reply descriptors.
+ * @rep_desc_q_seg_cnt: Number of segments in a reply descriptor queue.
+ * @rq_cnt: Number of request queues.
+ * @task_desc_dma_size: Size of task descriptor DMA memory.
+ * @use_32_dma_mask: Indicates if 32-bit DMA mask is used.
+ * @name: Adapter name string.
+ * @board_name: Board name retrieved from manufacturing page 0.
*/
struct leapraid_adapter_attr {
u8 id;
- bool raid_support;
+ u8 raid_support;
u32 bios_version;
- bool enable_mp;
+ u8 enable_mp;
u32 wideport_max_queue_depth;
u32 narrowport_max_queue_depth;
u32 sata_max_queue_depth;
+ u32 raid_volume_max_queue_depth;
struct leapraid_adapter_features features;
u32 adapter_total_qd;
u32 io_qd;
@@ -285,20 +325,20 @@ struct leapraid_adapter_attr {
u32 rep_desc_q_seg_cnt;
u16 rq_cnt;
u32 task_desc_dma_size;
- bool use_32_dma_mask;
+ u8 use_32_dma_mask;
char name[LEAPRAID_NAME_LENGTH];
+ char board_name[LEAPRAID_BOARD_NAME_LENGTH];
};
/**
- * struct leapraid_io_req_tracker - Track a SCSI I/O request
- * for the adapter
+ * struct leapraid_io_req_tracker - Track a SCSI I/O request for the adapter
*
- * @taskid: Unique task ID for this I/O request
- * @scmd: Pointer to the associated SCSI command
- * @chain_list: List of chain frames associated with this request
- * @msix_io: MSI-X vector assigned to this I/O request
- * @chain: Pointer to the chain memory for this request
- * @chain_dma: DMA address of the chain memory
+ * @taskid: Unique task ID for this I/O request.
+ * @scmd: Pointer to the associated SCSI command.
+ * @chain_list: List of chain frames associated with this request.
+ * @msix_io: MSI-X vector assigned to this I/O request.
+ * @chain: Pointer to the chain memory for this request.
+ * @chain_dma: DMA address of the chain memory.
*/
struct leapraid_io_req_tracker {
u16 taskid;
@@ -312,9 +352,9 @@ struct leapraid_io_req_tracker {
/**
* struct leapraid_task_tracker - Tracks a task in the adapter
*
- * @taskid: Unique task ID for this tracker
- * @cb_idx: Callback index associated with this task
- * @tracker_list: Linked list node to chain this tracker in lists
+ * @taskid: Unique task ID for this tracker.
+ * @cb_idx: Callback index associated with this task.
+ * @tracker_list: Linked list node to chain this tracker in lists.
*/
struct leapraid_task_tracker {
u16 taskid;
@@ -323,11 +363,10 @@ struct leapraid_task_tracker {
};
/**
- * struct leapraid_rep_desc_maint - Maintains reply descriptor
- * memory
+ * struct leapraid_rep_desc_maint - Maintains reply descriptor memory
*
- * @rep_desc: Pointer to the reply descriptor
- * @rep_desc_dma: DMA address of the reply descriptor
+ * @rep_desc: Pointer to the reply descriptor.
+ * @rep_desc_dma: DMA address of the reply descriptor.
*/
struct leapraid_rep_desc_maint {
union leapraid_rep_desc_union *rep_desc;
@@ -335,12 +374,12 @@ struct leapraid_rep_desc_maint {
};
/**
- * struct leapraid_rep_desc_seg_maint - Maintains reply descriptor
- * segment memory
+ * struct leapraid_rep_desc_seg_maint -
+ * Maintains reply descriptor segment memory
*
- * @rep_desc_seg: Pointer to the reply descriptor segment
- * @rep_desc_seg_dma: DMA address of the reply descriptor segment
- * @rep_desc_maint: Pointer to the main reply descriptor structure
+ * @rep_desc_seg: Pointer to the reply descriptor segment.
+ * @rep_desc_seg_dma: DMA address of the reply descriptor segment.
+ * @rep_desc_maint: Pointer to the main reply descriptor structure.
*/
struct leapraid_rep_desc_seg_maint {
void *rep_desc_seg;
@@ -351,20 +390,20 @@ struct leapraid_rep_desc_seg_maint {
/**
* struct leapraid_mem_desc - Memory descriptor for LeapRAID adapter
*
- * @task_desc: Pointer to task descriptor
- * @task_desc_dma: DMA address of task descriptor
- * @sg_chain_pool: DMA pool for SGL chain allocations
- * @sg_chain_pool_size: Size of the sg_chain_pool
- * @io_tracker: IO request tracker array
- * @sense_data: Buffer for SCSI sense data
- * @sense_data_dma: DMA address of sense_data buffer
- * @rep_msg: Buffer for reply message
- * @rep_msg_dma: DMA address of reply message buffer
- * @rep_msg_addr: Pointer to reply message address
- * @rep_msg_addr_dma: DMA address of reply message address
- * @rep_desc_seg_maint: Pointer to reply descriptor segment
- * @rep_desc_q_arr: Pointer to reply descriptor queue array
- * @rep_desc_q_arr_dma: DMA address of reply descriptor queue array
+ * @task_desc: Pointer to task descriptor.
+ * @task_desc_dma: DMA address of task descriptor.
+ * @sg_chain_pool: DMA pool for SGL chain allocations.
+ * @sg_chain_pool_size: Size of the sg_chain_pool.
+ * @io_tracker: I/O request tracker array.
+ * @sense_data: Buffer for SCSI sense data.
+ * @sense_data_dma: DMA address of sense_data buffer.
+ * @rep_msg: Buffer for reply message.
+ * @rep_msg_dma: DMA address of reply message buffer.
+ * @rep_msg_addr: Pointer to reply message address.
+ * @rep_msg_addr_dma: DMA address of reply message address.
+ * @rep_desc_seg_maint: Pointer to reply descriptor segment.
+ * @rep_desc_q_arr: Pointer to reply descriptor queue array.
+ * @rep_desc_q_arr_dma: DMA address of reply descriptor queue array.
*/
struct leapraid_mem_desc {
void *task_desc;
@@ -383,31 +422,30 @@ struct leapraid_mem_desc {
dma_addr_t rep_desc_q_arr_dma;
};
-#define LEAPRAID_FIXED_INTER_CMDS 7
-#define LEAPRAID_FIXED_HP_CMDS 2
-#define LEAPRAID_INTER_HP_CMDS_DIF \
- (LEAPRAID_FIXED_INTER_CMDS - LEAPRAID_FIXED_HP_CMDS)
+/* internal cmd description */
+#define LEAPRAID_FIXED_INTER_CMDS 6
+#define LEAPRAID_FIXED_HP_CMDS 2
-#define LEAPRAID_CMD_NOT_USED 0x8000
-#define LEAPRAID_CMD_DONE 0x0001
-#define LEAPRAID_CMD_PENDING 0x0002
-#define LEAPRAID_CMD_REPLY_VALID 0x0004
-#define LEAPRAID_CMD_RESET 0x0008
+#define LEAPRAID_CMD_NOT_USED 0x8000
+#define LEAPRAID_CMD_DONE 0x0001
+#define LEAPRAID_CMD_PENDING 0x0002
+#define LEAPRAID_CMD_REPLY_VALID 0x0004
+#define LEAPRAID_CMD_RESET 0x0008
/**
* enum LEAPRAID_CB_INDEX - Callback index for LeapRAID driver
*
- * @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
- * @LEAPRAID_CTL_CB_IDX: Control callback index
- * @LEAPRAID_TM_CB_IDX: Task management callback index
+ * @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.
+ * @LEAPRAID_CTL_CB_IDX: Control callback index.
+ * @LEAPRAID_TM_CB_IDX: Task management callback index.
*/
enum LEAPRAID_CB_INDEX {
LEAPRAID_SCAN_DEV_CB_IDX = 0x1,
@@ -424,10 +462,25 @@ enum LEAPRAID_CB_INDEX {
LEAPRAID_NUM_CB_IDXS
};
+/**
+ * struct leapraid_default_reply - Default reply frame buffer
+ * @pad: Raw reply data buffer returned by firmware.
+ *
+ * This structure represents a generic reply frame used by the firmware
+ * when no specific reply format is required. The buffer size is defined
+ * by LEAPRAID_REPLY_SIZE and stores the raw reply data.
+ */
struct leapraid_default_reply {
- u8 pad[LEAPRAID_REPLY_SIEZ];
+ u8 pad[LEAPRAID_REPLY_SIZE];
};
+/**
+ * struct leapraid_sense_buffer - SCSI sense data buffer
+ * @pad: Buffer used to store sense data returned by a SCSI command.
+ *
+ * This buffer holds the sense data provided by a device.The size is
+ * defined by SCSI_SENSE_BUFFERSIZE.
+ */
struct leapraid_sense_buffer {
u8 pad[SCSI_SENSE_BUFFERSIZE];
};
@@ -435,17 +488,17 @@ struct leapraid_sense_buffer {
/**
* struct leapraid_driver_cmd - Driver command tracking structure
*
- * @reply: Default reply structure returned by the adapter
- * @done: Completion object used to signal command completion
- * @status: Status code returned by the firmware
- * @taskid: Unique task identifier for this command
- * @hp_taskid: Task identifier for high-priority commands
- * @inter_taskid: Task identifier for internal commands
- * @cb_idx: Callback index used to identify completion context
- * @async_scan_dev: True if this command is for asynchronous device scan
- * @sense: Sense buffer holding error information from device
- * @mutex: Mutex to protect access to this command structure
- * @list: List node for linking driver commands into lists
+ * @reply: Default reply structure returned by the adapter.
+ * @done: Completion object used to signal command completion.
+ * @status: Status code returned by the firmware.
+ * @taskid: Unique task identifier for this command.
+ * @hp_taskid: Task identifier for high-priority commands.
+ * @inter_taskid: Task identifier for internal commands.
+ * @cb_idx: Callback index used to identify completion context.
+ * @async_scan_dev: True if this command is for asynchronous device scan.
+ * @sense: Sense buffer holding error information from device.
+ * @mutex: Mutex to protect access to this command structure.
+ * @list: List node for linking driver commands into lists.
*/
struct leapraid_driver_cmd {
struct leapraid_default_reply reply;
@@ -455,27 +508,27 @@ struct leapraid_driver_cmd {
u16 hp_taskid;
u16 inter_taskid;
u8 cb_idx;
- bool async_scan_dev;
+ u8 async_scan_dev;
struct leapraid_sense_buffer sense;
- struct mutex mutex;
+ struct mutex mutex; /* Mutex for driver cmd */
struct list_head list;
};
/**
* struct leapraid_driver_cmds - Collection of driver command objects
*
- * @special_cmd_list: List head for tracking special driver commands
- * @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
+ * @special_cmd_list: List head for tracking special driver commands.
+ * @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;
@@ -495,14 +548,14 @@ struct leapraid_driver_cmds {
/**
* struct leapraid_dynamic_task_desc - Dynamic task descriptor
*
- * @task_lock: Spinlock to protect concurrent access
- * @hp_taskid: Current high-priority task ID
- * @hp_cmd_qd: Fixed command queue depth for high-priority tasks
- * @inter_taskid: Current internal task ID
- * @inter_cmd_qd: Fixed command queue depth for internal tasks
+ * @task_lock: Spinlock to protect concurrent access.
+ * @hp_taskid: Current high-priority task ID.
+ * @hp_cmd_qd: Fixed command queue depth for high-priority tasks.
+ * @inter_taskid: Current internal task ID.
+ * @inter_cmd_qd: Fixed command queue depth for internal tasks.
*/
struct leapraid_dynamic_task_desc {
- spinlock_t task_lock;
+ spinlock_t task_lock; /* protects dynamic task */
u16 hp_taskid;
u16 hp_cmd_qd;
u16 inter_taskid;
@@ -512,14 +565,14 @@ struct leapraid_dynamic_task_desc {
/**
* struct leapraid_fw_evt_work - Firmware event work structure
*
- * @list: Linked list node for queuing the work
- * @adapter: Pointer to the associated LeapRAID adapter
- * @work: Work structure used by the kernel workqueue
- * @refcnt: Reference counter for managing the lifetime of this work
- * @evt_data: Pointer to firmware event data
- * @dev_handle: Device handle associated with the event
- * @evt_type: Type of firmware event
- * @ignore: Flag indicating whether the event should be ignored
+ * @list: Linked list node for queuing the work.
+ * @adapter: Pointer to the associated LeapRAID adapter.
+ * @work: Work structure used by the kernel workqueue.
+ * @refcnt: Reference counter for managing the lifetime of this work.
+ * @evt_data: Pointer to firmware event data.
+ * @dev_handle: Device handle associated with the event.
+ * @evt_type: Type of firmware event.
+ * @ignore: Flag indicating whether the event should be ignored.
*/
struct leapraid_fw_evt_work {
struct list_head list;
@@ -535,33 +588,35 @@ struct leapraid_fw_evt_work {
/**
* struct leapraid_fw_evt_struct - Firmware event handling structure
*
- * @fw_evt_name: Name of the firmware event
- * @fw_evt_thread: Workqueue used for processing firmware events
- * @fw_evt_lock: Spinlock protecting access to the firmware event list
- * @fw_evt_list: Linked list of pending firmware events
- * @cur_evt: Pointer to the currently processing firmware event
- * @fw_evt_cleanup: Flag indicating whether cleanup of events is in progress
- * @leapraid_evt_masks: Array of event masks for filtering firmware events
+ * @fw_evt_name: Name of the firmware event.
+ * @fw_evt_thread: Workqueue used for processing firmware events.
+ * @fw_evt_lock: Spinlock protecting access to the firmware event list.
+ * @fw_evt_list: Linked list of pending firmware events.
+ * @cur_evt: Pointer to the currently processing firmware event.
+ * @cur_evt_task: Task currently executing @cur_evt work.
+ * @fw_evt_cleanup: Flag indicating whether cleanup of events is in progress.
+ * @leapraid_evt_masks: Array of event masks for filtering firmware events.
*/
struct leapraid_fw_evt_struct {
char fw_evt_name[48];
struct workqueue_struct *fw_evt_thread;
- spinlock_t fw_evt_lock;
+ spinlock_t fw_evt_lock; /* protects firmware event */
struct list_head fw_evt_list;
struct leapraid_fw_evt_work *cur_evt;
- int fw_evt_cleanup;
+ struct task_struct *cur_evt_task;
+ u8 fw_evt_cleanup;
u32 leapraid_evt_masks[4];
};
/**
* struct leapraid_rq - Represents a LeapRAID request queue
*
- * @adapter: Pointer to the associated LeapRAID adapter
- * @msix_idx: MSI-X vector index used by this queue
- * @rep_post_host_idx: Index of the last processed reply descriptor
- * @rep_desc: Pointer to the reply descriptor associated with this queue
- * @name: Name of the request queue
- * @busy: Atomic counter indicating if the queue is busy
+ * @adapter: Pointer to the associated LeapRAID adapter.
+ * @msix_idx: MSI-X vector index used by this queue.
+ * @rep_post_host_idx: Index of the last processed reply descriptor.
+ * @rep_desc: Pointer to the reply descriptor associated with this queue.
+ * @name: Name of the request queue.
+ * @busy: Atomic counter indicating if the queue is busy.
*/
struct leapraid_rq {
struct leapraid_adapter *adapter;
@@ -575,8 +630,8 @@ struct leapraid_rq {
/**
* struct leapraid_int_rq - Internal request queue for a CPU
*
- * @affinity_hint: CPU affinity mask for the queue
- * @rq: Underlying LeapRAID request queue structure
+ * @affinity_hint: CPU affinity mask for the queue.
+ * @rq: Underlying LeapRAID request queue structure.
*/
struct leapraid_int_rq {
cpumask_var_t affinity_hint;
@@ -586,9 +641,9 @@ struct leapraid_int_rq {
/**
* struct leapraid_blk_mq_poll_rq - Polling request for LeapRAID blk-mq
*
- * @busy: Atomic flag indicating request is being processed
- * @pause: Atomic flag to temporarily suspend polling
- * @rq: The underlying LeapRAID request structure
+ * @busy: Atomic flag indicating request is being processed.
+ * @pause: Atomic flag to temporarily suspend polling.
+ * @rq: The underlying LeapRAID request structure.
*/
struct leapraid_blk_mq_poll_rq {
atomic_t busy;
@@ -597,22 +652,25 @@ struct leapraid_blk_mq_poll_rq {
};
/**
- * struct leapraid_notification_desc - Notification
- * descriptor for LeapRAID
+ * struct leapraid_notification_desc - Notification descriptor for LeapRAID
*
- * @iopoll_qdex: Index of the I/O polling queue
- * @iopoll_qcnt: Count of I/O polling queues
- * @msix_enable: Flag indicating MSI-X is enabled
- * @msix_cpu_map: CPU map for MSI-X interrupts
- * @msix_cpu_map_sz: Size of the MSI-X 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
+ * @iopoll_qdex: Index of the I/O polling queue.
+ * @iopoll_qcnt: Count of I/O polling queues.
+ * @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.
+ * @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.
*/
struct leapraid_notification_desc {
u32 iopoll_qdex;
u32 iopoll_qcnt;
- bool msix_enable;
+ u8 msix_enable;
+ u8 irq_vectors_allocated;
+ u8 irq_mode;
u8 *msix_cpu_map;
u32 msix_cpu_map_sz;
struct leapraid_int_rq *int_rqs;
@@ -620,82 +678,104 @@ struct leapraid_notification_desc {
struct leapraid_blk_mq_poll_rq *blk_mq_poll_rqs;
};
+/**
+ * struct leapraid_overheat_desc - Overheat descriptor for LeapRAID
+ *
+ * @fault_overheat_wq: Workqueue for adapter thermal overheat operations.
+ * @fault_overheat_work: Work structure for thermal overheat.
+ * @thermal_alert: Flag indicating if adapter thermal alert is active.
+ * @fault_overheat_wq_name: Name of the fault overheat workqueue.
+ */
+struct leapraid_overheat_desc {
+ struct workqueue_struct *fault_overheat_wq;
+ struct work_struct fault_overheat_work;
+ atomic_t thermal_alert;
+ char fault_overheat_wq_name[48];
+};
+
/**
* struct leapraid_reset_desc - Reset descriptor for LeapRAID
*
- * @fault_reset_wq: Workqueue for fault reset operations
- * @fault_reset_work: Delayed work structure for fault reset
- * @fault_reset_wq_name: Name of the fault reset workqueue
- * @host_diag_mutex: Mutex for host diagnostic operations
- * @adapter_reset_lock: Spinlock for adapter reset operations
- * @adapter_reset_mutex: Mutex for adapter reset operations
- * @adapter_link_resetting: Flag indicating if adapter link is resetting
- * @adapter_reset_results: Results of the adapter reset operation
- * @pending_io_cnt: Count of pending I/O operations
- * @reset_wait_queue: Wait queue for reset operations
- * @reset_cnt: Counter for reset operations
+ * @fault_reset_wq: Workqueue for fault reset operations.
+ * @fault_reset_work: Delayed work structure for fault reset.
+ * @fault_reset_wq_name: Name of the fault reset workqueue.
+ * @host_diag_mutex: Mutex for host diagnostic operations.
+ * @adapter_reset_lock: Spinlock for adapter reset operations.
+ * @adapter_reset_mutex: Mutex for adapter reset operations.
+ * @adapter_link_resetting: Flag indicating if adapter link is resetting.
+ * @adapter_reset_results: Results of the adapter reset operation.
+ * @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;
struct delayed_work fault_reset_work;
char fault_reset_wq_name[48];
- struct mutex host_diag_mutex;
- spinlock_t adapter_reset_lock;
- struct mutex adapter_reset_mutex;
- bool adapter_link_resetting;
+ struct mutex host_diag_mutex; /* Mutex for operations. */
+ spinlock_t adapter_reset_lock; /* Protects adapter reset state. */
+ struct mutex adapter_reset_mutex; /* Serializes adapter reset. */
+ u8 adapter_link_resetting;
int adapter_reset_results;
int pending_io_cnt;
wait_queue_head_t reset_wait_queue;
u32 reset_cnt;
+ u32 last_reset_cnt;
};
/**
- * struct leapraid_scan_dev_desc - Scan device descriptor
- * for LeapRAID
+ * struct leapraid_scan_dev_desc - Scan device descriptor for LeapRAID
*
- * @wait_scan_dev_done: Flag indicating if scan device operation is done
- * @driver_loading: Flag indicating if driver is loading
- * @first_scan_dev_fired: Flag indicating if first scan device operation fired
- * @scan_dev_failed: Flag indicating if scan device operation failed
- * @scan_start: Flag indicating if scan operation started
- * @scan_start_failed: Count of failed scan start operations
+ * @wait_scan_dev_done: Flag indicating if scan device operation is done.
+ * @driver_loading: Flag indicating if driver is loading.
+ * @first_scan_dev_fired: Flag indicating if first scan device operation fired.
+ * @scan_dev_failed: Flag indicating if scan device operation failed.
+ * @scan_start: Flag indicating if scan operation started.
+ * @scan_start_failed: Count of failed scan start operations.
*/
struct leapraid_scan_dev_desc {
- bool wait_scan_dev_done;
- bool driver_loading;
- bool first_scan_dev_fired;
- bool scan_dev_failed;
- bool scan_start;
+ u8 wait_scan_dev_done;
+ u8 driver_loading;
+ wait_queue_head_t wait_driver_loading;
+ u8 first_scan_dev_fired;
+ u8 scan_dev_failed;
+ u8 scan_start;
u16 scan_start_failed;
};
/**
* struct leapraid_access_ctrl - Access control structure for LeapRAID
*
- * @pci_access_lock: Mutex for PCI access control
- * @adapter_thermal_alert: Flag indicating if adapter thermal alert is active
- * @shost_recovering: Flag indicating if host is recovering
- * @host_removing: Flag indicating if host is being removed
- * @pcie_recovering: Flag indicating if PCIe is recovering
+ * @pci_access_lock: Mutex for PCI access control.
+ * @shost_recovering: Flag indicating if host is recovering.
+ * @shost_recover_async: Flag indicating if host is recovering
+ * and the 0xFFFF event.
+ * @shost_recover_wq: Wait queue for threads waiting on shost_recover_async.
+ * @host_removing: Flag indicating if host is being removed.
+ * @pcie_recovering: Flag indicating if PCIe is recovering.
*/
struct leapraid_access_ctrl {
- struct mutex pci_access_lock;
- bool adapter_thermal_alert;
- bool shost_recovering;
- bool host_removing;
- bool pcie_recovering;
+ struct mutex pci_access_lock; /* serializes PCI register access. */
+ u8 shost_recovering;
+ wait_queue_head_t recovery_waitq;
+ u8 shost_recover_async;
+ wait_queue_head_t shost_recover_wq;
+ u8 host_removing;
+ u8 pcie_recovering;
};
/**
* struct leapraid_fw_log_desc - Firmware log descriptor for LeapRAID
*
- * @fw_log_buffer: Buffer for firmware log data
- * @fw_log_buffer_dma: DMA address of the firmware log buffer
- * @fw_log_wq_name: Name of the firmware log workqueue
- * @fw_log_wq: Workqueue for firmware log operations
- * @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
+ * @fw_log_buffer: Buffer for firmware log data.
+ * @fw_log_buffer_dma: DMA address of the firmware log buffer.
+ * @fw_log_wq_name: Name of the firmware log workqueue.
+ * @fw_log_wq: Workqueue for firmware log operations.
+ * @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.
*/
struct leapraid_fw_log_desc {
u8 *fw_log_buffer;
@@ -705,6 +785,7 @@ 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];
};
#define LEAPRAID_CARD_PORT_FLG_DIRTY 0x01
@@ -713,13 +794,13 @@ struct leapraid_fw_log_desc {
/**
* struct leapraid_card_port - Card port structure for LeapRAID
*
- * @list: List head for card port
- * @vphys_list: List head for virtual phy list
- * @port_id: Port ID
- * @sas_address: SAS address
- * @phy_mask: Mask of phy
- * @vphys_mask: Mask of virtual phy
- * @flg: Flags for the port
+ * @list: List head for card port.
+ * @vphys_list: List head for virtual PHY list.
+ * @port_id: Port ID.
+ * @sas_address: SAS address.
+ * @phy_mask: Mask of PHY.
+ * @vphys_mask: Mask of virtual PHY.
+ * @flg: Flags for the port.
*/
struct leapraid_card_port {
struct list_head list;
@@ -732,18 +813,18 @@ struct leapraid_card_port {
};
/**
- * struct leapraid_card_phy - Card phy structure for LeapRAID
+ * struct leapraid_card_phy - Card PHY structure for LeapRAID
*
- * @port_siblings: List head for port siblings
- * @card_port: Pointer to the card port
- * @identify: SAS identify structure
- * @remote_identify: Remote SAS identify structure
- * @phy: SAS phy structure
- * @phy_id: Phy ID
- * @hdl: Handle for the port
- * @attached_hdl: Handle for the attached port
- * @phy_is_assigned: Flag indicating if phy is assigned
- * @vphy: Flag indicating if virtual phy
+ * @port_siblings: List head for port siblings.
+ * @card_port: Pointer to the card port.
+ * @identify: SAS identify structure.
+ * @remote_identify: Remote SAS identify structure.
+ * @phy: SAS PHY structure.
+ * @phy_id: PHY ID.
+ * @hdl: Handle for the port.
+ * @attached_hdl: Handle for the attached port.
+ * @phy_is_assigned: Flag indicating if PHY is assigned.
+ * @vphy: Flag indicating if virtual PHY.
*/
struct leapraid_card_phy {
struct list_head port_siblings;
@@ -754,26 +835,26 @@ struct leapraid_card_phy {
u8 phy_id;
u16 hdl;
u16 attached_hdl;
- bool phy_is_assigned;
- bool vphy;
+ u8 phy_is_assigned;
+ u8 vphy;
};
/**
* struct leapraid_topo_node - SAS topology node for LeapRAID
*
- * @list: List head for linking nodes
- * @sas_port_list: List of SAS ports
- * @card_port: Associated card port
- * @card_phy: Associated card PHY
- * @rphy: SAS remote PHY device
- * @parent_dev: Parent device pointer
- * @sas_address: SAS address of this node
- * @sas_address_parent: Parent node's SAS address
- * @phys_num: Number of physical links
- * @hdl: Handle identifier
- * @enc_hdl: Enclosure handle
- * @enc_lid: Enclosure logical identifier
- * @resp: Response status flag
+ * @list: List head for linking nodes.
+ * @sas_port_list: List of SAS ports.
+ * @card_port: Associated card port.
+ * @card_phy: Associated card PHY.
+ * @rphy: SAS remote PHY device.
+ * @parent_dev: Parent device pointer.
+ * @sas_address: SAS address of this node.
+ * @sas_address_parent: Parent node's SAS address.
+ * @phys_num: Number of physical links.
+ * @hdl: Handle identifier.
+ * @enc_hdl: Enclosure handle.
+ * @enc_lid: Enclosure logical identifier.
+ * @resp: Response status flag.
*/
struct leapraid_topo_node {
struct list_head list;
@@ -788,32 +869,32 @@ struct leapraid_topo_node {
u16 hdl;
u16 enc_hdl;
u64 enc_lid;
- bool resp;
+ u8 resp;
};
/**
* struct leapraid_dev_topo - LeapRAID device topology management structure
*
- * @topo_node_lock: Spinlock for protecting topology node operations
- * @sas_dev_lock: Spinlock for SAS device list access
- * @raid_volume_lock: Spinlock for RAID volume list access
- * @sas_id: SAS domain identifier
- * @card: Main card topology node
- * @exp_list: List of expander devices
- * @enc_list: List of enclosure devices
- * @sas_dev_list: List of SAS devices
- * @sas_dev_init_list: List of SAS devices being initialized
- * @raid_volume_list: List of RAID volumes
- * @card_port_list: List of card ports
- * @pd_hdls: Array of physical disk handles
- * @dev_removing: Array tracking devices being removed
- * @pending_dev_add: Array tracking devices pending addition
- * @blocking_hdls: Array of blocking handles
+ * @topo_node_lock: Spinlock for protecting topology node operations.
+ * @sas_dev_lock: Spinlock for SAS device list access.
+ * @raid_volume_lock: Spinlock for RAID volume list access.
+ * @enc_lock: Spinlock for enclosure device list access.
+ * @sas_id: SAS domain identifier.
+ * @card: Main card topology node.
+ * @exp_list: List of expander devices.
+ * @enc_list: List of enclosure devices.
+ * @sas_dev_list: List of SAS devices.
+ * @sas_dev_init_list: List of SAS devices being initialized.
+ * @raid_volume_list: List of RAID volumes.
+ * @card_port_list: List of card ports.
+ * @pd_hdls: Array of physical disk handles.
+ * @blocking_hdls: Array of blocking handles.
*/
struct leapraid_dev_topo {
- spinlock_t topo_node_lock;
- spinlock_t sas_dev_lock;
- spinlock_t raid_volume_lock;
+ spinlock_t topo_node_lock; /* Protects topology node. */
+ spinlock_t sas_dev_lock; /* Protects SAS device list access. */
+ spinlock_t raid_volume_lock; /* Protects RAID volume list access. */
+ spinlock_t enc_lock; /* Protects enclosure device list access. */
int sas_id;
struct leapraid_topo_node card;
struct list_head exp_list;
@@ -823,21 +904,17 @@ struct leapraid_dev_topo {
struct list_head raid_volume_list;
struct list_head card_port_list;
u16 pd_hdls_sz;
- void *pd_hdls;
- void *blocking_hdls;
- u16 pending_dev_add_sz;
- void *pending_dev_add;
- u16 dev_removing_sz;
- void *dev_removing;
+ unsigned long *pd_hdls;
+ unsigned long *blocking_hdls;
};
/**
* struct leapraid_boot_dev - Boot device structure for LeapRAID
*
- * @dev: Device pointer
- * @chnl: Channel number
- * @form: Form factor
- * @pg_dev: Config page device content
+ * @dev: Device pointer.
+ * @chnl: Channel number.
+ * @form: Form factor.
+ * @pg_dev: Config page device content.
*/
struct leapraid_boot_dev {
void *dev;
@@ -848,11 +925,14 @@ struct leapraid_boot_dev {
/**
* struct leapraid_boot_devs - Boot device management structure
- * @requested_boot_dev: Requested primary boot device
- * @requested_alt_boot_dev: Requested alternate boot device
- * @current_boot_dev: Currently active boot device
+ *
+ * @lock: Spinlock protecting boot device cache access.
+ * @requested_boot_dev: Requested primary boot device.
+ * @requested_alt_boot_dev: Requested alternate boot device.
+ * @current_boot_dev: Currently active boot device.
*/
struct leapraid_boot_devs {
+ spinlock_t lock; /* protects boot dev */
struct leapraid_boot_dev requested_boot_dev;
struct leapraid_boot_dev requested_alt_boot_dev;
struct leapraid_boot_dev current_boot_dev;
@@ -860,9 +940,10 @@ struct leapraid_boot_devs {
/**
* 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
+ *
+ * @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;
@@ -872,26 +953,28 @@ struct leapraid_smart_poll_desc {
/**
* struct leapraid_adapter - Main LeapRAID adapter structure
- * @list: List head for adapter management
- * @shost: SCSI host structure
- * @pdev: PCI device structure
- * @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
- * @dynamic_task_desc: Dynamic task descriptor
- * @fw_evt_s: Firmware event structure
- * @notification_desc: Notification descriptor
- * @reset_desc: Reset descriptor
- * @scan_dev_desc: Device scan descriptor
- * @access_ctrl: Access control
- * @fw_log_desc: Firmware log descriptor
- * @dev_topo: Device topology
- * @boot_devs: Boot devices
- * @smart_poll_desc: SMART polling descriptor
+ *
+ * @list: List head for adapter management.
+ * @shost: SCSI host structure.
+ * @pdev: PCI device structure.
+ * @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.
+ * @dynamic_task_desc: Dynamic task descriptor.
+ * @fw_evt_s: Firmware event structure.
+ * @notification_desc: Notification descriptor.
+ * @reset_desc: Reset descriptor.
+ * @scan_dev_desc: Device scan descriptor.
+ * @access_ctrl: Access control.
+ * @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 {
struct list_head list;
@@ -899,7 +982,7 @@ struct leapraid_adapter {
struct pci_dev *pdev;
struct leapraid_reg_base __iomem *iomem_base;
u32 rep_msg_host_idx;
- bool mask_int;
+ u8 mask_int;
u32 timestamp_sync_cnt;
struct leapraid_adapter_attr adapter_attr;
@@ -915,6 +998,7 @@ struct leapraid_adapter {
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;
};
union cfg_param_1 {
@@ -931,6 +1015,7 @@ union cfg_param_2 {
enum config_page_action {
GET_BIOS_PG2,
GET_BIOS_PG3,
+ GET_MANUFACTURING_PG0,
GET_SAS_DEVICE_PG0,
GET_SAS_IOUNIT_PG0,
GET_SAS_IOUNIT_PG1,
@@ -945,8 +1030,9 @@ enum config_page_action {
/**
* struct leapraid_enc_node - Enclosure node structure
- * @list: List head for enclosure management
- * @pg0: Enclosure page 0 data
+ *
+ * @list: List head for enclosure management.
+ * @pg0: Enclosure page 0 data.
*/
struct leapraid_enc_node {
struct list_head list;
@@ -955,20 +1041,23 @@ struct leapraid_enc_node {
/**
* struct leapraid_raid_volume - RAID volume structure
- * @list: List head for volume management
- * @starget: SCSI target structure
- * @sdev: SCSI device structure
- * @id: Volume ID
- * @channel: SCSI channel
- * @wwid: World Wide Identifier
- * @hdl: Volume handle
- * @vol_type: Volume type
- * @pd_num: Number of physical disks
- * @resp: Response status
- * @dev_info: Device information
+ *
+ * @list: List head for volume management.
+ * @refcnt: Reference count.
+ * @starget: SCSI target structure.
+ * @sdev: SCSI device structure.
+ * @id: Volume ID.
+ * @channel: SCSI channel.
+ * @wwid: World wide Identifier.
+ * @hdl: Volume handle.
+ * @vol_type: Volume type.
+ * @pd_num: Number of physical disks.
+ * @resp: Response status.
+ * @dev_info: Device information.
*/
struct leapraid_raid_volume {
struct list_head list;
+ struct kref refcnt;
struct scsi_target *starget;
struct scsi_device *sdev;
unsigned int id;
@@ -981,20 +1070,31 @@ struct leapraid_raid_volume {
u32 dev_info;
};
+static inline void leapraid_raid_volume_free(struct kref *ref)
+{
+ kfree(container_of(ref, struct leapraid_raid_volume, refcnt));
+}
+
+#define leapraid_raid_volume_get(volume) \
+ kref_get(&(volume)->refcnt)
+#define leapraid_raid_volume_put(volume) \
+ kref_put(&(volume)->refcnt, leapraid_raid_volume_free)
+
#define LEAPRAID_TGT_FLG_RAID_MEMBER 0x01
#define LEAPRAID_TGT_FLG_VOLUME 0x02
#define LEAPRAID_NO_ULD_ATTACH 1
/**
* struct leapraid_starget_priv - SCSI target private data
- * @starget: SCSI target structure
- * @sas_address: SAS address
- * @hdl: Device handle
- * @num_luns: Number of LUNs
- * @flg: Flags
- * @deleted: Deletion flag
- * @tm_busy: Task management busy flag
- * @card_port: Associated card port
- * @sas_dev: SAS device structure
+ *
+ * @starget: SCSI target structure.
+ * @sas_address: SAS address.
+ * @hdl: Device handle.
+ * @num_luns: Number of LUNs.
+ * @flg: Flags.
+ * @deleted: Deletion flag.
+ * @tm_busy: Task management busy flag.
+ * @card_port: Associated card port.
+ * @sas_dev: SAS device structure.
*/
struct leapraid_starget_priv {
struct scsi_target *starget;
@@ -1002,8 +1102,8 @@ struct leapraid_starget_priv {
u16 hdl;
int num_luns;
u32 flg;
- bool deleted;
- bool tm_busy;
+ u8 deleted;
+ u8 tm_busy;
struct leapraid_card_port *card_port;
struct leapraid_sas_dev *sas_dev;
};
@@ -1011,50 +1111,52 @@ struct leapraid_starget_priv {
#define LEAPRAID_DEVICE_FLG_INIT 0x01
/**
* struct leapraid_sdev_priv - SCSI device private data
- * @starget_priv: Associated target private data
- * @lun: Logical Unit Number
- * @flg: Flags
- * @block: Block flag
- * @deleted: Deletion flag
- * @sep: SEP flag
+ *
+ * @starget_priv: Associated target private data.
+ * @lun: Logical Unit Number.
+ * @flg: Flags.
+ * @block: Block flag.
+ * @deleted: Deletion flag.
+ * @sep: SEP flag.
*/
struct leapraid_sdev_priv {
struct leapraid_starget_priv *starget_priv;
unsigned int lun;
u32 flg;
- bool ncq;
- bool block;
- bool deleted;
- bool sep;
+ u8 ncq;
+ u8 block;
+ u8 deleted;
+ u8 sep;
};
/**
* struct leapraid_sas_dev - SAS device structure
- * @list: List head for device management
- * @starget: SCSI target structure
- * @card_port: Associated card port
- * @rphy: SAS remote PHY
- * @refcnt: Reference count
- * @id: Device ID
- * @channel: SCSI channel
- * @slot: Slot number
- * @phy: PHY identifier
- * @resp: Response status
- * @led_on: LED state
- * @sas_addr: SAS address
- * @dev_name: Device name
- * @hdl: Device handle
- * @parent_sas_addr: Parent SAS address
- * @enc_hdl: Enclosure handle
- * @enc_lid: Enclosure logical ID
- * @volume_hdl: Volume handle
- * @volume_wwid: Volume WWID
- * @dev_info: Device information
- * @pend_sas_rphy_add: Pending SAS rphy addition flag
- * @enc_level: Enclosure level
- * @port_type: Port type
- * @connector_name: Connector name
- * @support_smart: SMART support flag
+ *
+ * @list: List head for device management.
+ * @starget: SCSI target structure.
+ * @card_port: Associated card port.
+ * @rphy: SAS remote PHY.
+ * @refcnt: Reference count.
+ * @id: Device ID.
+ * @channel: SCSI channel.
+ * @slot: Slot number.
+ * @phy: PHY identifier.
+ * @resp: Response status.
+ * @led_on: LED state.
+ * @sas_addr: SAS address.
+ * @dev_name: Device name.
+ * @hdl: Device handle.
+ * @parent_sas_addr: Parent SAS address.
+ * @enc_hdl: Enclosure handle.
+ * @enc_lid: Enclosure logical ID.
+ * @volume_hdl: Volume handle.
+ * @volume_wwid: Volume WWID.
+ * @dev_info: Device information.
+ * @pend_sas_rphy_add: Pending SAS remote PHY addition flag.
+ * @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;
@@ -1066,8 +1168,8 @@ struct leapraid_sas_dev {
unsigned int channel;
u16 slot;
u8 phy;
- bool resp;
- bool led_on;
+ u8 resp;
+ u8 led_on;
u64 sas_addr;
u64 dev_name;
u16 hdl;
@@ -1079,9 +1181,9 @@ struct leapraid_sas_dev {
u32 dev_info;
u8 pend_sas_rphy_add;
u8 enc_level;
- u8 port_type;
- u8 connector_name[5];
- bool support_smart;
+ 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)
@@ -1092,15 +1194,19 @@ static inline void leapraid_sdev_free(struct kref *ref)
#define leapraid_sdev_get(sdev) kref_get(&(sdev)->refcnt)
#define leapraid_sdev_put(sdev) kref_put(&(sdev)->refcnt, leapraid_sdev_free)
+void leapraid_boot_dev_get(void *dev, u32 chnl);
+void leapraid_boot_dev_put(void *dev, u32 chnl);
+
/**
* struct leapraid_sas_port - SAS port structure
- * @port_list: List head for port management
- * @phy_list: List of PHYs in this port
- * @port: SAS port structure
- * @card_port: Associated card port
- * @remote_identify: Remote device identification
- * @rphy: SAS remote PHY
- * @phys_num: Number of PHYs in this port
+ *
+ * @port_list: List head for port management.
+ * @phy_list: List of PHYs in this port.
+ * @port: SAS port structure.
+ * @card_port: Associated card port.
+ * @remote_identify: Remote device identification.
+ * @rphy: SAS remote PHY.
+ * @phys_num: Number of PHYs in this port.
*/
struct leapraid_sas_port {
struct list_head port_list;
@@ -1115,10 +1221,11 @@ struct leapraid_sas_port {
#define LEAPRAID_VPHY_FLG_DIRTY 0x01
/**
* struct leapraid_vphy - Virtual PHY structure
- * @list: List head for PHY management
- * @sas_address: SAS address
- * @phy_mask: PHY mask
- * @flg: Flags
+ *
+ * @list: List head for PHY management.
+ * @sas_address: SAS address.
+ * @phy_mask: PHY mask.
+ * @flg: Flags.
*/
struct leapraid_vphy {
struct list_head list;
@@ -1127,23 +1234,44 @@ struct leapraid_vphy {
u8 flg;
};
+/**
+ * struct leapraid_tgt_rst_list - Target reset tracking entry
+ * @list: List node used to link reset entries.
+ * @handle: Device handle of the target being reset.
+ * @state: Current state of the target reset operation.
+ *
+ * Each entry represents a target device that is undergoing or has
+ * undergone a target reset operation.
+ */
struct leapraid_tgt_rst_list {
struct list_head list;
u16 handle;
u16 state;
};
-struct leapraid_sc_list {
- struct list_head list;
- u16 handle;
-};
-
+/**
+ * struct sense_info - Parsed SCSI sense information
+ * @sense_key: Sense key extracted from sense data.
+ * @asc: Additional Sense Code (ASC).
+ * @ascq: Additional Sense Code Qualifier (ASCQ).
+ *
+ * This structure stores key fields parsed from SCSI sense data to
+ * simplify error handling and reporting.
+ */
struct sense_info {
u8 sense_key;
u8 asc;
u8 ascq;
};
+/**
+ * struct leapraid_fw_log_info - Firmware log position information
+ * @user_position: Current log read position used by the driver.
+ * @adapter_position: Current log write position maintained by firmware.
+ *
+ * This structure tracks firmware log buffer positions used for retrieving
+ * log entries from the adapter.
+ */
struct leapraid_fw_log_info {
u32 user_position;
u32 adapter_position;
@@ -1151,8 +1279,9 @@ struct leapraid_fw_log_info {
/**
* enum reset_type - Reset type enumeration
- * @FULL_RESET: Full hardware reset
- * @PART_RESET: Partial reset
+ *
+ * @FULL_RESET: Full hardware reset.
+ * @PART_RESET: Partial reset.
*/
enum reset_type {
FULL_RESET,
@@ -1174,22 +1303,23 @@ enum leapraid_port_checking_state {
/**
* struct leapraid_card_port_feature - Card port feature
- * @dirty_flg: Dirty flag indicator
- * @same_addr: Same address flag
- * @exact_phy: Exact PHY match flag
- * @phy_overlap: PHY overlap bitmap
- * @same_port: Same port flag
- * @cur_chking_old_port: Current checking old port
- * @expected_old_port: Expected old port
- * @same_addr_port_count: Same address port count
- * @checking_state: Port checking state
+ *
+ * @dirty_flg: Dirty flag indicator.
+ * @same_addr: Same address flag.
+ * @exact_phy: Exact PHY match flag.
+ * @phy_overlap: PHY overlap bitmap.
+ * @same_port: Same port flag.
+ * @cur_chking_old_port: Current checking old port.
+ * @expected_old_port: Expected old port.
+ * @same_addr_port_count: Same address port count.
+ * @checking_state: Port checking state.
*/
struct leapraid_card_port_feature {
u8 dirty_flg;
- bool same_addr;
- bool exact_phy;
+ u8 same_addr;
+ u8 exact_phy;
u32 phy_overlap;
- bool same_port;
+ u8 same_port;
struct leapraid_card_port *cur_chking_old_port;
struct leapraid_card_port *expected_old_port;
int same_addr_port_count;
@@ -1224,7 +1354,7 @@ struct leapraid_rep_manu_reply {
u8 vendor_identification[SAS_EXPANDER_VENDOR_ID_LEN];
u8 product_identification[SAS_EXPANDER_PRODUCT_ID_LEN];
u8 product_revision_level[SAS_EXPANDER_PRODUCT_REV_LEN];
- u8 component_vendor_identification[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
+ u8 comp_vendor_identification[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
u16 component_id;
u8 component_revision_level;
u8 r3;
@@ -1233,20 +1363,21 @@ struct leapraid_rep_manu_reply {
/**
* 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
+ *
+ * @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;
- bool raid_member;
+ u8 raid_member;
enum dma_data_direction dir;
u32 data_length;
void *data_buffer;
@@ -1273,7 +1404,8 @@ void leapraid_mask_int(struct leapraid_adapter *adapter);
void leapraid_unmask_int(struct leapraid_adapter *adapter);
u32 leapraid_get_adapter_state(struct leapraid_adapter *adapter);
bool leapraid_pci_removed(struct leapraid_adapter *adapter);
-int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter);
+int leapraid_check_adapter_is_op(struct leapraid_adapter *adapter, int wait,
+ const char *caller);
void *leapraid_get_task_desc(struct leapraid_adapter *adapter, u16 taskid);
void *leapraid_get_sense_buffer(struct leapraid_adapter *adapter, u16 taskid);
__le32 leapraid_get_sense_buffer_dma(struct leapraid_adapter *adapter,
@@ -1285,11 +1417,11 @@ u16 leapraid_alloc_scsiio_taskid(struct leapraid_adapter *adapter,
void leapraid_free_taskid(struct leapraid_adapter *adapter, u16 taskid);
struct leapraid_io_req_tracker *leapraid_get_io_tracker_from_taskid(
struct leapraid_adapter *adapter, u16 taskid);
-struct leapraid_io_req_tracker *leapraid_get_scmd_priv(struct scsi_cmnd *scmd);
struct scsi_cmnd *leapraid_get_scmd_from_taskid(
struct leapraid_adapter *adapter, u16 taskid);
int leapraid_scan_dev(struct leapraid_adapter *adapter, bool async_scan_dev);
void leapraid_scan_dev_done(struct leapraid_adapter *adapter);
+void leapraid_cleanup_lists(struct leapraid_adapter *adapter);
void leapraid_wait_cmds_done(struct leapraid_adapter *adapter);
void leapraid_clean_active_scsi_cmds(struct leapraid_adapter *adapter);
void leapraid_sync_irqs(struct leapraid_adapter *adapter, bool poll);
@@ -1305,14 +1437,16 @@ int leapraid_issue_locked_tm(struct leapraid_adapter *adapter, u16 handle,
int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 handle,
uint channel, uint id, uint lun, u8 type,
u16 taskid_task, u8 tr_method);
-u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
- u8 msix_index, u32 rep);
+bool leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
+ u8 msix_index, u32 rep);
int leapraid_get_volume_cap(struct leapraid_adapter *adapter,
struct leapraid_raid_volume *raid_volume);
-int leapraid_internal_init_cmd_priv(struct leapraid_adapter *adapter,
- struct leapraid_io_req_tracker *io_tracker);
-int leapraid_internal_exit_cmd_priv(struct leapraid_adapter *adapter,
- struct leapraid_io_req_tracker *io_tracker);
+int leapraid_internal_init_cmd_priv(
+ struct leapraid_adapter *adapter,
+ struct leapraid_io_req_tracker *io_tracker);
+int 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);
bool leapraid_scmd_find_by_lun(struct leapraid_adapter *adapter,
uint id, unsigned int lun, uint channel);
@@ -1381,10 +1515,13 @@ 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_adjust_sdev_queue_depth(struct scsi_device *sdev, int qdepth);
+void leapraid_log_req_context(struct leapraid_adapter *adapter,
+ const void *req_data);
+
+int leapraid_change_queue_depth(struct scsi_device *sdev, int qdepth);
int leapraid_ctl_release(struct inode *inode, struct file *filep);
-void leapraid_ctl_init(void);
+int leapraid_ctl_init(void);
void leapraid_ctl_exit(void);
extern struct sas_function_template leapraid_transport_functions;
@@ -1407,17 +1544,20 @@ void leapraid_transport_update_links(struct leapraid_adapter *adapter,
u64 sas_address, u16 handle,
u8 phy_number, u8 link_rate,
struct leapraid_card_port *card_port);
-void leapraid_transport_detach_phy_to_port(struct leapraid_adapter *adapter,
- struct leapraid_topo_node *topo_node,
- struct leapraid_card_phy *card_phy);
-void leapraid_transport_attach_phy_to_port(struct leapraid_adapter *adapter,
- struct leapraid_topo_node *sas_node,
- struct leapraid_card_phy *card_phy,
- u64 sas_address,
- struct leapraid_card_port *card_port);
+void leapraid_transport_detach_phy_to_port(
+ struct leapraid_adapter *adapter,
+ struct leapraid_topo_node *topo_node,
+ struct leapraid_card_phy *card_phy);
+void leapraid_transport_attach_phy_to_port(
+ struct leapraid_adapter *adapter,
+ struct leapraid_topo_node *sas_node,
+ struct leapraid_card_phy *card_phy,
+ 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);
diff --git a/drivers/scsi/leapraid/leapraid_os.c b/drivers/scsi/leapraid/leapraid_os.c
index 6635e74fd8ff..5a6cda0b5ea8 100644
--- a/drivers/scsi/leapraid/leapraid_os.c
+++ b/drivers/scsi/leapraid/leapraid_os.c
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2025 LeapIO Tech Inc.
+ * Copyright (C) 2026 LeapIO Tech Inc.
*
- * LeapRAID Storage and RAID Controller driver.
+ * LeapRAID storage and RAID controller driver.
*/
-
#include <linux/module.h>
#include "leapraid_func.h"
@@ -18,16 +17,16 @@ MODULE_DESCRIPTION(LEAPRAID_DESCRIPTION);
MODULE_LICENSE("GPL");
MODULE_VERSION(LEAPRAID_DRIVER_VERSION);
-static int leapraid_ids;
+static atomic_t leapraid_ids = ATOMIC_INIT(0);
static int open_pcie_trace = 1;
module_param(open_pcie_trace, int, 0644);
-MODULE_PARM_DESC(open_pcie_trace, "open_pcie_trace: default=1(open)/0(close)");
+MODULE_PARM_DESC(open_pcie_trace, "Default=1(open)/0(close)");
static int enable_mp = 1;
module_param(enable_mp, int, 0444);
MODULE_PARM_DESC(enable_mp,
- "enable multipath on target device. default=1(enable)");
+ "Enable multipath on target device. default=1(enable)");
static inline void leapraid_get_sense_data(char *sense,
struct sense_info *data)
@@ -46,14 +45,9 @@ static inline void leapraid_get_sense_data(char *sense,
}
}
-static struct Scsi_Host *pdev_to_shost(struct pci_dev *pdev)
-{
- return pci_get_drvdata(pdev);
-}
-
static struct leapraid_adapter *pdev_to_adapter(struct pci_dev *pdev)
{
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
if (!shost)
return NULL;
@@ -61,18 +55,13 @@ static struct leapraid_adapter *pdev_to_adapter(struct pci_dev *pdev)
return shost_priv(shost);
}
-struct leapraid_io_req_tracker *leapraid_get_scmd_priv(struct scsi_cmnd *scmd)
-{
- return (struct leapraid_io_req_tracker *)scmd->host_scribble;
-}
-
void leapraid_set_tm_flg(struct leapraid_adapter *adapter, u16 hdl)
{
struct leapraid_sdev_priv *sdev_priv;
struct scsi_device *sdev;
bool skip = false;
- /* don't break out of the loop */
+ /* Iterate over all devices. */
shost_for_each_device(sdev, adapter->shost) {
if (skip)
continue;
@@ -82,7 +71,7 @@ void leapraid_set_tm_flg(struct leapraid_adapter *adapter, u16 hdl)
continue;
if (sdev_priv->starget_priv->hdl == hdl) {
- sdev_priv->starget_priv->tm_busy = true;
+ sdev_priv->starget_priv->tm_busy = 1;
skip = true;
}
}
@@ -94,7 +83,7 @@ void leapraid_clear_tm_flg(struct leapraid_adapter *adapter, u16 hdl)
struct scsi_device *sdev;
bool skip = false;
- /* don't break out of the loop */
+ /* Iterate over all devices. */
shost_for_each_device(sdev, adapter->shost) {
if (skip)
continue;
@@ -104,7 +93,7 @@ void leapraid_clear_tm_flg(struct leapraid_adapter *adapter, u16 hdl)
continue;
if (sdev_priv->starget_priv->hdl == hdl) {
- sdev_priv->starget_priv->tm_busy = false;
+ sdev_priv->starget_priv->tm_busy = 0;
skip = true;
}
}
@@ -136,21 +125,19 @@ static int leapraid_tm_cmd_map_status(struct leapraid_adapter *adapter,
}
}
- if (taskid_task == adapter->driver_cmds.driver_scsiio_cmd.taskid) {
- if ((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.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) {
- if ((adapter->driver_cmds.ctl_cmd.status &
- LEAPRAID_CMD_DONE) ||
- (adapter->driver_cmds.ctl_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 ||
+ adapter->driver_cmds.ctl_cmd.status &
+ LEAPRAID_CMD_NOT_USED))
+ rc = SUCCESS;
return rc;
}
@@ -197,7 +184,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
struct leapraid_scsi_tm_req *scsi_tm_req;
struct leapraid_scsiio_req *scsiio_req;
struct leapraid_io_req_tracker *io_req_tracker = NULL;
- u16 msix_task = 0;
+ u16 msix_task;
bool issue_reset = false;
u32 db;
int rc;
@@ -208,7 +195,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
adapter->access_ctrl.host_removing ||
adapter->access_ctrl.pcie_recovering) {
dev_info(&adapter->pdev->dev,
- "%s %s: host is recovering, skip tm command!\n",
+ "%s %s: Host is recovering, skip tm command!\n",
__func__, adapter->adapter_attr.name);
return FAILED;
}
@@ -216,24 +203,25 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
db = leapraid_readl(&adapter->iomem_base->db);
if (db & LEAPRAID_DB_USED) {
dev_info(&adapter->pdev->dev,
- "%s unexpected db status, issuing hard reset!\n",
+ "%s Unexpected db status, issuing hard reset!\n",
adapter->adapter_attr.name);
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
- return (!rc) ? SUCCESS : FAILED;
+ return !rc ? SUCCESS : FAILED;
}
if ((db & LEAPRAID_DB_MASK) == LEAPRAID_DB_FAULT) {
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
- return (!rc) ? SUCCESS : FAILED;
+ return !rc ? SUCCESS : FAILED;
}
if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK)
- io_req_tracker = leapraid_get_io_tracker_from_taskid(adapter,
- target_taskid);
+ io_req_tracker =
+ leapraid_get_io_tracker_from_taskid(adapter,
+ target_taskid);
adapter->driver_cmds.tm_cmd.status = LEAPRAID_CMD_PENDING;
scsi_tm_req =
@@ -241,7 +229,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
adapter->driver_cmds.tm_cmd.hp_taskid);
leapraid_build_tm_req(scsi_tm_req, hdl, lun, type, tr_method,
target_taskid);
- memset((void *)(&adapter->driver_cmds.tm_cmd.reply), 0,
+ memset(&adapter->driver_cmds.tm_cmd.reply, 0,
sizeof(struct leapraid_scsi_tm_rep));
leapraid_set_tm_flg(adapter, hdl);
init_completion(&adapter->driver_cmds.tm_cmd.done);
@@ -257,16 +245,20 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
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);
issue_reset =
leapraid_check_reset(
adapter->driver_cmds.tm_cmd.status);
if (issue_reset) {
dev_info(&adapter->pdev->dev,
- "%s:%d call hard_reset\n",
+ "%s:%d: call hard_reset\n",
__func__, __LINE__);
rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
- rc = (!rc) ? SUCCESS : FAILED;
- goto out;
+ rc = !rc ? SUCCESS : FAILED;
+ goto out_cleanup;
}
}
@@ -276,15 +268,15 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
case LEAPRAID_TM_TASKTYPE_TARGET_RESET:
case LEAPRAID_TM_TASKTYPE_ABRT_TASK_SET:
case LEAPRAID_TM_TASKTYPE_LOGICAL_UNIT_RESET:
- rc = leapraid_tm_post_processing(adapter, hdl, channel, id, lun,
- type, target_taskid);
+ rc = leapraid_tm_post_processing(adapter, hdl, channel, id,
+ lun, type, target_taskid);
break;
case LEAPRAID_TM_TASKTYPE_ABORT_TASK:
rc = SUCCESS;
scsiio_req = leapraid_get_task_desc(adapter, target_taskid);
if (le16_to_cpu(scsiio_req->dev_hdl) != hdl)
break;
- dev_err(&adapter->pdev->dev, "%s abort failed, hdl=0x%04x\n",
+ dev_err(&adapter->pdev->dev, "%s: Abort failed, hdl=0x%04x\n",
adapter->adapter_attr.name, hdl);
rc = FAILED;
break;
@@ -296,7 +288,7 @@ int leapraid_issue_tm(struct leapraid_adapter *adapter, u16 hdl, uint channel,
break;
}
-out:
+out_cleanup:
leapraid_clear_tm_flg(adapter, hdl);
adapter->driver_cmds.tm_cmd.status = LEAPRAID_CMD_NOT_USED;
return rc;
@@ -327,20 +319,25 @@ void leapraid_smart_fault_detect(struct leapraid_adapter *adapter, u16 hdl)
sas_dev = leapraid_hold_lock_get_sas_dev_by_hdl(adapter, hdl);
if (!sas_dev) {
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
- goto out;
+ return;
}
starget = sas_dev->starget;
- starget_priv = starget->hostdata;
- if ((starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER) ||
- (starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME)) {
+ starget_priv = starget ? starget->hostdata : NULL;
+ if (!starget_priv) {
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
- goto out;
+ goto release_sdev;
+ }
+
+ if (starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER ||
+ starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME) {
+ spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
+ goto release_sdev;
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
leapraid_async_turn_on_led(adapter, hdl);
-out:
+release_sdev:
if (sas_dev)
leapraid_sdev_put(sas_dev);
}
@@ -420,7 +417,8 @@ static void leapraid_handle_success_status(
scmd->result = DID_RESET << LEAPRAID_SCSI_HOST_SHIFT;
}
-static void leapraid_scsiio_done_dispatch(struct leapraid_adapter *adapter,
+static void leapraid_scsiio_done_dispatch(
+ struct leapraid_adapter *adapter,
struct leapraid_scsiio_rep *scsiio_rep,
struct leapraid_sdev_priv *sdev_priv,
struct scsi_cmnd *scmd,
@@ -442,9 +440,8 @@ static void leapraid_scsiio_done_dispatch(struct leapraid_adapter *adapter,
xfer_cnt == 0 &&
(scsi_status == LEAPRAID_SCSI_STATUS_BUSY ||
scsi_status == LEAPRAID_SCSI_STATUS_RESERVATION_CONFLICT ||
- scsi_status == LEAPRAID_SCSI_STATUS_TASK_SET_FULL)) {
+ scsi_status == LEAPRAID_SCSI_STATUS_TASK_SET_FULL))
adapter_status = LEAPRAID_ADAPTER_STATUS_SUCCESS;
- }
switch (adapter_status) {
case LEAPRAID_ADAPTER_STATUS_SCSI_DEVICE_NOT_THERE:
@@ -516,7 +513,7 @@ static void leapraid_scsiio_done_dispatch(struct leapraid_adapter *adapter,
scsi_print_command(scmd);
dev_warn(&adapter->pdev->dev,
- "scsiio warn: hdl=0x%x, status are: 0x%x, 0x%x, 0x%x\n",
+ "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);
@@ -526,24 +523,23 @@ static void leapraid_scsiio_done_dispatch(struct leapraid_adapter *adapter,
sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
le32_to_cpu(scsiio_rep->sense_count));
if (scsi_normalize_sense(scmd->sense_buffer, sz,
- &sshdr)) {
+ &sshdr))
dev_warn(&adapter->pdev->dev,
- "sense: key=0x%x asc=0x%x ascq=0x%x\n",
+ "Sense: key=0x%x asc=0x%x ascq=0x%x\n",
sshdr.sense_key, sshdr.asc,
sshdr.ascq);
- } else {
+ else
dev_warn(&adapter->pdev->dev,
- "sense: invalid sense data\n");
- }
+ "Sense: Invalid sense data\n");
}
}
-u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
- u8 msix_index, u32 rep)
+bool leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
+ u8 msix_index, u32 rep)
{
- struct leapraid_scsiio_rep *scsiio_rep = NULL;
- struct leapraid_sdev_priv *sdev_priv = NULL;
- struct scsi_cmnd *scmd = NULL;
+ struct leapraid_scsiio_rep *scsiio_rep;
+ struct leapraid_sdev_priv *sdev_priv;
+ struct scsi_cmnd *scmd;
u32 response_code = 0;
if (likely(taskid != adapter->driver_cmds.driver_scsiio_cmd.taskid))
@@ -551,12 +547,12 @@ u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
else
scmd = adapter->driver_cmds.internal_scmd;
if (!scmd)
- return 1;
+ return true;
scsiio_rep = leapraid_get_reply_vaddr(adapter, rep);
if (!scsiio_rep) {
scmd->result = DID_OK << LEAPRAID_SCSI_HOST_SHIFT;
- goto out;
+ goto out_scsiio_done;
}
sdev_priv = scmd->device->hostdata;
@@ -564,7 +560,7 @@ u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
!sdev_priv->starget_priv ||
sdev_priv->starget_priv->deleted) {
scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT;
- goto out;
+ goto out_scsiio_done;
}
if (scsiio_rep->scsi_state & LEAPRAID_SCSI_STATE_RESPONSE_INFO_VALID)
@@ -574,33 +570,51 @@ u8 leapraid_scsiio_done(struct leapraid_adapter *adapter, u16 taskid,
leapraid_scsiio_done_dispatch(adapter, scsiio_rep, sdev_priv, scmd,
taskid, response_code);
-out:
+out_scsiio_done:
scsi_dma_unmap(scmd);
- if (unlikely(taskid == adapter->driver_cmds.driver_scsiio_cmd.taskid)) {
+ 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 0;
+ return false;
}
leapraid_free_taskid(adapter, taskid);
scmd->scsi_done(scmd);
- return 0;
+ return false;
}
static void leapraid_probe_raid(struct leapraid_adapter *adapter)
{
- struct leapraid_raid_volume *raid_volume, *raid_volume_next;
+ struct leapraid_raid_volume *raid_volume, *next_raid_volume;
+ unsigned long flags;
+ LIST_HEAD(head);
int rc;
- list_for_each_entry_safe(raid_volume, raid_volume_next,
- &adapter->dev_topo.raid_volume_list, list) {
- if (raid_volume->starget)
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ list_splice_init(&adapter->dev_topo.raid_volume_list, &head);
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
+
+ list_for_each_entry_safe(raid_volume, next_raid_volume, &head, list) {
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ list_move_tail(&raid_volume->list,
+ &adapter->dev_topo.raid_volume_list);
+ if (raid_volume->starget) {
+ spin_unlock_irqrestore(
+ &adapter->dev_topo.raid_volume_lock, flags);
continue;
+ }
+
+ leapraid_raid_volume_get(raid_volume);
+ spin_unlock_irqrestore(
+ &adapter->dev_topo.raid_volume_lock, flags);
rc = scsi_add_device(adapter->shost, RAID_CHANNEL,
raid_volume->id, 0);
if (rc)
leapraid_raid_volume_remove(adapter, raid_volume);
+
+ leapraid_raid_volume_put(raid_volume);
}
}
@@ -629,7 +643,6 @@ static void leapraid_probe_sas(struct leapraid_adapter *adapter)
sas_dev = leapraid_get_next_sas_dev_from_init_list(adapter);
if (!sas_dev)
break;
-
added = leapraid_transport_port_add(adapter,
sas_dev->hdl,
sas_dev->parent_sas_addr,
@@ -657,32 +670,52 @@ static void leapraid_probe_sas(struct leapraid_adapter *adapter)
}
}
-static bool leapraid_get_boot_dev(struct leapraid_boot_dev *boot_dev,
+static bool leapraid_get_boot_dev(struct leapraid_adapter *adapter,
+ struct leapraid_boot_dev *boot_dev,
void **pdev, u32 *pchnl)
{
- if (boot_dev->dev) {
- *pdev = boot_dev->dev;
- *pchnl = boot_dev->chnl;
- return true;
+ unsigned long flags;
+ void *dev;
+ u32 chnl;
+
+ spin_lock_irqsave(&adapter->boot_devs.lock, flags);
+ if (!boot_dev->dev) {
+ spin_unlock_irqrestore(&adapter->boot_devs.lock, flags);
+ return false;
}
- return false;
+
+ dev = boot_dev->dev;
+ chnl = boot_dev->chnl;
+ leapraid_boot_dev_get(dev, chnl);
+ spin_unlock_irqrestore(&adapter->boot_devs.lock, flags);
+
+ *pdev = dev;
+ *pchnl = chnl;
+ return true;
}
static void leapraid_probe_boot_dev(struct leapraid_adapter *adapter)
{
+ struct leapraid_raid_volume *raid_volume;
+ struct leapraid_sas_dev *sas_dev;
+ struct leapraid_sas_port *sport;
+ unsigned long flags;
void *dev = NULL;
u32 chnl;
- if (leapraid_get_boot_dev(&adapter->boot_devs.requested_boot_dev, &dev,
- &chnl))
+ if (leapraid_get_boot_dev(adapter,
+ &adapter->boot_devs.requested_boot_dev,
+ &dev, &chnl))
goto boot_dev_found;
- if (leapraid_get_boot_dev(&adapter->boot_devs.requested_alt_boot_dev,
+ if (leapraid_get_boot_dev(adapter,
+ &adapter->boot_devs.requested_alt_boot_dev,
&dev, &chnl))
goto boot_dev_found;
- if (leapraid_get_boot_dev(&adapter->boot_devs.current_boot_dev, &dev,
- &chnl))
+ if (leapraid_get_boot_dev(adapter,
+ &adapter->boot_devs.current_boot_dev,
+ &dev, &chnl))
goto boot_dev_found;
return;
@@ -690,12 +723,10 @@ static void leapraid_probe_boot_dev(struct leapraid_adapter *adapter)
boot_dev_found:
switch (chnl) {
case RAID_CHANNEL:
- {
- struct leapraid_raid_volume *raid_volume =
- (struct leapraid_raid_volume *)dev;
+ raid_volume = dev;
if (raid_volume->starget)
- return;
+ break;
/* TODO eedp */
@@ -703,16 +734,11 @@ static void leapraid_probe_boot_dev(struct leapraid_adapter *adapter)
raid_volume->id, 0))
leapraid_raid_volume_remove(adapter, raid_volume);
break;
- }
default:
- {
- struct leapraid_sas_dev *sas_dev =
- (struct leapraid_sas_dev *)dev;
- struct leapraid_sas_port *sas_port;
- unsigned long flags;
+ sas_dev = dev;
if (sas_dev->starget)
- return;
+ break;
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
list_move_tail(&sas_dev->list,
@@ -720,16 +746,17 @@ static void leapraid_probe_boot_dev(struct leapraid_adapter *adapter)
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
if (!sas_dev->card_port)
- return;
+ break;
- sas_port = leapraid_transport_port_add(adapter, sas_dev->hdl,
- sas_dev->parent_sas_addr,
- sas_dev->card_port);
- if (!sas_port)
+ sport = leapraid_transport_port_add(adapter, sas_dev->hdl,
+ sas_dev->parent_sas_addr,
+ sas_dev->card_port);
+ if (!sport)
leapraid_sas_dev_remove(adapter, sas_dev);
break;
}
- }
+
+ leapraid_boot_dev_put(dev, chnl);
}
static void leapraid_probe_devices(struct leapraid_adapter *adapter)
@@ -747,69 +774,23 @@ static void leapraid_probe_devices(struct leapraid_adapter *adapter)
void leapraid_scan_dev_done(struct leapraid_adapter *adapter)
{
if (adapter->scan_dev_desc.wait_scan_dev_done) {
- adapter->scan_dev_desc.wait_scan_dev_done = false;
+ adapter->scan_dev_desc.wait_scan_dev_done = 0;
leapraid_probe_devices(adapter);
}
+ adapter->scan_dev_desc.scan_start = 0;
+
leapraid_check_scheduled_fault_start(adapter);
leapraid_fw_log_start(adapter);
- adapter->scan_dev_desc.driver_loading = false;
+ adapter->scan_dev_desc.driver_loading = 0;
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
leapraid_smart_polling_start(adapter);
}
-static void leapraid_ir_shutdown(struct leapraid_adapter *adapter)
-{
- struct leapraid_raid_act_req *raid_act_req;
- struct leapraid_raid_act_rep *raid_act_rep;
- struct leapraid_driver_cmd *raid_action_cmd;
-
- if (!adapter || !adapter->adapter_attr.raid_support)
- return;
-
- if (list_empty(&adapter->dev_topo.raid_volume_list))
- return;
-
- if (leapraid_pci_removed(adapter))
- return;
-
- raid_action_cmd = &adapter->driver_cmds.raid_action_cmd;
-
- mutex_lock(&raid_action_cmd->mutex);
- raid_action_cmd->status = LEAPRAID_CMD_PENDING;
-
- raid_act_req = leapraid_get_task_desc(adapter,
- raid_action_cmd->inter_taskid);
- memset(raid_act_req, 0, sizeof(struct leapraid_raid_act_req));
- raid_act_req->func = LEAPRAID_FUNC_RAID_ACTION;
- raid_act_req->act = LEAPRAID_RAID_ACT_SYSTEM_SHUTDOWN_INITIATED;
-
- dev_info(&adapter->pdev->dev, "ir shutdown start\n");
- init_completion(&raid_action_cmd->done);
- leapraid_fire_task(adapter, raid_action_cmd->inter_taskid);
- wait_for_completion_timeout(&raid_action_cmd->done,
- LEAPRAID_RAID_ACTION_CMD_TIMEOUT * HZ);
-
- if (!(raid_action_cmd->status & LEAPRAID_CMD_DONE)) {
- dev_err(&adapter->pdev->dev,
- "%s: timeout waiting for ir shutdown\n", __func__);
- goto out;
- }
-
- if (raid_action_cmd->status & LEAPRAID_CMD_REPLY_VALID) {
- raid_act_rep = (void *)(&raid_action_cmd->reply);
- dev_info(&adapter->pdev->dev,
- "ir shutdown done, adapter status=0x%04x\n",
- le16_to_cpu(raid_act_rep->adapter_status));
- }
-
-out:
- raid_action_cmd->status = LEAPRAID_CMD_NOT_USED;
- mutex_unlock(&raid_action_cmd->mutex);
-}
-
static const struct pci_device_id leapraid_pci_table[] = {
- { PCI_DEVICE(LEAPRAID_VENDOR_ID, LEAPRAID_DEVID_HBA) },
- { PCI_DEVICE(LEAPRAID_VENDOR_ID, LEAPRAID_DEVID_RAID) },
+ { PCI_DEVICE_SUB(LEAPRAID_VENDOR_ID, LEAPRAID_DEVID_HBA,
+ LEAPRAID_SUBVENDOR_ID,
+ LEAPRAID_SUBDEVID_HBA) },
{ 0, }
};
@@ -819,7 +800,7 @@ static inline bool leapraid_is_scmd_permitted(struct leapraid_adapter *adapter,
u8 opcode;
if (adapter->access_ctrl.pcie_recovering ||
- adapter->access_ctrl.adapter_thermal_alert)
+ atomic_read(&adapter->overheat_desc.thermal_alert))
return false;
if (adapter->access_ctrl.host_removing) {
@@ -829,8 +810,8 @@ static inline bool leapraid_is_scmd_permitted(struct leapraid_adapter *adapter,
opcode = scmd->cmnd[0];
if (opcode == SYNCHRONIZE_CACHE || opcode == START_STOP)
return true;
- else
- return false;
+
+ return false;
}
return true;
}
@@ -860,28 +841,33 @@ static bool leapraid_should_queuecommand(struct leapraid_adapter *adapter,
scmd->result = (DRIVER_SENSE << LEAPRAID_SCSI_DRIVER_SHIFT) |
(DID_OK << LEAPRAID_SCSI_HOST_SHIFT) |
SAM_STAT_CHECK_CONDITION;
- goto done_out;
+ goto scsiio_done;
}
if (adapter->access_ctrl.shost_recovering ||
adapter->reset_desc.adapter_link_resetting) {
*rc = SCSI_MLQUEUE_HOST_BUSY;
- goto out;
- } else if (starget_priv->deleted || sdev_priv->deleted) {
+ return false;
+ }
+
+ if (starget_priv->deleted || sdev_priv->deleted)
goto no_connect;
- } else if (starget_priv->tm_busy || sdev_priv->block) {
+
+ if (starget_priv->tm_busy || sdev_priv->block) {
*rc = SCSI_MLQUEUE_DEVICE_BUSY;
- goto out;
+ return false;
}
return true;
no_connect:
scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT;
-done_out:
+scsiio_done:
if (likely(scmd != adapter->driver_cmds.internal_scmd))
scmd->scsi_done(scmd);
-out:
+ else
+ *rc = LEAPRAID_OPERATION_FAILED;
+
return false;
}
@@ -909,12 +895,14 @@ static u32 build_scsiio_req_control(struct scsi_cmnd *scmd,
IOPRIO_CLASS_RT))
control |= LEAPRAID_SCSIIO_CTRL_CMDPRI;
if (scmd->cmd_len == 32)
- control |= 4 << LEAPRAID_SCSIIO_CTRL_ADDCDBLEN_SHIFT;
+ control |= LEAPRAID_SCSIIO_CTRL_CDB_32BYTE <<
+ LEAPRAID_SCSIIO_CTRL_CDB_LEN_SHIFT;
return control;
}
-int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
+int leapraid_queuecommand(struct Scsi_Host *shost,
+ struct scsi_cmnd *scmd)
{
struct leapraid_adapter *adapter = shost_priv(scmd->device->host);
struct leapraid_sdev_priv *sdev_priv = scmd->device->hostdata;
@@ -926,7 +914,7 @@ int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
int rc = 0;
if (!leapraid_should_queuecommand(adapter, sdev_priv, scmd, &rc))
- goto out;
+ return rc;
starget_priv = sdev_priv->starget_priv;
hdl = starget_priv->hdl;
@@ -938,11 +926,11 @@ int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
taskid = leapraid_alloc_scsiio_taskid(adapter, scmd);
scsiio_req = leapraid_get_task_desc(adapter, taskid);
- scsiio_req->func = LEAPRAID_FUNC_SCSIIO_REQ;
+ scsiio_req->func = LEAPRAID_FUNC_SCSIIO;
if (sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER)
- scsiio_req->func = LEAPRAID_FUNC_RAID_SCSIIO_PASSTHROUGH;
+ scsiio_req->func = LEAPRAID_FUNC_SCSIIO_RAID_PASSTHROUGH;
else
- scsiio_req->func = LEAPRAID_FUNC_SCSIIO_REQ;
+ scsiio_req->func = LEAPRAID_FUNC_SCSIIO;
scsiio_req->dev_hdl = cpu_to_le16(hdl);
scsiio_req->data_len = cpu_to_le32(scsi_bufflen(scmd));
@@ -960,23 +948,21 @@ int leapraid_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
if (scsiio_req->data_len) {
if (leapraid_build_scmd_ieee_sg(adapter, scmd, taskid)) {
leapraid_free_taskid(adapter, taskid);
- rc = SCSI_MLQUEUE_HOST_BUSY;
- goto out;
+ return SCSI_MLQUEUE_HOST_BUSY;
}
} else {
leapraid_build_ieee_nodata_sg(adapter, &scsiio_req->sgl);
}
- if (likely(scsiio_req->func == LEAPRAID_FUNC_SCSIIO_REQ)) {
+ if (likely(scsiio_req->func == LEAPRAID_FUNC_SCSIIO))
leapraid_fire_scsi_io(adapter, taskid,
- le16_to_cpu(scsiio_req->dev_hdl));
- } else {
+ le16_to_cpu(scsiio_req->dev_hdl));
+ else
leapraid_fire_task(adapter, taskid);
- }
+
dev_dbg(&adapter->pdev->dev,
"LEAPRAID_SCSIIO: Send Descriptor taskid %d, req type 0x%x\n",
taskid, scsiio_req->func);
-out:
return rc;
}
@@ -999,9 +985,9 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd,
scsi_print_command(scmd);
if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK) {
- io_req_tracker = leapraid_get_scmd_priv(scmd);
+ io_req_tracker = (struct leapraid_io_req_tracker *)scmd->host_scribble;
dev_info(&adapter->pdev->dev,
- "EH ABORT: scmd=0x%p, pending=%u ms, tout=%u ms, req tag=%d\n",
+ "EH ABORT: scmd=0x%p, pend=%ums, tout=%ums, tag=%d\n",
scmd,
jiffies_to_msecs(jiffies - scmd->jiffies_at_alloc),
(scmd->request->timeout / HZ) * 1000,
@@ -1014,48 +1000,47 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd,
"EH %s failed: %s scmd=0x%p\n", str,
(adapter->access_ctrl.host_removing ?
"shost removing!" : "pci_dev removed!"), scmd);
- if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK)
- if (io_req_tracker && io_req_tracker->taskid)
- leapraid_free_taskid(adapter,
- io_req_tracker->taskid);
+ if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK &&
+ io_req_tracker && io_req_tracker->taskid)
+ leapraid_free_taskid(adapter, io_req_tracker->taskid);
scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT;
#ifdef FAST_IO_FAIL
rc = FAST_IO_FAIL;
#else
rc = FAILED;
#endif
- goto out;
+ goto out_eh_done;
}
sdev_priv = scmd->device->hostdata;
if (!sdev_priv || !sdev_priv->starget_priv) {
dev_warn(&adapter->pdev->dev,
- "EH %s: sdev or starget gone, scmd=0x%p\n",
+ "EH %s: SAS dev or starget gone, scmd=0x%p\n",
str, scmd);
scmd->result = DID_NO_CONNECT << LEAPRAID_SCSI_HOST_SHIFT;
scmd->scsi_done(scmd);
rc = SUCCESS;
- goto out;
+ goto out_eh_done;
}
if (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK) {
if (!io_req_tracker) {
dev_warn(&adapter->pdev->dev,
- "EH ABORT: no io tracker, scmd 0x%p\n", scmd);
+ "EH ABORT: No I/O tracker, scmd 0x%p\n", scmd);
scmd->result = DID_RESET << LEAPRAID_SCSI_HOST_SHIFT;
rc = SUCCESS;
- goto out;
+ goto out_eh_done;
}
if (sdev_priv->starget_priv->flg &
LEAPRAID_TGT_FLG_RAID_MEMBER ||
sdev_priv->starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME) {
dev_err(&adapter->pdev->dev,
- "EH ABORT: skip RAID/VOLUME target, scmd=0x%p\n",
+ "EH ABORT: Skip RAID/VOLUME, scmd=0x%p\n",
scmd);
scmd->result = DID_RESET << LEAPRAID_SCSI_HOST_SHIFT;
rc = FAILED;
- goto out;
+ goto out_eh_done;
}
hdl = sdev_priv->starget_priv->hdl;
@@ -1073,11 +1058,11 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd,
if (!hdl) {
dev_err(&adapter->pdev->dev,
- "EH %s failed: target handle is 0, scmd=0x%p\n",
+ "EH %s failed: Target handle 0, scmd=0x%p\n",
str, scmd);
scmd->result = DID_RESET << LEAPRAID_SCSI_HOST_SHIFT;
rc = FAILED;
- goto out;
+ goto out_eh_done;
}
}
@@ -1085,24 +1070,27 @@ static int leapraid_error_handler(struct scsi_cmnd *scmd,
"EH issue TM: type=%s, scmd=0x%p, hdl=0x%x\n",
str, scmd, hdl);
- rc = leapraid_issue_locked_tm(adapter, hdl, scmd->device->channel,
- scmd->device->id,
- (type == LEAPRAID_TM_TASKTYPE_TARGET_RESET ?
- 0 : scmd->device->lun),
- type,
- (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK ?
- io_req_tracker->taskid : 0),
- LEAPRAID_TM_MSGFLAGS_LINK_RESET);
-
-out:
+ rc = leapraid_issue_locked_tm(
+ adapter,
+ hdl,
+ scmd->device->channel,
+ scmd->device->id,
+ (type == LEAPRAID_TM_TASKTYPE_TARGET_RESET ?
+ 0 : scmd->device->lun),
+ type,
+ (type == LEAPRAID_TM_TASKTYPE_ABORT_TASK ?
+ io_req_tracker->taskid : 0),
+ LEAPRAID_TM_MSGFLAGS_LINK_RESET);
+
+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);
+ rc == SUCCESS ? "success" : "failed", scmd);
} else {
dev_info(&adapter->pdev->dev,
"EH %s result: %s, scmd=0x%p\n",
- str, ((rc == SUCCESS) ? "success" : "failed"), scmd);
+ str, rc == SUCCESS ? "success" : "failed", scmd);
if (sas_dev)
leapraid_sdev_put(sas_dev);
}
@@ -1145,19 +1133,19 @@ static int leapraid_eh_host_reset_handler(struct scsi_cmnd *scmd)
(adapter->access_ctrl.host_removing ?
"shost removing!" : "driver loading!"), scmd);
rc = FAILED;
- goto out;
+ goto out_host_reset_done;
}
- dev_info(&adapter->pdev->dev, "%s:%d issuing hard reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: Issuing hard reset\n",
__func__, __LINE__);
if (leapraid_hard_reset_handler(adapter, FULL_RESET) < 0)
rc = FAILED;
else
rc = SUCCESS;
-out:
+out_host_reset_done:
dev_info(&adapter->pdev->dev, "EH HOST RESET result: %s, scmd=0x%p\n",
- ((rc == SUCCESS) ? "success" : "failed"), scmd);
+ rc == SUCCESS ? "success" : "failed", scmd);
return rc;
}
@@ -1183,30 +1171,35 @@ static int leapraid_slave_alloc(struct scsi_device *sdev)
stgt_priv->num_luns++;
sdev_priv->starget_priv = stgt_priv;
sdev->hostdata = sdev_priv;
- if ((stgt_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER))
+ if (stgt_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER)
sdev->no_uld_attach = LEAPRAID_NO_ULD_ATTACH;
shost = dev_to_shost(&tgt->dev);
adapter = shost_priv(shost);
if (tgt->channel == RAID_CHANNEL) {
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_id(adapter,
tgt->id,
tgt->channel);
- if (raid_volume)
+ if (raid_volume) {
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock,
+ flags);
raid_volume->sdev = sdev;
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
- flags);
+ spin_unlock_irqrestore(
+ &adapter->dev_topo.raid_volume_lock, flags);
+ leapraid_raid_volume_put(raid_volume);
+ }
}
if (!(stgt_priv->flg & LEAPRAID_TGT_FLG_VOLUME)) {
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
- sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter,
- stgt_priv->sas_address,
- stgt_priv->card_port);
+ sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(
+ adapter,
+ stgt_priv->sas_address,
+ stgt_priv->card_port);
if (sas_dev && !sas_dev->starget) {
sdev_printk(KERN_INFO, sdev,
- "%s: assign starget to sas_dev\n", __func__);
+ "%s: Assign starget to sas_dev\n",
+ __func__);
sas_dev->starget = tgt;
}
@@ -1224,7 +1217,6 @@ static int leapraid_slave_cfg_volume(struct scsi_device *sdev)
struct leapraid_raid_volume *raid_volume;
struct leapraid_starget_priv *starget_priv;
struct leapraid_sdev_priv *sdev_priv;
- unsigned long flags;
int qd;
u16 hdl;
@@ -1232,37 +1224,38 @@ static int leapraid_slave_cfg_volume(struct scsi_device *sdev)
starget_priv = sdev_priv->starget_priv;
hdl = starget_priv->hdl;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_hdl(adapter, hdl);
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
if (!raid_volume) {
sdev_printk(KERN_WARNING, sdev,
- "%s: raid_volume not found, hdl=0x%x\n",
+ "%s: RAID volume not found, hdl=0x%x\n",
__func__, hdl);
return 1;
}
if (leapraid_get_volume_cap(adapter, raid_volume)) {
sdev_printk(KERN_ERR, sdev,
- "%s: failed to get volume cap, hdl=0x%x\n",
+ "%s: Failed to get volume cap, hdl=0x%x\n",
__func__, hdl);
+ leapraid_raid_volume_put(raid_volume);
return 1;
}
qd = (raid_volume->dev_info & LEAPRAID_DEVTYP_SSP_TGT) ?
- LEAPRAID_SAS_QUEUE_DEPTH : LEAPRAID_SATA_QUEUE_DEPTH;
+ adapter->adapter_attr.narrowport_max_queue_depth :
+ adapter->adapter_attr.sata_max_queue_depth;
if (raid_volume->vol_type != LEAPRAID_VOL_TYPE_RAID0)
- qd = LEAPRAID_RAID_QUEUE_DEPTH;
+ qd = adapter->adapter_attr.raid_volume_max_queue_depth;
sdev_printk(KERN_INFO, sdev,
- "raid volume: hdl=0x%04x, wwid=0x%016llx\n",
+ "RAID volume: hdl=0x%04x, wwid=0x%016llx\n",
raid_volume->hdl, (unsigned long long)raid_volume->wwid);
if (shost->max_sectors > LEAPRAID_MAX_SECTORS)
blk_queue_max_hw_sectors(sdev->request_queue,
LEAPRAID_MAX_SECTORS);
- leapraid_adjust_sdev_queue_depth(sdev, qd);
+ leapraid_change_queue_depth(sdev, qd);
+ leapraid_raid_volume_put(raid_volume);
return 0;
}
@@ -1280,13 +1273,14 @@ static int leapraid_slave_configure_extra(struct scsi_device *sdev,
sdev_priv = sdev->hostdata;
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
*is_target_ssp = false;
- sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(adapter,
- sdev_priv->starget_priv->sas_address,
- sdev_priv->starget_priv->card_port);
+ sas_dev = leapraid_hold_lock_get_sas_dev_by_addr(
+ adapter,
+ sdev_priv->starget_priv->sas_address,
+ sdev_priv->starget_priv->card_port);
if (!sas_dev) {
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
sdev_printk(KERN_WARNING, sdev,
- "%s: sas_dev not found, sas=0x%llx\n",
+ "%s: SAS dev not found, sas=0x%llx\n",
__func__, sdev_priv->starget_priv->sas_address);
return 1;
}
@@ -1295,18 +1289,18 @@ static int leapraid_slave_configure_extra(struct scsi_device *sdev,
sas_dev->volume_hdl = vol_hdl;
sas_dev->volume_wwid = volume_wwid;
if (sas_dev->dev_info & LEAPRAID_DEVTYP_SSP_TGT) {
- *qd = (sas_dev->port_type > 1) ?
+ *qd = (sas_dev->port_connection > 1) ?
adapter->adapter_attr.wideport_max_queue_depth :
adapter->adapter_attr.narrowport_max_queue_depth;
*is_target_ssp = true;
if (sas_dev->dev_info & LEAPRAID_DEVTYP_SEP)
- sdev_priv->sep = true;
+ sdev_priv->sep = 1;
} else {
*qd = adapter->adapter_attr.sata_max_queue_depth;
}
sdev_printk(KERN_INFO, sdev,
- "sdev: dev name=0x%016llx, sas addr=0x%016llx\n",
+ "device name=0x%016llx, SAS addr=0x%016llx\n",
(unsigned long long)sas_dev->dev_name,
(unsigned long long)sas_dev->sas_addr);
leapraid_sdev_put(sas_dev);
@@ -1337,7 +1331,7 @@ static int leapraid_slave_configure(struct scsi_device *sdev)
if (starget_priv->flg & LEAPRAID_TGT_FLG_RAID_MEMBER) {
if (leapraid_cfg_get_volume_hdl(adapter, hdl, &vol_hdl)) {
sdev_printk(KERN_WARNING, sdev,
- "%s: get volume hdl failed, hdl=0x%x\n",
+ "%s: Get volume hdl failed, hdl=0x%x\n",
__func__, hdl);
return 1;
}
@@ -1345,7 +1339,7 @@ static int leapraid_slave_configure(struct scsi_device *sdev)
if (vol_hdl && leapraid_cfg_get_volume_wwid(adapter, vol_hdl,
&volume_wwid)) {
sdev_printk(KERN_WARNING, sdev,
- "%s: get wwid failed, volume_hdl=0x%x\n",
+ "%s: Get wwid failed, volume_hdl=0x%x\n",
__func__, vol_hdl);
return 1;
}
@@ -1358,7 +1352,7 @@ static int leapraid_slave_configure(struct scsi_device *sdev)
return 1;
}
- leapraid_adjust_sdev_queue_depth(sdev, qd);
+ leapraid_change_queue_depth(sdev, qd);
if (is_target_ssp)
sas_read_port_mode_page(sdev);
@@ -1405,17 +1399,19 @@ static int leapraid_target_alloc_raid(struct scsi_target *tgt)
struct leapraid_adapter *adapter = shost_priv(shost);
unsigned long flags;
- starget_priv = (struct leapraid_starget_priv *)tgt->hostdata;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
+ starget_priv = tgt->hostdata;
raid_volume = leapraid_raid_volume_find_by_id(adapter, tgt->id,
tgt->channel);
if (raid_volume) {
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
starget_priv->hdl = raid_volume->hdl;
starget_priv->sas_address = raid_volume->wwid;
starget_priv->flg |= LEAPRAID_TGT_FLG_VOLUME;
raid_volume->starget = tgt;
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
+ flags);
+ leapraid_raid_volume_put(raid_volume);
}
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
return 0;
}
@@ -1430,12 +1426,13 @@ static int leapraid_target_alloc_sas(struct scsi_target *tgt)
shost = dev_to_shost(&tgt->dev);
adapter = shost_priv(shost);
- starget_priv = (struct leapraid_starget_priv *)tgt->hostdata;
+ starget_priv = tgt->hostdata;
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
rphy = dev_to_rphy(tgt->dev.parent);
- sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(adapter,
- rphy->identify.sas_address,
- rphy);
+ sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(
+ adapter,
+ rphy->identify.sas_address,
+ rphy);
if (sas_dev) {
starget_priv->sas_dev = sas_dev;
starget_priv->card_port = sas_dev->card_port;
@@ -1444,8 +1441,10 @@ static int leapraid_target_alloc_sas(struct scsi_target *tgt)
sas_dev->channel = tgt->channel;
sas_dev->id = tgt->id;
sas_dev->starget = tgt;
- if (test_bit(sas_dev->hdl,
- (unsigned long *)adapter->dev_topo.pd_hdls))
+ if (sas_dev->hdl &&
+ sas_dev->hdl <=
+ adapter->adapter_attr.features.max_dev_handle &&
+ test_bit(sas_dev->hdl, adapter->dev_topo.pd_hdls))
starget_priv->flg |= LEAPRAID_TGT_FLG_RAID_MEMBER;
}
spin_unlock_irqrestore(&adapter->dev_topo.sas_dev_lock, flags);
@@ -1477,14 +1476,16 @@ static void leapraid_target_destroy_raid(struct scsi_target *tgt)
struct leapraid_adapter *adapter = shost_priv(shost);
unsigned long flags;
- spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume = leapraid_raid_volume_find_by_id(adapter, tgt->id,
tgt->channel);
if (raid_volume) {
+ spin_lock_irqsave(&adapter->dev_topo.raid_volume_lock, flags);
raid_volume->starget = NULL;
raid_volume->sdev = NULL;
+ spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock,
+ flags);
+ leapraid_raid_volume_put(raid_volume);
}
- spin_unlock_irqrestore(&adapter->dev_topo.raid_volume_lock, flags);
}
static void leapraid_target_destroy_sas(struct scsi_target *tgt)
@@ -1526,12 +1527,12 @@ static void leapraid_target_destroy(struct scsi_target *tgt)
if (tgt->channel == RAID_CHANNEL) {
leapraid_target_destroy_raid(tgt);
- goto out;
+ goto out_free;
}
leapraid_target_destroy_sas(tgt);
-out:
+out_free:
kfree(starget_priv);
tgt->hostdata = NULL;
}
@@ -1552,24 +1553,27 @@ static bool leapraid_scan_check_status(struct leapraid_adapter *adapter,
if (adapter->driver_cmds.scan_dev_cmd.status & LEAPRAID_CMD_RESET) {
dev_err(&adapter->pdev->dev,
- "device scan: aborted due to reset\n");
+ "Device scan: Aborted due to reset\n");
adapter->driver_cmds.scan_dev_cmd.status =
LEAPRAID_CMD_NOT_USED;
- adapter->scan_dev_desc.driver_loading = false;
+ adapter->scan_dev_desc.driver_loading = 0;
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
return true;
}
if (adapter->scan_dev_desc.scan_start_failed) {
dev_err(&adapter->pdev->dev,
- "device scan: failed with adapter_status=0x%08x\n",
+ "Device scan: Failed with adapter_status=0x%08x\n",
adapter->scan_dev_desc.scan_start_failed);
- adapter->scan_dev_desc.driver_loading = false;
- adapter->scan_dev_desc.wait_scan_dev_done = false;
- adapter->access_ctrl.host_removing = true;
+ adapter->scan_dev_desc.driver_loading = 0;
+ 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");
+ 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;
@@ -1584,8 +1588,9 @@ static int leapraid_scan_finished(struct Scsi_Host *shost, unsigned long time)
adapter->driver_cmds.scan_dev_cmd.status =
LEAPRAID_CMD_NOT_USED;
dev_err(&adapter->pdev->dev,
- "device scan: failed with timeout 300s\n");
- adapter->scan_dev_desc.driver_loading = false;
+ "Device scan: Failed with timeout 300s\n");
+ adapter->scan_dev_desc.driver_loading = 0;
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
return 1;
}
@@ -1595,10 +1600,12 @@ static int leapraid_scan_finished(struct Scsi_Host *shost, unsigned long time)
if (need_hard_reset) {
adapter->driver_cmds.scan_dev_cmd.status =
LEAPRAID_CMD_NOT_USED;
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
- if (leapraid_hard_reset_handler(adapter, PART_RESET))
- adapter->scan_dev_desc.driver_loading = false;
+ if (leapraid_hard_reset_handler(adapter, PART_RESET)) {
+ adapter->scan_dev_desc.driver_loading = 0;
+ wake_up(&adapter->scan_dev_desc.wait_driver_loading);
+ }
}
return 1;
@@ -1608,18 +1615,88 @@ static void leapraid_scan_start(struct Scsi_Host *shost)
{
struct leapraid_adapter *adapter = shost_priv(shost);
- adapter->scan_dev_desc.scan_start = true;
+ adapter->scan_dev_desc.scan_start = 1;
leapraid_scan_dev(adapter, true);
}
+static u32 leapraid_get_raid_qd(struct leapraid_adapter *adapter,
+ const struct leapraid_raid_volume *raid_volume,
+ bool default_qd)
+{
+ const struct leapraid_adapter_attr *attr = &adapter->adapter_attr;
+
+ if (raid_volume->vol_type != LEAPRAID_VOL_TYPE_RAID0)
+ return default_qd ? LEAPRAID_RAID_QUEUE_DEPTH :
+ attr->raid_volume_max_queue_depth;
+
+ if (raid_volume->dev_info & LEAPRAID_DEVTYP_SSP_TGT)
+ return default_qd ? LEAPRAID_SAS_QUEUE_DEPTH :
+ attr->narrowport_max_queue_depth;
+
+ return default_qd ? LEAPRAID_SATA_QUEUE_DEPTH :
+ attr->sata_max_queue_depth;
+}
+
static int leapraid_calc_max_queue_depth(struct scsi_device *sdev, int qdepth)
{
struct Scsi_Host *shost;
+ struct leapraid_adapter *adapter;
+ struct leapraid_starget_priv *starget_priv;
+ struct leapraid_sdev_priv *sdev_priv;
+ struct leapraid_raid_volume *raid_volume;
+ struct leapraid_sas_dev *sas_dev;
int max_depth;
+ u32 default_qdepth = 0;
+ u32 fw_qdepth = 0;
shost = sdev->host;
+ adapter = shost_priv(shost);
max_depth = shost->can_queue;
+ sdev_priv = sdev->hostdata;
+ if (!sdev_priv)
+ goto out_tag_check;
+
+ starget_priv = sdev_priv->starget_priv;
+ if (!starget_priv)
+ goto out_tag_check;
+
+ if (starget_priv->flg & LEAPRAID_TGT_FLG_VOLUME) {
+ raid_volume = leapraid_raid_volume_find_by_hdl(
+ adapter, starget_priv->hdl);
+ if (raid_volume) {
+ default_qdepth = leapraid_get_raid_qd(
+ adapter, raid_volume, true);
+ fw_qdepth = leapraid_get_raid_qd(
+ adapter, raid_volume, false);
+ leapraid_raid_volume_put(raid_volume);
+ }
+ goto out_limit_check;
+ }
+
+ sas_dev = leapraid_get_sas_dev_from_tgt(adapter, starget_priv);
+ if (sas_dev) {
+ if (sas_dev->dev_info & LEAPRAID_DEVTYP_SSP_TGT) {
+ default_qdepth = LEAPRAID_SAS_QUEUE_DEPTH;
+ fw_qdepth = (sas_dev->port_connection > 1) ?
+ adapter->adapter_attr.wideport_max_queue_depth :
+ adapter->adapter_attr.narrowport_max_queue_depth;
+ }
+ if (sas_dev->dev_info & LEAPRAID_DEVTYP_SATA_DEV) {
+ default_qdepth = LEAPRAID_SATA_QUEUE_DEPTH;
+ fw_qdepth = adapter->adapter_attr.sata_max_queue_depth;
+ }
+ leapraid_sdev_put(sas_dev);
+ }
+
+out_limit_check:
+ if (fw_qdepth > shost->can_queue && default_qdepth)
+ fw_qdepth = default_qdepth;
+
+ if (fw_qdepth)
+ max_depth = min_t(int, max_depth, fw_qdepth);
+
+out_tag_check:
if (!sdev->tagged_supported)
max_depth = 1;
@@ -1629,26 +1706,21 @@ static int leapraid_calc_max_queue_depth(struct scsi_device *sdev, int qdepth)
return qdepth;
}
-static int leapraid_change_queue_depth(struct scsi_device *sdev, int qdepth)
+int leapraid_change_queue_depth(struct scsi_device *sdev, int qdepth)
{
qdepth = leapraid_calc_max_queue_depth(sdev, qdepth);
scsi_change_queue_depth(sdev, qdepth);
return sdev->queue_depth;
}
-void leapraid_adjust_sdev_queue_depth(struct scsi_device *sdev, int qdepth)
-{
- leapraid_change_queue_depth(sdev, qdepth);
-}
-
static int leapraid_bios_param(struct scsi_device *sdev,
struct block_device *bdev,
sector_t capacity, int geom[])
{
- int heads = 0;
- int sectors = 0;
+ int heads;
+ int sectors;
sector_t cylinders;
if (scsi_partsize(bdev, capacity, geom))
@@ -1692,12 +1764,24 @@ static ssize_t host_sas_address_show(struct device *cdev,
(unsigned long long)adapter->dev_topo.card.sas_address);
}
+static ssize_t board_name_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct leapraid_adapter *adapter = shost_priv(shost);
+
+ return scnprintf(buf, PAGE_SIZE, "%s\n",
+ adapter->adapter_attr.board_name);
+}
+
static DEVICE_ATTR_RO(fw_queue_depth);
static DEVICE_ATTR_RO(host_sas_address);
+static DEVICE_ATTR_RO(board_name);
static struct device_attribute *leapraid_shost_attrs[] = {
&dev_attr_fw_queue_depth,
&dev_attr_host_sas_address,
+ &dev_attr_board_name,
NULL,
};
@@ -1706,9 +1790,18 @@ static ssize_t sas_address_show(struct device *dev,
{
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,
+ "%s: Invalid sdev_priv or starget_priv\n", __func__);
+ return -EINVAL;
+ }
+
+ sas_address = sas_device_priv_data->starget_priv->sas_address;
return scnprintf(buf, PAGE_SIZE, "0x%016llx\n",
- (unsigned long long)sas_device_priv_data->starget_priv->sas_address);
+ (unsigned long long)sas_address);
}
static ssize_t sas_device_handle_show(struct device *dev,
@@ -1717,6 +1810,12 @@ static ssize_t sas_device_handle_show(struct device *dev,
struct scsi_device *sdev = to_scsi_device(dev);
struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata;
+ 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;
+ }
+
return scnprintf(buf, PAGE_SIZE, "0x%04x\n",
sas_device_priv_data->starget_priv->hdl);
}
@@ -1727,6 +1826,12 @@ static ssize_t sas_ncq_show(struct device *dev, struct device_attribute *attr,
struct scsi_device *sdev = to_scsi_device(dev);
struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data) {
+ dev_err(&sdev->sdev_gendev,
+ "%s: Invalid sdev_priv\n", __func__);
+ return -EINVAL;
+ }
+
return scnprintf(buf, PAGE_SIZE, "%d\n", sas_device_priv_data->ncq);
}
@@ -1737,21 +1842,34 @@ static ssize_t sas_ncq_store(struct device *dev,
struct scsi_device *sdev = to_scsi_device(dev);
struct leapraid_sdev_priv *sas_device_priv_data = sdev->hostdata;
unsigned char *vpd_pg89;
- int ncq_op = 0;
- bool ncq_supported = false;
+ int ncq_op;
+ bool ncq_supported;
+
+ if (!sas_device_priv_data) {
+ dev_err(&sdev->sdev_gendev,
+ "%s: Invalid sdev_priv\n", __func__);
+ return -EINVAL;
+ }
if (kstrtoint(buf, 0, &ncq_op))
- goto out;
+ 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);
+ return -EINVAL;
+ }
vpd_pg89 = kmalloc(LEAPRAID_VPD_PG89_MAX_LEN, GFP_KERNEL);
if (!vpd_pg89)
- goto out;
+ return -ENOMEM;
if (!scsi_device_supports_vpd(sdev) ||
scsi_get_vpd_page(sdev, LEAPRAID_VPD_PAGE_ATA_INFO,
vpd_pg89, LEAPRAID_VPD_PG89_MAX_LEN)) {
kfree(vpd_pg89);
- goto out;
+ return -EINVAL;
}
ncq_supported = (vpd_pg89[LEAPRAID_VPD_PG89_NCQ_BYTE_IDX] >>
@@ -1760,9 +1878,7 @@ static ssize_t sas_ncq_store(struct device *dev,
kfree(vpd_pg89);
if (ncq_supported)
sas_device_priv_data->ncq = ncq_op;
- return strlen(buf);
-out:
- return -EINVAL;
+ return count;
}
static DEVICE_ATTR_RO(sas_address);
@@ -1798,7 +1914,7 @@ static struct scsi_host_template leapraid_driver_template = {
.can_queue = LEAPRAID_CAN_QUEUE_MIN,
.this_id = LEAPRAID_THIS_ID_NONE,
.sg_tablesize = LEAPRAID_SG_DEPTH,
- .max_sectors = LEAPRAID_DEF_MAX_SECTORS,
+ .max_sectors = LEAPRAID_MAX_SECTORS,
.max_segment_size = LEAPRAID_MAX_SEGMENT_SIZE,
.cmd_per_lun = LEAPRAID_CMD_PER_LUN,
.shost_attrs = leapraid_shost_attrs,
@@ -1818,6 +1934,8 @@ static void leapraid_lock_init(struct leapraid_adapter *adapter)
spin_lock_init(&adapter->dev_topo.topo_node_lock);
spin_lock_init(&adapter->fw_evt_s.fw_evt_lock);
spin_lock_init(&adapter->dev_topo.raid_volume_lock);
+ spin_lock_init(&adapter->dev_topo.enc_lock);
+ spin_lock_init(&adapter->boot_devs.lock);
}
static void leapraid_list_init(struct leapraid_adapter *adapter)
@@ -1834,18 +1952,23 @@ static void leapraid_list_init(struct leapraid_adapter *adapter)
static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
- struct leapraid_adapter *adapter = NULL;
- struct Scsi_Host *shost = NULL;
+ struct leapraid_adapter *adapter;
+ struct Scsi_Host *shost;
int rc;
shost = scsi_host_alloc(&leapraid_driver_template,
sizeof(struct leapraid_adapter));
- if (!shost)
+ if (!shost) {
+ dev_err(&pdev->dev,
+ "%s: SCSI host alloc failed\n", __func__);
return -ENODEV;
+ }
adapter = shost_priv(shost);
memset(adapter, 0, sizeof(struct leapraid_adapter));
- adapter->adapter_attr.id = leapraid_ids++;
+
+ init_waitqueue_head(&adapter->access_ctrl.recovery_waitq);
+ adapter->adapter_attr.id = atomic_inc_return(&leapraid_ids) - 1;
adapter->adapter_attr.enable_mp = enable_mp;
@@ -1860,8 +1983,8 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
adapter->fw_log_desc.open_pcie_trace = open_pcie_trace;
leapraid_lock_init(adapter);
leapraid_list_init(adapter);
- sprintf(adapter->adapter_attr.name, "%s%d",
- LEAPRAID_DRIVER_NAME, adapter->adapter_attr.id);
+ snprintf(adapter->adapter_attr.name, LEAPRAID_NAME_LENGTH, "%s%d",
+ LEAPRAID_DRIVER_NAME, adapter->adapter_attr.id);
shost->max_cmd_len = LEAPRAID_MAX_CDB_LEN;
shost->max_lun = LEAPRAID_MAX_LUNS;
@@ -1875,12 +1998,17 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
adapter->fw_evt_s.fw_evt_thread =
alloc_ordered_workqueue(adapter->fw_evt_s.fw_evt_name, 0);
if (!adapter->fw_evt_s.fw_evt_thread) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to create fw event workqueue\n", __func__);
rc = -ENODEV;
goto evt_wq_fail;
}
- adapter->scan_dev_desc.driver_loading = true;
- if ((leapraid_ctrl_init(adapter))) {
+ init_waitqueue_head(&adapter->scan_dev_desc.wait_driver_loading);
+ adapter->scan_dev_desc.driver_loading = 1;
+ if (leapraid_ctrl_init(adapter)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Adapter init failed\n", __func__);
rc = -ENODEV;
goto ctrl_init_fail;
}
@@ -1888,9 +2016,8 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
rc = scsi_add_host(shost, &pdev->dev);
if (rc) {
- spin_lock(&leapraid_adapter_lock);
- list_del(&adapter->list);
- spin_unlock(&leapraid_adapter_lock);
+ dev_err(&pdev->dev,
+ "%s: SCSI host add failed\n", __func__);
goto scsi_add_shost_fail;
}
@@ -1900,6 +2027,7 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
scsi_add_shost_fail:
leapraid_remove_ctrl(adapter);
ctrl_init_fail:
+ leapraid_overheat_cleanup(adapter);
destroy_workqueue(adapter->fw_evt_s.fw_evt_thread);
evt_wq_fail:
spin_lock(&leapraid_adapter_lock);
@@ -1909,7 +2037,7 @@ static int leapraid_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return rc;
}
-static void leapraid_cleanup_lists(struct leapraid_adapter *adapter)
+void leapraid_cleanup_lists(struct leapraid_adapter *adapter)
{
struct leapraid_raid_volume *raid_volume, *next_raid_volume;
struct leapraid_starget_priv *starget_priv_data;
@@ -1921,12 +2049,14 @@ static void leapraid_cleanup_lists(struct leapraid_adapter *adapter)
&adapter->dev_topo.raid_volume_list, list) {
if (raid_volume->starget) {
starget_priv_data = raid_volume->starget->hostdata;
- starget_priv_data->deleted = true;
+ if (starget_priv_data)
+ starget_priv_data->deleted = 1;
scsi_remove_target(&raid_volume->starget->dev);
}
- pr_info("removing hdl=0x%04x, wwid=0x%016llx\n",
- raid_volume->hdl,
- (unsigned long long)raid_volume->wwid);
+ dev_info(&adapter->pdev->dev,
+ "removing hdl=0x%04x, wwid=0x%016llx\n",
+ raid_volume->hdl,
+ (unsigned long long)raid_volume->wwid);
leapraid_raid_volume_remove(adapter, raid_volume);
}
@@ -1935,16 +2065,18 @@ static void leapraid_cleanup_lists(struct leapraid_adapter *adapter)
port_list) {
if (leapraid_port->remote_identify.device_type ==
SAS_END_DEVICE)
- leapraid_sas_dev_remove_by_sas_address(adapter,
+ leapraid_sas_dev_remove_by_sas_address(
+ adapter,
leapraid_port->remote_identify.sas_address,
leapraid_port->card_port);
else if (leapraid_port->remote_identify.device_type ==
SAS_EDGE_EXPANDER_DEVICE ||
leapraid_port->remote_identify.device_type ==
SAS_FANOUT_EXPANDER_DEVICE)
- leapraid_exp_rm(adapter,
- leapraid_port->remote_identify.sas_address,
- leapraid_port->card_port);
+ leapraid_exp_rm(
+ adapter,
+ leapraid_port->remote_identify.sas_address,
+ leapraid_port->card_port);
}
list_for_each_entry_safe(port, port_next,
@@ -1969,27 +2101,26 @@ static void leapraid_cleanup_lists(struct leapraid_adapter *adapter)
static void leapraid_remove(struct pci_dev *pdev)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct workqueue_struct *wq;
unsigned long flags;
if (!shost || !adapter) {
- dev_err(&pdev->dev, "unable to remove!\n");
+ dev_err(&pdev->dev, "Unable to remove!\n");
return;
}
- while (adapter->scan_dev_desc.driver_loading)
- ssleep(1);
+ wait_event(adapter->scan_dev_desc.wait_driver_loading,
+ !adapter->scan_dev_desc.driver_loading);
+ wait_event(adapter->scan_dev_desc.wait_driver_loading,
+ !atomic_read(&adapter->overheat_desc.thermal_alert));
- while (adapter->access_ctrl.shost_recovering)
- ssleep(1);
-
- adapter->access_ctrl.host_removing = true;
+ adapter->access_ctrl.host_removing = 1;
+ wake_up(&adapter->access_ctrl.recovery_waitq);
leapraid_wait_cmds_done(adapter);
leapraid_smart_polling_stop(adapter);
- leapraid_free_internal_scsi_cmd(adapter);
if (leapraid_pci_removed(adapter)) {
leapraid_mq_polling_pause(adapter);
@@ -2004,7 +2135,6 @@ static void leapraid_remove(struct pci_dev *pdev)
if (wq)
destroy_workqueue(wq);
- leapraid_ir_shutdown(adapter);
sas_remove_host(shost);
leapraid_cleanup_lists(adapter);
leapraid_remove_ctrl(adapter);
@@ -2017,18 +2147,20 @@ static void leapraid_remove(struct pci_dev *pdev)
static void leapraid_shutdown(struct pci_dev *pdev)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct workqueue_struct *wq;
unsigned long flags;
if (!shost || !adapter) {
- dev_err(&pdev->dev, "unable to shutdown!\n");
+ dev_err(&pdev->dev, "Unable to shutdown!\n");
return;
}
- adapter->access_ctrl.host_removing = true;
+ 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);
leapraid_fw_log_stop(adapter);
spin_lock_irqsave(&adapter->fw_evt_s.fw_evt_lock, flags);
wq = adapter->fw_evt_s.fw_evt_thread;
@@ -2037,7 +2169,6 @@ static void leapraid_shutdown(struct pci_dev *pdev)
if (wq)
destroy_workqueue(wq);
- leapraid_ir_shutdown(adapter);
leapraid_disable_controller(adapter);
}
@@ -2045,29 +2176,31 @@ static pci_ers_result_t leapraid_pci_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
if (!shost || !adapter) {
- dev_err(&pdev->dev, "failed to error detected for device\n");
+ dev_err(&pdev->dev, "Failed to error detected for device\n");
return PCI_ERS_RESULT_DISCONNECT;
}
- pr_err("%s: pci error detected, state=%d\n",
- adapter->adapter_attr.name, state);
+ dev_err(&pdev->dev, "%s: PCI error detected, state=%d\n",
+ adapter->adapter_attr.name, state);
switch (state) {
case pci_channel_io_normal:
return PCI_ERS_RESULT_CAN_RECOVER;
case pci_channel_io_frozen:
- adapter->access_ctrl.pcie_recovering = true;
+ 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);
return PCI_ERS_RESULT_NEED_RESET;
case pci_channel_io_perm_failure:
- adapter->access_ctrl.pcie_recovering = true;
+ 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);
@@ -2082,15 +2215,15 @@ static pci_ers_result_t leapraid_pci_error_detected(struct pci_dev *pdev,
static pci_ers_result_t leapraid_pci_mmio_enabled(struct pci_dev *pdev)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
if (!shost || !adapter) {
dev_err(&pdev->dev,
- "failed to enable mmio for device\n");
+ "Failed to enable mmio for device\n");
return PCI_ERS_RESULT_DISCONNECT;
}
- dev_info(&pdev->dev, "%s: pci error mmio enabled\n",
+ dev_info(&pdev->dev, "%s: PCI error mmio enabled\n",
adapter->adapter_attr.name);
return PCI_ERS_RESULT_RECOVERED;
@@ -2099,43 +2232,47 @@ static pci_ers_result_t leapraid_pci_mmio_enabled(struct pci_dev *pdev)
static pci_ers_result_t leapraid_pci_slot_reset(struct pci_dev *pdev)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
int rc;
if (!shost || !adapter) {
dev_err(&pdev->dev,
- "failed to slot reset for device\n");
+ "Failed to slot reset for device\n");
return PCI_ERS_RESULT_DISCONNECT;
}
- dev_err(&pdev->dev, "%s pci error slot reset\n",
+ dev_err(&pdev->dev, "%s PCI error slot reset\n",
adapter->adapter_attr.name);
- adapter->access_ctrl.pcie_recovering = false;
+ adapter->access_ctrl.pcie_recovering = 0;
adapter->pdev = pdev;
pci_restore_state(pdev);
- if (leapraid_set_pcie_and_notification(adapter))
+ if (leapraid_set_pcie_and_notification(adapter)) {
+ dev_err(&pdev->dev,
+ "%s: Failed to set PCIe state and notification\n",
+ __func__);
return PCI_ERS_RESULT_DISCONNECT;
+ }
- dev_info(&pdev->dev, "%s: hard reset triggered by pci slot reset\n",
+ 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",
+ 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");
+ adapter->adapter_attr.name, rc == 0 ? "success" : "failed");
- return (rc == 0) ? PCI_ERS_RESULT_RECOVERED :
+ return rc == 0 ? PCI_ERS_RESULT_RECOVERED :
PCI_ERS_RESULT_DISCONNECT;
}
static void leapraid_pci_resume(struct pci_dev *pdev)
{
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
if (!shost || !adapter) {
- dev_err(&pdev->dev, "failed to resume\n");
+ dev_err(&pdev->dev, "Failed to resume\n");
return;
}
@@ -2159,24 +2296,24 @@ static struct pci_error_handlers leapraid_err_handler = {
static int leapraid_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
pci_power_t device_state;
if (!shost || !adapter) {
dev_err(&pdev->dev,
- "suspend failed, invalid host or adapter\n");
+ "Suspend failed, invalid host or adapter\n");
return -ENXIO;
}
+ leapraid_overheat_cleanup(adapter);
leapraid_smart_polling_stop(adapter);
leapraid_check_scheduled_fault_stop(adapter);
leapraid_fw_log_stop(adapter);
flush_scheduled_work();
scsi_block_requests(shost);
device_state = pci_choose_state(pdev, state);
- leapraid_ir_shutdown(adapter);
- dev_info(&pdev->dev, "entering PCI power state D%d, (slot=%s)\n",
+ dev_info(&pdev->dev, "Entering PCI power state D%d, (slot=%s)\n",
device_state, pci_name(pdev));
pci_save_state(pdev);
@@ -2188,18 +2325,18 @@ static int leapraid_suspend(struct pci_dev *pdev, pm_message_t state)
static int leapraid_resume(struct pci_dev *pdev)
{
struct leapraid_adapter *adapter = pdev_to_adapter(pdev);
- struct Scsi_Host *shost = pdev_to_shost(pdev);
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
pci_power_t device_state = pdev->current_state;
int rc;
if (!shost || !adapter) {
dev_err(&pdev->dev,
- "resume failed, invalid host or adapter\n");
+ "Resume failed, invalid host or adapter\n");
return -ENXIO;
}
dev_info(&pdev->dev,
- "resuming device %s, previous state D%d\n",
+ "Resuming device %s, previous state D%d\n",
pci_name(pdev), device_state);
pci_set_power_state(pdev, PCI_D0);
@@ -2207,12 +2344,22 @@ static int leapraid_resume(struct pci_dev *pdev)
pci_restore_state(pdev);
adapter->pdev = pdev;
rc = leapraid_set_pcie_and_notification(adapter);
- if (rc)
+ if (rc) {
+ dev_err(&pdev->dev,
+ "%s: Failed to set PCIe state and notification\n",
+ __func__);
return rc;
+ }
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
- leapraid_hard_reset_handler(adapter, PART_RESET);
+ rc = leapraid_hard_reset_handler(adapter, PART_RESET);
+ if (rc) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Hard reset failed during resume, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
scsi_unblock_requests(shost);
leapraid_check_scheduled_fault_start(adapter);
leapraid_fw_log_start(adapter);
@@ -2238,29 +2385,37 @@ static int __init leapraid_init(void)
{
int error;
- pr_info("%s version %s loaded\n", LEAPRAID_DRIVER_NAME,
- LEAPRAID_DRIVER_VERSION);
+ pr_info("%s initializing\n", LEAPRAID_DRIVER_NAME);
leapraid_transport_template =
sas_attach_transport(&leapraid_transport_functions);
- if (!leapraid_transport_template)
+ if (!leapraid_transport_template) {
+ pr_err("%s: Failed to attach SAS transport\n",
+ LEAPRAID_DRIVER_NAME);
return -ENODEV;
-
- leapraid_ids = 0;
-
- leapraid_ctl_init();
+ }
error = pci_register_driver(&leapraid_driver);
- if (error)
+ if (error) {
+ pr_err("%s: PCI driver registration failed: %d\n",
+ LEAPRAID_DRIVER_NAME, error);
+ sas_release_transport(leapraid_transport_template);
+ return error;
+ }
+
+ error = leapraid_ctl_init();
+ if (error) {
+ pci_unregister_driver(&leapraid_driver);
sas_release_transport(leapraid_transport_template);
+ return error;
+ }
- return error;
+ return 0;
}
static void __exit leapraid_exit(void)
{
- pr_info("leapraid version %s unloading\n",
- LEAPRAID_DRIVER_VERSION);
+ pr_info("%s exiting\n", LEAPRAID_DRIVER_NAME);
leapraid_ctl_exit();
pci_unregister_driver(&leapraid_driver);
diff --git a/drivers/scsi/leapraid/leapraid_transport.c b/drivers/scsi/leapraid/leapraid_transport.c
index d224449732a3..738bc55df416 100644
--- a/drivers/scsi/leapraid/leapraid_transport.c
+++ b/drivers/scsi/leapraid/leapraid_transport.c
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2025 LeapIO Tech Inc.
+ * Copyright (C) 2026 LeapIO Tech Inc.
*
- * LeapRAID Storage and RAID Controller driver.
+ * LeapRAID storage and RAID controller driver.
*/
-
#include <scsi/scsi_host.h>
#include "leapraid_func.h"
@@ -16,10 +15,8 @@ static struct leapraid_topo_node *leapraid_transport_topo_node_by_sas_addr(
{
if (adapter->dev_topo.card.sas_address == sas_addr)
return &adapter->dev_topo.card;
- else
- return leapraid_exp_find_by_sas_address(adapter,
- sas_addr,
- card_port);
+
+ return leapraid_exp_find_by_sas_address(adapter, sas_addr, card_port);
}
static u8 leapraid_get_port_id_by_expander(struct leapraid_adapter *adapter,
@@ -49,7 +46,8 @@ static u8 leapraid_get_port_id_by_end_dev(struct leapraid_adapter *adapter,
u8 port_id = 0xFF;
spin_lock_irqsave(&adapter->dev_topo.sas_dev_lock, flags);
- sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(adapter,
+ sas_dev = leapraid_hold_lock_get_sas_dev_by_addr_and_rphy(
+ adapter,
rphy->identify.sas_address,
rphy);
if (sas_dev) {
@@ -131,10 +129,9 @@ static enum sas_linkrate leapraid_transport_convert_phy_link_rate(u8 link_rate)
},
};
- for (i = 0; i < ARRAY_SIZE(linkrate_table); i++) {
+ for (i = 0; i < ARRAY_SIZE(linkrate_table); i++)
if (linkrate_table[i].in == link_rate)
return linkrate_table[i].out;
- }
return SAS_LINK_RATE_UNKNOWN;
}
@@ -192,7 +189,7 @@ static void leapraid_set_identify_protocol_flags(u32 dev_info,
};
for (i = 0; i < ARRAY_SIZE(mappings); i++)
- if ((dev_info & mappings[i].mask) && mappings[i].target)
+ if (dev_info & mappings[i].mask && mappings[i].target)
*mappings[i].target |= mappings[i].protocol;
}
@@ -207,13 +204,19 @@ static int leapraid_transport_set_identify(struct leapraid_adapter *adapter,
if ((adapter->access_ctrl.shost_recovering &&
!adapter->scan_dev_desc.driver_loading) ||
- adapter->access_ctrl.pcie_recovering)
+ adapter->access_ctrl.pcie_recovering) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed, shost_recovering=%d pcie_recovering=%d\n",
+ __func__,
+ adapter->access_ctrl.shost_recovering,
+ adapter->access_ctrl.pcie_recovering);
return -EFAULT;
+ }
cfgp1.form = LEAPRAID_SAS_DEV_CFG_PGAD_HDL;
cfgp2.handle = hdl;
- if ((leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1,
- cfgp2, GET_SAS_DEVICE_PG0)))
+ if (leapraid_op_config_page(adapter, &sas_dev_pg0, cfgp1,
+ cfgp2, GET_SAS_DEVICE_PG0))
return -ENXIO;
memset(identify, 0, sizeof(struct sas_identify));
@@ -248,27 +251,34 @@ static void leapraid_transport_exp_set_edev(struct leapraid_adapter *adapter,
struct leapraid_smp_passthrough_rep *smp_passthrough_rep;
struct leapraid_rep_manu_reply *rep_manu_reply;
u8 *component_id;
- ssize_t __maybe_unused ret;
smp_passthrough_rep =
- (void *)(&adapter->driver_cmds.transport_cmd.reply);
+ (void *)&adapter->driver_cmds.transport_cmd.reply;
if (le16_to_cpu(smp_passthrough_rep->resp_data_len) !=
sizeof(struct leapraid_rep_manu_reply))
return;
rep_manu_reply = data_out + sizeof(struct leapraid_rep_manu_request);
- ret = strscpy(edev->vendor_id, rep_manu_reply->vendor_identification,
- SAS_EXPANDER_VENDOR_ID_LEN);
- ret = strscpy(edev->product_id, rep_manu_reply->product_identification,
- SAS_EXPANDER_PRODUCT_ID_LEN);
- ret = strscpy(edev->product_rev,
- rep_manu_reply->product_revision_level,
- SAS_EXPANDER_PRODUCT_REV_LEN);
+
+ memcpy(edev->vendor_id, rep_manu_reply->vendor_identification,
+ SAS_EXPANDER_VENDOR_ID_LEN);
+ edev->vendor_id[SAS_EXPANDER_VENDOR_ID_LEN] = '\0';
+
+ memcpy(edev->product_id, rep_manu_reply->product_identification,
+ SAS_EXPANDER_PRODUCT_ID_LEN);
+ edev->product_id[SAS_EXPANDER_PRODUCT_ID_LEN] = '\0';
+
+ memcpy(edev->product_rev, rep_manu_reply->product_revision_level,
+ SAS_EXPANDER_PRODUCT_REV_LEN);
+ edev->product_rev[SAS_EXPANDER_PRODUCT_REV_LEN] = '\0';
+
edev->level = rep_manu_reply->sas_format & 1;
if (edev->level) {
- ret = strscpy(edev->component_vendor_id,
- rep_manu_reply->component_vendor_identification,
- SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
+ memcpy(edev->component_vendor_id,
+ rep_manu_reply->comp_vendor_identification,
+ SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
+ edev->component_vendor_id[
+ SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN] = '\0';
component_id = (u8 *)&rep_manu_reply->component_id;
edev->component_id = component_id[0] << 8 | component_id[1];
@@ -291,18 +301,24 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
size_t c2h_size;
size_t h2c_size;
void *psge;
- int rc = 0;
+ int rc;
if (adapter->access_ctrl.shost_recovering ||
adapter->access_ctrl.pcie_recovering) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed, shost_recovering=%d pcie_recovering=%d\n",
+ __func__,
+ adapter->access_ctrl.shost_recovering,
+ adapter->access_ctrl.pcie_recovering);
return -EFAULT;
}
mutex_lock(&adapter->driver_cmds.transport_cmd.mutex);
adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_PENDING;
- rc = leapraid_check_adapter_is_op(adapter);
+ rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
+ __func__);
if (rc)
- goto out;
+ goto out_cleanup;
h2c_size = sizeof(struct leapraid_rep_manu_request);
c2h_size = sizeof(struct leapraid_rep_manu_reply);
@@ -312,7 +328,7 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
GFP_ATOMIC);
if (!data_out) {
rc = -ENOMEM;
- goto out;
+ goto out_cleanup;
}
rep_manu_request = data_out;
@@ -323,8 +339,9 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
rep_manu_request->request_length = 0;
smp_passthrough_req =
- leapraid_get_task_desc(adapter,
- adapter->driver_cmds.transport_cmd.inter_taskid);
+ leapraid_get_task_desc(
+ adapter,
+ adapter->driver_cmds.transport_cmd.inter_taskid);
memset(smp_passthrough_req, 0,
sizeof(struct leapraid_smp_passthrough_req));
smp_passthrough_req->func = LEAPRAID_FUNC_SMP_PASSTHROUGH;
@@ -342,11 +359,13 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
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)) {
+ rc = -ETIMEDOUT;
dev_err(&adapter->pdev->dev,
- "%s: smp passthrough to exp timeout\n",
- __func__);
+ "%s: SMP passthrough timeout, st=0x%x\n",
+ __func__, adapter->driver_cmds.transport_cmd.status);
+ leapraid_log_req_context(adapter, smp_passthrough_req);
if (!(adapter->driver_cmds.transport_cmd.status &
- LEAPRAID_CMD_RESET))
+ LEAPRAID_CMD_RESET))
issue_reset = true;
goto hard_reset;
@@ -358,11 +377,11 @@ static int leapraid_transport_exp_report_manu(struct leapraid_adapter *adapter,
hard_reset:
if (issue_reset) {
- dev_info(&adapter->pdev->dev, "%s:%d call hard_reset\n",
+ dev_info(&adapter->pdev->dev, "%s:%d: call hard_reset\n",
__func__, __LINE__);
- leapraid_hard_reset_handler(adapter, FULL_RESET);
+ rc = leapraid_hard_reset_handler(adapter, FULL_RESET);
}
-out:
+out_cleanup:
adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_NOT_USED;
if (data_out)
dma_free_coherent(&adapter->pdev->dev, h2c_size + c2h_size,
@@ -376,13 +395,14 @@ static void leapraid_transport_del_port(struct leapraid_adapter *adapter,
struct leapraid_sas_port *sas_port)
{
dev_info(&sas_port->port->dev,
- "remove port: sas addr=0x%016llx\n",
+ "Remove port: SAS addr=0x%016llx\n",
(unsigned long long)sas_port->remote_identify.sas_address);
switch (sas_port->remote_identify.device_type) {
case SAS_END_DEVICE:
- leapraid_sas_dev_remove_by_sas_address(adapter,
- sas_port->remote_identify.sas_address,
- sas_port->card_port);
+ leapraid_sas_dev_remove_by_sas_address(
+ adapter,
+ sas_port->remote_identify.sas_address,
+ sas_port->card_port);
break;
case SAS_EDGE_EXPANDER_DEVICE:
case SAS_FANOUT_EXPANDER_DEVICE:
@@ -399,13 +419,13 @@ static void leapraid_transport_del_phy(struct leapraid_adapter *adapter,
struct leapraid_card_phy *card_phy)
{
dev_info(&card_phy->phy->dev,
- "remove phy: sas addr=0x%016llx, phy=%d\n",
+ "Remove PHY: SAS addr=0x%016llx, phy=%d\n",
(unsigned long long)sas_port->remote_identify.sas_address,
card_phy->phy_id);
list_del(&card_phy->port_siblings);
sas_port->phys_num--;
sas_port_delete_phy(sas_port->port, card_phy->phy);
- card_phy->phy_is_assigned = false;
+ card_phy->phy_is_assigned = 0;
}
static void leapraid_transport_add_phy(struct leapraid_adapter *adapter,
@@ -413,16 +433,17 @@ static void leapraid_transport_add_phy(struct leapraid_adapter *adapter,
struct leapraid_card_phy *card_phy)
{
dev_info(&card_phy->phy->dev,
- "add phy: sas addr=0x%016llx, phy=%d\n",
+ "Add PHY: SAS addr=0x%016llx, phy=%d\n",
(unsigned long long)sas_port->remote_identify.sas_address,
card_phy->phy_id);
list_add_tail(&card_phy->port_siblings, &sas_port->phy_list);
sas_port->phys_num++;
sas_port_add_phy(sas_port->port, card_phy->phy);
- card_phy->phy_is_assigned = true;
+ card_phy->phy_is_assigned = 1;
}
-void leapraid_transport_attach_phy_to_port(struct leapraid_adapter *adapter,
+void leapraid_transport_attach_phy_to_port(
+ struct leapraid_adapter *adapter,
struct leapraid_topo_node *topo_node,
struct leapraid_card_phy *card_phy,
u64 sas_address,
@@ -454,7 +475,8 @@ void leapraid_transport_attach_phy_to_port(struct leapraid_adapter *adapter,
}
}
-void leapraid_transport_detach_phy_to_port(struct leapraid_adapter *adapter,
+void leapraid_transport_detach_phy_to_port(
+ struct leapraid_adapter *adapter,
struct leapraid_topo_node *topo_node,
struct leapraid_card_phy *target_card_phy)
{
@@ -482,7 +504,8 @@ void leapraid_transport_detach_phy_to_port(struct leapraid_adapter *adapter,
}
}
-static void leapraid_detach_phy_from_old_port(struct leapraid_adapter *adapter,
+static void leapraid_detach_phy_from_old_port(
+ struct leapraid_adapter *adapter,
struct leapraid_topo_node *topo_node,
u64 sas_address,
struct leapraid_card_port *card_port)
@@ -495,9 +518,10 @@ static void leapraid_detach_phy_from_old_port(struct leapraid_adapter *adapter,
topo_node->card_phy[i].card_port != card_port)
continue;
if (topo_node->card_phy[i].phy_is_assigned)
- leapraid_transport_detach_phy_to_port(adapter,
- topo_node,
- &topo_node->card_phy[i]);
+ leapraid_transport_detach_phy_to_port(
+ adapter,
+ topo_node,
+ &topo_node->card_phy[i]);
}
}
@@ -512,8 +536,11 @@ static struct leapraid_sas_port *leapraid_prepare_sas_port(
unsigned long flags;
sas_port = kzalloc(sizeof(*sas_port), GFP_KERNEL);
- if (!sas_port)
+ if (!sas_port) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed alloc sas_port\n", __func__);
return NULL;
+ }
INIT_LIST_HEAD(&sas_port->port_list);
INIT_LIST_HEAD(&sas_port->phy_list);
@@ -526,27 +553,30 @@ static struct leapraid_sas_port *leapraid_prepare_sas_port(
if (!topo_node) {
dev_err(&adapter->pdev->dev,
- "%s: failed to find parent node for sas addr 0x%016llx!\n",
+ "%s: Failed to locate parent for SAS 0x%016llx!\n",
__func__, sas_address);
- kfree(sas_port);
- return NULL;
+ goto out_cleanup;
}
if (leapraid_transport_set_identify(adapter, handle,
- &sas_port->remote_identify)) {
- kfree(sas_port);
- return NULL;
- }
+ &sas_port->remote_identify))
+ goto out_cleanup;
if (sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
- kfree(sas_port);
- return NULL;
+ dev_warn(&adapter->pdev->dev,
+ "%s: Failed, device type is SAS_PHY_UNUSED\n",
+ __func__);
+ goto out_cleanup;
}
sas_port->card_port = card_port;
*out_topo_node = topo_node;
return sas_port;
+
+out_cleanup:
+ kfree(sas_port);
+ return NULL;
}
static int leapraid_bind_phys_and_vphy(struct leapraid_adapter *adapter,
@@ -576,12 +606,12 @@ static int leapraid_bind_phys_and_vphy(struct leapraid_adapter *adapter,
vphy = leapraid_get_vphy_by_phy(card_port, i);
if (!vphy)
- return -1;
+ return LEAPRAID_OPERATION_FAILED;
}
}
*out_vphy = vphy;
- return sas_port->phys_num ? 0 : -1;
+ return sas_port->phys_num ? 0 : LEAPRAID_OPERATION_FAILED;
}
static struct sas_rphy *leapraid_create_and_register_rphy(
@@ -596,26 +626,42 @@ static struct sas_rphy *leapraid_create_and_register_rphy(
struct sas_port *port;
struct sas_rphy *rphy;
- if (!topo_node->parent_dev)
- return NULL;
+ if (sas_port->remote_identify.device_type == SAS_END_DEVICE) {
+ sas_dev = leapraid_get_sas_dev_by_addr(
+ adapter,
+ sas_port->remote_identify.sas_address,
+ card_port);
+ if (!sas_dev)
+ return NULL;
+ sas_dev->pend_sas_rphy_add = 1;
+ }
+
+ if (!topo_node->parent_dev) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: topo_node parent device is NULL\n", __func__);
+ goto cleanup_sas_dev;
+ }
port = sas_port_alloc_num(topo_node->parent_dev);
- if (sas_port_add(port))
- return NULL;
+ if (!port) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to allocate SAS port\n", __func__);
+ goto cleanup_sas_dev;
+ }
+
+ if (sas_port_add(port)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to add SAS port\n", __func__);
+ goto out_delete_port;
+ }
list_for_each_entry(card_phy, &sas_port->phy_list, port_siblings) {
sas_port_add_phy(port, card_phy->phy);
- card_phy->phy_is_assigned = true;
+ card_phy->phy_is_assigned = 1;
card_phy->card_port = card_port;
}
- if (sas_port->remote_identify.device_type == SAS_END_DEVICE) {
- sas_dev = leapraid_get_sas_dev_by_addr(adapter,
- sas_port->remote_identify.sas_address,
- card_port);
- if (!sas_dev)
- return NULL;
- sas_dev->pend_sas_rphy_add = 1;
+ if (sas_dev) {
rphy = sas_end_device_alloc(port);
sas_dev->rphy = rphy;
@@ -625,28 +671,63 @@ static struct sas_rphy *leapraid_create_and_register_rphy(
else
vphy->sas_address = sas_dev->sas_addr;
}
-
} else {
- rphy = sas_expander_alloc(port,
- sas_port->remote_identify.device_type);
+ rphy = sas_expander_alloc(
+ port,
+ sas_port->remote_identify.device_type);
if (topo_node->hdl <= adapter->dev_topo.card.phys_num)
card_port->sas_address =
sas_port->remote_identify.sas_address;
}
+ if (!rphy) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to allocate RPHY\n", __func__);
+ goto cleanup_card_phy;
+ }
+
rphy->identify = sas_port->remote_identify;
- if (sas_rphy_add(rphy))
+ if (sas_rphy_add(rphy)) {
dev_err(&adapter->pdev->dev,
- "%s: failed to add rphy\n", __func__);
+ "%s: Failed to add RPHY\n", __func__);
+ if (sas_dev)
+ sas_dev->rphy = NULL;
+
+ sas_rphy_free(rphy);
+ goto cleanup_card_phy;
+ }
+ sas_port->port = port;
if (sas_dev) {
sas_dev->pend_sas_rphy_add = 0;
leapraid_sdev_put(sas_dev);
}
- sas_port->port = port;
return rphy;
+
+cleanup_card_phy:
+ if (topo_node->hdl <= adapter->dev_topo.card.phys_num) {
+ if (!vphy)
+ card_port->sas_address = 0;
+ else
+ vphy->sas_address = 0;
+ }
+
+ list_for_each_entry(card_phy, &sas_port->phy_list, port_siblings) {
+ card_phy->phy_is_assigned = 0;
+ card_phy->card_port = NULL;
+ }
+
+out_delete_port:
+ sas_port_delete(port);
+
+cleanup_sas_dev:
+ if (sas_dev) {
+ sas_dev->pend_sas_rphy_add = 0;
+ leapraid_sdev_put(sas_dev);
+ }
+ return NULL;
}
struct leapraid_sas_port *leapraid_transport_port_add(
@@ -656,35 +737,45 @@ struct leapraid_sas_port *leapraid_transport_port_add(
{
struct leapraid_card_phy *card_phy, *card_phy_next;
struct leapraid_topo_node *topo_node = NULL;
- struct leapraid_sas_port *sas_port = NULL;
+ struct leapraid_sas_port *sas_port;
struct leapraid_vphy *vphy = NULL;
- struct sas_rphy *rphy = NULL;
+ struct sas_rphy *rphy;
unsigned long flags;
- if (!card_port)
+ if (!card_port) {
+ dev_warn(&adapter->pdev->dev,
+ "%s: Invalid card_port\n", __func__);
return NULL;
+ }
sas_port = leapraid_prepare_sas_port(adapter, hdl, sas_address,
card_port, &topo_node);
if (!sas_port)
return NULL;
- leapraid_detach_phy_from_old_port(adapter,
- topo_node,
- sas_port->remote_identify.sas_address,
- card_port);
+ leapraid_detach_phy_from_old_port(
+ adapter,
+ topo_node,
+ sas_port->remote_identify.sas_address,
+ card_port);
if (leapraid_bind_phys_and_vphy(adapter, sas_port, topo_node,
- card_port, &vphy))
+ card_port, &vphy)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to bind phy to vphy\n", __func__);
goto out_fail;
+ }
rphy = leapraid_create_and_register_rphy(adapter, sas_port, topo_node,
card_port, vphy);
- if (!rphy)
+ if (!rphy) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed to create rphy\n", __func__);
goto out_fail;
+ }
dev_info(&rphy->dev,
- "%s: added dev: hdl=0x%04x, sas addr=0x%016llx\n",
+ "%s: Added dev: hdl=0x%04x, SAS addr=0x%016llx\n",
__func__, hdl,
(unsigned long long)sas_port->remote_identify.sas_address);
@@ -695,20 +786,27 @@ struct leapraid_sas_port *leapraid_transport_port_add(
spin_unlock_irqrestore(&adapter->dev_topo.topo_node_lock, flags);
if (sas_port->remote_identify.device_type ==
- LEAPRAID_DEVTYP_EDGE_EXPANDER ||
+ SAS_EDGE_EXPANDER_DEVICE ||
sas_port->remote_identify.device_type ==
- LEAPRAID_DEVTYP_FANOUT_EXPANDER)
- leapraid_transport_exp_report_manu(adapter,
- sas_port->remote_identify.sas_address,
- rphy_to_expander_device(rphy),
- card_port->port_id);
+ SAS_FANOUT_EXPANDER_DEVICE)
+ leapraid_transport_exp_report_manu(
+ adapter,
+ sas_port->remote_identify.sas_address,
+ rphy_to_expander_device(rphy),
+ card_port->port_id);
return sas_port;
out_fail:
list_for_each_entry_safe(card_phy, card_phy_next,
- &sas_port->phy_list, port_siblings)
- list_del(&card_phy->port_siblings);
+ &sas_port->phy_list, port_siblings) {
+ if (topo_node->hdl <= adapter->dev_topo.card.phys_num &&
+ !card_phy->vphy)
+ card_port->phy_mask &= ~BIT(card_phy->phy_id);
+
+ list_del_init(&card_phy->port_siblings);
+ }
+
kfree(sas_port);
return NULL;
}
@@ -750,10 +848,10 @@ static void leapraid_cleanup_card_port_and_vphys(
if (vphy->sas_address != sas_address)
continue;
- dev_info(&adapter->pdev->dev,
- "%s: remove vphy: %p from port: %p, port_id=%d\n",
- __func__, vphy, remove_card_port,
- remove_card_port->port_id);
+ dev_dbg(&adapter->pdev->dev,
+ "%s: Remove vphy=%p from port=%p port_id=%d\n",
+ __func__, vphy, remove_card_port,
+ remove_card_port->port_id);
remove_card_port->vphys_mask &= ~vphy->phy_mask;
list_del(&vphy->list);
@@ -762,11 +860,11 @@ static void leapraid_cleanup_card_port_and_vphys(
if (!remove_card_port->vphys_mask &&
!remove_card_port->sas_address) {
- dev_info(&adapter->pdev->dev,
- "%s: remove empty hba_port: %p, port_id=%d\n",
- __func__,
- remove_card_port,
- remove_card_port->port_id);
+ dev_dbg(&adapter->pdev->dev,
+ "%s: Remove empty hba_port: %p, port_id=%d\n",
+ __func__,
+ remove_card_port,
+ remove_card_port->port_id);
list_del(&remove_card_port->list);
kfree(remove_card_port);
remove_card_port = NULL;
@@ -782,15 +880,15 @@ static void leapraid_cleanup_card_port_and_vphys(
continue;
if (!remove_card_port->vphys_mask) {
- dev_info(&adapter->pdev->dev,
- "%s: remove hba_port: %p, port_id=%d\n",
- __func__, card_port, card_port->port_id);
+ dev_dbg(&adapter->pdev->dev,
+ "%s: Remove hba_port: %p, port_id=%d\n",
+ __func__, card_port, card_port->port_id);
list_del(&card_port->list);
kfree(card_port);
} else {
- dev_info(&adapter->pdev->dev,
- "%s: clear sas_address of hba_port: %p, port_id=%d\n",
- __func__, card_port, card_port->port_id);
+ dev_dbg(&adapter->pdev->dev,
+ "Clear sas_address of port=%p, port_id=%d\n",
+ card_port, card_port->port_id);
remove_card_port->sas_address = 0;
}
break;
@@ -802,22 +900,23 @@ static void leapraid_clear_topo_node_phys(struct leapraid_topo_node *topo_node,
{
int i;
- for (i = 0; i < topo_node->phys_num; i++) {
+ for (i = 0; i < topo_node->phys_num; i++)
if (topo_node->card_phy[i].remote_identify.sas_address ==
sas_address) {
memset(&topo_node->card_phy[i].remote_identify, 0,
sizeof(struct sas_identify));
- topo_node->card_phy[i].vphy = false;
+ topo_node->card_phy[i].vphy = 0;
}
- }
}
-void leapraid_transport_port_remove(struct leapraid_adapter *adapter,
- u64 sas_address, u64 sas_address_parent,
+void leapraid_transport_port_remove(
+ struct leapraid_adapter *adapter,
+ u64 sas_address,
+ u64 sas_address_parent,
struct leapraid_card_port *remove_card_port)
{
struct leapraid_card_phy *card_phy, *card_phy_next;
- struct leapraid_sas_port *sas_port = NULL;
+ struct leapraid_sas_port *sas_port;
struct leapraid_topo_node *topo_node;
unsigned long flags;
bool found = false;
@@ -855,7 +954,7 @@ void leapraid_transport_port_remove(struct leapraid_adapter *adapter,
list_for_each_entry_safe(card_phy, card_phy_next,
&sas_port->phy_list, port_siblings) {
- card_phy->phy_is_assigned = false;
+ card_phy->phy_is_assigned = 0;
if (!adapter->access_ctrl.host_removing)
sas_port_delete_phy(sas_port->port, card_phy->phy);
@@ -865,9 +964,9 @@ void leapraid_transport_port_remove(struct leapraid_adapter *adapter,
if (!adapter->access_ctrl.host_removing)
sas_port_delete(sas_port->port);
- dev_info(&adapter->pdev->dev,
- "%s: removed sas_port for sas addr=0x%016llx\n",
- __func__, (unsigned long long)sas_address);
+ dev_dbg(&adapter->pdev->dev,
+ "%s: Removed sas_port for SAS addr=0x%016llx\n",
+ __func__, (unsigned long long)sas_address);
kfree(sas_port);
}
@@ -902,9 +1001,11 @@ static void leapraid_init_sas_or_exp_phy(struct leapraid_adapter *adapter,
LEAPRAID_SAS_HWRATE_MIN_RATE_MASK);
phy->maximum_linkrate_hw = phy_pg0 ?
leapraid_transport_convert_phy_link_rate(
- phy_pg0->hw_link_rate >> 4) :
+ phy_pg0->hw_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) :
leapraid_transport_convert_phy_link_rate(
- exp_pg1->hw_link_rate >> 4);
+ exp_pg1->hw_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT);
phy->minimum_linkrate = phy_pg0 ?
leapraid_transport_convert_phy_link_rate(
phy_pg0->p_link_rate &
@@ -914,9 +1015,11 @@ static void leapraid_init_sas_or_exp_phy(struct leapraid_adapter *adapter,
LEAPRAID_SAS_PRATE_MIN_RATE_MASK);
phy->maximum_linkrate = phy_pg0 ?
leapraid_transport_convert_phy_link_rate(
- phy_pg0->p_link_rate >> 4) :
+ phy_pg0->p_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT) :
leapraid_transport_convert_phy_link_rate(
- exp_pg1->p_link_rate >> 4);
+ exp_pg1->p_link_rate >>
+ LEAPRAID_SAS_NEG_LINK_RATE_SHIFT);
phy->hostdata = card_phy->card_port;
}
@@ -926,30 +1029,33 @@ void leapraid_transport_add_card_phy(struct leapraid_adapter *adapter,
struct device *parent_dev)
{
struct sas_phy *phy;
+ int ret;
INIT_LIST_HEAD(&card_phy->port_siblings);
phy = sas_phy_alloc(parent_dev, card_phy->phy_id);
if (!phy) {
dev_err(&adapter->pdev->dev,
- "%s sas_phy_alloc failed!\n", __func__);
+ "%s: sas_phy_alloc failed!\n", __func__);
return;
}
- if ((leapraid_transport_set_identify(adapter, card_phy->hdl,
- &card_phy->identify))) {
+ if (leapraid_transport_set_identify(adapter, card_phy->hdl,
+ &card_phy->identify)) {
dev_err(&adapter->pdev->dev,
- "%s set phy handle identify failed!\n", __func__);
+ "%s: Set PHY handle identify failed!\n", __func__);
sas_phy_free(phy);
return;
}
card_phy->attached_hdl = le16_to_cpu(phy_pg0->attached_dev_hdl);
if (card_phy->attached_hdl) {
- if (leapraid_transport_set_identify(adapter,
- card_phy->attached_hdl,
- &card_phy->remote_identify)) {
+ ret = leapraid_transport_set_identify(
+ adapter,
+ card_phy->attached_hdl,
+ &card_phy->remote_identify);
+ if (ret) {
dev_err(&adapter->pdev->dev,
- "%s set phy attached handle identify failed!\n",
+ "%s: Set PHY attached hdl identify failed!\n",
__func__);
sas_phy_free(phy);
return;
@@ -958,7 +1064,9 @@ void leapraid_transport_add_card_phy(struct leapraid_adapter *adapter,
leapraid_init_sas_or_exp_phy(adapter, card_phy, phy, phy_pg0, NULL);
- if ((sas_phy_add(phy))) {
+ if (sas_phy_add(phy)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: SAS PHY add failed!\n", __func__);
sas_phy_free(phy);
return;
}
@@ -972,38 +1080,41 @@ int leapraid_transport_add_exp_phy(struct leapraid_adapter *adapter,
struct device *parent_dev)
{
struct sas_phy *phy;
+ int ret;
INIT_LIST_HEAD(&card_phy->port_siblings);
phy = sas_phy_alloc(parent_dev, card_phy->phy_id);
if (!phy) {
dev_err(&adapter->pdev->dev,
- "%s sas_phy_alloc failed!\n", __func__);
+ "%s: sas_phy_alloc failed!\n", __func__);
return -EFAULT;
}
- if ((leapraid_transport_set_identify(adapter, card_phy->hdl,
- &card_phy->identify))) {
+ if (leapraid_transport_set_identify(adapter, card_phy->hdl,
+ &card_phy->identify)) {
dev_err(&adapter->pdev->dev,
- "%s set phy hdl identify failed!\n", __func__);
+ "%s: Set PHY hdl identify failed!\n", __func__);
sas_phy_free(phy);
return -EFAULT;
}
card_phy->attached_hdl = le16_to_cpu(exp_pg1->attached_dev_hdl);
if (card_phy->attached_hdl) {
- if (leapraid_transport_set_identify(adapter,
- card_phy->attached_hdl,
- &card_phy->remote_identify)) {
- dev_err(&adapter->pdev->dev,
- "%s set phy attached hdl identify failed!\n",
- __func__);
- sas_phy_free(phy);
- }
+ ret = leapraid_transport_set_identify(
+ adapter,
+ card_phy->attached_hdl,
+ &card_phy->remote_identify);
+ if (ret)
+ dev_warn(&adapter->pdev->dev,
+ "%s: Set PHY attached hdl identify failed!\n",
+ __func__);
}
leapraid_init_sas_or_exp_phy(adapter, card_phy, phy, NULL, exp_pg1);
- if ((sas_phy_add(phy))) {
+ if (sas_phy_add(phy)) {
+ dev_err(&adapter->pdev->dev,
+ "%s: SAS PHY add failed!\n", __func__);
sas_phy_free(phy);
return -EFAULT;
}
@@ -1012,13 +1123,14 @@ int leapraid_transport_add_exp_phy(struct leapraid_adapter *adapter,
return 0;
}
-void leapraid_transport_update_links(struct leapraid_adapter *adapter,
+void leapraid_transport_update_links(
+ struct leapraid_adapter *adapter,
u64 sas_address, u16 hdl, u8 phy_index,
u8 link_rate, struct leapraid_card_port *target_card_port)
{
struct leapraid_topo_node *topo_node;
struct leapraid_card_phy *card_phy;
- struct leapraid_card_port *card_port = NULL;
+ struct leapraid_card_port *card_port;
unsigned long flags;
if (adapter->access_ctrl.shost_recovering ||
@@ -1053,10 +1165,12 @@ void leapraid_transport_update_links(struct leapraid_adapter *adapter,
BIT(card_phy->phy_id);
}
}
- leapraid_transport_attach_phy_to_port(adapter, topo_node,
- card_phy,
- card_phy->remote_identify.sas_address,
- target_card_port);
+ leapraid_transport_attach_phy_to_port(
+ adapter,
+ topo_node,
+ card_phy,
+ card_phy->remote_identify.sas_address,
+ target_card_port);
} else {
memset(&card_phy->remote_identify, 0,
sizeof(struct sas_identify));
@@ -1079,8 +1193,12 @@ static int leapraid_dma_map_buffer(struct device *dev, struct bsg_buffer *buf,
*dma_len = buf->payload_len;
} else {
- if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL))
+ if (!dma_map_sg(dev, buf->sg_list, 1, DMA_BIDIRECTIONAL)) {
+ dev_err(dev,
+ "%s: Failed to map sg buffer for dma\n",
+ __func__);
return -ENOMEM;
+ }
*dma_addr = sg_dma_address(buf->sg_list);
*dma_len = sg_dma_len(buf->sg_list);
@@ -1106,11 +1224,11 @@ static void leapraid_build_smp_task(struct leapraid_adapter *adapter,
dma_addr_t c2h_dma_addr, size_t c2h_size)
{
struct leapraid_smp_passthrough_req *smp_passthrough_req;
+ u16 inter_taskid;
void *psge;
- 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(*smp_passthrough_req));
smp_passthrough_req->func = LEAPRAID_FUNC_SMP_PASSTHROUGH;
@@ -1130,30 +1248,36 @@ static void leapraid_build_smp_task(struct leapraid_adapter *adapter,
static int leapraid_send_smp_req(struct leapraid_adapter *adapter)
{
- dev_info(&adapter->pdev->dev,
- "%s: sending smp request\n", __func__);
+ const struct leapraid_smp_passthrough_req *smp_passthrough_req;
+
+ 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);
init_completion(&adapter->driver_cmds.transport_cmd.done);
leapraid_fire_task(adapter,
adapter->driver_cmds.transport_cmd.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\n", __func__);
+ 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);
if (!(adapter->driver_cmds.transport_cmd.status &
LEAPRAID_CMD_RESET)) {
- dev_info(&adapter->pdev->dev,
- "%s:%d call hard_reset\n",
- __func__, __LINE__);
+ dev_dbg(&adapter->pdev->dev,
+ "%s:%d: call hard_reset\n",
+ __func__, __LINE__);
leapraid_hard_reset_handler(adapter, FULL_RESET);
return -ETIMEDOUT;
}
}
- dev_info(&adapter->pdev->dev, "%s: smp request complete\n", __func__);
+ dev_dbg(&adapter->pdev->dev, "%s: SMP request complete\n", __func__);
if (!(adapter->driver_cmds.transport_cmd.status &
LEAPRAID_CMD_REPLY_VALID)) {
dev_err(&adapter->pdev->dev,
- "%s: smp request no reply\n", __func__);
+ "%s: SMP request no reply\n", __func__);
return -ENXIO;
}
@@ -1167,10 +1291,10 @@ static void leapraid_handle_smp_rep(struct leapraid_adapter *adapter,
struct leapraid_smp_passthrough_rep *smp_passthrough_rep;
smp_passthrough_rep =
- (void *)(&adapter->driver_cmds.transport_cmd.reply);
+ (void *)&adapter->driver_cmds.transport_cmd.reply;
- dev_info(&adapter->pdev->dev, "%s: response data len=%d\n",
- __func__, le16_to_cpu(smp_passthrough_rep->resp_data_len));
+ dev_dbg(&adapter->pdev->dev, "%s: Response data len=%d\n",
+ __func__, le16_to_cpu(smp_passthrough_rep->resp_data_len));
memcpy(job->reply, smp_passthrough_rep, sizeof(*smp_passthrough_rep));
job->reply_len = sizeof(*smp_passthrough_rep);
@@ -1198,13 +1322,19 @@ static void leapraid_transport_smp_handler(struct bsg_job *job,
if (adapter->access_ctrl.shost_recovering ||
adapter->access_ctrl.pcie_recovering) {
+ dev_err(&adapter->pdev->dev,
+ "%s: Failed, shost_recovering=%d pcie_recovering=%d\n",
+ __func__,
+ adapter->access_ctrl.shost_recovering,
+ adapter->access_ctrl.pcie_recovering);
rc = -EFAULT;
- goto done;
+ goto exit_bsg_job;
}
- rc = mutex_lock_interruptible(&adapter->driver_cmds.transport_cmd.mutex);
+ rc = mutex_lock_interruptible(&adapter->driver_cmds
+ .transport_cmd.mutex);
if (rc)
- goto done;
+ goto exit_bsg_job;
adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_PENDING;
rc = leapraid_dma_map_buffer(&adapter->pdev->dev,
@@ -1223,7 +1353,8 @@ static void leapraid_transport_smp_handler(struct bsg_job *job,
if (rc)
goto free_req_buf;
- rc = leapraid_check_adapter_is_op(adapter);
+ rc = leapraid_check_adapter_is_op(adapter, LEAPRAID_DB_WAIT_OP_SHORT,
+ __func__);
if (rc)
goto free_rep_buf;
@@ -1245,7 +1376,7 @@ static void leapraid_transport_smp_handler(struct bsg_job *job,
release_lock:
adapter->driver_cmds.transport_cmd.status = LEAPRAID_CMD_NOT_USED;
mutex_unlock(&adapter->driver_cmds.transport_cmd.mutex);
-done:
+exit_bsg_job:
bsg_job_done(job, rc, reslen);
}
--
2.25.1
2
1
[PATCH OLK-6.6] lib/crypto: chacha: Zeroize permuted_state before it leaves scope
by Yi Yang 26 May '26
by Yi Yang 26 May '26
26 May '26
From: Eric Biggers <ebiggers(a)kernel.org>
stable inclusion
from stable-v6.6.135
commit 066c760acead1fb743bae294dbd89f479ae43b9b
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/14894
CVE: CVE-2026-43336
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit e5046823f8fa3677341b541a25af2fcb99a5b1e0 upstream.
Since the ChaCha permutation is invertible, the local variable
'permuted_state' is sufficient to compute the original 'state', and thus
the key, even after the permutation has been done.
While the kernel is quite inconsistent about zeroizing secrets on the
stack (and some prominent userspace crypto libraries don't bother at all
since it's not guaranteed to work anyway), the kernel does try to do it
as a best practice, especially in cases involving the RNG.
Thus, explicitly zeroize 'permuted_state' before it goes out of scope.
Fixes: c08d0e647305 ("crypto: chacha20 - Add a generic ChaCha20 stream cipher implementation")
Cc: stable(a)vger.kernel.org
Acked-by: Ard Biesheuvel <ardb(a)kernel.org>
Link: https://lore.kernel.org/r/20260326032920.39408-1-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers(a)kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Yi Yang <yiyang13(a)huawei.com>
---
lib/crypto/chacha.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/crypto/chacha.c b/lib/crypto/chacha.c
index b748fd3d256e..1bff9f283777 100644
--- a/lib/crypto/chacha.c
+++ b/lib/crypto/chacha.c
@@ -86,6 +86,8 @@ void chacha_block_generic(u32 *state, u8 *stream, int nrounds)
put_unaligned_le32(x[i] + state[i], &stream[i * sizeof(u32)]);
state[12]++;
+
+ memzero_explicit(x, sizeof(x));
}
EXPORT_SYMBOL(chacha_block_generic);
@@ -110,5 +112,7 @@ void hchacha_block_generic(const u32 *state, u32 *stream, int nrounds)
memcpy(&stream[0], &x[0], 16);
memcpy(&stream[4], &x[12], 16);
+
+ memzero_explicit(x, sizeof(x));
}
EXPORT_SYMBOL(hchacha_block_generic);
--
2.25.1
2
1
[PATCH OLK-5.10] lib/crypto: chacha: Zeroize permuted_state before it leaves scope
by Yi Yang 26 May '26
by Yi Yang 26 May '26
26 May '26
From: Eric Biggers <ebiggers(a)kernel.org>
stable inclusion
from stable-v5.10.253
commit e90ee961af515a484f091678ce58a4c3f7b73b02
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/14894
CVE: CVE-2026-43336
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit e5046823f8fa3677341b541a25af2fcb99a5b1e0 upstream.
Since the ChaCha permutation is invertible, the local variable
'permuted_state' is sufficient to compute the original 'state', and thus
the key, even after the permutation has been done.
While the kernel is quite inconsistent about zeroizing secrets on the
stack (and some prominent userspace crypto libraries don't bother at all
since it's not guaranteed to work anyway), the kernel does try to do it
as a best practice, especially in cases involving the RNG.
Thus, explicitly zeroize 'permuted_state' before it goes out of scope.
Fixes: c08d0e647305 ("crypto: chacha20 - Add a generic ChaCha20 stream cipher implementation")
Cc: stable(a)vger.kernel.org
Acked-by: Ard Biesheuvel <ardb(a)kernel.org>
Link: https://lore.kernel.org/r/20260326032920.39408-1-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers(a)kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Yi Yang <yiyang13(a)huawei.com>
---
lib/crypto/chacha.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/crypto/chacha.c b/lib/crypto/chacha.c
index b748fd3d256e..1bff9f283777 100644
--- a/lib/crypto/chacha.c
+++ b/lib/crypto/chacha.c
@@ -86,6 +86,8 @@ void chacha_block_generic(u32 *state, u8 *stream, int nrounds)
put_unaligned_le32(x[i] + state[i], &stream[i * sizeof(u32)]);
state[12]++;
+
+ memzero_explicit(x, sizeof(x));
}
EXPORT_SYMBOL(chacha_block_generic);
@@ -110,5 +112,7 @@ void hchacha_block_generic(const u32 *state, u32 *stream, int nrounds)
memcpy(&stream[0], &x[0], 16);
memcpy(&stream[4], &x[12], 16);
+
+ memzero_explicit(x, sizeof(x));
}
EXPORT_SYMBOL(hchacha_block_generic);
--
2.25.1
2
1
yt6801 inclusion
category: bugfix
bugzilla: https://atomgit.com/openeuler/kernel/issues/7229
--------------------------------------------------------------------
fix the link info is not update on os installation.
Fixes: 6460d9d3c42d ("yt6801: Add Motorcomm yt6801 PCIe driver")
Signed-off-by: Frank_Sae <Frank.Sae(a)motor-comm.com>
---
drivers/net/ethernet/motorcomm/yt6801/yt6801_main.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/net/ethernet/motorcomm/yt6801/yt6801_main.c b/drivers/net/ethernet/motorcomm/yt6801/yt6801_main.c
index 01eed3ace3c6..4f2f82293125 100644
--- a/drivers/net/ethernet/motorcomm/yt6801/yt6801_main.c
+++ b/drivers/net/ethernet/motorcomm/yt6801/yt6801_main.c
@@ -27,6 +27,18 @@
const struct net_device_ops *fxgmac_get_netdev_ops(void);
static void fxgmac_napi_enable(struct fxgmac_pdata *priv);
+const struct ethtool_ops *fxgmac_get_ethtool_ops(void);
+
+static const struct ethtool_ops fxgmac_ethtool_ops = {
+ .get_link = ethtool_op_get_link,
+ .get_link_ksettings = phy_ethtool_get_link_ksettings,
+ .set_link_ksettings = phy_ethtool_set_link_ksettings
+};
+
+const struct ethtool_ops *fxgmac_get_ethtool_ops(void)
+{
+ return &fxgmac_ethtool_ops;
+}
#define PHY_WR_CONFIG(reg_offset) (0x8000205 + ((reg_offset) * 0x10000))
static int fxgmac_phy_write_reg(struct fxgmac_pdata *priv, u32 reg_id, u32 data)
@@ -1899,6 +1911,7 @@ static int fxgmac_init(struct fxgmac_pdata *priv, bool save_private_reg)
FXGMAC_JUMBO_PACKET_MTU + (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
ndev->netdev_ops = fxgmac_get_netdev_ops();/* Set device operations */
+ ndev->ethtool_ops = fxgmac_get_ethtool_ops();/* Set device operations */
/* Set device features */
if (priv->hw_feat.tso) {
--
2.34.1
2
1