Commit b8992029 authored by Suganath Prabu's avatar Suganath Prabu Committed by Martin K. Petersen

scsi: mpt3sas: Add separate function for aero doorbell reads

Sometimes Aero controllers appears to be returning bad data (0) for
doorbell register read and if retries are performed immediately after the
bad read, they return good data.

Workaround is added to retry read from doorbell registers for maximum three
times if driver get the zero.  Added functions base_readl_aero for Aero IOC
and base_readl for gen35 and other controllers.
Signed-off-by: default avatarSuganath Prabu <suganath-prabu.subramani@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent cc68e607
...@@ -156,6 +156,32 @@ _scsih_set_fwfault_debug(const char *val, const struct kernel_param *kp) ...@@ -156,6 +156,32 @@ _scsih_set_fwfault_debug(const char *val, const struct kernel_param *kp)
module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug,
param_get_int, &mpt3sas_fwfault_debug, 0644); param_get_int, &mpt3sas_fwfault_debug, 0644);
/**
* _base_readl_aero - retry readl for max three times.
* @addr - MPT Fusion system interface register address
*
* Retry the readl() for max three times if it gets zero value
* while reading the system interface register.
*/
static inline u32
_base_readl_aero(const volatile void __iomem *addr)
{
u32 i = 0, ret_val;
do {
ret_val = readl(addr);
i++;
} while (ret_val == 0 && i < 3);
return ret_val;
}
static inline u32
_base_readl(const volatile void __iomem *addr)
{
return readl(addr);
}
/** /**
* _base_clone_reply_to_sys_mem - copies reply to reply free iomem * _base_clone_reply_to_sys_mem - copies reply to reply free iomem
* in BAR0 space. * in BAR0 space.
...@@ -6398,6 +6424,10 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) ...@@ -6398,6 +6424,10 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
ioc->rdpq_array_enable_assigned = 0; ioc->rdpq_array_enable_assigned = 0;
ioc->dma_mask = 0; ioc->dma_mask = 0;
if (ioc->is_aero_ioc)
ioc->base_readl = &_base_readl_aero;
else
ioc->base_readl = &_base_readl;
r = mpt3sas_base_map_resources(ioc); r = mpt3sas_base_map_resources(ioc);
if (r) if (r)
goto out_free_resources; goto out_free_resources;
......
...@@ -912,6 +912,7 @@ typedef void (*NVME_BUILD_PRP)(struct MPT3SAS_ADAPTER *ioc, u16 smid, ...@@ -912,6 +912,7 @@ typedef void (*NVME_BUILD_PRP)(struct MPT3SAS_ADAPTER *ioc, u16 smid,
typedef void (*PUT_SMID_IO_FP_HIP) (struct MPT3SAS_ADAPTER *ioc, u16 smid, typedef void (*PUT_SMID_IO_FP_HIP) (struct MPT3SAS_ADAPTER *ioc, u16 smid,
u16 funcdep); u16 funcdep);
typedef void (*PUT_SMID_DEFAULT) (struct MPT3SAS_ADAPTER *ioc, u16 smid); typedef void (*PUT_SMID_DEFAULT) (struct MPT3SAS_ADAPTER *ioc, u16 smid);
typedef u32 (*BASE_READ_REG) (const volatile void __iomem *addr);
/* IOC Facts and Port Facts converted from little endian to cpu */ /* IOC Facts and Port Facts converted from little endian to cpu */
union mpi3_version_union { union mpi3_version_union {
...@@ -1392,6 +1393,7 @@ struct MPT3SAS_ADAPTER { ...@@ -1392,6 +1393,7 @@ struct MPT3SAS_ADAPTER {
u8 hide_drives; u8 hide_drives;
spinlock_t diag_trigger_lock; spinlock_t diag_trigger_lock;
u8 diag_trigger_active; u8 diag_trigger_active;
BASE_READ_REG base_readl;
struct SL_WH_MASTER_TRIGGER_T diag_trigger_master; struct SL_WH_MASTER_TRIGGER_T diag_trigger_master;
struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event; struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event;
struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi; struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment