[PATCH 4/4] mpt3sas: Update driver version to 27.101.00.00.

2018-12-06 Thread Suganath Prabu
Update driver version from 27.100.00.00 to 27.101.00.00.

Signed-off-by: Suganath Prabu 
---
 drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 3a294b9..8003519 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -75,9 +75,9 @@
 #define MPT3SAS_DRIVER_NAME"mpt3sas"
 #define MPT3SAS_AUTHOR "Avago Technologies "
 #define MPT3SAS_DESCRIPTION"LSI MPT Fusion SAS 3.0 Device Driver"
-#define MPT3SAS_DRIVER_VERSION "27.100.00.00"
+#define MPT3SAS_DRIVER_VERSION "27.101.00.00"
 #define MPT3SAS_MAJOR_VERSION  27
-#define MPT3SAS_MINOR_VERSION  100
+#define MPT3SAS_MINOR_VERSION  101
 #define MPT3SAS_BUILD_VERSION  0
 #define MPT3SAS_RELEASE_VERSION00
 
-- 
1.8.3.1



[PATCH 3/4] mpt3sas: Replace readl with ioc->base_readl.

2018-12-06 Thread Suganath Prabu
Use ioc->base_readl to restrict the readl retries to only
Aero controllers.

Signed-off-by: Suganath Prabu 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 39 +++--
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index d371c8e..8a0851e 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -742,7 +742,7 @@ mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc)
 
dump_stack();
 
-   doorbell = readl(>chip->Doorbell);
+   doorbell = ioc->base_readl(>chip->Doorbell);
if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
mpt3sas_base_fault_info(ioc , doorbell);
else {
@@ -1351,10 +1351,10 @@ _base_mask_interrupts(struct MPT3SAS_ADAPTER *ioc)
u32 him_register;
 
ioc->mask_interrupts = 1;
-   him_register = readl(>chip->HostInterruptMask);
+   him_register = ioc->base_readl(>chip->HostInterruptMask);
him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK;
writel(him_register, >chip->HostInterruptMask);
-   readl(>chip->HostInterruptMask);
+   ioc->base_readl(>chip->HostInterruptMask);
 }
 
 /**
@@ -1368,7 +1368,7 @@ _base_unmask_interrupts(struct MPT3SAS_ADAPTER *ioc)
 {
u32 him_register;
 
-   him_register = readl(>chip->HostInterruptMask);
+   him_register = ioc->base_readl(>chip->HostInterruptMask);
him_register &= ~MPI2_HIM_RIM;
writel(him_register, >chip->HostInterruptMask);
ioc->mask_interrupts = 0;
@@ -4880,7 +4880,7 @@ mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, 
int cooked)
 {
u32 s, sc;
 
-   s = readl(>chip->Doorbell);
+   s = ioc->base_readl(>chip->Doorbell);
sc = s & MPI2_IOC_STATE_MASK;
return cooked ? sc : s;
 }
@@ -4936,7 +4936,7 @@ _base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, 
int timeout)
count = 0;
cntdn = 1000 * timeout;
do {
-   int_status = readl(>chip->HostInterruptStatus);
+   int_status = ioc->base_readl(>chip->HostInterruptStatus);
if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
dhsprintk(ioc,
  ioc_info(ioc, "%s: successful count(%d), 
timeout(%d)\n",
@@ -4962,7 +4962,7 @@ _base_spin_on_doorbell_int(struct MPT3SAS_ADAPTER *ioc, 
int timeout)
count = 0;
cntdn = 2000 * timeout;
do {
-   int_status = readl(>chip->HostInterruptStatus);
+   int_status = ioc->base_readl(>chip->HostInterruptStatus);
if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
dhsprintk(ioc,
  ioc_info(ioc, "%s: successful count(%d), 
timeout(%d)\n",
@@ -5000,14 +5000,14 @@ _base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER 
*ioc, int timeout)
count = 0;
cntdn = 1000 * timeout;
do {
-   int_status = readl(>chip->HostInterruptStatus);
+   int_status = ioc->base_readl(>chip->HostInterruptStatus);
if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
dhsprintk(ioc,
  ioc_info(ioc, "%s: successful count(%d), 
timeout(%d)\n",
   __func__, count, timeout));
return 0;
} else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
-   doorbell = readl(>chip->Doorbell);
+   doorbell = ioc->base_readl(>chip->Doorbell);
if ((doorbell & MPI2_IOC_STATE_MASK) ==
MPI2_IOC_STATE_FAULT) {
mpt3sas_base_fault_info(ioc , doorbell);
@@ -5042,7 +5042,7 @@ _base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER 
*ioc, int timeout)
count = 0;
cntdn = 1000 * timeout;
do {
-   doorbell_reg = readl(>chip->Doorbell);
+   doorbell_reg = ioc->base_readl(>chip->Doorbell);
if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
dhsprintk(ioc,
  ioc_info(ioc, "%s: successful count(%d), 
timeout(%d)\n",
@@ -5157,13 +5157,13 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER 
*ioc, int request_bytes,
__le32 *mfp;
 
/* make sure doorbell is not in use */
-   if ((readl(>chip->Doorbell) & MPI2_DOORBELL_USED)) {
+   if ((ioc->base_readl(>chip->Doorbell) & MPI2_DOORBELL_USED)) {
ioc_err(ioc, "doorbell is in use (line=%d)\n&qu

[PATCH 1/4] mpt3sas: Introduce flag for aero based controllers.

2018-12-06 Thread Suganath Prabu
Adding flag "is_aero_ioc" to differentiate aero based controllers
from other gen35 controllers.

Signed-off-by: Suganath Prabu 
---
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  1 +
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 14 --
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 4b8b602..f200929 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1399,6 +1399,7 @@ struct MPT3SAS_ADAPTER {
void*device_remove_in_progress;
u16 device_remove_in_progress_sz;
u8  is_gen35_ioc;
+   u8  is_aero_ioc;
PUT_SMID_IO_FP_HIP put_smid_scsi_io;
 
 };
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 5b9806d..039dee4 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -10366,10 +10366,6 @@ _scsih_probe(struct pci_dev *pdev, const struct 
pci_device_id *id)
ioc->id = mpt3_ids++;
sprintf(ioc->driver_name, "%s", MPT3SAS_DRIVER_NAME);
switch (pdev->device) {
-   case MPI26_MFGPAGE_DEVID_CFG_SEC_3816:
-   case MPI26_MFGPAGE_DEVID_CFG_SEC_3916:
-   dev_info(>dev,
-   "HBA is in Configurable Secure mode\n");
case MPI26_MFGPAGE_DEVID_SAS3508:
case MPI26_MFGPAGE_DEVID_SAS3508_1:
case MPI26_MFGPAGE_DEVID_SAS3408:
@@ -10377,12 +10373,18 @@ _scsih_probe(struct pci_dev *pdev, const struct 
pci_device_id *id)
case MPI26_MFGPAGE_DEVID_SAS3516_1:
case MPI26_MFGPAGE_DEVID_SAS3416:
case MPI26_MFGPAGE_DEVID_SAS3616:
+   ioc->is_gen35_ioc = 1;
+   break;
+   case MPI26_MFGPAGE_DEVID_CFG_SEC_3816:
+   case MPI26_MFGPAGE_DEVID_CFG_SEC_3916:
+   dev_info(>dev,
+   "HBA is in Configurable Secure mode\n");
case MPI26_MFGPAGE_DEVID_HARD_SEC_3816:
case MPI26_MFGPAGE_DEVID_HARD_SEC_3916:
-   ioc->is_gen35_ioc = 1;
+   ioc->is_aero_ioc = ioc->is_gen35_ioc = 1;
break;
default:
-   ioc->is_gen35_ioc = 0;
+   ioc->is_gen35_ioc = ioc->is_aero_ioc = 0;
}
if ((ioc->hba_mpi_version_belonged == MPI25_VERSION &&
pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION) ||
-- 
1.8.3.1



[PATCH 2/4] mpt3sas: Add separate function for aero doorbell reads.

2018-12-06 Thread Suganath Prabu
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: Suganath Prabu 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 30 ++
 drivers/scsi/mpt3sas/mpt3sas_base.h |  2 ++
 2 files changed, 32 insertions(+)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 9254b52..d371c8e 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -157,6 +157,32 @@ module_param_call(mpt3sas_fwfault_debug, 
_scsih_set_fwfault_debug,
param_get_int, _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
  *   in BAR0 space.
  *
@@ -6398,6 +6424,10 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
 
ioc->rdpq_array_enable_assigned = 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);
if (r)
goto out_free_resources;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index f200929..3a294b9 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -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,
u16 funcdep);
 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 */
 union mpi3_version_union {
@@ -1392,6 +1393,7 @@ struct MPT3SAS_ADAPTER {
u8  hide_drives;
spinlock_t  diag_trigger_lock;
u8  diag_trigger_active;
+   BASE_READ_REG   base_readl;
struct SL_WH_MASTER_TRIGGER_T diag_trigger_master;
struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event;
struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi;
-- 
1.8.3.1



[PATCH 0/4] mpt3sas: Fix hardware bug in aero controllers.

2018-12-06 Thread Suganath Prabu
Problem statement:
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.

Fix:
In below four patches added workaround to retry read operation from
controller doorbell registers for maximum three times, if read
returns zero.

Suganath Prabu (4):
  mpt3sas: Introduce flag for aero based controllers.
  mpt3sas: Add separate function for aero doorbell reads.
  mpt3sas: Replace readl with ioc->base_readl.
  mpt3sas: Update driver version to 27.101.00.00.

 drivers/scsi/mpt3sas/mpt3sas_base.c  | 69 ++--
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  7 ++--
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 14 
 3 files changed, 63 insertions(+), 27 deletions(-)

-- 
1.8.3.1



Re: [PATCH v4 3/6] mpt3sas: Introdude _scsih_get_shost_and_ioc.

2018-10-01 Thread Suganath Prabu Subramani
On Thu, Sep 27, 2018 at 2:39 AM Bjorn Helgaas  wrote:
>
> On Wed, Sep 26, 2018 at 09:52:36AM +0530, Suganath Prabu S wrote:
> > The code for getting shost and IOC is redundant so
> > moved that to function "scsih_get_shost_and_ioc".
> > Also checks for NULL are added to IOC and shost.
> >
> > Signed-off-by: Suganath Prabu S 
> > ---
> >  drivers/scsi/mpt3sas/mpt3sas_scsih.c | 98 
> > ++--
> >  1 file changed, 82 insertions(+), 16 deletions(-)
> >
> > diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
> > b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
> > index 566a550..f6e92eb 100644
> > --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
> > +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
> > @@ -9809,6 +9809,35 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
> >  }
> >
> >  /**
> > + * _scsih_get_shost_and_ioc - get shost and ioc
> > + *   and verify whether they are NULL or not
> > + * @pdev: PCI device struct
> > + * @shost: address of scsi host pointer
> > + * @ioc: address of HBA adapter pointer
> > + *
> > + * Return zero if *shost and *ioc are not NULL otherwise return error 
> > number.
> > + */
> > +static int
> > +_scsih_get_shost_and_ioc(struct pci_dev *pdev,
> > + struct Scsi_Host **shost, struct MPT3SAS_ADAPTER **ioc)
> > +{
> > + *shost = pci_get_drvdata(pdev);
> > + if (*shost == NULL) {
> > + dev_err(>dev, "pdev's driver data is null\n");
> > + return -ENXIO;
> > + }
> > +
> > + *ioc = shost_priv(*shost);
> > + if (*ioc == NULL) {
> > + dev_err(>dev, "shost's private data is null\n");
> > + return -ENXIO;
>
> I think it's better to omit NULL pointer checks like these because
> there should not be a path where we can execute this code when these
> pointers are NULL.
>
> If there *is* such a path, I think that's a serious bug and it's
> better to oops when we try to dereference the NULL pointer.  If we
> just return an error code, it's likely the bug will be ignored and
> never fixed.
>
We have added the ioc and shost checks, because of kernel panic in
below scenario.
Have 3 HBA's in system and perform below operation.
1) Run “poweroff”.
2) Immediate hot unplug HBA.
We have observed, kernel's shutdown process has removed all the 3 HBA
devices smoothly,
and also user have unplugged the HBA device during this time. PCI
subsystem's hot-plug thread is also trying to remove
the hot plugged PCI device which is already removed/cleaned by the
shutdown process. (Which is not expected for the
already removed device) Due to this kernel panic is observed. And we
are not sure whether it
has to fixed from pciehp layer, so we added sanity checks in driver.

[ 1745.605510] BUG: unable to handle kernel NULL pointer dereference
at 0a98
[ 1745.606554] IP: [] scsih_remove+0x20/0x2d0 [mpt3sas]
[ 1745.607609] PGD 0
[ 1745.608621] Oops:  [#1] SMP
[ 1745.622989] CPU: 0 PID: 668 Comm: kworker/0:2 Tainted: G
O4.4.55-1.el7.elrepo.x86_64 #1
[ 1745.624800] Hardware name: PRO-MNU65930231
PRO-NME69559126/BRD-PRO55212588, BIOS 0.51e 05/08/2017
[ 1745.626673] Workqueue: pciehp-3 pciehp_power_thread
[ 1745.628566] task: 881fe50dd880 ti: 881fe88e4000 task.ti:
881fe88e4000
[ 1745.630530] RIP: 0010:[]  []
scsih_remove+0x20/0x2d0 [mpt3sas]
[ 1745.632577] RSP: 0018:881fe88e7c98  EFLAGS: 00010292
[ 1745.634639] RAX: 0001 RBX: 881feef5c000 RCX: 
[ 1745.636718] RDX:  RSI: 0202 RDI: 881feef5c000
[ 1745.638832] RBP: 881fe88e7cc8 R08:  R09: 000180220002
[ 1745.640972] R10: eaf4a401 R11: ea007fabd280 R12: 
[ 1745.643136] R13: a0576020 R14: 881fe9af8240 R15: 
[ 1745.645320] FS:  () GS:881ffde0()
knlGS:
[ 1745.647572] CS:  0010 DS:  ES:  CR0: 80050033
[ 1745.649833] CR2: 0a98 CR3: 001fe76df000 CR4: 003406f0
[ 1745.652147] DR0:  DR1:  DR2: 
[ 1745.654476] DR3:  DR6: fffe0ff0 DR7: 0400
[ 1745.656825] Stack:
[ 1745.659138]  881fe88e7cc8 881feef5c098 881feef5c000
a0576020
[ 1745.661562]  881fe9af8240  881fe88e7cf0
8137f9d9
[ 1745.663990]  881feef5c098 a0576088 881feef5c000
881fe88e7d10
[ 1745.666428] Call Trace:
[ 1745.668830]  [] pci_device_remove+0x39/0xc0
[ 1745.671256]  [] __device_release_driver+0x96/0x130
[ 1745.673664]  [] device_release_driver+0x23/0x30
[ 1745.676071]  [] pci_stop_bus_device+0x8c/0

Re: [PATCH v4 2/6] mpt3sas: Separate out mpt3sas_wait_for_ioc_to_operational

2018-09-27 Thread Suganath Prabu Subramani
Hi Bjorn,

Thanks for reviewing.

On Thu, Sep 27, 2018 at 2:33 AM Bjorn Helgaas  wrote:
>
> On Wed, Sep 26, 2018 at 09:52:35AM +0530, Suganath Prabu S wrote:
> > Introduce mpt3sas_wait_for_ioc_to_operational.
> >
> > This section of code "wait for IOC to be operational"
> > is used in many places across the driver,
> > and hence moved this section of code in to the function
> > "mpt3sas_wait_for_ioc_to_operational".
> >
> > Also added HBA hot unplug checks, and this returns with
> > error code EFAULT, if it detects HBA is hot unplugged
> > or IOC is not in operational state.
>
> This should be two patches:
>
>   1) Factor out the "wait for IOC" code.  This should not cause any
>  functional changes (I didn't verify in your code, but this is the
>  objective).
>
>   2) Add the hot unplug checks.
>
> This makes the patches much easier to review.
> Will move hot unplug check to separate patch.
> > V2 change set:
> > used pci_device_is_present instead of
> > mpt3sas_base_pci_device_is_unplugged
> >
> > v4 Change set:
> > Dont split strings in print statement
>
> I don't know the convention in drivers/scsi, but in driver/pci, I
> remove this sort of v2/v3 commentary from the changelog because it's
> really not of interest after the patch is merged.  It's nice to have
> it in the email, but I think if you put it after a line containing
> only "--" it will be in the email but not the changelog.
>Thanks, Will add change sets after --
> > Signed-off-by: Suganath Prabu S 
> > ---
> >  drivers/scsi/mpt3sas/mpt3sas_base.c  | 92 
> > +++-
> >  drivers/scsi/mpt3sas/mpt3sas_base.h  |  4 ++
> >  drivers/scsi/mpt3sas/mpt3sas_config.c| 28 +++---
> >  drivers/scsi/mpt3sas/mpt3sas_ctl.c   | 26 ++---
> >  drivers/scsi/mpt3sas/mpt3sas_transport.c | 75 +-
> >  5 files changed, 81 insertions(+), 144 deletions(-)
> >
> > diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
> > b/drivers/scsi/mpt3sas/mpt3sas_base.c
> > index c880e72..9f1d8fb 100644
> > --- a/drivers/scsi/mpt3sas/mpt3sas_base.c
> > +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
> > @@ -5176,6 +5176,53 @@ _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 
> > reset_type, int timeout)
> >  }
> >
> >  /**
> > + * mpt3sas_wait_for_ioc_to_operational - IOC's operational
> > + *   state and HBA hot unplug status are checked here.
> > + * @ioc: per adapter object
> > + * @wait_count: timeout in seconds
>
> "wait_count" is really a timeout and maybe should be named "timeout".
>Yes, wait_count is timeout, will rename wait_count to timeout
> > + * Return:  Returns EFAULT, if HBA is hot unplugged or IOC is
> > + * not in operational state, within the wait_count.
> > + * And returns 0, If not hot unplugged Or ioc is in
> > + * operational state.
>
> I think you mean something like:
>
>   Waits up to wait_count seconds for the IOC to become operational.
>   Returns 0 if IOC is present and operational; otherwise returns
>   -EFAULT.
> Yes.
> > + */
> > +
> > +int
> > +mpt3sas_wait_for_ioc_to_operational(struct MPT3SAS_ADAPTER *ioc,
> > + int wait_count)


[PATCH v4 1/6] mpt3sas: Introduce mpt3sas_base_pci_device_is_available

2018-09-25 Thread Suganath Prabu S
* Driver uses "pci_device_is_present" to check whether
If Hot unplugged:
the outstanding IOs with 'DID_NO_CONNECT' before removing the drives
attached to the HBA.
"DID_NO_CONNECT" status and free the smid, if driver detects that
HBA is hot unplugged.

* In the hard reset flush out all the outstanding IOs even if diag reset
fails and also if driver detects that HBA is hot unplugged.

v1 change set:
==
unlock mutex before goto "out_unlocked",
if active reset is in progress.

v2 change set:
==
1) Use pci_device_is_present instead of
mpt3sas_base_pci_device_is_unplugged.
2) As suggested by Lukas, removed using
watchdog thread for checking hba hot unplug(Patch 02 of V1).
Added Hot unplug checks in scan finish and reset paths.

v3 Change Set:
=
Simplified function "mpt3sas_base_pci_device_is_available" and
made inline.

v4 Changes:
===
Dont split strings in print statement.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 39 
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  3 ++-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 50 
 3 files changed, 86 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 59d7844..c880e72 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -543,6 +543,20 @@ static int mpt3sas_remove_dead_ioc_func(void *arg)
 }
 
 /**
+ * mpt3sas_base_pci_device_is_available - check whether pci device is
+ * available for any transactions with FW
+ *
+ * @ioc: per adapter object
+ *
+ * Return 1 if pci device state is up and running else return 0.
+ */
+inline bool
+mpt3sas_base_pci_device_is_available(struct MPT3SAS_ADAPTER *ioc)
+{
+   return !ioc->pci_error_recovery && pci_device_is_present(ioc->pdev);
+}
+
+/**
  * _base_fault_reset_work - workq handling ioc fault conditions
  * @work: input argument, used to derive ioc
  *
@@ -6122,6 +6136,11 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc)
 
count = 0;
do {
+   if (!pci_device_is_present(ioc->pdev)) {
+   ioc->remove_host = 1;
+   pr_err(MPT3SAS_FMT "Hba Hot unplugged\n", ioc->name);
+   goto out;
+   }
/* Write magic sequence to WriteSequence register
 * Loop until in diagnostic mode
 */
@@ -6853,6 +6872,13 @@ mpt3sas_wait_for_commands_to_complete(struct 
MPT3SAS_ADAPTER *ioc)
 
ioc->pending_io_count = 0;
 
+   if (!mpt3sas_base_pci_device_is_available(ioc)) {
+   pr_err(MPT3SAS_FMT
+   "%s: pci error recovery reset or pci device unplug 
occurred\n",
+   ioc->name, __func__);
+   return;
+   }
+
ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
return;
@@ -6899,6 +6925,19 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER 
*ioc,
/* wait for an active reset in progress to complete */
mutex_lock(>reset_in_progress_mutex);
 
+   if (!mpt3sas_base_pci_device_is_available(ioc)) {
+   pr_err(MPT3SAS_FMT
+   "%s: pci error recovery reset or pci device unplug 
occurred\n",
+   ioc->name, __func__);
+   if (!pci_device_is_present(ioc->pdev))
+   ioc->schedule_dead_ioc_flush_running_cmds(ioc);
+   r = 0;
+   mutex_unlock(>reset_in_progress_mutex);
+   goto out_unlocked;
+   }
+
+   mpt3sas_halt_firmware(ioc);
+
spin_lock_irqsave(>ioc_reset_in_progress_lock, flags);
ioc->shost_recovery = 1;
spin_unlock_irqrestore(>ioc_reset_in_progress_lock, flags);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 96dc15e..a802ad4 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1474,7 +1474,8 @@ void mpt3sas_base_update_missing_delay(struct 
MPT3SAS_ADAPTER *ioc,
u16 device_missing_delay, u8 io_missing_delay);
 
 int mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc);
-
+inline bool  mpt3sas_base_pci_device_is_available(
+   struct MPT3SAS_ADAPTER *ioc);
 void
 mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc);
 
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 53133cf..566a550 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2846,9 +2846,19 @@ scsih_abort(struct scsi_cmnd *scmd)
"attempting task abort! scmd(%p)\n", scmd);
_scsih_tm_display_info(ioc, scmd);
 

[PATCH v4 2/6] mpt3sas: Separate out mpt3sas_wait_for_ioc_to_operational

2018-09-25 Thread Suganath Prabu S
Introduce mpt3sas_wait_for_ioc_to_operational.

This section of code "wait for IOC to be operational"
is used in many places across the driver,
and hence moved this section of code in to the function
"mpt3sas_wait_for_ioc_to_operational".

Also added HBA hot unplug checks, and this returns with
error code EFAULT, if it detects HBA is hot unplugged
or IOC is not in operational state.

V2 change set:
used pci_device_is_present instead of
mpt3sas_base_pci_device_is_unplugged

v4 Change set:
Dont split strings in print statement

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 92 +++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  4 ++
 drivers/scsi/mpt3sas/mpt3sas_config.c| 28 +++---
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   | 26 ++---
 drivers/scsi/mpt3sas/mpt3sas_transport.c | 75 +-
 5 files changed, 81 insertions(+), 144 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index c880e72..9f1d8fb 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -5176,6 +5176,53 @@ _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 
reset_type, int timeout)
 }
 
 /**
+ * mpt3sas_wait_for_ioc_to_operational - IOC's operational
+ * state and HBA hot unplug status are checked here.
+ * @ioc: per adapter object
+ * @wait_count: timeout in seconds
+ *
+ * Return:  Returns EFAULT, if HBA is hot unplugged or IOC is
+ * not in operational state, within the wait_count.
+ * And returns 0, If not hot unplugged Or ioc is in
+ * operational state.
+ */
+
+int
+mpt3sas_wait_for_ioc_to_operational(struct MPT3SAS_ADAPTER *ioc,
+   int wait_count)
+{
+   int wait_state_count = 0;
+   u32 ioc_state;
+
+   if (!pci_device_is_present(ioc->pdev))
+   return -EFAULT;
+
+   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+   while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+
+   if (!pci_device_is_present(ioc->pdev))
+   return -EFAULT;
+
+   if (wait_state_count++ == wait_count) {
+   pr_err(MPT3SAS_FMT
+   "%s: failed due to ioc not operational\n",
+   ioc->name, __func__);
+   return -EFAULT;
+   }
+   ssleep(1);
+   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+   pr_info(MPT3SAS_FMT
+   "%s: waiting for operational state(count=%d)\n",
+ioc->name, __func__, wait_state_count);
+   }
+   if (wait_state_count)
+   pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
+   ioc->name, __func__);
+
+   return 0;
+}
+
+/**
  * _base_handshake_req_reply_wait - send request thru doorbell interface
  * @ioc: per adapter object
  * @request_bytes: request length
@@ -5316,11 +5363,9 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER 
*ioc,
Mpi2SasIoUnitControlRequest_t *mpi_request)
 {
u16 smid;
-   u32 ioc_state;
u8 issue_reset = 0;
int rc;
void *request;
-   u16 wait_state_count;
 
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
@@ -5334,22 +5379,10 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER 
*ioc,
goto out;
}
 
-   wait_state_count = 0;
-   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
-   while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-   if (wait_state_count++ == 10) {
-   pr_err(MPT3SAS_FMT
-   "%s: failed due to ioc not operational\n",
-   ioc->name, __func__);
-   rc = -EFAULT;
-   goto out;
-   }
-   ssleep(1);
-   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
-   pr_info(MPT3SAS_FMT
-   "%s: waiting for operational state(count=%d)\n",
-   ioc->name, __func__, wait_state_count);
-   }
+   rc = mpt3sas_wait_for_ioc_to_operational(ioc,
+   IOC_OPERATIONAL_WAIT_COUNT);
+   if (rc)
+   goto out;
 
smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
if (!smid) {
@@ -5416,11 +5449,9 @@ mpt3sas_base_scsi_enclosure_processor(struct 
MPT3SAS_ADAPTER *ioc,
Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request)
 {
u16 smid;
-   u32 ioc_state;
u8 issue_reset = 0;
int rc;
void *request;
-   u16 wait_state_count;
 
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
@@ -5434,23 +5465,10 @@ mpt3sas_base_scsi_enclosure_proce

[PATCH v4 0/6] mpt3sas: Hot-Plug Surprise removal support on IOC.

2018-09-25 Thread Suganath Prabu S
Posting below set of patches to support PCIe Hot Plug surprise removal,
and few defect fixes.

This is NOT the normal PCIe Hot Plug support, whereby the user informs the
OS that a hot removal is desired, the OS does an orderly shutdown of the
driver on the device, special hot plug circuitry removes power from the
PCIe slot, then the user can remove the device and replace it
(where orderly bring-up of the device is done).

With a true surprise removal (just removing HBA from a slot)
there is a possibility to get all kinds of PCIe transaction errors,
Below patches addresses those issues and remove HBA without bringing
the system down.

For surprise removal detection, driver does a PCI
read of IOC's vendor field in IOC's PCI configuration space.
If the read value is 0x this indicates that the device
might have hot removed and the device will be removed from driver.

V1 changes:
In Patch 0001 - unlock mutex, if active reset is in progress.

V2 changes:
Replaced mpt3sas_base_pci_device_is_unplugged with
pci_device_is_present.

V3 Change Set:
Simplified function "mpt3sas_base_pci_device_is_available" and
made inline

V4 Change set:
Reframe split strings in print statement, to avoid
warning from checkpatch.pl.

Suganath Prabu S (6):
  mpt3sas: Introduce  mpt3sas_base_pci_device_is_available
  mpt3sas: Separate out  mpt3sas_wait_for_ioc_to_operational
  mpt3sas: Introdude  _scsih_get_shost_and_ioc.
  mpt3sas: Fix Sync cache command failure during driver  unload.
  mpt3sas: Fix driver modifying NVRAM/persistent data.
  mpt3sas: Bump driver version to 27.100.00.00.

 drivers/scsi/mpt3sas/mpt3sas_base.c  | 133 +++---
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  11 +-
 drivers/scsi/mpt3sas/mpt3sas_config.c|  32 +-
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  26 +
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 189 +++
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  82 +++---
 6 files changed, 296 insertions(+), 177 deletions(-)

-- 
1.8.3.1



[PATCH v4 6/6] mpt3sas: Bump driver version to 27.100.00.00.

2018-09-25 Thread Suganath Prabu S
Modify driver version to 27.100.00.00
(which is equivalent to PH8 OOB driver)

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index f0351a2..b880d79 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -74,8 +74,8 @@
 #define MPT3SAS_DRIVER_NAME"mpt3sas"
 #define MPT3SAS_AUTHOR "Avago Technologies "
 #define MPT3SAS_DESCRIPTION"LSI MPT Fusion SAS 3.0 Device Driver"
-#define MPT3SAS_DRIVER_VERSION "26.100.00.00"
-#define MPT3SAS_MAJOR_VERSION  26
+#define MPT3SAS_DRIVER_VERSION "27.100.00.00"
+#define MPT3SAS_MAJOR_VERSION  27
 #define MPT3SAS_MINOR_VERSION  100
 #define MPT3SAS_BUILD_VERSION  0
 #define MPT3SAS_RELEASE_VERSION00
-- 
1.8.3.1



[PATCH v4 5/6] mpt3sas: Fix driver modifying NVRAM/persistent data.

2018-09-25 Thread Suganath Prabu S
* If EEDPTagMode field in manufacturing page11 is set,
unset it. This is needed to fix a hardware bug
in SAS3/SAS2 cards, So, skipping EEDPTagMode changes
in Manufacturing page11 for SAS35 controllers.

* Fix driver modifying NVRAM/persistent data in
Manufacturing page11 along with current copy. Driver should
change only current copy of Manufacturing page11

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c   | 2 +-
 drivers/scsi/mpt3sas/mpt3sas_config.c | 4 
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 9f1d8fb..a43579e 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -4122,7 +4122,7 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
 * flag unset in NVDATA.
 */
mpt3sas_config_get_manufacturing_pg11(ioc, _reply, >manu_pg11);
-   if (ioc->manu_pg11.EEDPTagMode == 0) {
+   if ((!ioc->is_gen35_ioc) && (ioc->manu_pg11.EEDPTagMode == 0)) {
pr_err("%s: overriding NVDATA EEDPTagMode setting\n",
ioc->name);
ioc->manu_pg11.EEDPTagMode &= ~0x3;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c 
b/drivers/scsi/mpt3sas/mpt3sas_config.c
index 5713a2d..f2a326a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_config.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -676,10 +676,6 @@ mpt3sas_config_set_manufacturing_pg11(struct 
MPT3SAS_ADAPTER *ioc,
r = _config_request(ioc, _request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
sizeof(*config_page));
-   mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
-   r = _config_request(ioc, _request, mpi_reply,
-   MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-   sizeof(*config_page));
  out:
return r;
 }
-- 
1.8.3.1



[PATCH v4 4/6] mpt3sas: Fix Sync cache command failure during driver unload.

2018-09-25 Thread Suganath Prabu S
This is to fix Sync cache and start stop command
 failures with DID_NO_CONNECT during driver unload.

1) Release drives first from SML, then remove internally
in driver.
2) And allow sync cache and Start stop commands to firmware,
even when remove_host flag is set

v2 Changeset:
Replaced this function mpt3sas_base_pci_device_is_unplugged
with pci_device_is_present

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 41 ++--
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  7 --
 2 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index f6e92eb..5d15d06 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -3806,6 +3806,43 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 
smid, u8 msix_index,
return _scsih_check_for_pending_tm(ioc, smid);
 }
 
+/** _scsih_allow_scmd_to_device - check whether scmd needs to
+ *  issue to IOC or not.
+ * @ioc: per adapter object
+ * @scmd: pointer to scsi command object
+ *
+ * Returns true if scmd can be issued to IOC otherwise returns false.
+ */
+inline bool _scsih_allow_scmd_to_device(struct MPT3SAS_ADAPTER *ioc,
+   struct scsi_cmnd *scmd)
+{
+
+   if (ioc->pci_error_recovery)
+   return false;
+
+   if (ioc->hba_mpi_version_belonged == MPI2_VERSION) {
+   if (ioc->remove_host)
+   return false;
+
+   return true;
+   }
+
+
+   if (ioc->remove_host) {
+   if (!pci_device_is_present(ioc->pdev))
+   return false;
+
+   switch (scmd->cmnd[0]) {
+   case SYNCHRONIZE_CACHE:
+   case START_STOP:
+   return true;
+   default:
+   return false;
+   }
+   }
+
+   return true;
+}
 
 /**
  * _scsih_sas_control_complete - completion routine
@@ -4640,7 +4677,7 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd 
*scmd)
return 0;
}
 
-   if (ioc->pci_error_recovery || ioc->remove_host) {
+   if (!(_scsih_allow_scmd_to_device(ioc, scmd))) {
scmd->result = DID_NO_CONNECT << 16;
scmd->scsi_done(scmd);
return 0;
@@ -9874,6 +9911,7 @@ static void scsih_remove(struct pci_dev *pdev)
 
/* release all the volumes */
_scsih_ir_shutdown(ioc);
+   sas_remove_host(shost);
list_for_each_entry_safe(raid_device, next, >raid_device_list,
list) {
if (raid_device->starget) {
@@ -9916,7 +9954,6 @@ static void scsih_remove(struct pci_dev *pdev)
ioc->sas_hba.num_phys = 0;
}
 
-   sas_remove_host(shost);
mpt3sas_base_detach(ioc);
spin_lock(_lock);
list_del(>list);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c 
b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index b10d73e..742da74 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -817,10 +817,13 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER 
*ioc, u64 sas_address,
mpt3sas_port->remote_identify.sas_address,
mpt3sas_phy->phy_id);
mpt3sas_phy->phy_belongs_to_port = 0;
-   sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
+   if (!ioc->remove_host)
+   sas_port_delete_phy(mpt3sas_port->port,
+   mpt3sas_phy->phy);
list_del(_phy->port_siblings);
}
-   sas_port_delete(mpt3sas_port->port);
+   if (!ioc->remove_host)
+   sas_port_delete(mpt3sas_port->port);
kfree(mpt3sas_port);
 }
 
-- 
1.8.3.1



[PATCH v4 3/6] mpt3sas: Introdude _scsih_get_shost_and_ioc.

2018-09-25 Thread Suganath Prabu S
The code for getting shost and IOC is redundant so
moved that to function "scsih_get_shost_and_ioc".
Also checks for NULL are added to IOC and shost.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 98 ++--
 1 file changed, 82 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 566a550..f6e92eb 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -9809,6 +9809,35 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
 }
 
 /**
+ * _scsih_get_shost_and_ioc - get shost and ioc
+ * and verify whether they are NULL or not
+ * @pdev: PCI device struct
+ * @shost: address of scsi host pointer
+ * @ioc: address of HBA adapter pointer
+ *
+ * Return zero if *shost and *ioc are not NULL otherwise return error number.
+ */
+static int
+_scsih_get_shost_and_ioc(struct pci_dev *pdev,
+   struct Scsi_Host **shost, struct MPT3SAS_ADAPTER **ioc)
+{
+   *shost = pci_get_drvdata(pdev);
+   if (*shost == NULL) {
+   dev_err(>dev, "pdev's driver data is null\n");
+   return -ENXIO;
+   }
+
+   *ioc = shost_priv(*shost);
+   if (*ioc == NULL) {
+   dev_err(>dev, "shost's private data is null\n");
+   return -ENXIO;
+   }
+
+   return 0;
+}
+
+
+/**
  * scsih_remove - detach and remove add host
  * @pdev: PCI device struct
  *
@@ -9816,8 +9845,8 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
  */
 static void scsih_remove(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
struct _sas_port *mpt3sas_port, *next_port;
struct _raid_device *raid_device, *next;
struct MPT3SAS_TARGET *sas_target_priv_data;
@@ -9825,6 +9854,10 @@ static void scsih_remove(struct pci_dev *pdev)
struct workqueue_struct *wq;
unsigned long flags;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "unable to remove device\n");
+   return;
+   }
ioc->remove_host = 1;
 
mpt3sas_wait_for_commands_to_complete(ioc);
@@ -9898,11 +9931,16 @@ static void scsih_remove(struct pci_dev *pdev)
 static void
 scsih_shutdown(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
struct workqueue_struct *wq;
unsigned long flags;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "unable to shutdown device\n");
+   return;
+   }
+
ioc->remove_host = 1;
 
mpt3sas_wait_for_commands_to_complete(ioc);
@@ -10727,10 +10765,16 @@ out_add_shost_fail:
 static int
 scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
pci_power_t device_state;
+   int rc;
 
+   rc = _scsih_get_shost_and_ioc(pdev, , );
+   if (rc) {
+   dev_err(>dev, "unable to suspend device\n");
+   return rc;
+   }
mpt3sas_base_stop_watchdog(ioc);
flush_scheduled_work();
scsi_block_requests(shost);
@@ -10754,11 +10798,17 @@ scsih_suspend(struct pci_dev *pdev, pm_message_t 
state)
 static int
 scsih_resume(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
pci_power_t device_state = pdev->current_state;
int r;
 
+   r = _scsih_get_shost_and_ioc(pdev, , );
+   if (r) {
+   dev_err(>dev, "unable to resume device\n");
+   return r;
+   }
+
pr_info(MPT3SAS_FMT
"pdev=0x%p, slot=%s, previous operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
@@ -10790,9 +10840,13 @@ scsih_resume(struct pci_dev *pdev)
 static pci_ers_result_t
 scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "device unavailable\n");
+   return PCI_ERS_RESULT_DISCONNECT;
+  

Re: [PATCH v3 1/6] mpt3sas: Introduce mpt3sas_base_pci_device_is_available

2018-09-25 Thread Suganath Prabu Subramani
On Tue, Sep 25, 2018 at 3:22 PM Andy Shevchenko
 wrote:
>
> On Tue, Sep 25, 2018 at 12:46 PM Suganath Prabu Subramani
>  wrote:
>
> > > > +   pr_err(MPT3SAS_FMT
> > > > +   "%s: pci error recovery reset or"
> > > > +   " pci device unplug occurred\n",
> > >
> > > This should be just one line.
> > Above line crosses over 80 characters, so it is in two lines.
>
> For years there is no such requirement for string literals.
Below is the one i was mentioning,
WARNING: line over 80 characters
#30: FILE: drivers/scsi/mpt3sas/mpt3sas_base.c:6861:
+ pr_err(MPT3SAS_FMT "%s: pci error recovery reset or pci device
unplug occurred\n", ioc->name, __func__);

Warning comes for both characters over 80 chars and string split.
Do you want us to ignore warning and repost like above in single line ?
> Please, don't split string literals in ugly way like this.
>
> --
> With Best Regards,
> Andy Shevchenko


Re: [PATCH v3 1/6] mpt3sas: Introduce mpt3sas_base_pci_device_is_available

2018-09-25 Thread Suganath Prabu Subramani
Hi Andy,

I forgot to add Lukas in last patch CC list, But i have sent a note
regarding the updated patch to him.
 Also added linux-pci

On Tue, Sep 25, 2018 at 2:10 PM Andy Shevchenko
 wrote:
>
> On Mon, Sep 24, 2018 at 9:36 AM Suganath Prabu S
>  wrote:
> >
> > * Driver uses "pci_device_is_present" to check whether
> > If Hot unplugged:
> > the outstanding IOs with 'DID_NO_CONNECT' before removing the drives
> > attached to the HBA.
> > "DID_NO_CONNECT" status and free the smid, if driver detects that
> > HBA is hot unplugged.
> >
> > * In the hard reset flush out all the outstanding IOs even if diag reset
> > fails and also if driver detects that HBA is hot unplugged.
>
> > +   if (!mpt3sas_base_pci_device_is_available(ioc)) {
>
> > +   pr_err(MPT3SAS_FMT
> > +   "%s: pci error recovery reset or"
> > +   " pci device unplug occurred\n",
>
> This should be just one line.
Above line crosses over 80 characters, so it is in two lines.
>
> > +   ioc->name, __func__);
> > +   return;
> > +   }
>
> --
> With Best Regards,
> Andy Shevchenko


[PATCH v3 6/6] mpt3sas: Bump driver version to 27.100.00.00.

2018-09-24 Thread Suganath Prabu S
Modify driver version to 27.100.00.00
(which is equivalent to PH8 OOB driver)

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index f0351a2..b880d79 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -74,8 +74,8 @@
 #define MPT3SAS_DRIVER_NAME"mpt3sas"
 #define MPT3SAS_AUTHOR "Avago Technologies "
 #define MPT3SAS_DESCRIPTION"LSI MPT Fusion SAS 3.0 Device Driver"
-#define MPT3SAS_DRIVER_VERSION "26.100.00.00"
-#define MPT3SAS_MAJOR_VERSION  26
+#define MPT3SAS_DRIVER_VERSION "27.100.00.00"
+#define MPT3SAS_MAJOR_VERSION  27
 #define MPT3SAS_MINOR_VERSION  100
 #define MPT3SAS_BUILD_VERSION  0
 #define MPT3SAS_RELEASE_VERSION00
-- 
1.8.3.1



[PATCH v3 4/6] mpt3sas: Fix Sync cache command failure during driver unload.

2018-09-24 Thread Suganath Prabu S
This is to fix Sync cache and start stop command
 failures with DID_NO_CONNECT during driver unload.

1) Release drives first from SML, then remove internally
in driver.
2) And allow sync cache and Start stop commands to firmware,
even when remove_host flag is set

v2 Changeset:
Replaced this function mpt3sas_base_pci_device_is_unplugged
with pci_device_is_present

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 41 ++--
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  7 --
 2 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index f6e92eb..5d15d06 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -3806,6 +3806,43 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 
smid, u8 msix_index,
return _scsih_check_for_pending_tm(ioc, smid);
 }
 
+/** _scsih_allow_scmd_to_device - check whether scmd needs to
+ *  issue to IOC or not.
+ * @ioc: per adapter object
+ * @scmd: pointer to scsi command object
+ *
+ * Returns true if scmd can be issued to IOC otherwise returns false.
+ */
+inline bool _scsih_allow_scmd_to_device(struct MPT3SAS_ADAPTER *ioc,
+   struct scsi_cmnd *scmd)
+{
+
+   if (ioc->pci_error_recovery)
+   return false;
+
+   if (ioc->hba_mpi_version_belonged == MPI2_VERSION) {
+   if (ioc->remove_host)
+   return false;
+
+   return true;
+   }
+
+
+   if (ioc->remove_host) {
+   if (!pci_device_is_present(ioc->pdev))
+   return false;
+
+   switch (scmd->cmnd[0]) {
+   case SYNCHRONIZE_CACHE:
+   case START_STOP:
+   return true;
+   default:
+   return false;
+   }
+   }
+
+   return true;
+}
 
 /**
  * _scsih_sas_control_complete - completion routine
@@ -4640,7 +4677,7 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd 
*scmd)
return 0;
}
 
-   if (ioc->pci_error_recovery || ioc->remove_host) {
+   if (!(_scsih_allow_scmd_to_device(ioc, scmd))) {
scmd->result = DID_NO_CONNECT << 16;
scmd->scsi_done(scmd);
return 0;
@@ -9874,6 +9911,7 @@ static void scsih_remove(struct pci_dev *pdev)
 
/* release all the volumes */
_scsih_ir_shutdown(ioc);
+   sas_remove_host(shost);
list_for_each_entry_safe(raid_device, next, >raid_device_list,
list) {
if (raid_device->starget) {
@@ -9916,7 +9954,6 @@ static void scsih_remove(struct pci_dev *pdev)
ioc->sas_hba.num_phys = 0;
}
 
-   sas_remove_host(shost);
mpt3sas_base_detach(ioc);
spin_lock(_lock);
list_del(>list);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c 
b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index b10d73e..742da74 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -817,10 +817,13 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER 
*ioc, u64 sas_address,
mpt3sas_port->remote_identify.sas_address,
mpt3sas_phy->phy_id);
mpt3sas_phy->phy_belongs_to_port = 0;
-   sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
+   if (!ioc->remove_host)
+   sas_port_delete_phy(mpt3sas_port->port,
+   mpt3sas_phy->phy);
list_del(_phy->port_siblings);
}
-   sas_port_delete(mpt3sas_port->port);
+   if (!ioc->remove_host)
+   sas_port_delete(mpt3sas_port->port);
kfree(mpt3sas_port);
 }
 
-- 
1.8.3.1



[PATCH v3 5/6] mpt3sas: Fix driver modifying NVRAM/persistent data.

2018-09-24 Thread Suganath Prabu S
* If EEDPTagMode field in manufacturing page11 is set,
unset it. This is needed to fix a hardware bug
in SAS3/SAS2 cards, So, skipping EEDPTagMode changes
in Manufacturing page11 for SAS35 controllers.

* Fix driver modifying NVRAM/persistent data in
Manufacturing page11 along with current copy. Driver should
change only current copy of Manufacturing page11

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c   | 2 +-
 drivers/scsi/mpt3sas/mpt3sas_config.c | 4 
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 55e6fd0..87a67fe 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -4122,7 +4122,7 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
 * flag unset in NVDATA.
 */
mpt3sas_config_get_manufacturing_pg11(ioc, _reply, >manu_pg11);
-   if (ioc->manu_pg11.EEDPTagMode == 0) {
+   if ((!ioc->is_gen35_ioc) && (ioc->manu_pg11.EEDPTagMode == 0)) {
pr_err("%s: overriding NVDATA EEDPTagMode setting\n",
ioc->name);
ioc->manu_pg11.EEDPTagMode &= ~0x3;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c 
b/drivers/scsi/mpt3sas/mpt3sas_config.c
index 5713a2d..f2a326a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_config.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -676,10 +676,6 @@ mpt3sas_config_set_manufacturing_pg11(struct 
MPT3SAS_ADAPTER *ioc,
r = _config_request(ioc, _request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
sizeof(*config_page));
-   mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
-   r = _config_request(ioc, _request, mpi_reply,
-   MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-   sizeof(*config_page));
  out:
return r;
 }
-- 
1.8.3.1



[PATCH v3 3/6] mpt3sas: Introdude _scsih_get_shost_and_ioc.

2018-09-24 Thread Suganath Prabu S
The code for getting shost and IOC is redundant so
moved that to function "scsih_get_shost_and_ioc".
Also checks for NULL are added to IOC and shost.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 98 ++--
 1 file changed, 82 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 566a550..f6e92eb 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -9809,6 +9809,35 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
 }
 
 /**
+ * _scsih_get_shost_and_ioc - get shost and ioc
+ * and verify whether they are NULL or not
+ * @pdev: PCI device struct
+ * @shost: address of scsi host pointer
+ * @ioc: address of HBA adapter pointer
+ *
+ * Return zero if *shost and *ioc are not NULL otherwise return error number.
+ */
+static int
+_scsih_get_shost_and_ioc(struct pci_dev *pdev,
+   struct Scsi_Host **shost, struct MPT3SAS_ADAPTER **ioc)
+{
+   *shost = pci_get_drvdata(pdev);
+   if (*shost == NULL) {
+   dev_err(>dev, "pdev's driver data is null\n");
+   return -ENXIO;
+   }
+
+   *ioc = shost_priv(*shost);
+   if (*ioc == NULL) {
+   dev_err(>dev, "shost's private data is null\n");
+   return -ENXIO;
+   }
+
+   return 0;
+}
+
+
+/**
  * scsih_remove - detach and remove add host
  * @pdev: PCI device struct
  *
@@ -9816,8 +9845,8 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
  */
 static void scsih_remove(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
struct _sas_port *mpt3sas_port, *next_port;
struct _raid_device *raid_device, *next;
struct MPT3SAS_TARGET *sas_target_priv_data;
@@ -9825,6 +9854,10 @@ static void scsih_remove(struct pci_dev *pdev)
struct workqueue_struct *wq;
unsigned long flags;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "unable to remove device\n");
+   return;
+   }
ioc->remove_host = 1;
 
mpt3sas_wait_for_commands_to_complete(ioc);
@@ -9898,11 +9931,16 @@ static void scsih_remove(struct pci_dev *pdev)
 static void
 scsih_shutdown(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
struct workqueue_struct *wq;
unsigned long flags;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "unable to shutdown device\n");
+   return;
+   }
+
ioc->remove_host = 1;
 
mpt3sas_wait_for_commands_to_complete(ioc);
@@ -10727,10 +10765,16 @@ out_add_shost_fail:
 static int
 scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
pci_power_t device_state;
+   int rc;
 
+   rc = _scsih_get_shost_and_ioc(pdev, , );
+   if (rc) {
+   dev_err(>dev, "unable to suspend device\n");
+   return rc;
+   }
mpt3sas_base_stop_watchdog(ioc);
flush_scheduled_work();
scsi_block_requests(shost);
@@ -10754,11 +10798,17 @@ scsih_suspend(struct pci_dev *pdev, pm_message_t 
state)
 static int
 scsih_resume(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
pci_power_t device_state = pdev->current_state;
int r;
 
+   r = _scsih_get_shost_and_ioc(pdev, , );
+   if (r) {
+   dev_err(>dev, "unable to resume device\n");
+   return r;
+   }
+
pr_info(MPT3SAS_FMT
"pdev=0x%p, slot=%s, previous operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
@@ -10790,9 +10840,13 @@ scsih_resume(struct pci_dev *pdev)
 static pci_ers_result_t
 scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "device unavailable\n");
+   return PCI_ERS_RESULT_DISCONNECT;
+  

[PATCH v3 0/6] mpt3sas: Hot-Plug Surprise removal support on IOC.

2018-09-24 Thread Suganath Prabu S
Posting below set of patches to support PCIe Hot Plug surprise removal,
and few defect fixes.

This is NOT the normal PCIe Hot Plug support, whereby the user informs the
OS that a hot removal is desired, the OS does an orderly shutdown of the
driver on the device, special hot plug circuitry removes power from the
PCIe slot, then the user can remove the device and replace it
(where orderly bring-up of the device is done).

With a true surprise removal (just removing HBA from a slot)
there is a possibility to get all kinds of PCIe transaction errors,
Below patches addresses those issues and remove HBA without bringing
the system down.

For surprise removal detection, driver does a PCI
read of IOC's vendor field in IOC's PCI configuration space.
If the read value is 0x this indicates that the device
might have hot removed and the device will be removed from driver.

V1 changes:
In Patch 0001 - unlock mutex, if active reset is in progress.

V2 changes:
Replaced mpt3sas_base_pci_device_is_unplugged with
pci_device_is_present.

V3 Change Set:
Simplified function "mpt3sas_base_pci_device_is_available" and
made inline

Suganath Prabu S (6):
  mpt3sas: Introduce  mpt3sas_base_pci_device_is_available
  mpt3sas: Separate out  mpt3sas_wait_for_ioc_to_operational
  mpt3sas: Introdude  _scsih_get_shost_and_ioc.
  mpt3sas: Fix Sync cache command failure during driver  unload.
  mpt3sas: Fix driver modifying NVRAM/persistent data.
  mpt3sas: Bump driver version to 27.100.00.00.

 drivers/scsi/mpt3sas/mpt3sas_base.c  | 135 +++---
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  11 +-
 drivers/scsi/mpt3sas/mpt3sas_config.c|  32 +-
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  26 +
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 189 +++
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  82 +++---
 6 files changed, 298 insertions(+), 177 deletions(-)

-- 
1.8.3.1



[PATCH v3 2/6] mpt3sas: Separate out mpt3sas_wait_for_ioc_to_operational

2018-09-24 Thread Suganath Prabu S
Introduce mpt3sas_wait_for_ioc_to_operational.

This section of code "wait for IOC to be operational"
is used in many places across the driver,
and hence moved this section of code in to the function
"mpt3sas_wait_for_ioc_to_operational".

Also added HBA hot unplug checks, and this returns with
error code EFAULT, if it detects HBA is hot unplugged
or IOC is not in operational state.

V2 change set:
used pci_device_is_present instead of
mpt3sas_base_pci_device_is_unplugged

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 92 +++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  4 ++
 drivers/scsi/mpt3sas/mpt3sas_config.c| 28 +++---
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   | 26 ++---
 drivers/scsi/mpt3sas/mpt3sas_transport.c | 75 +-
 5 files changed, 81 insertions(+), 144 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index c98d8e2..55e6fd0 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -5176,6 +5176,53 @@ _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 
reset_type, int timeout)
 }
 
 /**
+ * mpt3sas_wait_for_ioc_to_operational - IOC's operational
+ * state and HBA hot unplug status are checked here.
+ * @ioc: per adapter object
+ * @wait_count: timeout in seconds
+ *
+ * Return:  Returns EFAULT, if HBA is hot unplugged or IOC is
+ * not in operational state, within the wait_count.
+ * And returns 0, If not hot unplugged Or ioc is in
+ * operational state.
+ */
+
+int
+mpt3sas_wait_for_ioc_to_operational(struct MPT3SAS_ADAPTER *ioc,
+   int wait_count)
+{
+   int wait_state_count = 0;
+   u32 ioc_state;
+
+   if (!pci_device_is_present(ioc->pdev))
+   return -EFAULT;
+
+   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+   while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+
+   if (!pci_device_is_present(ioc->pdev))
+   return -EFAULT;
+
+   if (wait_state_count++ == wait_count) {
+   pr_err(MPT3SAS_FMT
+   "%s: failed due to ioc not operational\n",
+   ioc->name, __func__);
+   return -EFAULT;
+   }
+   ssleep(1);
+   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+   pr_info(MPT3SAS_FMT "%s: waiting for "
+   "operational state(count=%d)\n", ioc->name,
+   __func__, wait_state_count);
+   }
+   if (wait_state_count)
+   pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
+   ioc->name, __func__);
+
+   return 0;
+}
+
+/**
  * _base_handshake_req_reply_wait - send request thru doorbell interface
  * @ioc: per adapter object
  * @request_bytes: request length
@@ -5316,11 +5363,9 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER 
*ioc,
Mpi2SasIoUnitControlRequest_t *mpi_request)
 {
u16 smid;
-   u32 ioc_state;
u8 issue_reset = 0;
int rc;
void *request;
-   u16 wait_state_count;
 
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
@@ -5334,22 +5379,10 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER 
*ioc,
goto out;
}
 
-   wait_state_count = 0;
-   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
-   while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-   if (wait_state_count++ == 10) {
-   pr_err(MPT3SAS_FMT
-   "%s: failed due to ioc not operational\n",
-   ioc->name, __func__);
-   rc = -EFAULT;
-   goto out;
-   }
-   ssleep(1);
-   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
-   pr_info(MPT3SAS_FMT
-   "%s: waiting for operational state(count=%d)\n",
-   ioc->name, __func__, wait_state_count);
-   }
+   rc = mpt3sas_wait_for_ioc_to_operational(ioc,
+   IOC_OPERATIONAL_WAIT_COUNT);
+   if (rc)
+   goto out;
 
smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
if (!smid) {
@@ -5416,11 +5449,9 @@ mpt3sas_base_scsi_enclosure_processor(struct 
MPT3SAS_ADAPTER *ioc,
Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request)
 {
u16 smid;
-   u32 ioc_state;
u8 issue_reset = 0;
int rc;
void *request;
-   u16 wait_state_count;
 
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
@@ -5434,23 +5465,10 @@ mpt3sas_base_scsi_enclosure_processor(struct 
MPT3SAS_ADAPTER *ioc,
g

[PATCH v3 1/6] mpt3sas: Introduce mpt3sas_base_pci_device_is_available

2018-09-24 Thread Suganath Prabu S
* Driver uses "pci_device_is_present" to check whether
If Hot unplugged:
the outstanding IOs with 'DID_NO_CONNECT' before removing the drives
attached to the HBA.
"DID_NO_CONNECT" status and free the smid, if driver detects that
HBA is hot unplugged.

* In the hard reset flush out all the outstanding IOs even if diag reset
fails and also if driver detects that HBA is hot unplugged.

v1 change set:
==
unlock mutex before goto "out_unlocked",
if active reset is in progress.

v2 change set:
==
1) Use pci_device_is_present instead of
mpt3sas_base_pci_device_is_unplugged.
2) As suggested by Lukas, removed using
watchdog thread for checking hba hot unplug(Patch 02 of V1).
Added Hot unplug checks in scan finish and reset paths.

v3 Change Set:
=
Simplified function "mpt3sas_base_pci_device_is_available" and
made inline.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 41 +
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  3 ++-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 50 
 3 files changed, 88 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 59d7844..c98d8e2 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -543,6 +543,20 @@ static int mpt3sas_remove_dead_ioc_func(void *arg)
 }
 
 /**
+ * mpt3sas_base_pci_device_is_available - check whether pci device is
+ * available for any transactions with FW
+ *
+ * @ioc: per adapter object
+ *
+ * Return 1 if pci device state is up and running else return 0.
+ */
+inline bool
+mpt3sas_base_pci_device_is_available(struct MPT3SAS_ADAPTER *ioc)
+{
+   return !ioc->pci_error_recovery && pci_device_is_present(ioc->pdev);
+}
+
+/**
  * _base_fault_reset_work - workq handling ioc fault conditions
  * @work: input argument, used to derive ioc
  *
@@ -6122,6 +6136,11 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc)
 
count = 0;
do {
+   if (!pci_device_is_present(ioc->pdev)) {
+   ioc->remove_host = 1;
+   pr_err(MPT3SAS_FMT "Hba Hot unplugged\n", ioc->name);
+   goto out;
+   }
/* Write magic sequence to WriteSequence register
 * Loop until in diagnostic mode
 */
@@ -6853,6 +6872,14 @@ mpt3sas_wait_for_commands_to_complete(struct 
MPT3SAS_ADAPTER *ioc)
 
ioc->pending_io_count = 0;
 
+   if (!mpt3sas_base_pci_device_is_available(ioc)) {
+   pr_err(MPT3SAS_FMT
+   "%s: pci error recovery reset or"
+   " pci device unplug occurred\n",
+   ioc->name, __func__);
+   return;
+   }
+
ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
return;
@@ -6899,6 +6926,20 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER 
*ioc,
/* wait for an active reset in progress to complete */
mutex_lock(>reset_in_progress_mutex);
 
+   if (!mpt3sas_base_pci_device_is_available(ioc)) {
+   pr_err(MPT3SAS_FMT
+   "%s: pci error recovery reset or"
+   " pci device unplug occurred\n",
+   ioc->name, __func__);
+   if (!pci_device_is_present(ioc->pdev))
+   ioc->schedule_dead_ioc_flush_running_cmds(ioc);
+   r = 0;
+   mutex_unlock(>reset_in_progress_mutex);
+   goto out_unlocked;
+   }
+
+   mpt3sas_halt_firmware(ioc);
+
spin_lock_irqsave(>ioc_reset_in_progress_lock, flags);
ioc->shost_recovery = 1;
spin_unlock_irqrestore(>ioc_reset_in_progress_lock, flags);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 96dc15e..a802ad4 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1474,7 +1474,8 @@ void mpt3sas_base_update_missing_delay(struct 
MPT3SAS_ADAPTER *ioc,
u16 device_missing_delay, u8 io_missing_delay);
 
 int mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc);
-
+inline bool  mpt3sas_base_pci_device_is_available(
+   struct MPT3SAS_ADAPTER *ioc);
 void
 mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc);
 
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 53133cf..566a550 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2846,9 +2846,19 @@ scsih_abort(struct scsi_cmnd *scmd)
"attempting task abort! scmd(%p)\n", scmd);
_scsih_tm_displa

[PATCH v2 4/6] mpt3sas: Fix Sync cache command failure during driver unload.

2018-09-20 Thread Suganath Prabu S
This is to fix Sync cache and start stop command
 failures with DID_NO_CONNECT during driver unload.

1) Release drives first from SML, then remove internally
in driver.
2) And allow sync cache and Start stop commands to firmware,
even when remove_host flag is set

v2 Changeset:
Replaced this function mpt3sas_base_pci_device_is_unplugged
with pci_device_is_present

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 41 ++--
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  7 --
 2 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index f6e92eb..5d15d06 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -3806,6 +3806,43 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 
smid, u8 msix_index,
return _scsih_check_for_pending_tm(ioc, smid);
 }
 
+/** _scsih_allow_scmd_to_device - check whether scmd needs to
+ *  issue to IOC or not.
+ * @ioc: per adapter object
+ * @scmd: pointer to scsi command object
+ *
+ * Returns true if scmd can be issued to IOC otherwise returns false.
+ */
+inline bool _scsih_allow_scmd_to_device(struct MPT3SAS_ADAPTER *ioc,
+   struct scsi_cmnd *scmd)
+{
+
+   if (ioc->pci_error_recovery)
+   return false;
+
+   if (ioc->hba_mpi_version_belonged == MPI2_VERSION) {
+   if (ioc->remove_host)
+   return false;
+
+   return true;
+   }
+
+
+   if (ioc->remove_host) {
+   if (!pci_device_is_present(ioc->pdev))
+   return false;
+
+   switch (scmd->cmnd[0]) {
+   case SYNCHRONIZE_CACHE:
+   case START_STOP:
+   return true;
+   default:
+   return false;
+   }
+   }
+
+   return true;
+}
 
 /**
  * _scsih_sas_control_complete - completion routine
@@ -4640,7 +4677,7 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd 
*scmd)
return 0;
}
 
-   if (ioc->pci_error_recovery || ioc->remove_host) {
+   if (!(_scsih_allow_scmd_to_device(ioc, scmd))) {
scmd->result = DID_NO_CONNECT << 16;
scmd->scsi_done(scmd);
return 0;
@@ -9874,6 +9911,7 @@ static void scsih_remove(struct pci_dev *pdev)
 
/* release all the volumes */
_scsih_ir_shutdown(ioc);
+   sas_remove_host(shost);
list_for_each_entry_safe(raid_device, next, >raid_device_list,
list) {
if (raid_device->starget) {
@@ -9916,7 +9954,6 @@ static void scsih_remove(struct pci_dev *pdev)
ioc->sas_hba.num_phys = 0;
}
 
-   sas_remove_host(shost);
mpt3sas_base_detach(ioc);
spin_lock(_lock);
list_del(>list);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c 
b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index b10d73e..742da74 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -817,10 +817,13 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER 
*ioc, u64 sas_address,
mpt3sas_port->remote_identify.sas_address,
mpt3sas_phy->phy_id);
mpt3sas_phy->phy_belongs_to_port = 0;
-   sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
+   if (!ioc->remove_host)
+   sas_port_delete_phy(mpt3sas_port->port,
+   mpt3sas_phy->phy);
list_del(_phy->port_siblings);
}
-   sas_port_delete(mpt3sas_port->port);
+   if (!ioc->remove_host)
+   sas_port_delete(mpt3sas_port->port);
kfree(mpt3sas_port);
 }
 
-- 
1.8.3.1



[PATCH v2 6/6] mpt3sas: Bump driver version to 27.100.00.00.

2018-09-20 Thread Suganath Prabu S
Modify driver version to 27.100.00.00
(which is equivalent to PH8 OOB driver)

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 2bf4c4a..887e249 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -74,8 +74,8 @@
 #define MPT3SAS_DRIVER_NAME"mpt3sas"
 #define MPT3SAS_AUTHOR "Avago Technologies "
 #define MPT3SAS_DESCRIPTION"LSI MPT Fusion SAS 3.0 Device Driver"
-#define MPT3SAS_DRIVER_VERSION "26.100.00.00"
-#define MPT3SAS_MAJOR_VERSION  26
+#define MPT3SAS_DRIVER_VERSION "27.100.00.00"
+#define MPT3SAS_MAJOR_VERSION  27
 #define MPT3SAS_MINOR_VERSION  100
 #define MPT3SAS_BUILD_VERSION  0
 #define MPT3SAS_RELEASE_VERSION00
-- 
1.8.3.1



[PATCH v2 1/6] mpt3sas: Introduce mpt3sas_base_pci_device_is_available

2018-09-20 Thread Suganath Prabu S
* Driver uses "pci_device_is_present" to check whether
If Hot unplugged:
the outstanding IOs with 'DID_NO_CONNECT' before removing the drives
attached to the HBA.
"DID_NO_CONNECT" status and free the smid, if driver detects that
HBA is hot unplugged.

* In the hard reset flush out all the outstanding IOs even if diag reset
fails and also if driver detects that HBA is hot unplugged.

v1 change set:
==
unlock mutex before goto "out_unlocked",
if active reset is in progress.

v2 change set:
==
1) Use pci_device_is_present instead of
mpt3sas_base_pci_device_is_unplugged.
2) As suggested by Lukas, removed using
watchdog thread for checking hba hot unplug(Patch 02 of V1).
Added Hot unplug checks in scan finish and reset paths.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 46 -
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  2 +-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 50 
 3 files changed, 91 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 59d7844..89b74ed 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -62,7 +62,6 @@
 #include /* To get host page size per arch */
 #include 
 
-
 #include "mpt3sas_base.h"
 
 static MPT_CALLBACKmpt_callbacks[MPT_MAX_CALLBACKS];
@@ -543,6 +542,24 @@ static int mpt3sas_remove_dead_ioc_func(void *arg)
 }
 
 /**
+ * mpt3sas_base_pci_device_is_available - check whether pci device is
+ * available for any transactions with FW
+ *
+ * @ioc: per adapter object
+ *
+ * Return 1 if pci device state is up and running else return 0.
+ */
+u8
+mpt3sas_base_pci_device_is_available(struct MPT3SAS_ADAPTER *ioc)
+{
+   if (ioc->pci_error_recovery ||
+(!pci_device_is_present(ioc->pdev)))
+   return 0;
+
+   return 1;
+}
+
+/**
  * _base_fault_reset_work - workq handling ioc fault conditions
  * @work: input argument, used to derive ioc
  *
@@ -6122,6 +6139,11 @@ _base_diag_reset(struct MPT3SAS_ADAPTER *ioc)
 
count = 0;
do {
+   if (!pci_device_is_present(ioc->pdev)) {
+   ioc->remove_host = 1;
+   pr_err(MPT3SAS_FMT "Hba Hot unplugged\n", ioc->name);
+   goto out;
+   }
/* Write magic sequence to WriteSequence register
 * Loop until in diagnostic mode
 */
@@ -6853,6 +6875,14 @@ mpt3sas_wait_for_commands_to_complete(struct 
MPT3SAS_ADAPTER *ioc)
 
ioc->pending_io_count = 0;
 
+   if (!mpt3sas_base_pci_device_is_available(ioc)) {
+   pr_err(MPT3SAS_FMT
+   "%s: pci error recovery reset or"
+   " pci device unplug occurred\n",
+   ioc->name, __func__);
+   return;
+   }
+
ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
return;
@@ -6899,6 +6929,20 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER 
*ioc,
/* wait for an active reset in progress to complete */
mutex_lock(>reset_in_progress_mutex);
 
+   if (!mpt3sas_base_pci_device_is_available(ioc)) {
+   pr_err(MPT3SAS_FMT
+   "%s: pci error recovery reset or"
+   " pci device unplug occurred\n",
+   ioc->name, __func__);
+   if (!pci_device_is_present(ioc->pdev))
+   ioc->schedule_dead_ioc_flush_running_cmds(ioc);
+   r = 0;
+   mutex_unlock(>reset_in_progress_mutex);
+   goto out_unlocked;
+   }
+
+   mpt3sas_halt_firmware(ioc);
+
spin_lock_irqsave(>ioc_reset_in_progress_lock, flags);
ioc->shost_recovery = 1;
spin_unlock_irqrestore(>ioc_reset_in_progress_lock, flags);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 96dc15e..d673b00 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1474,7 +1474,7 @@ void mpt3sas_base_update_missing_delay(struct 
MPT3SAS_ADAPTER *ioc,
u16 device_missing_delay, u8 io_missing_delay);
 
 int mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc);
-
+u8 mpt3sas_base_pci_device_is_available(struct MPT3SAS_ADAPTER *ioc);
 void
 mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc);
 
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 53133cf..566a550 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2846,9 +2846,19 @@ scsih_abort(struct scsi_cmnd *scmd)
&q

[PATCH v2 0/6] mpt3sas: Hot-Plug Surprise removal support on IOC.

2018-09-20 Thread Suganath Prabu S
Posting below set of patches to support PCIe Hot Plug surprise removal,
and few defect fixes.

This is NOT the normal PCIe Hot Plug support, whereby the user informs the
OS that a hot removal is desired, the OS does an orderly shutdown of the
driver on the device, special hot plug circuitry removes power from the
PCIe slot, then the user can remove the device and replace it
(where orderly bring-up of the device is done).

With a true surprise removal (just removing HBA from a slot)
there is a possibility to get all kinds of PCIe transaction errors,
Below patches addresses those issues and remove HBA without bringing
the system down.

For surprise removal detection, driver does a PCI
read of IOC's vendor field in IOC's PCI configuration space.
If the read value is 0x this indicates that the device
might have hot removed and the device will be removed from driver.

V1 changes:
In Patch 0001 - unlock mutex, if active reset is in progress.

V2 changes:
Replaced mpt3sas_base_pci_device_is_unplugged with
pci_device_is_present.

Suganath Prabu S (6):
  mpt3sas: Introduce  mpt3sas_base_pci_device_is_available
  mpt3sas: Separate out  mpt3sas_wait_for_ioc_to_operational
  mpt3sas: Introdude  _scsih_get_shost_and_ioc.
  mpt3sas: Fix Sync cache command failure during driver  unload.
  mpt3sas: Fix driver modifying NVRAM/persistent data.
  mpt3sas: Bump driver version to 27.100.00.00.

 drivers/scsi/mpt3sas/mpt3sas_base.c  | 140 ---
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  10 +-
 drivers/scsi/mpt3sas/mpt3sas_config.c|  32 +-
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  26 +
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 189 +++
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  82 +++---
 6 files changed, 301 insertions(+), 178 deletions(-)

-- 
1.8.3.1



[PATCH v2 3/6] mpt3sas: Introdude _scsih_get_shost_and_ioc.

2018-09-20 Thread Suganath Prabu S
The code for getting shost and IOC is redundant so
moved that to function "scsih_get_shost_and_ioc".
Also checks for NULL are added to IOC and shost.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 98 ++--
 1 file changed, 82 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 566a550..f6e92eb 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -9809,6 +9809,35 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
 }
 
 /**
+ * _scsih_get_shost_and_ioc - get shost and ioc
+ * and verify whether they are NULL or not
+ * @pdev: PCI device struct
+ * @shost: address of scsi host pointer
+ * @ioc: address of HBA adapter pointer
+ *
+ * Return zero if *shost and *ioc are not NULL otherwise return error number.
+ */
+static int
+_scsih_get_shost_and_ioc(struct pci_dev *pdev,
+   struct Scsi_Host **shost, struct MPT3SAS_ADAPTER **ioc)
+{
+   *shost = pci_get_drvdata(pdev);
+   if (*shost == NULL) {
+   dev_err(>dev, "pdev's driver data is null\n");
+   return -ENXIO;
+   }
+
+   *ioc = shost_priv(*shost);
+   if (*ioc == NULL) {
+   dev_err(>dev, "shost's private data is null\n");
+   return -ENXIO;
+   }
+
+   return 0;
+}
+
+
+/**
  * scsih_remove - detach and remove add host
  * @pdev: PCI device struct
  *
@@ -9816,8 +9845,8 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
  */
 static void scsih_remove(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
struct _sas_port *mpt3sas_port, *next_port;
struct _raid_device *raid_device, *next;
struct MPT3SAS_TARGET *sas_target_priv_data;
@@ -9825,6 +9854,10 @@ static void scsih_remove(struct pci_dev *pdev)
struct workqueue_struct *wq;
unsigned long flags;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "unable to remove device\n");
+   return;
+   }
ioc->remove_host = 1;
 
mpt3sas_wait_for_commands_to_complete(ioc);
@@ -9898,11 +9931,16 @@ static void scsih_remove(struct pci_dev *pdev)
 static void
 scsih_shutdown(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
struct workqueue_struct *wq;
unsigned long flags;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "unable to shutdown device\n");
+   return;
+   }
+
ioc->remove_host = 1;
 
mpt3sas_wait_for_commands_to_complete(ioc);
@@ -10727,10 +10765,16 @@ out_add_shost_fail:
 static int
 scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
pci_power_t device_state;
+   int rc;
 
+   rc = _scsih_get_shost_and_ioc(pdev, , );
+   if (rc) {
+   dev_err(>dev, "unable to suspend device\n");
+   return rc;
+   }
mpt3sas_base_stop_watchdog(ioc);
flush_scheduled_work();
scsi_block_requests(shost);
@@ -10754,11 +10798,17 @@ scsih_suspend(struct pci_dev *pdev, pm_message_t 
state)
 static int
 scsih_resume(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
pci_power_t device_state = pdev->current_state;
int r;
 
+   r = _scsih_get_shost_and_ioc(pdev, , );
+   if (r) {
+   dev_err(>dev, "unable to resume device\n");
+   return r;
+   }
+
pr_info(MPT3SAS_FMT
"pdev=0x%p, slot=%s, previous operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
@@ -10790,9 +10840,13 @@ scsih_resume(struct pci_dev *pdev)
 static pci_ers_result_t
 scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "device unavailable\n");
+   return PCI_ERS_RESULT_DISCONNECT;
+  

[PATCH v2 2/6] mpt3sas: Separate out mpt3sas_wait_for_ioc_to_operational

2018-09-20 Thread Suganath Prabu S
Introduce mpt3sas_wait_for_ioc_to_operational.

This section of code "wait for IOC to be operational"
is used in many places across the driver,
and hence moved this section of code in to the function
"mpt3sas_wait_for_ioc_to_operational".

Also added HBA hot unplug checks, and this returns with
error code EFAULT, if it detects HBA is hot unplugged
or IOC is not in operational state.

V2 change set:
used pci_device_is_present instead of
mpt3sas_base_pci_device_is_unplugged

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 92 +++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  4 ++
 drivers/scsi/mpt3sas/mpt3sas_config.c| 28 +++---
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   | 26 ++---
 drivers/scsi/mpt3sas/mpt3sas_transport.c | 75 +-
 5 files changed, 81 insertions(+), 144 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 89b74ed..554de04 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -5179,6 +5179,53 @@ _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 
reset_type, int timeout)
 }
 
 /**
+ * mpt3sas_wait_for_ioc_to_operational - IOC's operational
+ * state and HBA hot unplug status are checked here.
+ * @ioc: per adapter object
+ * @wait_count: timeout in seconds
+ *
+ * Return:  Returns EFAULT, if HBA is hot unplugged or IOC is
+ * not in operational state, within the wait_count.
+ * And returns 0, If not hot unplugged Or ioc is in
+ * operational state.
+ */
+
+int
+mpt3sas_wait_for_ioc_to_operational(struct MPT3SAS_ADAPTER *ioc,
+   int wait_count)
+{
+   int wait_state_count = 0;
+   u32 ioc_state;
+
+   if (!pci_device_is_present(ioc->pdev))
+   return -EFAULT;
+
+   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+   while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+
+   if (!pci_device_is_present(ioc->pdev))
+   return -EFAULT;
+
+   if (wait_state_count++ == wait_count) {
+   pr_err(MPT3SAS_FMT
+   "%s: failed due to ioc not operational\n",
+   ioc->name, __func__);
+   return -EFAULT;
+   }
+   ssleep(1);
+   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+   pr_info(MPT3SAS_FMT "%s: waiting for "
+   "operational state(count=%d)\n", ioc->name,
+   __func__, wait_state_count);
+   }
+   if (wait_state_count)
+   pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
+   ioc->name, __func__);
+
+   return 0;
+}
+
+/**
  * _base_handshake_req_reply_wait - send request thru doorbell interface
  * @ioc: per adapter object
  * @request_bytes: request length
@@ -5319,11 +5366,9 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER 
*ioc,
Mpi2SasIoUnitControlRequest_t *mpi_request)
 {
u16 smid;
-   u32 ioc_state;
u8 issue_reset = 0;
int rc;
void *request;
-   u16 wait_state_count;
 
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
@@ -5337,22 +5382,10 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER 
*ioc,
goto out;
}
 
-   wait_state_count = 0;
-   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
-   while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-   if (wait_state_count++ == 10) {
-   pr_err(MPT3SAS_FMT
-   "%s: failed due to ioc not operational\n",
-   ioc->name, __func__);
-   rc = -EFAULT;
-   goto out;
-   }
-   ssleep(1);
-   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
-   pr_info(MPT3SAS_FMT
-   "%s: waiting for operational state(count=%d)\n",
-   ioc->name, __func__, wait_state_count);
-   }
+   rc = mpt3sas_wait_for_ioc_to_operational(ioc,
+   IOC_OPERATIONAL_WAIT_COUNT);
+   if (rc)
+   goto out;
 
smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
if (!smid) {
@@ -5419,11 +5452,9 @@ mpt3sas_base_scsi_enclosure_processor(struct 
MPT3SAS_ADAPTER *ioc,
Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request)
 {
u16 smid;
-   u32 ioc_state;
u8 issue_reset = 0;
int rc;
void *request;
-   u16 wait_state_count;
 
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
@@ -5437,23 +5468,10 @@ mpt3sas_base_scsi_enclosure_processor(struct 
MPT3SAS_ADAPTER *ioc,
g

[Patch v1 5/7] mpt3sas: Fix Sync cache command failure during driver unload.

2018-08-30 Thread Suganath Prabu S
This is to fix Sync cache and start stop command
 failures with DID_NO_CONNECT during driver unload.

1) Release drives first from SML, then remove internally
in driver.
2) And allow sync cache and Start stop commands to firmware,
even when remove_host flag is set

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 41 ++--
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  7 --
 2 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 2c7f44c..f796808 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -3806,6 +3806,43 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 
smid, u8 msix_index,
return _scsih_check_for_pending_tm(ioc, smid);
 }
 
+/** _scsih_allow_scmd_to_device - check whether scmd needs to
+ *  issue to IOC or not.
+ * @ioc: per adapter object
+ * @scmd: pointer to scsi command object
+ *
+ * Returns true if scmd can be issued to IOC otherwise returns false.
+ */
+inline bool _scsih_allow_scmd_to_device(struct MPT3SAS_ADAPTER *ioc,
+   struct scsi_cmnd *scmd)
+{
+
+   if (ioc->pci_error_recovery)
+   return false;
+
+   if (ioc->hba_mpi_version_belonged == MPI2_VERSION) {
+   if (ioc->remove_host)
+   return false;
+
+   return true;
+   }
+
+
+   if (ioc->remove_host) {
+   if (mpt3sas_base_pci_device_is_unplugged(ioc))
+   return false;
+
+   switch (scmd->cmnd[0]) {
+   case SYNCHRONIZE_CACHE:
+   case START_STOP:
+   return true;
+   default:
+   return false;
+   }
+   }
+
+   return true;
+}
 
 /**
  * _scsih_sas_control_complete - completion routine
@@ -4640,7 +4677,7 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd 
*scmd)
return 0;
}
 
-   if (ioc->pci_error_recovery || ioc->remove_host) {
+   if (!(_scsih_allow_scmd_to_device(ioc, scmd))) {
scmd->result = DID_NO_CONNECT << 16;
scmd->scsi_done(scmd);
return 0;
@@ -9876,6 +9913,7 @@ static void scsih_remove(struct pci_dev *pdev)
 
/* release all the volumes */
_scsih_ir_shutdown(ioc);
+   sas_remove_host(shost);
list_for_each_entry_safe(raid_device, next, >raid_device_list,
list) {
if (raid_device->starget) {
@@ -9918,7 +9956,6 @@ static void scsih_remove(struct pci_dev *pdev)
ioc->sas_hba.num_phys = 0;
}
 
-   sas_remove_host(shost);
mpt3sas_base_detach(ioc);
spin_lock(_lock);
list_del(>list);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c 
b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index b10d73e..742da74 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -817,10 +817,13 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER 
*ioc, u64 sas_address,
mpt3sas_port->remote_identify.sas_address,
mpt3sas_phy->phy_id);
mpt3sas_phy->phy_belongs_to_port = 0;
-   sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
+   if (!ioc->remove_host)
+   sas_port_delete_phy(mpt3sas_port->port,
+   mpt3sas_phy->phy);
list_del(_phy->port_siblings);
}
-   sas_port_delete(mpt3sas_port->port);
+   if (!ioc->remove_host)
+   sas_port_delete(mpt3sas_port->port);
kfree(mpt3sas_port);
 }
 
-- 
1.8.3.1



[Patch v1 1/7] mpt3sas: Introduce mpt3sas_base_pci_device_is_unplugged

2018-08-30 Thread Suganath Prabu S
* Driver does a PCIe read to check whether HBA is hot unplugged or
not. If the returned vendor ID is 0x/0x0, then this
indicates that the device might have been hot removed and the device
will be removed from driver.

* In the PCI device remove() callback function, flush out all
the outstanding IOs with 'DID_NO_CONNECT' before removing the drives
attached to the HBA.

* In the TM abort() callback function return the scmd with
"DID_NO_CONNECT" status and free the smid, if driver detects that
HBA is hot unplugged.

* In the hard reset flush out all the outstanding IOs even if diag reset
fails and also if driver detects that HBA is hot unplugged.

v1 change set:
unlock mutex before goto "out_unlocked", 
if active reset is in progress.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 62 +++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  3 +-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 42 +---
 3 files changed, 100 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 836b2e1..8b33670 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -61,7 +61,7 @@
 #include 
 #include /* To get host page size per arch */
 #include 
-
+#include <../drivers/pci/pci.h>
 
 #include "mpt3sas_base.h"
 
@@ -543,6 +543,44 @@ static int mpt3sas_remove_dead_ioc_func(void *arg)
 }
 
 /**
+ * mpt3sas_base_pci_device_is_unplugged - Check whether HBA device is
+ *  hot unplugged or not
+ * @ioc: per adapter object
+ *
+ * Return 1 if the HBA device is hot unplugged else return 0.
+ */
+u8
+mpt3sas_base_pci_device_is_unplugged(struct MPT3SAS_ADAPTER *ioc)
+{
+   struct pci_dev *pdev = ioc->pdev;
+   int devfn = pdev->devfn;
+   u32 l;
+
+   if (pci_bus_read_dev_vendor_id(pdev->bus, devfn, , 0))
+   return 0;
+
+   return 1;
+}
+
+/**
+ * mpt3sas_base_pci_device_is_available - check whether pci device is
+ * available for any transactions with FW
+ *
+ * @ioc: per adapter object
+ *
+ * Return 1 if pci device state is up and running else return 0.
+ */
+u8
+mpt3sas_base_pci_device_is_available(struct MPT3SAS_ADAPTER *ioc)
+{
+   if (ioc->pci_error_recovery ||
+   mpt3sas_base_pci_device_is_unplugged(ioc))
+   return 0;
+
+   return 1;
+}
+
+/**
  * _base_fault_reset_work - workq handling ioc fault conditions
  * @work: input argument, used to derive ioc
  *
@@ -6853,6 +6891,14 @@ mpt3sas_wait_for_commands_to_complete(struct 
MPT3SAS_ADAPTER *ioc)
 
ioc->pending_io_count = 0;
 
+   if (!mpt3sas_base_pci_device_is_available(ioc)) {
+   pr_err(MPT3SAS_FMT
+   "%s: pci error recovery reset or"
+   " pci device unplug occurred\n",
+   ioc->name, __func__);
+   return;
+   }
+
ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
return;
@@ -6899,6 +6945,20 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER 
*ioc,
/* wait for an active reset in progress to complete */
mutex_lock(>reset_in_progress_mutex);
 
+   if (!mpt3sas_base_pci_device_is_available(ioc)) {
+   pr_err(MPT3SAS_FMT
+   "%s: pci error recovery reset or"
+   " pci device unplug occurred\n",
+   ioc->name, __func__);
+   if (mpt3sas_base_pci_device_is_unplugged(ioc))
+   ioc->schedule_dead_ioc_flush_running_cmds(ioc);
+   r = 0;
+   mutex_unlock(>reset_in_progress_mutex);
+   goto out_unlocked;
+   }
+
+   mpt3sas_halt_firmware(ioc);
+
spin_lock_irqsave(>ioc_reset_in_progress_lock, flags);
ioc->shost_recovery = 1;
spin_unlock_irqrestore(>ioc_reset_in_progress_lock, flags);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 96dc15e..8ee3ba7 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1474,7 +1474,8 @@ void mpt3sas_base_update_missing_delay(struct 
MPT3SAS_ADAPTER *ioc,
u16 device_missing_delay, u8 io_missing_delay);
 
 int mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc);
-
+u8 mpt3sas_base_pci_device_is_unplugged(struct MPT3SAS_ADAPTER *ioc);
+u8 mpt3sas_base_pci_device_is_available(struct MPT3SAS_ADAPTER *ioc);
 void
 mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc);
 
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 8dd3d67..9da 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/driv

[Patch v1 2/7] mpt3sas: Add HBA hot plug watchdog thread.

2018-08-30 Thread Suganath Prabu S
During driver load create a hba hot unplug watchdog thread
"_base_hba_hot_unplug_work".

This will poll whether HBA device is unplugged or not by reading IOC's
vendor field in IOC's PCI configuration space for every one second.

If hot unplug is detected, it terminates all the outstanding IOs
and hence kernels's PCIe hotplug module (i.e. pciehp) will clear the
instances of the hot unplugged PCI device.

Below functions starts and stops the watchdog.
mpt3sas_base_start_hba_unplug_watchdog
mpt3sas_base_stop_hba_unplug_watchdog
Watchdog thread starts immediately once IOC becomes operational.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 92 +++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  6 +++
 drivers/scsi/mpt3sas/mpt3sas_scsih.c |  7 +++
 3 files changed, 104 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 8b33670..6c8a30f 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -69,6 +69,7 @@ static MPT_CALLBACK   mpt_callbacks[MPT_MAX_CALLBACKS];
 
 
 #define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
+#define HBA_HOTUNPLUG_POLLING_INTERVAL 1000 /* in milliseconds */
 
  /* maximum controller queue depth */
 #define MAX_HBA_QUEUE_DEPTH3
@@ -672,6 +673,46 @@ _base_fault_reset_work(struct work_struct *work)
spin_unlock_irqrestore(>ioc_reset_in_progress_lock, flags);
 }
 
+static void
+_base_hba_hot_unplug_work(struct work_struct *work)
+{
+   struct MPT3SAS_ADAPTER *ioc =
+   container_of(work, struct MPT3SAS_ADAPTER,
+   hba_hot_unplug_work.work);
+   unsigned longflags;
+
+   spin_lock_irqsave(>hba_hot_unplug_lock, flags);
+   if (ioc->shost_recovery || ioc->pci_error_recovery)
+   goto rearm_timer;
+
+   if (mpt3sas_base_pci_device_is_unplugged(ioc)) {
+   if (ioc->remove_host) {
+   pr_err(MPT3SAS_FMT
+   "The IOC seems hot unplugged and the driver is "
+   "waiting for pciehp module to remove the PCIe "
+   "device instance associated with IOC!!!\n",
+   ioc->name);
+   goto rearm_timer;
+   }
+
+   /* Set remove_host flag here, since kernel will invoke driver's
+* .remove() callback function one after the other for all hot
+* un-plugged devices, so it may take some time to call
+* .remove() function for subsequent hot un-plugged
+* PCI devices.
+*/
+   ioc->remove_host = 1;
+   }
+
+rearm_timer:
+   if (ioc->hba_hot_unplug_work_q)
+   queue_delayed_work(ioc->hba_hot_unplug_work_q,
+   >hba_hot_unplug_work,
+   msecs_to_jiffies(HBA_HOTUNPLUG_POLLING_INTERVAL));
+   spin_unlock_irqrestore(>hba_hot_unplug_lock, flags);
+}
+
+
 /**
  * mpt3sas_base_start_watchdog - start the fault_reset_work_q
  * @ioc: per adapter object
@@ -730,6 +771,54 @@ mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc)
}
 }
 
+void
+mpt3sas_base_start_hba_unplug_watchdog(struct MPT3SAS_ADAPTER *ioc)
+{
+   unsigned longflags;
+
+   if (ioc->hba_hot_unplug_work_q)
+   return;
+
+   /* Initialize hba hot unplug polling */
+   INIT_DELAYED_WORK(>hba_hot_unplug_work,
+   _base_hba_hot_unplug_work);
+   snprintf(ioc->hba_hot_unplug_work_q_name,
+   sizeof(ioc->hba_hot_unplug_work_q_name), "poll_%s%d_hba_unplug",
+   ioc->driver_name, ioc->id);
+   ioc->hba_hot_unplug_work_q =
+   create_singlethread_workqueue(ioc->hba_hot_unplug_work_q_name);
+   if (!ioc->hba_hot_unplug_work_q) {
+   pr_err(MPT3SAS_FMT "%s: failed (line=%d)\n",
+   ioc->name, __func__, __LINE__);
+   return;
+   }
+
+   spin_lock_irqsave(>hba_hot_unplug_lock, flags);
+   if (ioc->hba_hot_unplug_work_q)
+   queue_delayed_work(ioc->hba_hot_unplug_work_q,
+   >hba_hot_unplug_work,
+   msecs_to_jiffies(HBA_HOTUNPLUG_POLLING_INTERVAL));
+   spin_unlock_irqrestore(>hba_hot_unplug_lock, flags);
+}
+
+void
+mpt3sas_base_stop_hba_unplug_watchdog(struct MPT3SAS_ADAPTER *ioc)
+{
+   unsigned long flags;
+   struct workqueue_struct *wq;
+
+   spin_lock_irqsave(>hba_hot_unplug_lock, flags);
+   wq = ioc->hba_hot_unplug_work_q;
+   ioc->hba_hot_unplug_work_q = NULL;
+   spin_unlock_irqrestore(>hba_hot_unplug_lock, flags);
+
+   if (wq) {
+   if (!cancel_delayed_work_sync(>hba_hot_unplug_work))
+   flush_wo

[Patch v1 6/7] mpt3sas: Fix driver modifying NVRAM/persistent data.

2018-08-30 Thread Suganath Prabu S
* If EEDPTagMode field in manufacturing page11 is set,
unset it. This is needed to fix a hardware bug
in SAS3/SAS2 cards, So, skipping EEDPTagMode changes
in Manufacturing page11 for SAS35 controllers.

* Fix driver modifying NVRAM/persistent data in
Manufacturing page11 along with current copy. Driver should
change only current copy of Manufacturing page11

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c   | 2 +-
 drivers/scsi/mpt3sas/mpt3sas_config.c | 4 
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index a46ded8..92637c5 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -4235,7 +4235,7 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
 * flag unset in NVDATA.
 */
mpt3sas_config_get_manufacturing_pg11(ioc, _reply, >manu_pg11);
-   if (ioc->manu_pg11.EEDPTagMode == 0) {
+   if ((!ioc->is_gen35_ioc) && (ioc->manu_pg11.EEDPTagMode == 0)) {
pr_err("%s: overriding NVDATA EEDPTagMode setting\n",
ioc->name);
ioc->manu_pg11.EEDPTagMode &= ~0x3;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c 
b/drivers/scsi/mpt3sas/mpt3sas_config.c
index 5713a2d..f2a326a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_config.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -676,10 +676,6 @@ mpt3sas_config_set_manufacturing_pg11(struct 
MPT3SAS_ADAPTER *ioc,
r = _config_request(ioc, _request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
sizeof(*config_page));
-   mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
-   r = _config_request(ioc, _request, mpi_reply,
-   MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-   sizeof(*config_page));
  out:
return r;
 }
-- 
1.8.3.1



[Patch v1 0/7] mpt3sas: Hot-Plug Surprise removal support on IOC.

2018-08-30 Thread Suganath Prabu S
Posting below set of patches to support PCIe Hot Plug surprise removal,
and few defect fixes.

This is NOT the normal PCIe Hot Plug support, whereby the user informs the
OS that a hot removal is desired, the OS does an orderly shutdown of the driver
on the device, special hot plug circuitry removes power from the PCIe slot,
then the user can remove the device and replace it
(where orderly bring-up of the device is done).

With a true surprise removal (just removing HBA from a slot)
there is a possibility to get all kinds of PCIe transaction errors,
Below patches addresses those issues and remove HBA without bringing
the system down.

For surprise removal detection, driver does a PCI
read of IOC's vendor field in IOC's PCI configuration space.
If the read value is 0x this indicates that the device
might have hot removed and the device will be removed from driver.

V1 changes:
In Patch 0001 - unlock mutex, if active reset is in progress.

Suganath Prabu S (7):
  mpt3sas: Introduce mpt3sas_base_pci_device_is_unplugged
  mpt3sas: Add HBA hot plug watchdog thread.
  mpt3sas: Seperate out  mpt3sas_wait_for_ioc_to_operational
  mpt3sas: Introdude  _scsih_get_shost_and_ioc.
  mpt3sas: Fix Sync cache command failure during driver  unload.
  mpt3sas: Fix driver modifying NVRAM/persistent data.
  mpt3sas: Bump driver version to 27.100.00.00.

 drivers/scsi/mpt3sas/mpt3sas_base.c  | 248 ++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  17 ++-
 drivers/scsi/mpt3sas/mpt3sas_config.c|  32 +---
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  26 +---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 188 ---
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  82 +++---
 6 files changed, 414 insertions(+), 179 deletions(-)

-- 
1.8.3.1



[Patch v1 3/7] mpt3sas: Seperate out mpt3sas_wait_for_ioc_to_operational

2018-08-30 Thread Suganath Prabu S
Introduce mpt3sas_wait_for_ioc_to_operational.

This section of code "wait for IOC to be operational"
is used in many places across the driver,
and hence moved this section of code in to the function
"mpt3sas_wait_for_ioc_to_operational".

Also added HBA hot unplug checks, and this returns with
error code EFAULT, if it detects HBA is hot unplugged
or IOC is not in operational state.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 92 +++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  4 ++
 drivers/scsi/mpt3sas/mpt3sas_config.c| 28 +++---
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   | 26 ++---
 drivers/scsi/mpt3sas/mpt3sas_transport.c | 75 +-
 5 files changed, 81 insertions(+), 144 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 6c8a30f..a46ded8 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -5289,6 +5289,53 @@ _base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 
reset_type, int timeout)
 }
 
 /**
+ * mpt3sas_wait_for_ioc_to_operational - IOC's operational
+ * state and HBA hot unplug status are checked here.
+ * @ioc: per adapter object
+ * @wait_count: timeout in seconds
+ *
+ * Return:  Returns EFAULT, if HBA is hot unplugged or IOC is
+ * not in operational state, within the wait_count.
+ * And returns 0, If not hot unplugged Or ioc is in
+ * operational state.
+ */
+
+int
+mpt3sas_wait_for_ioc_to_operational(struct MPT3SAS_ADAPTER *ioc,
+   int wait_count)
+{
+   int wait_state_count = 0;
+   u32 ioc_state;
+
+   if (mpt3sas_base_pci_device_is_unplugged(ioc))
+   return -EFAULT;
+
+   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+   while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+
+   if (mpt3sas_base_pci_device_is_unplugged(ioc))
+   return -EFAULT;
+
+   if (wait_state_count++ == wait_count) {
+   pr_err(MPT3SAS_FMT
+   "%s: failed due to ioc not operational\n",
+   ioc->name, __func__);
+   return -EFAULT;
+   }
+   ssleep(1);
+   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
+   pr_info(MPT3SAS_FMT "%s: waiting for "
+   "operational state(count=%d)\n", ioc->name,
+   __func__, wait_state_count);
+   }
+   if (wait_state_count)
+   pr_info(MPT3SAS_FMT "%s: ioc is operational\n",
+   ioc->name, __func__);
+
+   return 0;
+}
+
+/**
  * _base_handshake_req_reply_wait - send request thru doorbell interface
  * @ioc: per adapter object
  * @request_bytes: request length
@@ -5429,11 +5476,9 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER 
*ioc,
Mpi2SasIoUnitControlRequest_t *mpi_request)
 {
u16 smid;
-   u32 ioc_state;
u8 issue_reset = 0;
int rc;
void *request;
-   u16 wait_state_count;
 
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
@@ -5447,22 +5492,10 @@ mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER 
*ioc,
goto out;
}
 
-   wait_state_count = 0;
-   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
-   while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
-   if (wait_state_count++ == 10) {
-   pr_err(MPT3SAS_FMT
-   "%s: failed due to ioc not operational\n",
-   ioc->name, __func__);
-   rc = -EFAULT;
-   goto out;
-   }
-   ssleep(1);
-   ioc_state = mpt3sas_base_get_iocstate(ioc, 1);
-   pr_info(MPT3SAS_FMT
-   "%s: waiting for operational state(count=%d)\n",
-   ioc->name, __func__, wait_state_count);
-   }
+   rc = mpt3sas_wait_for_ioc_to_operational(ioc,
+   IOC_OPERATIONAL_WAIT_COUNT);
+   if (rc)
+   goto out;
 
smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
if (!smid) {
@@ -5529,11 +5562,9 @@ mpt3sas_base_scsi_enclosure_processor(struct 
MPT3SAS_ADAPTER *ioc,
Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request)
 {
u16 smid;
-   u32 ioc_state;
u8 issue_reset = 0;
int rc;
void *request;
-   u16 wait_state_count;
 
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
@@ -5547,23 +5578,10 @@ mpt3sas_base_scsi_enclosure_processor(struct 
MPT3SAS_ADAPTER *ioc,
goto out;
}
 
-   wait_state_count = 0;
-   ioc_state = mpt3sas_base_

[Patch v1 7/7] mpt3sas: Bump driver version to 27.100.00.00.

2018-08-30 Thread Suganath Prabu S
Modify driver version to 27.100.00.00
(which is equivalent to PH8 OOB driver)

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 8b2cc66..7f29b0e 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -74,8 +74,8 @@
 #define MPT3SAS_DRIVER_NAME"mpt3sas"
 #define MPT3SAS_AUTHOR "Avago Technologies "
 #define MPT3SAS_DESCRIPTION"LSI MPT Fusion SAS 3.0 Device Driver"
-#define MPT3SAS_DRIVER_VERSION "26.100.00.00"
-#define MPT3SAS_MAJOR_VERSION  26
+#define MPT3SAS_DRIVER_VERSION "27.100.00.00"
+#define MPT3SAS_MAJOR_VERSION  27
 #define MPT3SAS_MINOR_VERSION  100
 #define MPT3SAS_BUILD_VERSION  0
 #define MPT3SAS_RELEASE_VERSION00
-- 
1.8.3.1



[Patch v1 4/7] mpt3sas: Introdude _scsih_get_shost_and_ioc.

2018-08-30 Thread Suganath Prabu S
The code for getting shost and IOC is redundant so
moved that to function "scsih_get_shost_and_ioc".
Also checks for NULL are added to IOC and shost.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 98 ++--
 1 file changed, 82 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 7e0c4ec..2c7f44c 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -9809,6 +9809,35 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
 }
 
 /**
+ * _scsih_get_shost_and_ioc - get shost and ioc
+ * and verify whether they are NULL or not
+ * @pdev: PCI device struct
+ * @shost: address of scsi host pointer
+ * @ioc: address of HBA adapter pointer
+ *
+ * Return zero if *shost and *ioc are not NULL otherwise return error number.
+ */
+static int
+_scsih_get_shost_and_ioc(struct pci_dev *pdev,
+   struct Scsi_Host **shost, struct MPT3SAS_ADAPTER **ioc)
+{
+   *shost = pci_get_drvdata(pdev);
+   if (*shost == NULL) {
+   dev_err(>dev, "pdev's driver data is null\n");
+   return -ENXIO;
+   }
+
+   *ioc = shost_priv(*shost);
+   if (*ioc == NULL) {
+   dev_err(>dev, "shost's private data is null\n");
+   return -ENXIO;
+   }
+
+   return 0;
+}
+
+
+/**
  * scsih_remove - detach and remove add host
  * @pdev: PCI device struct
  *
@@ -9816,8 +9845,8 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
  */
 static void scsih_remove(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
struct _sas_port *mpt3sas_port, *next_port;
struct _raid_device *raid_device, *next;
struct MPT3SAS_TARGET *sas_target_priv_data;
@@ -9825,6 +9854,10 @@ static void scsih_remove(struct pci_dev *pdev)
struct workqueue_struct *wq;
unsigned long flags;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "unable to remove device\n");
+   return;
+   }
ioc->remove_host = 1;
 
mpt3sas_wait_for_commands_to_complete(ioc);
@@ -9900,11 +9933,16 @@ static void scsih_remove(struct pci_dev *pdev)
 static void
 scsih_shutdown(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
struct workqueue_struct *wq;
unsigned long flags;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "unable to shutdown device\n");
+   return;
+   }
+
ioc->remove_host = 1;
 
mpt3sas_wait_for_commands_to_complete(ioc);
@@ -10721,10 +10759,16 @@ out_add_shost_fail:
 static int
 scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
pci_power_t device_state;
+   int rc;
 
+   rc = _scsih_get_shost_and_ioc(pdev, , );
+   if (rc) {
+   dev_err(>dev, "unable to suspend device\n");
+   return rc;
+   }
mpt3sas_base_stop_watchdog(ioc);
mpt3sas_base_stop_hba_unplug_watchdog(ioc);
flush_scheduled_work();
@@ -10749,11 +10793,17 @@ scsih_suspend(struct pci_dev *pdev, pm_message_t 
state)
 static int
 scsih_resume(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
pci_power_t device_state = pdev->current_state;
int r;
 
+   r = _scsih_get_shost_and_ioc(pdev, , );
+   if (r) {
+   dev_err(>dev, "unable to resume device\n");
+   return r;
+   }
+
pr_info(MPT3SAS_FMT
"pdev=0x%p, slot=%s, previous operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
@@ -10786,9 +10836,13 @@ scsih_resume(struct pci_dev *pdev)
 static pci_ers_result_t
 scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "device unavailable\n");
+   return PCI_ERS_RESULT_DI

[PATCH 5/7] mpt3sas: Fix Sync cache command failure during driver unload.

2018-08-29 Thread Suganath Prabu S
This is to fix Sync cache and start stop command
 failures with DID_NO_CONNECT during driver unload.

1) Release drives first from SML, then remove internally
in driver.
2) And allow sync cache and Start stop commands to firmware,
even when remove_host flag is set.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 41 ++--
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  7 --
 2 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 2c7f44c..f796808 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -3806,6 +3806,43 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 
smid, u8 msix_index,
return _scsih_check_for_pending_tm(ioc, smid);
 }
 
+/** _scsih_allow_scmd_to_device - check whether scmd needs to
+ *  issue to IOC or not.
+ * @ioc: per adapter object
+ * @scmd: pointer to scsi command object
+ *
+ * Returns true if scmd can be issued to IOC otherwise returns false.
+ */
+inline bool _scsih_allow_scmd_to_device(struct MPT3SAS_ADAPTER *ioc,
+   struct scsi_cmnd *scmd)
+{
+
+   if (ioc->pci_error_recovery)
+   return false;
+
+   if (ioc->hba_mpi_version_belonged == MPI2_VERSION) {
+   if (ioc->remove_host)
+   return false;
+
+   return true;
+   }
+
+
+   if (ioc->remove_host) {
+   if (mpt3sas_base_pci_device_is_unplugged(ioc))
+   return false;
+
+   switch (scmd->cmnd[0]) {
+   case SYNCHRONIZE_CACHE:
+   case START_STOP:
+   return true;
+   default:
+   return false;
+   }
+   }
+
+   return true;
+}
 
 /**
  * _scsih_sas_control_complete - completion routine
@@ -4640,7 +4677,7 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd 
*scmd)
return 0;
}
 
-   if (ioc->pci_error_recovery || ioc->remove_host) {
+   if (!(_scsih_allow_scmd_to_device(ioc, scmd))) {
scmd->result = DID_NO_CONNECT << 16;
scmd->scsi_done(scmd);
return 0;
@@ -9876,6 +9913,7 @@ static void scsih_remove(struct pci_dev *pdev)
 
/* release all the volumes */
_scsih_ir_shutdown(ioc);
+   sas_remove_host(shost);
list_for_each_entry_safe(raid_device, next, >raid_device_list,
list) {
if (raid_device->starget) {
@@ -9918,7 +9956,6 @@ static void scsih_remove(struct pci_dev *pdev)
ioc->sas_hba.num_phys = 0;
}
 
-   sas_remove_host(shost);
mpt3sas_base_detach(ioc);
spin_lock(_lock);
list_del(>list);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_transport.c 
b/drivers/scsi/mpt3sas/mpt3sas_transport.c
index b10d73e..742da74 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_transport.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_transport.c
@@ -817,10 +817,13 @@ mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER 
*ioc, u64 sas_address,
mpt3sas_port->remote_identify.sas_address,
mpt3sas_phy->phy_id);
mpt3sas_phy->phy_belongs_to_port = 0;
-   sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy);
+   if (!ioc->remove_host)
+   sas_port_delete_phy(mpt3sas_port->port,
+   mpt3sas_phy->phy);
list_del(_phy->port_siblings);
}
-   sas_port_delete(mpt3sas_port->port);
+   if (!ioc->remove_host)
+   sas_port_delete(mpt3sas_port->port);
kfree(mpt3sas_port);
 }
 
-- 
1.8.3.1



[PATCH 0/7] mpt3sas: Hot-Plug Surprise removal support on IOC.

2018-08-29 Thread Suganath Prabu S
Posting below set of patches to support PCIe Hot Plug surprise removal,
and few defect fixes.

This is NOT the normal PCIe Hot Plug support, whereby the user informs the
OS that a hot removal is desired, the OS does an orderly shutdown of the driver
on the device, special hot plug circuitry removes power from the PCIe slot,
then the user can remove the device and replace it
(where orderly bring-up of the device is done).

With a true surprise removal (just removing HBA from a slot)
there is a possibility to get all kinds of PCIe transaction errors,
Below patches addresses those issues and remove HBA without bringing
the system down.

For surprise removal detection, driver does a PCI
read of IOC's vendor field in IOC's PCI configuration space.
If the read value is 0x this indicates that the device
might have hot removed and the device will be removed from driver.

Suganath Prabu S (7):
  mpt3sas: Introduce mpt3sas_base_pci_device_is_unplugged
  mpt3sas: Add HBA hot plug watchdog thread.
  mpt3sas: Seperate out  mpt3sas_wait_for_ioc_to_operational
  mpt3sas: Introdude  _scsih_get_shost_and_ioc.
  mpt3sas: Fix Sync cache command failure during driver  unload.
  mpt3sas: Fix driver modifying NVRAM/persistent data.
  mpt3sas: Bump driver version to 27.100.00.00.

 drivers/scsi/mpt3sas/mpt3sas_base.c  | 247 ++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  17 ++-
 drivers/scsi/mpt3sas/mpt3sas_config.c|  32 +---
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  26 +---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 188 ---
 drivers/scsi/mpt3sas/mpt3sas_transport.c |  82 +++---
 6 files changed, 413 insertions(+), 179 deletions(-)

-- 
1.8.3.1



[PATCH 6/7] mpt3sas: Fix driver modifying NVRAM/persistent data.

2018-08-29 Thread Suganath Prabu S
* If EEDPTagMode field in manufacturing page11 is set,
unset it. This is needed to fix a hardware bug
in SAS3/SAS2 cards, So, skipping EEDPTagMode changes
in Manufacturing page11 for SAS35 controllers.

* Fix driver modifying NVRAM/persistent data in
Manufacturing page11 along with current copy. Driver should
change only current copy of Manufacturing page11.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c   | 2 +-
 drivers/scsi/mpt3sas/mpt3sas_config.c | 4 
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index bebc2b0..732d749 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -4235,7 +4235,7 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
 * flag unset in NVDATA.
 */
mpt3sas_config_get_manufacturing_pg11(ioc, _reply, >manu_pg11);
-   if (ioc->manu_pg11.EEDPTagMode == 0) {
+   if ((!ioc->is_gen35_ioc) && (ioc->manu_pg11.EEDPTagMode == 0)) {
pr_err("%s: overriding NVDATA EEDPTagMode setting\n",
ioc->name);
ioc->manu_pg11.EEDPTagMode &= ~0x3;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c 
b/drivers/scsi/mpt3sas/mpt3sas_config.c
index 5713a2d..f2a326a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_config.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -676,10 +676,6 @@ mpt3sas_config_set_manufacturing_pg11(struct 
MPT3SAS_ADAPTER *ioc,
r = _config_request(ioc, _request, mpi_reply,
MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
sizeof(*config_page));
-   mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM;
-   r = _config_request(ioc, _request, mpi_reply,
-   MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page,
-   sizeof(*config_page));
  out:
return r;
 }
-- 
1.8.3.1



[PATCH 1/7] mpt3sas: Introduce mpt3sas_base_pci_device_is_unplugged

2018-08-29 Thread Suganath Prabu S
* Driver does a PCIe read to check whether HBA is hot unplugged or
not. If the returned vendor ID is 0x/0x0, then this
indicates that the device might have been hot removed and the device
will be removed from driver.

* In the PCI device remove() callback function, flush out all
the outstanding IOs with 'DID_NO_CONNECT' before removing the drives
attached to the HBA.

* In the TM abort() callback function return the scmd with
"DID_NO_CONNECT" status and free the smid, if driver detects that
HBA is hot unplugged.

* In the hard reset flush out all the outstanding IOs even if diag reset
fails and also if driver detects that HBA is hot unplugged.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 61 +++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  3 +-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 42 ++---
 3 files changed, 99 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 836b2e1..7ef8daf 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -61,7 +61,7 @@
 #include 
 #include /* To get host page size per arch */
 #include 
-
+#include <../drivers/pci/pci.h>
 
 #include "mpt3sas_base.h"
 
@@ -543,6 +543,44 @@ static int mpt3sas_remove_dead_ioc_func(void *arg)
 }
 
 /**
+ * mpt3sas_base_pci_device_is_unplugged - Check whether HBA device is
+ *  hot unplugged or not
+ * @ioc: per adapter object
+ *
+ * Return 1 if the HBA device is hot unplugged else return 0.
+ */
+u8
+mpt3sas_base_pci_device_is_unplugged(struct MPT3SAS_ADAPTER *ioc)
+{
+   struct pci_dev *pdev = ioc->pdev;
+   int devfn = pdev->devfn;
+   u32 l;
+
+   if (pci_bus_read_dev_vendor_id(pdev->bus, devfn, , 0))
+   return 0;
+
+   return 1;
+}
+
+/**
+ * mpt3sas_base_pci_device_is_available - check whether pci device is
+ * available for any transactions with FW
+ *
+ * @ioc: per adapter object
+ *
+ * Return 1 if pci device state is up and running else return 0.
+ */
+u8
+mpt3sas_base_pci_device_is_available(struct MPT3SAS_ADAPTER *ioc)
+{
+   if (ioc->pci_error_recovery ||
+   mpt3sas_base_pci_device_is_unplugged(ioc))
+   return 0;
+
+   return 1;
+}
+
+/**
  * _base_fault_reset_work - workq handling ioc fault conditions
  * @work: input argument, used to derive ioc
  *
@@ -6853,6 +6891,14 @@ mpt3sas_wait_for_commands_to_complete(struct 
MPT3SAS_ADAPTER *ioc)
 
ioc->pending_io_count = 0;
 
+   if (!mpt3sas_base_pci_device_is_available(ioc)) {
+   pr_err(MPT3SAS_FMT
+   "%s: pci error recovery reset or"
+   " pci device unplug occurred\n",
+   ioc->name, __func__);
+   return;
+   }
+
ioc_state = mpt3sas_base_get_iocstate(ioc, 0);
if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
return;
@@ -6899,6 +6945,19 @@ mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER 
*ioc,
/* wait for an active reset in progress to complete */
mutex_lock(>reset_in_progress_mutex);
 
+   if (!mpt3sas_base_pci_device_is_available(ioc)) {
+   pr_err(MPT3SAS_FMT
+   "%s: pci error recovery reset or"
+   " pci device unplug occurred\n",
+   ioc->name, __func__);
+   if (mpt3sas_base_pci_device_is_unplugged(ioc))
+   ioc->schedule_dead_ioc_flush_running_cmds(ioc);
+   r = 0;
+   goto out_unlocked;
+   }
+
+   mpt3sas_halt_firmware(ioc);
+
spin_lock_irqsave(>ioc_reset_in_progress_lock, flags);
ioc->shost_recovery = 1;
spin_unlock_irqrestore(>ioc_reset_in_progress_lock, flags);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 96dc15e..8ee3ba7 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1474,7 +1474,8 @@ void mpt3sas_base_update_missing_delay(struct 
MPT3SAS_ADAPTER *ioc,
u16 device_missing_delay, u8 io_missing_delay);
 
 int mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc);
-
+u8 mpt3sas_base_pci_device_is_unplugged(struct MPT3SAS_ADAPTER *ioc);
+u8 mpt3sas_base_pci_device_is_available(struct MPT3SAS_ADAPTER *ioc);
 void
 mpt3sas_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc);
 
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 8dd3d67..9da 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2846,9 +2846,19 @@ scsih_abort(struct scsi_cmnd *scmd)
"attempting task abort! scmd(%p)\n&quo

[PATCH 7/7] mpt3sas: Bump driver version to 27.100.00.00.

2018-08-29 Thread Suganath Prabu S
Modify driver version to 27.100.00.00
(which is equivalent to PH8 OOB driver)

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 8b2cc66..7f29b0e 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -74,8 +74,8 @@
 #define MPT3SAS_DRIVER_NAME"mpt3sas"
 #define MPT3SAS_AUTHOR "Avago Technologies "
 #define MPT3SAS_DESCRIPTION"LSI MPT Fusion SAS 3.0 Device Driver"
-#define MPT3SAS_DRIVER_VERSION "26.100.00.00"
-#define MPT3SAS_MAJOR_VERSION  26
+#define MPT3SAS_DRIVER_VERSION "27.100.00.00"
+#define MPT3SAS_MAJOR_VERSION  27
 #define MPT3SAS_MINOR_VERSION  100
 #define MPT3SAS_BUILD_VERSION  0
 #define MPT3SAS_RELEASE_VERSION00
-- 
1.8.3.1



[PATCH 2/7] mpt3sas: Add HBA hot plug watchdog thread.

2018-08-29 Thread Suganath Prabu S
During driver load create a hba hot unplug watchdog thread
"_base_hba_hot_unplug_work".

This will poll whether HBA device is unplugged or not by reading IOC's
vendor field in IOC's PCI configuration space for every one second.

If hot unplug is detected, it terminates all the outstanding IOs
and hence kernels's PCIe hotplug module (i.e. pciehp) will clear the
instances of the hot unplugged PCI device.

Below functions starts and stops the watchdog.
mpt3sas_base_start_hba_unplug_watchdog
mpt3sas_base_stop_hba_unplug_watchdog
Watchdog thread starts immediately once IOC becomes operational.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 92 +++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  6 +++
 drivers/scsi/mpt3sas/mpt3sas_scsih.c |  7 +++
 3 files changed, 104 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 7ef8daf..97e9939 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -69,6 +69,7 @@ static MPT_CALLBACK   mpt_callbacks[MPT_MAX_CALLBACKS];
 
 
 #define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
+#define HBA_HOTUNPLUG_POLLING_INTERVAL 1000 /* in milliseconds */
 
  /* maximum controller queue depth */
 #define MAX_HBA_QUEUE_DEPTH3
@@ -672,6 +673,46 @@ _base_fault_reset_work(struct work_struct *work)
spin_unlock_irqrestore(>ioc_reset_in_progress_lock, flags);
 }
 
+static void
+_base_hba_hot_unplug_work(struct work_struct *work)
+{
+   struct MPT3SAS_ADAPTER *ioc =
+   container_of(work, struct MPT3SAS_ADAPTER,
+   hba_hot_unplug_work.work);
+   unsigned longflags;
+
+   spin_lock_irqsave(>hba_hot_unplug_lock, flags);
+   if (ioc->shost_recovery || ioc->pci_error_recovery)
+   goto rearm_timer;
+
+   if (mpt3sas_base_pci_device_is_unplugged(ioc)) {
+   if (ioc->remove_host) {
+   pr_err(MPT3SAS_FMT
+   "The IOC seems hot unplugged and the driver is "
+   "waiting for pciehp module to remove the PCIe "
+   "device instance associated with IOC!!!\n",
+   ioc->name);
+   goto rearm_timer;
+   }
+
+   /* Set remove_host flag here, since kernel will invoke driver's
+* .remove() callback function one after the other for all hot
+* un-plugged devices, so it may take some time to call
+* .remove() function for subsequent hot un-plugged
+* PCI devices.
+*/
+   ioc->remove_host = 1;
+   }
+
+rearm_timer:
+   if (ioc->hba_hot_unplug_work_q)
+   queue_delayed_work(ioc->hba_hot_unplug_work_q,
+   >hba_hot_unplug_work,
+   msecs_to_jiffies(HBA_HOTUNPLUG_POLLING_INTERVAL));
+   spin_unlock_irqrestore(>hba_hot_unplug_lock, flags);
+}
+
+
 /**
  * mpt3sas_base_start_watchdog - start the fault_reset_work_q
  * @ioc: per adapter object
@@ -730,6 +771,54 @@ mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc)
}
 }
 
+void
+mpt3sas_base_start_hba_unplug_watchdog(struct MPT3SAS_ADAPTER *ioc)
+{
+   unsigned longflags;
+
+   if (ioc->hba_hot_unplug_work_q)
+   return;
+
+   /* Initialize hba hot unplug polling */
+   INIT_DELAYED_WORK(>hba_hot_unplug_work,
+   _base_hba_hot_unplug_work);
+   snprintf(ioc->hba_hot_unplug_work_q_name,
+   sizeof(ioc->hba_hot_unplug_work_q_name), "poll_%s%d_hba_unplug",
+   ioc->driver_name, ioc->id);
+   ioc->hba_hot_unplug_work_q =
+   create_singlethread_workqueue(ioc->hba_hot_unplug_work_q_name);
+   if (!ioc->hba_hot_unplug_work_q) {
+   pr_err(MPT3SAS_FMT "%s: failed (line=%d)\n",
+   ioc->name, __func__, __LINE__);
+   return;
+   }
+
+   spin_lock_irqsave(>hba_hot_unplug_lock, flags);
+   if (ioc->hba_hot_unplug_work_q)
+   queue_delayed_work(ioc->hba_hot_unplug_work_q,
+   >hba_hot_unplug_work,
+   msecs_to_jiffies(HBA_HOTUNPLUG_POLLING_INTERVAL));
+   spin_unlock_irqrestore(>hba_hot_unplug_lock, flags);
+}
+
+void
+mpt3sas_base_stop_hba_unplug_watchdog(struct MPT3SAS_ADAPTER *ioc)
+{
+   unsigned long flags;
+   struct workqueue_struct *wq;
+
+   spin_lock_irqsave(>hba_hot_unplug_lock, flags);
+   wq = ioc->hba_hot_unplug_work_q;
+   ioc->hba_hot_unplug_work_q = NULL;
+   spin_unlock_irqrestore(>hba_hot_unplug_lock, flags);
+
+   if (wq) {
+   if (!cancel_delayed_work_sync(>hba_hot_unplug_work))
+   flush_wo

[PATCH 4/7] mpt3sas: Introdude _scsih_get_shost_and_ioc.

2018-08-29 Thread Suganath Prabu S
The code for getting shost and IOC is redundant so
moved that to function "scsih_get_shost_and_ioc".
Also checks for NULL are added to IOC and shost.

Signed-off-by: Suganath Prabu S 
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 98 ++--
 1 file changed, 82 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 7e0c4ec..2c7f44c 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -9809,6 +9809,35 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
 }
 
 /**
+ * _scsih_get_shost_and_ioc - get shost and ioc
+ * and verify whether they are NULL or not
+ * @pdev: PCI device struct
+ * @shost: address of scsi host pointer
+ * @ioc: address of HBA adapter pointer
+ *
+ * Return zero if *shost and *ioc are not NULL otherwise return error number.
+ */
+static int
+_scsih_get_shost_and_ioc(struct pci_dev *pdev,
+   struct Scsi_Host **shost, struct MPT3SAS_ADAPTER **ioc)
+{
+   *shost = pci_get_drvdata(pdev);
+   if (*shost == NULL) {
+   dev_err(>dev, "pdev's driver data is null\n");
+   return -ENXIO;
+   }
+
+   *ioc = shost_priv(*shost);
+   if (*ioc == NULL) {
+   dev_err(>dev, "shost's private data is null\n");
+   return -ENXIO;
+   }
+
+   return 0;
+}
+
+
+/**
  * scsih_remove - detach and remove add host
  * @pdev: PCI device struct
  *
@@ -9816,8 +9845,8 @@ _scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc)
  */
 static void scsih_remove(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
struct _sas_port *mpt3sas_port, *next_port;
struct _raid_device *raid_device, *next;
struct MPT3SAS_TARGET *sas_target_priv_data;
@@ -9825,6 +9854,10 @@ static void scsih_remove(struct pci_dev *pdev)
struct workqueue_struct *wq;
unsigned long flags;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "unable to remove device\n");
+   return;
+   }
ioc->remove_host = 1;
 
mpt3sas_wait_for_commands_to_complete(ioc);
@@ -9900,11 +9933,16 @@ static void scsih_remove(struct pci_dev *pdev)
 static void
 scsih_shutdown(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
struct workqueue_struct *wq;
unsigned long flags;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "unable to shutdown device\n");
+   return;
+   }
+
ioc->remove_host = 1;
 
mpt3sas_wait_for_commands_to_complete(ioc);
@@ -10721,10 +10759,16 @@ out_add_shost_fail:
 static int
 scsih_suspend(struct pci_dev *pdev, pm_message_t state)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
pci_power_t device_state;
+   int rc;
 
+   rc = _scsih_get_shost_and_ioc(pdev, , );
+   if (rc) {
+   dev_err(>dev, "unable to suspend device\n");
+   return rc;
+   }
mpt3sas_base_stop_watchdog(ioc);
mpt3sas_base_stop_hba_unplug_watchdog(ioc);
flush_scheduled_work();
@@ -10749,11 +10793,17 @@ scsih_suspend(struct pci_dev *pdev, pm_message_t 
state)
 static int
 scsih_resume(struct pci_dev *pdev)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
pci_power_t device_state = pdev->current_state;
int r;
 
+   r = _scsih_get_shost_and_ioc(pdev, , );
+   if (r) {
+   dev_err(>dev, "unable to resume device\n");
+   return r;
+   }
+
pr_info(MPT3SAS_FMT
"pdev=0x%p, slot=%s, previous operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
@@ -10786,9 +10836,13 @@ scsih_resume(struct pci_dev *pdev)
 static pci_ers_result_t
 scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
 {
-   struct Scsi_Host *shost = pci_get_drvdata(pdev);
-   struct MPT3SAS_ADAPTER *ioc = shost_priv(shost);
+   struct Scsi_Host *shost = NULL;
+   struct MPT3SAS_ADAPTER *ioc = NULL;
 
+   if (_scsih_get_shost_and_ioc(pdev, , )) {
+   dev_err(>dev, "device unavailable\n");
+   return PCI_ERS_RESULT_DI

Re: mpt3sas heavy I/O load causes kernel BUG at block/blk-core.c:2695

2018-06-07 Thread Suganath Prabu Subramani
Hi Douglas,

Can you check if this patch is already part of driver, If not please
try with below patch.
This patch is to fix the completion of abort before the IO completion.
With this, driver will process IO's reply first followed by TM.

authorSuganath prabu Subramani
2016-01-28 12:07:06 +0530
committerMartin K. Petersen 2016-02-23
21:27:02 -0500
commit03d1fb3a65783979f23bd58b5a0387e6992d9e26 (patch)
tree6aca275e2ebe7fbcd5fac1654cedd8f56d0947d0 /drivers/scsi/mpt3sas
parent5c739b6157bd090942e5847ddd12bfb99cd4240d (diff)
downloadlinux-03d1fb3a65783979f23bd58b5a0387e6992d9e26.tar.gz

mpt3sas: Fix for Asynchronous completion of timedout IO and task abort
of timedout IO.
Track msix of each IO and use the same msix for issuing abort to timed
out IO. With this driver will process IO's reply first followed by TM.
Signed-off-by: Suganath prabu Subramani
 Signed-off-by: Chaitra P B
 Reviewed-by: Tomas Henzl
 Signed-off-by: Martin K. Petersen



Thanks,
Suganath Prabu S

On Wed, Jun 6, 2018 at 7:50 PM, Douglas Miller
 wrote:
> Running a heavy I/O load on multipath/dual-ported SSD disks attached to a
> SAS3008 adapter (mpt3sas driver), we are seeing I/Os get aborted and tasks
> stuck in blk_complete_request() and this sometimes results in hitting a
> BUG_ON in blk_start_request(). It would appear that we are seeing two
> completions performed on an I/O, and the second completion is racing with
> re-use of the request for a new I/O.
>
> I saw this upstream commit:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v4.17-rc3=9961c9bbf2b43acaaf030a0fbabc9954d937ad8c
>
> which addresses the case where the normal completion occurs before the abort
> completion. But the situation I am seeing appears to be that the abort
> completion occurs before the normal completion (due to tasks getting delayed
> in blk_complete_request()). I don't find any commit to fix this second case.
>
> Of course, tasks being delayed like this is a concern, and is being worked
> separately. But it seems that the alternate double-completion case is being
> ignored here.
>
> Does everyone concur that this second case needs to be addressed? Is there a
> proposed fix?
>
> Thanks,
>
> Doug
>
> FYI, system is a Power9 running RHEL-ALT 7.5, two SAS3008 adapters connected
> to an IBM EXP24SX SAS Storage Enclosure with 24 HUSMM8040ASS201 drives. FIO
> was being used to drive the I/O load.
>
>


Re: mpt3sas: sleeping function called from invalid context

2018-03-13 Thread Suganath Prabu Subramani
Hi Bart,

We have root caused the issue and it is same as you mentioned.
"_scsih_get_enclosure_logicalid_chassis_slot()" is called with interrupts
disabled and this function
"_scsih_get_enclosure_logicalid_chassis_slot" again calls
_config_request(), with mutex_lock().

We have patch ready along with few other change and we ll be posting
it by tomorrow after covering BST.

Thanks,
Suganath Prabu S

On Mon, Mar 12, 2018 at 11:53 PM, Bart Van Assche
<bart.vanass...@wdc.com> wrote:
> Hello,
>
> For the first I/O request after boot that is sent to a disk attached to an
> mpt3sas adapter I see the below complaint appearing in the kernel log. This
> occurs at least with kernels v4.16-rc4 and v4.16-rc5.
>
> What I see in the mpt3sas source code is that
> _scsih_get_enclosure_logicalid_chassis_slot() is called with interrupts
> disabled and also that a function called by that function, namely
> _config_request(), calls mutex_lock().
>
> Can someone who is more familiar than I with the mpt3sas adapter have a look
> at this and propose a fix?
>
> Thanks,
>
> Bart.
>
> BUG: sleeping function called from invalid context at 
> kernel/locking/mutex.c:747
> in_atomic(): 1, irqs_disabled(): 1, pid: 2389, name: kworker/u64:1
> INFO: lockdep is turned off.
> irq event stamp: 278
> hardirqs last  enabled at (277): [<32c577ec>] 
> _raw_spin_unlock_irq+0x24/0x50
> hardirqs last disabled at (278): [<6082e2fa>] __schedule+0x120/0x1010
> softirqs last  enabled at (0): [<8c2eb285>] 
> copy_process.part.45+0x930/0x3470
> softirqs last disabled at (0): [<  (null)>]   (null)
> Preemption disabled at:
> [<>]   (null)
> CPU: 3 PID: 2389 Comm: kworker/u64:1 Tainted: GW
> 4.16.0-rc5-dbg+ #1
> Workqueue: poll_mpt3sas0_statu _base_fault_reset_work [mpt3sas]
> Call Trace:
> dump_stack+0x67/0x90
> ___might_sleep+0x1da/0x2c0
> __mutex_lock+0xb9/0xbb0
> _config_request.constprop.5+0xa3/0xe70 [mpt3sas]
> mpt3sas_config_get_enclosure_pg0+0xb3/0x110 [mpt3sas]
> _scsih_get_enclosure_logicalid_chassis_slot+0xf8/0x160 [mpt3sas]
> mpt3sas_scsih_reset_handler+0x3f6/0xb30 [mpt3sas]
> mpt3sas_base_hard_reset_handler+0x49a/0x7c0 [mpt3sas]
> _base_fault_reset_work+0x1bb/0x260 [mpt3sas]
> process_one_work+0x441/0xa50
> worker_thread+0x76/0x6c0
> kthread+0x1b2/0x1d0
> ret_from_fork+0x24/0x30
>


Re: [PATCH 5/6] mpt3sas: Introduce function to clone mpi request.

2018-02-23 Thread Suganath Prabu Subramani
Hi tomas,
We have sent V1 version of patches on 7th of Feb. Please review.

Thanks,
Suganath Prabu S

On Mon, Jan 22, 2018 at 8:08 PM, Tomas Henzl <the...@redhat.com> wrote:
> On 01/19/2018 01:37 PM, Suganath Prabu S wrote:
>> 1) Added function _base_clone_mpi_to_sys_mem to clone
>> MPI request into system BAR0 mapped region.
>>
>> 2) Seperate out MPI Endpoint IO submissions to function
>> _base_put_smid_mpi_ep_scsi_io.
>>
>> 3) MPI EP requests are submitted in two 32 bit MMIO writes.
>> from _base_mpi_ep_writeq.
>>
>> Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
>> ---
>>  drivers/scsi/mpt3sas/mpt3sas_base.c | 131 
>> +---
>>  1 file changed, 123 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
>> b/drivers/scsi/mpt3sas/mpt3sas_base.c
>> index 40a1806..0248058 100644
>> --- a/drivers/scsi/mpt3sas/mpt3sas_base.c
>> +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
>> @@ -126,6 +126,24 @@ module_param_call(mpt3sas_fwfault_debug, 
>> _scsih_set_fwfault_debug,
>>   param_get_int, _fwfault_debug, 0644);
>>
>>  /**
>> + * _base_clone_mpi_to_sys_mem - Writes/copies MPI frames
>> + *   to system/BAR0 region.
>> + *
>> + * @dst_iomem: Pointer to the destinaltion location in BAR0 space.
>> + * @src: Pointer to the Source data.
>> + * @size: Size of data to be copied.
>> + */
>> +static void
>> +_base_clone_mpi_to_sys_mem(void *dst_iomem, void *src, u32 size)
>> +{
>> + int i;
>> + __le32 *src_virt_mem = (__le32 *)src;
>> +
>> + for (i = 0; i < size/4; i++)
>> + writel(cpu_to_le32(src_virt_mem[i]), dst_iomem + (i * 4));
>> +}
>> +
>> +/**
>>   * _base_clone_to_sys_mem - Writes/copies data to system/BAR0 region
>>   *
>>   * @dst_iomem: Pointer to the destinaltion location in BAR0 space.
>> @@ -3265,6 +3283,29 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, 
>> u16 smid)
>>  }
>>
>>  /**
>> + * _base_mpi_ep_writeq - 32 bit write to MMIO
>> + * @b: data payload
>> + * @addr: address in MMIO space
>> + * @writeq_lock: spin lock
>> + *
>> + * This special handling for MPI EP to take care of 32 bit
>> + * environment where its not quarenteed to send the entire word
>> + * in one transfer.
>
> Hi Suganath,
> so is a single writeq possible ? There already is a _base_writeq function
> which seems to be identical to _base_mpi_ep_writeq.
> Also you may want to add a mmiowb() call.
> tomash
>
>> + */
>> +static inline void
>> +_base_mpi_ep_writeq(__u64 b, volatile void __iomem *addr,
>> + spinlock_t *writeq_lock)
>> +{
>> + unsigned long flags;
>> + __u64 data_out = cpu_to_le64(b);
>> +
>> + spin_lock_irqsave(writeq_lock, flags);
>> + writel((u32)(data_out), addr);
>> + writel((u32)(data_out >> 32), (addr + 4));
>> + spin_unlock_irqrestore(writeq_lock, flags);
>> +}
>> +
>> +/**
>>   * _base_writeq - 64 bit write to MMIO
>>   * @ioc: per adapter object
>>   * @b: data payload
>> @@ -3296,6 +3337,36 @@ _base_writeq(__u64 b, volatile void __iomem *addr, 
>> spinlock_t *writeq_lock)
>>  #endif
>>
>>  /**
>> + * _base_put_smid_mpi_ep_scsi_io - send SCSI_IO request to firmware
>> + * @ioc: per adapter object
>> + * @smid: system request message index
>> + * @handle: device handle
>> + *
>> + * Return nothing.
>> + */
>> +static void
>> +_base_put_smid_mpi_ep_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 
>> handle)
>> +{
>> + Mpi2RequestDescriptorUnion_t descriptor;
>> + u64 *request = (u64 *)
>> + void *mpi_req_iomem;
>> + __le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid);
>> +
>> + _clone_sg_entries(ioc, (void *) mfp, smid);
>> + mpi_req_iomem = (void *)ioc->chip +
>> + MPI_FRAME_START_OFFSET + (smid * ioc->request_sz);
>> + _base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp,
>> + ioc->request_sz);
>> + descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
>> + descriptor.SCSIIO.MSIxIndex =  _base_get_msix_index(ioc);
>> + descriptor.SCSIIO.SMID = cpu_to_le16(smid);
>> + descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
>> + descriptor.SCSIIO.LMID = 0;
>> + _base_mpi_ep_writeq(

Re: [V1 0/6] mpt3sas: Adding MPI Endpoint device support.

2018-02-15 Thread Suganath Prabu Subramani
Gentle Reminder, Any update on this ?

Thanks,
Suganath Prabu S

On Wed, Feb 7, 2018 at 4:21 PM, Suganath Prabu S
<suganath-prabu.subram...@broadcom.com> wrote:
> V1 Change info:
>
> * Few sparse warning fixes over initial patch set.
> * For 32 bit Arch,_base_writeq function is identical
> to _base_mpi_ep_writeq, Removed duplicate code as suggested by Martin.
>
> Andromeda is a PCIe switch, and it has a dedicated management
>  CPU (mCPU), nonvolatile flash memory, RAM etc... and
>  Linux kernel runs on mCPU. MPI Endpoint driver is the
>  management driver for Andromeda.
>
> The Plx Manager driver running on mCPU synthesizes a
>  virtual/Synthetic MPI End point to host.
> Synthetic MPI End point is emulated IT firmware running on
>  Linux operating system, which interfaces with PLX management
>  driver.
>
> PLX Management driver integrates IOCFW in same driver binary.
> At the end of Plx_Mgr driver load, it initializes IOC FW as well.
> Current implementation is single instance
>  of IOC FW (as it supports only one host).
>
>  PLX management driver will provide required resources
> and infrastructure for Synthetic MPI End point.
>
> Existing PLXManagement driver will reserve virtual slot for
>  MPI end point. currently, Virtual slot number 29 is reserved
>  for MPI end point.
>
> Synthetic device in management driver will be marked as
>  new type “PLX_DEV_TYPE_SYNTH_MPI_EP”. PLXmanagement driver
>  will interface with Synthetic MPI Endpoint for any
>  communication happening on PLX_DEV_TYPE_SYNTH_MPI_EP device
>  type from host.
>
> Link between host and PLX C2 is in below diagram.
>
>  ___
>  ___|   |
> |   |   |   |
> | PLX C2|===|HOST   |
> | PCI - |===|   MACHINE |
> |  SWITCH   |   |   |
> |___|   |   |
> ||  |___|
> ||
> ||
>  ___||__
> |   |
> |  MCPU |
> |   |
> |___|
>
>
>
>  After MPI end point implementation -
> (Host will see dedicated Virtual SLOT as MPI End point.)
> In Below single line is logical channel for MPI Endpoint
>  ___
>  ___|   |
> |   |   |   |
> | PLX C2|===|   HOST|
> | PCI - |===|   MACHINE |
> |  SWITCH   |   |   |
> |   |   |  ---  |
> |___|---| | IT DRIVER | |
> ||  |   |  ---  |
> ||  |   |___|
> ||  |
> ||  |
>  ___||__|___
> |   ||  |   |
> |  MCPU |   |
> |___|   |
> |   | PLX MGR|  |
> |   | DRIVER |  |
> |   ||  |
> |   |   |
> |___|_  |
> |   | | |
> |   |IOC FW   | |
> |   |_| |
> |___|
>
> PLXmanagement driver will create MPI end point based on
>  device table definition. PLXManagement driver will also
>  populate Synthetic device tree based on Device Table
>  for each host.
>
> From host it will be seen as IT HBA (Simplified version of SAS2/MPI2)
> (PCI Device, in which emulated IT FW running on mCPU behind Synthetic
>  endpoint of PCISWITCH). For host it is considered as actual
>  Physical Device.
>
> PLX Management driver provide interface to do DMA from mCPU to Host
>  using “MCPU Response Data Buffer“ method. DMA from Host to mCPU using
>  “MCPU Response Data Buffer” is not possible.
>
> Why DMA from host to mCPU is not possible using Responsebuffer ?
>  MCPU Response buffer is not really for reading from host
>  (reading will work, but answer TLP will not come back to the CSR FIFO,
>  but will go to the MCPU root complex - which could be an
>  unexpected read completion!
>
> Existing host driver (mpt2sas) will not work
>  for MPI end point. As the interface to DMA from host to mCPU is
>  not present for Mcpu/MPI Endpoint device, To overcome this
>  Driver should do double copy of those buffer directly to the
>  mCPU memory region via BAR-0 region.
>
> The host BAR0 region is divided into different group to serve Host
>  assisted DMA.
>
>  0- 255 System register(Doorbell, Host Interrupt etc)
>  256  - 4352MPI Frame. (This is based on maxCredit 32)
>  4352 - 

[V1] mpt3sas: Do not use 32-bit atomic request descriptor for Ventura controllers.

2018-02-14 Thread Suganath Prabu S
Problem Statement: Sending I/O through 32 bit descriptors to
 Ventura series of controller results in IO timeout on certain conditions.

This error only occurs on systems with high I/O activity on
Ventura series controllers.

Changes in this patch will prevent driver from using 32 bit descriptor
and use 64 bit Descriptors

V1 Change set:
1) In this patch removed callbacks as suggested by Hannes.

Note:
 This patch Should be applied on top of
https://www.spinics.net/lists/linux-scsi/msg117405.html
"Adding MPI Endpoint device support" patches.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 169 ---
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  11 +-
 drivers/scsi/mpt3sas/mpt3sas_config.c|   2 +-
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  22 ++--
 drivers/scsi/mpt3sas/mpt3sas_scsih.c |  20 ++--
 drivers/scsi/mpt3sas/mpt3sas_transport.c |   8 +-
 6 files changed, 54 insertions(+), 178 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 1c29286..d7ecdf3 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -1227,7 +1227,7 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 
msix_index, u32 reply)
ack_request->EventContext = mpi_reply->EventContext;
ack_request->VF_ID = 0;  /* TODO */
ack_request->VP_ID = 0;
-   ioc->put_smid_default(ioc, smid);
+   mpt3sas_base_put_smid_default(ioc, smid);
 
  out:
 
@@ -3420,15 +3420,15 @@ _base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 
smid, u16 handle)
 }
 
 /**
- * _base_put_smid_fast_path - send fast path request to firmware
+ * mpt3sas_base_put_smid_fast_path - send fast path request to firmware
  * @ioc: per adapter object
  * @smid: system request message index
  * @handle: device handle
  *
  * Return nothing.
  */
-static void
-_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+void
+mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid,
u16 handle)
 {
Mpi2RequestDescriptorUnion_t descriptor;
@@ -3445,14 +3445,14 @@ _base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, 
u16 smid,
 }
 
 /**
- * _base_put_smid_hi_priority - send Task Management request to firmware
+ * mpt3sas_base_put_smid_hi_priority - send Task Management request to firmware
  * @ioc: per adapter object
  * @smid: system request message index
  * @msix_task: msix_task will be same as msix of IO incase of task abort else 
0.
  * Return nothing.
  */
-static void
-_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+void
+mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid,
u16 msix_task)
 {
Mpi2RequestDescriptorUnion_t descriptor;
@@ -3490,15 +3490,15 @@ _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, 
u16 smid,
 }
 
 /**
- * _base_put_smid_nvme_encap - send NVMe encapsulated request to
+ * mpt3sas_base_put_smid_nvme_encap - send NVMe encapsulated request to
  *  firmware
  * @ioc: per adapter object
  * @smid: system request message index
  *
  * Return nothing.
  */
-static void
-_base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+void
+mpt3sas_base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 {
Mpi2RequestDescriptorUnion_t descriptor;
u64 *request = (u64 *)
@@ -3514,14 +3514,14 @@ _base_put_smid_nvme_encap(struct MPT3SAS_ADAPTER *ioc, 
u16 smid)
 }
 
 /**
- * _base_put_smid_default - Default, primarily used for config pages
+ * mpt3sas_base_put_smid_default - Default, primarily used for config pages
  * @ioc: per adapter object
  * @smid: system request message index
  *
  * Return nothing.
  */
-static void
-_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+void
+mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 {
Mpi2RequestDescriptorUnion_t descriptor;
void *mpi_req_iomem;
@@ -3556,116 +3556,6 @@ _base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 
smid)
 }
 
 /**
-* _base_put_smid_scsi_io_atomic - send SCSI_IO request to firmware using
-*   Atomic Request Descriptor
-* @ioc: per adapter object
-* @smid: system request message index
-* @handle: device handle, unused in this function, for function type match
-*
-* Return nothing.
-*/
-static void
-_base_put_smid_scsi_io_atomic(struct MPT3SAS_ADAPTER *ioc, u16 smid,
-   u16 handle)
-{
-   Mpi26AtomicRequestDescriptor_t descriptor;
-   u32 *request = (u32 *)
-
-   descriptor.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
-   descriptor.MSIxIndex = _base_get_msix_index(ioc);
-   descriptor.SMID = cpu_to_le16(smid);
-
-   writel(cpu_to_le32(*request), >chip->AtomicRequestDescriptorPost);
-}
-
-/**
- * _base_put_smid_fast_path_atomic - send fast path request to firmware
- * using Atomic Request Descriptor
- * @ioc: per adapter object
- 

[V1 4/6] mpt3sas: Introduce Base function for cloning.

2018-02-07 Thread Suganath Prabu S
All scsi IO's and config requests data buffer and
sgl are cloned to system memory in _clone_sg_entries
before submitting it to Firmware.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c   | 215 +-
 drivers/scsi/mpt3sas/mpt3sas_base.h   |   3 +
 drivers/scsi/mpt3sas/mpt3sas_config.c |   1 +
 3 files changed, 218 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 36f1242..c41c65b 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -126,6 +126,24 @@ module_param_call(mpt3sas_fwfault_debug, 
_scsih_set_fwfault_debug,
param_get_int, _fwfault_debug, 0644);
 
 /**
+ * _base_clone_to_sys_mem - Writes/copies data to system/BAR0 region
+ *
+ * @dst_iomem: Pointer to the destinaltion location in BAR0 space.
+ * @src: Pointer to the Source data.
+ * @size: Size of data to be copied.
+ */
+static void
+_base_clone_to_sys_mem(void __iomem *dst_iomem, void *src, u32 size)
+{
+   int i;
+   u32 *src_virt_mem = (u32 *)(src);
+
+   for (i = 0; i < size/4; i++)
+   writel((u32)src_virt_mem[i],
+   (void __iomem *)dst_iomem + (i * 4));
+}
+
+/**
  * _base_get_chain - Calculates and Returns virtual chain address
  *  for the provided smid in BAR0 space.
  *
@@ -219,6 +237,201 @@ _base_get_buffer_phys_bar0(struct MPT3SAS_ADAPTER *ioc, 
u16 smid)
 }
 
 /**
+ * _base_get_chain_buffer_dma_to_chain_buffer - Iterates chain
+ * lookup list and Provides chain_buffer
+ * address for the matching dma address.
+ * (Each smid can have 64K starts from 17024)
+ *
+ * @ioc: per adapter object
+ * @chain_buffer_dma: Chain buffer dma address.
+ *
+ * @Returns - Pointer to chain buffer. Or Null on Failure.
+ */
+static void *
+_base_get_chain_buffer_dma_to_chain_buffer(struct MPT3SAS_ADAPTER *ioc,
+   dma_addr_t chain_buffer_dma)
+{
+   u16 index;
+
+   for (index = 0; index < ioc->chain_depth; index++) {
+   if (ioc->chain_lookup[index].chain_buffer_dma ==
+   chain_buffer_dma)
+   return ioc->chain_lookup[index].chain_buffer;
+   }
+   pr_info(MPT3SAS_FMT
+   "Provided chain_buffer_dma address is not in the lookup list\n",
+   ioc->name);
+   return NULL;
+}
+
+/**
+ * _clone_sg_entries - MPI EP's scsiio and config requests
+ * are handled here. Base function for
+ * double buffering, before submitting
+ * the requests.
+ *
+ * @ioc: per adapter object.
+ * @mpi_request: mf request pointer.
+ * @smid: system request message index.
+ *
+ * @Returns: Nothing.
+ */
+static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc,
+   void *mpi_request, u16 smid)
+{
+   Mpi2SGESimple32_t *sgel, *sgel_next;
+   u32  sgl_flags, sge_chain_count = 0;
+   bool is_write = 0;
+   u16 i = 0;
+   void __iomem *buffer_iomem;
+   void  *buffer_iomem_phys;
+   void __iomem *buff_ptr;
+   void *buff_ptr_phys;
+   void __iomem *dst_chain_addr[MCPU_MAX_CHAINS_PER_IO];
+   void *src_chain_addr[MCPU_MAX_CHAINS_PER_IO], *dst_addr_phys;
+   MPI2RequestHeader_t *request_hdr;
+   struct scsi_cmnd *scmd;
+   struct scatterlist *sg_scmd = NULL;
+   int is_scsiio_req = 0;
+
+   request_hdr = (MPI2RequestHeader_t *) mpi_request;
+
+   if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
+   Mpi25SCSIIORequest_t *scsiio_request =
+   (Mpi25SCSIIORequest_t *)mpi_request;
+   sgel = (Mpi2SGESimple32_t *) _request->SGL;
+   is_scsiio_req = 1;
+   } else if (request_hdr->Function == MPI2_FUNCTION_CONFIG) {
+   Mpi2ConfigRequest_t  *config_req =
+   (Mpi2ConfigRequest_t *)mpi_request;
+   sgel = (Mpi2SGESimple32_t *) _req->PageBufferSGE;
+   } else
+   return;
+
+   /* From smid we can get scsi_cmd, once we have sg_scmd,
+* we just need to get sg_virt and sg_next to get virual
+* address associated with sgel->Address.
+*/
+
+   if (is_scsiio_req) {
+   /* Get scsi_cmd using smid */
+   scmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid);
+   if (scmd == NULL) {
+   pr_err(MPT3SAS_FMT "scmd is NULL\n", ioc->name);
+   return;
+   }
+
+   /* Get sg_scmd from scmd provided */
+   sg_scmd = scsi_sglist(scmd);
+   }
+
+   /*
+* 0 - 255  System register
+* 256 - 4352   MPI Frame. (This is based on maxCredit 32)
+* 4352 - 4864  Reply_free pool (512 byt

[V1 5/6] mpt3sas: Introduce function to clone mpi request.

2018-02-07 Thread Suganath Prabu S
1) Added function _base_clone_mpi_to_sys_mem to clone
MPI request into system BAR0 mapped region.

2) Separate out MPI Endpoint IO submissions to function
_base_put_smid_mpi_ep_scsi_io.

3) MPI EP requests are submitted in two 32 bit MMIO writes.
from _base_mpi_ep_writeq.

 For 32 bit Arch,_base_writeq function is identical
to _base_mpi_ep_writeq, Removed duplicate code as suggested.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 140 
 1 file changed, 125 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index c41c65b..52effd1 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -126,6 +126,25 @@ module_param_call(mpt3sas_fwfault_debug, 
_scsih_set_fwfault_debug,
param_get_int, _fwfault_debug, 0644);
 
 /**
+ * _base_clone_mpi_to_sys_mem - Writes/copies MPI frames
+ * to system/BAR0 region.
+ *
+ * @dst_iomem: Pointer to the destinaltion location in BAR0 space.
+ * @src: Pointer to the Source data.
+ * @size: Size of data to be copied.
+ */
+static void
+_base_clone_mpi_to_sys_mem(void *dst_iomem, void *src, u32 size)
+{
+   int i;
+   u32 *src_virt_mem = (u32 *)src;
+
+   for (i = 0; i < size/4; i++)
+   writel((u32)src_virt_mem[i],
+   (void __iomem *)dst_iomem + (i * 4));
+}
+
+/**
  * _base_clone_to_sys_mem - Writes/copies data to system/BAR0 region
  *
  * @dst_iomem: Pointer to the destinaltion location in BAR0 space.
@@ -3268,6 +3287,29 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 
smid)
 }
 
 /**
+ * _base_mpi_ep_writeq - 32 bit write to MMIO
+ * @b: data payload
+ * @addr: address in MMIO space
+ * @writeq_lock: spin lock
+ *
+ * This special handling for MPI EP to take care of 32 bit
+ * environment where its not quarenteed to send the entire word
+ * in one transfer.
+ */
+static inline void
+_base_mpi_ep_writeq(__u64 b, volatile void __iomem *addr,
+   spinlock_t *writeq_lock)
+{
+   unsigned long flags;
+   __u64 data_out = cpu_to_le64(b);
+
+   spin_lock_irqsave(writeq_lock, flags);
+   writel((u32)(data_out), addr);
+   writel((u32)(data_out >> 32), (addr + 4));
+   spin_unlock_irqrestore(writeq_lock, flags);
+}
+
+/**
  * _base_writeq - 64 bit write to MMIO
  * @ioc: per adapter object
  * @b: data payload
@@ -3288,17 +3330,41 @@ _base_writeq(__u64 b, volatile void __iomem *addr, 
spinlock_t *writeq_lock)
 static inline void
 _base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock)
 {
-   unsigned long flags;
-   __u64 data_out = cpu_to_le64(b);
-
-   spin_lock_irqsave(writeq_lock, flags);
-   writel((u32)(data_out), addr);
-   writel((u32)(data_out >> 32), (addr + 4));
-   spin_unlock_irqrestore(writeq_lock, flags);
+   _base_mpi_ep_writeq(b, addr, writeq_lock);
 }
 #endif
 
 /**
+ * _base_put_smid_mpi_ep_scsi_io - send SCSI_IO request to firmware
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @handle: device handle
+ *
+ * Return nothing.
+ */
+static void
+_base_put_smid_mpi_ep_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 
handle)
+{
+   Mpi2RequestDescriptorUnion_t descriptor;
+   u64 *request = (u64 *)
+   void *mpi_req_iomem;
+   __le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid);
+
+   _clone_sg_entries(ioc, (void *) mfp, smid);
+   mpi_req_iomem = (void *)ioc->chip +
+   MPI_FRAME_START_OFFSET + (smid * ioc->request_sz);
+   _base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp,
+   ioc->request_sz);
+   descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
+   descriptor.SCSIIO.MSIxIndex =  _base_get_msix_index(ioc);
+   descriptor.SCSIIO.SMID = cpu_to_le16(smid);
+   descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
+   descriptor.SCSIIO.LMID = 0;
+   _base_mpi_ep_writeq(*request, >chip->RequestDescriptorPostLow,
+   >scsi_lookup_lock);
+}
+
+/**
  * _base_put_smid_scsi_io - send SCSI_IO request to firmware
  * @ioc: per adapter object
  * @smid: system request message index
@@ -3359,7 +3425,23 @@ _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, 
u16 smid,
u16 msix_task)
 {
Mpi2RequestDescriptorUnion_t descriptor;
-   u64 *request = (u64 *)
+   void *mpi_req_iomem;
+   u64 *request;
+
+   if (ioc->is_mcpu_endpoint) {
+   MPI2RequestHeader_t *request_hdr;
+
+   __le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid);
+
+   request_hdr = (MPI2RequestHeader_t *)mfp;
+   /* TBD 256 is offset within sys register. */
+   mpi_req_iomem = 

[V1 6/6] mpt3sas: Introduce function to clone mpi reply.

2018-02-07 Thread Suganath Prabu S
If the posted request has an error of any type, the IOC writes
a Reply message into a host-based system reply message frame.
This functions clone it in the BAR0 mapped region.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 37 -
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 52effd1..1c29286 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -126,6 +126,33 @@ module_param_call(mpt3sas_fwfault_debug, 
_scsih_set_fwfault_debug,
param_get_int, _fwfault_debug, 0644);
 
 /**
+ * _base_clone_reply_to_sys_mem - copies reply to reply free iomem
+ *   in BAR0 space.
+ *
+ * @ioc: per adapter object
+ * @reply: reply message frame(lower 32bit addr)
+ * @index: System request message index.
+ *
+ * @Returns - Nothing
+ */
+static void
+_base_clone_reply_to_sys_mem(struct MPT3SAS_ADAPTER *ioc, u32 reply,
+   u32 index)
+{
+   /*
+* 256 is offset within sys register.
+* 256 offset MPI frame starts. Max MPI frame supported is 32.
+* 32 * 128 = 4K. From here, Clone of reply free for mcpu starts
+*/
+   u16 cmd_credit = ioc->facts.RequestCredit + 1;
+   void __iomem *reply_free_iomem = (void __iomem *)ioc->chip +
+   MPI_FRAME_START_OFFSET +
+   (cmd_credit * ioc->request_sz) + (index * sizeof(u32));
+
+   writel(reply, reply_free_iomem);
+}
+
+/**
  * _base_clone_mpi_to_sys_mem - Writes/copies MPI frames
  * to system/BAR0 region.
  *
@@ -1400,6 +1427,10 @@ _base_interrupt(int irq, void *bus_id)
0 : ioc->reply_free_host_index + 1;
ioc->reply_free[ioc->reply_free_host_index] =
cpu_to_le32(reply);
+   if (ioc->is_mcpu_endpoint)
+   _base_clone_reply_to_sys_mem(ioc,
+   cpu_to_le32(reply),
+   ioc->reply_free_host_index);
writel(ioc->reply_free_host_index,
>chip->ReplyFreeHostIndex);
}
@@ -6242,8 +6273,12 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
/* initialize Reply Free Queue */
for (i = 0, reply_address = (u32)ioc->reply_dma ;
i < ioc->reply_free_queue_depth ; i++, reply_address +=
-   ioc->reply_sz)
+   ioc->reply_sz) {
ioc->reply_free[i] = cpu_to_le32(reply_address);
+   if (ioc->is_mcpu_endpoint)
+   _base_clone_reply_to_sys_mem(ioc,
+   (__le32)reply_address, i);
+   }
 
/* initialize reply queues */
if (ioc->is_driver_loading)
-- 
2.5.5



[V1 0/6] mpt3sas: Adding MPI Endpoint device support.

2018-02-07 Thread Suganath Prabu S
can consider this as front end for IOC FW.
 PLXManagementdriver will call IOC front end API which will be the entry
 point in IOC FW module. Once PLX management calls relevant callbackfrom
 IOC FW, rest of the processing will behandled within IOC FW. 
 IOC FW should release TLP packet as soon as possible to avoid any
 TLP timeout.

Suganath Prabu S (6):
  mpt3sas: Add PCI device ID for Andromeda.
  mpt3sas: Configure reply post queue depth, DMA and sgl  tablesize.
  mpt3sas: Introduce API's to get BAR0 mapped buffer  address.
  mpt3sas: Introduce Base function for cloning.
  mpt3sas: Introduce function to clone mpi request.
  mpt3sas: Introduce function to clone mpi reply.

 drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h |1 +
 drivers/scsi/mpt3sas/mpt3sas_base.c  |  528 -
 drivers/scsi/mpt3sas/mpt3sas_base.h  |6 +
 drivers/scsi/mpt3sas/mpt3sas_config.c|1 +
 drivers/scsi/mpt3sas/mpt3sas_scsih.c |   54 +-
 16 files changed, 540 insertions(+), 9291 deletions(-)

Thanks,
Suganath Prabu S
-- 
2.5.5



[V1 2/6] mpt3sas: Configure reply post queue depth, DMA and sgl tablesize.

2018-02-07 Thread Suganath Prabu S
This configures shost max sector to 128, single reply descriptor
post queue, sgl table size to 16 and 32 bit DMA for MPI Endpoint
and it supports 64K as max IO.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 47 +++-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 40 ++
 2 files changed, 54 insertions(+), 33 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 13d6e4e..f45da9a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -2214,6 +2214,9 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, 
struct pci_dev *pdev)
struct sysinfo s;
u64 consistent_dma_mask;
 
+   if (ioc->is_mcpu_endpoint)
+   goto try_32bit;
+
if (ioc->dma_mask)
consistent_dma_mask = DMA_BIT_MASK(64);
else
@@ -2232,6 +2235,7 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, 
struct pci_dev *pdev)
}
}
 
+ try_32bit:
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
&& !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
ioc->base_add_sg_single = &_base_add_sg_single_32;
@@ -3887,17 +3891,21 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
sg_tablesize = min_t(unsigned short, sg_tablesize,
   MPT_KDUMP_MIN_PHYS_SEGMENTS);
 
-   if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS)
-   sg_tablesize = MPT_MIN_PHYS_SEGMENTS;
-   else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) {
-   sg_tablesize = min_t(unsigned short, sg_tablesize,
- SG_MAX_SEGMENTS);
-   pr_warn(MPT3SAS_FMT
-"sg_tablesize(%u) is bigger than kernel"
-" defined SG_CHUNK_SIZE(%u)\n", ioc->name,
-sg_tablesize, MPT_MAX_PHYS_SEGMENTS);
+   if (ioc->is_mcpu_endpoint)
+   ioc->shost->sg_tablesize = MPT_MIN_PHYS_SEGMENTS;
+   else {
+   if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS)
+   sg_tablesize = MPT_MIN_PHYS_SEGMENTS;
+   else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) {
+   sg_tablesize = min_t(unsigned short, sg_tablesize,
+   SG_MAX_SEGMENTS);
+   pr_warn(MPT3SAS_FMT
+   "sg_tablesize(%u) is bigger than kernel "
+   "defined SG_CHUNK_SIZE(%u)\n", ioc->name,
+   sg_tablesize, MPT_MAX_PHYS_SEGMENTS);
+   }
+   ioc->shost->sg_tablesize = sg_tablesize;
}
-   ioc->shost->sg_tablesize = sg_tablesize;
 
ioc->internal_depth = min_t(int, (facts->HighPriorityCredit + (5)),
(facts->RequestCredit / 4));
@@ -3982,13 +3990,18 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
/* reply free queue sizing - taking into account for 64 FW events */
ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
 
-   /* calculate reply descriptor post queue depth */
-   ioc->reply_post_queue_depth = ioc->hba_queue_depth +
-   ioc->reply_free_queue_depth +  1 ;
-   /* align the reply post queue on the next 16 count boundary */
-   if (ioc->reply_post_queue_depth % 16)
-   ioc->reply_post_queue_depth += 16 -
-   (ioc->reply_post_queue_depth % 16);
+   /* mCPU manage single counters for simplicity */
+   if (ioc->is_mcpu_endpoint)
+   ioc->reply_post_queue_depth = ioc->reply_free_queue_depth;
+   else {
+   /* calculate reply descriptor post queue depth */
+   ioc->reply_post_queue_depth = ioc->hba_queue_depth +
+   ioc->reply_free_queue_depth +  1;
+   /* align the reply post queue on the next 16 count boundary */
+   if (ioc->reply_post_queue_depth % 16)
+   ioc->reply_post_queue_depth += 16 -
+   (ioc->reply_post_queue_depth % 16);
+   }
 
if (ioc->reply_post_queue_depth >
facts->MaxReplyDescriptorPostQueueDepth) {
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index bde3c6f..5e52679 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -10521,26 +10521,34 @@ _scsih_probe(struct pci_dev *pdev, const struct 
pci_device_id *id)
shost->transportt = mpt3sas_transport_template;
shost->unique_id = ioc->id;
 
-   if (max_sectors != 0x) {
-   if (max_sectors < 64) {
-

[V1 1/6] mpt3sas: Add PCI device ID for Andromeda.

2018-02-07 Thread Suganath Prabu S
Add device ID and flag for Andromeda/MPI Emdpont.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h |  1 +
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  1 +
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 14 --
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h 
b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
index ee11710..0ad88de 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
@@ -524,6 +524,7 @@ typedef struct _MPI2_CONFIG_REPLY {
 #define MPI2_MFGPAGE_DEVID_SAS2308_1(0x0086)
 #define MPI2_MFGPAGE_DEVID_SAS2308_2(0x0087)
 #define MPI2_MFGPAGE_DEVID_SAS2308_3(0x006E)
+#define MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP   (0x02B0)
 
 /*MPI v2.5 SAS products */
 #define MPI25_MFGPAGE_DEVID_SAS3004 (0x0096)
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 789bc42..897394d 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1336,6 +1336,7 @@ struct MPT3SAS_ADAPTER {
u32 ring_buffer_offset;
u32 ring_buffer_sz;
u8  is_warpdrive;
+   u8  is_mcpu_endpoint;
u8  hide_ir_msg;
u8  mfg_pg10_hide_flag;
u8  hide_drives;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 74fca18..bde3c6f 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -10335,6 +10335,7 @@ _scsih_determine_hba_mpi_version(struct pci_dev *pdev)
case MPI2_MFGPAGE_DEVID_SAS2308_1:
case MPI2_MFGPAGE_DEVID_SAS2308_2:
case MPI2_MFGPAGE_DEVID_SAS2308_3:
+   case MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP:
return MPI2_VERSION;
case MPI25_MFGPAGE_DEVID_SAS3004:
case MPI25_MFGPAGE_DEVID_SAS3008:
@@ -10412,11 +10413,18 @@ _scsih_probe(struct pci_dev *pdev, const struct 
pci_device_id *id)
ioc->hba_mpi_version_belonged = hba_mpi_version;
ioc->id = mpt2_ids++;
sprintf(ioc->driver_name, "%s", MPT2SAS_DRIVER_NAME);
-   if (pdev->device == MPI2_MFGPAGE_DEVID_SSS6200) {
+   switch (pdev->device) {
+   case MPI2_MFGPAGE_DEVID_SSS6200:
ioc->is_warpdrive = 1;
ioc->hide_ir_msg = 1;
-   } else
+   break;
+   case MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP:
+   ioc->is_mcpu_endpoint = 1;
+   break;
+   default:
ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
+   break;
+   }
break;
case MPI25_VERSION:
case MPI26_VERSION:
@@ -10845,6 +10853,8 @@ static const struct pci_device_id mpt3sas_pci_table[] = 
{
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
PCI_ANY_ID, PCI_ANY_ID },
+   { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP,
+   PCI_ANY_ID, PCI_ANY_ID },
/* SSS6200 */
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
PCI_ANY_ID, PCI_ANY_ID },
-- 
2.5.5



[V1 3/6] mpt3sas: Introduce API's to get BAR0 mapped buffer address.

2018-02-07 Thread Suganath Prabu S
For MPI Endpoint/Mcpu, Driver should double buffer data buffer/sgl's.
 This is normally copied from host to internal memory of IOC by
 DMA engine of PCI Device. Since the interface to DMA from host
 to mCPU is not present for Mcpu/MPI Endpoint device,
 Driver does double copy of those buffer directly to the mCPU
 memory region via BAR-0 region.

 Introduced API's to calculate and return BAR0 mapped
 host buffer's physical and virtual address for the provided smid

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 93 +
 drivers/scsi/mpt3sas/mpt3sas_base.h |  2 +
 2 files changed, 95 insertions(+)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index f45da9a..36f1242 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -126,6 +126,99 @@ module_param_call(mpt3sas_fwfault_debug, 
_scsih_set_fwfault_debug,
param_get_int, _fwfault_debug, 0644);
 
 /**
+ * _base_get_chain - Calculates and Returns virtual chain address
+ *  for the provided smid in BAR0 space.
+ *
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @sge_chain_count: Scatter gather chain count.
+ *
+ * @Return: chain address.
+ */
+static inline void __iomem*
+_base_get_chain(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+   u8 sge_chain_count)
+{
+   void __iomem *base_chain, *chain_virt;
+   u16 cmd_credit = ioc->facts.RequestCredit + 1;
+
+   base_chain  = (void __iomem *)ioc->chip + MPI_FRAME_START_OFFSET +
+   (cmd_credit * ioc->request_sz) +
+   REPLY_FREE_POOL_SIZE;
+   chain_virt = base_chain + (smid * ioc->facts.MaxChainDepth *
+   ioc->request_sz) + (sge_chain_count * ioc->request_sz);
+   return chain_virt;
+}
+
+/**
+ * _base_get_chain_phys - Calculates and Returns physical address
+ * in BAR0 for scatter gather chains, for
+ * the provided smid.
+ *
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @sge_chain_count: Scatter gather chain count.
+ *
+ * @Return - Physical chain address.
+ */
+static inline void *
+_base_get_chain_phys(struct MPT3SAS_ADAPTER *ioc, u16 smid,
+   u8 sge_chain_count)
+{
+   void *base_chain_phys, *chain_phys;
+   u16 cmd_credit = ioc->facts.RequestCredit + 1;
+
+   base_chain_phys  = (void *)ioc->chip_phys + MPI_FRAME_START_OFFSET +
+   (cmd_credit * ioc->request_sz) +
+   REPLY_FREE_POOL_SIZE;
+   chain_phys = base_chain_phys + (smid * ioc->facts.MaxChainDepth *
+   ioc->request_sz) + (sge_chain_count * ioc->request_sz);
+   return chain_phys;
+}
+
+/**
+ * _base_get_buffer_bar0 - Calculates and Returns BAR0 mapped Host
+ * buffer address for the provided smid.
+ * (Each smid can have 64K starts from 17024)
+ *
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * @Returns - Pointer to buffer location in BAR0.
+ */
+
+static void __iomem *
+_base_get_buffer_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+   u16 cmd_credit = ioc->facts.RequestCredit + 1;
+   // Added extra 1 to reach end of chain.
+   void __iomem *chain_end = _base_get_chain(ioc,
+   cmd_credit + 1,
+   ioc->facts.MaxChainDepth);
+   return chain_end + (smid * 64 * 1024);
+}
+
+/**
+ * _base_get_buffer_phys_bar0 - Calculates and Returns BAR0 mapped
+ * Host buffer Physical address for the provided smid.
+ * (Each smid can have 64K starts from 17024)
+ *
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * @Returns - Pointer to buffer location in BAR0.
+ */
+static void *
+_base_get_buffer_phys_bar0(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+   u16 cmd_credit = ioc->facts.RequestCredit + 1;
+   void *chain_end_phys = _base_get_chain_phys(ioc,
+   cmd_credit + 1,
+   ioc->facts.MaxChainDepth);
+   return chain_end_phys + (smid * 64 * 1024);
+}
+
+/**
  *  mpt3sas_remove_dead_ioc_func - kthread context to remove dead ioc
  * @arg: input argument, used to derive ioc
  *
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 897394d..2529d25 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -120,6 +120,8 @@
 #define MPT3SAS_NVME_QUEUE_DEPTH   128
 #define MPT_NAME_LENGTH32  /* generic length of 
strings */
 #define MPT_STRING_LENGTH  64
+#define MPI_FRAME_START_OFFSET 256
+#define REPLY_FREE_POOL_SIZE   512 /*(32 maxcredix *4)*(4 times)*/
 
 #define MPT_MAX_CALLBACKS  32
 
-- 
2.5.5



Re: [PATCH] mpt3sas: fix an out of bound write

2018-01-28 Thread Suganath Prabu Subramani
Hi,
Please consider this patch as Ack-by: Suganath Prabu S
<suganath-prabu.subram...@broadcom.com>

Thanks.

On Fri, Jan 19, 2018 at 8:52 PM, Tomas Henzl <the...@redhat.com> wrote:
> cpu_msix_table is allocated to store online cpus, but pci_irq_get_affinity
> may return cpu_possible_mask which is then used to access cpu_msix_table.
> That causes bad user experience.
> Fix limits access to only online cpus, I've also added an additonal test
> to protect from an unlikely change in cpu_online_mask.
>
> Fixes: 1d55abc0e98a0bf35f3af80665aac564e3b30572 scsi: mpt3sas: switch to 
> pci_alloc_irq_vectors
>
> Signed-off-by: Tomas Henzl <the...@redhat.com>
> ---
>  drivers/scsi/mpt3sas/mpt3sas_base.c | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
> b/drivers/scsi/mpt3sas/mpt3sas_base.c
> index 13d6e4ec3..59a87ca32 100644
> --- a/drivers/scsi/mpt3sas/mpt3sas_base.c
> +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
> @@ -2410,8 +2410,11 @@ _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc)
> continue;
> }
>
> -   for_each_cpu(cpu, mask)
> +   for_each_cpu_and(cpu, mask, cpu_online_mask) {
> +   if (cpu >= ioc->cpu_msix_table_sz)
> +   break;
> ioc->cpu_msix_table[cpu] = 
> reply_q->msix_index;
> +   }
> }
> return;
> }
> --
> 2.14.3
>


Re: [PATCH 4/6] mpt3sas: Introduce Base function for cloning.

2018-01-23 Thread Suganath Prabu Subramani
Hi All,

We tried to reproduce below error
"drivers/scsi/mpt3sas/mpt3sas_base.c:315:10: error: implicit
declaration of function 'mpt3sas_scsih_scsi_lookup_get'; did you mean
scmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid);"

with base code and Make file flags (sparse) as mentioned under
reproduce in auto build test log.

We are not seeing this error. We have reviewed the code and it seems
to be fine. Let us know if we miss something here.

base:   https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
reproduce:
# apt-get install sparse
make ARCH=x86_64 allmodconfig
make C=1 CF=-D__CHECK_ENDIAN__

  drivers/scsi/mpt3sas/mpt3sas_base.c: In function '_clone_sg_entries':
   drivers/scsi/mpt3sas/mpt3sas_base.c:315:10: error: implicit
declaration of function 'mpt3sas_scsih_scsi_lookup_get'; did you mean
scmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid);
^
mpt3sas_scsih_issue_locked_tm
   drivers/scsi/mpt3sas/mpt3sas_base.c:315:8: warning: assignment
makes pointer from integer without a cast
scmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid);
^
   At top level:
   drivers/scsi/mpt3sas/mpt3sas_base.c:278:13: warning:
'_clone_sg_entries' defined but not used
static void _clone_sg_entries(struct MPT3SAS_ADAPTER
^
   cc1: some warnings being treated as errors


Thanks,
Suganath Prabu S

On Sat, Jan 20, 2018 at 11:37 PM, kbuild test robot <l...@intel.com> wrote:
> Hi Suganath,
>
> I love your patch! Perhaps something to improve:
>
> [auto build test WARNING on scsi/for-next]
> [also build test WARNING on v4.15-rc8 next-20180119]
> [if your patch is applied to the wrong git tree, please drop us a note to 
> help improve the system]
>
> url:    
> https://github.com/0day-ci/linux/commits/Suganath-Prabu-S/mpt3sas-Add-PCI-device-ID-for-Andromeda/20180121-002454
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
> reproduce:
> # apt-get install sparse
> make ARCH=x86_64 allmodconfig
> make C=1 CF=-D__CHECK_ENDIAN__
>
>
> sparse warnings: (new ones prefixed by >>)
>
>>> drivers/scsi/mpt3sas/mpt3sas_base.c:142:24: sparse: cast from restricted 
>>> __le32
>drivers/scsi/mpt3sas/mpt3sas_base.c:142:24: sparse: incorrect type in 
> argument 1 (different base types) @@ expected unsigned int val @@ got 
> restrunsigned int val @@
>drivers/scsi/mpt3sas/mpt3sas_base.c:142:24: expected unsigned int val
>drivers/scsi/mpt3sas/mpt3sas_base.c:142:24: got restricted __le32 
>>> drivers/scsi/mpt3sas/mpt3sas_base.c:142:64: sparse: incorrect type in 
>>> argument 2 (different address spaces) @@ expected void volatile @@ got @@
>drivers/scsi/mpt3sas/mpt3sas_base.c:142:64: expected void volatile
>drivers/scsi/mpt3sas/mpt3sas_base.c:142:64: got void COPYING CREDITS 
> Documentation Kbuild Kconfig MAINTAINERS Makefile README arch block certs 
> crypto drivers firmware fs include init ipc kernel lib mm net samples scripts 
> security sound tools usr virt
>drivers/scsi/mpt3sas/mpt3sas_base.c:162:24: sparse: cast removes address 
> space of expression
>drivers/scsi/mpt3sas/mpt3sas_base.c:315:24: sparse: undefined identifier 
> 'mpt3sas_scsih_scsi_lookup_get'
>drivers/scsi/mpt3sas/mpt3sas_base.c:1164:42: sparse: incorrect type in 
> assignment (different base types) @@ expected unsigned short Event @@ got 
> short Event @@
>drivers/scsi/mpt3sas/mpt3sas_base.c:1165:49: sparse: incorrect type in 
> assignment (different base types) @@ expected unsigned int EventContext @@ 
> got ed int EventContext @@
>drivers/scsi/mpt3sas/mpt3sas_base.c:1383:64: sparse: incorrect type in 
> argument 2 (different address spaces) @@ expected void volatile @@ got oid 
> volatile @@
>drivers/scsi/mpt3sas/mpt3sas_base.c:1432:52: sparse: incorrect type in 
> argument 2 (different address spaces) @@ expected void volatile @@ got oid 
> volatile @@
>drivers/scsi/mpt3sas/mpt3sas_base.c:2964:32: sparse: cast removes address 
> space of expression
>drivers/scsi/mpt3sas/mpt3sas_base.c:3256:16: sparse: incorrect type in 
> argument 1 (different base types) @@ expected unsigned long val @@ got 
> restunsigned long val @@
>drivers/scsi/mpt3sas/mpt3sas_base.c:3256:16: sparse: incorrect type in 
> argument 1 (different base types) @@ expected unsigned long val @@ got 
> restunsigned long val @@
>drivers/scsi/mpt3sas/mpt3sas_base.c:3256:16: sparse: incorrect type in 
> argument 1 (different base types) @@ expected unsigned long val @@ got 
> restunsigned long val @@
>drivers/scsi/mpt3sas/mpt3sas_base.c:3256:16: sparse: incorrect type in 
> argument 1 (different base types) @@ expected unsigned long val @@ got 
> restunsigned 

[PATCH 0/6] mpt3sas: Adding MPI Endpoint device support.

2018-01-19 Thread Suganath Prabu S
est of the processing will behandled within IOC FW. 
 IOC FW should release TLP packet as soon as possible to avoid any
 TLP timeout.

Suganath Prabu S (6):
  mpt3sas: Add PCI device ID for Andromeda.
  mpt3sas: Configure reply post queue depth, DMA and sgl tablesize.
  mpt3sas: Introduce API's to get BAR0 mapped buffer address.
  mpt3sas: Introduce Base function for cloning.
  mpt3sas: Introduce function to clone mpi request.
  mpt3sas: Introduce function to clone mpi reply.

 drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h  |   1 +
 drivers/scsi/mpt3sas/mpt3sas_base.c   | 513 --
 drivers/scsi/mpt3sas/mpt3sas_base.h   |   6 +
 drivers/scsi/mpt3sas/mpt3sas_config.c |   1 +
 drivers/scsi/mpt3sas/mpt3sas_scsih.c  |  54 ++--
 5 files changed, 532 insertions(+), 43 deletions(-)

Thanks,
Suganath Prabu S
-- 
2.5.5



[PATCH 5/6] mpt3sas: Introduce function to clone mpi request.

2018-01-19 Thread Suganath Prabu S
1) Added function _base_clone_mpi_to_sys_mem to clone
MPI request into system BAR0 mapped region.

2) Seperate out MPI Endpoint IO submissions to function
_base_put_smid_mpi_ep_scsi_io.

3) MPI EP requests are submitted in two 32 bit MMIO writes.
from _base_mpi_ep_writeq.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 131 +---
 1 file changed, 123 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 40a1806..0248058 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -126,6 +126,24 @@ module_param_call(mpt3sas_fwfault_debug, 
_scsih_set_fwfault_debug,
param_get_int, _fwfault_debug, 0644);
 
 /**
+ * _base_clone_mpi_to_sys_mem - Writes/copies MPI frames
+ * to system/BAR0 region.
+ *
+ * @dst_iomem: Pointer to the destinaltion location in BAR0 space.
+ * @src: Pointer to the Source data.
+ * @size: Size of data to be copied.
+ */
+static void
+_base_clone_mpi_to_sys_mem(void *dst_iomem, void *src, u32 size)
+{
+   int i;
+   __le32 *src_virt_mem = (__le32 *)src;
+
+   for (i = 0; i < size/4; i++)
+   writel(cpu_to_le32(src_virt_mem[i]), dst_iomem + (i * 4));
+}
+
+/**
  * _base_clone_to_sys_mem - Writes/copies data to system/BAR0 region
  *
  * @dst_iomem: Pointer to the destinaltion location in BAR0 space.
@@ -3265,6 +3283,29 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 
smid)
 }
 
 /**
+ * _base_mpi_ep_writeq - 32 bit write to MMIO
+ * @b: data payload
+ * @addr: address in MMIO space
+ * @writeq_lock: spin lock
+ *
+ * This special handling for MPI EP to take care of 32 bit
+ * environment where its not quarenteed to send the entire word
+ * in one transfer.
+ */
+static inline void
+_base_mpi_ep_writeq(__u64 b, volatile void __iomem *addr,
+   spinlock_t *writeq_lock)
+{
+   unsigned long flags;
+   __u64 data_out = cpu_to_le64(b);
+
+   spin_lock_irqsave(writeq_lock, flags);
+   writel((u32)(data_out), addr);
+   writel((u32)(data_out >> 32), (addr + 4));
+   spin_unlock_irqrestore(writeq_lock, flags);
+}
+
+/**
  * _base_writeq - 64 bit write to MMIO
  * @ioc: per adapter object
  * @b: data payload
@@ -3296,6 +3337,36 @@ _base_writeq(__u64 b, volatile void __iomem *addr, 
spinlock_t *writeq_lock)
 #endif
 
 /**
+ * _base_put_smid_mpi_ep_scsi_io - send SCSI_IO request to firmware
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @handle: device handle
+ *
+ * Return nothing.
+ */
+static void
+_base_put_smid_mpi_ep_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 
handle)
+{
+   Mpi2RequestDescriptorUnion_t descriptor;
+   u64 *request = (u64 *)
+   void *mpi_req_iomem;
+   __le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid);
+
+   _clone_sg_entries(ioc, (void *) mfp, smid);
+   mpi_req_iomem = (void *)ioc->chip +
+   MPI_FRAME_START_OFFSET + (smid * ioc->request_sz);
+   _base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp,
+   ioc->request_sz);
+   descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
+   descriptor.SCSIIO.MSIxIndex =  _base_get_msix_index(ioc);
+   descriptor.SCSIIO.SMID = cpu_to_le16(smid);
+   descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
+   descriptor.SCSIIO.LMID = 0;
+   _base_mpi_ep_writeq(*request, >chip->RequestDescriptorPostLow,
+   >scsi_lookup_lock);
+}
+
+/**
  * _base_put_smid_scsi_io - send SCSI_IO request to firmware
  * @ioc: per adapter object
  * @smid: system request message index
@@ -3356,7 +3427,23 @@ _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, 
u16 smid,
u16 msix_task)
 {
Mpi2RequestDescriptorUnion_t descriptor;
-   u64 *request = (u64 *)
+   void *mpi_req_iomem;
+   u64 *request;
+
+   if (ioc->is_mcpu_endpoint) {
+   MPI2RequestHeader_t *request_hdr;
+
+   __le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid);
+
+   request_hdr = (MPI2RequestHeader_t *)mfp;
+   /* TBD 256 is offset within sys register. */
+   mpi_req_iomem = (void *)ioc->chip + MPI_FRAME_START_OFFSET
+   + (smid * ioc->request_sz);
+   _base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp,
+   ioc->request_sz);
+   }
+
+   request = (u64 *)
 
descriptor.HighPriority.RequestFlags =
MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
@@ -3364,8 +3451,13 @@ _base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, 
u16 smid,
descriptor.HighPriority.SMID = cpu_to_le16(smid);
descriptor.HighPriority.LMID =

[PATCH 4/6] mpt3sas: Introduce Base function for cloning.

2018-01-19 Thread Suganath Prabu S
All scsi IO's and config requests data buffer and
sgl are cloned to system memory in _clone_sg_entries
before submitting it to Firmware.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c   | 212 +-
 drivers/scsi/mpt3sas/mpt3sas_base.h   |   3 +
 drivers/scsi/mpt3sas/mpt3sas_config.c |   1 +
 3 files changed, 215 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index dc289c0..40a1806 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -126,6 +126,23 @@ module_param_call(mpt3sas_fwfault_debug, 
_scsih_set_fwfault_debug,
param_get_int, _fwfault_debug, 0644);
 
 /**
+ * _base_clone_to_sys_mem - Writes/copies data to system/BAR0 region
+ *
+ * @dst_iomem: Pointer to the destinaltion location in BAR0 space.
+ * @src: Pointer to the Source data.
+ * @size: Size of data to be copied.
+ */
+static void
+_base_clone_to_sys_mem(void *dst_iomem, void *src, u32 size)
+{
+   int i;
+   __le32 *src_virt_mem = (__le32 *)(src);
+
+   for (i = 0; i < size/4; i++)
+   writel(cpu_to_le32(src_virt_mem[i]), dst_iomem + (i * 4));
+}
+
+/**
  * _base_get_chain - Calculates and Returns virtual chain address
  *  for the provided smid in BAR0 space.
  *
@@ -219,6 +236,199 @@ _base_get_buffer_phys_bar0(struct MPT3SAS_ADAPTER *ioc, 
u16 smid)
 }
 
 /**
+ * _base_get_chain_buffer_dma_to_chain_buffer - Iterates chain
+ * lookup list and Provides chain_buffer
+ * address for the matching dma address.
+ * (Each smid can have 64K starts from 17024)
+ *
+ * @ioc: per adapter object
+ * @chain_buffer_dma: Chain buffer dma address.
+ *
+ * @Returns - Pointer to chain buffer. Or Null on Failure.
+ */
+static void *
+_base_get_chain_buffer_dma_to_chain_buffer(struct MPT3SAS_ADAPTER *ioc,
+   dma_addr_t chain_buffer_dma)
+{
+   u16 index;
+
+   for (index = 0; index < ioc->chain_depth; index++) {
+   if (ioc->chain_lookup[index].chain_buffer_dma ==
+   chain_buffer_dma)
+   return ioc->chain_lookup[index].chain_buffer;
+   }
+   pr_info(MPT3SAS_FMT
+   "Provided chain_buffer_dma address is not in the lookup list\n",
+   ioc->name);
+   return NULL;
+}
+
+/**
+ * _clone_sg_entries - MPI EP's scsiio and config requests
+ * are handled here. Base function for
+ * double buffering, before submitting
+ * the requests.
+ *
+ * @ioc: per adapter object.
+ * @mpi_request: mf request pointer.
+ * @smid: system request message index.
+ *
+ * @Returns: Nothing.
+ */
+static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc,
+   void *mpi_request, u16 smid)
+{
+   Mpi2SGESimple32_t *sgel, *sgel_next;
+   u32  sgl_flags, sge_chain_count = 0;
+   bool is_write = 0;
+   u16 i = 0;
+   void  *buffer_iomem, *buffer_iomem_phys;
+   void *buff_ptr, *buff_ptr_phys;
+   void *dst_chain_addr[MCPU_MAX_CHAINS_PER_IO];
+   void *src_chain_addr[MCPU_MAX_CHAINS_PER_IO], *dst_addr_phys;
+   MPI2RequestHeader_t *request_hdr;
+   struct scsi_cmnd *scmd;
+   struct scatterlist *sg_scmd = NULL;
+   int is_scsiio_req = 0;
+
+   request_hdr = (MPI2RequestHeader_t *) mpi_request;
+
+   if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) {
+   Mpi25SCSIIORequest_t *scsiio_request =
+   (Mpi25SCSIIORequest_t *)mpi_request;
+   sgel = (Mpi2SGESimple32_t *) _request->SGL;
+   is_scsiio_req = 1;
+   } else if (request_hdr->Function == MPI2_FUNCTION_CONFIG) {
+   Mpi2ConfigRequest_t  *config_req =
+   (Mpi2ConfigRequest_t *)mpi_request;
+   sgel = (Mpi2SGESimple32_t *) _req->PageBufferSGE;
+   } else
+   return;
+
+   /* From smid we can get scsi_cmd, once we have sg_scmd,
+* we just need to get sg_virt and sg_next to get virual
+* address associated with sgel->Address.
+*/
+
+   if (is_scsiio_req) {
+   /* Get scsi_cmd using smid */
+   scmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid);
+   if (scmd == NULL) {
+   pr_err(MPT3SAS_FMT "scmd is NULL\n", ioc->name);
+   return;
+   }
+
+   /* Get sg_scmd from scmd provided */
+   sg_scmd = scsi_sglist(scmd);
+   }
+
+   /*
+* 0 - 255  System register
+* 256 - 4352   MPI Frame. (This is based on maxCredit 32)
+* 4352 - 4864  Reply_free pool (512 byte is reserved
+*  considering maxCredit 32. Reply need ext

[PATCH 6/6] mpt3sas: Introduce function to clone mpi reply.

2018-01-19 Thread Suganath Prabu S
If the posted request has an error of any type, the IOC writes
a Reply message into a host-based system reply message frame.
This functions clone it in the BAR0 mapped region.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 34 +-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 0248058..fa13916 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -126,6 +126,32 @@ module_param_call(mpt3sas_fwfault_debug, 
_scsih_set_fwfault_debug,
param_get_int, _fwfault_debug, 0644);
 
 /**
+ * _base_clone_reply_to_sys_mem - copies reply to reply free iomem
+ *   in BAR0 space.
+ *
+ * @ioc: per adapter object
+ * @reply: reply message frame(lower 32bit addr)
+ * @index: System request message index.
+ *
+ * @Returns - Nothing
+ */
+static void
+_base_clone_reply_to_sys_mem(struct MPT3SAS_ADAPTER *ioc, U32 reply,
+   u32 index)
+{
+   /*
+* 256 is offset within sys register.
+* 256 offset MPI frame starts. Max MPI frame supported is 32.
+* 32 * 128 = 4K. From here, Clone of reply free for mcpu starts
+*/
+   u16 cmd_credit = ioc->facts.RequestCredit + 1;
+   void *reply_free_iomem = (void *)ioc->chip + MPI_FRAME_START_OFFSET +
+   (cmd_credit * ioc->request_sz) + (index * sizeof(u32));
+
+   writel(cpu_to_le32(reply), reply_free_iomem);
+}
+
+/**
  * _base_clone_mpi_to_sys_mem - Writes/copies MPI frames
  * to system/BAR0 region.
  *
@@ -1396,6 +1422,9 @@ _base_interrupt(int irq, void *bus_id)
0 : ioc->reply_free_host_index + 1;
ioc->reply_free[ioc->reply_free_host_index] =
cpu_to_le32(reply);
+   if (ioc->is_mcpu_endpoint)
+   _base_clone_reply_to_sys_mem(ioc, reply,
+   ioc->reply_free_host_index);
writel(ioc->reply_free_host_index,
>chip->ReplyFreeHostIndex);
}
@@ -6244,8 +6273,11 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
/* initialize Reply Free Queue */
for (i = 0, reply_address = (u32)ioc->reply_dma ;
i < ioc->reply_free_queue_depth ; i++, reply_address +=
-   ioc->reply_sz)
+   ioc->reply_sz) {
ioc->reply_free[i] = cpu_to_le32(reply_address);
+   if (ioc->is_mcpu_endpoint)
+   _base_clone_reply_to_sys_mem(ioc, reply_address, i);
+   }
 
/* initialize reply queues */
if (ioc->is_driver_loading)
-- 
2.5.5



[PATCH 1/6] mpt3sas: Add PCI device ID for Andromeda.

2018-01-19 Thread Suganath Prabu S
Add device ID and flag for Andromeda/MPI Emdpont.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h |  1 +
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  1 +
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 14 --
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h 
b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
index ee11710..0ad88de 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
@@ -524,6 +524,7 @@ typedef struct _MPI2_CONFIG_REPLY {
 #define MPI2_MFGPAGE_DEVID_SAS2308_1(0x0086)
 #define MPI2_MFGPAGE_DEVID_SAS2308_2(0x0087)
 #define MPI2_MFGPAGE_DEVID_SAS2308_3(0x006E)
+#define MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP   (0x02B0)
 
 /*MPI v2.5 SAS products */
 #define MPI25_MFGPAGE_DEVID_SAS3004 (0x0096)
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 789bc42..897394d 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1336,6 +1336,7 @@ struct MPT3SAS_ADAPTER {
u32 ring_buffer_offset;
u32 ring_buffer_sz;
u8  is_warpdrive;
+   u8  is_mcpu_endpoint;
u8  hide_ir_msg;
u8  mfg_pg10_hide_flag;
u8  hide_drives;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 74fca18..bde3c6f 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -10335,6 +10335,7 @@ _scsih_determine_hba_mpi_version(struct pci_dev *pdev)
case MPI2_MFGPAGE_DEVID_SAS2308_1:
case MPI2_MFGPAGE_DEVID_SAS2308_2:
case MPI2_MFGPAGE_DEVID_SAS2308_3:
+   case MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP:
return MPI2_VERSION;
case MPI25_MFGPAGE_DEVID_SAS3004:
case MPI25_MFGPAGE_DEVID_SAS3008:
@@ -10412,11 +10413,18 @@ _scsih_probe(struct pci_dev *pdev, const struct 
pci_device_id *id)
ioc->hba_mpi_version_belonged = hba_mpi_version;
ioc->id = mpt2_ids++;
sprintf(ioc->driver_name, "%s", MPT2SAS_DRIVER_NAME);
-   if (pdev->device == MPI2_MFGPAGE_DEVID_SSS6200) {
+   switch (pdev->device) {
+   case MPI2_MFGPAGE_DEVID_SSS6200:
ioc->is_warpdrive = 1;
ioc->hide_ir_msg = 1;
-   } else
+   break;
+   case MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP:
+   ioc->is_mcpu_endpoint = 1;
+   break;
+   default:
ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS;
+   break;
+   }
break;
case MPI25_VERSION:
case MPI26_VERSION:
@@ -10845,6 +10853,8 @@ static const struct pci_device_id mpt3sas_pci_table[] = 
{
PCI_ANY_ID, PCI_ANY_ID },
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3,
PCI_ANY_ID, PCI_ANY_ID },
+   { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_MPI_EP,
+   PCI_ANY_ID, PCI_ANY_ID },
/* SSS6200 */
{ MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200,
PCI_ANY_ID, PCI_ANY_ID },
-- 
2.5.5



[PATCH 2/6] mpt3sas: Configure reply post queue depth, DMA and sgl tablesize.

2018-01-19 Thread Suganath Prabu S
This configures shost max sector to 128, single reply descriptor
post queue, sgl table size to 16 and 32 bit DMA for MPI Endpoint
and it supports 64K as max IO.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 47 +++-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 40 ++
 2 files changed, 54 insertions(+), 33 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index a44b9be..c0a1c0f 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -2214,6 +2214,9 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, 
struct pci_dev *pdev)
struct sysinfo s;
u64 consistent_dma_mask;
 
+   if (ioc->is_mcpu_endpoint)
+   goto try_32bit;
+
if (ioc->dma_mask)
consistent_dma_mask = DMA_BIT_MASK(64);
else
@@ -2232,6 +2235,7 @@ _base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, 
struct pci_dev *pdev)
}
}
 
+ try_32bit:
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
&& !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
ioc->base_add_sg_single = &_base_add_sg_single_32;
@@ -3887,17 +3891,21 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
sg_tablesize = min_t(unsigned short, sg_tablesize,
   MPT_KDUMP_MIN_PHYS_SEGMENTS);
 
-   if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS)
-   sg_tablesize = MPT_MIN_PHYS_SEGMENTS;
-   else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) {
-   sg_tablesize = min_t(unsigned short, sg_tablesize,
- SG_MAX_SEGMENTS);
-   pr_warn(MPT3SAS_FMT
-"sg_tablesize(%u) is bigger than kernel"
-" defined SG_CHUNK_SIZE(%u)\n", ioc->name,
-sg_tablesize, MPT_MAX_PHYS_SEGMENTS);
+   if (ioc->is_mcpu_endpoint)
+   ioc->shost->sg_tablesize = MPT_MIN_PHYS_SEGMENTS;
+   else {
+   if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS)
+   sg_tablesize = MPT_MIN_PHYS_SEGMENTS;
+   else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) {
+   sg_tablesize = min_t(unsigned short, sg_tablesize,
+   SG_MAX_SEGMENTS);
+   pr_warn(MPT3SAS_FMT
+   "sg_tablesize(%u) is bigger than kernel "
+   "defined SG_CHUNK_SIZE(%u)\n", ioc->name,
+   sg_tablesize, MPT_MAX_PHYS_SEGMENTS);
+   }
+   ioc->shost->sg_tablesize = sg_tablesize;
}
-   ioc->shost->sg_tablesize = sg_tablesize;
 
ioc->internal_depth = min_t(int, (facts->HighPriorityCredit + (5)),
(facts->RequestCredit / 4));
@@ -3982,13 +3990,18 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
/* reply free queue sizing - taking into account for 64 FW events */
ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64;
 
-   /* calculate reply descriptor post queue depth */
-   ioc->reply_post_queue_depth = ioc->hba_queue_depth +
-   ioc->reply_free_queue_depth +  1 ;
-   /* align the reply post queue on the next 16 count boundary */
-   if (ioc->reply_post_queue_depth % 16)
-   ioc->reply_post_queue_depth += 16 -
-   (ioc->reply_post_queue_depth % 16);
+   /* mCPU manage single counters for simplicity */
+   if (ioc->is_mcpu_endpoint)
+   ioc->reply_post_queue_depth = ioc->reply_free_queue_depth;
+   else {
+   /* calculate reply descriptor post queue depth */
+   ioc->reply_post_queue_depth = ioc->hba_queue_depth +
+   ioc->reply_free_queue_depth +  1;
+   /* align the reply post queue on the next 16 count boundary */
+   if (ioc->reply_post_queue_depth % 16)
+   ioc->reply_post_queue_depth += 16 -
+   (ioc->reply_post_queue_depth % 16);
+   }
 
if (ioc->reply_post_queue_depth >
facts->MaxReplyDescriptorPostQueueDepth) {
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index bde3c6f..5e52679 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -10521,26 +10521,34 @@ _scsih_probe(struct pci_dev *pdev, const struct 
pci_device_id *id)
shost->transportt = mpt3sas_transport_template;
shost->unique_id = ioc->id;
 
-   if (max_sectors != 0x) {
-   if (max_sectors < 64) {
-

[Resend 03/11] mpt3sas: separate out _base_recovery_check()

2018-01-04 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

No functional change.

Signed-off-by: Hannes Reinecke <h...@suse.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 23 ++-
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 464a11e..55aa80c 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -2873,6 +2873,19 @@ mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, 
u8 cb_idx)
return smid;
 }
 
+static void
+_base_recovery_check(struct MPT3SAS_ADAPTER *ioc)
+{
+   /*
+* See _wait_for_commands_to_complete() call with regards to this code.
+*/
+   if (ioc->shost_recovery && ioc->pending_io_count) {
+   if (ioc->pending_io_count == 1)
+   wake_up(>reset_wq);
+   ioc->pending_io_count--;
+   }
+}
+
 /**
  * mpt3sas_base_free_smid - put smid back on free_list
  * @ioc: per adapter object
@@ -2898,15 +2911,7 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 
smid)
list_add(>scsi_lookup[i].tracker_list, >free_list);
spin_unlock_irqrestore(>scsi_lookup_lock, flags);
 
-   /*
-* See _wait_for_commands_to_complete() call with regards
-* to this code.
-*/
-   if (ioc->shost_recovery && ioc->pending_io_count) {
-   if (ioc->pending_io_count == 1)
-   wake_up(>reset_wq);
-   ioc->pending_io_count--;
-   }
+   _base_recovery_check(ioc);
return;
} else if (smid < ioc->internal_smid) {
/* hi-priority */
-- 
2.5.5



[Resend 02/11] mpt3sas: use list_splice_init()

2018-01-04 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Use 'list_splice_init()' instead of hand-crafted function.
No functional change.

Signed-off-by: Hannes Reinecke <h...@suse.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index e3857e5..464a11e 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -2885,20 +2885,13 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 
smid)
 {
unsigned long flags;
int i;
-   struct chain_tracker *chain_req, *next;
 
spin_lock_irqsave(>scsi_lookup_lock, flags);
if (smid < ioc->hi_priority_smid) {
/* scsiio queue */
i = smid - 1;
-   if (!list_empty(>scsi_lookup[i].chain_list)) {
-   list_for_each_entry_safe(chain_req, next,
-   >scsi_lookup[i].chain_list, tracker_list) {
-   list_del_init(_req->tracker_list);
-   list_add(_req->tracker_list,
-   >free_chain_list);
-   }
-   }
+   list_splice_init(>scsi_lookup[i].chain_list,
+>free_chain_list);
ioc->scsi_lookup[i].cb_idx = 0xFF;
ioc->scsi_lookup[i].scmd = NULL;
ioc->scsi_lookup[i].direct_io = 0;
-- 
2.5.5



[Resend 04/11] mpt3sas: open-code _scsih_scsi_lookup_get()

2018-01-04 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Just a wrapper around the scsi lookup array and only used
in one place, so open-code it.

Signed-off-by: Hannes Reinecke <h...@suse.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 15 +--
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 9a2cede..e482fa2 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -1445,19 +1445,6 @@ _scsih_is_nvme_device(u32 device_info)
 }
 
 /**
- * _scsih_scsi_lookup_get - returns scmd entry
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns the smid stored scmd pointer.
- */
-static struct scsi_cmnd *
-_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
-{
-   return ioc->scsi_lookup[smid - 1].scmd;
-}
-
-/**
  * __scsih_scsi_lookup_get_clear - returns scmd entry without
  * holding any lock.
  * @ioc: per adapter object
@@ -7543,7 +7530,7 @@ _scsih_sas_broadcast_primitive_event(struct 
MPT3SAS_ADAPTER *ioc,
for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
if (ioc->shost_recovery)
goto out;
-   scmd = _scsih_scsi_lookup_get(ioc, smid);
+   scmd = ioc->scsi_lookup[smid - 1].scmd;
if (!scmd)
continue;
sdev = scmd->device;
-- 
2.5.5



[Resend PATCH 00/11] mpt3sas: Enable scsi MQ & lockless command submission

2018-01-04 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Hi all,

This patch set is initially posted by Hannes Reinecke to enable scsi
multiqueue for the mpt3sas driver.
While the HBA only has a single mailbox register for submitting commands,
it does have individual receive queues per MSI-X interrupt and as such
does benefit from converting it to full multiqueue support. 

Suganath Prabu S (11):
  mpt3sas: set default value for cb_idx
  mpt3sas: use list_splice_init()
  mpt3sas: separate out _base_recovery_check()
  mpt3sas: open-code _scsih_scsi_lookup_get()
  mpt3sas: Introduce mpt3sas_get_st_from_smid()
  mpt3sas: check command status before attempting abort
  mpt3sas: always use first reserved smid for ioctl  passthrough
  mpt3sas: simplify task management functions
  mpt3sas: simplify mpt3sas_scsi_issue_tm()
  mpt3sas: simplify _wait_for_commands_to_complete()
  mpt3sas: lockless command submission

 drivers/scsi/mpt3sas/mpt3sas_base.c  | 199 +++--
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  29 ++-
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  31 ++--
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 292 +++
 drivers/scsi/mpt3sas/mpt3sas_warpdrive.c |  33 +---
 5 files changed, 191 insertions(+), 393 deletions(-)

Thanks,
Suganath Prabu S
-- 
2.5.5



[Resend 05/11] mpt3sas: Introduce mpt3sas_get_st_from_smid()

2018-01-04 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Abstract accesses to the scsi_lookup array by introducing
mpt3sas_get_st_from_smid().

Signed-off-by: Hannes Reinecke <h...@suse.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 22 ++
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  2 ++
 drivers/scsi/mpt3sas/mpt3sas_scsih.c |  7 ---
 drivers/scsi/mpt3sas/mpt3sas_warpdrive.c |  4 +++-
 4 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 55aa80c..1ea4232 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -888,6 +888,15 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 
msix_index, u32 reply)
return 1;
 }
 
+struct scsiio_tracker *
+mpt3sas_get_st_from_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+   if (WARN_ON(!smid) ||
+   WARN_ON(smid >= ioc->hi_priority_smid))
+   return NULL;
+   return >scsi_lookup[smid - 1];
+}
+
 /**
  * _base_get_cb_idx - obtain the callback index
  * @ioc: per adapter object
@@ -902,8 +911,11 @@ _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
u8 cb_idx = 0xFF;
 
if (smid < ioc->hi_priority_smid) {
-   i = smid - 1;
-   cb_idx = ioc->scsi_lookup[i].cb_idx;
+   struct scsiio_tracker *st;
+
+   st = mpt3sas_get_st_from_smid(ioc, smid);
+   if (st)
+   cb_idx = st->cb_idx;
} else if (smid < ioc->internal_smid) {
i = smid - ioc->hi_priority_smid;
cb_idx = ioc->hpr_lookup[i].cb_idx;
@@ -1294,6 +1306,7 @@ static struct chain_tracker *
 _base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 {
struct chain_tracker *chain_req;
+   struct scsiio_tracker *st;
unsigned long flags;
 
spin_lock_irqsave(>scsi_lookup_lock, flags);
@@ -1306,8 +1319,9 @@ _base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER 
*ioc, u16 smid)
chain_req = list_entry(ioc->free_chain_list.next,
struct chain_tracker, tracker_list);
list_del_init(_req->tracker_list);
-   list_add_tail(_req->tracker_list,
-   >scsi_lookup[smid - 1].chain_list);
+   st = mpt3sas_get_st_from_smid(ioc, smid);
+   if (st)
+   list_add_tail(_req->tracker_list, >chain_list);
spin_unlock_irqrestore(>scsi_lookup_lock, flags);
return chain_req;
 }
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 60f42ca..23e9af5 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1402,6 +1402,8 @@ void mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER 
*ioc);
 u16 mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx);
 u16 mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx,
struct scsi_cmnd *scmd);
+struct scsiio_tracker *mpt3sas_get_st_from_smid(struct MPT3SAS_ADAPTER *ioc,
+   u16 smid);
 
 u16 mpt3sas_base_get_smid(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx);
 void mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index e482fa2..a11774b 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2779,7 +2779,7 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 
handle, uint channel,
}
 
if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
-   scsi_lookup = >scsi_lookup[smid_task - 1];
+   scsi_lookup = mpt3sas_get_st_from_smid(ioc, smid_task);
 
dtmprintk(ioc, pr_info(MPT3SAS_FMT
"sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n",
@@ -2797,7 +2797,8 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 
handle, uint channel,
mpt3sas_scsih_set_tm_flag(ioc, handle);
init_completion(>tm_cmds.done);
if ((type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) &&
-   (scsi_lookup->msix_io < ioc->reply_queue_count))
+   scsi_lookup &&
+   (scsi_lookup->msix_io < ioc->reply_queue_count))
msix_task = scsi_lookup->msix_io;
else
msix_task = 0;
@@ -2838,7 +2839,7 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 
handle, uint channel,
switch (type) {
case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
rc = SUCCESS;
-   if (scsi_lookup->scmd == NULL)
+   if (scsi_lookup && scsi_lookup->scmd == NULL)
break;
rc = FAILED;
break;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_warp

[Resend 07/11] mpt3sas: always use first reserved smid for ioctl passthrough

2018-01-04 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

ioctl passthrough commands require a SCSIIO smid, but cannot
easily integrate with the block layer. But the driver already
has reserved some SCSIIO smids and we're only ever allowing
one ioctl command at a time we can use the first reserved smid
for ioctl commands.

Signed-off-by: Hannes Reinecke <h...@suse.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 19 +--
 drivers/scsi/mpt3sas/mpt3sas_ctl.c  | 10 ++
 2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 1ea4232..d4b32af 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -908,14 +908,18 @@ static u8
 _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 {
int i;
+   u16 ctl_smid = ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT + 1;
u8 cb_idx = 0xFF;
 
if (smid < ioc->hi_priority_smid) {
struct scsiio_tracker *st;
 
-   st = mpt3sas_get_st_from_smid(ioc, smid);
-   if (st)
-   cb_idx = st->cb_idx;
+   if (smid < ctl_smid) {
+   st = mpt3sas_get_st_from_smid(ioc, smid);
+   if (st)
+   cb_idx = st->cb_idx;
+   } else if (smid == ctl_smid)
+   cb_idx = ioc->ctl_cb_idx;
} else if (smid < ioc->internal_smid) {
i = smid - ioc->hi_priority_smid;
cb_idx = ioc->hpr_lookup[i].cb_idx;
@@ -2922,7 +2926,9 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 
smid)
ioc->scsi_lookup[i].cb_idx = 0xFF;
ioc->scsi_lookup[i].scmd = NULL;
ioc->scsi_lookup[i].direct_io = 0;
-   list_add(>scsi_lookup[i].tracker_list, >free_list);
+   if (i < ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT)
+   list_add(>scsi_lookup[i].tracker_list,
+>free_list);
spin_unlock_irqrestore(>scsi_lookup_lock, flags);
 
_base_recovery_check(ioc);
@@ -5787,8 +5793,9 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
ioc->scsi_lookup[i].smid = smid;
ioc->scsi_lookup[i].scmd = NULL;
ioc->scsi_lookup[i].direct_io = 0;
-   list_add_tail(>scsi_lookup[i].tracker_list,
-   >free_list);
+   if (i < ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT)
+   list_add_tail(>scsi_lookup[i].tracker_list,
+ >free_list);
}
 
/* hi-priority queue */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c 
b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index b4c374b..4f23498 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -724,14 +724,8 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct 
mpt3_ioctl_command karg,
goto out;
}
} else {
-
-   smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL);
-   if (!smid) {
-   pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
-   ioc->name, __func__);
-   ret = -EAGAIN;
-   goto out;
-   }
+   /* Use first reserved smid for passthrough ioctls */
+   smid = ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT + 1;
}
 
ret = 0;
-- 
2.5.5



[Resend 08/11] mpt3sas: simplify task management functions

2018-01-04 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

No functional change. Code optimization.
One can simply check 'target_busy' or 'device_busy' when figuring
out if there are outstanding commands; no need to painstakingly
counting them by hand.

Signed-off-by: Hannes Reinecke <h...@suse.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 88 +++-
 1 file changed, 7 insertions(+), 81 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 8870cef..c6cbadc 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -1517,74 +1517,6 @@ _scsih_scsi_lookup_find_by_scmd(struct MPT3SAS_ADAPTER 
*ioc, struct scsi_cmnd
 }
 
 /**
- * _scsih_scsi_lookup_find_by_target - search for matching channel:id
- * @ioc: per adapter object
- * @id: target id
- * @channel: channel
- * Context: This function will acquire ioc->scsi_lookup_lock.
- *
- * This will search for a matching channel:id in the scsi_lookup array,
- * returning 1 if found.
- */
-static u8
-_scsih_scsi_lookup_find_by_target(struct MPT3SAS_ADAPTER *ioc, int id,
-   int channel)
-{
-   u8 found;
-   unsigned long   flags;
-   int i;
-
-   spin_lock_irqsave(>scsi_lookup_lock, flags);
-   found = 0;
-   for (i = 0 ; i < ioc->scsiio_depth; i++) {
-   if (ioc->scsi_lookup[i].scmd &&
-   (ioc->scsi_lookup[i].scmd->device->id == id &&
-   ioc->scsi_lookup[i].scmd->device->channel == channel)) {
-   found = 1;
-   goto out;
-   }
-   }
- out:
-   spin_unlock_irqrestore(>scsi_lookup_lock, flags);
-   return found;
-}
-
-/**
- * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
- * @ioc: per adapter object
- * @id: target id
- * @lun: lun number
- * @channel: channel
- * Context: This function will acquire ioc->scsi_lookup_lock.
- *
- * This will search for a matching channel:id:lun in the scsi_lookup array,
- * returning 1 if found.
- */
-static u8
-_scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
-   unsigned int lun, int channel)
-{
-   u8 found;
-   unsigned long   flags;
-   int i;
-
-   spin_lock_irqsave(>scsi_lookup_lock, flags);
-   found = 0;
-   for (i = 0 ; i < ioc->scsiio_depth; i++) {
-   if (ioc->scsi_lookup[i].scmd &&
-   (ioc->scsi_lookup[i].scmd->device->id == id &&
-   ioc->scsi_lookup[i].scmd->device->channel == channel &&
-   ioc->scsi_lookup[i].scmd->device->lun == lun)) {
-   found = 1;
-   goto out;
-   }
-   }
- out:
-   spin_unlock_irqrestore(>scsi_lookup_lock, flags);
-   return found;
-}
-
-/**
  * scsih_change_queue_depth - setting device queue depth
  * @sdev: scsi device struct
  * @qdepth: requested queue depth
@@ -2849,19 +2781,9 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 
handle, uint channel,
rc = FAILED;
break;
 
-   case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
-   if (_scsih_scsi_lookup_find_by_target(ioc, id, channel))
-   rc = FAILED;
-   else
-   rc = SUCCESS;
-   break;
case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
-   if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
-   rc = FAILED;
-   else
-   rc = SUCCESS;
-   break;
+   case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
rc = SUCCESS;
break;
@@ -3082,7 +3004,9 @@ scsih_dev_reset(struct scsi_cmnd *scmd)
r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
scmd->device->id, scmd->device->lun,
MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30);
-
+   /* Check for busy commands after reset */
+   if (r == SUCCESS && atomic_read(>device->device_busy))
+   r = FAILED;
  out:
sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
@@ -3144,7 +3068,9 @@ scsih_target_reset(struct scsi_cmnd *scmd)
r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
30);
-
+   /* Check for busy commands after reset */
+   if (r == SUCCESS && atomic_read(>target_busy))
+   r = FAILED;
  out:
starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
-- 
2.5.5



[Resend 06/11] mpt3sas: check command status before attempting abort

2018-01-04 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

When attempting a command abort we should check the command status
prior to sending the abort; the command might've been completed
already.

Signed-off-by: Hannes Reinecke <h...@suse.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index a11774b..8870cef 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2771,6 +2771,14 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 
handle, uint channel,
return (!rc) ? SUCCESS : FAILED;
}
 
+   if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
+   scsi_lookup = mpt3sas_get_st_from_smid(ioc, smid_task);
+   if (!scsi_lookup)
+   return FAILED;
+   if (scsi_lookup->cb_idx == 0xFF)
+   return SUCCESS;
+   }
+
smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx);
if (!smid) {
pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
@@ -2778,9 +2786,6 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 
handle, uint channel,
return FAILED;
}
 
-   if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
-   scsi_lookup = mpt3sas_get_st_from_smid(ioc, smid_task);
-
dtmprintk(ioc, pr_info(MPT3SAS_FMT
"sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n",
ioc->name, handle, type, smid_task));
-- 
2.5.5



[Resend 09/11] mpt3sas: simplify mpt3sas_scsi_issue_tm()

2018-01-04 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Move the check for outstanding commands out of the function
allowing us to simplify the overall code.

Signed-off-by: Hannes Reinecke <h...@suse.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.h  |   6 +-
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |   4 +-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 106 ---
 3 files changed, 41 insertions(+), 75 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 23e9af5..58ac923 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1444,11 +1444,9 @@ u8 mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER 
*ioc, u8 msix_index,
 void mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase);
 
 int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
-   uint channel, uint id, uint lun, u8 type, u16 smid_task,
-   ulong timeout);
+   u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout);
 int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
-   uint channel, uint id, uint lun, u8 type, u16 smid_task,
-   ulong timeout);
+   u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout);
 
 void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
 void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c 
b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index 4f23498..fc74e22 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -1075,8 +1075,8 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct 
mpt3_ioctl_command karg,
le16_to_cpu(mpi_request->FunctionDependent1));
mpt3sas_halt_firmware(ioc);
mpt3sas_scsih_issue_locked_tm(ioc,
-   le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
-   0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30);
+   le16_to_cpu(mpi_request->FunctionDependent1), 0,
+   MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 0, 30);
} else
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index c6cbadc..e6c8dec 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -1495,25 +1495,24 @@ _scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER 
*ioc, u16 smid)
  * This will search for a scmd pointer in the scsi_lookup array,
  * returning the revelent smid.  A returned value of zero means invalid.
  */
-static u16
+struct scsiio_tracker *
 _scsih_scsi_lookup_find_by_scmd(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd
*scmd)
 {
-   u16 smid;
-   unsigned long   flags;
+   struct scsiio_tracker *st = NULL;
+   unsigned long flags;
int i;
 
spin_lock_irqsave(>scsi_lookup_lock, flags);
-   smid = 0;
for (i = 0; i < ioc->scsiio_depth; i++) {
if (ioc->scsi_lookup[i].scmd == scmd) {
-   smid = ioc->scsi_lookup[i].smid;
+   st = >scsi_lookup[i];
goto out;
}
}
  out:
spin_unlock_irqrestore(>scsi_lookup_lock, flags);
-   return smid;
+   return st;
 }
 
 /**
@@ -2646,32 +2645,30 @@ mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER 
*ioc, u16 handle)
 /**
  * mpt3sas_scsih_issue_tm - main routine for sending tm requests
  * @ioc: per adapter struct
- * @device_handle: device handle
- * @channel: the channel assigned by the OS
- * @id: the id assigned by the OS
+ * @handle: device handle
  * @lun: lun number
  * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
  * @smid_task: smid assigned to the task
+ * @msix_task: MSIX table index supplied by the OS
  * @timeout: timeout in seconds
  * Context: user
  *
  * A generic API for sending task management requests to firmware.
  *
  * The callback index is set inside `ioc->tm_cb_idx`.
+ * The caller is responsible to check for outstanding commands.
  *
  * Return SUCCESS or FAILED.
  */
 int
-mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
-   uint id, uint lun, u8 type, u16 smid_task, ulong timeout)
+mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+   u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout)
 {
Mpi2SCSITaskManagementRequest_t *mpi_request;
Mpi2SCSITaskManagementReply_t *mpi_reply;
u16 smid = 0;
u32 ioc_state;
-   struct scsiio_tracker *scsi_lookup = NULL;
int rc;
-   u16 msix_task = 0;
 
lockdep

[Resend 11/11] mpt3sas: lockless command submission

2018-01-04 Thread Suganath Prabu S
Performance improvement using block layer tag.
Curent driver gets scsiio tracker and free smid from link list
and array based tracking managed by driver.
Accessing  list in main io path is performance pentaly because
of protection using spinlock "scsi_lookup_lock".

In this patch -
1. Driver removes all link list access from main io path and
use scmd->request->tag to get free smid.
2. Instead of holding 'struct scsiio_tracker' in its own pool
driver can embed it into the scsi command.

Driver provides cmd_size in scsi_host_template, so that
struct scsiio_tracker is preallocated by scsi mid layer for each
scsi command.

Signed-off-by: Hannes Reinecke <h...@suse.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 147 ++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  25 ++
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  17 ++--
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 121 -
 drivers/scsi/mpt3sas/mpt3sas_warpdrive.c |  35 +---
 5 files changed, 124 insertions(+), 221 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 2314949..a44b9be 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -889,12 +889,19 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 
msix_index, u32 reply)
 }
 
 struct scsiio_tracker *
-mpt3sas_get_st_from_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+_get_st_from_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 {
+   struct scsi_cmnd *cmd;
+
if (WARN_ON(!smid) ||
WARN_ON(smid >= ioc->hi_priority_smid))
return NULL;
-   return >scsi_lookup[smid - 1];
+
+   cmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid);
+   if (cmd)
+   return scsi_cmd_priv(cmd);
+
+   return NULL;
 }
 
 /**
@@ -915,7 +922,7 @@ _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
struct scsiio_tracker *st;
 
if (smid < ctl_smid) {
-   st = mpt3sas_get_st_from_smid(ioc, smid);
+   st = _get_st_from_smid(ioc, smid);
if (st)
cb_idx = st->cb_idx;
} else if (smid == ctl_smid)
@@ -1302,15 +1309,16 @@ _base_add_sg_single_64(void *paddr, u32 flags_length, 
dma_addr_t dma_addr)
 /**
  * _base_get_chain_buffer_tracker - obtain chain tracker
  * @ioc: per adapter object
- * @smid: smid associated to an IO request
+ * @scmd: SCSI commands of the IO request
  *
  * Returns chain tracker(from ioc->free_chain_list)
  */
 static struct chain_tracker *
-_base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+_base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc,
+  struct scsi_cmnd *scmd)
 {
struct chain_tracker *chain_req;
-   struct scsiio_tracker *st;
+   struct scsiio_tracker *st = scsi_cmd_priv(scmd);
unsigned long flags;
 
spin_lock_irqsave(>scsi_lookup_lock, flags);
@@ -1323,9 +1331,7 @@ _base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER 
*ioc, u16 smid)
chain_req = list_entry(ioc->free_chain_list.next,
struct chain_tracker, tracker_list);
list_del_init(_req->tracker_list);
-   st = mpt3sas_get_st_from_smid(ioc, smid);
-   if (st)
-   list_add_tail(_req->tracker_list, >chain_list);
+   list_add_tail(_req->tracker_list, >chain_list);
spin_unlock_irqrestore(>scsi_lookup_lock, flags);
return chain_req;
 }
@@ -1940,7 +1946,7 @@ _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc,
 
/* initializing the chain flags and pointers */
chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
-   chain_req = _base_get_chain_buffer_tracker(ioc, smid);
+   chain_req = _base_get_chain_buffer_tracker(ioc, scmd);
if (!chain_req)
return -1;
chain = chain_req->chain_buffer;
@@ -1980,7 +1986,7 @@ _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc,
sges_in_segment--;
}
 
-   chain_req = _base_get_chain_buffer_tracker(ioc, smid);
+   chain_req = _base_get_chain_buffer_tracker(ioc, scmd);
if (!chain_req)
return -1;
chain = chain_req->chain_buffer;
@@ -2083,7 +2089,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
}
 
/* initializing the pointers */
-   chain_req = _base_get_chain_buffer_tracker(ioc, smid);
+   chain_req = _base_get_chain_buffer_tracker(ioc, scmd);
if (!chain_req)
return -1;
chain = chain_req->chain_buffer;
@@ -2114,7 +2120,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
sges_in_segment--;
   

[Resend 10/11] mpt3sas: simplify _wait_for_commands_to_complete()

2018-01-04 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Use 'host_busy' instead of counting outstanding commands by hand.

Signed-off-by: Hannes Reinecke <h...@suse.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index d4b32af..2314949 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -2898,9 +2898,9 @@ _base_recovery_check(struct MPT3SAS_ADAPTER *ioc)
 * See _wait_for_commands_to_complete() call with regards to this code.
 */
if (ioc->shost_recovery && ioc->pending_io_count) {
-   if (ioc->pending_io_count == 1)
+   ioc->pending_io_count = atomic_read(>shost->host_busy);
+   if (ioc->pending_io_count == 0)
wake_up(>reset_wq);
-   ioc->pending_io_count--;
}
 }
 
@@ -6310,15 +6310,13 @@ _base_reset_handler(struct MPT3SAS_ADAPTER *ioc, int 
reset_phase)
  * _wait_for_commands_to_complete - reset controller
  * @ioc: Pointer to MPT_ADAPTER structure
  *
- * This function waiting(3s) for all pending commands to complete
+ * This function is waiting 10s for all pending commands to complete
  * prior to putting controller in reset.
  */
 static void
 _wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc)
 {
u32 ioc_state;
-   unsigned long flags;
-   u16 i;
 
ioc->pending_io_count = 0;
 
@@ -6327,11 +6325,7 @@ _wait_for_commands_to_complete(struct MPT3SAS_ADAPTER 
*ioc)
return;
 
/* pending command count */
-   spin_lock_irqsave(>scsi_lookup_lock, flags);
-   for (i = 0; i < ioc->scsiio_depth; i++)
-   if (ioc->scsi_lookup[i].cb_idx != 0xFF)
-   ioc->pending_io_count++;
-   spin_unlock_irqrestore(>scsi_lookup_lock, flags);
+   ioc->pending_io_count = atomic_read(>shost->host_busy);
 
if (!ioc->pending_io_count)
return;
-- 
2.5.5



[Resend 01/11] mpt3sas: set default value for cb_idx

2018-01-04 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

No functional change

Signed-off-by: Hannes Reinecke <h...@suse.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 08237b8..e3857e5 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -899,7 +899,7 @@ static u8
 _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 {
int i;
-   u8 cb_idx;
+   u8 cb_idx = 0xFF;
 
if (smid < ioc->hi_priority_smid) {
i = smid - 1;
@@ -910,8 +910,7 @@ _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
} else if (smid <= ioc->hba_queue_depth) {
i = smid - ioc->internal_smid;
cb_idx = ioc->internal_lookup[i].cb_idx;
-   } else
-   cb_idx = 0xFF;
+   }
return cb_idx;
 }
 
-- 
2.5.5



[PATCH 11/11] mpt3sas: lockless command submission

2017-12-21 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Performance improvement using block layer tag.
Curent driver gets scsiio tracker and free smid from link list
and array based tracking managed by driver.
Accessing  list in main io path is performance pentaly because
of proection using spinlock "scsi_lookup_lock". 

In this patch -
1. Driver removes all link list access from main io path and
use scmd->request->tag to get free smid.
2. Instead of holding 'struct scsiio_tracker' in its own pool
driver can embed it into the scsi command. 

Driver provides cmd_size in scsi_host_template, so that
struct scsiio_tracker is preallocated by scsi mid layer for each
scsi command.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 147 ++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  25 ++
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  17 ++--
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 121 -
 drivers/scsi/mpt3sas/mpt3sas_warpdrive.c |  35 +---
 5 files changed, 124 insertions(+), 221 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index eb4cc20..2730bb5 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -889,12 +889,19 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 
msix_index, u32 reply)
 }
 
 struct scsiio_tracker *
-mpt3sas_get_st_from_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+_get_st_from_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 {
+   struct scsi_cmnd *cmd;
+
if (WARN_ON(!smid) ||
WARN_ON(smid >= ioc->hi_priority_smid))
return NULL;
-   return >scsi_lookup[smid - 1];
+
+   cmd = mpt3sas_scsih_scsi_lookup_get(ioc, smid);
+   if (cmd)
+   return scsi_cmd_priv(cmd);
+
+   return NULL;
 }
 
 /**
@@ -915,7 +922,7 @@ _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
struct scsiio_tracker *st;
 
if (smid < ctl_smid) {
-   st = mpt3sas_get_st_from_smid(ioc, smid);
+   st = _get_st_from_smid(ioc, smid);
if (st)
cb_idx = st->cb_idx;
} else if (smid == ctl_smid)
@@ -1302,15 +1309,16 @@ _base_add_sg_single_64(void *paddr, u32 flags_length, 
dma_addr_t dma_addr)
 /**
  * _base_get_chain_buffer_tracker - obtain chain tracker
  * @ioc: per adapter object
- * @smid: smid associated to an IO request
+ * @scmd: SCSI commands of the IO request
  *
  * Returns chain tracker(from ioc->free_chain_list)
  */
 static struct chain_tracker *
-_base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+_base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc,
+  struct scsi_cmnd *scmd)
 {
struct chain_tracker *chain_req;
-   struct scsiio_tracker *st;
+   struct scsiio_tracker *st = scsi_cmd_priv(scmd);
unsigned long flags;
 
spin_lock_irqsave(>scsi_lookup_lock, flags);
@@ -1323,9 +1331,7 @@ _base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER 
*ioc, u16 smid)
chain_req = list_entry(ioc->free_chain_list.next,
struct chain_tracker, tracker_list);
list_del_init(_req->tracker_list);
-   st = mpt3sas_get_st_from_smid(ioc, smid);
-   if (st)
-   list_add_tail(_req->tracker_list, >chain_list);
+   list_add_tail(_req->tracker_list, >chain_list);
spin_unlock_irqrestore(>scsi_lookup_lock, flags);
return chain_req;
 }
@@ -1940,7 +1946,7 @@ _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc,
 
/* initializing the chain flags and pointers */
chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
-   chain_req = _base_get_chain_buffer_tracker(ioc, smid);
+   chain_req = _base_get_chain_buffer_tracker(ioc, scmd);
if (!chain_req)
return -1;
chain = chain_req->chain_buffer;
@@ -1980,7 +1986,7 @@ _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc,
sges_in_segment--;
}
 
-   chain_req = _base_get_chain_buffer_tracker(ioc, smid);
+   chain_req = _base_get_chain_buffer_tracker(ioc, scmd);
if (!chain_req)
return -1;
chain = chain_req->chain_buffer;
@@ -2083,7 +2089,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
}
 
/* initializing the pointers */
-   chain_req = _base_get_chain_buffer_tracker(ioc, smid);
+   chain_req = _base_get_chain_buffer_tracker(ioc, scmd);
if (!chain_req)
return -1;
chain = chain_req->chain_buffer;
@@ -2114,7 +2120,7 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *io

[PATCH 05/11] mpt3sas: Introduce mpt3sas_get_st_from_smid()

2017-12-21 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Abstract accesses to the scsi_lookup array by introducing
mpt3sas_get_st_from_smid().

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 22 ++
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  2 ++
 drivers/scsi/mpt3sas/mpt3sas_scsih.c |  7 ---
 drivers/scsi/mpt3sas/mpt3sas_warpdrive.c |  4 +++-
 4 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 35d36a9..afe42a8 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -888,6 +888,15 @@ _base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 
msix_index, u32 reply)
return 1;
 }
 
+struct scsiio_tracker *
+mpt3sas_get_st_from_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid)
+{
+   if (WARN_ON(!smid) ||
+   WARN_ON(smid >= ioc->hi_priority_smid))
+   return NULL;
+   return >scsi_lookup[smid - 1];
+}
+
 /**
  * _base_get_cb_idx - obtain the callback index
  * @ioc: per adapter object
@@ -902,8 +911,11 @@ _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
u8 cb_idx = 0xFF;
 
if (smid < ioc->hi_priority_smid) {
-   i = smid - 1;
-   cb_idx = ioc->scsi_lookup[i].cb_idx;
+   struct scsiio_tracker *st;
+
+   st = mpt3sas_get_st_from_smid(ioc, smid);
+   if (st)
+   cb_idx = st->cb_idx;
} else if (smid < ioc->internal_smid) {
i = smid - ioc->hi_priority_smid;
cb_idx = ioc->hpr_lookup[i].cb_idx;
@@ -1294,6 +1306,7 @@ static struct chain_tracker *
 _base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 {
struct chain_tracker *chain_req;
+   struct scsiio_tracker *st;
unsigned long flags;
 
spin_lock_irqsave(>scsi_lookup_lock, flags);
@@ -1306,8 +1319,9 @@ _base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER 
*ioc, u16 smid)
chain_req = list_entry(ioc->free_chain_list.next,
struct chain_tracker, tracker_list);
list_del_init(_req->tracker_list);
-   list_add_tail(_req->tracker_list,
-   >scsi_lookup[smid - 1].chain_list);
+   st = mpt3sas_get_st_from_smid(ioc, smid);
+   if (st)
+   list_add_tail(_req->tracker_list, >chain_list);
spin_unlock_irqrestore(>scsi_lookup_lock, flags);
return chain_req;
 }
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 60f42ca..23e9af5 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1402,6 +1402,8 @@ void mpt3sas_base_sync_reply_irqs(struct MPT3SAS_ADAPTER 
*ioc);
 u16 mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx);
 u16 mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx,
struct scsi_cmnd *scmd);
+struct scsiio_tracker *mpt3sas_get_st_from_smid(struct MPT3SAS_ADAPTER *ioc,
+   u16 smid);
 
 u16 mpt3sas_base_get_smid(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx);
 void mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 7d76e8f..aae7396 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2779,7 +2779,7 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 
handle, uint channel,
}
 
if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
-   scsi_lookup = >scsi_lookup[smid_task - 1];
+   scsi_lookup = mpt3sas_get_st_from_smid(ioc, smid_task);
 
dtmprintk(ioc, pr_info(MPT3SAS_FMT
"sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n",
@@ -2797,7 +2797,8 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 
handle, uint channel,
mpt3sas_scsih_set_tm_flag(ioc, handle);
init_completion(>tm_cmds.done);
if ((type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) &&
-   (scsi_lookup->msix_io < ioc->reply_queue_count))
+   scsi_lookup &&
+   (scsi_lookup->msix_io < ioc->reply_queue_count))
msix_task = scsi_lookup->msix_io;
else
msix_task = 0;
@@ -2838,7 +2839,7 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 
handle, uint channel,
switch (type) {
case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK:
rc = SUCCESS;
-   if (scsi_lookup->scmd == NULL)
+   if (scsi_lookup && scsi_lookup->scmd == NULL)
break;
rc = FAILED;
break;
diff --git a/drivers/scsi/mpt3sa

[PATCH 08/11] mpt3sas: simplify task management functions

2017-12-21 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

No functional change. Code optimization.
One can simply check 'target_busy' or 'device_busy' when figuring
out if there are outstanding commands; no need to painstakingly
counting them by hand.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 88 +++-
 1 file changed, 7 insertions(+), 81 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 0434fd6..c8216c4 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -1517,74 +1517,6 @@ _scsih_scsi_lookup_find_by_scmd(struct MPT3SAS_ADAPTER 
*ioc, struct scsi_cmnd
 }
 
 /**
- * _scsih_scsi_lookup_find_by_target - search for matching channel:id
- * @ioc: per adapter object
- * @id: target id
- * @channel: channel
- * Context: This function will acquire ioc->scsi_lookup_lock.
- *
- * This will search for a matching channel:id in the scsi_lookup array,
- * returning 1 if found.
- */
-static u8
-_scsih_scsi_lookup_find_by_target(struct MPT3SAS_ADAPTER *ioc, int id,
-   int channel)
-{
-   u8 found;
-   unsigned long   flags;
-   int i;
-
-   spin_lock_irqsave(>scsi_lookup_lock, flags);
-   found = 0;
-   for (i = 0 ; i < ioc->scsiio_depth; i++) {
-   if (ioc->scsi_lookup[i].scmd &&
-   (ioc->scsi_lookup[i].scmd->device->id == id &&
-   ioc->scsi_lookup[i].scmd->device->channel == channel)) {
-   found = 1;
-   goto out;
-   }
-   }
- out:
-   spin_unlock_irqrestore(>scsi_lookup_lock, flags);
-   return found;
-}
-
-/**
- * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun
- * @ioc: per adapter object
- * @id: target id
- * @lun: lun number
- * @channel: channel
- * Context: This function will acquire ioc->scsi_lookup_lock.
- *
- * This will search for a matching channel:id:lun in the scsi_lookup array,
- * returning 1 if found.
- */
-static u8
-_scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id,
-   unsigned int lun, int channel)
-{
-   u8 found;
-   unsigned long   flags;
-   int i;
-
-   spin_lock_irqsave(>scsi_lookup_lock, flags);
-   found = 0;
-   for (i = 0 ; i < ioc->scsiio_depth; i++) {
-   if (ioc->scsi_lookup[i].scmd &&
-   (ioc->scsi_lookup[i].scmd->device->id == id &&
-   ioc->scsi_lookup[i].scmd->device->channel == channel &&
-   ioc->scsi_lookup[i].scmd->device->lun == lun)) {
-   found = 1;
-   goto out;
-   }
-   }
- out:
-   spin_unlock_irqrestore(>scsi_lookup_lock, flags);
-   return found;
-}
-
-/**
  * scsih_change_queue_depth - setting device queue depth
  * @sdev: scsi device struct
  * @qdepth: requested queue depth
@@ -2849,19 +2781,9 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 
handle, uint channel,
rc = FAILED;
break;
 
-   case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
-   if (_scsih_scsi_lookup_find_by_target(ioc, id, channel))
-   rc = FAILED;
-   else
-   rc = SUCCESS;
-   break;
case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET:
case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET:
-   if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel))
-   rc = FAILED;
-   else
-   rc = SUCCESS;
-   break;
+   case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET:
case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK:
rc = SUCCESS;
break;
@@ -3082,7 +3004,9 @@ scsih_dev_reset(struct scsi_cmnd *scmd)
r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
scmd->device->id, scmd->device->lun,
MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30);
-
+   /* Check for busy commands after reset */
+   if (r == SUCCESS && atomic_read(>device->device_busy))
+   r = FAILED;
  out:
sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n",
((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
@@ -3144,7 +3068,9 @@ scsih_target_reset(struct scsi_cmnd *scmd)
r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->channel,
scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
30);
-
+   /* Check for busy commands after reset */
+   if (r == SUCCESS && atomic_read(>target_busy))
+   r = FAILED;
  out:
starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n",
((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
-- 
2.5.5



[PATCH 06/11] mpt3sas: check command status before attempting abort

2017-12-21 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

When attempting a command abort we should check the command status
prior to sending the abort; the command might've been completed
already.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index aae7396..0434fd6 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2771,6 +2771,14 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 
handle, uint channel,
return (!rc) ? SUCCESS : FAILED;
}
 
+   if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
+   scsi_lookup = mpt3sas_get_st_from_smid(ioc, smid_task);
+   if (!scsi_lookup)
+   return FAILED;
+   if (scsi_lookup->cb_idx == 0xFF)
+   return SUCCESS;
+   }
+
smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx);
if (!smid) {
pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
@@ -2778,9 +2786,6 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 
handle, uint channel,
return FAILED;
}
 
-   if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK)
-   scsi_lookup = mpt3sas_get_st_from_smid(ioc, smid_task);
-
dtmprintk(ioc, pr_info(MPT3SAS_FMT
"sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n",
ioc->name, handle, type, smid_task));
-- 
2.5.5



[PATCH 04/11] mpt3sas: open-code _scsih_scsi_lookup_get()

2017-12-21 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Just a wrapper around the scsi lookup array and only used
in one place, so open-code it.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 15 +--
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 6fea5e6..7d76e8f 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -1445,19 +1445,6 @@ _scsih_is_nvme_device(u32 device_info)
 }
 
 /**
- * _scsih_scsi_lookup_get - returns scmd entry
- * @ioc: per adapter object
- * @smid: system request message index
- *
- * Returns the smid stored scmd pointer.
- */
-static struct scsi_cmnd *
-_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid)
-{
-   return ioc->scsi_lookup[smid - 1].scmd;
-}
-
-/**
  * __scsih_scsi_lookup_get_clear - returns scmd entry without
  * holding any lock.
  * @ioc: per adapter object
@@ -7541,7 +7528,7 @@ _scsih_sas_broadcast_primitive_event(struct 
MPT3SAS_ADAPTER *ioc,
for (smid = 1; smid <= ioc->scsiio_depth; smid++) {
if (ioc->shost_recovery)
goto out;
-   scmd = _scsih_scsi_lookup_get(ioc, smid);
+   scmd = ioc->scsi_lookup[smid - 1].scmd;
if (!scmd)
continue;
sdev = scmd->device;
-- 
2.5.5



[PATCH 02/11] mpt3sas: use list_splice_init()

2017-12-21 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Use 'list_splice_init()' instead of hand-crafted function.
No functional change.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 0119a39..5a9ad26 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -2885,20 +2885,13 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 
smid)
 {
unsigned long flags;
int i;
-   struct chain_tracker *chain_req, *next;
 
spin_lock_irqsave(>scsi_lookup_lock, flags);
if (smid < ioc->hi_priority_smid) {
/* scsiio queue */
i = smid - 1;
-   if (!list_empty(>scsi_lookup[i].chain_list)) {
-   list_for_each_entry_safe(chain_req, next,
-   >scsi_lookup[i].chain_list, tracker_list) {
-   list_del_init(_req->tracker_list);
-   list_add(_req->tracker_list,
-   >free_chain_list);
-   }
-   }
+   list_splice_init(>scsi_lookup[i].chain_list,
+>free_chain_list);
ioc->scsi_lookup[i].cb_idx = 0xFF;
ioc->scsi_lookup[i].scmd = NULL;
ioc->scsi_lookup[i].direct_io = 0;
-- 
2.5.5



[PATCH 10/11] mpt3sas: simplify _wait_for_commands_to_complete()

2017-12-21 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Use 'host_busy' instead of counting outstanding commands by hand.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index a49040e..eb4cc20 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -2898,9 +2898,9 @@ _base_recovery_check(struct MPT3SAS_ADAPTER *ioc)
 * See _wait_for_commands_to_complete() call with regards to this code.
 */
if (ioc->shost_recovery && ioc->pending_io_count) {
-   if (ioc->pending_io_count == 1)
+   ioc->pending_io_count = atomic_read(>shost->host_busy);
+   if (ioc->pending_io_count == 0)
wake_up(>reset_wq);
-   ioc->pending_io_count--;
}
 }
 
@@ -6310,15 +6310,13 @@ _base_reset_handler(struct MPT3SAS_ADAPTER *ioc, int 
reset_phase)
  * _wait_for_commands_to_complete - reset controller
  * @ioc: Pointer to MPT_ADAPTER structure
  *
- * This function waiting(3s) for all pending commands to complete
+ * This function is waiting 10s for all pending commands to complete
  * prior to putting controller in reset.
  */
 static void
 _wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc)
 {
u32 ioc_state;
-   unsigned long flags;
-   u16 i;
 
ioc->pending_io_count = 0;
 
@@ -6327,11 +6325,7 @@ _wait_for_commands_to_complete(struct MPT3SAS_ADAPTER 
*ioc)
return;
 
/* pending command count */
-   spin_lock_irqsave(>scsi_lookup_lock, flags);
-   for (i = 0; i < ioc->scsiio_depth; i++)
-   if (ioc->scsi_lookup[i].cb_idx != 0xFF)
-   ioc->pending_io_count++;
-   spin_unlock_irqrestore(>scsi_lookup_lock, flags);
+   ioc->pending_io_count = atomic_read(>shost->host_busy);
 
if (!ioc->pending_io_count)
return;
-- 
2.5.5



[PATCH 07/11] mpt3sas: always use first reserved smid for ioctl passthrough

2017-12-21 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

ioctl passthrough commands require a SCSIIO smid, but cannot
easily integrate with the block layer. But the driver already
has reserved some SCSIIO smids and we're only ever allowing
one ioctl command at a time we can use the first reserved smid
for ioctl commands.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 19 +--
 drivers/scsi/mpt3sas/mpt3sas_ctl.c  | 10 ++
 2 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index afe42a8..a49040e 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -908,14 +908,18 @@ static u8
 _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 {
int i;
+   u16 ctl_smid = ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT + 1;
u8 cb_idx = 0xFF;
 
if (smid < ioc->hi_priority_smid) {
struct scsiio_tracker *st;
 
-   st = mpt3sas_get_st_from_smid(ioc, smid);
-   if (st)
-   cb_idx = st->cb_idx;
+   if (smid < ctl_smid) {
+   st = mpt3sas_get_st_from_smid(ioc, smid);
+   if (st)
+   cb_idx = st->cb_idx;
+   } else if (smid == ctl_smid)
+   cb_idx = ioc->ctl_cb_idx;
} else if (smid < ioc->internal_smid) {
i = smid - ioc->hi_priority_smid;
cb_idx = ioc->hpr_lookup[i].cb_idx;
@@ -2922,7 +2926,9 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 
smid)
ioc->scsi_lookup[i].cb_idx = 0xFF;
ioc->scsi_lookup[i].scmd = NULL;
ioc->scsi_lookup[i].direct_io = 0;
-   list_add(>scsi_lookup[i].tracker_list, >free_list);
+   if (i < ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT)
+   list_add(>scsi_lookup[i].tracker_list,
+>free_list);
spin_unlock_irqrestore(>scsi_lookup_lock, flags);
 
_base_recovery_check(ioc);
@@ -5787,8 +5793,9 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
ioc->scsi_lookup[i].smid = smid;
ioc->scsi_lookup[i].scmd = NULL;
ioc->scsi_lookup[i].direct_io = 0;
-   list_add_tail(>scsi_lookup[i].tracker_list,
-   >free_list);
+   if (i < ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT)
+   list_add_tail(>scsi_lookup[i].tracker_list,
+ >free_list);
}
 
/* hi-priority queue */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c 
b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index b4c374b..4f23498 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -724,14 +724,8 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct 
mpt3_ioctl_command karg,
goto out;
}
} else {
-
-   smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL);
-   if (!smid) {
-   pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
-   ioc->name, __func__);
-   ret = -EAGAIN;
-   goto out;
-   }
+   /* Use first reserved smid for passthrough ioctls */
+   smid = ioc->scsiio_depth - INTERNAL_SCSIIO_CMDS_COUNT + 1;
}
 
ret = 0;
-- 
2.5.5



[PATCH 09/11] mpt3sas: simplify mpt3sas_scsi_issue_tm()

2017-12-21 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Move the check for outstanding commands out of the function
allowing us to simplify the overall code.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.h  |   6 +-
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |   4 +-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 106 ---
 3 files changed, 41 insertions(+), 75 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 23e9af5..58ac923 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1444,11 +1444,9 @@ u8 mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER 
*ioc, u8 msix_index,
 void mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase);
 
 int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
-   uint channel, uint id, uint lun, u8 type, u16 smid_task,
-   ulong timeout);
+   u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout);
 int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
-   uint channel, uint id, uint lun, u8 type, u16 smid_task,
-   ulong timeout);
+   u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout);
 
 void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
 void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c 
b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index 4f23498..fc74e22 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -1075,8 +1075,8 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct 
mpt3_ioctl_command karg,
le16_to_cpu(mpi_request->FunctionDependent1));
mpt3sas_halt_firmware(ioc);
mpt3sas_scsih_issue_locked_tm(ioc,
-   le16_to_cpu(mpi_request->FunctionDependent1), 0, 0,
-   0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30);
+   le16_to_cpu(mpi_request->FunctionDependent1), 0,
+   MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 0, 30);
} else
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index c8216c4..27e1506 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -1495,25 +1495,24 @@ _scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER 
*ioc, u16 smid)
  * This will search for a scmd pointer in the scsi_lookup array,
  * returning the revelent smid.  A returned value of zero means invalid.
  */
-static u16
+struct scsiio_tracker *
 _scsih_scsi_lookup_find_by_scmd(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd
*scmd)
 {
-   u16 smid;
-   unsigned long   flags;
+   struct scsiio_tracker *st = NULL;
+   unsigned long flags;
int i;
 
spin_lock_irqsave(>scsi_lookup_lock, flags);
-   smid = 0;
for (i = 0; i < ioc->scsiio_depth; i++) {
if (ioc->scsi_lookup[i].scmd == scmd) {
-   smid = ioc->scsi_lookup[i].smid;
+   st = >scsi_lookup[i];
goto out;
}
}
  out:
spin_unlock_irqrestore(>scsi_lookup_lock, flags);
-   return smid;
+   return st;
 }
 
 /**
@@ -2646,32 +2645,30 @@ mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER 
*ioc, u16 handle)
 /**
  * mpt3sas_scsih_issue_tm - main routine for sending tm requests
  * @ioc: per adapter struct
- * @device_handle: device handle
- * @channel: the channel assigned by the OS
- * @id: the id assigned by the OS
+ * @handle: device handle
  * @lun: lun number
  * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
  * @smid_task: smid assigned to the task
+ * @msix_task: MSIX table index supplied by the OS
  * @timeout: timeout in seconds
  * Context: user
  *
  * A generic API for sending task management requests to firmware.
  *
  * The callback index is set inside `ioc->tm_cb_idx`.
+ * The caller is responsible to check for outstanding commands.
  *
  * Return SUCCESS or FAILED.
  */
 int
-mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel,
-   uint id, uint lun, u8 type, u16 smid_task, ulong timeout)
+mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
+   u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout)
 {
Mpi2SCSITaskManagementRequest_t *mpi_request;
Mpi2SCSITaskManagementReply_t *mpi_reply;
u16 smid = 0;
u32 ioc_state;
-   struct scsiio_tracker *scsi_lookup = NULL;
int rc;
-   u16 msix_task = 0;
 
   

[PATCH 03/11] mpt3sas: separate out _base_recovery_check()

2017-12-21 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

No functional change.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 23 ++-
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 5a9ad26..35d36a9 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -2873,6 +2873,19 @@ mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, 
u8 cb_idx)
return smid;
 }
 
+static void
+_base_recovery_check(struct MPT3SAS_ADAPTER *ioc)
+{
+   /*
+* See _wait_for_commands_to_complete() call with regards to this code.
+*/
+   if (ioc->shost_recovery && ioc->pending_io_count) {
+   if (ioc->pending_io_count == 1)
+   wake_up(>reset_wq);
+   ioc->pending_io_count--;
+   }
+}
+
 /**
  * mpt3sas_base_free_smid - put smid back on free_list
  * @ioc: per adapter object
@@ -2898,15 +2911,7 @@ mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 
smid)
list_add(>scsi_lookup[i].tracker_list, >free_list);
spin_unlock_irqrestore(>scsi_lookup_lock, flags);
 
-   /*
-* See _wait_for_commands_to_complete() call with regards
-* to this code.
-*/
-   if (ioc->shost_recovery && ioc->pending_io_count) {
-   if (ioc->pending_io_count == 1)
-   wake_up(>reset_wq);
-   ioc->pending_io_count--;
-   }
+   _base_recovery_check(ioc);
return;
} else if (smid < ioc->internal_smid) {
/* hi-priority */
-- 
2.5.5



[PATCH 01/11] mpt3sas: set default value for cb_idx

2017-12-21 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

No functional change

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
---
 drivers/scsi/mpt3sas/modules.order  | 2 +-
 drivers/scsi/mpt3sas/mpt3sas_base.c | 5 ++---
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/mpt3sas/modules.order 
b/drivers/scsi/mpt3sas/modules.order
index 352a4dd..5052fdf 100644
--- a/drivers/scsi/mpt3sas/modules.order
+++ b/drivers/scsi/mpt3sas/modules.order
@@ -1 +1 @@
-kernel/drivers/scsi/mpt3sas/mpt3sas.ko
+kernel//opt/upstream_io_tag/linux/drivers/scsi/mpt3sas/mpt3sas.ko
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 8027de4..0119a39 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -899,7 +899,7 @@ static u8
 _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
 {
int i;
-   u8 cb_idx;
+   u8 cb_idx = 0xFF;
 
if (smid < ioc->hi_priority_smid) {
i = smid - 1;
@@ -910,8 +910,7 @@ _base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid)
} else if (smid <= ioc->hba_queue_depth) {
i = smid - ioc->internal_smid;
cb_idx = ioc->internal_lookup[i].cb_idx;
-   } else
-   cb_idx = 0xFF;
+   }
return cb_idx;
 }
 
-- 
2.5.5



[PATCH 00/11] mpt3sas: Enable scsi MQ & lockless command submission

2017-12-21 Thread Suganath Prabu S
From: Hannes Reinecke <h...@suse.de>

Hi all,

This patch set is initially posted by Hannes Reinecke to enable scsi
multiqueue for the mpt3sas driver.
While the HBA only has a single mailbox register for submitting commands,
it does have individual receive queues per MSI-X interrupt and as such
does benefit from converting it to full multiqueue support. 

Suganath Prabu S (11):
  mpt3sas: set default value for cb_idx
  mpt3sas: use list_splice_init()
  mpt3sas: separate out _base_recovery_check()
  mpt3sas: open-code _scsih_scsi_lookup_get()
  mpt3sas: Introduce mpt3sas_get_st_from_smid()
  mpt3sas: check command status before attempting abort
  mpt3sas: always use first reserved smid for ioctl  passthrough
  mpt3sas: simplify task management functions
  mpt3sas: simplify mpt3sas_scsi_issue_tm()
  mpt3sas: simplify _wait_for_commands_to_complete()
  mpt3sas: lockless command submission

 drivers/scsi/mpt3sas/modules.order   |   2 +-
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 199 +++--
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  29 ++-
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  31 ++--
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 292 +++
 drivers/scsi/mpt3sas/mpt3sas_warpdrive.c |  33 +---
 6 files changed, 192 insertions(+), 394 deletions(-)

Thanks,
Suganath Prabu S
-- 
2.5.5



[PATCH] mpt3sas: Remove unused variable requeue_event

2017-12-02 Thread Suganath Prabu S
No Functional change just cleanup,
Removed variable requeue_event and made function as void.

Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 12 +---
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 362f406..c71f964 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -7211,7 +7211,7 @@ _scsih_pcie_topology_change_event_debug(struct 
MPT3SAS_ADAPTER *ioc,
  * Context: user.
  *
  */
-static int
+static void
 _scsih_pcie_topology_change_event(struct MPT3SAS_ADAPTER *ioc,
struct fw_event_work *fw_event)
 {
@@ -7221,7 +7221,6 @@ _scsih_pcie_topology_change_event(struct MPT3SAS_ADAPTER 
*ioc,
u8 link_rate, prev_link_rate;
unsigned long flags;
int rc;
-   int requeue_event;
Mpi26EventDataPCIeTopologyChangeList_t *event_data =
(Mpi26EventDataPCIeTopologyChangeList_t *) fw_event->event_data;
struct _pcie_device *pcie_device;
@@ -7231,12 +7230,12 @@ _scsih_pcie_topology_change_event(struct 
MPT3SAS_ADAPTER *ioc,
 
if (ioc->shost_recovery || ioc->remove_host ||
ioc->pci_error_recovery)
-   return 0;
+   return;
 
if (fw_event->ignore) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT "ignoring switch event\n",
ioc->name));
-   return 0;
+   return;
}
 
/* handle siblings events */
@@ -7244,10 +7243,10 @@ _scsih_pcie_topology_change_event(struct 
MPT3SAS_ADAPTER *ioc,
if (fw_event->ignore) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"ignoring switch event\n", ioc->name));
-   return 0;
+   return;
}
if (ioc->remove_host || ioc->pci_error_recovery)
-   return 0;
+   return;
reason_code = event_data->PortEntry[i].PortStatus;
handle =
le16_to_cpu(event_data->PortEntry[i].AttachedDevHandle);
@@ -7316,7 +7315,6 @@ _scsih_pcie_topology_change_event(struct MPT3SAS_ADAPTER 
*ioc,
break;
}
}
-   return requeue_event;
 }
 
 /**
-- 
2.5.5



[PATCH 04/13] mpt3sas: API 's to support NVMe drive addition to SML

2017-10-31 Thread Suganath Prabu S
Below Functions are added in various paths to support NVMe
drive addition.

_scsih_pcie_add_device
_scsih_pcie_device_add
_scsih_pcie_device_init_add
_scsih_check_pcie_access_status
_scsih_pcie_check_device

mpt3sas_get_pdev_by_handle

mpt3sas_config_get_pcie_device_pg0
mpt3sas_config_get_pcie_device_pg2

Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.h   |  10 +
 drivers/scsi/mpt3sas/mpt3sas_config.c | 100 
 drivers/scsi/mpt3sas/mpt3sas_scsih.c  | 457 +-
 3 files changed, 565 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 034b34d..a4ec459 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -1464,6 +1464,10 @@ struct _sas_device *mpt3sas_get_sdev_by_addr(
 struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
 struct _sas_device *__mpt3sas_get_sdev_by_addr(
 struct MPT3SAS_ADAPTER *ioc, u64 sas_address);
+struct _sas_device *mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc,
+   u16 handle);
+struct _pcie_device *mpt3sas_get_pdev_by_handle(struct MPT3SAS_ADAPTER *ioc,
+   u16 handle);
 
 void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc);
 struct _raid_device *
@@ -1502,6 +1506,12 @@ int mpt3sas_config_get_sas_device_pg0(struct 
MPT3SAS_ADAPTER *ioc,
 int mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page,
u32 form, u32 handle);
+int mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
+   Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
+   u32 form, u32 handle);
+int mpt3sas_config_get_pcie_device_pg2(struct MPT3SAS_ADAPTER *ioc,
+   Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage2_t *config_page,
+   u32 form, u32 handle);
 int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page,
u16 sz);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_config.c 
b/drivers/scsi/mpt3sas/mpt3sas_config.c
index dd62701..1c747cf 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_config.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_config.c
@@ -150,6 +150,24 @@ _config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, 
u16 smid,
case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
desc = "driver_mapping";
break;
+   case MPI2_CONFIG_EXTPAGETYPE_SAS_PORT:
+   desc = "sas_port";
+   break;
+   case MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING:
+   desc = "ext_manufacturing";
+   break;
+   case MPI2_CONFIG_EXTPAGETYPE_PCIE_IO_UNIT:
+   desc = "pcie_io_unit";
+   break;
+   case MPI2_CONFIG_EXTPAGETYPE_PCIE_SWITCH:
+   desc = "pcie_switch";
+   break;
+   case MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE:
+   desc = "pcie_device";
+   break;
+   case MPI2_CONFIG_EXTPAGETYPE_PCIE_LINK:
+   desc = "pcie_link";
+   break;
}
break;
}
@@ -1053,6 +1071,88 @@ mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER 
*ioc,
 }
 
 /**
+ * mpt3sas_config_get_pcie_device_pg0 - obtain pcie device page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: device handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt3sas_config_get_pcie_device_pg0(struct MPT3SAS_ADAPTER *ioc,
+   Mpi2ConfigReply_t *mpi_reply, Mpi26PCIeDevicePage0_t *config_page,
+   u32 form, u32 handle)
+{
+   Mpi2ConfigRequest_t mpi_request;
+   int r;
+
+   memset(_request, 0, sizeof(Mpi2ConfigRequest_t));
+   mpi_request.Function = MPI2_FUNCTION_CONFIG;
+   mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+   mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+   mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_PCIE_DEVICE;
+   mpi_request.Header.PageVersion = MPI26_PCIEDEVICE0_PAGEVERSION;
+   mpi_request.Header.PageNumber = 0;
+   ioc->build_zero_len_sge_mpi(ioc, _request.PageBufferSGE);
+   r = _config_request(ioc, _request, mpi_reply,
+   MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0);
+   if (r)
+   goto out;
+
+   mpi_request.PageAddress = cpu_to_le32(form | handle);
+   mpi_request.Action = MPI2_

[PATCH 00/13] mpt3sas driver NVMe support:

2017-10-31 Thread Suganath Prabu S
Ventura Series controller are Tri-mode. The controller and
firmware are capable of supporting NVMe devices and
PCIe switches to be connected with the controller. This
patch set adds driver level support for NVMe devices and
PCIe switches.

Suganath Prabu S (13):
  mpt3sas: Add nvme device support in slave alloc,  target  alloc
and probe
  mpt3sas: SGL to PRP Translation for I/Os to NVMe  devices
  mpt3sas: Added support for nvme encapsulated request  message.
  mpt3sas: API 's to support NVMe drive addition to  SML
  mpt3sas: API's to remove nvme drive from sml
  mpt3sas: Handle NVMe PCIe device related events  generated from
firmware.
  mpt3sas: Set NVMe device queue depth as 128
  mpt3sas: scan and add nvme device after controller  reset
  mpt3as: Add-Task-management-debug-info-for-NVMe-drives.
  mpt3sas: NVMe drive support for BTDHMAPPING ioctl  command and log
info
  mpt3sas: Fix nvme drives checking for tlr.
  mpt3sas: Fix sparse warnings
  mpt3sas: Update mpt3sas driver version.

 drivers/scsi/mpt3sas/mpt3sas_base.c  |  643 -
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  171 ++-
 drivers/scsi/mpt3sas/mpt3sas_config.c|  100 ++
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |  158 ++-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 2080 +++---
 drivers/scsi/mpt3sas/mpt3sas_warpdrive.c |2 +-
 7 files changed, 3054 insertions(+), 330 deletions(-)

Thanks,
Suganath Prabu S
-- 
2.5.5



[PATCH 02/13] mpt3sas: SGL to PRP Translation for I/Os to NVMe devices

2017-10-31 Thread Suganath Prabu S
* Added support for translating the SGLs associated with incoming
commands either to IEE SGL or NVMe PRPs for NVMe devices.

* The hardware translation of IEEE SGL to NVMe PRPs has limitation
and if a command cannot be translated by hardware then it will go
to firmware and the firmware needs to translate it. And this will
have a performance reduction. To avoid that driver proactively
checks whether the translation will be done in hardware or not,
if not then driver try to translate inside the driver.

Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  | 339 ++-
 drivers/scsi/mpt3sas/mpt3sas_base.h  |  41 +++-
 drivers/scsi/mpt3sas/mpt3sas_ctl.c   |   1 +
 drivers/scsi/mpt3sas/mpt3sas_scsih.c |  14 +-
 drivers/scsi/mpt3sas/mpt3sas_warpdrive.c |   2 +-
 5 files changed, 380 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 11c6afe..1ad3cbb 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -59,6 +59,7 @@
 #include 
 #include 
 #include 
+#include /* To get host page size per arch */
 #include 
 
 
@@ -1344,7 +1345,218 @@ _base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge,
}
 }
 
-/* IEEE format sgls */
+/**
+ * base_make_prp_nvme -
+ * Prepare PRPs(Physical Region Page)- SGLs specific to NVMe drives only
+ *
+ * @ioc:   per adapter object
+ * @scmd:  SCSI command from the mid-layer
+ * @mpi_request:   mpi request
+ * @smid:  msg Index
+ * @sge_count: scatter gather element count.
+ *
+ * Returns:true: PRPs are built
+ * false: IEEE SGLs needs to be built
+ */
+void
+base_make_prp_nvme(struct MPT3SAS_ADAPTER *ioc,
+   struct scsi_cmnd *scmd,
+   Mpi25SCSIIORequest_t *mpi_request,
+   u16 smid, int sge_count)
+{
+   int sge_len, offset, num_prp_in_chain = 0;
+   Mpi25IeeeSgeChain64_t *main_chain_element, *ptr_first_sgl;
+   u64 *curr_buff;
+   dma_addr_t msg_phys;
+   u64 sge_addr;
+   u32 page_mask, page_mask_result;
+   struct scatterlist *sg_scmd;
+   u32 first_prp_len;
+   int data_len = scsi_bufflen(scmd);
+   u32 nvme_pg_size;
+
+   nvme_pg_size = max_t(u32, ioc->page_size, NVME_PRP_PAGE_SIZE);
+   /*
+* Nvme has a very convoluted prp format.  One prp is required
+* for each page or partial page. Driver need to split up OS sg_list
+* entries if it is longer than one page or cross a page
+* boundary.  Driver also have to insert a PRP list pointer entry as
+* the last entry in each physical page of the PRP list.
+*
+* NOTE: The first PRP "entry" is actually placed in the first
+* SGL entry in the main message as IEEE 64 format.  The 2nd
+* entry in the main message is the chain element, and the rest
+* of the PRP entries are built in the contiguous pcie buffer.
+*/
+   page_mask = nvme_pg_size - 1;
+
+   /*
+* Native SGL is needed.
+* Put a chain element in main message frame that points to the first
+* chain buffer.
+*
+* NOTE:  The ChainOffset field must be 0 when using a chain pointer to
+*a native SGL.
+*/
+
+   /* Set main message chain element pointer */
+   main_chain_element = (pMpi25IeeeSgeChain64_t)_request->SGL;
+   /*
+* For NVMe the chain element needs to be the 2nd SG entry in the main
+* message.
+*/
+   main_chain_element = (Mpi25IeeeSgeChain64_t *)
+   ((u8 *)main_chain_element + sizeof(MPI25_IEEE_SGE_CHAIN64));
+
+   /*
+* For the PRP entries, use the specially allocated buffer of
+* contiguous memory.  Normal chain buffers can't be used
+* because each chain buffer would need to be the size of an OS
+* page (4k).
+*/
+   curr_buff = mpt3sas_base_get_pcie_sgl(ioc, smid);
+   msg_phys = (dma_addr_t)mpt3sas_base_get_pcie_sgl_dma(ioc, smid);
+
+   main_chain_element->Address = cpu_to_le64(msg_phys);
+   main_chain_element->NextChainOffset = 0;
+   main_chain_element->Flags = MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
+   MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR |
+   MPI26_IEEE_SGE_FLAGS_NSF_NVME_PRP;
+
+   /* Build first prp, sge need not to be page aligned*/
+   ptr_first_sgl = (pMpi25IeeeSgeChain64_t)_request->SGL;
+   sg_scmd = scsi_sglist(scmd);
+   sge_addr = sg_dma_address(sg_scmd);
+   sge_len = sg_dma_len(sg_scmd);
+
+   offset = (u32)(sge_addr & page_mask);
+   first_prp_len = nvme_pg_size - offset;
+
+   ptr_first_sgl->Address = cpu_to_le64(sge_add

[PATCH 01/13] mpt3sas: Add nvme device support in slave alloc, target alloc and probe

2017-10-31 Thread Suganath Prabu S
1) Added support for probing pcie device and adding NVMe drives to
SML and driver's internal list pcie_device_list.

2) Added support for determing NVMe as boot device.

3) Added nvme device support for call back functions scan_finished
target_alloc,slave_alloc,target destroy and slave destroy.

 a) During scan, pcie devices are probed and added to SML to drivers
internal list.

 b) target_alloc & slave alloc API's allocates resources for
(MPT3SAS_TARGET & MPT3SAS_DEVICE) private datas and holds
information like handle, target_id etc.

 c) slave_destroy & target_destroy are called when driver unregisters
or removes device. Also frees allocated resources and info.

Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.h  | 110 +++-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 431 +--
 3 files changed, 647 insertions(+), 124 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h 
b/drivers/scsi/mpt3sas/mpt3sas_base.h
index 0fe3969..dd04a28 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -161,6 +161,7 @@
 #define MPT_TARGET_FLAGS_VOLUME0x02
 #define MPT_TARGET_FLAGS_DELETED   0x04
 #define MPT_TARGET_FASTPATH_IO 0x08
+#define MPT_TARGET_FLAGS_PCIE_DEVICE   0x10
 
 #define SAS2_PCI_DEVICE_B0_REVISION(0x01)
 #define SAS3_PCI_DEVICE_C0_REVISION(0x02)
@@ -359,7 +360,8 @@ struct Mpi2ManufacturingPage11_t {
  * @flags: MPT_TARGET_FLAGS_XXX flags
  * @deleted: target flaged for deletion
  * @tm_busy: target is busy with TM request.
- * @sdev: The sas_device associated with this target
+ * @sas_dev: The sas_device associated with this target
+ * @pcie_dev: The pcie device associated with this target
  */
 struct MPT3SAS_TARGET {
struct scsi_target *starget;
@@ -370,7 +372,8 @@ struct MPT3SAS_TARGET {
u32 flags;
u8  deleted;
u8  tm_busy;
-   struct _sas_device *sdev;
+   struct _sas_device *sas_dev;
+   struct _pcie_device *pcie_dev;
 };
 
 
@@ -514,6 +517,89 @@ static inline void sas_device_put(struct _sas_device *s)
kref_put(>refcount, sas_device_free);
 }
 
+/*
+ * struct _pcie_device - attached PCIe device information
+ * @list: pcie device list
+ * @starget: starget object
+ * @wwid: device WWID
+ * @handle: device handle
+ * @device_info: bitfield provides detailed info about the device
+ * @id: target id
+ * @channel: target channel
+ * @slot: slot number
+ * @port_num: port number
+ * @responding: used in _scsih_pcie_device_mark_responding
+ * @fast_path: fast path feature enable bit
+ * @nvme_mdts: MaximumDataTransferSize from PCIe Device Page 2 for
+ * NVMe device only
+ * @enclosure_handle: enclosure handle
+ * @enclosure_logical_id: enclosure logical identifier
+ * @enclosure_level: The level of device's enclosure from the controller
+ * @connector_name: ASCII value of the Connector's name
+ * @serial_number: pointer of serial number string allocated runtime
+ * @refcount: reference count for deletion
+ */
+struct _pcie_device {
+   struct list_head list;
+   struct scsi_target *starget;
+   u64 wwid;
+   u16 handle;
+   u32 device_info;
+   int id;
+   int channel;
+   u16 slot;
+   u8  port_num;
+   u8  responding;
+   u8  fast_path;
+   u32 nvme_mdts;
+   u16 enclosure_handle;
+   u64 enclosure_logical_id;
+   u8  enclosure_level;
+   u8  connector_name[4];
+   u8  *serial_number;
+   struct kref refcount;
+};
+/**
+ * pcie_device_get - Increment the pcie device reference count
+ *
+ * @p: pcie_device object
+ *
+ * When ever this function called it will increment the
+ * reference count of the pcie device for which this function called.
+ *
+ */
+static inline void pcie_device_get(struct _pcie_device *p)
+{
+   kref_get(>refcount);
+}
+
+/**
+ * pcie_device_free - Release the pcie device object
+ * @r - kref object
+ *
+ * Free's the pcie device object. It will be called when reference count
+ * reaches to zero.
+ */
+static inline void pcie_device_free(struct kref *r)
+{
+   kfree(container_of(r, struct _pcie_device, refcount));
+}
+
+/**
+ * pcie_device_put - Decrement the pcie device reference count
+ *
+ * @p: pcie_device object
+ *
+ * When ever this function called it will decrement the
+ * reference count of the pcie device for which this function called.
+ *
+ * When refernce count reaches to Zero, this will call pcie_device_free to the
+ * pcie_device object.
+ */
+static inline void pcie_device_put(struct _pcie_device *p)
+{
+   kref_put(>refcount, pcie_device_free);
+}
 /**
  * struct _raid_device - raid volume link list
  * @list: sas device list
@@ -562,12 +648,13 @@ struct _raid_device {
 
 /**
  * struc

[PATCH 06/13] mpt3sas: Handle NVMe PCIe device related events generated from firmware.

2017-10-31 Thread Suganath Prabu S
* The controller firmware sends separate events for NVMe devices and
PCIe switches similar to existing SAS events.

* NVMe device detection, addition and removal are reported by the
firmware through PCIe Topology Change list events.

* The PCIe device state change events are sent when the firmware
detects any abnormal conditions with a NVMe device or switch.

* The enumeration event are sent when the firmware starts PCIe device
enumeration and stops.

* This patch has the code change to handle the events and add/remove
NVMe devices in driver's inventory.

Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c  |  30 ++-
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 471 ++-
 2 files changed, 495 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index b0a75c6..0da639d 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -663,6 +663,26 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc,
case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION:
desc = "Cable Event";
break;
+   case MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE:
+   desc = "PCIE Device Status Change";
+   break;
+   case MPI2_EVENT_PCIE_ENUMERATION:
+   {
+   Mpi26EventDataPCIeEnumeration_t *event_data =
+   (Mpi26EventDataPCIeEnumeration_t *)mpi_reply->EventData;
+   pr_info(MPT3SAS_FMT "PCIE Enumeration: (%s)", ioc->name,
+  (event_data->ReasonCode ==
+   MPI26_EVENT_PCIE_ENUM_RC_STARTED) ?
+   "start" : "stop");
+   if (event_data->EnumerationStatus)
+   pr_info("enumeration_status(0x%08x)",
+  le32_to_cpu(event_data->EnumerationStatus));
+   pr_info("\n");
+   return;
+   }
+   case MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST:
+   desc = "PCIE Topology Change List";
+   break;
}
 
if (!desc)
@@ -6125,7 +6145,15 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
_base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
_base_unmask_events(ioc, MPI2_EVENT_TEMP_THRESHOLD);
_base_unmask_events(ioc, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION);
-
+   if (ioc->hba_mpi_version_belonged == MPI26_VERSION) {
+   if (ioc->is_gen35_ioc) {
+   _base_unmask_events(ioc,
+   MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE);
+   _base_unmask_events(ioc, MPI2_EVENT_PCIE_ENUMERATION);
+   _base_unmask_events(ioc,
+   MPI2_EVENT_PCIE_TOPOLOGY_CHANGE_LIST);
+   }
+   }
r = _base_make_ioc_operational(ioc);
if (r)
goto out_free_resources;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index d83560c..21260bd 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -75,6 +75,8 @@ static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 
handle,
 static int _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle);
 static void _scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc,
struct _pcie_device *pcie_device);
+static void
+_scsih_pcie_check_device(struct MPT3SAS_ADAPTER *ioc, u16 handle);
 static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid);
 
 /* global parameters */
@@ -3476,8 +3478,6 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 
handle)
struct _sas_device *sas_device;
 
sas_device = mpt3sas_get_sdev_by_handle(ioc, handle);
-   if (!sas_device)
-   return;
 
shost_for_each_device(sdev, ioc->shost) {
sas_device_priv_data = sdev->hostdata;
@@ -3487,7 +3487,7 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 
handle)
continue;
if (sas_device_priv_data->block)
continue;
-   if (sas_device->pend_sas_rphy_add)
+   if (sas_device && sas_device->pend_sas_rphy_add)
continue;
if (sas_device_priv_data->ignore_delay_remove) {
sdev_printk(KERN_INFO, sdev,
@@ -3498,7 +3498,8 @@ _scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 
handle)
_scsih_internal_device_block(sdev, sas_device_priv_data);
}
 
-   sas_device_put(sas_device);
+   if (sas_device)
+   

[PATCH 09/13] mpt3as: Add-Task-management-debug-info-for-NVMe-drives.

2017-10-31 Thread Suganath Prabu S
Added debug information for NVMe/PCIe drives in target rest path

Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 80 
 1 file changed, 71 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 81f4d2d..dc1fdad 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2929,6 +2929,7 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, 
struct scsi_cmnd *scmd)
struct scsi_target *starget = scmd->device->sdev_target;
struct MPT3SAS_TARGET *priv_target = starget->hostdata;
struct _sas_device *sas_device = NULL;
+   struct _pcie_device *pcie_device = NULL;
unsigned long flags;
char *device_str = NULL;
 
@@ -2945,6 +2946,31 @@ _scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, 
struct scsi_cmnd *scmd)
"%s handle(0x%04x), %s wwid(0x%016llx)\n",
device_str, priv_target->handle,
device_str, (unsigned long long)priv_target->sas_address);
+
+   } else if (priv_target->flags & MPT_TARGET_FLAGS_PCIE_DEVICE) {
+   spin_lock_irqsave(>pcie_device_lock, flags);
+   pcie_device = __mpt3sas_get_pdev_from_target(ioc, priv_target);
+   if (pcie_device) {
+   starget_printk(KERN_INFO, starget,
+   "handle(0x%04x), wwid(0x%016llx), port(%d)\n",
+   pcie_device->handle,
+   (unsigned long long)pcie_device->wwid,
+   pcie_device->port_num);
+   if (pcie_device->enclosure_handle != 0)
+   starget_printk(KERN_INFO, starget,
+   "enclosure logical id(0x%016llx), 
slot(%d)\n",
+   (unsigned long long)
+   pcie_device->enclosure_logical_id,
+   pcie_device->slot);
+   if (pcie_device->connector_name[0] != '\0')
+   starget_printk(KERN_INFO, starget,
+   "enclosure level(0x%04x), connector 
name( %s)\n",
+   pcie_device->enclosure_level,
+   pcie_device->connector_name);
+   pcie_device_put(pcie_device);
+   }
+   spin_unlock_irqrestore(>pcie_device_lock, flags);
+
} else {
spin_lock_irqsave(>sas_device_lock, flags);
sas_device = __mpt3sas_get_sdev_from_target(ioc, priv_target);
@@ -3680,18 +3706,14 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 
handle)
Mpi2SCSITaskManagementRequest_t *mpi_request;
u16 smid;
struct _sas_device *sas_device = NULL;
+   struct _pcie_device *pcie_device = NULL;
struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
u64 sas_address = 0;
unsigned long flags;
struct _tr_list *delayed_tr;
u32 ioc_state;
 
-   if (ioc->remove_host) {
-   dewtprintk(ioc, pr_info(MPT3SAS_FMT
-   "%s: host has been removed: handle(0x%04x)\n",
-   __func__, ioc->name, handle));
-   return;
-   } else if (ioc->pci_error_recovery) {
+   if (ioc->pci_error_recovery) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: host in pci error recovery: handle(0x%04x)\n",
__func__, ioc->name,
@@ -3722,14 +3744,52 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 
handle)
sas_address = sas_device->sas_address;
}
spin_unlock_irqrestore(>sas_device_lock, flags);
-
+   if (!sas_device) {
+   spin_lock_irqsave(>pcie_device_lock, flags);
+   pcie_device = __mpt3sas_get_pdev_by_handle(ioc, handle);
+   if (pcie_device && pcie_device->starget &&
+   pcie_device->starget->hostdata) {
+   sas_target_priv_data = pcie_device->starget->hostdata;
+   sas_target_priv_data->deleted = 1;
+   sas_address = pcie_device->wwid;
+   }
+   spin_unlock_irqrestore(>pcie_device_lock, flags);
+   }
if (sas_target_priv_data) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"setting delete flag: handle(0x%04x), 
sas_addr(0x%016llx)\n",
ioc->name, handle,

[PATCH 08/13] mpt3sas: scan and add nvme device after controller reset

2017-10-31 Thread Suganath Prabu S
After Controller reset, Scan and add nvme device back to the topology.

Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 194 ++-
 1 file changed, 190 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 9006a60..81f4d2d 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -4887,6 +4887,7 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct 
scsi_cmnd *scmd,
char *desc_scsi_state = ioc->tmp_string;
u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
struct _sas_device *sas_device = NULL;
+   struct _pcie_device *pcie_device = NULL;
struct scsi_target *starget = scmd->device->sdev_target;
struct MPT3SAS_TARGET *priv_target = starget->hostdata;
char *device_str = NULL;
@@ -5019,6 +5020,28 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct 
scsi_cmnd *scmd,
if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) {
pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name,
device_str, (unsigned long long)priv_target->sas_address);
+   } else if (priv_target->flags & MPT_TARGET_FLAGS_PCIE_DEVICE) {
+   pcie_device = mpt3sas_get_pdev_from_target(ioc, priv_target);
+   if (pcie_device) {
+   pr_info(MPT3SAS_FMT "\twwid(0x%016llx), port(%d)\n",
+   ioc->name,
+   (unsigned long long)pcie_device->wwid,
+   pcie_device->port_num);
+   if (pcie_device->enclosure_handle != 0)
+   pr_info(MPT3SAS_FMT
+   "\tenclosure logical id(0x%016llx), "
+   "slot(%d)\n", ioc->name,
+   (unsigned long long)
+   pcie_device->enclosure_logical_id,
+   pcie_device->slot);
+   if (pcie_device->connector_name[0])
+   pr_info(MPT3SAS_FMT
+   "\tenclosure level(0x%04x),"
+   "connector name( %s)\n",
+   ioc->name, pcie_device->enclosure_level,
+   pcie_device->connector_name);
+   pcie_device_put(pcie_device);
+   }
} else {
sas_device = mpt3sas_get_sdev_from_target(ioc, priv_target);
if (sas_device) {
@@ -5055,11 +5078,10 @@ _scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, 
struct scsi_cmnd *scmd,
struct sense_info data;
_scsih_normalize_sense(scmd->sense_buffer, );
pr_warn(MPT3SAS_FMT
-   "\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], 
count(%d)\n",
-   ioc->name, data.skey,
-   data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
+ "\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n",
+ ioc->name, data.skey,
+ data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount));
}
-
if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
response_info = le32_to_cpu(mpi_reply->ResponseInfo);
response_bytes = (u8 *)_info;
@@ -8559,6 +8581,130 @@ _scsih_search_responding_sas_devices(struct 
MPT3SAS_ADAPTER *ioc)
 }
 
 /**
+ * _scsih_mark_responding_pcie_device - mark a pcie_device as responding
+ * @ioc: per adapter object
+ * @pcie_device_pg0: PCIe Device page 0
+ *
+ * After host reset, find out whether devices are still responding.
+ * Used in _scsih_remove_unresponding_devices.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_mark_responding_pcie_device(struct MPT3SAS_ADAPTER *ioc,
+   Mpi26PCIeDevicePage0_t *pcie_device_pg0)
+{
+   struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
+   struct scsi_target *starget;
+   struct _pcie_device *pcie_device;
+   unsigned long flags;
+
+   spin_lock_irqsave(>pcie_device_lock, flags);
+   list_for_each_entry(pcie_device, >pcie_device_list, list) {
+   if ((pcie_device->wwid == pcie_device_pg0->WWID) &&
+   (pcie_device->slot == pcie_device_pg0->Slot)) {
+   pcie_device->responding = 1;
+   starget = pcie_device->starget;
+   if (starget && starget->hostdata) {
+

[PATCH 03/13] mpt3sas: Added support for nvme encapsulated request message.

2017-10-31 Thread Suganath Prabu S
* Mpt3sas driver uses the NVMe Encapsulated Request message to
send an NVMe command to an NVMe device attached to the IOC.

* Normal I/O commands like reads and writes are passed to the
controller as SCSI commands and the controller has the ability
to translate the commands to NVMe equivalent.

* This encapsulated NVMe command is used by applications to send
direct NVMe commands to NVMe drives.

Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_base.c | 276 +++-
 drivers/scsi/mpt3sas/mpt3sas_base.h |   4 +
 drivers/scsi/mpt3sas/mpt3sas_ctl.c  |  69 -
 3 files changed, 342 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c 
b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 1ad3cbb..b0a75c6 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -557,6 +557,11 @@ _base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, 
MPI2DefaultReply_t *mpi_reply,
frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size;
func_str = "smp_passthru";
break;
+   case MPI2_FUNCTION_NVME_ENCAPSULATED:
+   frame_sz = sizeof(Mpi26NVMeEncapsulatedRequest_t) +
+   ioc->sge_size;
+   func_str = "nvme_encapsulated";
+   break;
default:
frame_sz = 32;
func_str = "unknown";
@@ -985,7 +990,9 @@ _base_interrupt(int irq, void *bus_id)
if (request_desript_type ==
MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS ||
request_desript_type ==
-   MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
+   MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS ||
+   request_desript_type ==
+   MPI26_RPY_DESCRIPT_FLAGS_PCIE_ENCAPSULATED_SUCCESS) {
cb_idx = _base_get_cb_idx(ioc, smid);
if ((likely(cb_idx < MPT_MAX_CALLBACKS)) &&
(likely(mpt_callbacks[cb_idx] != NULL))) {
@@ -1345,6 +1352,225 @@ _base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge,
}
 }
 
+/* IEEE format sgls */
+
+/**
+ * _base_build_nvme_prp - This function is called for NVMe end devices to build
+ * a native SGL (NVMe PRP). The native SGL is built starting in the first PRP
+ * entry of the NVMe message (PRP1).  If the data buffer is small enough to be
+ * described entirely using PRP1, then PRP2 is not used.  If needed, PRP2 is
+ * used to describe a larger data buffer.  If the data buffer is too large to
+ * describe using the two PRP entriess inside the NVMe message, then PRP1
+ * describes the first data memory segment, and PRP2 contains a pointer to a 
PRP
+ * list located elsewhere in memory to describe the remaining data memory
+ * segments.  The PRP list will be contiguous.
+
+ * The native SGL for NVMe devices is a Physical Region Page (PRP).  A PRP
+ * consists of a list of PRP entries to describe a number of noncontigous
+ * physical memory segments as a single memory buffer, just as a SGL does.  
Note
+ * however, that this function is only used by the IOCTL call, so the memory
+ * given will be guaranteed to be contiguous.  There is no need to translate
+ * non-contiguous SGL into a PRP in this case.  All PRPs will describe
+ * contiguous space that is one page size each.
+ *
+ * Each NVMe message contains two PRP entries.  The first (PRP1) either 
contains
+ * a PRP list pointer or a PRP element, depending upon the command.  PRP2
+ * contains the second PRP element if the memory being described fits within 2
+ * PRP entries, or a PRP list pointer if the PRP spans more than two entries.
+ *
+ * A PRP list pointer contains the address of a PRP list, structured as a 
linear
+ * array of PRP entries.  Each PRP entry in this list describes a segment of
+ * physical memory.
+ *
+ * Each 64-bit PRP entry comprises an address and an offset field.  The address
+ * always points at the beginning of a 4KB physical memory page, and the offset
+ * describes where within that 4KB page the memory segment begins.  Only the
+ * first element in a PRP list may contain a non-zero offest, implying that all
+ * memory segments following the first begin at the start of a 4KB page.
+ *
+ * Each PRP element normally describes 4KB of physical memory, with exceptions
+ * for the first and last elements in the list.  If the memory being described
+ * by the list begins at a non-zero offset within the first 4KB page, then the
+ * first PRP element will contain a non-zero offset indicating where the region
+ * begins within the 4KB page.  The last memory segment may end before the end
+ * of the 4KB segment, depending upon the overall size of the memory being
+ * described by the PRP list.
+ *
+ * Since PRP e

[PATCH 05/13] mpt3sas: API's to remove nvme drive from sml

2017-10-31 Thread Suganath Prabu S
Below API's are included in nvme drive remove path.
_scsih_pcie_device_remove_by_handle
_scsih_pcie_device_remove_from_sml

Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 148 ++-
 1 file changed, 145 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index d3f8a10..d83560c 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -73,6 +73,8 @@ static void _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc,
 static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle,
u8 retry_count, u8 is_pd);
 static int _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle);
+static void _scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc,
+   struct _pcie_device *pcie_device);
 static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid);
 
 /* global parameters */
@@ -1126,6 +1128,41 @@ _scsih_pcie_device_remove(struct MPT3SAS_ADAPTER *ioc,
pcie_device_put(pcie_device);
}
 }
+
+
+/**
+ * _scsih_pcie_device_remove_by_handle - removing pcie device object by handle
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * Return nothing.
+ */
+static void
+_scsih_pcie_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+   struct _pcie_device *pcie_device;
+   unsigned long flags;
+   int was_on_pcie_device_list = 0;
+
+   if (ioc->shost_recovery)
+   return;
+
+   spin_lock_irqsave(>pcie_device_lock, flags);
+   pcie_device = __mpt3sas_get_pdev_by_handle(ioc, handle);
+   if (pcie_device) {
+   if (!list_empty(_device->list)) {
+   list_del_init(_device->list);
+   was_on_pcie_device_list = 1;
+   pcie_device_put(pcie_device);
+   }
+   }
+   spin_unlock_irqrestore(>pcie_device_lock, flags);
+   if (was_on_pcie_device_list) {
+   _scsih_pcie_device_remove_from_sml(ioc, pcie_device);
+   pcie_device_put(pcie_device);
+   }
+}
+
 /**
  * _scsih_pcie_device_add - add pcie_device object
  * @ioc: per adapter object
@@ -6567,6 +6604,83 @@ _scsih_check_pcie_access_status(struct MPT3SAS_ADAPTER 
*ioc, u64 wwid,
(unsigned long long)wwid, handle);
return rc;
 }
+
+/**
+ * _scsih_pcie_device_remove_from_sml -  removing pcie device
+ * from SML and free up associated memory
+ * @ioc: per adapter object
+ * @pcie_device: the pcie_device object
+ *
+ * Return nothing.
+ */
+static void
+_scsih_pcie_device_remove_from_sml(struct MPT3SAS_ADAPTER *ioc,
+   struct _pcie_device *pcie_device)
+{
+   struct MPT3SAS_TARGET *sas_target_priv_data;
+
+   dewtprintk(ioc, pr_info(MPT3SAS_FMT
+   "%s: enter: handle(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
+   pcie_device->handle, (unsigned long long)
+   pcie_device->wwid));
+   if (pcie_device->enclosure_handle != 0)
+   dewtprintk(ioc, pr_info(MPT3SAS_FMT
+   "%s: enter: enclosure logical id(0x%016llx), slot(%d)\n",
+   ioc->name, __func__,
+   (unsigned long long)pcie_device->enclosure_logical_id,
+   pcie_device->slot));
+   if (pcie_device->connector_name[0] != '\0')
+   dewtprintk(ioc, pr_info(MPT3SAS_FMT
+   "%s: enter: enclosure level(0x%04x), connector name( %s)\n",
+   ioc->name, __func__,
+   pcie_device->enclosure_level,
+   pcie_device->connector_name));
+
+   if (pcie_device->starget && pcie_device->starget->hostdata) {
+   sas_target_priv_data = pcie_device->starget->hostdata;
+   sas_target_priv_data->deleted = 1;
+   _scsih_ublock_io_device(ioc, pcie_device->wwid);
+   sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE;
+   }
+
+   pr_info(MPT3SAS_FMT
+   "removing handle(0x%04x), wwid (0x%016llx)\n",
+   ioc->name, pcie_device->handle,
+   (unsigned long long) pcie_device->wwid);
+   if (pcie_device->enclosure_handle != 0)
+   pr_info(MPT3SAS_FMT
+   "removing : enclosure logical id(0x%016llx), slot(%d)\n",
+   ioc->name,
+   (unsigned long long)pcie_device->enclosure_logical_id,
+   pcie_device->slot);
+   if (pcie_device->connector_name[0] != '\0')
+   pr_info(MPT3SAS_FMT
+   "removing: enclosure level(0x%04x)

[PATCH 10/13] mpt3sas: NVMe drive support for BTDHMAPPING ioctl command and log info

2017-10-31 Thread Suganath Prabu S
* Added debug prints for pcie devices in ioctl debug path. Which
will be helpful for debugging.
* Added PCIe device support for ioctl BTDHMAPPING ioctl.

Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_ctl.c | 88 +-
 1 file changed, 58 insertions(+), 30 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c 
b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index 205c443..b4c374b 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -79,32 +79,6 @@ enum block_state {
 };
 
 /**
- * _ctl_sas_device_find_by_handle - sas device search
- * @ioc: per adapter object
- * @handle: sas device handle (assigned by firmware)
- * Context: Calling function should acquire ioc->sas_device_lock
- *
- * This searches for sas_device based on sas_address, then return sas_device
- * object.
- */
-static struct _sas_device *
-_ctl_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
-{
-   struct _sas_device *sas_device, *r;
-
-   r = NULL;
-   list_for_each_entry(sas_device, >sas_device_list, list) {
-   if (sas_device->handle != handle)
-   continue;
-   r = sas_device;
-   goto out;
-   }
-
- out:
-   return r;
-}
-
-/**
  * _ctl_display_some_debug - debug routine
  * @ioc: per adapter object
  * @smid: system request message index
@@ -229,10 +203,9 @@ _ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 
smid,
Mpi2SCSIIOReply_t *scsi_reply =
(Mpi2SCSIIOReply_t *)mpi_reply;
struct _sas_device *sas_device = NULL;
-   unsigned long flags;
+   struct _pcie_device *pcie_device = NULL;
 
-   spin_lock_irqsave(>sas_device_lock, flags);
-   sas_device = _ctl_sas_device_find_by_handle(ioc,
+   sas_device = mpt3sas_get_sdev_by_handle(ioc,
le16_to_cpu(scsi_reply->DevHandle));
if (sas_device) {
pr_warn(MPT3SAS_FMT "\tsas_address(0x%016llx), 
phy(%d)\n",
@@ -242,8 +215,25 @@ _ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 
smid,
"\tenclosure_logical_id(0x%016llx), slot(%d)\n",
ioc->name, (unsigned long long)
sas_device->enclosure_logical_id, sas_device->slot);
+   sas_device_put(sas_device);
+   }
+   if (!sas_device) {
+   pcie_device = mpt3sas_get_pdev_by_handle(ioc,
+   le16_to_cpu(scsi_reply->DevHandle));
+   if (pcie_device) {
+   pr_warn(MPT3SAS_FMT
+   "\tWWID(0x%016llx), port(%d)\n", ioc->name,
+   (unsigned long long)pcie_device->wwid,
+   pcie_device->port_num);
+   if (pcie_device->enclosure_handle != 0)
+   pr_warn(MPT3SAS_FMT
+   "\tenclosure_logical_id(0x%016llx), 
slot(%d)\n",
+   ioc->name, (unsigned long long)
+   pcie_device->enclosure_logical_id,
+   pcie_device->slot);
+   pcie_device_put(pcie_device);
+   }
}
-   spin_unlock_irqrestore(>sas_device_lock, flags);
if (scsi_reply->SCSIState || scsi_reply->SCSIStatus)
pr_info(MPT3SAS_FMT
"\tscsi_state(0x%02x), scsi_status"
@@ -1347,6 +1337,42 @@ _ctl_btdh_search_sas_device(struct MPT3SAS_ADAPTER *ioc,
 }
 
 /**
+ * _ctl_btdh_search_pcie_device - searching for pcie device
+ * @ioc: per adapter object
+ * @btdh: btdh ioctl payload
+ */
+static int
+_ctl_btdh_search_pcie_device(struct MPT3SAS_ADAPTER *ioc,
+   struct mpt3_ioctl_btdh_mapping *btdh)
+{
+   struct _pcie_device *pcie_device;
+   unsigned long flags;
+   int rc = 0;
+
+   if (list_empty(>pcie_device_list))
+   return rc;
+
+   spin_lock_irqsave(>pcie_device_lock, flags);
+   list_for_each_entry(pcie_device, >pcie_device_list, list) {
+   if (btdh->bus == 0x && btdh->id == 0x &&
+  btdh->handle == pcie_device->handle) {
+   btdh->bus = pcie_device->channel;
+   btdh->id = pcie_device->id;
+   rc = 1;
+   goto out;
+   } else if (btdh->bu

[PATCH 11/13] mpt3sas: Fix nvme drives checking for tlr.

2017-10-31 Thread Suganath Prabu S
Check for NVMe drives before enabling or checking tlr.

Signed-off-by: Chaitra P B <chaitra.basa...@broadcom.com>
Signed-off-by: Suganath Prabu S <suganath-prabu.subram...@broadcom.com>
---
 drivers/scsi/mpt3sas/mpt3sas_scsih.c | 22 --
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c 
b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index dc1fdad..72dd57f 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -2048,6 +2048,14 @@ scsih_is_raid(struct device *dev)
return (sdev->channel == RAID_CHANNEL) ? 1 : 0;
 }
 
+static int
+scsih_is_nvme(struct device *dev)
+{
+   struct scsi_device *sdev = to_scsi_device(dev);
+
+   return (sdev->channel == PCIE_CHANNEL) ? 1 : 0;
+}
+
 /**
  * scsih_get_resync - get raid volume resync percent complete
  * @dev the device struct object
@@ -4834,8 +4842,9 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd 
*scmd)
/* Make sure Device is not raid volume.
 * We do not expose raid functionality to upper layer for warpdrive.
 */
-   if (!ioc->is_warpdrive && !scsih_is_raid(>device->sdev_gendev)
-   && sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32)
+   if (((!ioc->is_warpdrive && !scsih_is_raid(>device->sdev_gendev))
+   && !scsih_is_nvme(>device->sdev_gendev))
+   && sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32)
mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
 
smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd);
@@ -4880,8 +4889,8 @@ scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd 
*scmd)
 
raid_device = sas_target_priv_data->raid_device;
if (raid_device && raid_device->direct_io_enabled)
-   mpt3sas_setup_direct_io(ioc, scmd, raid_device, mpi_request,
-   smid);
+   mpt3sas_setup_direct_io(ioc, scmd,
+   raid_device, mpi_request, smid);
 
if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) {
if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) {
@@ -5411,9 +5420,10 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 
msix_index, u32 reply)
le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF;
if (!sas_device_priv_data->tlr_snoop_check) {
sas_device_priv_data->tlr_snoop_check++;
-   if (!ioc->is_warpdrive &&
+   if ((!ioc->is_warpdrive &&
!scsih_is_raid(>device->sdev_gendev) &&
-   sas_is_tlr_enabled(scmd->device) &&
+   !scsih_is_nvme(>device->sdev_gendev))
+   && sas_is_tlr_enabled(scmd->device) &&
response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) {
sas_disable_tlr(scmd->device);
sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n");
-- 
2.5.5



  1   2   3   >