Re: [PATCH] scsi: hisi_sas: add missing break in switch statement

2017-03-28 Thread John Garry

On 28/03/2017 12:12, Colin King wrote:

From: Colin Ian King <colin.k...@canonical.com>

It appears that a break in the TRANS_TX_OPEN_CNX_ERR_NO_DESTINATION
case got accidentally removed in an earlier commit, as it stands,
the ts->stat and ts->open_rej_reason are being updated twice for this
case which looks incorrect.  Fix this by adding in the missing break
statement.

Detected by CoverityScan, CID#1422110 ("Missing break in switch")

Fixes: 634a9585f49c7 ("scsi: hisi_sas: process error codes according to their 
priority")
Signed-off-by: Colin Ian King <colin.k...@canonical.com>


Thanks, checkpatch.pl would normally catch this but it was hidden in the 
formatted patch


Signed-off-by: John Garry <john.ga...@huawei.com>



[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 <john.ga...@huawei.com>
---
 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 <chenxian...@hisilicon.com>

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 <chenxian...@hisilicon.com>
Signed-off-by: Xiaofei Tan <tanxiao...@huawei.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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;
+

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

2017-03-22 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

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 <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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 <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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 

[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 <chenxian...@hisilicon.com>

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 <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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 <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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_h

[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 <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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 <chenxian...@hisilicon.com>

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 <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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_

[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 <john.ga...@huawei.com>
---
 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 <tanxiao...@huawei.com>

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 <tanxiao...@huawei.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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 <chenxian...@hisilicon.com>

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 <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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_

[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 <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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 <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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 <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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 <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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_

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

2017-03-22 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

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 <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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 <chenxian...@hisilicon.com>

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

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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 <chenxian...@hisilicon.com>
Signed-off-by: Zhao Nenglong <zhaonengl...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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 <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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 <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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 <tanxiao...@huawei.com>

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 <tanxiao...@huawei.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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 <john.ga...@huawei.com>
Reviewed-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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 <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxi...@hisilicon.com>
---
 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



Re: [PATCH] scsi: libsas: fix ata xfer length

2017-03-20 Thread John Garry

On 19/03/2017 17:21, Martin K. Petersen wrote:

John Garry <john.ga...@huawei.com> writes:

John,


The total ata xfer length may not be calculated properly,
in that we do not use the proper method to get an sg element
dma length.

According to the code comment, sg_dma_len() should be used
after dma_map_sg() is called.

This issue was found by turning on the SMMUv3 in front of
the hisi_sas controller in hip07. Multiple sg elements
were being combined into a single element, but the original
first element length was being use as the total xfer length.




I should have added this originally to the changelog:
Fixes: ff2aeb1eb64c8a4770a6 ("libata: convert to chained sg")

BTW, I am surprised this issue has not been seen in almost 10 years, but 
we cannot attach a SATA disk when SMMU enabled without it.


Cheers,
John


Applied to 4.11/scsi-fixes.






[PATCH] scsi: libsas: fix ata xfer length

2017-03-16 Thread John Garry
The total ata xfer length may not be calculated properly,
in that we do not use the proper method to get an sg element
dma length.

According to the code comment, sg_dma_len() should be used
after dma_map_sg() is called.

This issue was found by turning on the SMMUv3 in front of
the hisi_sas controller in hip07. Multiple sg elements
were being combined into a single element, but the original
first element length was being use as the total xfer length.

Signed-off-by: John Garry <john.ga...@huawei.com>

diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 763f012..87f5e694 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -221,7 +221,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd 
*qc)
task->num_scatter = qc->n_elem;
} else {
for_each_sg(qc->sg, sg, qc->n_elem, si)
-   xfer += sg->length;
+   xfer += sg_dma_len(sg);
 
task->total_xfer_len = xfer;
task->num_scatter = si;
-- 
1.9.1



[PATCH v2 5/7] scsi: hisi_sas: downgrade internal abort exit print

2017-01-20 Thread John Garry
Downgrade the exit print in hisi_sas_internal_task_abort()
to dbg level, as info is not required.

Signed-off-by: John Garry <john.ga...@huawei.com>
Reviewed-by: Xiang Chen <chenxian...@hisilicon.com>
Reviewed-by: Johannes Thumshirn <jthumsh...@suse.de>
---
 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 eee7ae2..b2782ce 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1121,7 +1121,7 @@ static int hisi_sas_query_task(struct sas_task *task)
}
 
 exit:
-   dev_info(dev, "internal task abort: task to dev %016llx task=%p "
+   dev_dbg(dev, "internal task abort: task to dev %016llx task=%p "
"resp: 0x%x sts 0x%x\n",
SAS_ADDR(device->sas_addr),
task,
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 3/7] scsi: hisi_sas: downgrade refclk message

2017-01-20 Thread John Garry
The message to inform that the controller has no refclk
is currently at warning level, which is unnecessary, so
downgrade to debug.

Signed-off-by: John Garry <john.ga...@huawei.com>
Reviewed-by: Xiang Chen <chenxian...@hisilicon.com>
Reviewed-by: Johannes Thumshirn <jthumsh...@suse.de>
---
 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 22dba01..eee7ae2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1453,7 +1453,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
 
refclk = devm_clk_get(>dev, NULL);
if (IS_ERR(refclk))
-   dev_info(dev, "no ref clk property\n");
+   dev_dbg(dev, "no ref clk property\n");
else
hisi_hba->refclk_frequency_mhz = clk_get_rate(refclk) / 100;
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/7] scsi: hisi_sas: modify some values of ITCT table

2017-01-20 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

Set SMP connection timeout and continue AWT timer;
Clear ITCT table when dev gone.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
Reviewed-by: Johannes Thumshirn <jthumsh...@suse.de>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 14 ++
 1 file changed, 10 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 6c787eb..93fceda 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -334,6 +334,11 @@
 #define ITCT_HDR_MCR_MSK   (0xf << ITCT_HDR_MCR_OFF)
 #define ITCT_HDR_VLN_OFF   9
 #define ITCT_HDR_VLN_MSK   (0xf << ITCT_HDR_VLN_OFF)
+#define ITCT_HDR_SMP_TIMEOUT_OFF   16
+#define ITCT_HDR_SMP_TIMEOUT_8US   1
+#define ITCT_HDR_SMP_TIMEOUT   (ITCT_HDR_SMP_TIMEOUT_8US * \
+250) /* 2ms */
+#define ITCT_HDR_AWT_CONTINUE_OFF  25
 #define ITCT_HDR_PORT_ID_OFF   28
 #define ITCT_HDR_PORT_ID_MSK   (0xf << ITCT_HDR_PORT_ID_OFF)
 /* qw2 */
@@ -696,6 +701,8 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
qw0 |= ((1 << ITCT_HDR_VALID_OFF) |
(device->linkrate << ITCT_HDR_MCR_OFF) |
(1 << ITCT_HDR_VLN_OFF) |
+   (ITCT_HDR_SMP_TIMEOUT << ITCT_HDR_SMP_TIMEOUT_OFF) |
+   (1 << ITCT_HDR_AWT_CONTINUE_OFF) |
(port->id << ITCT_HDR_PORT_ID_OFF));
itct->qw0 = cpu_to_le64(qw0);
 
@@ -705,7 +712,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
 
/* qw2 */
if (!dev_is_sata(device))
-   itct->qw2 = cpu_to_le64((500ULL << ITCT_HDR_INLT_OFF) |
+   itct->qw2 = cpu_to_le64((5000ULL << ITCT_HDR_INLT_OFF) |
(0x1ULL << ITCT_HDR_BITLT_OFF) |
(0x32ULL << ITCT_HDR_MCTLT_OFF) |
(0x1ULL << ITCT_HDR_RTOLT_OFF));
@@ -714,7 +721,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
 static void free_device_v2_hw(struct hisi_hba *hisi_hba,
  struct hisi_sas_device *sas_dev)
 {
-   u64 qw0, dev_id = sas_dev->device_id;
+   u64 dev_id = sas_dev->device_id;
struct device *dev = _hba->pdev->dev;
struct hisi_sas_itct *itct = _hba->itct[dev_id];
u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
@@ -738,8 +745,7 @@ static void free_device_v2_hw(struct hisi_hba *hisi_hba,
dev_dbg(dev, "got clear ITCT done interrupt\n");
 
/* invalid the itct state*/
-   qw0 = cpu_to_le64(itct->qw0);
-   qw0 &= ~(1 << ITCT_HDR_VALID_OFF);
+   memset(itct, 0, sizeof(struct hisi_sas_itct));
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
 ENT_INT_SRC3_ITC_INT_MSK);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 0/7] hisi_sas: SATA IO workaround and other misc patches

2017-01-20 Thread John Garry
This patchset introduces some misc fixes and improvements.

Most signifigantly this patchset includes a workaround
for a SATA IO issue on v2 hw (hip06/7).

Differences v1->v2:
- Add macro for SMP TIMEOUT in ITCT struct

John Garry (2):
  scsi: hisi_sas: downgrade refclk message
  scsi: hisi_sas: downgrade internal abort exit print

Xiang Chen (5):
  scsi: hisi_sas: workaround v2 hw SATA IO timeout issue
  scsi: hisi_sas: modify some values of ITCT table
  scsi: hisi_sas: modify hard reset for directed-attached disk
  scsi: hisi_sas: fix probe ordering problem
  scsi: hisi_sas: decrease running_req in hisi_sas_slot_task_free()

 drivers/scsi/hisi_sas/hisi_sas_main.c  |  20 +++---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 109 +
 2 files changed, 106 insertions(+), 23 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/7] scsi: hisi_sas: workaround v2 hw SATA IO timeout issue

2017-01-20 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

The v2 SAS controller needs more time to detect channel idle
and send setup link request than SATA disk does, so it is
difficult for the SAS controller to setup an STP link. Therefore
it may cause some IO timeouts.

We need to periodically configure the SAS controller so it
doesn't receive STP setup requests from SATA disks for a while,
so IO can be sent during this period.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
Reviewed-by: Johannes Thumshirn <jthumsh...@suse.de>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 75 +-
 1 file changed, 74 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 69b0f06..6c787eb 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -215,6 +215,7 @@
 #define RX_IDAF_DWORD5 (PORT_BASE + 0xd8)
 #define RX_IDAF_DWORD6 (PORT_BASE + 0xdc)
 #define RXOP_CHECK_CFG_H   (PORT_BASE + 0xfc)
+#define CON_CONTROL(PORT_BASE + 0x118)
 #define DONE_RECEIVED_TIME (PORT_BASE + 0x11c)
 #define CHL_INT0   (PORT_BASE + 0x1b4)
 #define CHL_INT0_HOTPLUG_TOUT_OFF  0
@@ -526,6 +527,8 @@ enum {
 #define SATA_PROTOCOL_FPDMA0x8
 #define SATA_PROTOCOL_ATAPI0x10
 
+static void hisi_sas_link_timeout_disable_link(unsigned long data);
+
 static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
 {
void __iomem *regs = hisi_hba->regs + off;
@@ -978,6 +981,50 @@ 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)
+{
+   struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
+   int i, reg_val;
+
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   reg_val = hisi_sas_phy_read32(hisi_hba, i, CON_CONTROL);
+   if (!(reg_val & BIT(0))) {
+   hisi_sas_phy_write32(hisi_hba, i,
+   CON_CONTROL, 0x7);
+   break;
+   }
+   }
+
+   hisi_hba->timer.function = hisi_sas_link_timeout_disable_link;
+   mod_timer(_hba->timer, jiffies + msecs_to_jiffies(900));
+}
+
+static void hisi_sas_link_timeout_disable_link(unsigned long data)
+{
+   struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
+   int i, reg_val;
+
+   reg_val = hisi_sas_read32(hisi_hba, PHY_STATE);
+   for (i = 0; i < hisi_hba->n_phy && reg_val; i++) {
+   if (reg_val & BIT(i)) {
+   hisi_sas_phy_write32(hisi_hba, i,
+   CON_CONTROL, 0x6);
+   break;
+   }
+   }
+
+   hisi_hba->timer.function = hisi_sas_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.expires = jiffies + msecs_to_jiffies(1000);
+   add_timer(_hba->timer);
+}
+
 static int hw_init_v2_hw(struct hisi_hba *hisi_hba)
 {
struct device *dev = _hba->pdev->dev;
@@ -2020,9 +2067,12 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba 
*hisi_hba)
if (phy->identify.device_type == SAS_END_DEVICE)
phy->identify.target_port_protocols =
SAS_PROTOCOL_SSP;
-   else if (phy->identify.device_type != SAS_PHY_UNUSED)
+   else if (phy->identify.device_type != SAS_PHY_UNUSED) {
phy->identify.target_port_protocols =
SAS_PROTOCOL_SMP;
+   if (!timer_pending(_hba->timer))
+   set_link_timer_quirk(hisi_hba);
+   }
queue_work(hisi_hba->wq, >phyup_ws);
 
 end:
@@ -2033,10 +2083,23 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba 
*hisi_hba)
return res;
 }
 
+static bool check_any_wideports_v2_hw(struct hisi_hba *hisi_hba)
+{
+   u32 port_state;
+
+   port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
+   if (port_state & 0x1ff)
+   return true;
+
+   return false;
+}
+
 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;
 
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);
 
@@ -2046,6 +2109,10 @@ static int phy_down_v2_hw(int phy_no, struct hisi_hba 
*hisi_hba)

[PATCH v2 6/7] scsi: hisi_sas: fix probe ordering problem

2017-01-20 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

There is a potential probe issue in how we trigger the hw initialisation.
Although we use 1s timer to delay hw initialisation, there is still a
potential that sas_register_ha() is not be finished before we start
the PHY init from hw->hw_init().
To avoid this issue, initialise the hw after sas_register_ha() in the
same probe context.
Note: it is not necessary to use 1s timer now (modified v2 hw only).

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
Reviewed-by: Johannes Thumshirn <jthumsh...@suse.de>
---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 8 
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 8 ++--
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index b2782ce..8601cec 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1552,10 +1552,6 @@ int hisi_sas_probe(struct platform_device *pdev,
 
hisi_sas_init_add(hisi_hba);
 
-   rc = hisi_hba->hw->hw_init(hisi_hba);
-   if (rc)
-   goto err_out_ha;
-
rc = scsi_add_host(shost, >dev);
if (rc)
goto err_out_ha;
@@ -1564,6 +1560,10 @@ int hisi_sas_probe(struct platform_device *pdev,
if (rc)
goto err_out_register_ha;
 
+   rc = hisi_hba->hw->hw_init(hisi_hba);
+   if (rc)
+   goto err_out_register_ha;
+
scsi_scan_host(shost);
 
return 0;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 2e776b7..9e16f42 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1093,9 +1093,8 @@ static void phy_hard_reset_v2_hw(struct hisi_hba 
*hisi_hba, int phy_no)
start_phy_v2_hw(hisi_hba, phy_no);
 }
 
-static void start_phys_v2_hw(unsigned long data)
+static void start_phys_v2_hw(struct hisi_hba *hisi_hba)
 {
-   struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
int i;
 
for (i = 0; i < hisi_hba->n_phy; i++)
@@ -1104,10 +1103,7 @@ static void start_phys_v2_hw(unsigned long data)
 
 static void phys_init_v2_hw(struct hisi_hba *hisi_hba)
 {
-   struct timer_list *timer = _hba->timer;
-
-   setup_timer(timer, start_phys_v2_hw, (unsigned long)hisi_hba);
-   mod_timer(timer, jiffies + HZ);
+   start_phys_v2_hw(hisi_hba);
 }
 
 static void sl_notify_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 4/7] scsi: hisi_sas: modify hard reset for directed-attached disk

2017-01-20 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

Correctly set registers in v2 for root PHY hardreset for directly
attached disk.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
Reviewed-by: Johannes Thumshirn <jthumsh...@suse.de>
---
 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 93fceda..2e776b7 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -207,6 +207,8 @@
 #define TXID_AUTO  (PORT_BASE + 0xb8)
 #define TXID_AUTO_CT3_OFF  1
 #define TXID_AUTO_CT3_MSK  (0x1 << TXID_AUTO_CT3_OFF)
+#define TX_HARDRST_OFF  2
+#define TX_HARDRST_MSK  (0x1 << TX_HARDRST_OFF)
 #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4)
 #define RX_IDAF_DWORD1 (PORT_BASE + 0xc8)
 #define RX_IDAF_DWORD2 (PORT_BASE + 0xcc)
@@ -1078,7 +1080,15 @@ static void stop_phy_v2_hw(struct hisi_hba *hisi_hba, 
int phy_no)
 
 static void phy_hard_reset_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
 {
+   struct hisi_sas_phy *phy = _hba->phy[phy_no];
+   u32 txid_auto;
+
stop_phy_v2_hw(hisi_hba, phy_no);
+   if (phy->identify.device_type == SAS_END_DEVICE) {
+   txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO);
+   hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
+   txid_auto | TX_HARDRST_MSK);
+   }
msleep(100);
start_phy_v2_hw(hisi_hba, phy_no);
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 7/7] scsi: hisi_sas: decrease running_req in hisi_sas_slot_task_free()

2017-01-20 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

There is an issue that hisi_sas_dev.running_req is not
decremented properly for internal abort and TMF.

To resolve, only decrease running_req in hisi_sas_slot_task_free()

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
Reviewed-by: Johannes Thumshirn <jthumsh...@suse.de>
---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 8 
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 --
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 8601cec..53637a9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -71,6 +71,8 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, 
struct sas_task *task,
 struct hisi_sas_slot *slot)
 {
struct device *dev = _hba->pdev->dev;
+   struct domain_device *device = task->dev;
+   struct hisi_sas_device *sas_dev = device->lldd_dev;
 
if (!slot->task)
return;
@@ -97,6 +99,8 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, 
struct sas_task *task,
slot->task = NULL;
slot->port = NULL;
hisi_sas_slot_index_free(hisi_hba, slot->idx);
+   if (sas_dev)
+   atomic64_dec(_dev->running_req);
/* slot memory is fully zeroed when it is reused */
 }
 EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);
@@ -141,8 +145,6 @@ static void hisi_sas_slot_abort(struct work_struct *work)
struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
struct scsi_cmnd *cmnd = task->uldd_task;
struct hisi_sas_tmf_task tmf_task;
-   struct domain_device *device = task->dev;
-   struct hisi_sas_device *sas_dev = device->lldd_dev;
struct scsi_lun lun;
struct device *dev = _hba->pdev->dev;
int tag = abort_slot->idx;
@@ -165,8 +167,6 @@ static void hisi_sas_slot_abort(struct work_struct *work)
spin_unlock_irqrestore(_hba->lock, flags);
if (task->task_done)
task->task_done(task);
-   if (sas_dev)
-   atomic64_dec(_dev->running_req);
 }
 
 static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 9e16f42..1b21445 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1830,8 +1830,6 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
}
 
 out:
-   if (sas_dev)
-   atomic64_dec(_dev->running_req);
 
hisi_sas_slot_task_free(hisi_hba, task, slot);
sts = ts->stat;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/7] scsi: hisi_sas: modify some values of ITCT table

2017-01-19 Thread John Garry

On 19/01/2017 08:44, Johannes Thumshirn wrote:

On Thu, Jan 19, 2017 at 12:32:48AM +0800, John Garry wrote:

From: Xiang Chen <chenxian...@hisilicon.com>

Set SMP connection timeout and continue AWT timer;
Clear ITCT table when dev gone.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 11 +++
 1 file changed, 7 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 6c787eb..452e329 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -334,6 +334,8 @@
 #define ITCT_HDR_MCR_MSK   (0xf << ITCT_HDR_MCR_OFF)
 #define ITCT_HDR_VLN_OFF   9
 #define ITCT_HDR_VLN_MSK   (0xf << ITCT_HDR_VLN_OFF)
+#define ITCT_HDR_SMP_TIMEOUT_OFF   16
+#define ITCT_HDR_AWT_CONTINUE_OFF  25
 #define ITCT_HDR_PORT_ID_OFF   28
 #define ITCT_HDR_PORT_ID_MSK   (0xf << ITCT_HDR_PORT_ID_OFF)
 /* qw2 */
@@ -696,6 +698,8 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
qw0 |= ((1 << ITCT_HDR_VALID_OFF) |
(device->linkrate << ITCT_HDR_MCR_OFF) |
(1 << ITCT_HDR_VLN_OFF) |
+   (0xfa << ITCT_HDR_SMP_TIMEOUT_OFF) |

 ^~ You may want to give that magic value a name.



Thanks for having a look.

We will create a new patch without the mysterious value.

Regards,
John


Other than that,
Reviewed-by: Johannes Thumshirn <jthumsh...@suse.de>




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/7] scsi: hisi_sas: fix probe ordering problem

2017-01-18 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

There is a potential probe issue in how we trigger the hw initialisation.
Although we use 1s timer to delay hw initialisation, there is still a
potential that sas_register_ha() is not be finished before we start
the PHY init from hw->hw_init().
To avoid this issue, initialise the hw after sas_register_ha() in the
same probe context.
Note: it is not necessary to use 1s timer now (modified v2 hw only).

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 8 
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 8 ++--
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index b2782ce..8601cec 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1552,10 +1552,6 @@ int hisi_sas_probe(struct platform_device *pdev,
 
hisi_sas_init_add(hisi_hba);
 
-   rc = hisi_hba->hw->hw_init(hisi_hba);
-   if (rc)
-   goto err_out_ha;
-
rc = scsi_add_host(shost, >dev);
if (rc)
goto err_out_ha;
@@ -1564,6 +1560,10 @@ int hisi_sas_probe(struct platform_device *pdev,
if (rc)
goto err_out_register_ha;
 
+   rc = hisi_hba->hw->hw_init(hisi_hba);
+   if (rc)
+   goto err_out_register_ha;
+
scsi_scan_host(shost);
 
return 0;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 7519772..62655c7 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1090,9 +1090,8 @@ static void phy_hard_reset_v2_hw(struct hisi_hba 
*hisi_hba, int phy_no)
start_phy_v2_hw(hisi_hba, phy_no);
 }
 
-static void start_phys_v2_hw(unsigned long data)
+static void start_phys_v2_hw(struct hisi_hba *hisi_hba)
 {
-   struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
int i;
 
for (i = 0; i < hisi_hba->n_phy; i++)
@@ -1101,10 +1100,7 @@ static void start_phys_v2_hw(unsigned long data)
 
 static void phys_init_v2_hw(struct hisi_hba *hisi_hba)
 {
-   struct timer_list *timer = _hba->timer;
-
-   setup_timer(timer, start_phys_v2_hw, (unsigned long)hisi_hba);
-   mod_timer(timer, jiffies + HZ);
+   start_phys_v2_hw(hisi_hba);
 }
 
 static void sl_notify_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 7/7] scsi: hisi_sas: decrease running_req in hisi_sas_slot_task_free()

2017-01-18 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

There is an issue that hisi_sas_dev.running_req is not
decremented properly for internal abort and TMF.

To resolve, only decrease running_req in hisi_sas_slot_task_free()

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 8 
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 --
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 8601cec..53637a9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -71,6 +71,8 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, 
struct sas_task *task,
 struct hisi_sas_slot *slot)
 {
struct device *dev = _hba->pdev->dev;
+   struct domain_device *device = task->dev;
+   struct hisi_sas_device *sas_dev = device->lldd_dev;
 
if (!slot->task)
return;
@@ -97,6 +99,8 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, 
struct sas_task *task,
slot->task = NULL;
slot->port = NULL;
hisi_sas_slot_index_free(hisi_hba, slot->idx);
+   if (sas_dev)
+   atomic64_dec(_dev->running_req);
/* slot memory is fully zeroed when it is reused */
 }
 EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);
@@ -141,8 +145,6 @@ static void hisi_sas_slot_abort(struct work_struct *work)
struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
struct scsi_cmnd *cmnd = task->uldd_task;
struct hisi_sas_tmf_task tmf_task;
-   struct domain_device *device = task->dev;
-   struct hisi_sas_device *sas_dev = device->lldd_dev;
struct scsi_lun lun;
struct device *dev = _hba->pdev->dev;
int tag = abort_slot->idx;
@@ -165,8 +167,6 @@ static void hisi_sas_slot_abort(struct work_struct *work)
spin_unlock_irqrestore(_hba->lock, flags);
if (task->task_done)
task->task_done(task);
-   if (sas_dev)
-   atomic64_dec(_dev->running_req);
 }
 
 static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 62655c7..de240d2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1827,8 +1827,6 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
}
 
 out:
-   if (sas_dev)
-   atomic64_dec(_dev->running_req);
 
hisi_sas_slot_task_free(hisi_hba, task, slot);
sts = ts->stat;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/7] hisi_sas: SATA IO workaround and other misc patches

2017-01-18 Thread John Garry
This patchset introduces some misc fixes and improvements.

Most signifigantly this patchset includes a workaround
for a SATA IO issue on v2 hw (hip06/7).

John Garry (2):
  scsi: hisi_sas: downgrade refclk message
  scsi: hisi_sas: downgrade internal abort exit print

Xiang Chen (5):
  scsi: hisi_sas: workaround v2 hw SATA IO timeout issue
  scsi: hisi_sas: modify some values of ITCT table
  scsi: hisi_sas: modify hard reset for directed-attached disk
  scsi: hisi_sas: fix probe ordering problem
  scsi: hisi_sas: decrease running_req in hisi_sas_slot_task_free()

 drivers/scsi/hisi_sas/hisi_sas_main.c  |  20 +++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 106 +
 2 files changed, 103 insertions(+), 23 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/7] scsi: hisi_sas: downgrade internal abort exit print

2017-01-18 Thread John Garry
Downgrade the exit print in hisi_sas_internal_task_abort()
to dbg level, as info is not required.

Signed-off-by: John Garry <john.ga...@huawei.com>
Reviewed-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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 eee7ae2..b2782ce 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1121,7 +1121,7 @@ static int hisi_sas_query_task(struct sas_task *task)
}
 
 exit:
-   dev_info(dev, "internal task abort: task to dev %016llx task=%p "
+   dev_dbg(dev, "internal task abort: task to dev %016llx task=%p "
"resp: 0x%x sts 0x%x\n",
SAS_ADDR(device->sas_addr),
task,
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/7] scsi: hisi_sas: modify some values of ITCT table

2017-01-18 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

Set SMP connection timeout and continue AWT timer;
Clear ITCT table when dev gone.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 11 +++
 1 file changed, 7 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 6c787eb..452e329 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -334,6 +334,8 @@
 #define ITCT_HDR_MCR_MSK   (0xf << ITCT_HDR_MCR_OFF)
 #define ITCT_HDR_VLN_OFF   9
 #define ITCT_HDR_VLN_MSK   (0xf << ITCT_HDR_VLN_OFF)
+#define ITCT_HDR_SMP_TIMEOUT_OFF   16
+#define ITCT_HDR_AWT_CONTINUE_OFF  25
 #define ITCT_HDR_PORT_ID_OFF   28
 #define ITCT_HDR_PORT_ID_MSK   (0xf << ITCT_HDR_PORT_ID_OFF)
 /* qw2 */
@@ -696,6 +698,8 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
qw0 |= ((1 << ITCT_HDR_VALID_OFF) |
(device->linkrate << ITCT_HDR_MCR_OFF) |
(1 << ITCT_HDR_VLN_OFF) |
+   (0xfa << ITCT_HDR_SMP_TIMEOUT_OFF) |
+   (1 << ITCT_HDR_AWT_CONTINUE_OFF) |
(port->id << ITCT_HDR_PORT_ID_OFF));
itct->qw0 = cpu_to_le64(qw0);
 
@@ -705,7 +709,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
 
/* qw2 */
if (!dev_is_sata(device))
-   itct->qw2 = cpu_to_le64((500ULL << ITCT_HDR_INLT_OFF) |
+   itct->qw2 = cpu_to_le64((5000ULL << ITCT_HDR_INLT_OFF) |
(0x1ULL << ITCT_HDR_BITLT_OFF) |
(0x32ULL << ITCT_HDR_MCTLT_OFF) |
(0x1ULL << ITCT_HDR_RTOLT_OFF));
@@ -714,7 +718,7 @@ static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
 static void free_device_v2_hw(struct hisi_hba *hisi_hba,
  struct hisi_sas_device *sas_dev)
 {
-   u64 qw0, dev_id = sas_dev->device_id;
+   u64 dev_id = sas_dev->device_id;
struct device *dev = _hba->pdev->dev;
struct hisi_sas_itct *itct = _hba->itct[dev_id];
u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
@@ -738,8 +742,7 @@ static void free_device_v2_hw(struct hisi_hba *hisi_hba,
dev_dbg(dev, "got clear ITCT done interrupt\n");
 
/* invalid the itct state*/
-   qw0 = cpu_to_le64(itct->qw0);
-   qw0 &= ~(1 << ITCT_HDR_VALID_OFF);
+   memset(itct, 0, sizeof(struct hisi_sas_itct));
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
 ENT_INT_SRC3_ITC_INT_MSK);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/7] scsi: hisi_sas: workaround v2 hw SATA IO timeout issue

2017-01-18 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

The v2 SAS controller needs more time to detect channel idle
and send setup link request than SATA disk does, so it is
difficult for SAS controller to setup an STP link. Therefore it
may cause some IO timeouts.

We need to periodically configure the SAS controller so it
doesn't receive STP setup requests from SATA disks for a while,
so IO can be sent during this period.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 75 +-
 1 file changed, 74 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 69b0f06..6c787eb 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -215,6 +215,7 @@
 #define RX_IDAF_DWORD5 (PORT_BASE + 0xd8)
 #define RX_IDAF_DWORD6 (PORT_BASE + 0xdc)
 #define RXOP_CHECK_CFG_H   (PORT_BASE + 0xfc)
+#define CON_CONTROL(PORT_BASE + 0x118)
 #define DONE_RECEIVED_TIME (PORT_BASE + 0x11c)
 #define CHL_INT0   (PORT_BASE + 0x1b4)
 #define CHL_INT0_HOTPLUG_TOUT_OFF  0
@@ -526,6 +527,8 @@ enum {
 #define SATA_PROTOCOL_FPDMA0x8
 #define SATA_PROTOCOL_ATAPI0x10
 
+static void hisi_sas_link_timeout_disable_link(unsigned long data);
+
 static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
 {
void __iomem *regs = hisi_hba->regs + off;
@@ -978,6 +981,50 @@ 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)
+{
+   struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
+   int i, reg_val;
+
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   reg_val = hisi_sas_phy_read32(hisi_hba, i, CON_CONTROL);
+   if (!(reg_val & BIT(0))) {
+   hisi_sas_phy_write32(hisi_hba, i,
+   CON_CONTROL, 0x7);
+   break;
+   }
+   }
+
+   hisi_hba->timer.function = hisi_sas_link_timeout_disable_link;
+   mod_timer(_hba->timer, jiffies + msecs_to_jiffies(900));
+}
+
+static void hisi_sas_link_timeout_disable_link(unsigned long data)
+{
+   struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
+   int i, reg_val;
+
+   reg_val = hisi_sas_read32(hisi_hba, PHY_STATE);
+   for (i = 0; i < hisi_hba->n_phy && reg_val; i++) {
+   if (reg_val & BIT(i)) {
+   hisi_sas_phy_write32(hisi_hba, i,
+   CON_CONTROL, 0x6);
+   break;
+   }
+   }
+
+   hisi_hba->timer.function = hisi_sas_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.expires = jiffies + msecs_to_jiffies(1000);
+   add_timer(_hba->timer);
+}
+
 static int hw_init_v2_hw(struct hisi_hba *hisi_hba)
 {
struct device *dev = _hba->pdev->dev;
@@ -2020,9 +2067,12 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba 
*hisi_hba)
if (phy->identify.device_type == SAS_END_DEVICE)
phy->identify.target_port_protocols =
SAS_PROTOCOL_SSP;
-   else if (phy->identify.device_type != SAS_PHY_UNUSED)
+   else if (phy->identify.device_type != SAS_PHY_UNUSED) {
phy->identify.target_port_protocols =
SAS_PROTOCOL_SMP;
+   if (!timer_pending(_hba->timer))
+   set_link_timer_quirk(hisi_hba);
+   }
queue_work(hisi_hba->wq, >phyup_ws);
 
 end:
@@ -2033,10 +2083,23 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba 
*hisi_hba)
return res;
 }
 
+static bool check_any_wideports_v2_hw(struct hisi_hba *hisi_hba)
+{
+   u32 port_state;
+
+   port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
+   if (port_state & 0x1ff)
+   return true;
+
+   return false;
+}
+
 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;
 
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);
 
@@ -2046,6 +2109,10 @@ static int phy_down_v2_hw(int phy_no, struct hisi_hba 
*hisi_hba)
sl_ctrl = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
 

[PATCH 4/7] scsi: hisi_sas: modify hard reset for directed-attached disk

2017-01-18 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

Correctly set registers in v2 for root PHY hardreset for directly
attached disk.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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 452e329..7519772 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -207,6 +207,8 @@
 #define TXID_AUTO  (PORT_BASE + 0xb8)
 #define TXID_AUTO_CT3_OFF  1
 #define TXID_AUTO_CT3_MSK  (0x1 << TXID_AUTO_CT3_OFF)
+#define TX_HARDRST_OFF  2
+#define TX_HARDRST_MSK  (0x1 << TX_HARDRST_OFF)
 #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4)
 #define RX_IDAF_DWORD1 (PORT_BASE + 0xc8)
 #define RX_IDAF_DWORD2 (PORT_BASE + 0xcc)
@@ -1075,7 +1077,15 @@ static void stop_phy_v2_hw(struct hisi_hba *hisi_hba, 
int phy_no)
 
 static void phy_hard_reset_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
 {
+   struct hisi_sas_phy *phy = _hba->phy[phy_no];
+   u32 txid_auto;
+
stop_phy_v2_hw(hisi_hba, phy_no);
+   if (phy->identify.device_type == SAS_END_DEVICE) {
+   txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO);
+   hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
+   txid_auto | TX_HARDRST_MSK);
+   }
msleep(100);
start_phy_v2_hw(hisi_hba, phy_no);
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/7] scsi: hisi_sas: downgrade refclk message

2017-01-18 Thread John Garry
The message to inform that the controller has no refclk
is currently at warning level, which is unnecessary, so
downgrade to debug.

Signed-off-by: John Garry <john.ga...@huawei.com>
Reviewed-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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 22dba01..eee7ae2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1453,7 +1453,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
 
refclk = devm_clk_get(>dev, NULL);
if (IS_ERR(refclk))
-   dev_info(dev, "no ref clk property\n");
+   dev_dbg(dev, "no ref clk property\n");
else
hisi_hba->refclk_frequency_mhz = clk_get_rate(refclk) / 100;
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] libsas: fix \"sysfs group not found\" warnings at port teardown time

2017-01-11 Thread John Garry

On 11/01/2017 06:29, seeteena wrote:

Hi All,

Let me know if this patch is accepted in Upsteam? let me know the commit id



If it is the patch I think it is then it is not upstream 
(https://patchwork.kernel.org/patch/6450731/).


I did propose a patch at the end of last year which fixed the warn, but 
it introduced some other potential hotplug issue.


An engineer in my organisation proposed a re-work of libsas to fix all 
the hotplug issues, but it was not pushed and never got far:

https://lkml.org/lkml/2016/9/12/1225

John


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html





--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] scsi: remove useless acpi functions in the head file

2017-01-10 Thread John Garry

On 10/01/2017 08:14, Hanjun Guo wrote:

From: Hanjun Guo <hanjun@linaro.org>

commit f1bc1e4c44b1 ("ata: acpi: rework the ata acpi bind support")
removed scsi_register_acpi_bus_type() and scsi_unregister_acpi_bus_type(),
but forgot to remove them in the head file, do it now.

Signed-off-by: Hanjun Guo <hanjun@linaro.org>
---
 include/scsi/scsi.h | 10 --
 1 file changed, 10 deletions(-)

diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 8ec7c30..a1e1930 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -29,16 +29,6 @@ enum scsi_timeouts {
  */
 #define SCAN_WILD_CARD ~0

-#ifdef CONFIG_ACPI
-struct acpi_bus_type;
-
-extern int
-scsi_register_acpi_bus_type(struct acpi_bus_type *bus);
-
-extern void
-scsi_unregister_acpi_bus_type(struct acpi_bus_type *bus);
-#endif
-
 /** scsi_status_is_good - check the status return.
  *
  * @status: the status passed up from the driver (including host and



Looks ok,

Reviewed-by: John Garry <john.ga...@huawei.com>

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/3] scsi: hisi_sas: lock sensitive region in hisi_sas_slot_abort()

2017-01-03 Thread John Garry
When we call hisi_sas_slot_task_free() we should grab the
hisi_hba.lock, as hisi_sas_slot_task_free() accesses common
hisi_hba elements.
Function hisi_sas_slot_abort() is missing this, so add it.

Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index d50e9cf..22dba01 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -146,6 +146,7 @@ static void hisi_sas_slot_abort(struct work_struct *work)
struct scsi_lun lun;
struct device *dev = _hba->pdev->dev;
int tag = abort_slot->idx;
+   unsigned long flags;
 
if (!(task->task_proto & SAS_PROTOCOL_SSP)) {
dev_err(dev, "cannot abort slot for non-ssp task\n");
@@ -159,7 +160,9 @@ static void hisi_sas_slot_abort(struct work_struct *work)
hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, _task);
 out:
/* Do cleanup for this task */
+   spin_lock_irqsave(_hba->lock, flags);
hisi_sas_slot_task_free(hisi_hba, task, abort_slot);
+   spin_unlock_irqrestore(_hba->lock, flags);
if (task->task_done)
task->task_done(task);
if (sas_dev)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/3] scsi: hisi_sas: service v2 hw CQ ISR with tasklet

2017-01-03 Thread John Garry
Currently the all the slot processing for the completion
queue is done in ISR context. It is judged that the slot
processing can take a long time, especially when a SATA
NCQ completes (upto 32 slots).

So, as a solution, defer the bulk of the ISR processing
to tasklet context. Each CQ will have its down tasklet.

Signed-off-by: John Garry <john.ga...@huawei.com>
Reviewed-by: Xiang Chen <chenxian...@hisilicon.com>
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  1 +
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 24 ++--
 2 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index c0cd505..9216dea 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -95,6 +95,7 @@ struct hisi_sas_port {
 
 struct hisi_sas_cq {
struct hisi_hba *hisi_hba;
+   struct tasklet_struct tasklet;
int rd_point;
int id;
 };
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index b934aec..e506260 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2481,20 +2481,17 @@ static irqreturn_t fatal_axi_int_v2_hw(int irq_no, void 
*p)
return IRQ_HANDLED;
 }
 
-static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
+static void cq_tasklet_v2_hw(unsigned long val)
 {
-   struct hisi_sas_cq *cq = p;
+   struct hisi_sas_cq *cq = (struct hisi_sas_cq *)val;
struct hisi_hba *hisi_hba = cq->hisi_hba;
struct hisi_sas_slot *slot;
struct hisi_sas_itct *itct;
struct hisi_sas_complete_v2_hdr *complete_queue;
-   u32 irq_value, rd_point = cq->rd_point, wr_point, dev_id;
+   u32 rd_point = cq->rd_point, wr_point, dev_id;
int queue = cq->id;
 
complete_queue = hisi_hba->complete_hdr[queue];
-   irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC);
-
-   hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
 
wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
   (0x14 * queue));
@@ -2545,6 +2542,18 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void 
*p)
/* update rd_point */
cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
+}
+
+static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
+{
+   struct hisi_sas_cq *cq = p;
+   struct hisi_hba *hisi_hba = cq->hisi_hba;
+   int queue = cq->id;
+
+   hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
+
+   tasklet_schedule(>tasklet);
+
return IRQ_HANDLED;
 }
 
@@ -2726,6 +2735,8 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
 
for (i = 0; i < hisi_hba->queue_count; i++) {
int idx = i + 96; /* First cq interrupt is irq96 */
+   struct hisi_sas_cq *cq = _hba->cq[i];
+   struct tasklet_struct *t = >tasklet;
 
irq = irq_map[idx];
if (!irq) {
@@ -2742,6 +2753,7 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
irq, rc);
return -ENOENT;
}
+   tasklet_init(t, cq_tasklet_v2_hw, (unsigned long)cq);
}
 
return 0;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/3] hisi_sas: some CQ processing fixes

2017-01-03 Thread John Garry
This patchset fixes some issues related to servicing of the
completion queue interrupt.
The major fix is that sensitive hisi_hba structures need to be
locked when free'ing a slot.
Another modification is that the v2 hw completion queue irq is
now serviced with a tasklet, as too much work was being done in
the ISR.

John Garry (3):
  scsi: hisi_sas: service v2 hw CQ ISR with tasklet
  scsi: hisi_sas: lock sensitive regions when servicing CQ interrupt
  scsi: hisi_sas: lock sensitive region in hisi_sas_slot_abort()

 drivers/scsi/hisi_sas/hisi_sas.h   |  1 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  |  3 +++
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  2 ++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 26 --
 4 files changed, 26 insertions(+), 6 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/3] scsi: hisi_sas: lock sensitive regions when servicing CQ interrupt

2017-01-03 Thread John Garry
There is a bug in the current driver in that certain hisi_hba
and port structure elements which we access when servicing
the CQ interrupt do not use thread-safe accesses; these include
hisi_sas_port linked-list of active slots (hisi_sas_port.entry),
bitmap of currently allocated IPTT (in hisi_hba.slot_index_tags),
and completion queue read pointer.

As a solution, lock these elements with the hisi_hba.lock.

Signed-off-by: John Garry <john.ga...@huawei.com>
Reviewed-by: Xiang Chen <chenxian...@hisilicon.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 2 ++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 8a1be0b..854fbea 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1596,6 +1596,7 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p)
hisi_hba->complete_hdr[queue];
u32 irq_value, rd_point = cq->rd_point, wr_point;
 
+   spin_lock(_hba->lock);
irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC);
 
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
@@ -1628,6 +1629,7 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p)
/* update rd_point */
cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
+   spin_unlock(_hba->lock);
 
return IRQ_HANDLED;
 }
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index e506260..69b0f06 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2493,6 +2493,7 @@ static void cq_tasklet_v2_hw(unsigned long val)
 
complete_queue = hisi_hba->complete_hdr[queue];
 
+   spin_lock(_hba->lock);
wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
   (0x14 * queue));
 
@@ -2542,6 +2543,7 @@ static void cq_tasklet_v2_hw(unsigned long val)
/* update rd_point */
cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
+   spin_unlock(_hba->lock);
 }
 
 static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] scsi: hisi_sas: support deferred probe for v2 hw

2016-12-06 Thread John Garry
In the hip06 and hip07 SoCs, the interrupt lines from the
SAS controllers are connected to mbigen hw module [1].
The mbigen module is probed with module_init, and, as such,
is not guaranteed to probe before the SAS driver. So we need
to support deferred probe.

We check for probe deferral in the hw layer probe, so we not
probe into the main layer and allocate shost, memories, etc.,
to later learn that we need to defer the probe.

[1] 
./Documentation/devicetree/bindings/interrupt-controller/hisilicon,mbigen-v2.txt

Signed-off-by: John Garry <john.ga...@huawei.com>

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index c0e7bf2..a179592 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2971,6 +2971,18 @@ static int hisi_sas_v2_init(struct hisi_hba *hisi_hba)
 
 static int hisi_sas_v2_probe(struct platform_device *pdev)
 {
+   /*
+* Check if we should defer the probe before we probe the
+* upper layer, as it's hard to defer later on.
+*/
+   int ret = platform_get_irq(pdev, 0);
+
+   if (ret < 0) {
+   if (ret != -EPROBE_DEFER)
+   dev_err(>dev, "cannot obtain irq\n");
+   return ret;
+   }
+
return hisi_sas_probe(pdev, _sas_v2_hw);
 }
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] scsi: hisi_sas: fix free'ing in probe and remove

2016-11-29 Thread John Garry
From: Xiaofei Tan <tanxiao...@huawei.com>

This patch addresses 4 problems in the module probe/remove:
- When hisi_sas_shost_alloc() fails after we alloc shost memory,
we should free shost memory before the function returns.
- When hisi_sas_probe() fails after we alloc the HBA memories,
we should also free the HBA memories.
- We should free shost memory at the end of hisi_sas_remove().
- sha->core.shost is set twice, so remove extra set.

Signed-off-by: Xiaofei Tan <tanxiao...@huawei.com>
Signed-off-by: John Garry <john.ga...@huawei.com>

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 6d6f150..d50e9cf 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1412,8 +1412,10 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
struct clk *refclk;
 
shost = scsi_host_alloc(_sas_sht, sizeof(*hisi_hba));
-   if (!shost)
-   goto err_out;
+   if (!shost) {
+   dev_err(dev, "scsi host alloc failed\n");
+   return NULL;
+   }
hisi_hba = shost_priv(shost);
 
hisi_hba->hw = hw;
@@ -1477,6 +1479,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
 
return shost;
 err_out:
+   kfree(shost);
dev_err(dev, "shost alloc failed\n");
return NULL;
 }
@@ -1503,10 +1506,8 @@ int hisi_sas_probe(struct platform_device *pdev,
int rc, phy_nr, port_nr, i;
 
shost = hisi_sas_shost_alloc(pdev, hw);
-   if (!shost) {
-   rc = -ENOMEM;
-   goto err_out_ha;
-   }
+   if (!shost)
+   return -ENOMEM;
 
sha = SHOST_TO_SAS_HA(shost);
hisi_hba = shost_priv(shost);
@@ -1516,12 +1517,13 @@ int hisi_sas_probe(struct platform_device *pdev,
 
arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL);
arr_port = devm_kcalloc(dev, port_nr, sizeof(void *), GFP_KERNEL);
-   if (!arr_phy || !arr_port)
-   return -ENOMEM;
+   if (!arr_phy || !arr_port) {
+   rc = -ENOMEM;
+   goto err_out_ha;
+   }
 
sha->sas_phy = arr_phy;
sha->sas_port = arr_port;
-   sha->core.shost = shost;
sha->lldd_ha = hisi_hba;
 
shost->transportt = hisi_sas_stt;
@@ -1566,6 +1568,7 @@ int hisi_sas_probe(struct platform_device *pdev,
 err_out_register_ha:
scsi_remove_host(shost);
 err_out_ha:
+   hisi_sas_free(hisi_hba);
kfree(shost);
return rc;
 }
@@ -1575,12 +1578,14 @@ int hisi_sas_remove(struct platform_device *pdev)
 {
struct sas_ha_struct *sha = platform_get_drvdata(pdev);
struct hisi_hba *hisi_hba = sha->lldd_ha;
+   struct Scsi_Host *shost = sha->core.shost;
 
scsi_remove_host(sha->core.shost);
sas_unregister_ha(sha);
sas_remove_host(sha->core.shost);
 
hisi_sas_free(hisi_hba);
+   kfree(shost);
return 0;
 }
 EXPORT_SYMBOL_GPL(hisi_sas_remove);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [patch] scsi: hisi_sas: shift vs compare typos

2016-11-29 Thread John Garry

On 29/11/2016 10:47, Dan Carpenter wrote:

There are some typos where we intended "<<" but have "<".  Seems likely
to cause a bunch of problems.

Fixes: d3b688d3c69d ("scsi: hisi_sas: add v2 hw support for ECC and AXI bus fatal 
error")
Signed-off-by: Dan Carpenter <dan.carpen...@oracle.com>
---
There is another static checker warning to fix perhaps:

drivers/scsi/hisi_sas/hisi_sas_v2_hw.c:2015 phy_up_v2_hw()
warn: was expecting a 64 bit value instead of '(2 | 1)'

The code is doing:

phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);


Right, I think that a u32 would suffice. We can generate a separate 
patch for this.




phy->phy_type is a u64 and PORT_TYPE_SAS is "1U << 1".  So this code
is clearing out the high 32 bits of ->phy_type uninitentionally.  It's
simple enough to make it 1ULL << 1 but the question is, do we really
need ->phy_type to be a 64 bit variable?  I'm pretty sure that a u32
will suffice.

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 15487f2..93876c0 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -64,19 +64,19 @@
 HGC_LM_DFX_STATUS2_ITCTLIST_OFF)
 #define HGC_CQE_ECC_ADDR   0x13c
 #define HGC_CQE_ECC_1B_ADDR_OFF0
-#define HGC_CQE_ECC_1B_ADDR_MSK(0x3f < HGC_CQE_ECC_1B_ADDR_OFF)
+#define HGC_CQE_ECC_1B_ADDR_MSK(0x3f << HGC_CQE_ECC_1B_ADDR_OFF)
 #define HGC_CQE_ECC_MB_ADDR_OFF8
-#define HGC_CQE_ECC_MB_ADDR_MSK (0x3f < HGC_CQE_ECC_MB_ADDR_OFF)
+#define HGC_CQE_ECC_MB_ADDR_MSK (0x3f << HGC_CQE_ECC_MB_ADDR_OFF)
 #define HGC_IOST_ECC_ADDR  0x140
 #define HGC_IOST_ECC_1B_ADDR_OFF   0
-#define HGC_IOST_ECC_1B_ADDR_MSK   (0x3ff < HGC_IOST_ECC_1B_ADDR_OFF)
+#define HGC_IOST_ECC_1B_ADDR_MSK   (0x3ff << HGC_IOST_ECC_1B_ADDR_OFF)
 #define HGC_IOST_ECC_MB_ADDR_OFF   16
-#define HGC_IOST_ECC_MB_ADDR_MSK   (0x3ff < HGC_IOST_ECC_MB_ADDR_OFF)
+#define HGC_IOST_ECC_MB_ADDR_MSK   (0x3ff << HGC_IOST_ECC_MB_ADDR_OFF)
 #define HGC_DQE_ECC_ADDR   0x144
 #define HGC_DQE_ECC_1B_ADDR_OFF0
-#define HGC_DQE_ECC_1B_ADDR_MSK(0xfff < HGC_DQE_ECC_1B_ADDR_OFF)
+#define HGC_DQE_ECC_1B_ADDR_MSK(0xfff << HGC_DQE_ECC_1B_ADDR_OFF)
 #define HGC_DQE_ECC_MB_ADDR_OFF16
-#define HGC_DQE_ECC_MB_ADDR_MSK (0xfff < HGC_DQE_ECC_MB_ADDR_OFF)
+#define HGC_DQE_ECC_MB_ADDR_MSK (0xfff << HGC_DQE_ECC_MB_ADDR_OFF)
 #define HGC_INVLD_DQE_INFO 0x148
 #define HGC_INVLD_DQE_INFO_FB_CH0_OFF  9
 #define HGC_INVLD_DQE_INFO_FB_CH0_MSK  (0x1 << HGC_INVLD_DQE_INFO_FB_CH0_OFF)

.



Cheers

These were introduced in recent patch applied to 4.10 queue, and would 
only affect rare occurance of AXI/ECC error.


Signed-off-by: John Garry <john.ga...@huawei.com>

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 00/11] hisi_sas: some fixes, improvements, and new features

2016-11-25 Thread John Garry

On 22/11/2016 22:01, Martin K. Petersen wrote:

"John" == John Garry <john.ga...@huawei.com> writes:


John,

John> Are you happy with this patchset now that I've got an external
John> review?

Zhangfei Geo asked a question about patch 1/11 that has yet to be
answered. Patch 5/11 is still unreviewed.



Hi Martin,

I think that these 2 outstanding issues have been addressed. Please let 
me know if there is anything else.


Thanks alot,
John

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 01/11] hisi_sas: add v2 hw support for ECC and AXI bus fatal error

2016-11-23 Thread John Garry

On 16/11/2016 01:47, Zhangfei Gao wrote:

On Mon, Nov 7, 2016 at 8:48 PM, John Garry <john.ga...@huawei.com> wrote:

From: Xiang Chen <chenxian...@hisilicon.com>

For ECC 1bit error, logic can recover it, so we only print
a warning.
For ECC multi-bit and AXI bus fatal error, we panic.


Is it possible to recover via resetting phy and device etc instead of panic?

Thanks





Hi Zhangfei,

We are actually now working on supporting controller reset for certain 
AXI/ECC errors, so that we will not need to panic.


Thanks,
John

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH] scsi: libsas: fix WARN on device removal

2016-11-22 Thread John Garry

On 21/11/2016 17:13, Dan Williams wrote:

On Mon, Nov 21, 2016 at 7:16 AM, John Garry <john.ga...@huawei.com> wrote:

@Maintainers, would you be willing to accept this patch as an interim
fix
for the dastardly WARN while we try to fix the flutter issue?




To me this adds a bug to quiet a benign, albeit noisy, warning.



What is the bug which is being added?



The bug where we queue a port teardown, but see a port formation event
in the meantime.



As I understand, this vulnerability already exists:
http://marc.info/?l=linux-scsi=143801026028006=2

I actually don't understand how libsas dealt with flutter (which I take to
mean a burst of up and down events) before these changes, as it can only
queue simultaneously one up and one down event per port. So, if we get a
flutter, then the events are lost and we get indeterminate state.



The events are not lost.


In sas_queue_event(), if there is a particular event pending for a 
port/PHY, we cannot queue further same event types for that port/PHY. I 
think my colleagues found issue where we try to enqueue multiple 
complementary events.



The new problem this patch introduces is
delaying sas port deletion where it was previously immediate.  So now
we can get into a situation where the port has gone down and can start
processing a port up event before the previous deletion work has run.




And it's a very noisy warning, as in 6K lines on the console when an
expander is unplugged.



Does something like this modulate the failure?


I'm curious if we simply need to fix the double deletion of the
sas_port bsg queue, could you try the changes below?



No, I just tested it on a root port and we get the same WARN.



diff --git a/drivers/scsi/scsi_transport_sas.c
b/drivers/scsi/scsi_transport_sas.cindex
60b651bfaa01..11401e5c88ba 100644
 --- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -262,9 +262,10 @@ static void sas_bsg_remove(struct Scsi_Host
*shost, struct sas_rphy *rphy
 {
struct request_queue *q;

-   if (rphy)
+   if (rphy) {
q = rphy->q;
-   else
+   rphy->q = NULL;
+   } else
q = to_sas_host_attrs(shost)->q;

if (!q)

.






.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 00/11] hisi_sas: some fixes, improvements, and new features

2016-11-22 Thread John Garry

On 14/11/2016 23:49, Martin K. Petersen wrote:

"John" == John Garry <john.ga...@huawei.com> writes:


John> This patchset introduces some misc bug fixes, improvements, and
John> new features to the HiSilicon SAS driver.

This series needs review.



Hi Martin,

Are you happy with this patchset now that I've got an external review?

Thanks,
John

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH] scsi: libsas: fix WARN on device removal

2016-11-21 Thread John Garry

@Maintainers, would you be willing to accept this patch as an interim fix
for the dastardly WARN while we try to fix the flutter issue?



To me this adds a bug to quiet a benign, albeit noisy, warning.



What is the bug which is being added?


The bug where we queue a port teardown, but see a port formation event
in the meantime.


As I understand, this vulnerability already exists:
http://marc.info/?l=linux-scsi=143801026028006=2

I actually don't understand how libsas dealt with flutter (which I take 
to mean a burst of up and down events) before these changes, as it can 
only queue simultaneously one up and one down event per port. So, if we 
get a flutter, then the events are lost and we get indeterminate state.





And it's a very noisy warning, as in 6K lines on the console when an
expander is unplugged.


Does something like this modulate the failure?

diff --git a/drivers/scsi/scsi_transport_sas.c
b/drivers/scsi/scsi_transport_sas.cindex
60b651bfaa01..11401e5c88ba 100644
 --- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -262,9 +262,10 @@ static void sas_bsg_remove(struct Scsi_Host
*shost, struct sas_rphy *rphy
 {
struct request_queue *q;

-   if (rphy)
+   if (rphy) {
q = rphy->q;
-   else
+   rphy->q = NULL;
+   } else
q = to_sas_host_attrs(shost)->q;

if (!q)

.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] scsi: hisi_sas: Add a missing call to kfree

2016-11-21 Thread John Garry

On 21/11/2016 14:25, Quentin Lambert wrote:


On 11/21/2016 03:16 PM, John Garry wrote:

On 21/11/2016 13:20, Quentin Lambert wrote:



On 11/21/2016 01:53 PM, John Garry wrote:

However I have noticed that we should do a call to hisi_sas_free() for
this failure, and later failures in the probe.

I don't understand why, and would welcome the opportunity to learn
something.



We call hisi_sas_alloc() from hisi_sas_shost_alloc(); if we fail after
this in hisi_sas_probe(), then we should free the memmories and
workqueue got in hisi_sas_alloc(), which we don't.

Thanks.
Are you writing the patch or do you want me to do it?



We can do it, thanks.


Quentin





--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] scsi: hisi_sas: Add a missing call to kfree

2016-11-21 Thread John Garry

On 21/11/2016 13:20, Quentin Lambert wrote:



On 11/21/2016 01:53 PM, John Garry wrote:

However I have noticed that we should do a call to hisi_sas_free() for
this failure, and later failures in the probe.

I don't understand why, and would welcome the opportunity to learn
something.



We call hisi_sas_alloc() from hisi_sas_shost_alloc(); if we fail after 
this in hisi_sas_probe(), then we should free the memmories and 
workqueue got in hisi_sas_alloc(), which we don't.


Thanks,
John


Quentin






--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] scsi: hisi_sas: Add a missing call to kfree

2016-11-21 Thread John Garry

On 19/11/2016 17:42, Quentin Lambert wrote:

Most error branches following the call to hisi_sas_shost_alloc contain
a call to kfree. This patch add these calls where they are
missing.

This issue was found with Hector.


I think that this patch is fine. However I have noticed that we should 
do a call to hisi_sas_free() for this failure, and later failures in the 
probe.


I can generate a patch for this.

Cheers,
John



Signed-off-by: Quentin Lambert 

---
 drivers/scsi/hisi_sas/hisi_sas_main.c |6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1503,8 +1503,10 @@ int hisi_sas_probe(struct platform_devic

arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL);
arr_port = devm_kcalloc(dev, port_nr, sizeof(void *), GFP_KERNEL);
-   if (!arr_phy || !arr_port)
-   return -ENOMEM;
+   if (!arr_phy || !arr_port) {
+   rc = -ENOMEM;
+   goto err_out_ha;
+   }

sha->sas_phy = arr_phy;
sha->sas_port = arr_port;

.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH] scsi: libsas: fix WARN on device removal

2016-11-18 Thread John Garry

On 18/11/2016 01:53, Dan Williams wrote:

On Thu, Nov 17, 2016 at 7:23 AM, John Garry <john.ga...@huawei.com> wrote:

On 11/11/2016 08:49, wangyijing wrote:


I have not seen the flutter issue. I am just trying to solve the
horrible WARN dump.
However I do understand that there may be a issue related to how we
queue the events; there was a recent attempt to fix this, but it came to
nothing:
https://www.spinics.net/lists/linux-scsi/msg1.html



We found libsas hotplug several problems:
1. sysfs warning calltrace(like the case you found);



Maybe you can then review my patch.



I did it, I think your solution to fix the sysfs calltrace issue is ok,
and what I worried about is we still need to fix
the rest issues. So it's better if we could fix all issues one time.



@Maintainers, would you be willing to accept this patch as an interim fix
for the dastardly WARN while we try to fix the flutter issue?


To me this adds a bug to quiet a benign, albeit noisy, warning.



What is the bug which is being added?

And it's a very noisy warning, as in 6K lines on the console when an 
expander is unplugged.



.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH] scsi: libsas: fix WARN on device removal

2016-11-17 Thread John Garry

On 11/11/2016 08:49, wangyijing wrote:

I have not seen the flutter issue. I am just trying to solve the horrible WARN 
dump.
However I do understand that there may be a issue related to how we queue the 
events; there was a recent attempt to fix this, but it came to nothing:
https://www.spinics.net/lists/linux-scsi/msg1.html


We found libsas hotplug several problems:
1. sysfs warning calltrace(like the case you found);


Maybe you can then review my patch.


I did it, I think your solution to fix the sysfs calltrace issue is ok, and 
what I worried about is we still need to fix
the rest issues. So it's better if we could fix all issues one time.



@Maintainers, would you be willing to accept this patch as an interim 
fix for the dastardly WARN while we try to fix the flutter issue?





2. hot-add and hot-remove work events may process out of order;
3. in some extreme cases, libsas may miss some events, if the same event is 
still pending in workqueue.



Can you tell me how to recreate #2 and #3?


Qilin Chen and Yousong He help me to reproduce it, I told them to reply this 
mail to tell you the test steps.
Some tests we did is make sas phy link flutter, so hardware would post phy down 
and phy up events sequentially.

1. scsi host workqueue receive phy down and phy up events.  
   in process new added
2. sas_deform_port would post a new destruct event to scsi host workqueue, so 
things in workqueue like [phy down-phy up -destruct]

So the phy down logic is separated by phy up, and it's not atomic, not safe, 
something unexpected would happen.

For case 3, we make hardware burst post lots pair of phy up and phy down 
events, so if libsas is processing the phy up event, the next
phy up event can not queue to scsi host workqueue again, it will lost, it's not 
we expect.




It's a complex issue, we posted two patches, try to fix these issues, but now 
few people are interested in it  :(



IIRC, you sent as RFC and got a "reviewed-by" from Hannes, so I'm not sure what 
else you want. BTW, I thought that the changes were quite drastic.


I agree, the changes seems something drastic. But I think current libsas 
hotplug framework has a big flaw.



John





Alternatively we need a mechanism to cancel in-flight port shutdown
requests when we start re-attaching devices before queued port
destruction events have run.

.




___
linuxarm mailing list
linux...@huawei.com
http://rnd-openeuler.huawei.com/mailman/listinfo/linuxarm

.




.





.




.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 02/11] hisi_sas: alloc queue id of slot according to device id

2016-11-16 Thread John Garry

On 16/11/2016 01:41, Zhangfei Gao wrote:

On Mon, Nov 7, 2016 at 8:48 PM, John Garry <john.ga...@huawei.com> wrote:

From: Xiang Chen <chenxian...@hisilicon.com>

Currently slots are allocated from queues in a round-robin fashion.
This causes a problem for internal commands in device mode. For this
mode, we should ensure that the internal abort command is the last
command seen in the host for that device. We can only ensure this when
we place the internal abort command after the preceding commands for
device that in the same queue, as there is no order in which the host
will select a queue to execute the next command.


Is there performance penalty, since only one queue is supported for a device.


Hi Zhangfei,

From testing I have not seen any noteable performance change. However, 
please note the comment on mq, below.


Cheers,
John





This queue restriction makes supporting scsi mq more tricky in
the future, but should not be a blocker.

Note: Even though v1 hw does not support internal abort, the
  allocation method is chosen to be the same for consistency.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>


Reviewed-by: Zhangfei Gao <zhangfei@linaro.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH] scsi: libsas: fix WARN on device removal

2016-11-11 Thread John Garry

On 11/11/2016 08:12, wangyijing wrote:


They're not the same. I don't see how your solution properly deals with remote 
sas_port deletion.

When we unplug a device connected to an expander, can't the sas_port be deleted 
twice, in sas_unregister_devs_sas_addr() from domain revalidation and also now 
in sas_destruct_devices()? I think that this gives a NULL dereference.
And we still get the WARN as the sas_port has still been deleted before the 
device.

In my solution, we should always delete the sas_port after the attached device.



i.e. it moves the port destruction to the workqueue and still suffers
from the flutter problem:

http://marc.info/?l=linux-scsi=143801026028006=2
http://marc.info/?l=linux-scsi=143801971131073=2

Perhaps we instead need to quiet this warning?

http://marc.info/?l=linux-scsi=143802229932175=2


I have not seen the flutter issue. I am just trying to solve the horrible WARN 
dump.
However I do understand that there may be a issue related to how we queue the 
events; there was a recent attempt to fix this, but it came to nothing:
https://www.spinics.net/lists/linux-scsi/msg1.html


We found libsas hotplug several problems:
1. sysfs warning calltrace(like the case you found);


Maybe you can then review my patch.


2. hot-add and hot-remove work events may process out of order;
3. in some extreme cases, libsas may miss some events, if the same event is 
still pending in workqueue.



Can you tell me how to recreate #2 and #3?


It's a complex issue, we posted two patches, try to fix these issues, but now 
few people are interested in it  :(



IIRC, you sent as RFC and got a "reviewed-by" from Hannes, so I'm not 
sure what else you want. BTW, I thought that the changes were quite drastic.


John





Alternatively we need a mechanism to cancel in-flight port shutdown
requests when we start re-attaching devices before queued port
destruction events have run.

.




___
linuxarm mailing list
linux...@huawei.com
http://rnd-openeuler.huawei.com/mailman/listinfo/linuxarm

.




.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH] scsi: libsas: fix WARN on device removal

2016-11-10 Thread John Garry

On 09/11/2016 20:35, Dan Williams wrote:

On Wed, Nov 9, 2016 at 11:09 AM, Dan Williams <dan.j.willi...@intel.com> wrote:

On Wed, Nov 9, 2016 at 9:36 AM, John Garry <john.ga...@huawei.com> wrote:

On 09/11/2016 12:28, John Garry wrote:


On 03/11/2016 14:58, John Garry wrote:


The following patch introduces an annoying WARN
when a device is removed from the SAS topology:
[SCSI] libsas: prevent domain rediscovery competing with ata error
handling



Are there any views on this patch? I would have thought that the parties
who use the drivers based on libsas would be interested in fixing this
bug.



I should have added the before and after logs earlier, so the issue is
illustrated. Now attached. When a 24-port expander is unplugged we get >6k
lines of WARN on the console, lasting >30 seconds. Not nice.



I might be mistaken, but this patch seems functionally identical to
this attempt:

http://marc.info/?l=linux-scsi=143459794823595=2


Hi Dan,

They're not the same. I don't see how your solution properly deals with 
remote sas_port deletion.


When we unplug a device connected to an expander, can't the sas_port be 
deleted twice, in sas_unregister_devs_sas_addr() from domain 
revalidation and also now in sas_destruct_devices()? I think that this 
gives a NULL dereference.
And we still get the WARN as the sas_port has still been deleted before 
the device.


In my solution, we should always delete the sas_port after the attached 
device.




i.e. it moves the port destruction to the workqueue and still suffers
from the flutter problem:

http://marc.info/?l=linux-scsi=143801026028006=2
http://marc.info/?l=linux-scsi=143801971131073=2

Perhaps we instead need to quiet this warning?

http://marc.info/?l=linux-scsi=143802229932175=2


I have not seen the flutter issue. I am just trying to solve the 
horrible WARN dump.
However I do understand that there may be a issue related to how we 
queue the events; there was a recent attempt to fix this, but it came to 
nothing:

https://www.spinics.net/lists/linux-scsi/msg1.html

Cheers,
John



Alternatively we need a mechanism to cancel in-flight port shutdown
requests when we start re-attaching devices before queued port
destruction events have run.

.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH] scsi: libsas: fix WARN on device removal

2016-11-09 Thread John Garry

On 03/11/2016 14:58, John Garry wrote:

The following patch introduces an annoying WARN
when a device is removed from the SAS topology:
[SCSI] libsas: prevent domain rediscovery competing with ata error handling



Are there any views on this patch? I would have thought that the parties 
who use the drivers based on libsas would be interested in fixing this bug.


BTW, We are internally testing, hence the RFC.

Thanks in advance,
John


A sample WARN is as follows:
[  236.842227] WARNING: CPU: 7 PID: 1520 at fs/sysfs/group.c:237 
sysfs_remove_group+0x90/0x98
[  236.850465] Modules linked in:
[  236.853544]
[  236.855045] CPU: 7 PID: 1520 Comm: kworker/u64:4 Tainted: GW   
4.9.0-rc1-15310-g3fbc29e-dirty #676
[  236.865010] Hardware name: Huawei Taishan 2180 /D03, BIOS Estuary v2.3 D03 
UEFI 08/17/2016
[  236.873249] Workqueue: scsi_wq_0 sas_destruct_devices
[  236.878317] task: 8027ba31b200 task.stack: 8027b9d44000
[  236.884225] PC is at sysfs_remove_group+0x90/0x98
[  236.888920] LR is at sysfs_remove_group+0x90/0x98
[  236.893616] pc : [] lr : [] pstate: 
6145
[  236.900989] sp : 8027b9d47bf0

< snip >

[  237.116463] [] sysfs_remove_group+0x90/0x98
[  237.122197] [] dpm_sysfs_remove+0x58/0x68
[  237.127758] [] device_del+0x40/0x218
[  237.132886] [] device_unregister+0x14/0x2c
[  237.138536] [] bsg_unregister_queue+0x5c/0xa0
[  237.12] [] sas_rphy_remove+0x44/0x80
[  237.149915] [] sas_rphy_delete+0x14/0x28
[  237.155388] [] sas_destruct_devices+0x64/0x98
[  237.161293] [] process_one_work+0x128/0x2e4
[  237.167027] [] worker_thread+0x58/0x434
[  237.172415] [] kthread+0xd4/0xe8
[  237.177198] [] ret_from_fork+0x10/0x50
[  237.182557] sysfs group 'power' not found for kobject 'end_device-0:0:5'

(this can be really huge when an expander is unplugged)

The problem is with the process of sas_port and domain_device
destruction in domain revalidation. There is a 2-stage process:
In domain revalidation (which runs in work queue context), if a
domain_device is discovered to be gone, then the following happens:
- the domain_device is queued for destruction in a separate work item
- the associated sas_port is destroyed immediately

This causes a problem in that the sas_port associated with
a domain_device is destroyed prior the domain_device: this causes
the sysfs WARN. Essentially the "rug has been pulled from underneath".

Also, likewise, when a root port is deformed due to loss of signal,
we have the same issue.

To solve, destroy the sas_port in a separate work item to which
we do the domain revalidation with a new discovery event, as follows:
- When a domain_device is detected to be gone, the domain_device is
  queued for destruction in a separate work item. The associated
  sas_port is also queued for destruction in another separate work item
  (needs to be queued 2nd)
- the domain_device is destroyed
- the sas_port is destroyed
[similar is done for loss of signal event, in sas_port_deformed()].

Fixes: 87c8331fcf72e501c3a3c0cdc5c [SCSI] libsas: prevent domain
rediscovery competing with ata error handling

Signed-off-by: John Garry <john.ga...@huawei.com>

diff --git a/drivers/scsi/libsas/sas_discover.c 
b/drivers/scsi/libsas/sas_discover.c
index 60de662..01d0fe2 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -361,7 +361,7 @@ static void sas_destruct_devices(struct work_struct *work)

clear_bit(DISCE_DESTRUCT, >disc.pending);

-   list_for_each_entry_safe(dev, n, >destroy_list, disco_list_node) {
+   list_for_each_entry_safe(dev, n, >dev_destroy_list, 
disco_list_node) {
list_del_init(>disco_list_node);

sas_remove_children(>rphy->dev);
@@ -383,7 +383,7 @@ void sas_unregister_dev(struct asd_sas_port *port, struct 
domain_device *dev)

if (!test_and_set_bit(SAS_DEV_DESTROY, >state)) {
sas_rphy_unlink(dev->rphy);
-   list_move_tail(>disco_list_node, >destroy_list);
+   list_move_tail(>disco_list_node, >dev_destroy_list);
sas_discover_event(dev->port, DISCE_DESTRUCT);
}
 }
@@ -525,6 +525,28 @@ static void sas_revalidate_domain(struct work_struct *work)
mutex_unlock(>disco_mutex);
 }

+/* -- Async Port destruct -- */
+static void sas_async_port_destruct(struct work_struct *work)
+{
+   struct sas_discovery_event *ev = to_sas_discovery_event(work);
+   struct asd_sas_port *port = ev->port;
+   struct sas_port *sas_port, *n;
+
+   clear_bit(DISCE_PORT_DESTRUCT, >disc.pending);
+
+   list_for_each_entry_safe(sas_port, n, >port_destroy_list, 
destroy_list) {
+   list_del_init(>port_destroy_list);
+
+   sas_port_delete(sas_port);
+   }
+}
+
+void sas_port_destruct(struct asd_sas_port *port, struct sas_port *sas_port)
+{
+   list_move_tail(_port->destroy_

[PATCH 07/11] hisi_sas: delete repeated configuration in free_device_v2_hw()

2016-11-07 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

Delete repeated configuration items for hisi_sas_device() when
we free a device. These items are now only set in
hisi_sas_dev_gone().

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 7567193..3081eec 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -739,8 +739,6 @@ static void free_device_v2_hw(struct hisi_hba *hisi_hba,
qw0 &= ~(1 << ITCT_HDR_VALID_OFF);
hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
 ENT_INT_SRC3_ITC_INT_MSK);
-   hisi_hba->devices[dev_id].dev_type = SAS_PHY_UNUSED;
-   hisi_hba->devices[dev_id].dev_status = 
HISI_SAS_DEV_NORMAL;
 
/* clear the itct */
hisi_sas_write32(hisi_hba, ITCT_CLR, 0);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 01/11] hisi_sas: add v2 hw support for ECC and AXI bus fatal error

2016-11-07 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

For ECC 1bit error, logic can recover it, so we only print
a warning.
For ECC multi-bit and AXI bus fatal error, we panic.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 425 -
 1 file changed, 420 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 0763b47..9e70e6d 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -55,10 +55,44 @@
 #define HGC_DFX_CFG2   0xc0
 #define HGC_IOMB_PROC1_STATUS  0x104
 #define CFG_1US_TIMER_TRSH 0xcc
+#define HGC_LM_DFX_STATUS2 0x128
+#define HGC_LM_DFX_STATUS2_IOSTLIST_OFF0
+#define HGC_LM_DFX_STATUS2_IOSTLIST_MSK(0xfff << \
+HGC_LM_DFX_STATUS2_IOSTLIST_OFF)
+#define HGC_LM_DFX_STATUS2_ITCTLIST_OFF12
+#define HGC_LM_DFX_STATUS2_ITCTLIST_MSK(0x7ff << \
+HGC_LM_DFX_STATUS2_ITCTLIST_OFF)
+#define HGC_CQE_ECC_ADDR   0x13c
+#define HGC_CQE_ECC_1B_ADDR_OFF0
+#define HGC_CQE_ECC_1B_ADDR_MSK(0x3f < HGC_CQE_ECC_1B_ADDR_OFF)
+#define HGC_CQE_ECC_MB_ADDR_OFF8
+#define HGC_CQE_ECC_MB_ADDR_MSK (0x3f < HGC_CQE_ECC_MB_ADDR_OFF)
+#define HGC_IOST_ECC_ADDR  0x140
+#define HGC_IOST_ECC_1B_ADDR_OFF   0
+#define HGC_IOST_ECC_1B_ADDR_MSK   (0x3ff < HGC_IOST_ECC_1B_ADDR_OFF)
+#define HGC_IOST_ECC_MB_ADDR_OFF   16
+#define HGC_IOST_ECC_MB_ADDR_MSK   (0x3ff < HGC_IOST_ECC_MB_ADDR_OFF)
+#define HGC_DQE_ECC_ADDR   0x144
+#define HGC_DQE_ECC_1B_ADDR_OFF0
+#define HGC_DQE_ECC_1B_ADDR_MSK(0xfff < HGC_DQE_ECC_1B_ADDR_OFF)
+#define HGC_DQE_ECC_MB_ADDR_OFF16
+#define HGC_DQE_ECC_MB_ADDR_MSK (0xfff < HGC_DQE_ECC_MB_ADDR_OFF)
 #define HGC_INVLD_DQE_INFO 0x148
 #define HGC_INVLD_DQE_INFO_FB_CH0_OFF  9
 #define HGC_INVLD_DQE_INFO_FB_CH0_MSK  (0x1 << HGC_INVLD_DQE_INFO_FB_CH0_OFF)
 #define HGC_INVLD_DQE_INFO_FB_CH3_OFF  18
+#define HGC_ITCT_ECC_ADDR  0x150
+#define HGC_ITCT_ECC_1B_ADDR_OFF   0
+#define HGC_ITCT_ECC_1B_ADDR_MSK   (0x3ff << \
+HGC_ITCT_ECC_1B_ADDR_OFF)
+#define HGC_ITCT_ECC_MB_ADDR_OFF   16
+#define HGC_ITCT_ECC_MB_ADDR_MSK   (0x3ff << \
+HGC_ITCT_ECC_MB_ADDR_OFF)
+#define HGC_AXI_FIFO_ERR_INFO  0x154
+#define AXI_ERR_INFO_OFF   0
+#define AXI_ERR_INFO_MSK   (0xff << AXI_ERR_INFO_OFF)
+#define FIFO_ERR_INFO_OFF  8
+#define FIFO_ERR_INFO_MSK  (0xff << FIFO_ERR_INFO_OFF)
 #define INT_COAL_EN0x19c
 #define OQ_INT_COAL_TIME   0x1a0
 #define OQ_INT_COAL_CNT0x1a4
@@ -73,13 +107,41 @@
 #define ENT_INT_SRC1_D2H_FIS_CH1_MSK   (0x1 << ENT_INT_SRC1_D2H_FIS_CH1_OFF)
 #define ENT_INT_SRC2   0x1bc
 #define ENT_INT_SRC3   0x1c0
+#define ENT_INT_SRC3_WP_DEPTH_OFF  8
+#define ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF 9
+#define ENT_INT_SRC3_RP_DEPTH_OFF  10
+#define ENT_INT_SRC3_AXI_OFF   11
+#define ENT_INT_SRC3_FIFO_OFF  12
+#define ENT_INT_SRC3_LM_OFF14
 #define ENT_INT_SRC3_ITC_INT_OFF   15
 #define ENT_INT_SRC3_ITC_INT_MSK   (0x1 << ENT_INT_SRC3_ITC_INT_OFF)
+#define ENT_INT_SRC3_ABT_OFF   16
 #define ENT_INT_SRC_MSK1   0x1c4
 #define ENT_INT_SRC_MSK2   0x1c8
 #define ENT_INT_SRC_MSK3   0x1cc
 #define ENT_INT_SRC_MSK3_ENT95_MSK_OFF 31
 #define ENT_INT_SRC_MSK3_ENT95_MSK_MSK (0x1 << ENT_INT_SRC_MSK3_ENT95_MSK_OFF)
+#define SAS_ECC_INTR   0x1e8
+#define SAS_ECC_INTR_DQE_ECC_1B_OFF0
+#define SAS_ECC_INTR_DQE_ECC_MB_OFF1
+#define SAS_ECC_INTR_IOST_ECC_1B_OFF   2
+#define SAS_ECC_INTR_IOST_ECC_MB_OFF   3
+#define SAS_ECC_INTR_ITCT_ECC_MB_OFF   4
+#define SAS_ECC_INTR_ITCT_ECC_1B_OFF   5
+#define SAS_ECC_INTR_IOSTLIST_ECC_MB_OFF   6
+#define SAS_ECC_INTR_IOSTLIST_ECC_1B_OFF   7
+#define SAS_ECC_INTR_ITCTLIST_ECC_1B_OFF   8
+#define SAS_ECC_INTR_ITCTLIST_ECC_MB_OFF   9
+#define SAS_ECC_INTR_CQE_ECC_1B_OFF10
+#define SAS_ECC_INTR_CQE_ECC_MB_OFF11
+#define SAS_ECC_INTR_NCQ_MEM0_ECC_MB_OFF   12
+#define SAS_ECC_INTR_NCQ_MEM0_ECC_1B_OFF   13
+#define SAS_ECC_INTR_NCQ_MEM1_ECC_MB_OFF   14
+#define SAS_ECC_INTR_NCQ_MEM1_ECC_1B_OFF   15
+#define SAS_ECC_INTR_NCQ_MEM2_ECC_MB_OFF   16
+#define SAS_ECC_INTR_NCQ_MEM2_ECC_1B_OFF  

[PATCH 08/11] hisi_sas: modify some values in get_ata_protocol()

2016-11-07 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

Modify and add some SATA commands according to SATA protocol.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 3081eec..a5faa4d 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1750,6 +1750,7 @@ static u8 get_ata_protocol(u8 cmd, int direction)
case ATA_CMD_NCQ_NON_DATA:
return SATA_PROTOCOL_FPDMA;
 
+   case ATA_CMD_DOWNLOAD_MICRO:
case ATA_CMD_ID_ATA:
case ATA_CMD_PMP_READ:
case ATA_CMD_READ_LOG_EXT:
@@ -1761,18 +1762,27 @@ static u8 get_ata_protocol(u8 cmd, int direction)
case ATA_CMD_PIO_WRITE_EXT:
return SATA_PROTOCOL_PIO;
 
+   case ATA_CMD_DSM:
+   case ATA_CMD_DOWNLOAD_MICRO_DMA:
+   case ATA_CMD_PMP_READ_DMA:
+   case ATA_CMD_PMP_WRITE_DMA:
case ATA_CMD_READ:
case ATA_CMD_READ_EXT:
case ATA_CMD_READ_LOG_DMA_EXT:
+   case ATA_CMD_READ_STREAM_DMA_EXT:
+   case ATA_CMD_TRUSTED_RCV_DMA:
+   case ATA_CMD_TRUSTED_SND_DMA:
case ATA_CMD_WRITE:
case ATA_CMD_WRITE_EXT:
+   case ATA_CMD_WRITE_FUA_EXT:
case ATA_CMD_WRITE_QUEUED:
case ATA_CMD_WRITE_LOG_DMA_EXT:
+   case ATA_CMD_WRITE_STREAM_DMA_EXT:
return SATA_PROTOCOL_DMA;
 
-   case ATA_CMD_DOWNLOAD_MICRO:
-   case ATA_CMD_DEV_RESET:
case ATA_CMD_CHK_POWER:
+   case ATA_CMD_DEV_RESET:
+   case ATA_CMD_EDD:
case ATA_CMD_FLUSH:
case ATA_CMD_FLUSH_EXT:
case ATA_CMD_VERIFY:
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/11] hisi_sas: use atomic64_t for hisi_sas_device.running_req

2016-11-07 Thread John Garry
Sometimes the value of hisi_sas_device.running_req
would go negative unless we have the check for
running_req >= 0 before trying to decrement.

This is because using running_req is not thread-safe.

As such, the value for running_req may be actually incorrect,
so use atomic64_t instead.

Signed-off-by: John Garry <john.ga...@huawei.com>
Reviewed-by: Xiang Chen <chenxian...@hisilicon.com>
---
 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 | 4 ++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 ++--
 4 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index bf59fab..8b5ecc6 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -111,7 +111,7 @@ struct hisi_sas_device {
struct domain_device*sas_device;
u64 attached_phy;
u64 device_id;
-   u64 running_req;
+   atomic64_t running_req;
u8 dev_status;
 };
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 504cbcf..18e2194 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -162,8 +162,8 @@ static void hisi_sas_slot_abort(struct work_struct *work)
hisi_sas_slot_task_free(hisi_hba, task, abort_slot);
if (task->task_done)
task->task_done(task);
-   if (sas_dev && sas_dev->running_req)
-   sas_dev->running_req--;
+   if (sas_dev)
+   atomic64_dec(_dev->running_req);
 }
 
 static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
@@ -303,7 +303,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
 
hisi_hba->slot_prep = slot;
 
-   sas_dev->running_req++;
+   atomic64_inc(_dev->running_req);
++(*pass);
 
return 0;
@@ -1027,7 +1027,8 @@ static int hisi_sas_query_task(struct sas_task *task)
 
hisi_hba->slot_prep = slot;
 
-   sas_dev->running_req++;
+   atomic64_inc(_dev->running_req);
+
/* send abort command to our chip */
hisi_hba->hw->start_delivery(hisi_hba);
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index bbc5760..05177fc 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1366,8 +1366,8 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
}
 
 out:
-   if (sas_dev && sas_dev->running_req)
-   sas_dev->running_req--;
+   if (sas_dev)
+   atomic64_dec(_dev->running_req);
 
hisi_sas_slot_task_free(hisi_hba, task, slot);
sts = ts->stat;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index cda3baf..e88113a 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1728,8 +1728,8 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
}
 
 out:
-   if (sas_dev && sas_dev->running_req)
-   sas_dev->running_req--;
+   if (sas_dev)
+   atomic64_dec(_dev->running_req);
 
hisi_sas_slot_task_free(hisi_hba, task, slot);
sts = ts->stat;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 04/11] hisi_sas: fix port form bug in hisi_sas_port_notify_formed()

2016-11-07 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

When we form a wideport, we should use hardware PHY port_id instead
of sas_phy->id.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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 9f5ccc5..486aa92 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -537,7 +537,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[sas_phy->id];
+   struct hisi_sas_port *port = _hba->port[phy->port_id];
unsigned long flags;
 
if (!sas_port)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/11] hisi_sas: only process broadcast change in phy_bcast_v2_hw()

2016-11-07 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

There are many BROADCAST primitives generated by the host.
We are only interested in BROADCAST (CHANGE) primitives currently,
so only process this.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index cb19e73..7567193 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -194,6 +194,9 @@
 #define SL_CONTROL_NOTIFY_EN_MSK   (0x1 << SL_CONTROL_NOTIFY_EN_OFF)
 #define SL_CONTROL_CTA_OFF 17
 #define SL_CONTROL_CTA_MSK (0x1 << SL_CONTROL_CTA_OFF)
+#define RX_PRIMS_STATUS (PORT_BASE + 0x98)
+#define RX_BCAST_CHG_OFF1
+#define RX_BCAST_CHG_MSK(0x1 << RX_BCAST_CHG_OFF)
 #define TX_ID_DWORD0   (PORT_BASE + 0x9c)
 #define TX_ID_DWORD1   (PORT_BASE + 0xa0)
 #define TX_ID_DWORD2   (PORT_BASE + 0xa4)
@@ -2044,9 +2047,12 @@ static void phy_bcast_v2_hw(int phy_no, struct hisi_hba 
*hisi_hba)
struct hisi_sas_phy *phy = _hba->phy[phy_no];
struct asd_sas_phy *sas_phy = >sas_phy;
struct sas_ha_struct *sas_ha = _hba->sha;
+   u32 bcast_status;
 
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1);
-   sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+   bcast_status = hisi_sas_phy_read32(hisi_hba, phy_no, RX_PRIMS_STATUS);
+   if (bcast_status & RX_BCAST_CHG_MSK)
+   sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
 CHL_INT0_SL_RX_BCST_ACK_MSK);
hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 00/11] hisi_sas: some fixes, improvements, and new features

2016-11-07 Thread John Garry
This patchset introduces some misc bug fixes, improvements,
and new features to the HiSilicon SAS driver.

The new features include:
- ECC and AXI bus fatal error handling for v2 hw
- PHY (min and max) linkrate setting

John Garry (1):
  hisi_sas: use atomic64_t for hisi_sas_device.running_req

Xiang Chen (10):
  hisi_sas: add v2 hw support for ECC and AXI bus fatal error
  hisi_sas: alloc queue id of slot according to device id
  hisi_sas: only process broadcast change in phy_bcast_v2_hw()
  hisi_sas: fix port form bug in hisi_sas_port_notify_formed()
  hisi_sas: replace WARN_ON() with dev_warn() for internal abort
  hisi_sas: modify return value of hisi_sas_query_task()
  hisi_sas: delete repeated configuration in free_device_v2_hw()
  hisi_sas: modify some values in get_ata_protocol()
  hisi_sas: check SATA FIS when directly attaching SATA device
  hisi_sas: add PHY set linkrate support for v1 and v2 hw

 drivers/scsi/hisi_sas/hisi_sas.h   |   9 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  |  37 ++-
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  79 +++--
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 539 +++--
 4 files changed, 599 insertions(+), 65 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 06/11] hisi_sas: modify return value of hisi_sas_query_task()

2016-11-07 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

sas_scsi_find_task() only deals with return value
TMF_RESP_FUNC_FAILED/TMF_RESP_FUNC_SUCC/TMF_RESP_FUNC_COMPLETE of
query task. So for LLDD errors just return TMF_RESP_FUNC_FAILED.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 9133238..504cbcf 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -961,6 +961,9 @@ static int hisi_sas_query_task(struct sas_task *task)
case TMF_RESP_FUNC_FAILED:
case TMF_RESP_FUNC_COMPLETE:
break;
+   default:
+   rc = TMF_RESP_FUNC_FAILED;
+   break;
}
}
return rc;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/11] hisi_sas: check SATA FIS when directly attaching SATA device

2016-11-07 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

Check ERR bit of status to decide whether there is something wrong with
initial register-D2H FIS. If error exists, PHY reset the channel to
restart OOB.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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 a5faa4d..cda3baf 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2537,6 +2537,16 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
goto end;
}
 
+   /* check ERR bit of Status Register */
+   if (fis->status & ATA_ERR) {
+   dev_warn(dev, "sata int: phy%d FIS status: 0x%x\n", phy_no,
+   fis->status);
+   disable_phy_v2_hw(hisi_hba, phy_no);
+   enable_phy_v2_hw(hisi_hba, phy_no);
+   res = IRQ_NONE;
+   goto end;
+   }
+
if (unlikely(phy_no == 8)) {
u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 11/11] hisi_sas: add PHY set linkrate support for v1 and v2 hw

2016-11-07 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

Add the function to set PHY min and max linkrate through
sysfs interface.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  3 +++
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 12 +++--
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 45 ++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 45 ++
 4 files changed, 103 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 8b5ecc6..c0cd505 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -168,6 +168,9 @@ struct hisi_sas_hw {
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);
+   void (*phy_set_linkrate)(struct hisi_hba *hisi_hba, int phy_no,
+   struct sas_phy_linkrates *linkrates);
+   enum sas_linkrate (*phy_get_max_linkrate)(void);
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);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 18e2194..6d6f150 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -369,9 +369,14 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba 
*hisi_hba, int phy_no)
struct sas_phy *sphy = sas_phy->phy;
 
sphy->negotiated_linkrate = sas_phy->linkrate;
-   sphy->minimum_linkrate = phy->minimum_linkrate;
sphy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
-   sphy->maximum_linkrate = phy->maximum_linkrate;
+   sphy->maximum_linkrate_hw =
+   hisi_hba->hw->phy_get_max_linkrate();
+   if (sphy->minimum_linkrate == SAS_LINK_RATE_UNKNOWN)
+   sphy->minimum_linkrate = phy->minimum_linkrate;
+
+   if (sphy->maximum_linkrate == SAS_LINK_RATE_UNKNOWN)
+   sphy->maximum_linkrate = phy->maximum_linkrate;
}
 
if (phy->phy_type & PORT_TYPE_SAS) {
@@ -645,6 +650,9 @@ static int hisi_sas_control_phy(struct asd_sas_phy 
*sas_phy, enum phy_func func,
break;
 
case PHY_FUNC_SET_LINK_RATE:
+   hisi_hba->hw->phy_set_linkrate(hisi_hba, phy_no, funcdata);
+   break;
+
case PHY_FUNC_RELEASE_SPINUP_HOLD:
default:
return -EOPNOTSUPP;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 05177fc..8a1be0b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -843,6 +843,49 @@ static void sl_notify_v1_hw(struct hisi_hba *hisi_hba, int 
phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
 }
 
+static enum sas_linkrate phy_get_max_linkrate_v1_hw(void)
+{
+   return SAS_LINK_RATE_6_0_GBPS;
+}
+
+static void phy_set_linkrate_v1_hw(struct hisi_hba *hisi_hba, int phy_no,
+   struct sas_phy_linkrates *r)
+{
+   u32 prog_phy_link_rate =
+   hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE);
+   struct hisi_sas_phy *phy = _hba->phy[phy_no];
+   struct asd_sas_phy *sas_phy = >sas_phy;
+   int i;
+   enum sas_linkrate min, max;
+   u32 rate_mask = 0;
+
+   if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
+   max = sas_phy->phy->maximum_linkrate;
+   min = r->minimum_linkrate;
+   } else if (r->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) {
+   max = r->maximum_linkrate;
+   min = sas_phy->phy->minimum_linkrate;
+   } else
+   return;
+
+   sas_phy->phy->maximum_linkrate = max;
+   sas_phy->phy->minimum_linkrate = min;
+
+   min -= SAS_LINK_RATE_1_5_GBPS;
+   max -= SAS_LINK_RATE_1_5_GBPS;
+
+   for (i = 0; i <= max; i++)
+   rate_mask |= 1 << (i * 2);
+
+   prog_phy_link_rate &= ~0xff;
+   prog_phy_link_rate |= rate_mask;
+
+   hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
+   prog_phy_link_rate);
+
+   phy_hard_reset_v1_hw(hisi_hba, phy_no);
+}
+
 static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id)
 {
int i, bitmap = 0;
@@ -1818,6 +1861,8 @@ static int hisi_sas_v1_init(struct hisi_hba *hisi_hba)
.phy_enable = enable_phy_v1_hw,
.phy_disable = disable_phy_v1_hw,
.phy_hard_res

[PATCH 05/11] hisi_sas: replace WARN_ON() with dev_warn() for internal abort

2016-11-07 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

Replace WARN_ON() with dev_warn() print when internal abort fails.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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 486aa92..9133238 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -764,7 +764,8 @@ static int hisi_sas_exec_internal_tmf_task(struct 
domain_device *device,
task = NULL;
}
 ex_err:
-   WARN_ON(retry == TASK_RETRY);
+   if (retry == TASK_RETRY)
+   dev_warn(dev, "abort tmf: executing internal task failed!\n");
sas_free_task(task);
return res;
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/11] hisi_sas: alloc queue id of slot according to device id

2016-11-07 Thread John Garry
From: Xiang Chen <chenxian...@hisilicon.com>

Currently slots are allocated from queues in a round-robin fashion.
This causes a problem for internal commands in device mode. For this
mode, we should ensure that the internal abort command is the last
command seen in the host for that device. We can only ensure this when
we place the internal abort command after the preceding commands for
device that in the same queue, as there is no order in which the host
will select a queue to execute the next command.

This queue restriction makes supporting scsi mq more tricky in
the future, but should not be a blocker.

Note: Even though v1 hw does not support internal abort, the
  allocation method is chosen to be the same for consistency.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  4 ++--
 drivers/scsi/hisi_sas/hisi_sas_main.c  |  8 
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 30 --
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 29 -
 4 files changed, 30 insertions(+), 41 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 64046c5..bf59fab 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -150,7 +150,8 @@ struct hisi_sas_hw {
struct domain_device *device);
struct hisi_sas_device *(*alloc_dev)(struct domain_device *device);
void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no);
-   int (*get_free_slot)(struct hisi_hba *hisi_hba, int *q, int *s);
+   int (*get_free_slot)(struct hisi_hba *hisi_hba, u32 dev_id,
+   int *q, int *s);
void (*start_delivery)(struct hisi_hba *hisi_hba);
int (*prep_ssp)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot, int is_tmf,
@@ -207,7 +208,6 @@ struct hisi_hba {
struct hisi_sas_port port[HISI_SAS_MAX_PHYS];
 
int queue_count;
-   int queue;
struct hisi_sas_slot*slot_prep;
 
struct dma_pool *sge_page_pool;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 9afc697..9f5ccc5 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -232,8 +232,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
rc = hisi_sas_slot_index_alloc(hisi_hba, _idx);
if (rc)
goto err_out;
-   rc = hisi_hba->hw->get_free_slot(hisi_hba, _queue,
-_queue_slot);
+   rc = hisi_hba->hw->get_free_slot(hisi_hba, sas_dev->device_id,
+   _queue, _queue_slot);
if (rc)
goto err_out_tag;
 
@@ -987,8 +987,8 @@ static int hisi_sas_query_task(struct sas_task *task)
rc = hisi_sas_slot_index_alloc(hisi_hba, _idx);
if (rc)
goto err_out;
-   rc = hisi_hba->hw->get_free_slot(hisi_hba, _queue,
-_queue_slot);
+   rc = hisi_hba->hw->get_free_slot(hisi_hba, sas_dev->device_id,
+   _queue, _queue_slot);
if (rc)
goto err_out_tag;
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index c0ac49d..bbc5760 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -862,29 +862,23 @@ static int get_wideport_bitmap_v1_hw(struct hisi_hba 
*hisi_hba, int port_id)
  * The callpath to this function and upto writing the write
  * queue pointer should be safe from interruption.
  */
-static int get_free_slot_v1_hw(struct hisi_hba *hisi_hba, int *q, int *s)
+static int get_free_slot_v1_hw(struct hisi_hba *hisi_hba, u32 dev_id,
+   int *q, int *s)
 {
struct device *dev = _hba->pdev->dev;
struct hisi_sas_dq *dq;
u32 r, w;
-   int queue = hisi_hba->queue;
-
-   while (1) {
-   dq = _hba->dq[queue];
-   w = dq->wr_point;
-   r = hisi_sas_read32_relaxed(hisi_hba,
-   DLVRY_Q_0_RD_PTR + (queue * 0x14));
-   if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
-   queue = (queue + 1) % hisi_hba->queue_count;
-   if (queue == hisi_hba->queue) {
-   dev_warn(dev, "could not find free slot\n");
-   return -EAGAIN;
-   }
-   continue;
-   }
-   break;
+   int queue = dev_id % hisi_hba->queue_count;
+
+   dq = _hba->dq[queue];
+   w = dq->wr_point;
+   r = hisi_sas_r

[RFC PATCH] scsi: libsas: fix WARN on device removal

2016-11-03 Thread John Garry
The following patch introduces an annoying WARN
when a device is removed from the SAS topology:
[SCSI] libsas: prevent domain rediscovery competing with ata error handling

A sample WARN is as follows:
[  236.842227] WARNING: CPU: 7 PID: 1520 at fs/sysfs/group.c:237 
sysfs_remove_group+0x90/0x98
[  236.850465] Modules linked in:
[  236.853544]
[  236.855045] CPU: 7 PID: 1520 Comm: kworker/u64:4 Tainted: GW   
4.9.0-rc1-15310-g3fbc29e-dirty #676
[  236.865010] Hardware name: Huawei Taishan 2180 /D03, BIOS Estuary v2.3 D03 
UEFI 08/17/2016
[  236.873249] Workqueue: scsi_wq_0 sas_destruct_devices
[  236.878317] task: 8027ba31b200 task.stack: 8027b9d44000
[  236.884225] PC is at sysfs_remove_group+0x90/0x98
[  236.888920] LR is at sysfs_remove_group+0x90/0x98
[  236.893616] pc : [] lr : [] pstate: 
6145
[  236.900989] sp : 8027b9d47bf0

< snip >

[  237.116463] [] sysfs_remove_group+0x90/0x98
[  237.122197] [] dpm_sysfs_remove+0x58/0x68
[  237.127758] [] device_del+0x40/0x218
[  237.132886] [] device_unregister+0x14/0x2c
[  237.138536] [] bsg_unregister_queue+0x5c/0xa0
[  237.12] [] sas_rphy_remove+0x44/0x80
[  237.149915] [] sas_rphy_delete+0x14/0x28
[  237.155388] [] sas_destruct_devices+0x64/0x98
[  237.161293] [] process_one_work+0x128/0x2e4
[  237.167027] [] worker_thread+0x58/0x434
[  237.172415] [] kthread+0xd4/0xe8
[  237.177198] [] ret_from_fork+0x10/0x50
[  237.182557] sysfs group 'power' not found for kobject 'end_device-0:0:5'

(this can be really huge when an expander is unplugged)

The problem is with the process of sas_port and domain_device
destruction in domain revalidation. There is a 2-stage process:
In domain revalidation (which runs in work queue context), if a
domain_device is discovered to be gone, then the following happens:
- the domain_device is queued for destruction in a separate work item
- the associated sas_port is destroyed immediately

This causes a problem in that the sas_port associated with
a domain_device is destroyed prior the domain_device: this causes
the sysfs WARN. Essentially the "rug has been pulled from underneath".

Also, likewise, when a root port is deformed due to loss of signal,
we have the same issue.

To solve, destroy the sas_port in a separate work item to which
we do the domain revalidation with a new discovery event, as follows:
- When a domain_device is detected to be gone, the domain_device is
  queued for destruction in a separate work item. The associated
  sas_port is also queued for destruction in another separate work item
  (needs to be queued 2nd)
- the domain_device is destroyed
- the sas_port is destroyed
[similar is done for loss of signal event, in sas_port_deformed()].

Fixes: 87c8331fcf72e501c3a3c0cdc5c [SCSI] libsas: prevent domain
rediscovery competing with ata error handling

Signed-off-by: John Garry <john.ga...@huawei.com>

diff --git a/drivers/scsi/libsas/sas_discover.c 
b/drivers/scsi/libsas/sas_discover.c
index 60de662..01d0fe2 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -361,7 +361,7 @@ static void sas_destruct_devices(struct work_struct *work)
 
clear_bit(DISCE_DESTRUCT, >disc.pending);
 
-   list_for_each_entry_safe(dev, n, >destroy_list, disco_list_node) {
+   list_for_each_entry_safe(dev, n, >dev_destroy_list, 
disco_list_node) {
list_del_init(>disco_list_node);
 
sas_remove_children(>rphy->dev);
@@ -383,7 +383,7 @@ void sas_unregister_dev(struct asd_sas_port *port, struct 
domain_device *dev)
 
if (!test_and_set_bit(SAS_DEV_DESTROY, >state)) {
sas_rphy_unlink(dev->rphy);
-   list_move_tail(>disco_list_node, >destroy_list);
+   list_move_tail(>disco_list_node, >dev_destroy_list);
sas_discover_event(dev->port, DISCE_DESTRUCT);
}
 }
@@ -525,6 +525,28 @@ static void sas_revalidate_domain(struct work_struct *work)
mutex_unlock(>disco_mutex);
 }
 
+/* -- Async Port destruct -- */
+static void sas_async_port_destruct(struct work_struct *work)
+{
+   struct sas_discovery_event *ev = to_sas_discovery_event(work);
+   struct asd_sas_port *port = ev->port;
+   struct sas_port *sas_port, *n;
+
+   clear_bit(DISCE_PORT_DESTRUCT, >disc.pending);
+
+   list_for_each_entry_safe(sas_port, n, >port_destroy_list, 
destroy_list) {
+   list_del_init(>port_destroy_list);
+
+   sas_port_delete(sas_port);
+   }
+}
+
+void sas_port_destruct(struct asd_sas_port *port, struct sas_port *sas_port)
+{
+   list_move_tail(_port->destroy_list, >port_destroy_list);
+   sas_discover_event(port, DISCE_PORT_DESTRUCT);
+}
+
 /* -- Events -- */
 
 static void sas_chain_work(struct sas_ha_struct *ha, struct sas_work *sw)
@@ -582,6 +604,7 @@ void sas_init_disc(struct sas_discovery *disc,

Re: [bug report] scsi: hisi_sas: add internal abort to hisi_sas_abort_task()

2016-10-12 Thread John Garry

On 12/10/2016 14:12, Dan Carpenter wrote:

Hello John Garry,

The patch dc8a49cabc73: "scsi: hisi_sas: add internal abort to
hisi_sas_abort_task()" from Aug 24, 2016, leads to the following
static checker warning:

drivers/scsi/hisi_sas/hisi_sas_main.c:848 hisi_sas_abort_task()
error: we previously assumed 'slot' could be null (see line 847)

drivers/scsi/hisi_sas/hisi_sas_main.c
809  spin_unlock_irqrestore(>task_state_lock, flags);
810  sas_dev->dev_status = HISI_SAS_DEV_EH;
811  if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
 ^^^
We assume that ->lldd_task can be NULL.

812  struct scsi_cmnd *cmnd = task->uldd_task;
813  struct hisi_sas_slot *slot = task->lldd_task;
814  u32 tag = slot->idx;
815
816  int_to_scsilun(cmnd->device->lun, );
817  tmf_task.tmf = TMF_ABORT_TASK;
818  tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag);
819
820  rc = hisi_sas_debug_issue_ssp_tmf(task->dev, 
lun.scsi_lun,
821_task);
822
823  /* if successful, clear the task and callback 
forwards.*/
824  if (rc == TMF_RESP_FUNC_COMPLETE) {
825  if (task->lldd_task) {
826  struct hisi_sas_slot *slot;
827
828  slot = _hba->slot_info
829  
[tmf_task.tag_of_task_to_be_managed];
830  spin_lock_irqsave(_hba->lock, 
flags);
831  hisi_hba->hw->slot_complete(hisi_hba, 
slot, 1);
832  
spin_unlock_irqrestore(_hba->lock, flags);
833  }
834  }
835
836  hisi_sas_internal_task_abort(hisi_hba, device,
837   HISI_SAS_INT_ABT_CMD, 
tag);
838  } else if (task->task_proto & SAS_PROTOCOL_SATA ||
839  task->task_proto & SAS_PROTOCOL_STP) {
840  if (task->dev->dev_type == SAS_SATA_DEV) {
841  hisi_sas_internal_task_abort(hisi_hba, device,
842   
HISI_SAS_INT_ABT_DEV, 0);
843  rc = TMF_RESP_FUNC_COMPLETE;
844  }
845  } else if (task->task_proto & SAS_PROTOCOL_SMP) {
846  /* SMP */
847  struct hisi_sas_slot *slot = task->lldd_task;

We assign it to slot.


I will check this.

Thanks,
John



848  u32 tag = slot->idx;
   ^
slot dereferenced without checking.

849
850  hisi_sas_internal_task_abort(hisi_hba, device,
851   HISI_SAS_INT_ABT_CMD, 
tag);
852  }



regards,
dan carpenter

.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/3] devicetree: bindings: scsi: hisi_sas add hip07 support

2016-10-04 Thread John Garry
Add support for hip07 chipset to hisi_sas controller.

Chipset hip07 has v2 hw.

Signed-off-by: John Garry <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 Documentation/devicetree/bindings/scsi/hisilicon-sas.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt 
b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
index bf2411f..2a42a32 100644
--- a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
+++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
@@ -6,6 +6,7 @@ Main node required properties:
   - compatible : value should be as follows:
(a) "hisilicon,hip05-sas-v1" for v1 hw in hip05 chipset
(b) "hisilicon,hip06-sas-v2" for v2 hw in hip06 chipset
+   (c) "hisilicon,hip07-sas-v2" for v2 hw in hip07 chipset
   - sas-addr : array of 8 bytes for host SAS address
   - reg : Address and length of the SAS register
   - hisilicon,sas-syscon: phandle of syscon used for sas control
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 0/3] hisi_sas add hip07 support

2016-10-04 Thread John Garry
This patchset introduces support for hip07 SoC.

The hip07 SoC has the same v2 hw as in hip06.

Support for different reference clock is required
as some SAS registers need be programmed
differently, depending on the refclock rate.

Related patchset:
- https://patchwork.ozlabs.org/patch/665172/
  Once 4.9-rc1 is released, the D03 dts can be
  updated for the refclock.
  Note: there will be only 1 D03 dts, UEFI will update
the refclock rate for that board in the fdt at
boottime.

Differences to v1:
- dropped sas-v2 quirk amt for hip07

John Garry (3):
  devicetree: bindings: scsi: hisi_sas add hip07 support
  hisi_sas: add device tree support for hip07
  hisi_sas: add v2 hw support for different refclk

 Documentation/devicetree/bindings/scsi/hisilicon-sas.txt | 1 +
 drivers/scsi/hisi_sas/hisi_sas.h | 2 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c| 7 +++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c   | 5 -
 4 files changed, 14 insertions(+), 1 deletion(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 3/3] hisi_sas: add v2 hw support for different refclk

2016-10-04 Thread John Garry
The hip06 D03 and hip07 D05 boards have different
reference clock frequencies for the SAS controller.

Register PHY_CTRL needs to be programmed differently
according to this frequency, so add support for this.

The default register setting in PHY_CTRL is for 50MHz,
so only update this register when the refclk frequency
is 66MHz.

For ACPI we expect the _RST handler to set the correct
value for PHY_CTRL (we're forced to take different
approach for DT and ACPI as ACPI does not support
fixed-clock device).

Signed-off-by: John Garry <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 drivers/scsi/hisi_sas/hisi_sas.h   | 2 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 7 +++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 +++-
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 72c9852..64046c5 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -13,6 +13,7 @@
 #define _HISI_SAS_H_
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -183,6 +184,7 @@ struct hisi_hba {
u32 ctrl_reset_reg;
u32 ctrl_reset_sts_reg;
u32 ctrl_clock_ena_reg;
+   u32 refclk_frequency_mhz;
u8 sas_addr[SAS_ADDR_SIZE];
 
int n_phy;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 2f872f7..9afc697 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1396,6 +1396,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
struct hisi_hba *hisi_hba;
struct device *dev = >dev;
struct device_node *np = pdev->dev.of_node;
+   struct clk *refclk;
 
shost = scsi_host_alloc(_sas_sht, sizeof(*hisi_hba));
if (!shost)
@@ -1432,6 +1433,12 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
goto err_out;
}
 
+   refclk = devm_clk_get(>dev, NULL);
+   if (IS_ERR(refclk))
+   dev_info(dev, "no ref clk property\n");
+   else
+   hisi_hba->refclk_frequency_mhz = clk_get_rate(refclk) / 100;
+
if (device_property_read_u32(dev, "phy-count", _hba->n_phy))
goto err_out;
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 758e06f..0763b47 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -836,7 +836,9 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
hisi_sas_phy_write32(hisi_hba, i, SL_RX_BCAST_CHK_MSK, 0x0);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT_COAL_EN, 0x0);
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x0);
-   hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL, 0x199B694);
+   if (hisi_hba->refclk_frequency_mhz == 66)
+   hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL, 0x199B694);
+   /* else, do nothing -> leave it how you found it */
}
 
for (i = 0; i < hisi_hba->queue_count; i++) {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/3] hisi_sas: add device tree support for hip07

2016-10-04 Thread John Garry
Chipset hip07 incorporates v2 hw.

Signed-off-by: John Garry <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 9825a3f..758e06f 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2319,6 +2319,7 @@ static int hisi_sas_v2_remove(struct platform_device 
*pdev)
 
 static const struct of_device_id sas_v2_of_match[] = {
{ .compatible = "hisilicon,hip06-sas-v2",},
+   { .compatible = "hisilicon,hip07-sas-v2",},
{},
 };
 MODULE_DEVICE_TABLE(of, sas_v2_of_match);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/3] devicetree: bindings: scsi: hisi_sas hip07 support

2016-09-24 Thread John Garry

On 23/09/2016 19:36, Rob Herring wrote:

On Tue, Sep 20, 2016 at 06:48:58PM +0800, John Garry wrote:

Add support for hip07 chipset to bindings.

Chipset hip07 has v2 hw.

The sas-v2 quirk amt is expanded to cover hip07.

Signed-off-by: John Garry <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 Documentation/devicetree/bindings/scsi/hisilicon-sas.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt 
b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
index bf2411f..e604527 100644
--- a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
+++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
@@ -6,6 +6,7 @@ Main node required properties:
   - compatible : value should be as follows:
(a) "hisilicon,hip05-sas-v1" for v1 hw in hip05 chipset
(b) "hisilicon,hip06-sas-v2" for v2 hw in hip06 chipset
+   (c) "hisilicon,hip07-sas-v2" for v2 hw in hip07 chipset
   - sas-addr : array of 8 bytes for host SAS address
   - reg : Address and length of the SAS register
   - hisilicon,sas-syscon: phandle of syscon used for sas control
@@ -47,7 +48,7 @@ Main node required properties:
increasing order.

 Optional main node properties:
- - hip06-sas-v2-quirk-amt : when set, indicates that the v2 controller has the
+ - hip06/7-sas-v2-quirk-amt : when set, indicates that the v2 controller has 
the


Just use the existing property name for hip07.


OK, but you mean existing hip06 property (hip06-sas-v2-quirk-amt), right?




"am-max-transmissions" limitation.

 Example:
--
1.9.1



.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/3] devicetree: bindings: scsi: hisi_sas hip07 support

2016-09-20 Thread John Garry
Add support for hip07 chipset to bindings.

Chipset hip07 has v2 hw.

The sas-v2 quirk amt is expanded to cover hip07.

Signed-off-by: John Garry <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 Documentation/devicetree/bindings/scsi/hisilicon-sas.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt 
b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
index bf2411f..e604527 100644
--- a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
+++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
@@ -6,6 +6,7 @@ Main node required properties:
   - compatible : value should be as follows:
(a) "hisilicon,hip05-sas-v1" for v1 hw in hip05 chipset
(b) "hisilicon,hip06-sas-v2" for v2 hw in hip06 chipset
+   (c) "hisilicon,hip07-sas-v2" for v2 hw in hip07 chipset
   - sas-addr : array of 8 bytes for host SAS address
   - reg : Address and length of the SAS register
   - hisilicon,sas-syscon: phandle of syscon used for sas control
@@ -47,7 +48,7 @@ Main node required properties:
increasing order.
 
 Optional main node properties:
- - hip06-sas-v2-quirk-amt : when set, indicates that the v2 controller has the
+ - hip06/7-sas-v2-quirk-amt : when set, indicates that the v2 controller has 
the
"am-max-transmissions" limitation.
 
 Example:
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/3] hisi_sas: add v2 hw support for different refclk

2016-09-20 Thread John Garry
Some hip06 D03 and hip07 D05 boards have different
reference clock frequencies for the SAS controller.

Register PHY_CTRL needs to be programmed differently
according to this frequency, so add support for this.

The default register setting in PHY_CTRL is for 50MHz,
so only update this register when the refclk frequency
is 66MHz.

The register cannot be set according to hip06 or hip07
as some variants of hip06 D03 board are 50MHz and some
are 66MHz (early editions). All hip07 D05 are 50MHz.

For ACPI we expect the _RST handler to set the correct
value for PHY_CTRL (we take an alternate approach for
DT and ACPI as ACPI does not support fixed-clock device
type).

Signed-off-by: John Garry <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 drivers/scsi/hisi_sas/hisi_sas.h   | 2 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 7 +++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 +++-
 3 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 72c9852..64046c5 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -13,6 +13,7 @@
 #define _HISI_SAS_H_
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -183,6 +184,7 @@ struct hisi_hba {
u32 ctrl_reset_reg;
u32 ctrl_reset_sts_reg;
u32 ctrl_clock_ena_reg;
+   u32 refclk_frequency_mhz;
u8 sas_addr[SAS_ADDR_SIZE];
 
int n_phy;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 2f872f7..0bc3165 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1396,6 +1396,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
struct hisi_hba *hisi_hba;
struct device *dev = >dev;
struct device_node *np = pdev->dev.of_node;
+   struct clk *refclk;
 
shost = scsi_host_alloc(_sas_sht, sizeof(*hisi_hba));
if (!shost)
@@ -1432,6 +1433,12 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
goto err_out;
}
 
+   refclk = devm_clk_get(>dev, NULL);
+   if (IS_ERR(refclk))
+   dev_info(dev, "no ref clk property\n");
+   else
+   hisi_hba->refclk_frequency_mhz = clk_get_rate(refclk) / 100;
+
if (device_property_read_u32(dev, "phy-count", _hba->n_phy))
goto err_out;
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index c1e3aa7..7014d99 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -837,7 +837,9 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
hisi_sas_phy_write32(hisi_hba, i, SL_RX_BCAST_CHK_MSK, 0x0);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT_COAL_EN, 0x0);
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_OOB_RESTART_MSK, 0x0);
-   hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL, 0x199B694);
+   if (hisi_hba->refclk_frequency_mhz == 66)
+   hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL, 0x199B694);
+   /* else, do nothing -> leave it how you found it */
}
 
for (i = 0; i < hisi_hba->queue_count; i++) {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/3] hisi_sas add hip07 support

2016-09-20 Thread John Garry
This patchset introduces support for hip07 SoC.

The hip07 SoC has the same v2 hw as in hip06.

Support for different reference clock is required
as some SAS registers need be programmed
differently, depending on the refclock rate.

Related patchset:
- https://patchwork.ozlabs.org/patch/665172/
  Once 4.9-rc1 is released, the D03 dts can be
  updated for the refclock.
  Note: there will be only 1 D03 dts, UEFI will update
the refclock rate for that board in the fdt at
boot time.

John Garry (3):
  devicetree: bindings: scsi: hisi_sas add hip07 support
  hisi_sas: add device tree support for hip07
  hisi_sas: add v2 hw support for different refclk

 Documentation/devicetree/bindings/scsi/hisilicon-sas.txt | 3 ++-
 drivers/scsi/hisi_sas/hisi_sas.h | 2 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c| 7 +++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c   | 8 ++--
 4 files changed, 17 insertions(+), 3 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/3] hisi_sas: add device tree support for hip07

2016-09-20 Thread John Garry
Chipset hip07 incorporates v2 hw.

Signed-off-by: John Garry <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 9825a3f..c1e3aa7 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -777,7 +777,8 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
/* Global registers init */
 
/* Deal with am-max-transmissions quirk */
-   if (device_property_present(dev, "hip06-sas-v2-quirk-amt")) {
+   if (device_property_present(dev, "hip06-sas-v2-quirk-amt") ||
+   device_property_present(dev, "hip07-sas-v2-quirk-amt")) {
hisi_sas_write32(hisi_hba, AM_CFG_MAX_TRANS, 0x2020);
hisi_sas_write32(hisi_hba, AM_CFG_SINGLE_PORT_MAX_TRANS,
 0x2020);
@@ -2319,6 +2320,7 @@ static int hisi_sas_v2_remove(struct platform_device 
*pdev)
 
 static const struct of_device_id sas_v2_of_match[] = {
{ .compatible = "hisilicon,hip06-sas-v2",},
+   { .compatible = "hisilicon,hip07-sas-v2",},
{},
 };
 MODULE_DEVICE_TABLE(of, sas_v2_of_match);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] [SCSI] wd719x: Avoid calling request_firmware under spinlock

2016-09-15 Thread John Garry

On 15/09/2016 15:08, John Garry wrote:

On 15/09/2016 14:48, Vaishali Thakkar wrote:

It is preferrable to use request_firmware where sleeping is
allowed. Using it under spinlock can cause blocking. Here,
the function wd719x_chip_init calls request_firmware while
holding a spinlock. So, let's access it outside the spinlock.

Coccinelle is used to detect the issue.

Signed-off-by: Vaishali Thakkar <vaishali.thak...@oracle.com>
---
Please note that the patch is compile-tested only. And this change
may require driver testing.
---
 drivers/scsi/wd719x.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/wd719x.c b/drivers/scsi/wd719x.c
index e3da1a2..b8e57f3 100644
--- a/drivers/scsi/wd719x.c
+++ b/drivers/scsi/wd719x.c
@@ -518,13 +518,14 @@ static int wd719x_host_reset(struct scsi_cmnd *cmd)
 int result;

 dev_info(>pdev->dev, "host reset requested\n");
-spin_lock_irqsave(wd->sh->host_lock, flags);
+


In the version of code I have flags is only used for this spinlock, so
can flags be removed?


I see we're just relocating the spinlock, so ignore me




 /* Try to reinit the RISC */
 if (wd719x_chip_init(wd) == 0)
 result = SUCCESS;
 else
 result = FAILED;

+spin_lock_irqsave(wd->sh->host_lock, flags);
 /* flush all SCBs */
 list_for_each_entry_safe(scb, tmp, >active_scbs, list) {
 struct scsi_cmnd *tmp_cmd = scb->cmd;




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] [SCSI] wd719x: Avoid calling request_firmware under spinlock

2016-09-15 Thread John Garry

On 15/09/2016 14:48, Vaishali Thakkar wrote:

It is preferrable to use request_firmware where sleeping is
allowed. Using it under spinlock can cause blocking. Here,
the function wd719x_chip_init calls request_firmware while
holding a spinlock. So, let's access it outside the spinlock.

Coccinelle is used to detect the issue.

Signed-off-by: Vaishali Thakkar 
---
Please note that the patch is compile-tested only. And this change
may require driver testing.
---
 drivers/scsi/wd719x.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/wd719x.c b/drivers/scsi/wd719x.c
index e3da1a2..b8e57f3 100644
--- a/drivers/scsi/wd719x.c
+++ b/drivers/scsi/wd719x.c
@@ -518,13 +518,14 @@ static int wd719x_host_reset(struct scsi_cmnd *cmd)
int result;

dev_info(>pdev->dev, "host reset requested\n");
-   spin_lock_irqsave(wd->sh->host_lock, flags);
+


In the version of code I have flags is only used for this spinlock, so 
can flags be removed?



/* Try to reinit the RISC */
if (wd719x_chip_init(wd) == 0)
result = SUCCESS;
else
result = FAILED;

+   spin_lock_irqsave(wd->sh->host_lock, flags);
/* flush all SCBs */
list_for_each_entry_safe(scb, tmp, >active_scbs, list) {
struct scsi_cmnd *tmp_cmd = scb->cmd;




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 01/15] hisi_sas: save completion queue read pointer

2016-09-06 Thread John Garry
Optimise by saving an avoidable read in the cq
interrupt.
The queue read pointer will only be updated
by software, so don't bother re-reading
what was already written in the previous interrupt.

Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas.h   | 1 +
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 6 ++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 5 ++---
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index ca55ec2..9410335 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -94,6 +94,7 @@ struct hisi_sas_port {
 
 struct hisi_sas_cq {
struct hisi_hba *hisi_hba;
+   int rd_point;
int id;
 };
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 1abbc2e..3b31b20 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1565,14 +1565,11 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p)
struct hisi_sas_complete_v1_hdr *complete_queue =
(struct hisi_sas_complete_v1_hdr *)
hisi_hba->complete_hdr[queue];
-   u32 irq_value, rd_point, wr_point;
+   u32 irq_value, rd_point = cq->rd_point, wr_point;
 
irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC);
 
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
-
-   rd_point = hisi_sas_read32(hisi_hba,
-   COMPL_Q_0_RD_PTR + (0x14 * queue));
wr_point = hisi_sas_read32(hisi_hba,
COMPL_Q_0_WR_PTR + (0x14 * queue));
 
@@ -1600,6 +1597,7 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p)
}
 
/* update rd_point */
+   cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
 
return IRQ_HANDLED;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index bf9b693..11006c9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2049,7 +2049,7 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
struct hisi_sas_slot *slot;
struct hisi_sas_itct *itct;
struct hisi_sas_complete_v2_hdr *complete_queue;
-   u32 irq_value, rd_point, wr_point, dev_id;
+   u32 irq_value, rd_point = cq->rd_point, wr_point, dev_id;
int queue = cq->id;
 
complete_queue = hisi_hba->complete_hdr[queue];
@@ -2057,8 +2057,6 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
 
hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
 
-   rd_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_RD_PTR +
-  (0x14 * queue));
wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
   (0x14 * queue));
 
@@ -2106,6 +2104,7 @@ static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
}
 
/* update rd_point */
+   cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
return IRQ_HANDLED;
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 09/15] hisi_sas: set dma mask before allocate DMA memory

2016-09-06 Thread John Garry
The device DMA mask was being set after the bulk of the
DMA allocations in the driver init, so potentially
DMA allocates fail.
To resolve, relocate before allocating the DMA memory when
initialising the driver.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 13 ++---
 1 file changed, 6 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index d58e223..2f872f7 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1439,6 +1439,12 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
 _hba->queue_count))
goto err_out;
 
+   if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) &&
+   dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
+   dev_err(dev, "No usable DMA addressing method\n");
+   goto err_out;
+   }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hisi_hba->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(hisi_hba->regs))
@@ -1486,13 +1492,6 @@ int hisi_sas_probe(struct platform_device *pdev,
hisi_hba = shost_priv(shost);
platform_set_drvdata(pdev, sha);
 
-   if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) &&
-   dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
-   dev_err(dev, "No usable DMA addressing method\n");
-   rc = -EIO;
-   goto err_out_ha;
-   }
-
phy_nr = port_nr = hisi_hba->n_phy;
 
arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/15] hisi_sas: save delivery queue write pointer

2016-09-06 Thread John Garry
Optimise by saving an avoidable read in the
get_free_slot function.
The delivery queue write pointer will only be
updated by software, so don't bother re-reading
what was already written in the previous call
to start_delivery function.

Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  7 +++
 drivers/scsi/hisi_sas/hisi_sas_main.c  |  5 +
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 12 +++-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  9 ++---
 4 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 9410335..72c9852 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -98,6 +98,12 @@ struct hisi_sas_cq {
int id;
 };
 
+struct hisi_sas_dq {
+   struct hisi_hba *hisi_hba;
+   int wr_point;
+   int id;
+};
+
 struct hisi_sas_device {
enum sas_device_typedev_type;
struct hisi_hba *hisi_hba;
@@ -194,6 +200,7 @@ struct hisi_hba {
struct Scsi_Host *shost;
 
struct hisi_sas_cq cq[HISI_SAS_MAX_QUEUES];
+   struct hisi_sas_dq dq[HISI_SAS_MAX_QUEUES];
struct hisi_sas_phy phy[HISI_SAS_MAX_PHYS];
struct hisi_sas_port port[HISI_SAS_MAX_PHYS];
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 85c73d3..5d56576 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1239,11 +1239,16 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, 
struct Scsi_Host *shost)
 
for (i = 0; i < hisi_hba->queue_count; i++) {
struct hisi_sas_cq *cq = _hba->cq[i];
+   struct hisi_sas_dq *dq = _hba->dq[i];
 
/* Completion queue structure */
cq->id = i;
cq->hisi_hba = hisi_hba;
 
+   /* Delivery queue structure */
+   dq->id = i;
+   dq->hisi_hba = hisi_hba;
+
/* Delivery queue */
s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
hisi_hba->cmd_hdr[i] = dma_alloc_coherent(dev, s,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 3b31b20..b537464 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -875,12 +875,13 @@ static int get_wideport_bitmap_v1_hw(struct hisi_hba 
*hisi_hba, int port_id)
 static int get_free_slot_v1_hw(struct hisi_hba *hisi_hba, int *q, int *s)
 {
struct device *dev = _hba->pdev->dev;
+   struct hisi_sas_dq *dq;
u32 r, w;
int queue = hisi_hba->queue;
 
while (1) {
-   w = hisi_sas_read32_relaxed(hisi_hba,
-   DLVRY_Q_0_WR_PTR + (queue * 0x14));
+   dq = _hba->dq[queue];
+   w = dq->wr_point;
r = hisi_sas_read32_relaxed(hisi_hba,
DLVRY_Q_0_RD_PTR + (queue * 0x14));
if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
@@ -903,10 +904,11 @@ static void start_delivery_v1_hw(struct hisi_hba 
*hisi_hba)
 {
int dlvry_queue = hisi_hba->slot_prep->dlvry_queue;
int dlvry_queue_slot = hisi_hba->slot_prep->dlvry_queue_slot;
+   struct hisi_sas_dq *dq = _hba->dq[dlvry_queue];
 
-   hisi_sas_write32(hisi_hba,
-DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
-++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS);
+   dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS;
+   hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
+dq->wr_point);
 }
 
 static int prep_prd_sge_v1_hw(struct hisi_hba *hisi_hba,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 11006c9..e0c124b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1023,12 +1023,13 @@ static int get_wideport_bitmap_v2_hw(struct hisi_hba 
*hisi_hba, int port_id)
 static int get_free_slot_v2_hw(struct hisi_hba *hisi_hba, int *q, int *s)
 {
struct device *dev = _hba->pdev->dev;
+   struct hisi_sas_dq *dq;
u32 r, w;
int queue = hisi_hba->queue;
 
while (1) {
-   w = hisi_sas_read32_relaxed(hisi_hba,
-   DLVRY_Q_0_WR_PTR + (queue * 0x14));
+   dq = _hba->dq[queue];
+   w = dq->wr_point;
r = hisi_sas_read32_relaxed(hisi_hba,
DLVRY_Q_0_RD_PTR + (queue * 0x14));
if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
@@ -1051,9 +1052,11 @@ static void start_delivery_v2_hw(struct hisi_hba 
*hisi_hba)
 {
int dlvry_queue = hisi_hba->slot_

[PATCH 04/15] hisi_sas: only zero slot memory when reused

2016-09-06 Thread John Garry
Currently the slot memory is zeroed when it is
freed and also when it is reused, like in
hisi_sas_task_prep(). Optimise by avoiding the
redundant zeroing in the free.

Signed-off-by: John Garry <john.ga...@huawei.com>
---
 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 5d56576..0e48751 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -97,7 +97,7 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, 
struct sas_task *task,
slot->task = NULL;
slot->port = NULL;
hisi_sas_slot_index_free(hisi_hba, slot->idx);
-   memset(slot, 0, sizeof(*slot));
+   /* slot memory is fully zeroed when it is reused */
 }
 EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 00/15] hisi_sas misc fixes and minor optimisations

2016-09-06 Thread John Garry
This patchset introdcues some minor bug fixes and
optimisations for v1+v2 hw.

No new functional features are introduced in this patchset.

John Garry (15):
  hisi_sas: save completion queue read pointer
  hisi_sas: save delivery queue write pointer
  hisi_sas: keep CHL_INT2 masked for v2 HW
  hisi_sas: only zero slot memory when reused
  hisi_sas: use safe BITS_PER_BYTE for slot tag size calculation
  hisi_sas: disable dlvry queues once at reset for v2 hw
  hisi_sas: fix phy8 linkrate calculation in phy_up_v2_hw()
  hisi_sas: fix a potential warning for sata disk ejection
  hisi_sas: set dma mask before allocate DMA memory
  hisi_sas: fix HBA SAS addr endianness for v2 hw
  hisi_sas: fix HBA SAS addr endianness for v1 hw
  hisi_sas: remove init_id_frame_v2_hw()
  hisi_sas: remove init_id_frame_v1_hw()
  hisi_sas: add missing SATA pending device type to v2 hw
  hisi_sas: send three identify before PHY up

 drivers/scsi/hisi_sas/hisi_sas.h   |  8 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 48 ++---
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 36 +++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 66 --
 4 files changed, 70 insertions(+), 88 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 15/15] hisi_sas: send three identify before phy up

2016-09-06 Thread John Garry
When the v2 hw is attached with many disks through
an expander, there may be OOB reset resulting in a PHY
going down after the speed is negotiated (very low
probability).

This issue is resolved by modifying the link control
registers to send three identify frames before the PHY
is ready (according to 6.10.3.3.2 in SAS 3.0 spec) and
close ready when the PHY is down.

Signed-off-by: NengLong Zhao <zhaonengl...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 20 
 1 file changed, 16 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 735ebff..9825a3f 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -117,6 +117,8 @@
 #define SL_CONTROL (PORT_BASE + 0x94)
 #define SL_CONTROL_NOTIFY_EN_OFF   0
 #define SL_CONTROL_NOTIFY_EN_MSK   (0x1 << SL_CONTROL_NOTIFY_EN_OFF)
+#define SL_CONTROL_CTA_OFF 17
+#define SL_CONTROL_CTA_MSK (0x1 << SL_CONTROL_CTA_OFF)
 #define TX_ID_DWORD0   (PORT_BASE + 0x9c)
 #define TX_ID_DWORD1   (PORT_BASE + 0xa0)
 #define TX_ID_DWORD2   (PORT_BASE + 0xa4)
@@ -124,6 +126,9 @@
 #define TX_ID_DWORD4   (PORT_BASE + 0xaC)
 #define TX_ID_DWORD5   (PORT_BASE + 0xb0)
 #define TX_ID_DWORD6   (PORT_BASE + 0xb4)
+#define TXID_AUTO  (PORT_BASE + 0xb8)
+#define TXID_AUTO_CT3_OFF  1
+#define TXID_AUTO_CT3_MSK  (0x1 << TXID_AUTO_CT3_OFF)
 #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4)
 #define RX_IDAF_DWORD1 (PORT_BASE + 0xc8)
 #define RX_IDAF_DWORD2 (PORT_BASE + 0xcc)
@@ -814,6 +819,8 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855);
hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, 0x30b9908);
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, CHL_INT0, 0x);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0x);
@@ -1901,16 +1908,21 @@ end:
 static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
 {
int res = 0;
-   u32 phy_cfg, phy_state;
+   u32 phy_state, sl_ctrl, txid_auto;
 
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);
 
-   phy_cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
-
phy_state = hisi_sas_read32(hisi_hba, PHY_STATE);
-
hisi_sas_phy_down(hisi_hba, phy_no, (phy_state & 1 << phy_no) ? 1 : 0);
 
+   sl_ctrl = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
+   hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL,
+sl_ctrl & ~SL_CONTROL_CTA_MSK);
+
+   txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO);
+   hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
+txid_auto | TXID_AUTO_CT3_MSK);
+
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);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/15] hisi_sas: fix a potential warning for sata disk ejection

2016-09-06 Thread John Garry
If hisi_sas_task_prep() fails for a SATA device due to PHY
down, we return a failure to libata and also call task_done(),
which will cause ata_qc_complete() to be called twice:
- first call from hisi_sas_task_prep(), which will clear flag
  ATA_QCFLAG_ACTIVE
- ata_qc_complete() called from libata
The warning call trace is as follows:

[  117.070206] [] __ata_qc_complete+0xf4/0x11c
[  117.070208] [] ata_qc_complete+0x180/0x200
[  117.070210] [] ata_qc_issue+0x110/0x354
[  117.070212] [] ata_exec_internal_sg+0x240/0x4d0
[  117.070214] [] ata_exec_internal+0x60/0xa0
[  117.070217] [] ata_read_log_page+0x188/0x1b4
[  117.070218] [] ata_eh_analyze_ncq_error+0xa8/0x274
[  117.070220] [] ata_eh_link_autopsy+0x94/0x8c8
[  117.070222] [] ata_eh_autopsy+0x34/0xe8
[  117.070223] [] ata_do_eh+0x28/0xc0
[  117.070225] [] ata_std_error_handler+0x3c/0x84
[  117.070227] [] ata_scsi_port_error_handler+0x480/0x674
[  117.070230] [] async_sas_ata_eh+0x44/0x78
[  117.070231] [] async_run_entry_fn+0x40/0x104
[  117.070234] [] process_one_work+0x128/0x2f0
[  117.070235] [] worker_thread+0x58/0x434
[  117.070237] [] kthread+0xd4/0xe8
[  117.070240] [] ret_from_fork+0x10/0x40

The issue is resolved by simply returning a failure status
code to the upper layer.

Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
Signed-off-by: John Garry <john.ga...@huawei.com>
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 26 ++
 1 file changed, 6 insertions(+), 20 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index dcb17a3..d58e223 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -205,26 +205,12 @@ static int hisi_sas_task_prep(struct sas_task *task, 
struct hisi_hba *hisi_hba,
}
port = device->port->lldd_port;
if (port && !port->port_attached) {
-   if (sas_protocol_ata(task->task_proto)) {
-   struct task_status_struct *ts = >task_status;
-
-   dev_info(dev,
-"task prep: SATA/STP port%d not attach 
device\n",
-device->port->id);
-   ts->resp = SAS_TASK_COMPLETE;
-   ts->stat = SAS_PHY_DOWN;
-   task->task_done(task);
-   } else {
-   struct task_status_struct *ts = >task_status;
-
-   dev_info(dev,
-"task prep: SAS port%d does not attach 
device\n",
-device->port->id);
-   ts->resp = SAS_TASK_UNDELIVERED;
-   ts->stat = SAS_PHY_DOWN;
-   task->task_done(task);
-   }
-   return 0;
+   dev_info(dev, "task prep: %s port%d not attach device\n",
+(sas_protocol_ata(task->task_proto)) ?
+"SATA/STP" : "SAS",
+device->port->id);
+
+   return SAS_PHY_DOWN;
}
 
if (!sas_protocol_ata(task->task_proto)) {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/15] hisi_sas: fix HBA SAS addr endianness for v2 hw

2016-09-06 Thread John Garry
The endianness for the SAS address in the TX_ID_DWORD
registers is set incorrectly.
We see errors like this in the boot log:
[7.583284] sas: target proto 0x0 at 5d1108e7923f:0x1f not handled

This is due to the host SAS addr not matching the PHY SAS
addr in the expander host-attached phy discovery responses.

To fix, we byte swap the SAS addr from BE to LE (which is
the endianness of the SAS controller).

Signed-off-by: John Garry <john.ga...@huawei.com>
Signed-off-by: Xiang Chen <chenxian...@hisilicon.com>
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 8 
 1 file changed, 4 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 ae3..ce84211 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -562,13 +562,13 @@ static void config_id_frame_v2_hw(struct hisi_hba 
*hisi_hba, int phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0,
__swab32(identify_buffer[0]));
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1,
-   identify_buffer[2]);
+   __swab32(identify_buffer[1]));
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2,
-   identify_buffer[1]);
+   __swab32(identify_buffer[2]));
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3,
-   identify_buffer[4]);
+   __swab32(identify_buffer[3]));
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4,
-   identify_buffer[3]);
+   __swab32(identify_buffer[4]));
hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5,
__swab32(identify_buffer[5]));
 }
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


<    1   2   3   4   5   6   7   8   >