RE: [PATCH 1/1] fnic: Adding Check Condition counter to misc fnicstats

2017-03-22 Thread Satish Kharat (satishkh)
Hi Martin,
 Apologies for the delay. I was not able to verify this because of another fnic 
issue blocking this test. Just now submitted a fix for that 'fnic issue' (in 
the patch => [PATCH 1/1] fnic: bug fix for fip.fip_subcode in 
fnic_fcoe_send_vlan_req)

Did some quick verification and basic IO test, this patch looks good.

Thanks,
Satish Kharat

-Original Message-
From: Martin K. Petersen [mailto:martin.peter...@oracle.com] 
Sent: Wednesday, March 01, 2017 7:04 PM
To: Satish Kharat (satishkh) 
Cc: linux-scsi@vger.kernel.org; Sesidhar Baddela (sebaddel) 
Subject: Re: [PATCH 1/1] fnic: Adding Check Condition counter to misc fnicstats

> "Satish" == Satish Kharat  writes:

Satish,

Satish> Just a simple counter of number of check conditions encountered 
Satish> on that host.

Please test and review the following:

https://patchwork.kernel.org/patch/9549777/

Thank you!

-- 
Martin K. Petersen  Oracle Linux Engineering


[PATCH 1/1] fnic: bug fix for fip.fip_subcode in fnic_fcoe_send_vlan_req

2017-03-22 Thread Satish Kharat
This is a bug introduced when they moved the fip subcodes
to central place. Was sending FIP_SC_VL_NOTE in fip.fip_subcode
for VLAN request in fnic_fcoe_send_vlan_req. Change is to use
FIP_SC_VL_REQ instead.

Signed-off-by: Satish Kharat 
Signed-off-by: Sesidhar Baddela 
---
 drivers/scsi/fnic/fnic_fcs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/fnic/fnic_fcs.c b/drivers/scsi/fnic/fnic_fcs.c
index 3b7da66..f5e632f 100644
--- a/drivers/scsi/fnic/fnic_fcs.c
+++ b/drivers/scsi/fnic/fnic_fcs.c
@@ -359,7 +359,7 @@ static void fnic_fcoe_send_vlan_req(struct fnic *fnic)
 
vlan->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
vlan->fip.fip_op = htons(FIP_OP_VLAN);
-   vlan->fip.fip_subcode = FIP_SC_VL_NOTE;
+   vlan->fip.fip_subcode = FIP_SC_VL_REQ;
vlan->fip.fip_dl_len = htons(sizeof(vlan->desc) / FIP_BPW);
 
vlan->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
-- 
2.7.4



RE: [PATCH v7 09/11] scsi: ufs: connect to RPMB subsystem

2017-03-22 Thread Winkler, Tomas
> 
> On Mon, Nov 07, 2016 at 07:27:38PM +, Winkler, Tomas wrote:
> > I  value your opinion but I'm not responsible for inventing RPMB
> > and/or its  implementation storage devices (eMMC, UFC, NVMe), it's pretty
> much done deal out there in the wild.
> > I'm just trying to provide common API above it.

Somehow I've missed that answer, now I got back when search for comments before 
I'll post a new series.
 
> And the common API must go through the SCSI midlayer.  

I've actually tried to do  a midlayer, but I found it's too UFS specific, so 
there is no point to this abstraction.  
As not all needed data are accessible via scsi calls.  The solution I propose 
fits with what is done in eMMC (emmc specific  IOCTL).
There is already some code that breaks that layering in  
ufshcd_set_dev_pwr_mode when talking to the special sdev_ufs.
Maybe I need more hint for the correct directions.

If it can't we won't
> support it, so please drop the UFS patches from the series.

If you have more constructive comments, I'll be glad to hear and address. 

Thanks
Tomas



[PATCH] scsi: pm8001: build in relevant functions and code on PM8001_USE_MSIX

2017-03-22 Thread Colin King
From: Colin Ian King 

Currently the misx and intx variables of the interrupt enable/disable
helper functions are built in no matter what the setting of the
macro PM8001_USE_MSIX.  Clean this up by just building in the
necessary helper functions and calls to these functions depending on
the setting of PM8001_USE_MSIX.  This addresses several dead code
paths found by static analysis with CoverityScan.

Signed-off-by: Colin Ian King 
---
 drivers/scsi/pm8001/pm8001_hwi.c | 63 +---
 1 file changed, 33 insertions(+), 30 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 10546faac58c..d1be10fd1350 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1204,26 +1204,7 @@ void pm8001_chip_iounmap(struct pm8001_hba_info 
*pm8001_ha)
}
 }
 
-/**
- * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt
- * @pm8001_ha: our hba card information
- */
-static void
-pm8001_chip_intx_interrupt_enable(struct pm8001_hba_info *pm8001_ha)
-{
-   pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, ODMR_CLEAR_ALL);
-   pm8001_cw32(pm8001_ha, 0, MSGU_ODCR, ODCR_CLEAR_ALL);
-}
-
- /**
-  * pm8001_chip_intx_interrupt_disable- disable PM8001 chip interrupt
-  * @pm8001_ha: our hba card information
-  */
-static void
-pm8001_chip_intx_interrupt_disable(struct pm8001_hba_info *pm8001_ha)
-{
-   pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, ODMR_MASK_ALL);
-}
+#ifdef PM8001_USE_MSIX
 
 /**
  * pm8001_chip_msix_interrupt_enable - enable PM8001 chip interrupt
@@ -1257,6 +1238,30 @@ pm8001_chip_msix_interrupt_disable(struct 
pm8001_hba_info *pm8001_ha,
pm8001_cw32(pm8001_ha, 0,  msi_index, MSIX_INTERRUPT_DISABLE);
 }
 
+#else
+
+/**
+ * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt
+ * @pm8001_ha: our hba card information
+ */
+static void
+pm8001_chip_intx_interrupt_enable(struct pm8001_hba_info *pm8001_ha)
+{
+   pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, ODMR_CLEAR_ALL);
+   pm8001_cw32(pm8001_ha, 0, MSGU_ODCR, ODCR_CLEAR_ALL);
+}
+
+ /**
+  * pm8001_chip_intx_interrupt_disable- disable PM8001 chip interrupt
+  * @pm8001_ha: our hba card information
+  */
+static void
+pm8001_chip_intx_interrupt_disable(struct pm8001_hba_info *pm8001_ha)
+{
+   pm8001_cw32(pm8001_ha, 0, MSGU_ODMR, ODMR_MASK_ALL);
+}
+#endif
+
 /**
  * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt
  * @pm8001_ha: our hba card information
@@ -1266,10 +1271,9 @@ pm8001_chip_interrupt_enable(struct pm8001_hba_info 
*pm8001_ha, u8 vec)
 {
 #ifdef PM8001_USE_MSIX
pm8001_chip_msix_interrupt_enable(pm8001_ha, 0);
-   return;
-#endif
+#else
pm8001_chip_intx_interrupt_enable(pm8001_ha);
-
+#endif
 }
 
 /**
@@ -1281,10 +1285,9 @@ pm8001_chip_interrupt_disable(struct pm8001_hba_info 
*pm8001_ha, u8 vec)
 {
 #ifdef PM8001_USE_MSIX
pm8001_chip_msix_interrupt_disable(pm8001_ha, 0);
-   return;
-#endif
+#else
pm8001_chip_intx_interrupt_disable(pm8001_ha);
-
+#endif
 }
 
 /**
@@ -4613,15 +4616,15 @@ static int pm8001_chip_phy_ctl_req(struct 
pm8001_hba_info *pm8001_ha,
 
 static u32 pm8001_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha)
 {
-   u32 value;
 #ifdef PM8001_USE_MSIX
return 1;
-#endif
-   value = pm8001_cr32(pm8001_ha, 0, MSGU_ODR);
+#else
+   u32 value = pm8001_cr32(pm8001_ha, 0, MSGU_ODR);
+
if (value)
return 1;
return 0;
-
+#endif
 }
 
 /**
-- 
2.11.0



Re: [PATCH] scsi: fcoe: sanity check string size for store_ctrl_mode option

2017-03-22 Thread Colin Ian King
On 22/03/17 19:39, Dan Carpenter wrote:
> On Wed, Mar 22, 2017 at 02:01:37PM +, Colin King wrote:
>> From: Colin Ian King 
>>
>> Reading and writing to mode[count - 1] implies the count should not
>> be less than 1 so add a sanity check for this.
>>
>> Detected with CoverityScan, CID#1357345 ("Overflowed array index write")
>>
>> Signed-off-by: Colin Ian King 
> 
> This is harmless, of course, but count can't be zero.  This is a sysfs
> file so we test for zero size writes in sysfs_kf_write() and return
> early.

Ah, thanks for pointing out that. I overlooked that detail.

Colin

> 
> regards,
> dan carpenter
> 



Re: [PATCH] scsi: fcoe: sanity check string size for store_ctrl_mode option

2017-03-22 Thread Dan Carpenter
On Wed, Mar 22, 2017 at 02:01:37PM +, Colin King wrote:
> From: Colin Ian King 
> 
> Reading and writing to mode[count - 1] implies the count should not
> be less than 1 so add a sanity check for this.
> 
> Detected with CoverityScan, CID#1357345 ("Overflowed array index write")
> 
> Signed-off-by: Colin Ian King 

This is harmless, of course, but count can't be zero.  This is a sysfs
file so we test for zero size writes in sysfs_kf_write() and return
early.

regards,
dan carpenter



Re: support ranges TRIM for libata

2017-03-22 Thread Christoph Hellwig
On Tue, Mar 21, 2017 at 02:59:01PM -0400, Tejun Heo wrote:
> I do like the fact that this is a lot simpler than the previous
> implementation but am not quite sure we want to deviate significantly
> from what we do for other commands (command translation).  Is it
> because fixing the existing implementation would involve invaisve
> changes including memory allocations?

The current implementation already has the issue of that it does
corrupt user data reliably if the using SG_IO for WRITE SAME commands.

Doing ranges using translation would turn into a nightmare because
ATA TRIM ranges are 16 bits long while SCSI UNAMP ranges are 32-bit,
so we effectively can't translated them without introducing a
non-standard hook between libata and scsi to communicate that
limit.  And once we're down that path we might as well just do the
right thing directly.


[PATCH 14/23] scsi: hisi_sas: remove task free'ing for timeouts

2017-03-22 Thread John Garry
When a TMF or internal abort times-out, do not free
slot. We expect this to be done upon later escalated
error handling.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 15 +--
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index f9ea5cc..3d63a24 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -743,14 +743,6 @@ static int hisi_sas_exec_internal_tmf_task(struct 
domain_device *device,
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
dev_err(dev, "abort tmf: TMF task timeout\n");
-   if (task->lldd_task) {
-   struct hisi_sas_slot *slot =
-   task->lldd_task;
-
-   hisi_sas_slot_task_free(hisi_hba,
-   task, slot);
-   }
-
goto ex_err;
}
}
@@ -1248,15 +1240,10 @@ static int hisi_sas_query_task(struct sas_task *task)
goto exit;
}
 
-   /* TMF timed out, return direct. */
+   /* Internal abort timed out */
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
dev_err(dev, "internal task abort: timeout.\n");
-   if (task->lldd_task) {
-   struct hisi_sas_slot *slot = task->lldd_task;
-
-   hisi_sas_slot_task_free(hisi_hba, task, slot);
-   }
}
}
 
-- 
1.9.1



[PATCH 02/23] scsi: hisi_sas: add controller reset

2017-03-22 Thread John Garry
From: Xiang Chen 

There are some scenarios that we need to warm-rest to
reset registers of SAS controller. During reset we disable
interrupts/DQs/PHYs, and after reset we re-init the hardware
and rescan the topology to see if anything changed.

Signed-off-by: Xiang Chen 
Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |   7 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 134 +++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  94 +++
 3 files changed, 227 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index a018a8a..fd76a02 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -31,6 +31,7 @@
 #define HISI_SAS_QUEUE_SLOTS 512
 #define HISI_SAS_MAX_ITCT_ENTRIES 2048
 #define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES
+#define HISI_SAS_RESET_BIT 0
 
 #define HISI_SAS_STATUS_BUF_SZ \
(sizeof(struct hisi_sas_err_record) + 1024)
@@ -175,6 +176,7 @@ struct hisi_sas_hw {
void (*free_device)(struct hisi_hba *hisi_hba,
struct hisi_sas_device *dev);
int (*get_wideport_bitmap)(struct hisi_hba *hisi_hba, int port_id);
+   int (*soft_reset)(struct hisi_hba *hisi_hba);
int max_command_entries;
int complete_hdr_size;
 };
@@ -233,7 +235,9 @@ struct hisi_hba {
struct hisi_sas_breakpoint *sata_breakpoint;
dma_addr_t sata_breakpoint_dma;
struct hisi_sas_slot*slot_info;
+   unsigned long flags;
const struct hisi_sas_hw *hw;   /* Low level hw interface */
+   struct work_struct rst_work;
 };
 
 /* Generic HW DMA host memory structures */
@@ -356,4 +360,7 @@ extern int hisi_sas_probe(struct platform_device *pdev,
 extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
struct sas_task *task,
struct hisi_sas_slot *slot);
+extern void hisi_sas_init_mem(struct hisi_hba *hisi_hba);
+extern void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_state,
+u32 state);
 #endif
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 11f32d2..cbaef90 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -351,6 +351,9 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t 
gfp_flags,
struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
struct device *dev = _hba->pdev->dev;
 
+   if (unlikely(test_bit(HISI_SAS_RESET_BIT, _hba->flags)))
+   return -EINVAL;
+
/* protect task_prep and start_delivery sequence */
spin_lock_irqsave(_hba->lock, flags);
rc = hisi_sas_task_prep(task, hisi_hba, is_tmf, tmf, );
@@ -613,6 +616,20 @@ static void hisi_sas_release_task(struct hisi_hba 
*hisi_hba,
hisi_sas_do_release_task(hisi_hba, sas_phy->id, device);
 }
 
+static void hisi_sas_release_tasks(struct hisi_hba *hisi_hba)
+{
+   int i;
+
+   for (i = 0; i < HISI_SAS_MAX_PHYS; i++) {
+   struct hisi_sas_phy *phy = _hba->phy[i];
+   struct asd_sas_phy *sas_phy = >sas_phy;
+
+   if (!sas_phy->port)
+   continue;
+   hisi_sas_port_notify_deformed(sas_phy);
+   }
+}
+
 static void hisi_sas_dev_gone(struct domain_device *device)
 {
struct hisi_sas_device *sas_dev = device->lldd_dev;
@@ -803,6 +820,40 @@ static int hisi_sas_debug_issue_ssp_tmf(struct 
domain_device *device,
sizeof(ssp_task), tmf);
 }
 
+static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
+{
+   int rc;
+
+   if (!hisi_hba->hw->soft_reset)
+   return -1;
+
+   if (!test_and_set_bit(HISI_SAS_RESET_BIT, _hba->flags)) {
+   struct device *dev = _hba->pdev->dev;
+   struct sas_ha_struct *sas_ha = _hba->sha;
+   unsigned long flags;
+
+   dev_dbg(dev, "controller reset begins!\n");
+   scsi_block_requests(hisi_hba->shost);
+   rc = hisi_hba->hw->soft_reset(hisi_hba);
+   if (rc) {
+   dev_warn(dev, "controller reset failed (%d)\n", rc);
+   goto out;
+   }
+   spin_lock_irqsave(_hba->lock, flags);
+   hisi_sas_release_tasks(hisi_hba);
+   spin_unlock_irqrestore(_hba->lock, flags);
+
+   sas_ha->notify_ha_event(sas_ha, HAE_RESET);
+   dev_dbg(dev, "controller reset successful!\n");
+   } else
+   return -1;
+
+out:
+   scsi_unblock_requests(hisi_hba->shost);
+   clear_bit(HISI_SAS_RESET_BIT, _hba->flags);
+   return rc;
+}
+
 

[PATCH 08/23] scsi: hisi_sas: modify error handling for v2 hw

2017-03-22 Thread John Garry
From: Xiang Chen 

For error codes which need abort-and-retry, simulate IO
timeout and let SCSI+ATA layers process those errors.

Previously for SSP, we should try to abort the IO in
the LLDD and then pass back to upper layer, but sometimes
this would also error. So Instead of adding special error
handling for this scenario in the LLDD, allow the upper
layer to handle completely.

No performance hit is seen by taking this approach.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index b9d5132..a35f881 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1747,7 +1747,6 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
 
task->task_state_flags &=
~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
-   task->task_state_flags |= SAS_TASK_STATE_DONE;
 
memset(ts, 0, sizeof(*ts));
ts->resp = SAS_TASK_COMPLETE;
@@ -1786,11 +1785,9 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
(!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) {
 
slot_err_v2_hw(hisi_hba, task, slot);
-   if (unlikely(slot->abort)) {
-   queue_work(hisi_hba->wq, >abort_slot);
-   /* immediately return and do not complete */
+
+   if (unlikely(slot->abort))
return ts->stat;
-   }
goto out;
}
 
@@ -1842,7 +1839,7 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
}
 
 out:
-
+   task->task_state_flags |= SAS_TASK_STATE_DONE;
hisi_sas_slot_task_free(hisi_hba, task, slot);
sts = ts->stat;
 
-- 
1.9.1



[PATCH 05/23] scsi: hisi_sas: remove hisi_sas_port_deformed()

2017-03-22 Thread John Garry
Currently when a root PHY is deformed from a asd_sas_port
we try to release the slots in the LLDD, and fail.

Regardless, it is not right to release this early.

This patch removes the deformed function. As it was
before, port deformation is still done in
hisi_sas_phy_down().

It would be nice to actually remove the
hisi_sas_port_{de}formed() pair, however we cannot as
we need to know the asd_sas_port index libsas has
associated with an asd_sas_phy.

The hw does actually generate a port id for a PHY, but
this seems to a random number, so ignored for this
purpose.

This patch also changes the code to link slots to the
hisi_sas_device, and not hisi_sas_port.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  4 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 85 ++
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  9 ++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 13 +++---
 4 files changed, 46 insertions(+), 65 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 2135de9..6aa0b62 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -91,7 +91,6 @@ struct hisi_sas_port {
struct asd_sas_port sas_port;
u8  port_attached;
u8  id; /* from hw */
-   struct list_headlist;
 };
 
 struct hisi_sas_cq {
@@ -114,6 +113,7 @@ struct hisi_sas_device {
u64 attached_phy;
u64 device_id;
atomic64_t running_req;
+   struct list_headlist;
u8 dev_status;
 };
 
@@ -166,7 +166,7 @@ struct hisi_sas_hw {
  struct hisi_sas_slot *slot,
  int device_id, int abort_flag, int tag_to_abort);
int (*slot_complete)(struct hisi_hba *hisi_hba,
-struct hisi_sas_slot *slot, int abort);
+struct hisi_sas_slot *slot);
void (*phys_init)(struct hisi_hba *hisi_hba);
void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no);
void (*phy_disable)(struct hisi_hba *hisi_hba, int phy_no);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 9d9f305..f64c1b6 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -308,7 +308,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
goto err_out_command_table;
}
 
-   list_add_tail(>entry, >list);
+   list_add_tail(>entry, _dev->list);
spin_lock(>task_state_lock);
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock(>task_state_lock);
@@ -424,6 +424,7 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct 
domain_device *device)
sas_dev->dev_type = device->dev_type;
sas_dev->hisi_hba = hisi_hba;
sas_dev->sas_device = device;
+   INIT_LIST_HEAD(_hba->devices[i].list);
break;
}
}
@@ -568,63 +569,55 @@ static void hisi_sas_port_notify_formed(struct 
asd_sas_phy *sas_phy)
spin_unlock_irqrestore(_hba->lock, flags);
 }
 
-static void hisi_sas_do_release_task(struct hisi_hba *hisi_hba, int phy_no,
-struct domain_device *device)
+static void hisi_sas_do_release_task(struct hisi_hba *hisi_hba,
+struct sas_task *task,
+struct hisi_sas_slot *slot)
 {
-   struct hisi_sas_phy *phy;
-   struct hisi_sas_port *port;
-   struct hisi_sas_slot *slot, *slot2;
-   struct device *dev = _hba->pdev->dev;
+   struct task_status_struct *ts;
+   unsigned long flags;
 
-   phy = _hba->phy[phy_no];
-   port = phy->port;
-   if (!port)
+   if (!task)
return;
 
-   list_for_each_entry_safe(slot, slot2, >list, entry) {
-   struct sas_task *task;
-
-   task = slot->task;
-   if (device && task->dev != device)
-   continue;
-
-   dev_info(dev, "Release slot [%d:%d], task [%p]:\n",
-slot->dlvry_queue, slot->dlvry_queue_slot, task);
-   hisi_hba->hw->slot_complete(hisi_hba, slot, 1);
-   }
-}
+   ts = >task_status;
 
-static void hisi_sas_port_notify_deformed(struct asd_sas_phy *sas_phy)
-{
-   struct domain_device *device;
-   struct hisi_sas_phy *phy = sas_phy->lldd_phy;
-   struct asd_sas_port *sas_port = sas_phy->port;
+   ts->resp = SAS_TASK_COMPLETE;
+   ts->stat = SAS_ABORTED_TASK;
+   spin_lock_irqsave(>task_state_lock, flags);
+   task->task_state_flags &=
+   ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
+   task->task_state_flags |= SAS_TASK_STATE_DONE;
+   

[PATCH 22/23] scsi: hisi_sas: use dev_is_sata to identify SATA or SAS disk

2017-03-22 Thread John Garry
From: Xiang Chen 

When SMP IO is sent, sas_protocol_ata couldn't judge whether
the disk is SATA or SAS disk.
So use dev_is_sata to identify SATA or SAS disk.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index dcceff9..9890dfd 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -218,7 +218,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
port = to_hisi_sas_port(sas_port);
if (port && !port->port_attached) {
dev_info(dev, "task prep: %s port%d not attach device\n",
-(sas_protocol_ata(task->task_proto)) ?
+(dev_is_sata(device)) ?
 "SATA/STP" : "SAS",
 device->port->id);
 
-- 
1.9.1



[PATCH 01/23] scsi: hisi_sas: add to_hisi_sas_port()

2017-03-22 Thread John Garry
Introduce function to get hisi_sas_port from
asd_sas_port.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  2 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 17 +
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  4 +++-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  6 --
 4 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 9216dea..a018a8a 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -346,6 +346,8 @@ struct hisi_sas_command_table_ssp {
struct hisi_sas_command_table_smp smp;
struct hisi_sas_command_table_stp stp;
 };
+
+extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port);
 extern int hisi_sas_probe(struct platform_device *pdev,
  const struct hisi_sas_hw *ops);
 extern int hisi_sas_remove(struct platform_device *pdev);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 53637a9..11f32d2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -27,6 +27,12 @@ static struct hisi_hba *dev_to_hisi_hba(struct domain_device 
*device)
return device->port->ha->lldd_ha;
 }
 
+struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port)
+{
+   return container_of(sas_port, struct hisi_sas_port, sas_port);
+}
+EXPORT_SYMBOL_GPL(to_hisi_sas_port);
+
 static void hisi_sas_slot_index_clear(struct hisi_hba *hisi_hba, int slot_idx)
 {
void *bitmap = hisi_hba->slot_index_tags;
@@ -178,10 +184,11 @@ static int hisi_sas_task_prep(struct sas_task *task, 
struct hisi_hba *hisi_hba,
struct hisi_sas_port *port;
struct hisi_sas_slot *slot;
struct hisi_sas_cmd_hdr *cmd_hdr_base;
+   struct asd_sas_port *sas_port = device->port;
struct device *dev = _hba->pdev->dev;
int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
 
-   if (!device->port) {
+   if (!sas_port) {
struct task_status_struct *ts = >task_status;
 
ts->resp = SAS_TASK_UNDELIVERED;
@@ -206,7 +213,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
rc = SAS_PHY_DOWN;
return rc;
}
-   port = device->port->lldd_port;
+
+   port = to_hisi_sas_port(sas_port);
if (port && !port->port_attached) {
dev_info(dev, "task prep: %s port%d not attach device\n",
 (sas_protocol_ata(task->task_proto)) ?
@@ -545,7 +553,7 @@ static void hisi_sas_port_notify_formed(struct asd_sas_phy 
*sas_phy)
struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
struct hisi_sas_phy *phy = sas_phy->lldd_phy;
struct asd_sas_port *sas_port = sas_phy->port;
-   struct hisi_sas_port *port = _hba->port[phy->port_id];
+   struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
unsigned long flags;
 
if (!sas_port)
@@ -990,13 +998,14 @@ static int hisi_sas_query_task(struct sas_task *task)
struct device *dev = _hba->pdev->dev;
struct hisi_sas_port *port;
struct hisi_sas_slot *slot;
+   struct asd_sas_port *sas_port = device->port;
struct hisi_sas_cmd_hdr *cmd_hdr_base;
int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
 
if (!device->port)
return -1;
 
-   port = device->port->lldd_port;
+   port = to_hisi_sas_port(sas_port);
 
/* simply get a slot and send abort command */
rc = hisi_sas_slot_index_alloc(hisi_hba, _idx);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 854fbea..022ad10 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -508,6 +508,8 @@ static void setup_itct_v1_hw(struct hisi_hba *hisi_hba,
struct device *dev = _hba->pdev->dev;
u64 qw0, device_id = sas_dev->device_id;
struct hisi_sas_itct *itct = _hba->itct[device_id];
+   struct asd_sas_port *sas_port = device->port;
+   struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
 
memset(itct, 0, sizeof(*itct));
 
@@ -528,7 +530,7 @@ static void setup_itct_v1_hw(struct hisi_hba *hisi_hba,
(1 << ITCT_HDR_AWT_CONTROL_OFF) |
(device->max_linkrate << ITCT_HDR_MAX_CONN_RATE_OFF) |
(1 << ITCT_HDR_VALID_LINK_NUM_OFF) |
-   (device->port->id << ITCT_HDR_PORT_ID_OFF));
+   (port->id << ITCT_HDR_PORT_ID_OFF));
itct->qw0 = cpu_to_le64(qw0);
 
/* qw1 */
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 1b21445..1590e2f 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ 

[PATCH 06/23] scsi: hisi_sas: error hisi_sas_task_prep() when port down

2017-03-22 Thread John Garry
When sas_port is NULL, then return SAS_PHY_DOWN.

In addition, when the sas_dev is gone then explicitly
return SAS_PHY_DOWN.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index f64c1b6..7c1fb75 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -200,7 +200,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
 */
if (device->dev_type != SAS_SATA_DEV)
task->task_done(task);
-   return 0;
+   return SAS_PHY_DOWN;
}
 
if (DEV_IS_GONE(sas_dev)) {
@@ -211,8 +211,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
dev_info(dev, "task prep: device %016llx not ready\n",
 SAS_ADDR(device->sas_addr));
 
-   rc = SAS_PHY_DOWN;
-   return rc;
+   return SAS_PHY_DOWN;
}
 
port = to_hisi_sas_port(sas_port);
-- 
1.9.1



[PATCH 15/23] scsi: hisi_sas: process error codes according to their priority

2017-03-22 Thread John Garry
From: Xiang Chen 

There are some rules to decide which error code has the high
priority  when errors happen together:
(1) Error phase of CQ decides the error happens on RX or TX;
(2) For TX error, when DMA/TRANS TX error happen simultaneously,
the priority of DMA TX error is higher than TRANS TX error, so
for the priority of TX error:
DW2 (DMA TX part) > DW0;
(3) For RX error, when TRANS/DMA/SIPC RX error happen simultaneously,
the priority of TRANS RX error is higher than DMA and SIPC RX error,
and we should also keep the rules (the priority of DW3 > DW2), so for
the priority of RX error:
DW1 > DW3 > DW2(SIPC RX part);
(4) There are also a priority we should keep in the same error type.

So, modify slot error code to handle this.

In addition to this, some some error codes are modified according to
recommendation from SoC designer.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 553 -
 1 file changed, 398 insertions(+), 155 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 2b6e64c..66a458b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -313,6 +313,8 @@
 
 /* Completion header */
 /* dw0 */
+#define CMPLT_HDR_ERR_PHASE_OFF2
+#define CMPLT_HDR_ERR_PHASE_MSK(0xff << CMPLT_HDR_ERR_PHASE_OFF)
 #define CMPLT_HDR_RSPNS_XFRD_OFF   10
 #define CMPLT_HDR_RSPNS_XFRD_MSK   (0x1 << CMPLT_HDR_RSPNS_XFRD_OFF)
 #define CMPLT_HDR_ERX_OFF  12
@@ -389,10 +391,10 @@ enum {
 
 enum {
TRANS_TX_FAIL_BASE = 0x0, /* dw0 */
-   TRANS_RX_FAIL_BASE = 0x100, /* dw1 */
-   DMA_TX_ERR_BASE = 0x200, /* dw2 bit 15-0 */
-   SIPC_RX_ERR_BASE = 0x300, /* dw2 bit 31-16*/
-   DMA_RX_ERR_BASE = 0x400, /* dw3 */
+   TRANS_RX_FAIL_BASE = 0x20, /* dw1 */
+   DMA_TX_ERR_BASE = 0x40, /* dw2 bit 15-0 */
+   SIPC_RX_ERR_BASE = 0x50, /* dw2 bit 31-16*/
+   DMA_RX_ERR_BASE = 0x60, /* dw3 */
 
/* trans tx*/
TRANS_TX_OPEN_FAIL_WITH_IT_NEXUS_LOSS = TRANS_TX_FAIL_BASE, /* 0x0 */
@@ -432,97 +434,100 @@ enum {
TRANS_TX_ERR_WITH_WAIT_RECV_TIMEOUT, /* 0x1f for sata/stp */
 
/* trans rx */
-   TRANS_RX_ERR_WITH_RXFRAME_CRC_ERR = TRANS_RX_FAIL_BASE, /* 0x100 */
-   TRANS_RX_ERR_WITH_RXFIS_8B10B_DISP_ERR, /* 0x101 for sata/stp */
-   TRANS_RX_ERR_WITH_RXFRAME_HAVE_ERRPRM, /* 0x102 for ssp/smp */
-   /*IO_ERR_WITH_RXFIS_8B10B_CODE_ERR, [> 0x102 <] for sata/stp */
-   TRANS_RX_ERR_WITH_RXFIS_DECODE_ERROR, /* 0x103 for sata/stp */
-   TRANS_RX_ERR_WITH_RXFIS_CRC_ERR, /* 0x104 for sata/stp */
-   TRANS_RX_ERR_WITH_RXFRAME_LENGTH_OVERRUN, /* 0x105 for smp */
-   /*IO_ERR_WITH_RXFIS_TX SYNCP, [> 0x105 <] for sata/stp */
-   TRANS_RX_ERR_WITH_RXFIS_RX_SYNCP, /* 0x106 for sata/stp*/
-   TRANS_RX_ERR_WITH_LINK_BUF_OVERRUN, /* 0x107 */
-   TRANS_RX_ERR_WITH_BREAK_TIMEOUT, /* 0x108 */
-   TRANS_RX_ERR_WITH_BREAK_REQUEST, /* 0x109 */
-   TRANS_RX_ERR_WITH_BREAK_RECEVIED, /* 0x10a */
-   RESERVED1, /* 0x10b */
-   TRANS_RX_ERR_WITH_CLOSE_NORMAL, /* 0x10c */
-   TRANS_RX_ERR_WITH_CLOSE_PHY_DISABLE, /* 0x10d */
-   TRANS_RX_ERR_WITH_CLOSE_DWS_TIMEOUT, /* 0x10e */
-   TRANS_RX_ERR_WITH_CLOSE_COMINIT, /* 0x10f */
-   TRANS_RX_ERR_WITH_DATA_LEN0, /* 0x110 for ssp/smp */
-   TRANS_RX_ERR_WITH_BAD_HASH, /* 0x111 for ssp */
-   /*IO_RX_ERR_WITH_FIS_TOO_SHORT, [> 0x111 <] for sata/stp */
-   TRANS_RX_XRDY_WLEN_ZERO_ERR, /* 0x112 for ssp*/
-   /*IO_RX_ERR_WITH_FIS_TOO_LONG, [> 0x112 <] for sata/stp */
-   TRANS_RX_SSP_FRM_LEN_ERR, /* 0x113 for ssp */
-   /*IO_RX_ERR_WITH_SATA_DEVICE_LOST, [> 0x113 <] for sata */
-   RESERVED2, /* 0x114 */
-   RESERVED3, /* 0x115 */
-   RESERVED4, /* 0x116 */
-   RESERVED5, /* 0x117 */
-   TRANS_RX_ERR_WITH_BAD_FRM_TYPE, /* 0x118 */
-   TRANS_RX_SMP_FRM_LEN_ERR, /* 0x119 */
-   TRANS_RX_SMP_RESP_TIMEOUT_ERR, /* 0x11a */
-   RESERVED6, /* 0x11b */
-   RESERVED7, /* 0x11c */
-   RESERVED8, /* 0x11d */
-   RESERVED9, /* 0x11e */
-   TRANS_RX_R_ERR, /* 0x11f */
+   TRANS_RX_ERR_WITH_RXFRAME_CRC_ERR = TRANS_RX_FAIL_BASE, /* 0x20 */
+   TRANS_RX_ERR_WITH_RXFIS_8B10B_DISP_ERR, /* 0x21 for sata/stp */
+   TRANS_RX_ERR_WITH_RXFRAME_HAVE_ERRPRM, /* 0x22 for ssp/smp */
+   /*IO_ERR_WITH_RXFIS_8B10B_CODE_ERR, [> 0x22 <] for sata/stp */
+   TRANS_RX_ERR_WITH_RXFIS_DECODE_ERROR, /* 0x23 for sata/stp */
+   TRANS_RX_ERR_WITH_RXFIS_CRC_ERR, /* 0x24 for sata/stp */
+   TRANS_RX_ERR_WITH_RXFRAME_LENGTH_OVERRUN, /* 0x25 for smp */
+   /*IO_ERR_WITH_RXFIS_TX SYNCP, [> 0x25 <] for sata/stp */
+   TRANS_RX_ERR_WITH_RXFIS_RX_SYNCP, /* 0x26 for sata/stp*/
+   TRANS_RX_ERR_WITH_LINK_BUF_OVERRUN, /* 0x27 */
+ 

[PATCH 18/23] scsi: hisi_sas: rename hisi_sas_link_timeout_{enable, disable}_link

2017-03-22 Thread John Garry
For consistency, remove the "hisi_sas_" prefix.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 45bd69d..e9c7188 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -549,7 +549,7 @@ enum {
 #define ERR_ON_RX_PHASE(err_phase) (err_phase == 0x10 || \
err_phase == 0x20 || err_phase == 0x40)
 
-static void hisi_sas_link_timeout_disable_link(unsigned long data);
+static void link_timeout_disable_link(unsigned long data);
 
 static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
 {
@@ -1006,7 +1006,7 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
 upper_32_bits(hisi_hba->initial_fis_dma));
 }
 
-static void hisi_sas_link_timeout_enable_link(unsigned long data)
+static void link_timeout_enable_link(unsigned long data)
 {
struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
int i, reg_val;
@@ -1020,11 +1020,11 @@ static void hisi_sas_link_timeout_enable_link(unsigned 
long data)
}
}
 
-   hisi_hba->timer.function = hisi_sas_link_timeout_disable_link;
+   hisi_hba->timer.function = link_timeout_disable_link;
mod_timer(_hba->timer, jiffies + msecs_to_jiffies(900));
 }
 
-static void hisi_sas_link_timeout_disable_link(unsigned long data)
+static void link_timeout_disable_link(unsigned long data)
 {
struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
int i, reg_val;
@@ -1038,14 +1038,14 @@ static void hisi_sas_link_timeout_disable_link(unsigned 
long data)
}
}
 
-   hisi_hba->timer.function = hisi_sas_link_timeout_enable_link;
+   hisi_hba->timer.function = link_timeout_enable_link;
mod_timer(_hba->timer, jiffies + msecs_to_jiffies(100));
 }
 
 static void set_link_timer_quirk(struct hisi_hba *hisi_hba)
 {
hisi_hba->timer.data = (unsigned long)hisi_hba;
-   hisi_hba->timer.function = hisi_sas_link_timeout_disable_link;
+   hisi_hba->timer.function = link_timeout_disable_link;
hisi_hba->timer.expires = jiffies + msecs_to_jiffies(1000);
add_timer(_hba->timer);
 }
-- 
1.9.1



[PATCH 17/23] scsi: hisi_sas: handle PHY UP+DOWN simultaneous irq

2017-03-22 Thread John Garry
From: Xiaofei Tan 

Handle the situation that PHY UP and DOWN irq happen simultaneously.
There is no mechanism of SoC HW to ensure this situation will never
happen. So, we add this handle just in case.

Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 56 +++---
 1 file changed, 39 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 8e869d9..45bd69d 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2285,7 +2285,7 @@ static int prep_abort_v2_hw(struct hisi_hba *hisi_hba,
 
 static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
 {
-   int i, res = 0;
+   int i, res = IRQ_HANDLED;
u32 context, port_id, link_rate, hard_phy_linkrate;
struct hisi_sas_phy *phy = _hba->phy[phy_no];
struct asd_sas_phy *sas_phy = >sas_phy;
@@ -2373,7 +2373,6 @@ static bool check_any_wideports_v2_hw(struct hisi_hba 
*hisi_hba)
 
 static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
 {
-   int res = 0;
u32 phy_state, sl_ctrl, txid_auto;
struct hisi_sas_phy *phy = _hba->phy[phy_no];
struct hisi_sas_port *port = phy->port;
@@ -2398,7 +2397,7 @@ static int phy_down_v2_hw(int phy_no, struct hisi_hba 
*hisi_hba)
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_NOT_RDY_MSK);
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 0);
 
-   return res;
+   return IRQ_HANDLED;
 }
 
 static irqreturn_t int_phy_updown_v2_hw(int irq_no, void *p)
@@ -2406,35 +2405,58 @@ static irqreturn_t int_phy_updown_v2_hw(int irq_no, 
void *p)
struct hisi_hba *hisi_hba = p;
u32 irq_msk;
int phy_no = 0;
-   irqreturn_t res = IRQ_HANDLED;
 
irq_msk = (hisi_sas_read32(hisi_hba, HGC_INVLD_DQE_INFO)
   >> HGC_INVLD_DQE_INFO_FB_CH0_OFF) & 0x1ff;
while (irq_msk) {
if (irq_msk  & 1) {
-   u32 irq_value = hisi_sas_phy_read32(hisi_hba, phy_no,
-   CHL_INT0);
+   u32 reg_value = hisi_sas_phy_read32(hisi_hba, phy_no,
+   CHL_INT0);
+
+   switch (reg_value & (CHL_INT0_NOT_RDY_MSK |
+   CHL_INT0_SL_PHY_ENABLE_MSK)) {
 
-   if (irq_value & CHL_INT0_SL_PHY_ENABLE_MSK)
+   case CHL_INT0_SL_PHY_ENABLE_MSK:
/* phy up */
-   if (phy_up_v2_hw(phy_no, hisi_hba)) {
-   res = IRQ_NONE;
-   goto end;
-   }
+   if (phy_up_v2_hw(phy_no, hisi_hba) ==
+   IRQ_NONE)
+   return IRQ_NONE;
+   break;
 
-   if (irq_value & CHL_INT0_NOT_RDY_MSK)
+   case CHL_INT0_NOT_RDY_MSK:
/* phy down */
-   if (phy_down_v2_hw(phy_no, hisi_hba)) {
-   res = IRQ_NONE;
-   goto end;
+   if (phy_down_v2_hw(phy_no, hisi_hba) ==
+   IRQ_NONE)
+   return IRQ_NONE;
+   break;
+
+   case (CHL_INT0_NOT_RDY_MSK |
+   CHL_INT0_SL_PHY_ENABLE_MSK):
+   reg_value = hisi_sas_read32(hisi_hba,
+   PHY_STATE);
+   if (reg_value & BIT(phy_no)) {
+   /* phy up */
+   if (phy_up_v2_hw(phy_no, hisi_hba) ==
+   IRQ_NONE)
+   return IRQ_NONE;
+   } else {
+   /* phy down */
+   if (phy_down_v2_hw(phy_no, hisi_hba) ==
+   IRQ_NONE)
+   return IRQ_NONE;
}
+   break;
+
+   default:
+   break;
+   }
+
}
irq_msk >>= 1;
phy_no++;
}
 
-end:
-   return res;
+   return IRQ_HANDLED;
 }
 
 static void phy_bcast_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
-- 
1.9.1



[PATCH 04/23] scsi: hisi_sas: add softreset function for SATA disk

2017-03-22 Thread John Garry
From: Xiang Chen 

Add softreset to clear IO after internal abort device
for SATA disk.

The SATA error handling for the controller is based on
device internal abort and softreset function.

The controller does not support internal abort for single
IO, so we need to execute internal abort for device.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/Kconfig  |  2 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 70 --
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  3 +-
 3 files changed, 69 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig
index d1dd161..ded2c20 100644
--- a/drivers/scsi/hisi_sas/Kconfig
+++ b/drivers/scsi/hisi_sas/Kconfig
@@ -2,7 +2,7 @@ config SCSI_HISI_SAS
tristate "HiSilicon SAS"
depends on HAS_DMA && HAS_IOMEM
depends on ARM64 || COMPILE_TEST
-   select SCSI_SAS_LIBSAS
+   depends on SCSI_SAS_ATA
select BLK_DEV_INTEGRITY
help
This driver supports HiSilicon's SAS HBA
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index b86a228..9d9f305 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -21,6 +21,7 @@ static int hisi_sas_debug_issue_ssp_tmf(struct domain_device 
*device,
 hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
 struct domain_device *device,
 int abort_flag, int tag);
+static int hisi_sas_softreset_ata_disk(struct domain_device *device);
 
 static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
 {
@@ -720,7 +721,12 @@ static int hisi_sas_exec_internal_tmf_task(struct 
domain_device *device,
task->dev = device;
task->task_proto = device->tproto;
 
-   memcpy(>ssp_task, parameter, para_len);
+   if (dev_is_sata(device)) {
+   task->ata_task.device_control_reg_update = 1;
+   memcpy(>ata_task.fis, parameter, para_len);
+   } else {
+   memcpy(>ssp_task, parameter, para_len);
+   }
task->task_done = hisi_sas_task_done;
 
task->slow_task->timer.data = (unsigned long) task;
@@ -742,8 +748,7 @@ static int hisi_sas_exec_internal_tmf_task(struct 
domain_device *device,
/* Even TMF timed out, return direct. */
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
-   dev_err(dev, "abort tmf: TMF task[%d] 
timeout\n",
-   tmf->tag_of_task_to_be_managed);
+   dev_err(dev, "abort tmf: TMF task timeout\n");
if (task->lldd_task) {
struct hisi_sas_slot *slot =
task->lldd_task;
@@ -803,6 +808,63 @@ static int hisi_sas_exec_internal_tmf_task(struct 
domain_device *device,
return res;
 }
 
+static void hisi_sas_fill_ata_reset_cmd(struct ata_device *dev,
+   bool reset, int pmp, u8 *fis)
+{
+   struct ata_taskfile tf;
+
+   ata_tf_init(dev, );
+   if (reset)
+   tf.ctl |= ATA_SRST;
+   else
+   tf.ctl &= ~ATA_SRST;
+   tf.command = ATA_CMD_DEV_RESET;
+   ata_tf_to_fis(, pmp, 0, fis);
+}
+
+static int hisi_sas_softreset_ata_disk(struct domain_device *device)
+{
+   u8 fis[20] = {0};
+   struct ata_port *ap = device->sata_dev.ap;
+   struct ata_link *link;
+   int rc = TMF_RESP_FUNC_FAILED;
+   struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+   struct device *dev = _hba->pdev->dev;
+   int s = sizeof(struct host_to_dev_fis);
+   unsigned long flags;
+
+   ata_for_each_link(link, ap, EDGE) {
+   int pmp = sata_srst_pmp(link);
+
+   hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, fis);
+   rc = hisi_sas_exec_internal_tmf_task(device, fis, s, NULL);
+   if (rc != TMF_RESP_FUNC_COMPLETE)
+   break;
+   }
+
+   if (rc == TMF_RESP_FUNC_COMPLETE) {
+   ata_for_each_link(link, ap, EDGE) {
+   int pmp = sata_srst_pmp(link);
+
+   hisi_sas_fill_ata_reset_cmd(link->device, 0, pmp, fis);
+   rc = hisi_sas_exec_internal_tmf_task(device, fis,
+s, NULL);
+   if (rc != TMF_RESP_FUNC_COMPLETE)
+   dev_err(dev, "ata disk de-reset failed\n");
+   }
+   } else {
+   dev_err(dev, "ata disk reset failed\n");
+   }
+
+  

[PATCH 19/23] scsi: hisi_sas: add hisi_sas_clear_nexus_ha()

2017-03-22 Thread John Garry
Add function for upper-layer to reset controller
when all else fails.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 3d63a24..f86263b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1070,6 +1070,13 @@ static int hisi_sas_lu_reset(struct domain_device 
*device, u8 *lun)
return rc;
 }
 
+static int hisi_sas_clear_nexus_ha(struct sas_ha_struct *sas_ha)
+{
+   struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
+
+   return hisi_sas_controller_reset(hisi_hba);
+}
+
 static int hisi_sas_query_task(struct sas_task *task)
 {
struct scsi_lun lun;
@@ -1368,6 +1375,7 @@ void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, 
u32 old_state,
.lldd_I_T_nexus_reset   = hisi_sas_I_T_nexus_reset,
.lldd_lu_reset  = hisi_sas_lu_reset,
.lldd_query_task= hisi_sas_query_task,
+   .lldd_clear_nexus_ha = hisi_sas_clear_nexus_ha,
.lldd_port_formed   = hisi_sas_port_formed,
 };
 
-- 
1.9.1



[PATCH 03/23] scsi: hisi_sas: move PHY init to hisi_sas_scan_start()

2017-03-22 Thread John Garry
Relocate the PHY init code from LLDD hw init path
to hisi_sas_scan_start().

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas.h   | 2 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 9 +++--
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 +--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 3 +--
 4 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index fd76a02..2135de9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -167,6 +167,7 @@ struct hisi_sas_hw {
  int device_id, int abort_flag, int tag_to_abort);
int (*slot_complete)(struct hisi_hba *hisi_hba,
 struct hisi_sas_slot *slot, int abort);
+   void (*phys_init)(struct hisi_hba *hisi_hba);
void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no);
void (*phy_disable)(struct hisi_hba *hisi_hba, int phy_no);
void (*phy_hard_reset)(struct hisi_hba *hisi_hba, int phy_no);
@@ -195,7 +196,6 @@ struct hisi_hba {
u8 sas_addr[SAS_ADDR_SIZE];
 
int n_phy;
-   int scan_finished;
spinlock_t lock;
 
struct timer_list timer;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index cbaef90..b86a228 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -493,12 +493,8 @@ static int hisi_sas_slave_configure(struct scsi_device 
*sdev)
 static void hisi_sas_scan_start(struct Scsi_Host *shost)
 {
struct hisi_hba *hisi_hba = shost_priv(shost);
-   int i;
-
-   for (i = 0; i < hisi_hba->n_phy; ++i)
-   hisi_sas_bytes_dmaed(hisi_hba, i);
 
-   hisi_hba->scan_finished = 1;
+   hisi_hba->hw->phys_init(hisi_hba);
 }
 
 static int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
@@ -506,7 +502,8 @@ static int hisi_sas_scan_finished(struct Scsi_Host *shost, 
unsigned long time)
struct hisi_hba *hisi_hba = shost_priv(shost);
struct sas_ha_struct *sha = _hba->sha;
 
-   if (hisi_hba->scan_finished == 0)
+   /* Wait for PHY up interrupt to occur */
+   if (time < HZ)
return 0;
 
sas_drain_work(sha);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 022ad10..43988eb 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1847,8 +1847,6 @@ static int hisi_sas_v1_init(struct hisi_hba *hisi_hba)
if (rc)
return rc;
 
-   phys_init_v1_hw(hisi_hba);
-
return 0;
 }
 
@@ -1862,6 +1860,7 @@ static int hisi_sas_v1_init(struct hisi_hba *hisi_hba)
.get_free_slot = get_free_slot_v1_hw,
.start_delivery = start_delivery_v1_hw,
.slot_complete = slot_complete_v1_hw,
+   .phys_init = phys_init_v1_hw,
.phy_enable = enable_phy_v1_hw,
.phy_disable = disable_phy_v1_hw,
.phy_hard_reset = phy_hard_reset_v1_hw,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 53651cf..73e4f66 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2864,8 +2864,6 @@ static int hisi_sas_v2_init(struct hisi_hba *hisi_hba)
if (rc)
return rc;
 
-   phys_init_v2_hw(hisi_hba);
-
return 0;
 }
 
@@ -2965,6 +2963,7 @@ static int soft_reset_v2_hw(struct hisi_hba *hisi_hba)
.get_free_slot = get_free_slot_v2_hw,
.start_delivery = start_delivery_v2_hw,
.slot_complete = slot_complete_v2_hw,
+   .phys_init = phys_init_v2_hw,
.phy_enable = enable_phy_v2_hw,
.phy_disable = disable_phy_v2_hw,
.phy_hard_reset = phy_hard_reset_v2_hw,
-- 
1.9.1



[PATCH 10/23] scsi: hisi_sas: hardreset for SATA disk in LU reset

2017-03-22 Thread John Garry
When issuing an LU reset for a SATA target, issue an
internal abort and a hard reset.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 38 ++-
 1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 36d4e5a..19f2892 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1037,23 +1037,43 @@ static int hisi_sas_I_T_nexus_reset(struct 
domain_device *device)
 
 static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
 {
-   struct hisi_sas_tmf_task tmf_task;
struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct device *dev = _hba->pdev->dev;
unsigned long flags;
int rc = TMF_RESP_FUNC_FAILED;
 
-   tmf_task.tmf = TMF_LU_RESET;
sas_dev->dev_status = HISI_SAS_DEV_EH;
-   rc = hisi_sas_debug_issue_ssp_tmf(device, lun, _task);
-   if (rc == TMF_RESP_FUNC_COMPLETE) {
-   spin_lock_irqsave(_hba->lock, flags);
-   hisi_sas_release_task(hisi_hba, device);
-   spin_unlock_irqrestore(_hba->lock, flags);
-   }
+   if (dev_is_sata(device)) {
+   struct sas_phy *phy;
+
+   /* Clear internal IO and then hardreset */
+   rc = hisi_sas_internal_task_abort(hisi_hba, device,
+ HISI_SAS_INT_ABT_DEV, 0);
+   if (rc == TMF_RESP_FUNC_FAILED)
+   goto out;
 
-   /* If failed, fall-through I_T_Nexus reset */
+   phy = sas_get_local_phy(device);
+
+   rc = sas_phy_reset(phy, 1);
+
+   if (rc == 0) {
+   spin_lock_irqsave(_hba->lock, flags);
+   hisi_sas_release_task(hisi_hba, device);
+   spin_unlock_irqrestore(_hba->lock, flags);
+   }
+   sas_put_local_phy(phy);
+   } else {
+   struct hisi_sas_tmf_task tmf_task = { .tmf =  TMF_LU_RESET };
+
+   rc = hisi_sas_debug_issue_ssp_tmf(device, lun, _task);
+   if (rc == TMF_RESP_FUNC_COMPLETE) {
+   spin_lock_irqsave(_hba->lock, flags);
+   hisi_sas_release_task(hisi_hba, device);
+   spin_unlock_irqrestore(_hba->lock, flags);
+   }
+   }
+out:
dev_err(dev, "lu_reset: for device[%llx]:rc= %d\n",
sas_dev->device_id, rc);
return rc;
-- 
1.9.1



[PATCH 13/23] scsi: hisi_sas: fix some sas_task.task_state_lock locking

2017-03-22 Thread John Garry
Some more locking needs to be added/modified for when
read-modify-writing sas_task.task_state_flags.

Note: since we can attempt to grab this lock in interrupt
  context we should use irq variant of spin_lock.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 13 ++---
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  3 +++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  7 +--
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 49cac22..f9ea5cc 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -188,6 +188,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
struct asd_sas_port *sas_port = device->port;
struct device *dev = _hba->pdev->dev;
int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
+   unsigned long flags;
 
if (!sas_port) {
struct task_status_struct *ts = >task_status;
@@ -308,9 +309,9 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
}
 
list_add_tail(>entry, _dev->list);
-   spin_lock(>task_state_lock);
+   spin_lock_irqsave(>task_state_lock, flags);
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
-   spin_unlock(>task_state_lock);
+   spin_unlock_irqrestore(>task_state_lock, flags);
 
hisi_hba->slot_prep = slot;
 
@@ -922,14 +923,11 @@ static int hisi_sas_abort_task(struct sas_task *task)
return TMF_RESP_FUNC_FAILED;
}
 
-   spin_lock_irqsave(>task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
-   spin_unlock_irqrestore(>task_state_lock, flags);
rc = TMF_RESP_FUNC_COMPLETE;
goto out;
}
 
-   spin_unlock_irqrestore(>task_state_lock, flags);
sas_dev->dev_status = HISI_SAS_DEV_EH;
if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd *cmnd = task->uldd_task;
@@ -1127,6 +1125,7 @@ static int hisi_sas_query_task(struct sas_task *task)
struct asd_sas_port *sas_port = device->port;
struct hisi_sas_cmd_hdr *cmd_hdr_base;
int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
+   unsigned long flags;
 
if (unlikely(test_bit(HISI_SAS_RESET_BIT, _hba->flags)))
return -EINVAL;
@@ -1167,9 +1166,9 @@ static int hisi_sas_query_task(struct sas_task *task)
 
 
list_add_tail(>entry, _dev->list);
-   spin_lock(>task_state_lock);
+   spin_lock_irqsave(>task_state_lock, flags);
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
-   spin_unlock(>task_state_lock);
+   spin_unlock_irqrestore(>task_state_lock, flags);
 
hisi_hba->slot_prep = slot;
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 2f3e877..fc1c1b2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1288,6 +1288,7 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_complete_v1_hdr *complete_queue =
hisi_hba->complete_hdr[slot->cmplt_queue];
struct hisi_sas_complete_v1_hdr *complete_hdr;
+   unsigned long flags;
u32 cmplt_hdr_data;
 
complete_hdr = _queue[slot->cmplt_queue_slot];
@@ -1300,9 +1301,11 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
device = task->dev;
sas_dev = device->lldd_dev;
 
+   spin_lock_irqsave(>task_state_lock, flags);
task->task_state_flags &=
~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
task->task_state_flags |= SAS_TASK_STATE_DONE;
+   spin_unlock_irqrestore(>task_state_lock, flags);
 
memset(ts, 0, sizeof(*ts));
ts->resp = SAS_TASK_COMPLETE;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index f4d8200..2b6e64c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1737,6 +1737,7 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
hisi_hba->complete_hdr[slot->cmplt_queue];
struct hisi_sas_complete_v2_hdr *complete_hdr =
_queue[slot->cmplt_queue_slot];
+   unsigned long flags;
int aborted;
 
if (unlikely(!task || !task->lldd_task || !task->dev))
@@ -1746,11 +1747,11 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
device = task->dev;
sas_dev = device->lldd_dev;
 
-   spin_lock(>task_state_lock);
+   spin_lock_irqsave(>task_state_lock, flags);
aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED;
task->task_state_flags &=

[PATCH 20/23] scsi: hisi_sas: release SMP slot in lldd_abort_task

2017-03-22 Thread John Garry
From: Xiang Chen 

When an SMP task timeouts, it will call lldd_abort_task
to release the associated slot, and then will release
the sas_task.

Currently in lldd_abort_task, if we fail to internally
abort IO, then the slot of SMP IO is not released,
but sas_task will still be later released, so the slot's
sas_task is NULL, which will cause NULL pointer when
hisi_sas_slot_task_free happens later.

To resolve, check the return value of internal abort,
and release the slot if it failed.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index f86263b..1391f2d 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -962,8 +962,13 @@ static int hisi_sas_abort_task(struct sas_task *task)
struct hisi_sas_slot *slot = task->lldd_task;
u32 tag = slot->idx;
 
-   hisi_sas_internal_task_abort(hisi_hba, device,
-HISI_SAS_INT_ABT_CMD, tag);
+   rc = hisi_sas_internal_task_abort(hisi_hba, device,
+HISI_SAS_INT_ABT_CMD, tag);
+   if (rc == TMF_RESP_FUNC_FAILED) {
+   spin_lock_irqsave(_hba->lock, flags);
+   hisi_sas_do_release_task(hisi_hba, task, slot);
+   spin_unlock_irqrestore(_hba->lock, flags);
+   }
}
 
 out:
-- 
1.9.1



[PATCH 12/23] scsi: hisi_sas: free slots after hardreset

2017-03-22 Thread John Garry
From: Xiang Chen 

After hardreset, we clear up IOs of remote disks, so we
need to free those slots in LLDD.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 19f2892..49cac22 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1028,11 +1028,12 @@ static int hisi_sas_I_T_nexus_reset(struct 
domain_device *device)
 
rc = hisi_sas_debug_I_T_nexus_reset(device);
 
-   spin_lock_irqsave(_hba->lock, flags);
-   hisi_sas_release_task(hisi_hba, device);
-   spin_unlock_irqrestore(_hba->lock, flags);
-
-   return 0;
+   if (rc == TMF_RESP_FUNC_COMPLETE) {
+   spin_lock_irqsave(_hba->lock, flags);
+   hisi_sas_release_task(hisi_hba, device);
+   spin_unlock_irqrestore(_hba->lock, flags);
+   }
+   return rc;
 }
 
 static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
-- 
1.9.1



[PATCH 16/23] scsi: hisi_sas: some modifications to v2 hw reg init values

2017-03-22 Thread John Garry
This patch includes:
(1) Disable transport layer retry
(2) Support CQ time and count interrupt coal
(3) fix link FIFO full issue

Signed-off-by: Xiang Chen 
Signed-off-by: Zhao Nenglong 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 66a458b..8e869d9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -893,7 +893,7 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
 (u32)((1ULL << hisi_hba->queue_count) - 1));
hisi_sas_write32(hisi_hba, AXI_USER1, 0xc000);
hisi_sas_write32(hisi_hba, AXI_USER2, 0x1);
-   hisi_sas_write32(hisi_hba, HGC_SAS_TXFAIL_RETRY_CTRL, 0x108);
+   hisi_sas_write32(hisi_hba, HGC_SAS_TXFAIL_RETRY_CTRL, 0x0);
hisi_sas_write32(hisi_hba, HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL, 0x7FF);
hisi_sas_write32(hisi_hba, OPENA_WT_CONTI_TIME, 0x1);
hisi_sas_write32(hisi_hba, I_T_NEXUS_LOSS_TIME, 0x1F4);
@@ -902,9 +902,9 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
hisi_sas_write32(hisi_hba, CFG_AGING_TIME, 0x1);
hisi_sas_write32(hisi_hba, HGC_ERR_STAT_EN, 0x1);
hisi_sas_write32(hisi_hba, HGC_GET_ITV_TIME, 0x1);
-   hisi_sas_write32(hisi_hba, INT_COAL_EN, 0x1);
-   hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, 0x1);
-   hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, 0x1);
+   hisi_sas_write32(hisi_hba, INT_COAL_EN, 0xc);
+   hisi_sas_write32(hisi_hba, OQ_INT_COAL_TIME, 0x60);
+   hisi_sas_write32(hisi_hba, OQ_INT_COAL_CNT, 0x3);
hisi_sas_write32(hisi_hba, ENT_INT_COAL_TIME, 0x1);
hisi_sas_write32(hisi_hba, ENT_INT_COAL_CNT, 0x1);
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 0x0);
@@ -927,14 +927,14 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
hisi_sas_phy_write32(hisi_hba, i, SL_TOUT_CFG, 0x7d7d7d7d);
hisi_sas_phy_write32(hisi_hba, i, SL_CONTROL, 0x0);
hisi_sas_phy_write32(hisi_hba, i, TXID_AUTO, 0x2);
-   hisi_sas_phy_write32(hisi_hba, i, DONE_RECEIVED_TIME, 0x10);
+   hisi_sas_phy_write32(hisi_hba, i, DONE_RECEIVED_TIME, 0x8);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0x);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0x);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xfff87fff);
hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0x);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x8bff);
-   hisi_sas_phy_write32(hisi_hba, i, SL_CFG, 0x23f801fc);
+   hisi_sas_phy_write32(hisi_hba, i, SL_CFG, 0x13f801fc);
hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0);
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0);
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_DWS_RESET_MSK, 0x0);
-- 
1.9.1



[PATCH 21/23] scsi: hisi_sas: check hisi_sas_lu_reset() error message

2017-03-22 Thread John Garry
Unless we actually get some sort of failure in
hisi_sas_lu_reset(), don't print a message.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 1391f2d..dcceff9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1070,8 +1070,9 @@ static int hisi_sas_lu_reset(struct domain_device 
*device, u8 *lun)
}
}
 out:
-   dev_err(dev, "lu_reset: for device[%llx]:rc= %d\n",
-   sas_dev->device_id, rc);
+   if (rc != TMF_RESP_FUNC_COMPLETE)
+   dev_err(dev, "lu_reset: for device[%llx]:rc= %d\n",
+sas_dev->device_id, rc);
return rc;
 }
 
-- 
1.9.1



[PATCH 09/23] scsi: hisi_sas: modify hisi_sas_abort_task() for SSP

2017-03-22 Thread John Garry
Currently an internal abort is executed regardless
of the result of the TMF. We should also check the
result of the internal abort to see if we should
free the slot.

So change the status code STAT_IO_COMPLETE to
TMF_RESP_FUNC_SUCC, meaning the slot has been
successfully aborted.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 28 ++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  2 +-
 2 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 00068d2..36d4e5a 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -935,6 +935,7 @@ static int hisi_sas_abort_task(struct sas_task *task)
struct scsi_cmnd *cmnd = task->uldd_task;
struct hisi_sas_slot *slot = task->lldd_task;
u32 tag = slot->idx;
+   int rc2;
 
int_to_scsilun(cmnd->device->lun, );
tmf_task.tmf = TMF_ABORT_TASK;
@@ -943,21 +944,22 @@ static int hisi_sas_abort_task(struct sas_task *task)
rc = hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun,
  _task);
 
-   /* if successful, clear the task and callback forwards.*/
-   if (rc == TMF_RESP_FUNC_COMPLETE) {
+   rc2 = hisi_sas_internal_task_abort(hisi_hba, device,
+  HISI_SAS_INT_ABT_CMD, tag);
+   /*
+* If the TMF finds that the IO is not in the device and also
+* the internal abort does not succeed, then it is safe to
+* free the slot.
+* Note: if the internal abort succeeds then the slot
+* will have already been completed
+*/
+   if (rc == TMF_RESP_FUNC_COMPLETE && rc2 != TMF_RESP_FUNC_SUCC) {
if (task->lldd_task) {
-   struct hisi_sas_slot *slot;
-
-   slot = _hba->slot_info
-   [tmf_task.tag_of_task_to_be_managed];
spin_lock_irqsave(_hba->lock, flags);
-   hisi_hba->hw->slot_complete(hisi_hba, slot);
+   hisi_sas_do_release_task(hisi_hba, task, slot);
spin_unlock_irqrestore(_hba->lock, flags);
}
}
-
-   hisi_sas_internal_task_abort(hisi_hba, device,
-HISI_SAS_INT_ABT_CMD, tag);
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) {
if (task->dev->dev_type == SAS_SATA_DEV) {
@@ -1220,6 +1222,12 @@ static int hisi_sas_query_task(struct sas_task *task)
goto exit;
}
 
+   if (task->task_status.resp == SAS_TASK_COMPLETE &&
+   task->task_status.stat == TMF_RESP_FUNC_SUCC) {
+   res = TMF_RESP_FUNC_SUCC;
+   goto exit;
+   }
+
/* TMF timed out, return direct. */
if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index a35f881..ad5a7e6 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1766,7 +1766,7 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
goto out;
case STAT_IO_COMPLETE:
/* internal abort command complete */
-   ts->stat = TMF_RESP_FUNC_COMPLETE;
+   ts->stat = TMF_RESP_FUNC_SUCC;
goto out;
case STAT_IO_NO_DEVICE:
ts->stat = TMF_RESP_FUNC_COMPLETE;
-- 
1.9.1



[PATCH 23/23] scsi: hisi_sas: add is_sata_phy_v2_hw()

2017-03-22 Thread John Garry
From: Xiaofei Tan 

Add helper function is_sata_phy_v2_hw() to judge whether
the attached device is SATA disk for a root PHY.

Signed-off-by: Xiaofei Tan 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index e9c7188..a3af380 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1075,6 +1075,17 @@ static void enable_phy_v2_hw(struct hisi_hba *hisi_hba, 
int phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
 }
 
+static bool is_sata_phy_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   u32 context;
+
+   context = hisi_sas_read32(hisi_hba, PHY_CONTEXT);
+   if (context & (1 << phy_no))
+   return true;
+
+   return false;
+}
+
 static void disable_phy_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
 {
u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
@@ -2286,7 +2297,7 @@ static int prep_abort_v2_hw(struct hisi_hba *hisi_hba,
 static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
 {
int i, res = IRQ_HANDLED;
-   u32 context, port_id, link_rate, hard_phy_linkrate;
+   u32 port_id, link_rate, hard_phy_linkrate;
struct hisi_sas_phy *phy = _hba->phy[phy_no];
struct asd_sas_phy *sas_phy = >sas_phy;
struct device *dev = _hba->pdev->dev;
@@ -2295,9 +2306,7 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba 
*hisi_hba)
 
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1);
 
-   /* Check for SATA dev */
-   context = hisi_sas_read32(hisi_hba, PHY_CONTEXT);
-   if (context & (1 << phy_no))
+   if (is_sata_phy_v2_hw(hisi_hba, phy_no))
goto end;
 
if (phy_no == 8) {
-- 
1.9.1



[PATCH 11/23] scsi: hisi_sas: check for SAS_TASK_STATE_ABORTED in slot complete

2017-03-22 Thread John Garry
Check in slot_complete_v2_hw() for whether a task has
already been completed by upper layer.

Signed-off-by: John Garry 
Reviewed-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index ad5a7e6..f4d8200 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1737,6 +1737,7 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
hisi_hba->complete_hdr[slot->cmplt_queue];
struct hisi_sas_complete_v2_hdr *complete_hdr =
_queue[slot->cmplt_queue_slot];
+   int aborted;
 
if (unlikely(!task || !task->lldd_task || !task->dev))
return -EINVAL;
@@ -1745,12 +1746,21 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
device = task->dev;
sas_dev = device->lldd_dev;
 
+   spin_lock(>task_state_lock);
+   aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED;
task->task_state_flags &=
~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
+   spin_unlock(>task_state_lock);
 
memset(ts, 0, sizeof(*ts));
ts->resp = SAS_TASK_COMPLETE;
 
+   if (unlikely(aborted)) {
+   ts->stat = SAS_ABORTED_TASK;
+   hisi_sas_slot_task_free(hisi_hba, task, slot);
+   return -1;
+   }
+
if (unlikely(!sas_dev)) {
dev_dbg(dev, "slot complete: port has no device\n");
ts->stat = SAS_PHY_DOWN;
-- 
1.9.1



[PATCH 07/23] scsi: hisi_sas: only reset link for PHY_FUNC_LINK_RESET

2017-03-22 Thread John Garry
We currently do a hard reset for a link reset. Change this
to do a link reset only.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 7c1fb75..00068d2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -659,8 +659,9 @@ static int hisi_sas_control_phy(struct asd_sas_phy 
*sas_phy, enum phy_func func,
break;
 
case PHY_FUNC_LINK_RESET:
+   hisi_hba->hw->phy_disable(hisi_hba, phy_no);
+   msleep(100);
hisi_hba->hw->phy_enable(hisi_hba, phy_no);
-   hisi_hba->hw->phy_hard_reset(hisi_hba, phy_no);
break;
 
case PHY_FUNC_DISABLE:
-- 
1.9.1



[PATCH 00/23] hisi_sas: error handling and other misc fixes and improvements

2017-03-22 Thread John Garry
This patchset introduces a range of error handling
and other misc improvements for the HiSilicon SAS
controller, including:
- controller reset function
- softreset for SATA error handling
- fixes for slot free'ing
- v2 hw error handling improvements
- and other misc, more minor stuff

John Garry (14):
  scsi: hisi_sas: add to_hisi_sas_port()
  scsi: hisi_sas: move PHY init to hisi_sas_scan_start()
  scsi: hisi_sas: remove hisi_sas_port_deformed()
  scsi: hisi_sas: error hisi_sas_task_prep() when port down
  scsi: hisi_sas: only reset link for PHY_FUNC_LINK_RESET
  scsi: hisi_sas: modify hisi_sas_abort_task() for SSP
  scsi: hisi_sas: hardreset for SATA disk in LU reset
  scsi: hisi_sas: check for SAS_TASK_STATE_ABORTED in slot complete
  scsi: hisi_sas: fix some sas_task.task_state_lock locking
  scsi: hisi_sas: remove task free'ing for timeouts
  scsi: hisi_sas: some modifications to v2 hw reg init values
  scsi: hisi_sas: rename hisi_sas_link_timeout_{enable, disable}_link
  scsi: hisi_sas: add hisi_sas_clear_nexus_ha()
  scsi: hisi_sas: check hisi_sas_lu_reset() error message

Xiang Chen (7):
  scsi: hisi_sas: add controller reset
  scsi: hisi_sas: add softreset function for SATA disk
  scsi: hisi_sas: modify error handling for v2 hw
  scsi: hisi_sas: free slots after hardreset
  scsi: hisi_sas: process error codes according to their priority
  scsi: hisi_sas: release SMP slot in lldd_abort_task
  scsi: hisi_sas: use dev_is_sata to identify SATA or SAS disk

Xiaofei Tan (2):
  scsi: hisi_sas: handle PHY UP+DOWN simultaneous irq
  scsi: hisi_sas: add is_sata_phy_v2_hw()

 drivers/scsi/hisi_sas/Kconfig  |   2 +-
 drivers/scsi/hisi_sas/hisi_sas.h   |  15 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 436 +-
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  19 +-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 789 -
 5 files changed, 925 insertions(+), 336 deletions(-)

-- 
1.9.1



[Bug 176951] boot fails unless acpi=off Acer Travelmate X-349

2017-03-22 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=176951

Alan Welsh (itsallene...@gmail.com) changed:

   What|Removed |Added

 CC||itsallene...@gmail.com

--- Comment #22 from Alan Welsh (itsallene...@gmail.com) ---
I can confirm the system does not boot unless either: a) passed with the
acpi=off parameter in legacy mode or, b) booted in UEFI mode.

As for (a): This issue is resolved with grsecurity kernel.

As for (b): UEFI cannot be used because all linux bootloaders fail to be
recognized by the firmware. There is not one distribution which boots after
installation. The bootloader never loads. Only receive error message "disk not
found" or something to that effect.

Acer swift 3 (bios 1.08)

All x64 flavors from: Ubuntu, Fedora, Gentoo, Arch, opensuse.

-- 
You are receiving this mail because:
You are watching the assignee of the bug.


[PATCH] scsi: fcoe: sanity check string size for store_ctrl_mode option

2017-03-22 Thread Colin King
From: Colin Ian King 

Reading and writing to mode[count - 1] implies the count should not
be less than 1 so add a sanity check for this.

Detected with CoverityScan, CID#1357345 ("Overflowed array index write")

Signed-off-by: Colin Ian King 
---
 drivers/scsi/fcoe/fcoe_sysfs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/fcoe/fcoe_sysfs.c b/drivers/scsi/fcoe/fcoe_sysfs.c
index 9cf3d56296ab..e298240c728c 100644
--- a/drivers/scsi/fcoe/fcoe_sysfs.c
+++ b/drivers/scsi/fcoe/fcoe_sysfs.c
@@ -288,7 +288,7 @@ static ssize_t store_ctlr_mode(struct device *dev,
struct fcoe_ctlr_device *ctlr = dev_to_ctlr(dev);
char mode[FCOE_MAX_MODENAME_LEN + 1];
 
-   if (count > FCOE_MAX_MODENAME_LEN)
+   if (count < 1 || count > FCOE_MAX_MODENAME_LEN)
return -EINVAL;
 
strncpy(mode, buf, count);
-- 
2.11.0



Re: [PATCH] scsi: ufs: remove the duplicated checking for supporting clkscaling

2017-03-22 Thread Bartlomiej Zolnierkiewicz

Hi,

On Tuesday, March 21, 2017 09:19:57 PM Jaehoon Chung wrote:
> There are same conditions for checking whether supporting clkscaling or
> not.
> When ufshcd is supporting clkscaling, active_reqs should be decreased by
> two.

I guess you meant "one" here, not "two"?

> Signed-off-by: Jaehoon Chung 
> ---
>  drivers/scsi/ufs/ufshcd.c | 2 --
>  1 file changed, 2 deletions(-)
> 
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index dc6efbd..f2cbc71 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -4598,8 +4598,6 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba 
> *hba,
>   }
>   if (ufshcd_is_clkscaling_supported(hba))
>   hba->clk_scaling.active_reqs--;
> - if (ufshcd_is_clkscaling_supported(hba))
> - hba->clk_scaling.active_reqs--;
>   }
>  
>   /* clear corresponding bits of completed commands */

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R Institute Poland
Samsung Electronics



[PATCH] qla4xxx: drop redundant init_completion

2017-03-22 Thread Nicholas Mc Guire
The redundant init_completion() here seems to be a cut error as
struct scsi_qla_host only has 4 completion elements to initialize, thus
the duplicate init_completion(disable_acb_comp) is simply removed.

Signed-off-by: Nicholas Mc Guire <der.h...@hofr.at>
---

Found by experimental coccinelle script: 
./drivers/scsi/qla4xxx/ql4_os.c:8667:1-16: WARNING: possible duplicate 
init_completion


checking struct scsi_qla_host in
drivers/scsi/qla4xxx/ql4_def.h:457 "Linux Host Adapter structure"
it contain only the following 4 completion objects:

struct completion disable_acb_comp;
struct completion idc_comp;
struct completion link_up_comp;
struct completion mbx_intr_comp;

so it seems the double initialization of disable_acb_comp was just a
cut but and no omission of some other completion object - thus
the second initialization is simply removed.

Patch was only compile tested with: x86_64_defconfig + SCSI_LOWLEVEL=y,
 CONFIG_SCSI_QLA_ISCSI=m
(...quite a few sparse and coccinelle errors/warnings during build-tests)

Patch is against 4.11-rc3 (localversion-next is next-20170322)

 drivers/scsi/qla4xxx/ql4_os.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index ac52150..64c6fa5 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -8663,9 +8663,8 @@ static int qla4xxx_probe_adapter(struct pci_dev *pdev,
init_completion(>mbx_intr_comp);
init_completion(>disable_acb_comp);
init_completion(>idc_comp);
init_completion(>link_up_comp);
-   init_completion(>disable_acb_comp);
 
spin_lock_init(>hardware_lock);
spin_lock_init(>work_lock);
 
-- 
2.1.4



Re: [PATCH] scsi: lpfc: fix linking against modular NVMe support

2017-03-22 Thread Arnd Bergmann
On Wed, Mar 22, 2017 at 3:25 AM, James Smart  wrote:
>
> On 3/21/2017 7:23 PM, James Smart wrote:
>>
>> Arnd,
>>
>> All of the build issues, including building as modules, should have been
>> resolved by the following patch:
>> http://www.spinics.net/lists/linux-scsi/msg106102.html
>>
>> Am I missing something ?
>
> Note: the patch I referenced
> (http://www.spinics.net/lists/linux-scsi/msg106102.html) replaced the one I
> think you referenced below
> (http://www.spinics.net/lists/linux-scsi/msg106024.html)

The build error I fixed was on yesterday's linux-next, which has the
http://www.spinics.net/lists/linux-scsi/msg106102.html patch, this is
the one I referenced as 7d7080335f8d ("scsi: lpfc: Finalize Kconfig
options for nvme").

The earlier version from linux-next-20170310 (there was no linux-next
last week) had the same bug but needed a different workaround:

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 4bf55b5d78be..52245eb83295 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1256,12 +1256,14 @@ config SCSI_LPFC_DEBUG_FS
 config LPFC_NVME_INITIATOR
  bool "Emulex LightPulse Fibre Channel NVME Initiator Support"
  depends on SCSI_LPFC && NVME_FC
+ depends on SCSI_LPFC=m || NVME_FC=y
  ---help---
   This enables NVME Initiator support in the Emulex lpfc driver.

 config LPFC_NVME_TARGET
  bool "Emulex LightPulse Fibre Channel NVME Initiator Support"
  depends on SCSI_LPFC && NVME_TARGET_FC
+ depends on SCSI_LPFC=m || NVME_TARGET_FC=y
  ---help---
   This enables NVME Target support in the Emulex lpfc driver.
   Target enablement must still be enabled on a per adapter

As a side-note, the patch introduces a slightly unusual construct
using #if (IS_ENABLED(CONFIG_NVME_FC)). This can usually
expressed in a more readable way like this:

--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -2190,13 +2192,12 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
 void
 lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
 {
-#if (IS_ENABLED(CONFIG_NVME_FC))
struct nvme_fc_local_port *localport;
struct lpfc_nvme_lport *lport;
struct lpfc_nvme_rport *rport = NULL, *rport_next = NULL;
int ret;

-   if (vport->nvmei_support == 0)
+   if (!IS_ENABLED(CONFIG_NVME_FC) || vport->nvmei_support == 0)
return;

localport = vport->localport;
@@ -2243,7 +2244,6 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
 "Failed, status x%x\n",
 ret);
}
-#endif
 }

 void


You could also use if(IS_REACHABLE()) here to work around
the link error when CONFIG_NVME_FC=m, but that would make
things a little more confusing for users as it is not immediately
clear why it fails to work at runtime.

  Arnd