[PATCH V2 2/4] pm80xx : Corrected dma_unmap_sg() parameter.

2018-09-11 Thread Viswas G
From: Deepak Ukey 

For the function dma_unmap_sg(), the  parameter should be
number of elements in the scatter list prior to the mapping, not
after the mapping.

Signed-off-by: Deepak Ukey 
Signed-off-by: Viswas G 
Acked-by: Jack Wang  
---
 drivers/scsi/pm8001/pm8001_sas.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index d8249675371e..e063faad66f5 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -488,7 +488,7 @@ static int pm8001_task_exec(struct sas_task *task,
dev_printk(KERN_ERR, pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc);
if (!sas_protocol_ata(t->task_proto))
if (n_elem)
-   dma_unmap_sg(pm8001_ha->dev, t->scatter, n_elem,
+   dma_unmap_sg(pm8001_ha->dev, t->scatter, t->num_scatter,
t->data_dir);
 out_done:
spin_unlock_irqrestore(_ha->lock, flags);
-- 
2.19.0-rc1



[PATCH V2 3/4] pm80xx : Fixed system hang issue during kexec boot.

2018-09-11 Thread Viswas G
From: Deepak Ukey 

When the firmware is not responding, execution of kexec boot
causes a system hang. When firmware assertion happened, driver
get notified with interrupt vector updated in MPI configuration
table. Then, the driver will read scratchpad register and
set controller_fatal_error flag to true.

Signed-off-by: Deepak Ukey 
Signed-off-by: Viswas G 
Acked-by: Jack Wang  
---
 drivers/scsi/pm8001/pm8001_hwi.c |  6 +++
 drivers/scsi/pm8001/pm8001_sas.c |  7 +++
 drivers/scsi/pm8001/pm8001_sas.h |  1 +
 drivers/scsi/pm8001/pm80xx_hwi.c | 80 +---
 drivers/scsi/pm8001/pm80xx_hwi.h |  3 ++
 5 files changed, 91 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index a14bf50a76d7..e37ab9789ba6 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1479,6 +1479,12 @@ u32 pm8001_mpi_msg_consume(struct pm8001_hba_info 
*pm8001_ha,
} else {
u32 producer_index;
void *pi_virt = circularQ->pi_virt;
+   /* spurious interrupt during setup if
+* kexec-ing and driver doing a doorbell access
+* with the pre-kexec oq interrupt setup
+*/
+   if (!pi_virt)
+   break;
/* Update the producer index from SPC */
producer_index = pm8001_read_32(pi_virt);
circularQ->producer_index = cpu_to_le32(producer_index);
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index e063faad66f5..b1e7d2699311 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -396,6 +396,13 @@ static int pm8001_task_exec(struct sas_task *task,
return 0;
}
pm8001_ha = pm8001_find_ha_by_dev(task->dev);
+   if (pm8001_ha->controller_fatal_error) {
+   struct task_status_struct *ts = >task_status;
+
+   ts->resp = SAS_TASK_UNDELIVERED;
+   t->task_done(t);
+   return 0;
+   }
PM8001_IO_DBG(pm8001_ha, pm8001_printk("pm8001_task_exec device \n "));
spin_lock_irqsave(_ha->lock, flags);
do {
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 80b4dd6df0c2..1816e351071f 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -538,6 +538,7 @@ struct pm8001_hba_info {
u32 logging_level;
u32 fw_status;
u32 smp_exp_mode;
+   boolcontroller_fatal_error;
const struct firmware   *fw_image;
struct isr_param irq_vector[PM8001_MAX_MSIX_VEC];
u32 reset_in_progress;
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 91ff6a44e9d9..b641875b8ad7 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -577,6 +577,9 @@ static void update_main_config_table(struct pm8001_hba_info 
*pm8001_ha)
pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size);
pm8001_mw32(address, MAIN_PCS_EVENT_LOG_OPTION,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity);
+   /* Update Fatal error interrupt vector */
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |=
+   ((pm8001_ha->number_of_intr - 1) << 8);
pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt);
pm8001_mw32(address, MAIN_EVENT_CRC_CHECK,
@@ -1110,6 +1113,9 @@ static int pm80xx_chip_init(struct pm8001_hba_info 
*pm8001_ha)
return -EBUSY;
}
 
+   /* Initialize the controller fatal error flag */
+   pm8001_ha->controller_fatal_error = false;
+
/* Initialize pci space address eg: mpi offset */
init_pci_device_addresses(pm8001_ha);
init_default_table_values(pm8001_ha);
@@ -1218,13 +1224,17 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha)
u32 bootloader_state;
u32 ibutton0, ibutton1;
 
-   /* Check if MPI is in ready state to reset */
-   if (mpi_uninit_check(pm8001_ha) != 0) {
-   PM8001_FAIL_DBG(pm8001_ha,
-   pm8001_printk("MPI state is not ready\n"));
-   return -1;
+   /* Process MPI table uninitialization only if FW is ready */
+   if (!pm8001_ha->controller_fatal_error) {
+   /* Check if MPI is in ready state to reset */
+   if (mpi_uninit_check(pm8001_ha) != 0) {
+   regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+   PM8001_

[PATCH V2 4/4] pm80xx : Update driver version to 0.1.39

2018-09-11 Thread Viswas G
From: Deepak Ukey 

Updated the driver version from 0.1.38 to 0.1.39.

Signed-off-by: Deepak Ukey 
Signed-off-by: Viswas G 
Acked-by: Jack Wang  
---
 drivers/scsi/pm8001/pm8001_sas.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 1816e351071f..f88b0d33c385 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -58,7 +58,7 @@
 #include "pm8001_defs.h"
 
 #define DRV_NAME   "pm80xx"
-#define DRV_VERSION"0.1.38"
+#define DRV_VERSION"0.1.39"
 #define PM8001_FAIL_LOGGING0x01 /* Error message logging */
 #define PM8001_INIT_LOGGING0x02 /* driver init logging */
 #define PM8001_DISC_LOGGING0x04 /* discovery layer logging */
-- 
2.19.0-rc1



[PATCH V2 0/4] pm0xx : Updates for driver version 0.1.39

2018-09-11 Thread Viswas G
From: Deepak Ukey 

This patch set include some bug fixes for pm80xx driver.

Changes from V1:
For "Fix for phy enable/disable functionality" patch,
-Initialized the PM8001F_RUN_TIME flag in pm8001_pci_probe().
-Differentiated PHY_LINK_UP state for SPC and SPCv controller.
-Used PHY_LINK_DOWN macro for phy state down.

Deepak Ukey (4):
  pm80xx : Fix for phy enable/disable functionality.
  pm80xx : Corrected dma_unmap_sg() parameter.
  pm80xx : Fixed system hang issue during kexec boot.
  pm80xx : Update driver version to 0.1.39

 drivers/scsi/pm8001/pm8001_defs.h |  8 +++
 drivers/scsi/pm8001/pm8001_hwi.c  |  9 ++-
 drivers/scsi/pm8001/pm8001_hwi.h  |  4 --
 drivers/scsi/pm8001/pm8001_init.c |  3 +-
 drivers/scsi/pm8001/pm8001_sas.c  | 37 ++--
 drivers/scsi/pm8001/pm8001_sas.h  |  3 +-
 drivers/scsi/pm8001/pm80xx_hwi.c  | 94 +++
 drivers/scsi/pm8001/pm80xx_hwi.h  |  9 ++-
 8 files changed, 142 insertions(+), 25 deletions(-)

-- 
2.19.0-rc1



[PATCH V2 1/4] pm80xx : Fix for phy enable/disable functionality.

2018-09-11 Thread Viswas G
From: Deepak Ukey 

Added proper mask for phy id in mpi_phy_stop_resp().

V2:
-Initialized the PM8001F_RUN_TIME flag in
 pm8001_pci_probe().
-Differentiated PHY_LINK_UP state for SPC and SPCv
 controller.
-Used PHY_LINK_DOWN macro for phy state down.

Signed-off-by: Deepak Ukey 
Signed-off-by: Viswas G 
---
 drivers/scsi/pm8001/pm8001_defs.h |  8 
 drivers/scsi/pm8001/pm8001_hwi.c  |  3 ++-
 drivers/scsi/pm8001/pm8001_hwi.h  |  4 
 drivers/scsi/pm8001/pm8001_init.c |  3 ++-
 drivers/scsi/pm8001/pm8001_sas.c  | 28 +---
 drivers/scsi/pm8001/pm80xx_hwi.c  | 14 --
 drivers/scsi/pm8001/pm80xx_hwi.h  |  6 --
 7 files changed, 49 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_defs.h 
b/drivers/scsi/pm8001/pm8001_defs.h
index 199527dbaaa1..48e0624ecc68 100644
--- a/drivers/scsi/pm8001/pm8001_defs.h
+++ b/drivers/scsi/pm8001/pm8001_defs.h
@@ -132,4 +132,12 @@ enum pm8001_hba_info_flags {
PM8001F_RUN_TIME= (1U << 1),
 };
 
+/**
+ * Phy Status
+ */
+#define PHY_LINK_DISABLE   0x00
+#define PHY_LINK_DOWN  0x01
+#define PHY_STATE_LINK_UP_SPCV 0x2
+#define PHY_STATE_LINK_UP_SPC  0x1
+
 #endif
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 4dd6cad330e8..a14bf50a76d7 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3810,7 +3810,8 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
" status = %x\n", status));
if (status == 0) {
phy->phy_state = 1;
-   if (pm8001_ha->flags == PM8001F_RUN_TIME)
+   if (pm8001_ha->flags == PM8001F_RUN_TIME &&
+   phy->enable_completion != NULL)
complete(phy->enable_completion);
}
break;
diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h
index e4867e690c84..6d91e2446542 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.h
+++ b/drivers/scsi/pm8001/pm8001_hwi.h
@@ -131,10 +131,6 @@
 #define LINKRATE_30(0x02 << 8)
 #define LINKRATE_60(0x04 << 8)
 
-/* for phy state */
-
-#define PHY_STATE_LINK_UP_SPC  0x1
-
 /* for new SPC controllers MEMBASE III is shared between BIOS and DATA */
 #define GSM_SM_BASE0x4F
 struct mpi_msg_hdr{
diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index 7a697ca68501..501830caba21 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -121,7 +121,7 @@ static void pm8001_phy_init(struct pm8001_hba_info 
*pm8001_ha, int phy_id)
 {
struct pm8001_phy *phy = _ha->phy[phy_id];
struct asd_sas_phy *sas_phy = >sas_phy;
-   phy->phy_state = 0;
+   phy->phy_state = PHY_LINK_DISABLE;
phy->pm8001_ha = pm8001_ha;
sas_phy->enabled = (phy_id < pm8001_ha->chip->n_phy) ? 1 : 0;
sas_phy->class = SAS;
@@ -1067,6 +1067,7 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
if (rc)
goto err_out_shost;
scsi_scan_host(pm8001_ha->shost);
+   pm8001_ha->flags = PM8001F_RUN_TIME;
return 0;
 
 err_out_shost:
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 947d6017d004..d8249675371e 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -157,9 +157,12 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum 
phy_func func,
int rc = 0, phy_id = sas_phy->id;
struct pm8001_hba_info *pm8001_ha = NULL;
struct sas_phy_linkrates *rates;
+   struct sas_ha_struct *sas_ha;
+   struct pm8001_phy *phy;
DECLARE_COMPLETION_ONSTACK(completion);
unsigned long flags;
pm8001_ha = sas_phy->ha->lldd_ha;
+   phy = _ha->phy[phy_id];
pm8001_ha->phy[phy_id].enable_completion = 
switch (func) {
case PHY_FUNC_SET_LINK_RATE:
@@ -172,7 +175,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum 
phy_func func,
pm8001_ha->phy[phy_id].maximum_linkrate =
rates->maximum_linkrate;
}
-   if (pm8001_ha->phy[phy_id].phy_state == 0) {
+   if (pm8001_ha->phy[phy_id].phy_state ==  PHY_LINK_DISABLE) {
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id);
wait_for_completion();
}
@@ -180,7 +183,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum 
phy_func func,
  PHY_LINK_RESET

[PATCH 0/4] pm0xx : Updates for driver version 0.1.39.

2018-09-04 Thread Viswas G
From: Deepak Ukey 

This patch set include some bug fixes for pm80xx driver.

Deepak Ukey (4):
  pm80xx : Fix for phy enable/disable functionality.
  pm80xx : Corrected dma_unmap_sg() parameter.
  pm80xx : Fixed system hang issue during kexec boot.
  pm80xx : Update driver version to 0.1.39

 drivers/scsi/pm8001/pm8001_defs.h |  7 
 drivers/scsi/pm8001/pm8001_hwi.c  | 10 -
 drivers/scsi/pm8001/pm8001_init.c |  2 +-
 drivers/scsi/pm8001/pm8001_sas.c  | 25 +--
 drivers/scsi/pm8001/pm8001_sas.h  |  3 +-
 drivers/scsi/pm8001/pm80xx_hwi.c  | 87 +++
 drivers/scsi/pm8001/pm80xx_hwi.h  |  7 
 7 files changed, 124 insertions(+), 17 deletions(-)

-- 
1.8.3.1



[PATCH 4/4] pm80xx : Update driver version to 0.1.39

2018-09-04 Thread Viswas G
From: Deepak Ukey 

Updated the driver version from 0.1.38 to 0.1.39.

Signed-off-by: Deepak Ukey 
Signed-off-by: Viswas G 
---
 drivers/scsi/pm8001/pm8001_sas.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 1816e35..f88b0d3 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -58,7 +58,7 @@
 #include "pm8001_defs.h"
 
 #define DRV_NAME   "pm80xx"
-#define DRV_VERSION"0.1.38"
+#define DRV_VERSION"0.1.39"
 #define PM8001_FAIL_LOGGING0x01 /* Error message logging */
 #define PM8001_INIT_LOGGING0x02 /* driver init logging */
 #define PM8001_DISC_LOGGING0x04 /* discovery layer logging */
-- 
1.8.3.1



[PATCH 1/4] pm80xx : Fix for phy enable/disable functionality.

2018-09-04 Thread Viswas G
From: Deepak Ukey 

Added proper mask for phy id in mpi_phy_stop_resp().

Signed-off-by: Deepak Ukey 
Signed-off-by: Viswas G 
---
 drivers/scsi/pm8001/pm8001_defs.h |  7 +++
 drivers/scsi/pm8001/pm8001_hwi.c  |  4 ++--
 drivers/scsi/pm8001/pm8001_init.c |  2 +-
 drivers/scsi/pm8001/pm8001_sas.c  | 16 +---
 drivers/scsi/pm8001/pm80xx_hwi.c  |  7 ---
 drivers/scsi/pm8001/pm80xx_hwi.h  |  4 
 6 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_defs.h 
b/drivers/scsi/pm8001/pm8001_defs.h
index 199527d..6b8bc66 100644
--- a/drivers/scsi/pm8001/pm8001_defs.h
+++ b/drivers/scsi/pm8001/pm8001_defs.h
@@ -132,4 +132,11 @@ enum pm8001_hba_info_flags {
PM8001F_RUN_TIME= (1U << 1),
 };
 
+/**
+ * Phy Status
+ */
+#define PHY_LINK_DISABLE   0x00
+#define PHY_LINK_DOWN  0x01
+#define PHY_LINK_UP0x02
+
 #endif
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 4dd6cad..fcfb4f7 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3829,7 +3829,7 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
pm8001_printk("HW_EVENT_PHY_STOP_STATUS "
"status = %x\n", status));
if (status == 0)
-   phy->phy_state = 0;
+   phy->phy_state = PHY_LINK_DISABLE;
break;
case HW_EVENT_SATA_SPINUP_HOLD:
PM8001_MSG_DBG(pm8001_ha,
@@ -3841,7 +3841,7 @@ static int mpi_hw_event(struct pm8001_hba_info 
*pm8001_ha, void* piomb)
pm8001_printk("HW_EVENT_PHY_DOWN\n"));
sas_ha->notify_phy_event(>sas_phy, PHYE_LOSS_OF_SIGNAL);
phy->phy_attached = 0;
-   phy->phy_state = 0;
+   phy->phy_state = PHY_LINK_DISABLE;
hw_event_phy_down(pm8001_ha, piomb);
break;
case HW_EVENT_PORT_INVALID:
diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index 7a697ca..3dca1dc 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -121,7 +121,7 @@ static void pm8001_phy_init(struct pm8001_hba_info 
*pm8001_ha, int phy_id)
 {
struct pm8001_phy *phy = _ha->phy[phy_id];
struct asd_sas_phy *sas_phy = >sas_phy;
-   phy->phy_state = 0;
+   phy->phy_state = PHY_LINK_DISABLE;
phy->pm8001_ha = pm8001_ha;
sas_phy->enabled = (phy_id < pm8001_ha->chip->n_phy) ? 1 : 0;
sas_phy->class = SAS;
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 947d601..96b173f 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -157,9 +157,12 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum 
phy_func func,
int rc = 0, phy_id = sas_phy->id;
struct pm8001_hba_info *pm8001_ha = NULL;
struct sas_phy_linkrates *rates;
+   struct sas_ha_struct *sas_ha;
+   struct pm8001_phy *phy;
DECLARE_COMPLETION_ONSTACK(completion);
unsigned long flags;
pm8001_ha = sas_phy->ha->lldd_ha;
+   phy = _ha->phy[phy_id];
pm8001_ha->phy[phy_id].enable_completion = 
switch (func) {
case PHY_FUNC_SET_LINK_RATE:
@@ -172,7 +175,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum 
phy_func func,
pm8001_ha->phy[phy_id].maximum_linkrate =
rates->maximum_linkrate;
}
-   if (pm8001_ha->phy[phy_id].phy_state == 0) {
+   if (pm8001_ha->phy[phy_id].phy_state ==  PHY_LINK_DISABLE) {
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id);
wait_for_completion();
}
@@ -180,7 +183,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum 
phy_func func,
  PHY_LINK_RESET);
break;
case PHY_FUNC_HARD_RESET:
-   if (pm8001_ha->phy[phy_id].phy_state == 0) {
+   if (pm8001_ha->phy[phy_id].phy_state == PHY_LINK_DISABLE) {
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id);
wait_for_completion();
}
@@ -188,7 +191,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum 
phy_func func,
  PHY_HARD_RESET);
break;
case PHY_FUNC_LINK_RESET:
-   if (pm8001_ha->phy[phy_id].phy_state == 0) {
+   if (pm8001_ha->phy[phy_id].phy_state == PHY_LINK_DISABLE) {
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id);
  

[PATCH 3/4] pm80xx : Fixed system hang issue during kexec boot.

2018-09-04 Thread Viswas G
From: Deepak Ukey 

When the firmware is not responding, execution of kexec boot
causes a system hang. When firmware assertion happened, driver
get notified with interrupt vector updated in MPI configuration
table. Then, the driver will read scratchpad register and
set controller_fatal_error flag to true.

Signed-off-by: Deepak Ukey 
Signed-off-by: Viswas G 
---
 drivers/scsi/pm8001/pm8001_hwi.c |  6 +++
 drivers/scsi/pm8001/pm8001_sas.c |  7 
 drivers/scsi/pm8001/pm8001_sas.h |  1 +
 drivers/scsi/pm8001/pm80xx_hwi.c | 80 +---
 drivers/scsi/pm8001/pm80xx_hwi.h |  3 ++
 5 files changed, 91 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index fcfb4f7..403ea8c 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -1479,6 +1479,12 @@ u32 pm8001_mpi_msg_consume(struct pm8001_hba_info 
*pm8001_ha,
} else {
u32 producer_index;
void *pi_virt = circularQ->pi_virt;
+   /* spurious interrupt during setup if
+* kexec-ing and driver doing a doorbell access
+* with the pre-kexec oq interrupt setup
+*/
+   if (!pi_virt)
+   break;
/* Update the producer index from SPC */
producer_index = pm8001_read_32(pi_virt);
circularQ->producer_index = cpu_to_le32(producer_index);
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 719233c..f9c8f21 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -384,6 +384,13 @@ static int pm8001_task_exec(struct sas_task *task,
return 0;
}
pm8001_ha = pm8001_find_ha_by_dev(task->dev);
+   if (pm8001_ha->controller_fatal_error) {
+   struct task_status_struct *ts = >task_status;
+
+   ts->resp = SAS_TASK_UNDELIVERED;
+   t->task_done(t);
+   return 0;
+   }
PM8001_IO_DBG(pm8001_ha, pm8001_printk("pm8001_task_exec device \n "));
spin_lock_irqsave(_ha->lock, flags);
do {
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 80b4dd6..1816e35 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -538,6 +538,7 @@ struct pm8001_hba_info {
u32 logging_level;
u32 fw_status;
u32 smp_exp_mode;
+   boolcontroller_fatal_error;
const struct firmware   *fw_image;
struct isr_param irq_vector[PM8001_MAX_MSIX_VEC];
u32 reset_in_progress;
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 17e74a3..6eec439 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -577,6 +577,9 @@ static void update_main_config_table(struct pm8001_hba_info 
*pm8001_ha)
pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size);
pm8001_mw32(address, MAIN_PCS_EVENT_LOG_OPTION,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity);
+   /* Update Fatal error interrupt vector */
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt |=
+   ((pm8001_ha->number_of_intr - 1) << 8);
pm8001_mw32(address, MAIN_FATAL_ERROR_INTERRUPT,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt);
pm8001_mw32(address, MAIN_EVENT_CRC_CHECK,
@@ -1110,6 +1113,9 @@ static int pm80xx_chip_init(struct pm8001_hba_info 
*pm8001_ha)
return -EBUSY;
}
 
+   /* Initialize the controller fatal error flag */
+   pm8001_ha->controller_fatal_error = false;
+
/* Initialize pci space address eg: mpi offset */
init_pci_device_addresses(pm8001_ha);
init_default_table_values(pm8001_ha);
@@ -1218,13 +1224,17 @@ static int mpi_uninit_check(struct pm8001_hba_info 
*pm8001_ha)
u32 bootloader_state;
u32 ibutton0, ibutton1;
 
-   /* Check if MPI is in ready state to reset */
-   if (mpi_uninit_check(pm8001_ha) != 0) {
-   PM8001_FAIL_DBG(pm8001_ha,
-   pm8001_printk("MPI state is not ready\n"));
-   return -1;
+   /* Process MPI table uninitialization only if FW is ready */
+   if (!pm8001_ha->controller_fatal_error) {
+   /* Check if MPI is in ready state to reset */
+   if (mpi_uninit_check(pm8001_ha) != 0) {
+   regval = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_1);
+   PM8001_FAIL_DBG(pm8001_ha, pm8001_printk(
+

[PATCH 2/4] pm80xx : Corrected dma_unmap_sg() parameter.

2018-09-04 Thread Viswas G
From: Deepak Ukey 

For the function dma_unmap_sg(), the  parameter should be
number of elements in the scatter list prior to the mapping, not
after the mapping.

Signed-off-by: Deepak Ukey 
Signed-off-by: Viswas G 
---
 drivers/scsi/pm8001/pm8001_sas.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 96b173f..719233c 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -476,7 +476,7 @@ static int pm8001_task_exec(struct sas_task *task,
dev_printk(KERN_ERR, pm8001_ha->dev, "pm8001 exec failed[%d]!\n", rc);
if (!sas_protocol_ata(t->task_proto))
if (n_elem)
-   dma_unmap_sg(pm8001_ha->dev, t->scatter, n_elem,
+   dma_unmap_sg(pm8001_ha->dev, t->scatter, t->num_scatter,
t->data_dir);
 out_done:
spin_unlock_irqrestore(_ha->lock, flags);
-- 
1.8.3.1



RE: PMC(Adaptec) 7805H(7H series) HBA compatibility problem with many Seagate HDDs

2018-01-21 Thread Viswas G
Hi sonofagun,

Can you please try below commands and share the kernel logs.

linux-lpds:~ # find /sys -iname "logging_level"
/sys/devices/pci:80/:80:03.2/:82:00.0/host10/scsi_host/host10/logging_level

linux-lpds:~ # echo 0xff >  
/sys/devices/pci:80/:80:03.2/:82:00.0/host10/scsi_host/host10/logging_level

After setting the log level to oxff, connect the drives with which you are 
facing issue.

Kindly share the logs after that.

Regards,
Viswas G

> -Original Message-
> From: Jack Wang [mailto:xjtu...@gmail.com]
> Sent: Friday, January 12, 2018 8:46 PM
> To: sonofa...@openmailbox.org; Viswas G <viswa...@microsemi.com>
> Cc: linux-scsi@vger.kernel.org
> Subject: Re: PMC(Adaptec) 7805H(7H series) HBA compatibility problem with
> many Seagate HDDs
> 
> EXTERNAL EMAIL
> 
> 
> +cc Viswas from micorsemi. maybe he can help.
> 
> 2018-01-12 12:15 GMT+01:00  <sonofa...@openmailbox.org>:
> >
> > Hello, we have a long standing issue for a couple of years with our SAS HBA.
> >
> > It happens no matter what distribution we use(Debian, CentOS, Ubuntu).
> >
> > When we bought this HBA we had already two 500GB Seagate SAS HDDs,
> Constellation ES.2 ST3500620SS. Those were working fine as expected.
> > In order to back up SATA disks we bought a couple of 4TB Seagate SAS
> HDDs, Constellation ES.3 ST4000NM0023.
> > Unfortunately they did not work with this HBA even though we updated
> both the HBA and the HDDs firmware a couple of times back in 2015 :(
> > Our LSI SAS Gen2 HBA had no issues at all with the same disks...
> >
> > A couple of years ago my brother contacted PMC and Seagate but the issue
> remains... Since the issue persisted they were moved to the LSI HBA.
> >
> > My brother thought it was a compatibility issue with Constellation ES.3 so
> he bought 3 newer Seagate disks in December. Those are Enterprise Capacity
> v5(ECv5) now called Exos 7E2.
> > Unfortunately none of them works on this HBA! Again our LSI SAS Gen2
> HBA had no issues at all with the newer disks...
> >
> > In order to have a decent disk for the PMC HBA, we bought a couple of 10K
> 2,5" Toshiba HDDs which support T1O DIF but have it inactive. Luckily those
> disks worked fine!
> >
> > The problem is that we have 5(2+3) Seagate 7200 class disks that cannot
> work with this controller!
> > Any newer seagate SAS HDD we tried and had protection information (aka
> T1O DIF) cannot be written on this HBA for some reason (even though DIF
> was never activated).
> > Formatting the disk from the HBA did not solve the issue. So dd and mke2fs
> are unusable. Both always hang even though the disk and the HBA are in
> good condition.
> > The affected disk was tested on all SAS ports but it failed miserably.
> Different cables were also used to ensure that no cabling issues arise.
> >
> > The ES.3 disks are unavailable for now as they have data. Any patch will be
> only tested with our ECv5.
> >
> > Here is what we get at normal boot with dd (input /dev/zero, block 8k in
> this case):
> >
> > [0.00] Linux version 4.9.0-5-amd64 (debian-ker...@lists.debian.org)
> (gcc version 6.3.0 20170516 (Debian 6.3.0-18) ) #1 SMP Debian 4.9.65-
> 3+deb9u2 (2018-01-04)
> > [0.00] Command line: BOOT_IMAGE=/boot/vmlinuz-4.9.0-5-amd64
> root=UUID=5e47893b-3c41-4eef-b6c8-c401681ec19f ro quiet
> > [0.644856] pci :06:00.0: [9005:8088] type 00 class 0x010700
> > [0.644867] pci :06:00.0: reg 0x10: [mem 0xfe25-0xfe25 64bit]
> > [0.644875] pci :06:00.0: reg 0x18: [mem 0xfe24-0xfe24 64bit]
> > [0.644884] pci :06:00.0: reg 0x24: [mem 0xfe20-0xfe23]
> > [0.644890] pci :06:00.0: reg 0x30: [mem 0xfe10-0xfe1f pref]
> > [0.644933] pci :06:00.0: supports D1
> > [0.644934] pci :06:00.0: PME# supported from D0 D1 D3hot
> > [1.290266] iommu: Adding device :06:00.0 to group 22
> > [1.441672] pm80xx :06:00.0: pm80xx: driver version 0.1.38
> > [2.302240] scsi host0: pm80xx
> > [2.802851] sas: phy-0:1 added to port-0:0, phy_mask:0x2
> (5000c500)
> > [2.802858] sas: DOING DISCOVERY on port 0, pid:189
> > [2.862822] sas: DONE DISCOVERY on port 0, pid:189, result:0
> > [2.877467] scsi 0:0:0:0: Direct-Access SEAGATE  ST2000NM0045 
> > N003
> PQ: 0 ANSI: 6
> > [3.792502] sd 0:0:0:0: [sdb] 3907029168 512-byte logical blocks: (2.00
> TB/1.82 TiB)
> > [3.795080] sd 0:0:0:0: [sdb] Write Protect is off
> > [3.795082] sd 0:0:0:0: [sdb] Mode Sense: db 00 10 08
> > [3.796995] sd 0:0:0:0: [sdb

[PATCH V4 7/9] pm80xx : corrected SATA abort handling sequence.

2017-10-18 Thread Viswas G
Modified SATA abort handling with following steps:
1) Set device state as recovery.
2) Send phy reset.
3) Wait for reset completion.
4) After successful reset, abort all IO's to the device.
5) After aborting all IO's to device, set device state as operational.

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c |  8 -
 drivers/scsi/pm8001/pm8001_sas.c | 72 ++--
 drivers/scsi/pm8001/pm8001_sas.h |  8 +
 drivers/scsi/pm8001/pm80xx_hwi.c | 36 
 4 files changed, 114 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index bc4a6f649ec9..db88a8e7ee0e 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3209,10 +3209,16 @@ int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info 
*pm8001_ha, void *piomb)
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op failed!\n",
phy_id, phy_op));
-   } else
+   } else {
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op success!\n",
phy_id, phy_op));
+   pm8001_ha->phy[phy_id].reset_success = true;
+   }
+   if (pm8001_ha->phy[phy_id].enable_completion) {
+   complete(pm8001_ha->phy[phy_id].enable_completion);
+   pm8001_ha->phy[phy_id].enable_completion = NULL;
+   }
pm8001_tag_free(pm8001_ha, tag);
return 0;
 }
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index a7626a851b62..ce605a8d1c67 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -1166,13 +1166,16 @@ int pm8001_abort_task(struct sas_task *task)
struct scsi_lun lun;
struct pm8001_device *pm8001_dev;
struct pm8001_tmf_task tmf_task;
-   int rc = TMF_RESP_FUNC_FAILED;
+   int rc = TMF_RESP_FUNC_FAILED, ret;
+   u32 phy_id;
+   struct sas_task_slow slow_task;
if (unlikely(!task || !task->lldd_task || !task->dev))
return TMF_RESP_FUNC_FAILED;
dev = task->dev;
pm8001_dev = dev->lldd_dev;
pm8001_ha = pm8001_find_ha_by_dev(dev);
device_id = pm8001_dev->device_id;
+   phy_id = pm8001_dev->attached_phy;
rc = pm8001_find_tag(task, );
if (rc == 0) {
pm8001_printk("no tag for task:%p\n", task);
@@ -1183,6 +1186,11 @@ int pm8001_abort_task(struct sas_task *task)
spin_unlock_irqrestore(>task_state_lock, flags);
return TMF_RESP_FUNC_COMPLETE;
}
+   task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+   if (task->slow_task == NULL) {
+   init_completion(_task.completion);
+   task->slow_task = _task;
+   }
spin_unlock_irqrestore(>task_state_lock, flags);
if (task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd *cmnd = task->uldd_task;
@@ -1194,14 +1202,72 @@ int pm8001_abort_task(struct sas_task *task)
pm8001_dev->sas_device, 0, tag);
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) {
-   rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-   pm8001_dev->sas_device, 0, tag);
+   if (pm8001_ha->chip_id == chip_8006) {
+   DECLARE_COMPLETION_ONSTACK(completion_reset);
+   DECLARE_COMPLETION_ONSTACK(completion);
+   struct pm8001_phy *phy = pm8001_ha->phy + phy_id;
+   /* 1. Set Device state as Recovery*/
+   pm8001_dev->setds_completion = 
+   PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
+   pm8001_dev, 0x03);
+   wait_for_completion();
+   /* 2. Send Phy Control Hard Reset */
+   reinit_completion();
+   phy->reset_success = false;
+   phy->enable_completion = 
+   phy->reset_completion = _reset;
+   ret = PM8001_CHIP_DISP->phy_ctl_req(pm8001_ha, phy_id,
+   PHY_HARD_RESET);
+   if (ret)
+   goto out;
+   PM8001_MSG_DBG(pm8001_ha,
+   pm8001_printk("Waiting for local phy ctl\n"));
+   wait_for_completion();
+   if (!phy->reset_success)
+   

[PATCH V4 6/9] pm80xx : modified port reset timer value for PM8006 card

2017-10-18 Thread Viswas G
Added port reset timer value as 2000ms for PM8006 sata controller.

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 097096bf4bb0..5d2a4a38bf73 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -597,6 +597,12 @@ static void update_main_config_table(struct 
pm8001_hba_info *pm8001_ha)
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &= 0x;
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |=
PORT_RECOVERY_TIMEOUT;
+   if (pm8001_ha->chip_id == chip_8006) {
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &=
+   0x;
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |=
+   0x14;
+   }
pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);
 }
-- 
2.12.3



[PATCH V4 1/9] pm80xx : redefine sas_identify_frame structure

2017-10-18 Thread Viswas G
sas_identify structure defined by pm80xx doesn't have CRC field.
So added a new sas_identify structure without CRC.

v2:
- Since the structure changes is applicable for only pm80xx,
  sas_identify_frame_local structure moved to pm80xx_hwi.h.

Signed-off-by: Raj Dinesh <raj.din...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.h | 98 +++-
 1 file changed, 97 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 7a443bad6163..82b8cf581da9 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -229,6 +229,102 @@
 #define IT_NEXUS_TIMEOUT   0x7D0
 #define PORT_RECOVERY_TIMEOUT  ((IT_NEXUS_TIMEOUT/100) + 30)
 
+#ifdef __LITTLE_ENDIAN_BITFIELD
+struct sas_identify_frame_local {
+   /* Byte 0 */
+   u8  frame_type:4;
+   u8  dev_type:3;
+   u8  _un0:1;
+
+   /* Byte 1 */
+   u8  _un1;
+
+   /* Byte 2 */
+   union {
+   struct {
+   u8  _un20:1;
+   u8  smp_iport:1;
+   u8  stp_iport:1;
+   u8  ssp_iport:1;
+   u8  _un247:4;
+   };
+   u8 initiator_bits;
+   };
+
+   /* Byte 3 */
+   union {
+   struct {
+   u8  _un30:1;
+   u8 smp_tport:1;
+   u8 stp_tport:1;
+   u8 ssp_tport:1;
+   u8 _un347:4;
+   };
+   u8 target_bits;
+   };
+
+   /* Byte 4 - 11 */
+   u8 _un4_11[8];
+
+   /* Byte 12 - 19 */
+   u8 sas_addr[SAS_ADDR_SIZE];
+
+   /* Byte 20 */
+   u8 phy_id;
+
+   u8 _un21_27[7];
+
+} __packed;
+
+#elif defined(__BIG_ENDIAN_BITFIELD)
+struct sas_identify_frame_local {
+   /* Byte 0 */
+   u8  _un0:1;
+   u8  dev_type:3;
+   u8  frame_type:4;
+
+   /* Byte 1 */
+   u8  _un1;
+
+   /* Byte 2 */
+   union {
+   struct {
+   u8  _un247:4;
+   u8  ssp_iport:1;
+   u8  stp_iport:1;
+   u8  smp_iport:1;
+   u8  _un20:1;
+   };
+   u8 initiator_bits;
+   };
+
+   /* Byte 3 */
+   union {
+   struct {
+   u8 _un347:4;
+   u8 ssp_tport:1;
+   u8 stp_tport:1;
+   u8 smp_tport:1;
+   u8 _un30:1;
+   };
+   u8 target_bits;
+   };
+
+   /* Byte 4 - 11 */
+   u8 _un4_11[8];
+
+   /* Byte 12 - 19 */
+   u8 sas_addr[SAS_ADDR_SIZE];
+
+   /* Byte 20 */
+   u8 phy_id;
+
+   u8 _un21_27[7];
+} __packed;
+#else
+#error "Bitfield order not defined!"
+#endif
+
 struct mpi_msg_hdr {
__le32  header; /* Bits [11:0] - Message operation code */
/* Bits [15:12] - Message Category */
@@ -248,7 +344,7 @@ struct mpi_msg_hdr {
 struct phy_start_req {
__le32  tag;
__le32  ase_sh_lm_slr_phyid;
-   struct sas_identify_frame sas_identify; /* 28 Bytes */
+   struct sas_identify_frame_local sas_identify; /* 28 Bytes */
__le32 spasti;
u32 reserved[21];
 } __attribute__((packed, aligned(4)));
-- 
2.12.3



[PATCH V4 9/9] pm80xx : corrected linkrate value.

2017-10-18 Thread Viswas G
Corrected the value defined for LINKRATE_60 (6 Gig).

Signed-off-by: Raj Dinesh <raj.din...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index e36c5176f9a9..889e69ce3689 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -167,7 +167,7 @@
 #define LINKMODE_AUTO  (0x03 << 12)
 #define LINKRATE_15(0x01 << 8)
 #define LINKRATE_30(0x02 << 8)
-#define LINKRATE_60(0x06 << 8)
+#define LINKRATE_60(0x04 << 8)
 #define LINKRATE_120   (0x08 << 8)
 
 /* phy_profile */
-- 
2.12.3



[PATCH V4 8/9] pm80xx : panic on ncq error cleaning up the read log.

2017-10-18 Thread Viswas G
when there's an error in 'ncq mode' the host has to read the ncq
error log (10h) to clear the error state. however, the ccb that
is setup for doing this doesn't setup the ccb so that the
previous state is cleared. if the ccb was previously used for an IO
n_elems is set and pm8001_ccb_task_free() treats this as the signal
to go free a scatter-gather list (that's already been free-ed).

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index f6df11a7c2d5..42f0405601ad 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1489,6 +1489,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info 
*pm8001_ha,
ccb->device = pm8001_ha_dev;
ccb->ccb_tag = ccb_tag;
ccb->task = task;
+   ccb->n_elem = 0;
pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
 
-- 
2.12.3



[PATCH V4 2/9] pm80xx : ILA and inactive firmware version through sysfs

2017-10-18 Thread Viswas G
Added support to read ILA version and inactive firmware version
from MPI configuration table and export through sysfs.

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c | 54 
 drivers/scsi/pm8001/pm8001_sas.h |  2 ++
 drivers/scsi/pm8001/pm80xx_hwi.c |  5 
 drivers/scsi/pm8001/pm80xx_hwi.h |  2 ++
 4 files changed, 63 insertions(+)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index be8269c8d127..596f3ff965f5 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -98,6 +98,58 @@ static ssize_t pm8001_ctl_fw_version_show(struct device 
*cdev,
}
 }
 static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL);
+
+/**
+ * pm8001_ctl_ila_version_show - ila version
+ * @cdev: pointer to embedded class device
+ * @buf: the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t pm8001_ctl_ila_version_show(struct device *cdev,
+   struct device_attribute *attr, char *buf)
+{
+   struct Scsi_Host *shost = class_to_shost(cdev);
+   struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+   struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+   if (pm8001_ha->chip_id != chip_8001) {
+   return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 24),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 16),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 8),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version));
+   }
+   return 0;
+}
+static DEVICE_ATTR(ila_version, 0444, pm8001_ctl_ila_version_show, NULL);
+
+/**
+ * pm8001_ctl_inactive_fw_version_show - Inacative firmware version number
+ * @cdev: pointer to embedded class device
+ * @buf: the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t pm8001_ctl_inactive_fw_version_show(struct device *cdev,
+   struct device_attribute *attr, char *buf)
+{
+   struct Scsi_Host *shost = class_to_shost(cdev);
+   struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+   struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+   if (pm8001_ha->chip_id != chip_8001) {
+   return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 24),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 16),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 8),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version));
+   }
+   return 0;
+}
+static
+DEVICE_ATTR(inc_fw_ver, 0444, pm8001_ctl_inactive_fw_version_show, NULL);
+
 /**
  * pm8001_ctl_max_out_io_show - max outstanding io supported
  * @cdev: pointer to embedded class device
@@ -748,6 +800,8 @@ struct device_attribute *pm8001_host_attrs[] = {
_attr_bios_version,
_attr_ib_log,
_attr_ob_log,
+   _attr_ila_version,
+   _attr_inc_fw_ver,
NULL,
 };
 
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index e81a8fa7ef1a..c75de413e062 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -404,6 +404,8 @@ union main_cfg_table {
u32 port_recovery_timer;
u32 interrupt_reassertion_delay;
u32 fatal_n_non_fatal_dump; /* 0x28 */
+   u32 ila_version;
+   u32 inc_fw_version;
} pm80xx_tbl;
 };
 
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index eb4fee61df72..8fb5ddf08cc4 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -312,6 +312,11 @@ static void read_main_config_table(struct pm8001_hba_info 
*pm8001_ha)
/* read port recover and reset timeout */
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer =
pm8001_mr32(address, MAIN_PORT_RECOVERY_TIMER);
+   /* read ILA and inactive firmware version */
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version =
+   pm8001_mr32(address, MAIN_MPI_ILA_RELEASE_TYPE);
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version =
+   pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION);
 }
 
 /**
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 82b8cf581da9..e36c5176f9a9 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -1445,6 +1445,8 @@ typedef struct SASProtocolTimerConfig 
SASProtocolTi

[PATCH V4 0/9] pm80xx updates

2017-10-18 Thread Viswas G

This patch set include some bug fixes and enhancement for pm80xx driver.

Changes from V3:
- Fixed kbuild warnings for patch 4 and 5.  

Changes from V2:
- Corrected date.

Changes from V1:
- sas_identify_frame_local structure moved to pm80xx_hwi.h
- sata abort handling patch split to four patches.
- tag allocation for phy control request.
- cleanup in pm8001_abort_task function.
- modified port reset timer value for PM8006 card
- corrected SATA abort handling sequence.


Viswas G (9):
  pm80xx : redefine sas_identify_frame structure
  pm80xx : ILA and inactive firmware version through sysfs
  pm80xx : Different SAS addresses for phys.
  pm80xx : tag allocation for phy control request.
  pm80xx : cleanup in pm8001_abort_task function.
  pm80xx : modified port reset timer value for PM8006  card
  pm80xx : corrected SATA abort handling sequence.
  pm80xx : panic on ncq error cleaning up the read log.
  pm80xx : corrected linkrate value.

 drivers/scsi/pm8001/pm8001_ctl.c  |  54 +
 drivers/scsi/pm8001/pm8001_hwi.c  |  11 +++-
 drivers/scsi/pm8001/pm8001_init.c |  13 +++--
 drivers/scsi/pm8001/pm8001_sas.c  | 119 +-
 drivers/scsi/pm8001/pm8001_sas.h  |  10 
 drivers/scsi/pm8001/pm80xx_hwi.c  |  62 
 drivers/scsi/pm8001/pm80xx_hwi.h  | 102 +++-
 7 files changed, 313 insertions(+), 58 deletions(-)

-- 
2.12.3



[PATCH V4 5/9] pm80xx : cleanup in pm8001_abort_task function.

2017-10-18 Thread Viswas G
v4:
-Removed the unused variable ccb in
 pm8001_abort_task.
-Removed the unused label out which
 is not used

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm8001_sas.c | 51 ++--
 1 file changed, 13 insertions(+), 38 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index ce584c31d36e..a7626a851b62 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -1159,40 +1159,34 @@ int pm8001_query_task(struct sas_task *task)
 int pm8001_abort_task(struct sas_task *task)
 {
unsigned long flags;
-   u32 tag = 0xdeadbeef;
+   u32 tag;
u32 device_id;
struct domain_device *dev ;
-   struct pm8001_hba_info *pm8001_ha = NULL;
-   struct pm8001_ccb_info *ccb;
+   struct pm8001_hba_info *pm8001_ha;
struct scsi_lun lun;
struct pm8001_device *pm8001_dev;
struct pm8001_tmf_task tmf_task;
int rc = TMF_RESP_FUNC_FAILED;
if (unlikely(!task || !task->lldd_task || !task->dev))
-   return rc;
+   return TMF_RESP_FUNC_FAILED;
+   dev = task->dev;
+   pm8001_dev = dev->lldd_dev;
+   pm8001_ha = pm8001_find_ha_by_dev(dev);
+   device_id = pm8001_dev->device_id;
+   rc = pm8001_find_tag(task, );
+   if (rc == 0) {
+   pm8001_printk("no tag for task:%p\n", 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;
+   return TMF_RESP_FUNC_COMPLETE;
}
spin_unlock_irqrestore(>task_state_lock, flags);
if (task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd *cmnd = task->uldd_task;
-   dev = task->dev;
-   ccb = task->lldd_task;
-   pm8001_dev = dev->lldd_dev;
-   pm8001_ha = pm8001_find_ha_by_dev(dev);
int_to_scsilun(cmnd->device->lun, );
-   rc = pm8001_find_tag(task, );
-   if (rc == 0) {
-   printk(KERN_INFO "No such tag in %s\n", __func__);
-   rc = TMF_RESP_FUNC_FAILED;
-   return rc;
-   }
-   device_id = pm8001_dev->device_id;
-   PM8001_EH_DBG(pm8001_ha,
-   pm8001_printk("abort io to deviceid= %d\n", device_id));
tmf_task.tmf = TMF_ABORT_TASK;
tmf_task.tag_of_task_to_be_managed = tag;
rc = pm8001_issue_ssp_tmf(dev, lun.scsi_lun, _task);
@@ -1200,33 +1194,14 @@ int pm8001_abort_task(struct sas_task *task)
pm8001_dev->sas_device, 0, tag);
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) {
-   dev = task->dev;
-   pm8001_dev = dev->lldd_dev;
-   pm8001_ha = pm8001_find_ha_by_dev(dev);
-   rc = pm8001_find_tag(task, );
-   if (rc == 0) {
-   printk(KERN_INFO "No such tag in %s\n", __func__);
-   rc = TMF_RESP_FUNC_FAILED;
-   return rc;
-   }
rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
pm8001_dev->sas_device, 0, tag);
} else if (task->task_proto & SAS_PROTOCOL_SMP) {
/* SMP */
-   dev = task->dev;
-   pm8001_dev = dev->lldd_dev;
-   pm8001_ha = pm8001_find_ha_by_dev(dev);
-   rc = pm8001_find_tag(task, );
-   if (rc == 0) {
-   printk(KERN_INFO "No such tag in %s\n", __func__);
-   rc = TMF_RESP_FUNC_FAILED;
-   return rc;
-   }
rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
pm8001_dev->sas_device, 0, tag);
 
}
-out:
if (rc != TMF_RESP_FUNC_COMPLETE)
pm8001_printk("rc= %d\n", rc);
return rc;
-- 
2.12.3



[PATCH V4 3/9] pm80xx : Different SAS addresses for phys.

2017-10-18 Thread Viswas G
Different SAS addresses are assigned for each set of phys.

Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm8001_init.c | 13 +
 drivers/scsi/pm8001/pm80xx_hwi.c  |  3 +--
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index 0e013f76b582..7a697ca68501 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -132,7 +132,7 @@ static void pm8001_phy_init(struct pm8001_hba_info 
*pm8001_ha, int phy_id)
sas_phy->oob_mode = OOB_NOT_CONNECTED;
sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
sas_phy->id = phy_id;
-   sas_phy->sas_addr = _ha->sas_addr[0];
+   sas_phy->sas_addr = (u8 *)>dev_sas_addr;
sas_phy->frame_rcvd = >frame_rcvd[0];
sas_phy->ha = (struct sas_ha_struct *)pm8001_ha->shost->hostdata;
sas_phy->lldd_phy = phy;
@@ -591,10 +591,12 @@ static void  pm8001_post_sas_ha_init(struct Scsi_Host 
*shost,
for (i = 0; i < chip_info->n_phy; i++) {
sha->sas_phy[i] = _ha->phy[i].sas_phy;
sha->sas_port[i] = _ha->port[i].sas_port;
+   sha->sas_phy[i]->sas_addr =
+   (u8 *)_ha->phy[i].dev_sas_addr;
}
sha->sas_ha_name = DRV_NAME;
sha->dev = pm8001_ha->dev;
-
+   sha->strict_wide_ports = 1;
sha->lldd_module = THIS_MODULE;
sha->sas_addr = _ha->sas_addr[0];
sha->num_phys = chip_info->n_phy;
@@ -611,6 +613,7 @@ static void  pm8001_post_sas_ha_init(struct Scsi_Host 
*shost,
 static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
 {
u8 i, j;
+   u8 sas_add[8];
 #ifdef PM8001_READ_VPD
/* For new SPC controllers WWN is stored in flash vpd
*  For SPC/SPCve controllers WWN is stored in EEPROM
@@ -672,10 +675,12 @@ static void pm8001_init_sas_add(struct pm8001_hba_info 
*pm8001_ha)
pm8001_ha->sas_addr[j] =
payload.func_specific[0x804 + i];
}
-
+   memcpy(sas_add, pm8001_ha->sas_addr, SAS_ADDR_SIZE);
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
+   if (i && ((i % 4) == 0))
+   sas_add[7] = sas_add[7] + 4;
memcpy(_ha->phy[i].dev_sas_addr,
-   pm8001_ha->sas_addr, SAS_ADDR_SIZE);
+   sas_add, SAS_ADDR_SIZE);
PM8001_INIT_DBG(pm8001_ha,
pm8001_printk("phy %d sas_addr = %016llx\n", i,
pm8001_ha->phy[i].dev_sas_addr));
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 8fb5ddf08cc4..2b26445d1b97 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -3041,7 +3041,6 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void 
*piomb)
port->port_state = portstate;
phy->identify.device_type = 0;
phy->phy_attached = 0;
-   memset(>dev_sas_addr, 0, SAS_ADDR_SIZE);
switch (portstate) {
case PORT_VALID:
break;
@@ -4394,7 +4393,7 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info 
*pm8001_ha, u8 phy_id)
payload.sas_identify.dev_type = SAS_END_DEVICE;
payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
memcpy(payload.sas_identify.sas_addr,
-   pm8001_ha->sas_addr, SAS_ADDR_SIZE);
+ _ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
payload.sas_identify.phy_id = phy_id;
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, , 0);
return ret;
-- 
2.12.3



[PATCH V4 4/9] pm80xx : tag allocation for phy control request.

2017-10-18 Thread Viswas G
tag is taken from the tag pool instead of using the hardcoded
tag value(1).

v4:
- Removed the unused variable ret in
  pm80xx_chip_phy_ctl_req.

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c |  3 +++
 drivers/scsi/pm8001/pm80xx_hwi.c | 11 +++
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 10546faac58c..bc4a6f649ec9 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3198,11 +3198,13 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info 
*pm8001_ha, void *piomb)
 
 int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
+   u32 tag;
struct local_phy_ctl_resp *pPayload =
(struct local_phy_ctl_resp *)(piomb + 4);
u32 status = le32_to_cpu(pPayload->status);
u32 phy_id = le32_to_cpu(pPayload->phyop_phyid) & ID_BITS;
u32 phy_op = le32_to_cpu(pPayload->phyop_phyid) & OP_BITS;
+   tag = le32_to_cpu(pPayload->tag);
if (status != 0) {
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op failed!\n",
@@ -3211,6 +3213,7 @@ int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info 
*pm8001_ha, void *piomb)
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op success!\n",
phy_id, phy_op));
+   pm8001_tag_free(pm8001_ha, tag);
return 0;
 }
 
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 2b26445d1b97..097096bf4bb0 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -4500,17 +4500,20 @@ static int pm80xx_chip_reg_dev_req(struct 
pm8001_hba_info *pm8001_ha,
 static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
u32 phyId, u32 phy_op)
 {
+   u32 tag;
+   int rc;
struct local_phy_ctl_req payload;
struct inbound_queue_table *circularQ;
-   int ret;
u32 opc = OPC_INB_LOCAL_PHY_CONTROL;
memset(, 0, sizeof(payload));
+   rc = pm8001_tag_alloc(pm8001_ha, );
+   if (rc)
+   return rc;
circularQ = _ha->inbnd_q_tbl[0];
-   payload.tag = cpu_to_le32(1);
+   payload.tag = cpu_to_le32(tag);
payload.phyop_phyid =
cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
-   ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, , 0);
-   return ret;
+   return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, , 0);
 }
 
 static u32 pm80xx_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha)
-- 
2.12.3



[PATCH V3 9/9] pm80xx : corrected linkrate value.

2017-09-19 Thread Viswas G
Corrected the value defined for LINKRATE_60 (6 Gig).

Signed-off-by: Raj Dinesh <raj.din...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index e36c5176f9a9..889e69ce3689 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -167,7 +167,7 @@
 #define LINKMODE_AUTO  (0x03 << 12)
 #define LINKRATE_15(0x01 << 8)
 #define LINKRATE_30(0x02 << 8)
-#define LINKRATE_60(0x06 << 8)
+#define LINKRATE_60(0x04 << 8)
 #define LINKRATE_120   (0x08 << 8)
 
 /* phy_profile */
-- 
2.12.3



[PATCH V3 8/9] pm80xx : panic on ncq error cleaning up the read log.

2017-09-19 Thread Viswas G
when there's an error in 'ncq mode' the host has to read the ncq
error log (10h) to clear the error state. however, the ccb that
is setup for doing this doesn't setup the ccb so that the
previous state is cleared. if the ccb was previously used for an IO
n_elems is set and pm8001_ccb_task_free() treats this as the signal
to go free a scatter-gather list (that's already been free-ed).

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 92d2045dea68..f2c0839afbe3 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1489,6 +1489,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info 
*pm8001_ha,
ccb->device = pm8001_ha_dev;
ccb->ccb_tag = ccb_tag;
ccb->task = task;
+   ccb->n_elem = 0;
pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
 
-- 
2.12.3



[PATCH V3 6/9] pm80xx : modified port reset timer value for PM8006 card

2017-09-19 Thread Viswas G
Added port reset timer value as 2000ms for PM8006 sata controller.

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index baab8a19c78e..8f1f5dc77d71 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -597,6 +597,12 @@ static void update_main_config_table(struct 
pm8001_hba_info *pm8001_ha)
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &= 0x;
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |=
PORT_RECOVERY_TIMEOUT;
+   if (pm8001_ha->chip_id == chip_8006) {
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &=
+   0x;
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |=
+   0x14;
+   }
pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);
 }
-- 
2.12.3



[PATCH V3 7/9] pm80xx : corrected SATA abort handling sequence.

2017-09-19 Thread Viswas G
Modified SATA abort handling with following steps:
1) Set device state as recovery.
2) Send phy reset.
3) Wait for reset completion.
4) After successful reset, abort all IO's to the device.
5) After aborting all IO's to device, set device state as operational.

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c |  8 -
 drivers/scsi/pm8001/pm8001_sas.c | 71 ++--
 drivers/scsi/pm8001/pm8001_sas.h |  8 +
 drivers/scsi/pm8001/pm80xx_hwi.c | 36 
 4 files changed, 113 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index bc4a6f649ec9..db88a8e7ee0e 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3209,10 +3209,16 @@ int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info 
*pm8001_ha, void *piomb)
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op failed!\n",
phy_id, phy_op));
-   } else
+   } else {
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op success!\n",
phy_id, phy_op));
+   pm8001_ha->phy[phy_id].reset_success = true;
+   }
+   if (pm8001_ha->phy[phy_id].enable_completion) {
+   complete(pm8001_ha->phy[phy_id].enable_completion);
+   pm8001_ha->phy[phy_id].enable_completion = NULL;
+   }
pm8001_tag_free(pm8001_ha, tag);
return 0;
 }
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index e80b0542a67f..60d5bec5c45e 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -1167,13 +1167,16 @@ int pm8001_abort_task(struct sas_task *task)
struct scsi_lun lun;
struct pm8001_device *pm8001_dev;
struct pm8001_tmf_task tmf_task;
-   int rc = TMF_RESP_FUNC_FAILED;
+   int rc = TMF_RESP_FUNC_FAILED, ret;
+   u32 phy_id;
+   struct sas_task_slow slow_task;
if (unlikely(!task || !task->lldd_task || !task->dev))
return TMF_RESP_FUNC_FAILED;
dev = task->dev;
pm8001_dev = dev->lldd_dev;
pm8001_ha = pm8001_find_ha_by_dev(dev);
device_id = pm8001_dev->device_id;
+   phy_id = pm8001_dev->attached_phy;
rc = pm8001_find_tag(task, );
if (rc == 0) {
pm8001_printk("no tag for task:%p\n", task);
@@ -1184,6 +1187,11 @@ int pm8001_abort_task(struct sas_task *task)
spin_unlock_irqrestore(>task_state_lock, flags);
return TMF_RESP_FUNC_COMPLETE;
}
+   task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+   if (task->slow_task == NULL) {
+   init_completion(_task.completion);
+   task->slow_task = _task;
+   }
spin_unlock_irqrestore(>task_state_lock, flags);
if (task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd *cmnd = task->uldd_task;
@@ -1195,8 +1203,61 @@ int pm8001_abort_task(struct sas_task *task)
pm8001_dev->sas_device, 0, tag);
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) {
-   rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-   pm8001_dev->sas_device, 0, tag);
+   if (pm8001_ha->chip_id == chip_8006) {
+   DECLARE_COMPLETION_ONSTACK(completion_reset);
+   DECLARE_COMPLETION_ONSTACK(completion);
+   struct pm8001_phy *phy = pm8001_ha->phy + phy_id;
+   /* 1. Set Device state as Recovery*/
+   pm8001_dev->setds_completion = 
+   PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
+   pm8001_dev, 0x03);
+   wait_for_completion();
+   /* 2. Send Phy Control Hard Reset */
+   reinit_completion();
+   phy->reset_success = false;
+   phy->enable_completion = 
+   phy->reset_completion = _reset;
+   ret = PM8001_CHIP_DISP->phy_ctl_req(pm8001_ha, phy_id,
+   PHY_HARD_RESET);
+   if (ret)
+   goto out;
+   PM8001_MSG_DBG(pm8001_ha,
+   pm8001_printk("Waiting for local phy ctl\n"));
+   wait_for_completion();
+   if (!phy->reset_success)
+   

[PATCH V3 3/9] pm80xx : Different SAS addresses for phys.

2017-09-19 Thread Viswas G
Different SAS addresses are assigned for each set of phys.

Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm8001_init.c | 13 +
 drivers/scsi/pm8001/pm80xx_hwi.c  |  3 +--
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index 0e013f76b582..7a697ca68501 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -132,7 +132,7 @@ static void pm8001_phy_init(struct pm8001_hba_info 
*pm8001_ha, int phy_id)
sas_phy->oob_mode = OOB_NOT_CONNECTED;
sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
sas_phy->id = phy_id;
-   sas_phy->sas_addr = _ha->sas_addr[0];
+   sas_phy->sas_addr = (u8 *)>dev_sas_addr;
sas_phy->frame_rcvd = >frame_rcvd[0];
sas_phy->ha = (struct sas_ha_struct *)pm8001_ha->shost->hostdata;
sas_phy->lldd_phy = phy;
@@ -591,10 +591,12 @@ static void  pm8001_post_sas_ha_init(struct Scsi_Host 
*shost,
for (i = 0; i < chip_info->n_phy; i++) {
sha->sas_phy[i] = _ha->phy[i].sas_phy;
sha->sas_port[i] = _ha->port[i].sas_port;
+   sha->sas_phy[i]->sas_addr =
+   (u8 *)_ha->phy[i].dev_sas_addr;
}
sha->sas_ha_name = DRV_NAME;
sha->dev = pm8001_ha->dev;
-
+   sha->strict_wide_ports = 1;
sha->lldd_module = THIS_MODULE;
sha->sas_addr = _ha->sas_addr[0];
sha->num_phys = chip_info->n_phy;
@@ -611,6 +613,7 @@ static void  pm8001_post_sas_ha_init(struct Scsi_Host 
*shost,
 static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
 {
u8 i, j;
+   u8 sas_add[8];
 #ifdef PM8001_READ_VPD
/* For new SPC controllers WWN is stored in flash vpd
*  For SPC/SPCve controllers WWN is stored in EEPROM
@@ -672,10 +675,12 @@ static void pm8001_init_sas_add(struct pm8001_hba_info 
*pm8001_ha)
pm8001_ha->sas_addr[j] =
payload.func_specific[0x804 + i];
}
-
+   memcpy(sas_add, pm8001_ha->sas_addr, SAS_ADDR_SIZE);
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
+   if (i && ((i % 4) == 0))
+   sas_add[7] = sas_add[7] + 4;
memcpy(_ha->phy[i].dev_sas_addr,
-   pm8001_ha->sas_addr, SAS_ADDR_SIZE);
+   sas_add, SAS_ADDR_SIZE);
PM8001_INIT_DBG(pm8001_ha,
pm8001_printk("phy %d sas_addr = %016llx\n", i,
pm8001_ha->phy[i].dev_sas_addr));
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 8fb5ddf08cc4..2b26445d1b97 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -3041,7 +3041,6 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void 
*piomb)
port->port_state = portstate;
phy->identify.device_type = 0;
phy->phy_attached = 0;
-   memset(>dev_sas_addr, 0, SAS_ADDR_SIZE);
switch (portstate) {
case PORT_VALID:
break;
@@ -4394,7 +4393,7 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info 
*pm8001_ha, u8 phy_id)
payload.sas_identify.dev_type = SAS_END_DEVICE;
payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
memcpy(payload.sas_identify.sas_addr,
-   pm8001_ha->sas_addr, SAS_ADDR_SIZE);
+ _ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
payload.sas_identify.phy_id = phy_id;
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, , 0);
return ret;
-- 
2.12.3



[PATCH V3 0/9] pm80xx updates

2017-09-19 Thread Viswas G
This patch set include some bug fixes and enhancement for pm80xx driver.

Changes from V2:
- Corrected date.

Changes from V1:
- sas_identify_frame_local structure moved to pm80xx_hwi.h
- sata abort handling patch split to four patches.
- tag allocation for phy control request.
- cleanup in pm8001_abort_task function.
- modified port reset timer value for PM8006 card
- corrected SATA abort handling sequence.


Viswas G (9):
  pm80xx : redefine sas_identify_frame structure
  pm80xx : ILA and inactive firmware version through sysfs
  pm80xx : Different SAS addresses for phys.
  pm80xx : tag allocation for phy control request.
  pm80xx : cleanup in pm8001_abort_task function.
  pm80xx : modified port reset timer value for PM8006 card
  pm80xx : corrected SATA abort handling sequence.
  pm80xx : panic on ncq error cleaning up the read log.
  pm80xx : corrected linkrate value.

 drivers/scsi/pm8001/pm8001_ctl.c  |  54 +
 drivers/scsi/pm8001/pm8001_hwi.c  |  11 +++-
 drivers/scsi/pm8001/pm8001_init.c |  13 +++--
 drivers/scsi/pm8001/pm8001_sas.c  | 118 ++
 drivers/scsi/pm8001/pm8001_sas.h  |  10 
 drivers/scsi/pm8001/pm80xx_hwi.c  |  61 
 drivers/scsi/pm8001/pm80xx_hwi.h  | 102 +++-
 7 files changed, 313 insertions(+), 56 deletions(-)

-- 
2.12.3



[PATCH V3 4/9] pm80xx : tag allocation for phy control request.

2017-09-19 Thread Viswas G
tag is taken from the tag pool instead of using the hardcoded
tag value(1).

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c |  3 +++
 drivers/scsi/pm8001/pm80xx_hwi.c | 10 +++---
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 10546faac58c..bc4a6f649ec9 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3198,11 +3198,13 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info 
*pm8001_ha, void *piomb)
 
 int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
+   u32 tag;
struct local_phy_ctl_resp *pPayload =
(struct local_phy_ctl_resp *)(piomb + 4);
u32 status = le32_to_cpu(pPayload->status);
u32 phy_id = le32_to_cpu(pPayload->phyop_phyid) & ID_BITS;
u32 phy_op = le32_to_cpu(pPayload->phyop_phyid) & OP_BITS;
+   tag = le32_to_cpu(pPayload->tag);
if (status != 0) {
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op failed!\n",
@@ -3211,6 +3213,7 @@ int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info 
*pm8001_ha, void *piomb)
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op success!\n",
phy_id, phy_op));
+   pm8001_tag_free(pm8001_ha, tag);
return 0;
 }
 
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 2b26445d1b97..baab8a19c78e 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -4500,17 +4500,21 @@ static int pm80xx_chip_reg_dev_req(struct 
pm8001_hba_info *pm8001_ha,
 static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
u32 phyId, u32 phy_op)
 {
+   u32 tag;
+   int rc;
struct local_phy_ctl_req payload;
struct inbound_queue_table *circularQ;
int ret;
u32 opc = OPC_INB_LOCAL_PHY_CONTROL;
memset(, 0, sizeof(payload));
+   rc = pm8001_tag_alloc(pm8001_ha, );
+   if (rc)
+   return rc;
circularQ = _ha->inbnd_q_tbl[0];
-   payload.tag = cpu_to_le32(1);
+   payload.tag = cpu_to_le32(tag);
payload.phyop_phyid =
cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
-   ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, , 0);
-   return ret;
+   return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, , 0);
 }
 
 static u32 pm80xx_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha)
-- 
2.12.3



[PATCH V3 1/9] pm80xx : redefine sas_identify_frame structure

2017-09-19 Thread Viswas G
sas_identify structure defined by pm80xx doesn't have CRC field.
So added a new sas_identify structure without CRC.

v2:
- Since the structure changes is applicable for only pm80xx,
  sas_identify_frame_local structure moved to pm80xx_hwi.h.

Signed-off-by: Raj Dinesh <raj.din...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.h | 98 +++-
 1 file changed, 97 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 7a443bad6163..82b8cf581da9 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -229,6 +229,102 @@
 #define IT_NEXUS_TIMEOUT   0x7D0
 #define PORT_RECOVERY_TIMEOUT  ((IT_NEXUS_TIMEOUT/100) + 30)
 
+#ifdef __LITTLE_ENDIAN_BITFIELD
+struct sas_identify_frame_local {
+   /* Byte 0 */
+   u8  frame_type:4;
+   u8  dev_type:3;
+   u8  _un0:1;
+
+   /* Byte 1 */
+   u8  _un1;
+
+   /* Byte 2 */
+   union {
+   struct {
+   u8  _un20:1;
+   u8  smp_iport:1;
+   u8  stp_iport:1;
+   u8  ssp_iport:1;
+   u8  _un247:4;
+   };
+   u8 initiator_bits;
+   };
+
+   /* Byte 3 */
+   union {
+   struct {
+   u8  _un30:1;
+   u8 smp_tport:1;
+   u8 stp_tport:1;
+   u8 ssp_tport:1;
+   u8 _un347:4;
+   };
+   u8 target_bits;
+   };
+
+   /* Byte 4 - 11 */
+   u8 _un4_11[8];
+
+   /* Byte 12 - 19 */
+   u8 sas_addr[SAS_ADDR_SIZE];
+
+   /* Byte 20 */
+   u8 phy_id;
+
+   u8 _un21_27[7];
+
+} __packed;
+
+#elif defined(__BIG_ENDIAN_BITFIELD)
+struct sas_identify_frame_local {
+   /* Byte 0 */
+   u8  _un0:1;
+   u8  dev_type:3;
+   u8  frame_type:4;
+
+   /* Byte 1 */
+   u8  _un1;
+
+   /* Byte 2 */
+   union {
+   struct {
+   u8  _un247:4;
+   u8  ssp_iport:1;
+   u8  stp_iport:1;
+   u8  smp_iport:1;
+   u8  _un20:1;
+   };
+   u8 initiator_bits;
+   };
+
+   /* Byte 3 */
+   union {
+   struct {
+   u8 _un347:4;
+   u8 ssp_tport:1;
+   u8 stp_tport:1;
+   u8 smp_tport:1;
+   u8 _un30:1;
+   };
+   u8 target_bits;
+   };
+
+   /* Byte 4 - 11 */
+   u8 _un4_11[8];
+
+   /* Byte 12 - 19 */
+   u8 sas_addr[SAS_ADDR_SIZE];
+
+   /* Byte 20 */
+   u8 phy_id;
+
+   u8 _un21_27[7];
+} __packed;
+#else
+#error "Bitfield order not defined!"
+#endif
+
 struct mpi_msg_hdr {
__le32  header; /* Bits [11:0] - Message operation code */
/* Bits [15:12] - Message Category */
@@ -248,7 +344,7 @@ struct mpi_msg_hdr {
 struct phy_start_req {
__le32  tag;
__le32  ase_sh_lm_slr_phyid;
-   struct sas_identify_frame sas_identify; /* 28 Bytes */
+   struct sas_identify_frame_local sas_identify; /* 28 Bytes */
__le32 spasti;
u32 reserved[21];
 } __attribute__((packed, aligned(4)));
-- 
2.12.3



[PATCH V3 5/9] pm80xx : cleanup in pm8001_abort_task function.

2017-09-19 Thread Viswas G
Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm8001_sas.c | 49 +++-
 1 file changed, 13 insertions(+), 36 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index ce584c31d36e..e80b0542a67f 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -1159,40 +1159,35 @@ int pm8001_query_task(struct sas_task *task)
 int pm8001_abort_task(struct sas_task *task)
 {
unsigned long flags;
-   u32 tag = 0xdeadbeef;
+   u32 tag;
u32 device_id;
struct domain_device *dev ;
-   struct pm8001_hba_info *pm8001_ha = NULL;
+   struct pm8001_hba_info *pm8001_ha;
struct pm8001_ccb_info *ccb;
struct scsi_lun lun;
struct pm8001_device *pm8001_dev;
struct pm8001_tmf_task tmf_task;
int rc = TMF_RESP_FUNC_FAILED;
if (unlikely(!task || !task->lldd_task || !task->dev))
-   return rc;
+   return TMF_RESP_FUNC_FAILED;
+   dev = task->dev;
+   pm8001_dev = dev->lldd_dev;
+   pm8001_ha = pm8001_find_ha_by_dev(dev);
+   device_id = pm8001_dev->device_id;
+   rc = pm8001_find_tag(task, );
+   if (rc == 0) {
+   pm8001_printk("no tag for task:%p\n", 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;
+   return TMF_RESP_FUNC_COMPLETE;
}
spin_unlock_irqrestore(>task_state_lock, flags);
if (task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd *cmnd = task->uldd_task;
-   dev = task->dev;
-   ccb = task->lldd_task;
-   pm8001_dev = dev->lldd_dev;
-   pm8001_ha = pm8001_find_ha_by_dev(dev);
int_to_scsilun(cmnd->device->lun, );
-   rc = pm8001_find_tag(task, );
-   if (rc == 0) {
-   printk(KERN_INFO "No such tag in %s\n", __func__);
-   rc = TMF_RESP_FUNC_FAILED;
-   return rc;
-   }
-   device_id = pm8001_dev->device_id;
-   PM8001_EH_DBG(pm8001_ha,
-   pm8001_printk("abort io to deviceid= %d\n", device_id));
tmf_task.tmf = TMF_ABORT_TASK;
tmf_task.tag_of_task_to_be_managed = tag;
rc = pm8001_issue_ssp_tmf(dev, lun.scsi_lun, _task);
@@ -1200,28 +1195,10 @@ int pm8001_abort_task(struct sas_task *task)
pm8001_dev->sas_device, 0, tag);
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) {
-   dev = task->dev;
-   pm8001_dev = dev->lldd_dev;
-   pm8001_ha = pm8001_find_ha_by_dev(dev);
-   rc = pm8001_find_tag(task, );
-   if (rc == 0) {
-   printk(KERN_INFO "No such tag in %s\n", __func__);
-   rc = TMF_RESP_FUNC_FAILED;
-   return rc;
-   }
rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
pm8001_dev->sas_device, 0, tag);
} else if (task->task_proto & SAS_PROTOCOL_SMP) {
/* SMP */
-   dev = task->dev;
-   pm8001_dev = dev->lldd_dev;
-   pm8001_ha = pm8001_find_ha_by_dev(dev);
-   rc = pm8001_find_tag(task, );
-   if (rc == 0) {
-   printk(KERN_INFO "No such tag in %s\n", __func__);
-   rc = TMF_RESP_FUNC_FAILED;
-   return rc;
-   }
rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
pm8001_dev->sas_device, 0, tag);
 
-- 
2.12.3



[PATCH V3 2/9] pm80xx : ILA and inactive firmware version through sysfs

2017-09-19 Thread Viswas G
Added support to read ILA version and inactive firmware version
from MPI configuration table and export through sysfs.

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c | 54 
 drivers/scsi/pm8001/pm8001_sas.h |  2 ++
 drivers/scsi/pm8001/pm80xx_hwi.c |  5 
 drivers/scsi/pm8001/pm80xx_hwi.h |  2 ++
 4 files changed, 63 insertions(+)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index be8269c8d127..596f3ff965f5 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -98,6 +98,58 @@ static ssize_t pm8001_ctl_fw_version_show(struct device 
*cdev,
}
 }
 static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL);
+
+/**
+ * pm8001_ctl_ila_version_show - ila version
+ * @cdev: pointer to embedded class device
+ * @buf: the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t pm8001_ctl_ila_version_show(struct device *cdev,
+   struct device_attribute *attr, char *buf)
+{
+   struct Scsi_Host *shost = class_to_shost(cdev);
+   struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+   struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+   if (pm8001_ha->chip_id != chip_8001) {
+   return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 24),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 16),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 8),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version));
+   }
+   return 0;
+}
+static DEVICE_ATTR(ila_version, 0444, pm8001_ctl_ila_version_show, NULL);
+
+/**
+ * pm8001_ctl_inactive_fw_version_show - Inacative firmware version number
+ * @cdev: pointer to embedded class device
+ * @buf: the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t pm8001_ctl_inactive_fw_version_show(struct device *cdev,
+   struct device_attribute *attr, char *buf)
+{
+   struct Scsi_Host *shost = class_to_shost(cdev);
+   struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+   struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+   if (pm8001_ha->chip_id != chip_8001) {
+   return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 24),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 16),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 8),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version));
+   }
+   return 0;
+}
+static
+DEVICE_ATTR(inc_fw_ver, 0444, pm8001_ctl_inactive_fw_version_show, NULL);
+
 /**
  * pm8001_ctl_max_out_io_show - max outstanding io supported
  * @cdev: pointer to embedded class device
@@ -748,6 +800,8 @@ struct device_attribute *pm8001_host_attrs[] = {
_attr_bios_version,
_attr_ib_log,
_attr_ob_log,
+   _attr_ila_version,
+   _attr_inc_fw_ver,
NULL,
 };
 
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index e81a8fa7ef1a..c75de413e062 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -404,6 +404,8 @@ union main_cfg_table {
u32 port_recovery_timer;
u32 interrupt_reassertion_delay;
u32 fatal_n_non_fatal_dump; /* 0x28 */
+   u32 ila_version;
+   u32 inc_fw_version;
} pm80xx_tbl;
 };
 
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index eb4fee61df72..8fb5ddf08cc4 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -312,6 +312,11 @@ static void read_main_config_table(struct pm8001_hba_info 
*pm8001_ha)
/* read port recover and reset timeout */
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer =
pm8001_mr32(address, MAIN_PORT_RECOVERY_TIMER);
+   /* read ILA and inactive firmware version */
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version =
+   pm8001_mr32(address, MAIN_MPI_ILA_RELEASE_TYPE);
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version =
+   pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION);
 }
 
 /**
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 82b8cf581da9..e36c5176f9a9 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -1445,6 +1445,8 @@ typedef struct SASProtocolTimerConfig 
SASProtocolTi

RE: [PATCH V2 0/9] pm80xx updates

2017-09-15 Thread Viswas G
Thanks Martin.

Do we need to send V3 patch set with corrected date ? 

Regards,
Viswas G

> -Original Message-
> From: Martin K. Petersen [mailto:martin.peter...@oracle.com]
> Sent: Saturday, September 16, 2017 1:06 AM
> To: Viswas G <viswa...@microsemi.com>
> Cc: linux-scsi@vger.kernel.org; Vasanthalakshmi Tharmarajan
> <vasanthalakshmi.t...@microsemi.com>; Deepak Ukey
> <deepak.u...@microsemi.com>; Raj Dinesh <raj.din...@microsemi.com>;
> jinpu.w...@profitbricks.com; martin.peter...@oracle.com
> Subject: Re: [PATCH V2 0/9] pm80xx updates
> 
> EXTERNAL EMAIL
> 
> 
> Viswas,
> 
> > This patch set include some bug fixes and enhancement for pm80xx
> > driver.
> 
> You are still sending mail from 2015. Please fix your system
> time. Thanks!
> 
> --
> Martin K. Petersen  Oracle Linux Engineering


[PATCH V2 4/9] pm80xx : tag allocation for phy control request.

2017-09-13 Thread Viswas G
tag is taken from the tag pool instead of using the hardcoded
tag value(1).

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c |  3 +++
 drivers/scsi/pm8001/pm80xx_hwi.c | 10 +++---
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 10546faac58c..bc4a6f649ec9 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3198,11 +3198,13 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info 
*pm8001_ha, void *piomb)
 
 int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
+   u32 tag;
struct local_phy_ctl_resp *pPayload =
(struct local_phy_ctl_resp *)(piomb + 4);
u32 status = le32_to_cpu(pPayload->status);
u32 phy_id = le32_to_cpu(pPayload->phyop_phyid) & ID_BITS;
u32 phy_op = le32_to_cpu(pPayload->phyop_phyid) & OP_BITS;
+   tag = le32_to_cpu(pPayload->tag);
if (status != 0) {
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op failed!\n",
@@ -3211,6 +3213,7 @@ int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info 
*pm8001_ha, void *piomb)
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op success!\n",
phy_id, phy_op));
+   pm8001_tag_free(pm8001_ha, tag);
return 0;
 }
 
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 2b26445d1b97..baab8a19c78e 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -4500,17 +4500,21 @@ static int pm80xx_chip_reg_dev_req(struct 
pm8001_hba_info *pm8001_ha,
 static int pm80xx_chip_phy_ctl_req(struct pm8001_hba_info *pm8001_ha,
u32 phyId, u32 phy_op)
 {
+   u32 tag;
+   int rc;
struct local_phy_ctl_req payload;
struct inbound_queue_table *circularQ;
int ret;
u32 opc = OPC_INB_LOCAL_PHY_CONTROL;
memset(, 0, sizeof(payload));
+   rc = pm8001_tag_alloc(pm8001_ha, );
+   if (rc)
+   return rc;
circularQ = _ha->inbnd_q_tbl[0];
-   payload.tag = cpu_to_le32(1);
+   payload.tag = cpu_to_le32(tag);
payload.phyop_phyid =
cpu_to_le32(((phy_op & 0xFF) << 8) | (phyId & 0xFF));
-   ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, , 0);
-   return ret;
+   return pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, , 0);
 }
 
 static u32 pm80xx_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha)
-- 
2.12.3



[PATCH V2 1/9] pm80xx : redefine sas_identify_frame structure

2017-09-13 Thread Viswas G
sas_identify structure defined by pm80xx doesn't have CRC field.
So added a new sas_identify structure without CRC.

v2:
- Since the structure changes is applicable for only pm80xx,
  sas_identify_frame_local structure moved to pm80xx_hwi.h.

Signed-off-by: Raj Dinesh <raj.din...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.h | 98 +++-
 1 file changed, 97 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 7a443bad6163..82b8cf581da9 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -229,6 +229,102 @@
 #define IT_NEXUS_TIMEOUT   0x7D0
 #define PORT_RECOVERY_TIMEOUT  ((IT_NEXUS_TIMEOUT/100) + 30)
 
+#ifdef __LITTLE_ENDIAN_BITFIELD
+struct sas_identify_frame_local {
+   /* Byte 0 */
+   u8  frame_type:4;
+   u8  dev_type:3;
+   u8  _un0:1;
+
+   /* Byte 1 */
+   u8  _un1;
+
+   /* Byte 2 */
+   union {
+   struct {
+   u8  _un20:1;
+   u8  smp_iport:1;
+   u8  stp_iport:1;
+   u8  ssp_iport:1;
+   u8  _un247:4;
+   };
+   u8 initiator_bits;
+   };
+
+   /* Byte 3 */
+   union {
+   struct {
+   u8  _un30:1;
+   u8 smp_tport:1;
+   u8 stp_tport:1;
+   u8 ssp_tport:1;
+   u8 _un347:4;
+   };
+   u8 target_bits;
+   };
+
+   /* Byte 4 - 11 */
+   u8 _un4_11[8];
+
+   /* Byte 12 - 19 */
+   u8 sas_addr[SAS_ADDR_SIZE];
+
+   /* Byte 20 */
+   u8 phy_id;
+
+   u8 _un21_27[7];
+
+} __packed;
+
+#elif defined(__BIG_ENDIAN_BITFIELD)
+struct sas_identify_frame_local {
+   /* Byte 0 */
+   u8  _un0:1;
+   u8  dev_type:3;
+   u8  frame_type:4;
+
+   /* Byte 1 */
+   u8  _un1;
+
+   /* Byte 2 */
+   union {
+   struct {
+   u8  _un247:4;
+   u8  ssp_iport:1;
+   u8  stp_iport:1;
+   u8  smp_iport:1;
+   u8  _un20:1;
+   };
+   u8 initiator_bits;
+   };
+
+   /* Byte 3 */
+   union {
+   struct {
+   u8 _un347:4;
+   u8 ssp_tport:1;
+   u8 stp_tport:1;
+   u8 smp_tport:1;
+   u8 _un30:1;
+   };
+   u8 target_bits;
+   };
+
+   /* Byte 4 - 11 */
+   u8 _un4_11[8];
+
+   /* Byte 12 - 19 */
+   u8 sas_addr[SAS_ADDR_SIZE];
+
+   /* Byte 20 */
+   u8 phy_id;
+
+   u8 _un21_27[7];
+} __packed;
+#else
+#error "Bitfield order not defined!"
+#endif
+
 struct mpi_msg_hdr {
__le32  header; /* Bits [11:0] - Message operation code */
/* Bits [15:12] - Message Category */
@@ -248,7 +344,7 @@ struct mpi_msg_hdr {
 struct phy_start_req {
__le32  tag;
__le32  ase_sh_lm_slr_phyid;
-   struct sas_identify_frame sas_identify; /* 28 Bytes */
+   struct sas_identify_frame_local sas_identify; /* 28 Bytes */
__le32 spasti;
u32 reserved[21];
 } __attribute__((packed, aligned(4)));
-- 
2.12.3



[PATCH V2 3/9] pm80xx : Different SAS addresses for phys.

2017-09-13 Thread Viswas G
Different SAS addresses are assigned for each set of phys.

Signed-off-by: Viswas G <viswa...@microsemi.com>
Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm8001_init.c | 13 +
 drivers/scsi/pm8001/pm80xx_hwi.c  |  3 +--
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index 034b2f7d1135..d282f1562615 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -132,7 +132,7 @@ static void pm8001_phy_init(struct pm8001_hba_info 
*pm8001_ha, int phy_id)
sas_phy->oob_mode = OOB_NOT_CONNECTED;
sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
sas_phy->id = phy_id;
-   sas_phy->sas_addr = _ha->sas_addr[0];
+   sas_phy->sas_addr = (u8 *)>dev_sas_addr;
sas_phy->frame_rcvd = >frame_rcvd[0];
sas_phy->ha = (struct sas_ha_struct *)pm8001_ha->shost->hostdata;
sas_phy->lldd_phy = phy;
@@ -593,10 +593,12 @@ static void  pm8001_post_sas_ha_init(struct Scsi_Host 
*shost,
for (i = 0; i < chip_info->n_phy; i++) {
sha->sas_phy[i] = _ha->phy[i].sas_phy;
sha->sas_port[i] = _ha->port[i].sas_port;
+   sha->sas_phy[i]->sas_addr =
+   (u8 *)_ha->phy[i].dev_sas_addr;
}
sha->sas_ha_name = DRV_NAME;
sha->dev = pm8001_ha->dev;
-
+   sha->strict_wide_ports = 1;
sha->lldd_module = THIS_MODULE;
sha->sas_addr = _ha->sas_addr[0];
sha->num_phys = chip_info->n_phy;
@@ -613,6 +615,7 @@ static void  pm8001_post_sas_ha_init(struct Scsi_Host 
*shost,
 static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
 {
u8 i, j;
+   u8 sas_add[8];
 #ifdef PM8001_READ_VPD
/* For new SPC controllers WWN is stored in flash vpd
*  For SPC/SPCve controllers WWN is stored in EEPROM
@@ -674,10 +677,12 @@ static void pm8001_init_sas_add(struct pm8001_hba_info 
*pm8001_ha)
pm8001_ha->sas_addr[j] =
payload.func_specific[0x804 + i];
}
-
+   memcpy(sas_add, pm8001_ha->sas_addr, SAS_ADDR_SIZE);
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
+   if (i && ((i % 4) == 0))
+   sas_add[7] = sas_add[7] + 4;
memcpy(_ha->phy[i].dev_sas_addr,
-   pm8001_ha->sas_addr, SAS_ADDR_SIZE);
+   sas_add, SAS_ADDR_SIZE);
PM8001_INIT_DBG(pm8001_ha,
pm8001_printk("phy %d sas_addr = %016llx\n", i,
pm8001_ha->phy[i].dev_sas_addr));
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 8fb5ddf08cc4..2b26445d1b97 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -3041,7 +3041,6 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void 
*piomb)
port->port_state = portstate;
phy->identify.device_type = 0;
phy->phy_attached = 0;
-   memset(>dev_sas_addr, 0, SAS_ADDR_SIZE);
switch (portstate) {
case PORT_VALID:
break;
@@ -4394,7 +4393,7 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info 
*pm8001_ha, u8 phy_id)
payload.sas_identify.dev_type = SAS_END_DEVICE;
payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
memcpy(payload.sas_identify.sas_addr,
-   pm8001_ha->sas_addr, SAS_ADDR_SIZE);
+ _ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
payload.sas_identify.phy_id = phy_id;
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, , 0);
return ret;
-- 
2.12.3



[PATCH V2 6/9] pm80xx : modified port reset timer value for PM8006 card

2017-09-13 Thread Viswas G
Added port reset timer value as 2000ms for PM8006 sata controller.

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index baab8a19c78e..8f1f5dc77d71 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -597,6 +597,12 @@ static void update_main_config_table(struct 
pm8001_hba_info *pm8001_ha)
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &= 0x;
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |=
PORT_RECOVERY_TIMEOUT;
+   if (pm8001_ha->chip_id == chip_8006) {
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer &=
+   0x;
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer |=
+   0x14;
+   }
pm8001_mw32(address, MAIN_PORT_RECOVERY_TIMER,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer);
 }
-- 
2.12.3



[PATCH V2 9/9] pm80xx : corrected linkrate value.

2017-09-13 Thread Viswas G
Corrected the value defined for LINKRATE_60 (6 Gig).

Signed-off-by: Raj Dinesh <raj.din...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>
Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index e36c5176f9a9..889e69ce3689 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -167,7 +167,7 @@
 #define LINKMODE_AUTO  (0x03 << 12)
 #define LINKRATE_15(0x01 << 8)
 #define LINKRATE_30(0x02 << 8)
-#define LINKRATE_60(0x06 << 8)
+#define LINKRATE_60(0x04 << 8)
 #define LINKRATE_120   (0x08 << 8)
 
 /* phy_profile */
-- 
2.12.3



[PATCH V2 2/9] pm80xx : ILA and inactive firmware version through sysfs

2017-09-13 Thread Viswas G
Added support to read ILA version and inactive firmware version
from MPI configuration table and export through sysfs.

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>

Acked-by: Jack Wang <jinpu.w...@profitbricks.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c | 54 
 drivers/scsi/pm8001/pm8001_sas.h |  2 ++
 drivers/scsi/pm8001/pm80xx_hwi.c |  5 
 drivers/scsi/pm8001/pm80xx_hwi.h |  2 ++
 4 files changed, 63 insertions(+)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index be8269c8d127..596f3ff965f5 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -98,6 +98,58 @@ static ssize_t pm8001_ctl_fw_version_show(struct device 
*cdev,
}
 }
 static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL);
+
+/**
+ * pm8001_ctl_ila_version_show - ila version
+ * @cdev: pointer to embedded class device
+ * @buf: the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t pm8001_ctl_ila_version_show(struct device *cdev,
+   struct device_attribute *attr, char *buf)
+{
+   struct Scsi_Host *shost = class_to_shost(cdev);
+   struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+   struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+   if (pm8001_ha->chip_id != chip_8001) {
+   return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 24),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 16),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 8),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version));
+   }
+   return 0;
+}
+static DEVICE_ATTR(ila_version, 0444, pm8001_ctl_ila_version_show, NULL);
+
+/**
+ * pm8001_ctl_inactive_fw_version_show - Inacative firmware version number
+ * @cdev: pointer to embedded class device
+ * @buf: the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t pm8001_ctl_inactive_fw_version_show(struct device *cdev,
+   struct device_attribute *attr, char *buf)
+{
+   struct Scsi_Host *shost = class_to_shost(cdev);
+   struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+   struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+   if (pm8001_ha->chip_id != chip_8001) {
+   return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 24),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 16),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 8),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version));
+   }
+   return 0;
+}
+static
+DEVICE_ATTR(inc_fw_ver, 0444, pm8001_ctl_inactive_fw_version_show, NULL);
+
 /**
  * pm8001_ctl_max_out_io_show - max outstanding io supported
  * @cdev: pointer to embedded class device
@@ -748,6 +800,8 @@ struct device_attribute *pm8001_host_attrs[] = {
_attr_bios_version,
_attr_ib_log,
_attr_ob_log,
+   _attr_ila_version,
+   _attr_inc_fw_ver,
NULL,
 };
 
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index e81a8fa7ef1a..c75de413e062 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -404,6 +404,8 @@ union main_cfg_table {
u32 port_recovery_timer;
u32 interrupt_reassertion_delay;
u32 fatal_n_non_fatal_dump; /* 0x28 */
+   u32 ila_version;
+   u32 inc_fw_version;
} pm80xx_tbl;
 };
 
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index eb4fee61df72..8fb5ddf08cc4 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -312,6 +312,11 @@ static void read_main_config_table(struct pm8001_hba_info 
*pm8001_ha)
/* read port recover and reset timeout */
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer =
pm8001_mr32(address, MAIN_PORT_RECOVERY_TIMER);
+   /* read ILA and inactive firmware version */
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version =
+   pm8001_mr32(address, MAIN_MPI_ILA_RELEASE_TYPE);
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version =
+   pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION);
 }
 
 /**
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 82b8cf581da9..e36c5176f9a9 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -1445,6 +1445,8 @@ typedef struct SASProtocolTimerConfig 
SASProtocolTi

[PATCH V2 8/9] pm80xx : panic on ncq error cleaning up the read log.

2017-09-13 Thread Viswas G
when there's an error in 'ncq mode' the host has to read the ncq
error log (10h) to clear the error state. however, the ccb that
is setup for doing this doesn't setup the ccb so that the
previous state is cleared. if the ccb was previously used for an IO
n_elems is set and pm8001_ccb_task_free() treats this as the signal
to go free a scatter-gather list (that's already been free-ed).

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 92d2045dea68..f2c0839afbe3 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1489,6 +1489,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info 
*pm8001_ha,
ccb->device = pm8001_ha_dev;
ccb->ccb_tag = ccb_tag;
ccb->task = task;
+   ccb->n_elem = 0;
pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
 
-- 
2.12.3



[PATCH V2 0/9] pm80xx updates

2017-09-13 Thread Viswas G
This patch set include some bug fixes and enhancement for pm80xx driver.

Changes from V1:

- sas_identify_frame_local structure moved to pm80xx_hwi.h
- sata abort handling patch split to four patches.
- tag allocation for phy control request.
- cleanup in pm8001_abort_task function.
- modified port reset timer value for PM8006 card
- corrected SATA abort handling sequence.

Viswas G (9):
  pm80xx : redefine sas_identify_frame structure
  pm80xx : ILA and inactive firmware version through sysfs
  pm80xx : Different SAS addresses for phys.
  pm80xx : tag allocation for phy control request.
  pm80xx : cleanup in pm8001_abort_task function.
  pm80xx : modified port reset timer value for PM8006 card
  pm80xx : corrected SATA abort handling sequence.
  pm80xx : panic on ncq error cleaning up the read log.
  pm80xx : corrected linkrate value.

 drivers/scsi/pm8001/pm8001_ctl.c  |  54 +
 drivers/scsi/pm8001/pm8001_hwi.c  |  11 +++-
 drivers/scsi/pm8001/pm8001_init.c |  13 +++--
 drivers/scsi/pm8001/pm8001_sas.c  | 118 ++
 drivers/scsi/pm8001/pm8001_sas.h  |  10 
 drivers/scsi/pm8001/pm80xx_hwi.c  |  61 
 drivers/scsi/pm8001/pm80xx_hwi.h  | 102 +++-
 7 files changed, 313 insertions(+), 56 deletions(-)

-- 
2.12.3



[PATCH V2 7/9] pm80xx : corrected SATA abort handling sequence.

2017-09-13 Thread Viswas G
Modified SATA abort handling with following steps:
1) Set device state as recovery.
2) Send phy reset.
3) Wait for reset completion.
4) After successful reset, abort all IO's to the device.
5) After aborting all IO's to device, set device state as operational.

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c |  8 -
 drivers/scsi/pm8001/pm8001_sas.c | 71 ++--
 drivers/scsi/pm8001/pm8001_sas.h |  8 +
 drivers/scsi/pm8001/pm80xx_hwi.c | 36 
 4 files changed, 113 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index bc4a6f649ec9..db88a8e7ee0e 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3209,10 +3209,16 @@ int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info 
*pm8001_ha, void *piomb)
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op failed!\n",
phy_id, phy_op));
-   } else
+   } else {
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op success!\n",
phy_id, phy_op));
+   pm8001_ha->phy[phy_id].reset_success = true;
+   }
+   if (pm8001_ha->phy[phy_id].enable_completion) {
+   complete(pm8001_ha->phy[phy_id].enable_completion);
+   pm8001_ha->phy[phy_id].enable_completion = NULL;
+   }
pm8001_tag_free(pm8001_ha, tag);
return 0;
 }
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index e80b0542a67f..60d5bec5c45e 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -1167,13 +1167,16 @@ int pm8001_abort_task(struct sas_task *task)
struct scsi_lun lun;
struct pm8001_device *pm8001_dev;
struct pm8001_tmf_task tmf_task;
-   int rc = TMF_RESP_FUNC_FAILED;
+   int rc = TMF_RESP_FUNC_FAILED, ret;
+   u32 phy_id;
+   struct sas_task_slow slow_task;
if (unlikely(!task || !task->lldd_task || !task->dev))
return TMF_RESP_FUNC_FAILED;
dev = task->dev;
pm8001_dev = dev->lldd_dev;
pm8001_ha = pm8001_find_ha_by_dev(dev);
device_id = pm8001_dev->device_id;
+   phy_id = pm8001_dev->attached_phy;
rc = pm8001_find_tag(task, );
if (rc == 0) {
pm8001_printk("no tag for task:%p\n", task);
@@ -1184,6 +1187,11 @@ int pm8001_abort_task(struct sas_task *task)
spin_unlock_irqrestore(>task_state_lock, flags);
return TMF_RESP_FUNC_COMPLETE;
}
+   task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+   if (task->slow_task == NULL) {
+   init_completion(_task.completion);
+   task->slow_task = _task;
+   }
spin_unlock_irqrestore(>task_state_lock, flags);
if (task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd *cmnd = task->uldd_task;
@@ -1195,8 +1203,61 @@ int pm8001_abort_task(struct sas_task *task)
pm8001_dev->sas_device, 0, tag);
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) {
-   rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
-   pm8001_dev->sas_device, 0, tag);
+   if (pm8001_ha->chip_id == chip_8006) {
+   DECLARE_COMPLETION_ONSTACK(completion_reset);
+   DECLARE_COMPLETION_ONSTACK(completion);
+   struct pm8001_phy *phy = pm8001_ha->phy + phy_id;
+   /* 1. Set Device state as Recovery*/
+   pm8001_dev->setds_completion = 
+   PM8001_CHIP_DISP->set_dev_state_req(pm8001_ha,
+   pm8001_dev, 0x03);
+   wait_for_completion();
+   /* 2. Send Phy Control Hard Reset */
+   reinit_completion();
+   phy->reset_success = false;
+   phy->enable_completion = 
+   phy->reset_completion = _reset;
+   ret = PM8001_CHIP_DISP->phy_ctl_req(pm8001_ha, phy_id,
+   PHY_HARD_RESET);
+   if (ret)
+   goto out;
+   PM8001_MSG_DBG(pm8001_ha,
+   pm8001_printk("Waiting for local phy ctl\n"));
+   wait_for_completion();
+   if (!phy->reset_success)
+   goto out;
+   /* 3. Wait for Port R

[PATCH V2 5/9] pm80xx : cleanup in pm8001_abort_task function.

2017-09-13 Thread Viswas G
Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>
---
 drivers/scsi/pm8001/pm8001_sas.c | 49 +++-
 1 file changed, 13 insertions(+), 36 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index ce584c31d36e..e80b0542a67f 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -1159,40 +1159,35 @@ int pm8001_query_task(struct sas_task *task)
 int pm8001_abort_task(struct sas_task *task)
 {
unsigned long flags;
-   u32 tag = 0xdeadbeef;
+   u32 tag;
u32 device_id;
struct domain_device *dev ;
-   struct pm8001_hba_info *pm8001_ha = NULL;
+   struct pm8001_hba_info *pm8001_ha;
struct pm8001_ccb_info *ccb;
struct scsi_lun lun;
struct pm8001_device *pm8001_dev;
struct pm8001_tmf_task tmf_task;
int rc = TMF_RESP_FUNC_FAILED;
if (unlikely(!task || !task->lldd_task || !task->dev))
-   return rc;
+   return TMF_RESP_FUNC_FAILED;
+   dev = task->dev;
+   pm8001_dev = dev->lldd_dev;
+   pm8001_ha = pm8001_find_ha_by_dev(dev);
+   device_id = pm8001_dev->device_id;
+   rc = pm8001_find_tag(task, );
+   if (rc == 0) {
+   pm8001_printk("no tag for task:%p\n", 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;
+   return TMF_RESP_FUNC_COMPLETE;
}
spin_unlock_irqrestore(>task_state_lock, flags);
if (task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd *cmnd = task->uldd_task;
-   dev = task->dev;
-   ccb = task->lldd_task;
-   pm8001_dev = dev->lldd_dev;
-   pm8001_ha = pm8001_find_ha_by_dev(dev);
int_to_scsilun(cmnd->device->lun, );
-   rc = pm8001_find_tag(task, );
-   if (rc == 0) {
-   printk(KERN_INFO "No such tag in %s\n", __func__);
-   rc = TMF_RESP_FUNC_FAILED;
-   return rc;
-   }
-   device_id = pm8001_dev->device_id;
-   PM8001_EH_DBG(pm8001_ha,
-   pm8001_printk("abort io to deviceid= %d\n", device_id));
tmf_task.tmf = TMF_ABORT_TASK;
tmf_task.tag_of_task_to_be_managed = tag;
rc = pm8001_issue_ssp_tmf(dev, lun.scsi_lun, _task);
@@ -1200,28 +1195,10 @@ int pm8001_abort_task(struct sas_task *task)
pm8001_dev->sas_device, 0, tag);
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) {
-   dev = task->dev;
-   pm8001_dev = dev->lldd_dev;
-   pm8001_ha = pm8001_find_ha_by_dev(dev);
-   rc = pm8001_find_tag(task, );
-   if (rc == 0) {
-   printk(KERN_INFO "No such tag in %s\n", __func__);
-   rc = TMF_RESP_FUNC_FAILED;
-   return rc;
-   }
rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
pm8001_dev->sas_device, 0, tag);
} else if (task->task_proto & SAS_PROTOCOL_SMP) {
/* SMP */
-   dev = task->dev;
-   pm8001_dev = dev->lldd_dev;
-   pm8001_ha = pm8001_find_ha_by_dev(dev);
-   rc = pm8001_find_tag(task, );
-   if (rc == 0) {
-   printk(KERN_INFO "No such tag in %s\n", __func__);
-   rc = TMF_RESP_FUNC_FAILED;
-   return rc;
-   }
rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev,
pm8001_dev->sas_device, 0, tag);
 
-- 
2.12.3



RE: [PATCH 3/6] pm80xx : Different SAS addresses for phys.

2017-08-30 Thread Viswas G
Hi Jack,

This is a customer requirement. Since the SAS addresses of all the phys were 
same , when the attached SAS addresses are different, it was forming only one 
domain.  If we assign different SAS addresses, this will cause duplicate domain 
unless we set the strict_wide_port to 1.

Regards,
Viswas G


> -Original Message-
> From: Jack Wang [mailto:xjtu...@gmail.com]
> Sent: Tuesday, August 29, 2017 4:55 PM
> To: Viswas G <viswa...@microsemi.com>
> Cc: linux-scsi@vger.kernel.org; Vasanthalakshmi Tharmarajan
> <vasanthalakshmi.t...@microsemi.com>
> Subject: Re: [PATCH 3/6] pm80xx : Different SAS addresses for phys.
> 
> EXTERNAL EMAIL
> 
> 
> 2015-01-30 7:06 GMT+01:00 Viswas G <viswa...@microsemi.com>:
> > Different SAS addresses are assigned for each set of phys.
> >
> > Signed-off-by: Viswas G <viswa...@microsemi.com>
> > ---
> >  drivers/scsi/pm8001/pm8001_init.c | 13 +
> >  drivers/scsi/pm8001/pm80xx_hwi.c  |  3 +--
> >  2 files changed, 10 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/scsi/pm8001/pm8001_init.c
> b/drivers/scsi/pm8001/pm8001_init.c
> > index 034b2f7d1135..d282f1562615 100644
> > --- a/drivers/scsi/pm8001/pm8001_init.c
> > +++ b/drivers/scsi/pm8001/pm8001_init.c
> > @@ -132,7 +132,7 @@ static void pm8001_phy_init(struct
> pm8001_hba_info *pm8001_ha, int phy_id)
> > sas_phy->oob_mode = OOB_NOT_CONNECTED;
> > sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
> > sas_phy->id = phy_id;
> > -   sas_phy->sas_addr = _ha->sas_addr[0];
> > +   sas_phy->sas_addr = (u8 *)>dev_sas_addr;
> > sas_phy->frame_rcvd = >frame_rcvd[0];
> > sas_phy->ha = (struct sas_ha_struct *)pm8001_ha->shost->hostdata;
> > sas_phy->lldd_phy = phy;
> > @@ -593,10 +593,12 @@ static void  pm8001_post_sas_ha_init(struct
> Scsi_Host *shost,
> > for (i = 0; i < chip_info->n_phy; i++) {
> > sha->sas_phy[i] = _ha->phy[i].sas_phy;
> > sha->sas_port[i] = _ha->port[i].sas_port;
> > +   sha->sas_phy[i]->sas_addr =
> > +   (u8 *)_ha->phy[i].dev_sas_addr;
> > }
> > sha->sas_ha_name = DRV_NAME;
> > sha->dev = pm8001_ha->dev;
> > -
> > +   sha->strict_wide_ports = 1;
> > sha->lldd_module = THIS_MODULE;
> > sha->sas_addr = _ha->sas_addr[0];
> > sha->num_phys = chip_info->n_phy;
> > @@ -613,6 +615,7 @@ static void  pm8001_post_sas_ha_init(struct
> Scsi_Host *shost,
> >  static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
> >  {
> > u8 i, j;
> > +   u8 sas_add[8];
> >  #ifdef PM8001_READ_VPD
> > /* For new SPC controllers WWN is stored in flash vpd
> > *  For SPC/SPCve controllers WWN is stored in EEPROM
> > @@ -674,10 +677,12 @@ static void pm8001_init_sas_add(struct
> pm8001_hba_info *pm8001_ha)
> > pm8001_ha->sas_addr[j] =
> > payload.func_specific[0x804 + i];
> > }
> > -
> > +   memcpy(sas_add, pm8001_ha->sas_addr, SAS_ADDR_SIZE);
> > for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
> > +   if (i && ((i % 4) == 0))
> > +   sas_add[7] = sas_add[7] + 4;
> > memcpy(_ha->phy[i].dev_sas_addr,
> > -   pm8001_ha->sas_addr, SAS_ADDR_SIZE);
> > +   sas_add, SAS_ADDR_SIZE);
> > PM8001_INIT_DBG(pm8001_ha,
> > pm8001_printk("phy %d sas_addr = %016llx\n", i,
> > pm8001_ha->phy[i].dev_sas_addr));
> > diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c
> b/drivers/scsi/pm8001/pm80xx_hwi.c
> > index 8fb5ddf08cc4..a07b023c09bf 100644
> > --- a/drivers/scsi/pm8001/pm80xx_hwi.c
> > +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
> > @@ -3041,7 +3041,6 @@ hw_event_phy_down(struct pm8001_hba_info
> *pm8001_ha, void *piomb)
> > port->port_state = portstate;
> > phy->identify.device_type = 0;
> > phy->phy_attached = 0;
> > -   memset(>dev_sas_addr, 0, SAS_ADDR_SIZE);
> > switch (portstate) {
> > case PORT_VALID:
> > break;
> > @@ -4394,7 +4393,7 @@ pm80xx_chip_phy_start_req(struct
> pm8001_hba_info *pm8001_ha, u8 phy_id)
> > payload.sas_identify.dev_type = SAS_END_DEVICE;
> > payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
> > memcpy(payload.sas_identify.sas_addr,
> > -   pm8001_ha->sas_addr, SAS_ADDR_SIZE);
> > +   _ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
> > payload.sas_identify.phy_id = phy_id;
> > ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode,
> , 0);
> > return ret;
> > --
> > 2.12.3
> >
> This removes the possibility to form a wide port, why do you want to do it?


RE: [PATCH 1/6] pm80xx : redefine sas_identify_frame structure

2017-08-30 Thread Viswas G
Thanks. We will move that to pm80xx_hwi.h.

Regards,
Viswas G

> -Original Message-
> From: Jack Wang [mailto:xjtu...@gmail.com]
> Sent: Wednesday, August 30, 2017 9:34 PM
> To: Viswas G <viswa...@microsemi.com>
> Cc: linux-scsi@vger.kernel.org; Vasanthalakshmi Tharmarajan
> <vasanthalakshmi.t...@microsemi.com>
> Subject: Re: [PATCH 1/6] pm80xx : redefine sas_identify_frame structure
> 
> EXTERNAL EMAIL
> 
> 
> 2017-08-30 17:41 GMT+02:00 Viswas G <viswa...@microsemi.com>:
> > Hi Jack,
> >
> > The firmware expectation is that there is no 4 byte CRC. This causes the
> IOMB to be generated incorrectly for PHY_START. Local structure for SAS
> Identify included in the driver so that it matches the Programmer's Manual
> and Firmware expectations.
> >
> > The sas_identify struct from the kernel includes the checksum word (32-
> bits) . So it is 32 bytes rather than 28 bytes. The changed size for the sas
> identify frame means that the "spasti" field for PHY_START is at a different
> offset than documented, word 11 rather than word 10. We're not changing
> the phy analog settings so this doesn't really matter, but the docs indicate
> that the sas frame's crc isn't included. So having a local definition will be
> better than taking the system definition.
> >
> > Regards,
> > Viswas G
> 
> Hi Viswas,
> 
> The spasti field is only for pm80xx, not for pm8001, I think it's
> better to move sas_identify_frame_local to pm80xx_hwi.h.
> 
> Regards,
> Jack
> 
> 
> >
> >> -Original Message-
> >> From: Jack Wang [mailto:xjtu...@gmail.com]
> >> Sent: Tuesday, August 29, 2017 4:49 PM
> >> To: Viswas G <viswa...@microsemi.com>
> >> Cc: linux-scsi@vger.kernel.org; Vasanthalakshmi Tharmarajan
> >> <vasanthalakshmi.t...@microsemi.com>
> >> Subject: Re: [PATCH 1/6] pm80xx : redefine sas_identify_frame structure
> >>
> >> EXTERNAL EMAIL
> >>
> >>
> >> 2015-01-30 7:06 GMT+01:00 Viswas G <viswa...@microsemi.com>:
> >> > sas_identify structure defined by pm80xx doesn't have CRC field.
> >> > So added a new sas_identify structure without CRC.
> >> >
> >> > Signed-off-by: Raj Dinesh <raj.din...@microsemi.com>
> >> > Signed-off-by: Viswas G <viswa...@microsemi.com>
> >> > ---
> >> >  drivers/scsi/pm8001/pm8001_hwi.h |  2 +-
> >> >  drivers/scsi/pm8001/pm8001_sas.h | 95
> >> 
> >> >  drivers/scsi/pm8001/pm80xx_hwi.h |  2 +-
> >> >  3 files changed, 97 insertions(+), 2 deletions(-)
> >> >
> >> > diff --git a/drivers/scsi/pm8001/pm8001_hwi.h
> >> b/drivers/scsi/pm8001/pm8001_hwi.h
> >> > index e4867e690c84..f4331afe9b0b 100644
> >> > --- a/drivers/scsi/pm8001/pm8001_hwi.h
> >> > +++ b/drivers/scsi/pm8001/pm8001_hwi.h
> >> > @@ -157,7 +157,7 @@ struct mpi_msg_hdr{
> >> >  struct phy_start_req {
> >> > __le32  tag;
> >> > __le32  ase_sh_lm_slr_phyid;
> >> > -   struct sas_identify_frame sas_identify;
> >> > +   struct sas_identify_frame_local sas_identify;
> >> > u32 reserved[5];
> >> >  } __attribute__((packed, aligned(4)));
> >> >
> >> > diff --git a/drivers/scsi/pm8001/pm8001_sas.h
> >> b/drivers/scsi/pm8001/pm8001_sas.h
> >> > index e81a8fa7ef1a..2e17505ed5b8 100644
> >> > --- a/drivers/scsi/pm8001/pm8001_sas.h
> >> > +++ b/drivers/scsi/pm8001/pm8001_sas.h
> >> > @@ -118,6 +118,101 @@ extern const struct pm8001_dispatch
> >> pm8001_80xx_dispatch;
> >> >  struct pm8001_hba_info;
> >> >  struct pm8001_ccb_info;
> >> >  struct pm8001_device;
> >> > +#ifdef __LITTLE_ENDIAN_BITFIELD
> >> > +struct sas_identify_frame_local {
> >> > +   /* Byte 0 */
> >> > +   u8  frame_type:4;
> >> > +   u8  dev_type:3;
> >> > +   u8  _un0:1;
> >> > +
> >> > +   /* Byte 1 */
> >> > +   u8  _un1;
> >> > +
> >> > +   /* Byte 2 */
> >> > +   union {
> >> > +   struct {
> >> > +   u8  _un20:1;
> >> > +   u8  smp_iport:1;
> >> > +   u8  stp_iport:1;
> >> > +   u8  ssp_iport:1;
> >> > +   u8  _un247:4;

RE: [PATCH 4/6] pm80xx : Corrected SATA abort handling.

2017-08-30 Thread Viswas G
Thanks Jack. We will split this patch as you suggested and send V2.

Regards,
Viswas G

> -Original Message-
> From: Jack Wang [mailto:xjtu...@gmail.com]
> Sent: Tuesday, August 29, 2017 5:16 PM
> To: Viswas G <viswa...@microsemi.com>
> Cc: linux-scsi@vger.kernel.org; Vasanthalakshmi Tharmarajan
> <vasanthalakshmi.t...@microsemi.com>
> Subject: Re: [PATCH 4/6] pm80xx : Corrected SATA abort handling.
> 
> EXTERNAL EMAIL
> 
> 
> 2015-01-30 7:06 GMT+01:00 Viswas G <viswa...@microsemi.com>:
> > Modified SATA abort handling with following steps:
> > 1) Set device state as recovery.
> > 2) Send phy reset.
> > 3) Wait for reset completion.
> > 4) After successful reset, abort all IO's to the device.
> > 5) After aborting all IO's to device, set device state as operational.
> >
> > Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
> > Signed-off-by: Viswas G <viswa...@microsemi.com>
> This one includes more than described above.
> Would be good to split it better.
> comments inline.
> 
> > ---
> >  drivers/scsi/pm8001/pm8001_hwi.c |  11 +++-
> >  drivers/scsi/pm8001/pm8001_sas.c | 125
> +++
> >  drivers/scsi/pm8001/pm8001_sas.h |   8 +++
> >  drivers/scsi/pm8001/pm80xx_hwi.c |  52 +---
> >  4 files changed, 148 insertions(+), 48 deletions(-)
> >
> > diff --git a/drivers/scsi/pm8001/pm8001_hwi.c
> b/drivers/scsi/pm8001/pm8001_hwi.c
> > index 10546faac58c..db88a8e7ee0e 100644
> > --- a/drivers/scsi/pm8001/pm8001_hwi.c
> > +++ b/drivers/scsi/pm8001/pm8001_hwi.c
> > @@ -3198,19 +3198,28 @@ pm8001_mpi_get_nvmd_resp(struct
> pm8001_hba_info *pm8001_ha, void *piomb)
> >
> >  int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void
> *piomb)
> >  {
> > +   u32 tag;
> > struct local_phy_ctl_resp *pPayload =
> > (struct local_phy_ctl_resp *)(piomb + 4);
> > u32 status = le32_to_cpu(pPayload->status);
> > u32 phy_id = le32_to_cpu(pPayload->phyop_phyid) & ID_BITS;
> > u32 phy_op = le32_to_cpu(pPayload->phyop_phyid) & OP_BITS;
> > +   tag = le32_to_cpu(pPayload->tag);
> > if (status != 0) {
> > PM8001_MSG_DBG(pm8001_ha,
> > pm8001_printk("%x phy execute %x phy op failed!\n",
> > phy_id, phy_op));
> > -   } else
> > +   } else {
> > PM8001_MSG_DBG(pm8001_ha,
> > pm8001_printk("%x phy execute %x phy op success!\n",
> > phy_id, phy_op));
> > +   pm8001_ha->phy[phy_id].reset_success = true;
> > +   }
> > +   if (pm8001_ha->phy[phy_id].enable_completion) {
> > +   complete(pm8001_ha->phy[phy_id].enable_completion);
> > +   pm8001_ha->phy[phy_id].enable_completion = NULL;
> > +   }
> > +   pm8001_tag_free(pm8001_ha, tag);
> > return 0;
> >  }
> >
> > diff --git a/drivers/scsi/pm8001/pm8001_sas.c
> b/drivers/scsi/pm8001/pm8001_sas.c
> > index ce584c31d36e..a409d3a6a3cb 100644
> > --- a/drivers/scsi/pm8001/pm8001_sas.c
> > +++ b/drivers/scsi/pm8001/pm8001_sas.c
> > @@ -1159,40 +1159,47 @@ int pm8001_query_task(struct sas_task *task)
> >  int pm8001_abort_task(struct sas_task *task)
> >  {
> > unsigned long flags;
> > -   u32 tag = 0xdeadbeef;
> > +   u32 tag;
> > u32 device_id;
> > struct domain_device *dev ;
> > -   struct pm8001_hba_info *pm8001_ha = NULL;
> > +   struct pm8001_hba_info *pm8001_ha;
> > struct pm8001_ccb_info *ccb;
> > struct scsi_lun lun;
> > struct pm8001_device *pm8001_dev;
> > struct pm8001_tmf_task tmf_task;
> > -   int rc = TMF_RESP_FUNC_FAILED;
> > +   int rc = TMF_RESP_FUNC_FAILED, ret;
> > +   u32 phy_id;
> > +   struct sas_task_slow slow_task;
> > +
> > if (unlikely(!task || !task->lldd_task || !task->dev))
> > -   return rc;
> > +   return TMF_RESP_FUNC_FAILED;
> > +
> > +   dev = task->dev;
> > +   pm8001_dev = dev->lldd_dev;
> > +   pm8001_ha = pm8001_find_ha_by_dev(dev);
> > +   device_id = pm8001_dev->device_id;
> > +   phy_id = pm8001_dev->attached_phy;
> > +   rc = pm8001_find_tag(task, );
> > +   if (rc == 0) {
> > +   pm8001_printk("no tag 

RE: [PATCH 1/6] pm80xx : redefine sas_identify_frame structure

2017-08-30 Thread Viswas G
Hi Jack,

The firmware expectation is that there is no 4 byte CRC. This causes the IOMB 
to be generated incorrectly for PHY_START. Local structure for SAS Identify 
included in the driver so that it matches the Programmer's Manual and Firmware 
expectations.

The sas_identify struct from the kernel includes the checksum word (32-bits) . 
So it is 32 bytes rather than 28 bytes. The changed size for the sas identify 
frame means that the "spasti" field for PHY_START is at a different offset than 
documented, word 11 rather than word 10. We're not changing the phy analog 
settings so this doesn't really matter, but the docs indicate that the sas 
frame's crc isn't included. So having a local definition will be better than 
taking the system definition. 

Regards,
Viswas G

> -Original Message-
> From: Jack Wang [mailto:xjtu...@gmail.com]
> Sent: Tuesday, August 29, 2017 4:49 PM
> To: Viswas G <viswa...@microsemi.com>
> Cc: linux-scsi@vger.kernel.org; Vasanthalakshmi Tharmarajan
> <vasanthalakshmi.t...@microsemi.com>
> Subject: Re: [PATCH 1/6] pm80xx : redefine sas_identify_frame structure
> 
> EXTERNAL EMAIL
> 
> 
> 2015-01-30 7:06 GMT+01:00 Viswas G <viswa...@microsemi.com>:
> > sas_identify structure defined by pm80xx doesn't have CRC field.
> > So added a new sas_identify structure without CRC.
> >
> > Signed-off-by: Raj Dinesh <raj.din...@microsemi.com>
> > Signed-off-by: Viswas G <viswa...@microsemi.com>
> > ---
> >  drivers/scsi/pm8001/pm8001_hwi.h |  2 +-
> >  drivers/scsi/pm8001/pm8001_sas.h | 95
> 
> >  drivers/scsi/pm8001/pm80xx_hwi.h |  2 +-
> >  3 files changed, 97 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/scsi/pm8001/pm8001_hwi.h
> b/drivers/scsi/pm8001/pm8001_hwi.h
> > index e4867e690c84..f4331afe9b0b 100644
> > --- a/drivers/scsi/pm8001/pm8001_hwi.h
> > +++ b/drivers/scsi/pm8001/pm8001_hwi.h
> > @@ -157,7 +157,7 @@ struct mpi_msg_hdr{
> >  struct phy_start_req {
> > __le32  tag;
> > __le32  ase_sh_lm_slr_phyid;
> > -   struct sas_identify_frame sas_identify;
> > +   struct sas_identify_frame_local sas_identify;
> > u32 reserved[5];
> >  } __attribute__((packed, aligned(4)));
> >
> > diff --git a/drivers/scsi/pm8001/pm8001_sas.h
> b/drivers/scsi/pm8001/pm8001_sas.h
> > index e81a8fa7ef1a..2e17505ed5b8 100644
> > --- a/drivers/scsi/pm8001/pm8001_sas.h
> > +++ b/drivers/scsi/pm8001/pm8001_sas.h
> > @@ -118,6 +118,101 @@ extern const struct pm8001_dispatch
> pm8001_80xx_dispatch;
> >  struct pm8001_hba_info;
> >  struct pm8001_ccb_info;
> >  struct pm8001_device;
> > +#ifdef __LITTLE_ENDIAN_BITFIELD
> > +struct sas_identify_frame_local {
> > +   /* Byte 0 */
> > +   u8  frame_type:4;
> > +   u8  dev_type:3;
> > +   u8  _un0:1;
> > +
> > +   /* Byte 1 */
> > +   u8  _un1;
> > +
> > +   /* Byte 2 */
> > +   union {
> > +   struct {
> > +   u8  _un20:1;
> > +   u8  smp_iport:1;
> > +   u8  stp_iport:1;
> > +   u8  ssp_iport:1;
> > +   u8  _un247:4;
> > +   };
> > +   u8 initiator_bits;
> > +   };
> > +
> > +   /* Byte 3 */
> > +   union {
> > +   struct {
> > +   u8  _un30:1;
> > +   u8 smp_tport:1;
> > +   u8 stp_tport:1;
> > +   u8 ssp_tport:1;
> > +   u8 _un347:4;
> > +   };
> > +   u8 target_bits;
> > +   };
> > +
> > +   /* Byte 4 - 11 */
> > +   u8 _un4_11[8];
> > +
> > +   /* Byte 12 - 19 */
> > +   u8 sas_addr[SAS_ADDR_SIZE];
> > +
> > +   /* Byte 20 */
> > +   u8 phy_id;
> > +
> > +   u8 _un21_27[7];
> > +
> > +} __packed;
> > +
> > +#elif defined(__BIG_ENDIAN_BITFIELD)
> > +struct sas_identify_frame_local {
> > +   /* Byte 0 */
> > +   u8  _un0:1;
> > +   u8  dev_type:3;
> > +   u8  frame_type:4;
> > +
> > +   /* Byte 1 */
> > +   u8  _un1;
> > +
> > +   /* Byte 2 */
> > +   union {
> > +   struct {
> > +   u8  _un247:4;
> > +   u8  ssp_iport:1;
> > +   u8  stp_iport:1;
> >

RE: [PATCH 0/6] pm80xx updates

2017-08-25 Thread Viswas G
Thanks Martin,

My system date was wrong.

I will correct the date when I send V1 for this patch set.

Regards,
Viswas G

-Original Message-
From: Martin K. Petersen [mailto:martin.peter...@oracle.com] 
Sent: Saturday, August 26, 2017 3:18 AM
To: Viswas G <viswa...@microsemi.com>
Cc: linux-scsi@vger.kernel.org; xjtu...@gmail.com; Vasanthalakshmi Tharmarajan 
<vasanthalakshmi.t...@microsemi.com>
Subject: Re: [PATCH 0/6] pm80xx updates

EXTERNAL EMAIL


Viswas,

> This patch set include some big fixes and enhancement for pm80xx 
> driver.

This patch set is dated January 2015!?!

--
Martin K. Petersen  Oracle Linux Engineering


[PATCH 6/6] pm80xx : corrected linkrate value.

2017-08-25 Thread Viswas G
Corrected the value defined for LINKRATE_60 (6 Gig).

Signed-off-by: Raj Dinesh <raj.din...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index d8e5d81e83f1..71dee83aeef0 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -167,7 +167,7 @@
 #define LINKMODE_AUTO  (0x03 << 12)
 #define LINKRATE_15(0x01 << 8)
 #define LINKRATE_30(0x02 << 8)
-#define LINKRATE_60(0x06 << 8)
+#define LINKRATE_60(0x04 << 8)
 #define LINKRATE_120   (0x08 << 8)
 
 /* phy_profile */
-- 
2.12.3



[PATCH 2/6] pm80xx: ILA and inactive firmware version through sysfs

2017-08-25 Thread Viswas G
Added support to read ILA version and inactive firmware version
from MPI configuration table and export through sysfs.

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>
---
 drivers/scsi/pm8001/pm8001_ctl.c | 55 
 drivers/scsi/pm8001/pm8001_sas.h |  2 ++
 drivers/scsi/pm8001/pm80xx_hwi.c |  5 
 drivers/scsi/pm8001/pm80xx_hwi.h |  2 ++
 4 files changed, 64 insertions(+)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index be8269c8d127..d278c807112f 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -98,6 +98,59 @@ static ssize_t pm8001_ctl_fw_version_show(struct device 
*cdev,
}
 }
 static DEVICE_ATTR(fw_version, S_IRUGO, pm8001_ctl_fw_version_show, NULL);
+
+/**
+ * pm8001_ctl_ila_version_show - ila version
+ * @cdev: pointer to embedded class device
+ * @buf: the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t pm8001_ctl_ila_version_show(struct device *cdev,
+   struct device_attribute *attr, char *buf)
+{
+   struct Scsi_Host *shost = class_to_shost(cdev);
+   struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+   struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+   if (pm8001_ha->chip_id != chip_8001) {
+   return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 24),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 16),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version >> 8),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version));
+   }
+   return 0;
+}
+static DEVICE_ATTR(ila_version, 0444, pm8001_ctl_ila_version_show, NULL);
+
+/**
+ * pm8001_ctl_inactive_fw_version_show - Inacative firmware version number
+ * @cdev: pointer to embedded class device
+ * @buf: the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t pm8001_ctl_inactive_fw_version_show(struct device *cdev,
+   struct device_attribute *attr, char *buf)
+{
+   struct Scsi_Host *shost = class_to_shost(cdev);
+   struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+   struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
+
+   if (pm8001_ha->chip_id != chip_8001) {
+   return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n",
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 24),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 16),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version >> 8),
+   (u8)(pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version));
+   }
+   return 0;
+}
+static
+DEVICE_ATTR(inc_fw_ver, 0444, pm8001_ctl_inactive_fw_version_show, NULL);
+
+
 /**
  * pm8001_ctl_max_out_io_show - max outstanding io supported
  * @cdev: pointer to embedded class device
@@ -748,6 +801,8 @@ struct device_attribute *pm8001_host_attrs[] = {
_attr_bios_version,
_attr_ib_log,
_attr_ob_log,
+   _attr_ila_version,
+   _attr_inc_fw_ver,
NULL,
 };
 
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 2e17505ed5b8..2eb3b670bf45 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -499,6 +499,8 @@ union main_cfg_table {
u32 port_recovery_timer;
u32 interrupt_reassertion_delay;
u32 fatal_n_non_fatal_dump; /* 0x28 */
+   u32 ila_version;
+   u32 inc_fw_version;
} pm80xx_tbl;
 };
 
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index eb4fee61df72..8fb5ddf08cc4 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -312,6 +312,11 @@ static void read_main_config_table(struct pm8001_hba_info 
*pm8001_ha)
/* read port recover and reset timeout */
pm8001_ha->main_cfg_tbl.pm80xx_tbl.port_recovery_timer =
pm8001_mr32(address, MAIN_PORT_RECOVERY_TIMER);
+   /* read ILA and inactive firmware version */
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version =
+   pm8001_mr32(address, MAIN_MPI_ILA_RELEASE_TYPE);
+   pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version =
+   pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION);
 }
 
 /**
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 1ee2ec210065..d8e5d81e83f1 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -1349,6 +1349,8 @@ typedef struct SASProtocolTimerConfig 
SASProtocolTimerConfig_t;
 #define MAIN_SAS_P

[PATCH 5/6] pm80xx : panic on ncq error cleaning up the read log

2017-08-25 Thread Viswas G
when there's an error in 'ncq mode' the host has to read the ncq
error log (10h) to clear the error state. however, the ccb that
is setup for doing this doesn't setup the ccb so that the
previous state is cleared. if the ccb was previously used for an IO
n_elems is set and pm8001_ccb_task_free() treats this as the signal
to go free a scatter-gather list (that's already been free-ed).

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>
---
 drivers/scsi/pm8001/pm80xx_hwi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index ae9252cf1706..e75b0aa497f0 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -1489,6 +1489,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info 
*pm8001_ha,
ccb->device = pm8001_ha_dev;
ccb->ccb_tag = ccb_tag;
ccb->task = task;
+   ccb->n_elem = 0;
pm8001_ha_dev->id |= NCQ_READ_LOG_FLAG;
pm8001_ha_dev->id |= NCQ_2ND_RLE_FLAG;
 
-- 
2.12.3



[PATCH 3/6] pm80xx : Different SAS addresses for phys.

2017-08-25 Thread Viswas G
Different SAS addresses are assigned for each set of phys.

Signed-off-by: Viswas G <viswa...@microsemi.com>
---
 drivers/scsi/pm8001/pm8001_init.c | 13 +
 drivers/scsi/pm8001/pm80xx_hwi.c  |  3 +--
 2 files changed, 10 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index 034b2f7d1135..d282f1562615 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -132,7 +132,7 @@ static void pm8001_phy_init(struct pm8001_hba_info 
*pm8001_ha, int phy_id)
sas_phy->oob_mode = OOB_NOT_CONNECTED;
sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
sas_phy->id = phy_id;
-   sas_phy->sas_addr = _ha->sas_addr[0];
+   sas_phy->sas_addr = (u8 *)>dev_sas_addr;
sas_phy->frame_rcvd = >frame_rcvd[0];
sas_phy->ha = (struct sas_ha_struct *)pm8001_ha->shost->hostdata;
sas_phy->lldd_phy = phy;
@@ -593,10 +593,12 @@ static void  pm8001_post_sas_ha_init(struct Scsi_Host 
*shost,
for (i = 0; i < chip_info->n_phy; i++) {
sha->sas_phy[i] = _ha->phy[i].sas_phy;
sha->sas_port[i] = _ha->port[i].sas_port;
+   sha->sas_phy[i]->sas_addr =
+   (u8 *)_ha->phy[i].dev_sas_addr;
}
sha->sas_ha_name = DRV_NAME;
sha->dev = pm8001_ha->dev;
-
+   sha->strict_wide_ports = 1;
sha->lldd_module = THIS_MODULE;
sha->sas_addr = _ha->sas_addr[0];
sha->num_phys = chip_info->n_phy;
@@ -613,6 +615,7 @@ static void  pm8001_post_sas_ha_init(struct Scsi_Host 
*shost,
 static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
 {
u8 i, j;
+   u8 sas_add[8];
 #ifdef PM8001_READ_VPD
/* For new SPC controllers WWN is stored in flash vpd
*  For SPC/SPCve controllers WWN is stored in EEPROM
@@ -674,10 +677,12 @@ static void pm8001_init_sas_add(struct pm8001_hba_info 
*pm8001_ha)
pm8001_ha->sas_addr[j] =
payload.func_specific[0x804 + i];
}
-
+   memcpy(sas_add, pm8001_ha->sas_addr, SAS_ADDR_SIZE);
for (i = 0; i < pm8001_ha->chip->n_phy; i++) {
+   if (i && ((i % 4) == 0))
+   sas_add[7] = sas_add[7] + 4;
memcpy(_ha->phy[i].dev_sas_addr,
-   pm8001_ha->sas_addr, SAS_ADDR_SIZE);
+   sas_add, SAS_ADDR_SIZE);
PM8001_INIT_DBG(pm8001_ha,
pm8001_printk("phy %d sas_addr = %016llx\n", i,
pm8001_ha->phy[i].dev_sas_addr));
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index 8fb5ddf08cc4..a07b023c09bf 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -3041,7 +3041,6 @@ hw_event_phy_down(struct pm8001_hba_info *pm8001_ha, void 
*piomb)
port->port_state = portstate;
phy->identify.device_type = 0;
phy->phy_attached = 0;
-   memset(>dev_sas_addr, 0, SAS_ADDR_SIZE);
switch (portstate) {
case PORT_VALID:
break;
@@ -4394,7 +4393,7 @@ pm80xx_chip_phy_start_req(struct pm8001_hba_info 
*pm8001_ha, u8 phy_id)
payload.sas_identify.dev_type = SAS_END_DEVICE;
payload.sas_identify.initiator_bits = SAS_PROTOCOL_ALL;
memcpy(payload.sas_identify.sas_addr,
-   pm8001_ha->sas_addr, SAS_ADDR_SIZE);
+   _ha->phy[phy_id].dev_sas_addr, SAS_ADDR_SIZE);
payload.sas_identify.phy_id = phy_id;
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opcode, , 0);
return ret;
-- 
2.12.3



[PATCH 4/6] pm80xx : Corrected SATA abort handling.

2017-08-25 Thread Viswas G
Modified SATA abort handling with following steps:
1) Set device state as recovery.
2) Send phy reset.
3) Wait for reset completion.
4) After successful reset, abort all IO's to the device.
5) After aborting all IO's to device, set device state as operational.

Signed-off-by: Deepak Ukey <deepak.u...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>
---
 drivers/scsi/pm8001/pm8001_hwi.c |  11 +++-
 drivers/scsi/pm8001/pm8001_sas.c | 125 +++
 drivers/scsi/pm8001/pm8001_sas.h |   8 +++
 drivers/scsi/pm8001/pm80xx_hwi.c |  52 +---
 4 files changed, 148 insertions(+), 48 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 10546faac58c..db88a8e7ee0e 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3198,19 +3198,28 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info 
*pm8001_ha, void *piomb)
 
 int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb)
 {
+   u32 tag;
struct local_phy_ctl_resp *pPayload =
(struct local_phy_ctl_resp *)(piomb + 4);
u32 status = le32_to_cpu(pPayload->status);
u32 phy_id = le32_to_cpu(pPayload->phyop_phyid) & ID_BITS;
u32 phy_op = le32_to_cpu(pPayload->phyop_phyid) & OP_BITS;
+   tag = le32_to_cpu(pPayload->tag);
if (status != 0) {
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op failed!\n",
phy_id, phy_op));
-   } else
+   } else {
PM8001_MSG_DBG(pm8001_ha,
pm8001_printk("%x phy execute %x phy op success!\n",
phy_id, phy_op));
+   pm8001_ha->phy[phy_id].reset_success = true;
+   }
+   if (pm8001_ha->phy[phy_id].enable_completion) {
+   complete(pm8001_ha->phy[phy_id].enable_completion);
+   pm8001_ha->phy[phy_id].enable_completion = NULL;
+   }
+   pm8001_tag_free(pm8001_ha, tag);
return 0;
 }
 
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index ce584c31d36e..a409d3a6a3cb 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -1159,40 +1159,47 @@ int pm8001_query_task(struct sas_task *task)
 int pm8001_abort_task(struct sas_task *task)
 {
unsigned long flags;
-   u32 tag = 0xdeadbeef;
+   u32 tag;
u32 device_id;
struct domain_device *dev ;
-   struct pm8001_hba_info *pm8001_ha = NULL;
+   struct pm8001_hba_info *pm8001_ha;
struct pm8001_ccb_info *ccb;
struct scsi_lun lun;
struct pm8001_device *pm8001_dev;
struct pm8001_tmf_task tmf_task;
-   int rc = TMF_RESP_FUNC_FAILED;
+   int rc = TMF_RESP_FUNC_FAILED, ret;
+   u32 phy_id;
+   struct sas_task_slow slow_task;
+
if (unlikely(!task || !task->lldd_task || !task->dev))
-   return rc;
+   return TMF_RESP_FUNC_FAILED;
+
+   dev = task->dev;
+   pm8001_dev = dev->lldd_dev;
+   pm8001_ha = pm8001_find_ha_by_dev(dev);
+   device_id = pm8001_dev->device_id;
+   phy_id = pm8001_dev->attached_phy;
+   rc = pm8001_find_tag(task, );
+   if (rc == 0) {
+   pm8001_printk("no tag for task:%p\n", 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;
+   }
+
+   task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+   if (task->slow_task == NULL) {
+   init_completion(_task.completion);
+   task->slow_task = _task;
}
spin_unlock_irqrestore(>task_state_lock, flags);
+
if (task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd *cmnd = task->uldd_task;
-   dev = task->dev;
-   ccb = task->lldd_task;
-   pm8001_dev = dev->lldd_dev;
-   pm8001_ha = pm8001_find_ha_by_dev(dev);
int_to_scsilun(cmnd->device->lun, );
-   rc = pm8001_find_tag(task, );
-   if (rc == 0) {
-   printk(KERN_INFO "No such tag in %s\n", __func__);
-   rc = TMF_RESP_FUNC_FAILED;
-   return rc;
-   }
-   device_id = pm8001_dev->device_id;
-   PM8001_EH_DBG(pm8001_ha,
-   pm8001_printk("abort io to deviceid= %d\n", device_id));
tmf_task.tmf = TMF_ABORT_TASK;
tmf_task.tag_

[PATCH 0/6] pm80xx updates

2017-08-25 Thread Viswas G
This patch set include some big fixes and enhancement for pm80xx driver. 

Viswas G (6):
  pm80xx : redefine sas_identify_frame structure
  pm80xx: ILA and inactive firmware version through sysfs
  pm80xx : Different SAS addresses for phys.
  pm80xx : Corrected SATA abort handling.
  pm80xx : panic on ncq error cleaning up the read log
  pm80xx : corrected linkrate value.

 drivers/scsi/pm8001/pm8001_ctl.c  |  55 +
 drivers/scsi/pm8001/pm8001_hwi.c  |  11 +++-
 drivers/scsi/pm8001/pm8001_hwi.h  |   2 +-
 drivers/scsi/pm8001/pm8001_init.c |  13 ++--
 drivers/scsi/pm8001/pm8001_sas.c  | 125 ++
 drivers/scsi/pm8001/pm8001_sas.h  | 105 
 drivers/scsi/pm8001/pm80xx_hwi.c  |  61 +++
 drivers/scsi/pm8001/pm80xx_hwi.h  |   6 +-
 8 files changed, 321 insertions(+), 57 deletions(-)

-- 
2.12.3



[PATCH 1/6] pm80xx : redefine sas_identify_frame structure

2017-08-25 Thread Viswas G
sas_identify structure defined by pm80xx doesn't have CRC field.
So added a new sas_identify structure without CRC.

Signed-off-by: Raj Dinesh <raj.din...@microsemi.com>
Signed-off-by: Viswas G <viswa...@microsemi.com>
---
 drivers/scsi/pm8001/pm8001_hwi.h |  2 +-
 drivers/scsi/pm8001/pm8001_sas.h | 95 
 drivers/scsi/pm8001/pm80xx_hwi.h |  2 +-
 3 files changed, 97 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h
index e4867e690c84..f4331afe9b0b 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.h
+++ b/drivers/scsi/pm8001/pm8001_hwi.h
@@ -157,7 +157,7 @@ struct mpi_msg_hdr{
 struct phy_start_req {
__le32  tag;
__le32  ase_sh_lm_slr_phyid;
-   struct sas_identify_frame sas_identify;
+   struct sas_identify_frame_local sas_identify;
u32 reserved[5];
 } __attribute__((packed, aligned(4)));
 
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index e81a8fa7ef1a..2e17505ed5b8 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -118,6 +118,101 @@ extern const struct pm8001_dispatch pm8001_80xx_dispatch;
 struct pm8001_hba_info;
 struct pm8001_ccb_info;
 struct pm8001_device;
+#ifdef __LITTLE_ENDIAN_BITFIELD
+struct sas_identify_frame_local {
+   /* Byte 0 */
+   u8  frame_type:4;
+   u8  dev_type:3;
+   u8  _un0:1;
+
+   /* Byte 1 */
+   u8  _un1;
+
+   /* Byte 2 */
+   union {
+   struct {
+   u8  _un20:1;
+   u8  smp_iport:1;
+   u8  stp_iport:1;
+   u8  ssp_iport:1;
+   u8  _un247:4;
+   };
+   u8 initiator_bits;
+   };
+
+   /* Byte 3 */
+   union {
+   struct {
+   u8  _un30:1;
+   u8 smp_tport:1;
+   u8 stp_tport:1;
+   u8 ssp_tport:1;
+   u8 _un347:4;
+   };
+   u8 target_bits;
+   };
+
+   /* Byte 4 - 11 */
+   u8 _un4_11[8];
+
+   /* Byte 12 - 19 */
+   u8 sas_addr[SAS_ADDR_SIZE];
+
+   /* Byte 20 */
+   u8 phy_id;
+
+   u8 _un21_27[7];
+
+} __packed;
+
+#elif defined(__BIG_ENDIAN_BITFIELD)
+struct sas_identify_frame_local {
+   /* Byte 0 */
+   u8  _un0:1;
+   u8  dev_type:3;
+   u8  frame_type:4;
+
+   /* Byte 1 */
+   u8  _un1;
+
+   /* Byte 2 */
+   union {
+   struct {
+   u8  _un247:4;
+   u8  ssp_iport:1;
+   u8  stp_iport:1;
+   u8  smp_iport:1;
+   u8  _un20:1;
+   };
+   u8 initiator_bits;
+   };
+
+   /* Byte 3 */
+   union {
+   struct {
+   u8 _un347:4;
+   u8 ssp_tport:1;
+   u8 stp_tport:1;
+   u8 smp_tport:1;
+   u8 _un30:1;
+   };
+   u8 target_bits;
+   };
+
+   /* Byte 4 - 11 */
+   u8 _un4_11[8];
+
+   /* Byte 12 - 19 */
+   u8 sas_addr[SAS_ADDR_SIZE];
+
+   /* Byte 20 */
+   u8 phy_id;
+
+   u8 _un21_27[7];
+} __packed;
+#else
+#error "Bitfield order not defined!"
+#endif
 /* define task management IU */
 struct pm8001_tmf_task {
u8  tmf;
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.h b/drivers/scsi/pm8001/pm80xx_hwi.h
index 7a443bad6163..1ee2ec210065 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.h
+++ b/drivers/scsi/pm8001/pm80xx_hwi.h
@@ -248,7 +248,7 @@ struct mpi_msg_hdr {
 struct phy_start_req {
__le32  tag;
__le32  ase_sh_lm_slr_phyid;
-   struct sas_identify_frame sas_identify; /* 28 Bytes */
+   struct sas_identify_frame_local sas_identify; /* 28 Bytes */
__le32 spasti;
u32 reserved[21];
 } __attribute__((packed, aligned(4)));
-- 
2.12.3



Re: [Bug 121531] Adaptec 7805H SAS HBA (pm80xx): hangs when writing >80MB at once

2016-07-07 Thread Viswas G
Patch set for pm80xx is pending for the last 3 quarters.
We will submit those soon with all the buf fixes and  performance
tuning changes.

Regards,
Viswas G

On Thu, Jul 7, 2016 at 10:04 PM,  <bugzilla-dae...@bugzilla.kernel.org> wrote:
> https://bugzilla.kernel.org/show_bug.cgi?id=121531
>
> --- Comment #14 from Jack Wang <xjtu...@gmail.com> ---
> The changes are huge, hard to do it, without help from MicroSemi/PMCs side.
> And I don't have hardware to test.
>
> I've asked developer from MicroSemi to upsteam their changes, but
> sadly no reply.
>
> 2016-07-07 17:36 GMT+02:00  <bugzilla-dae...@bugzilla.kernel.org>:
>> https://bugzilla.kernel.org/show_bug.cgi?id=121531
>>
>> --- Comment #13 from Martin von Wittich <martin.von.witt...@iserv.eu> ---
>> Yup, the Debian installation worked and seems to work fine so far. I manually
>> installed the pm80xx-1.4.0-11068-debian64.deb package in the target system
>> while I was still in the installer by chrooting to /target; then I added
>> "pm80xx" to /etc/initramfs/modules (without that update-initramfs wouldn't 
>> add
>> the pm80xx module, I'm not really sure why).
>>
>> After booting the system, I've succcessfully written ~500 GB of /dev/zero 
>> data
>> into a file on an MD raid consisting of both of the disks. No error messages 
>> in
>> the dmesg either.
>>
>> Can you include those missing changes into the official kernel, or how can we
>> resolve this bug? We'll ask to the customer if we can keep the server for an
>> additional two weeks for testing, so if you need me to test builds, let me
>> know.
>>
>> --
>> You are receiving this mail because:
>> You are on the CC list for the bug.
>
> --
> You are receiving this mail because:
> You are the assignee for the bug.
> --
> 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 V2 2/8] pm80xx: Corrected device state changes in I_T_Nexus_Reset.

2015-08-14 Thread Viswas G
On Thu, Aug 13, 2015 at 6:13 PM, Jinpu Wang jinpu.w...@profitbricks.com wrote:
 Hi

 On Tue, Aug 11, 2015 at 11:36 AM,  viswa...@pmcs.com wrote:
 From: Viswas G viswa...@pmcs.com

 In Nexus reset the device state request are not needed.

 Changes from V1:
 Device state change request has been removed as the firmware
 will handle it during internal cleanup. Also updated the
 proper return value in case of failures.

 If above is true, should we remove the device state change command
 support at all?


We can't remove the state change command as it is required for 
some task management command such as ABORT_TASK.

 Other than that, please feel free to add:
 Acked-by: Jack Wang jinpu.w...@profitbricks.com

 Thanks
 Jack



 Signed-off-by: Viswas G viswa...@pmcs.com

 Reviewed-by: Suresh Thiagarajan suresh.thiagara...@pmcs.com
 ---
  drivers/scsi/pm8001/pm8001_sas.c |   18 +-
  drivers/scsi/pm8001/pm8001_sas.h |8 
  2 files changed, 21 insertions(+), 5 deletions(-)

 diff --git a/drivers/scsi/pm8001/pm8001_sas.c 
 b/drivers/scsi/pm8001/pm8001_sas.c
 index b93f289..48f4627 100644
 --- a/drivers/scsi/pm8001/pm8001_sas.c
 +++ b/drivers/scsi/pm8001/pm8001_sas.c
 @@ -975,19 +975,27 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
 phy = sas_get_local_phy(dev);

 if (dev_is_sata(dev)) {
 -   DECLARE_COMPLETION_ONSTACK(completion_setstate);
 if (scsi_is_sas_phy_local(phy)) {
 rc = 0;
 goto out;
 }
 rc = sas_phy_reset(phy, 1);
 +   if (rc) {
 +   PM8001_EH_DBG(pm8001_ha,
 +   pm8001_printk(phy reset failed for device %x\n
 +   with rc %d\n, pm8001_dev-device_id, rc));
 +   rc = TMF_RESP_FUNC_FAILED;
 +   goto out;
 +   }
 msleep(2000);
 rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
 dev, 1, 0);
 -   pm8001_dev-setds_completion = completion_setstate;
 -   rc = PM8001_CHIP_DISP-set_dev_state_req(pm8001_ha,
 -   pm8001_dev, 0x01);
 -   wait_for_completion(completion_setstate);
 +   if (rc) {
 +   PM8001_EH_DBG(pm8001_ha,
 +   pm8001_printk(task abort failed %x\n
 +   with rc %d\n, pm8001_dev-device_id, rc));
 +   rc = TMF_RESP_FUNC_FAILED;
 +   }
 } else {
 rc = sas_phy_reset(phy, 1);
 msleep(2000);
 diff --git a/drivers/scsi/pm8001/pm8001_sas.h 
 b/drivers/scsi/pm8001/pm8001_sas.h
 index 8dd8b78..c9736cc 100644
 --- a/drivers/scsi/pm8001/pm8001_sas.h
 +++ b/drivers/scsi/pm8001/pm8001_sas.h
 @@ -569,6 +569,14 @@ struct pm8001_fw_image_header {
  #defineNCQ_READ_LOG_FLAG   0x8000
  #defineNCQ_ABORT_ALL_FLAG  0x4000
  #defineNCQ_2ND_RLE_FLAG0x2000
 +
 +/* Device states */
 +#define DS_OPERATIONAL 0x01
 +#define DS_PORT_IN_RESET   0x02
 +#define DS_IN_RECOVERY 0x03
 +#define DS_IN_ERROR0x04
 +#define DS_NON_OPERATIONAL 0x07
 +
  /**
   * brief param structure for firmware flash update.
   */
 --
 1.7.1




 --
 Mit freundlichen Grüßen,
 Best Regards,

 Jack Wang

 Linux Kernel Developer Storage
 ProfitBricks GmbH  The IaaS-Company.

 ProfitBricks GmbH
 Greifswalder Str. 207
 D - 10405 Berlin
 Tel: +49 30 5770083-42
 Fax: +49 30 5770085-98
 Email: jinpu.w...@profitbricks.com
 URL: http://www.profitbricks.de

 Sitz der Gesellschaft: Berlin.
 Registergericht: Amtsgericht Charlottenburg, HRB 125506 B.
 Geschäftsführer: Andreas Gauger, Achim Weiss.
 --
 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
N�r��yb�X��ǧv�^�)޺{.n�+{{ay�ʇڙ�,j��f���h���z��w���
���j:+v���w�j�mzZ+�ݢj��!�i

RE: [PATCH 2/8] pm80xx: Corrected device state changes in I_T_Nexus_Reset

2015-07-30 Thread Viswas G


On Wed, Jul 29, 2015 at 9:40 PM, Tomas Henzl the...@redhat.com wrote:
 On 29.7.2015 08:27, viswa...@pmcs.com wrote:
 From: Viswas G viswa...@pmcs.com

 In Nexus reset the device state set to DS_IN_RECOVERY before doing
 phy reset and internal cleanup. Once internal cleanup finishes,
 the device state will set to DS_OPERATIONAL.

 Signed-off-by: Viswas G viswa...@pmcs.com
 Signed-off-by: Suresh Thiagarajan suresh.thiagara...@pmcs.com
 ---
  drivers/scsi/pm8001/pm8001_sas.c |   14 +++---
  drivers/scsi/pm8001/pm8001_sas.h |8 
  2 files changed, 19 insertions(+), 3 deletions(-)

 diff --git a/drivers/scsi/pm8001/pm8001_sas.c 
 b/drivers/scsi/pm8001/pm8001_sas.c
 index b93f289..4e6955f 100644
 --- a/drivers/scsi/pm8001/pm8001_sas.c
 +++ b/drivers/scsi/pm8001/pm8001_sas.c
 @@ -980,13 +980,21 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
   rc = 0;
   goto out;
   }
 + pm8001_dev-setds_completion = completion_setstate;
 + PM8001_CHIP_DISP-set_dev_state_req(pm8001_ha,
 + pm8001_dev, DS_IN_RECOVERY);
 + wait_for_completion(completion_setstate);
   rc = sas_phy_reset(phy, 1);
   msleep(2000);
 + if (rc) {
 + PM8001_EH_DBG(pm8001_ha,
 + pm8001_printk(phy reset failed for device %x\n
 + with rc %d\n, pm8001_dev-device_id, rc));
 + }
   rc = pm8001_exec_internal_task_abort(pm8001_ha, pm8001_dev ,
   dev, 1, 0);
 - pm8001_dev-setds_completion = completion_setstate;
 - rc = PM8001_CHIP_DISP-set_dev_state_req(pm8001_ha,
 - pm8001_dev, 0x01);
 + PM8001_CHIP_DISP-set_dev_state_req(pm8001_ha,
 + pm8001_dev, DS_OPERATIONAL);
 Hi Viswas,
 the set_dev_state_req can't fail any more ? Also the
 pm8001_exec_internal_task_abort may fail - shouldn't
 be error handling also added ?
 Cheers,
 Tomas

Hi  Tomas,

The set_dev_state can fail if the ccb/Inbound queue slot is not available. It 
can happen
If there are more than 256 requests are penning with controller.
Internal task abort failure also can be handled. Will resent the patch with 
these changes.

Regards,
Viswas G
 

   wait_for_completion(completion_setstate);
   } else {
   rc = sas_phy_reset(phy, 1);
 diff --git a/drivers/scsi/pm8001/pm8001_sas.h 
 b/drivers/scsi/pm8001/pm8001_sas.h
 index 8dd8b78..c9736cc 100644
 --- a/drivers/scsi/pm8001/pm8001_sas.h
 +++ b/drivers/scsi/pm8001/pm8001_sas.h
 @@ -569,6 +569,14 @@ struct pm8001_fw_image_header {
  #define  NCQ_READ_LOG_FLAG   0x8000
  #define  NCQ_ABORT_ALL_FLAG  0x4000
  #define  NCQ_2ND_RLE_FLAG0x2000
 +
 +/* Device states */
 +#define DS_OPERATIONAL   0x01
 +#define DS_PORT_IN_RESET 0x02
 +#define DS_IN_RECOVERY   0x03
 +#define DS_IN_ERROR  0x04
 +#define DS_NON_OPERATIONAL   0x07
 +
  /**
   * brief param structure for firmware flash update.
   */


 --
 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

-Original Message-
From: Tomas Henzl [mailto:the...@redhat.com] 
Sent: Wednesday, July 29, 2015 9:40 PM
To: Viswas G; linux-scsi@vger.kernel.org
Cc: xjtu...@gmail.com; jbottom...@parallels.com; Suresh Thiagarajan
Subject: Re: [PATCH 2/8] pm80xx: Corrected device state changes in 
I_T_Nexus_Reset

On 29.7.2015 08:27, viswa...@pmcs.com wrote:
 From: Viswas G viswa...@pmcs.com
 
 In Nexus reset the device state set to DS_IN_RECOVERY before doing phy 
 reset and internal cleanup. Once internal cleanup finishes, the device 
 state will set to DS_OPERATIONAL.
 
 Signed-off-by: Viswas G viswa...@pmcs.com
 Signed-off-by: Suresh Thiagarajan suresh.thiagara...@pmcs.com
 ---
  drivers/scsi/pm8001/pm8001_sas.c |   14 +++---
  drivers/scsi/pm8001/pm8001_sas.h |8 
  2 files changed, 19 insertions(+), 3 deletions(-)
 
 diff --git a/drivers/scsi/pm8001/pm8001_sas.c 
 b/drivers/scsi/pm8001/pm8001_sas.c
 index b93f289..4e6955f 100644
 --- a/drivers/scsi/pm8001/pm8001_sas.c
 +++ b/drivers/scsi/pm8001/pm8001_sas.c
 @@ -980,13 +980,21 @@ int pm8001_I_T_nexus_reset(struct domain_device *dev)
   rc = 0;
   goto out;
   }
 + pm8001_dev-setds_completion = completion_setstate;
 + PM8001_CHIP_DISP-set_dev_state_req(pm8001_ha,
 + pm8001_dev, DS_IN_RECOVERY);
 + wait_for_completion(completion_setstate);
   rc = sas_phy_reset(phy, 1);
   msleep(2000);
 + if (rc

RE: [PATCH 5/8] pm80xx: Remove unnecessary phy disconnect while link error

2015-07-29 Thread Viswas G

On Wed, Jul 29, 2015 at 2:26 PM, Hannes Reinecke h...@suse.de wrote:
 On 07/29/2015 08:27 AM, viswa...@pmcs.com wrote:
 From: Viswas G viswa...@pmcs.com

 If the link error happens, we don't need to disconnect the phy,
 which will remove the drive. Instead acknowledging the controller
 and logging the error will be enough.

 Signed-off-by: Viswas G viswa...@pmcs.com
 Signed-off-by: Suresh Thiagarajan suresh.thiagara...@pmcs.com
 ---
  drivers/scsi/pm8001/pm80xx_hwi.c |   12 
  1 files changed, 0 insertions(+), 12 deletions(-)

 diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c 
 b/drivers/scsi/pm8001/pm80xx_hwi.c
 index dced9f7..3d8b4ae 100644
 --- a/drivers/scsi/pm8001/pm80xx_hwi.c
 +++ b/drivers/scsi/pm8001/pm80xx_hwi.c
 @@ -3176,9 +3176,6 @@ static int mpi_hw_event(struct pm8001_hba_info 
 *pm8001_ha, void *piomb)
   pm8001_printk(HW_EVENT_LINK_ERR_INVALID_DWORD\n));
   pm80xx_hw_event_ack_req(pm8001_ha, 0,
   HW_EVENT_LINK_ERR_INVALID_DWORD, port_id, phy_id, 0, 
 0);
 - sas_phy_disconnected(sas_phy);
 - phy-phy_attached = 0;
 - sas_ha-notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
   break;
   case HW_EVENT_LINK_ERR_DISPARITY_ERROR:
   PM8001_MSG_DBG(pm8001_ha,
 @@ -3186,9 +3183,6 @@ static int mpi_hw_event(struct pm8001_hba_info 
 *pm8001_ha, void *piomb)
   pm80xx_hw_event_ack_req(pm8001_ha, 0,
   HW_EVENT_LINK_ERR_DISPARITY_ERROR,
   port_id, phy_id, 0, 0);
 - sas_phy_disconnected(sas_phy);
 - phy-phy_attached = 0;
 - sas_ha-notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
   break;
   case HW_EVENT_LINK_ERR_CODE_VIOLATION:
   PM8001_MSG_DBG(pm8001_ha,
 @@ -3196,9 +3190,6 @@ static int mpi_hw_event(struct pm8001_hba_info 
 *pm8001_ha, void *piomb)
   pm80xx_hw_event_ack_req(pm8001_ha, 0,
   HW_EVENT_LINK_ERR_CODE_VIOLATION,
   port_id, phy_id, 0, 0);
 - sas_phy_disconnected(sas_phy);
 - phy-phy_attached = 0;
 - sas_ha-notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
   break;
   case HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH:
   PM8001_MSG_DBG(pm8001_ha, pm8001_printk(
 @@ -3206,9 +3197,6 @@ static int mpi_hw_event(struct pm8001_hba_info 
 *pm8001_ha, void *piomb)
   pm80xx_hw_event_ack_req(pm8001_ha, 0,
   HW_EVENT_LINK_ERR_LOSS_OF_DWORD_SYNCH,
   port_id, phy_id, 0, 0);
 - sas_phy_disconnected(sas_phy);
 - phy-phy_attached = 0;
 - sas_ha-notify_port_event(sas_phy, PORTE_LINK_RESET_ERR);
   break;
   case HW_EVENT_MALFUNCTION:
   PM8001_MSG_DBG(pm8001_ha,

 So what happens with the port, then?
 Will you be getting another event when the port finally disconnects?
 If not, how to you remove the port after a link failure?


When the Phy disconnects, we will be getting the PHY DOWN events for 
the phys in that port and we will remove that port. 

 Cheers,

 Hannes
 --
 Dr. Hannes ReineckezSeries  Storage
 h...@suse.de   +49 911 74053 688
 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
 GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
 HRB 21284 (AG Nürnberg)
 --
 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 3/4] pm8001: add a new spinlock to protect the CCB

2014-06-27 Thread Viswas G
HI Tomas,

This lock is not needed as we are already protecting the tag allocation and 
freeing with the pm8001_ha-lock. We are always acquiring this lock before 
calling 
pm8001_tag_alloc().

We are allocating and freeing the tag in following paths, 

1) Request/Response path : This we are protecting using pm8001_ha-lock.
2)Driver initialization : We are not using the lock here . As there only one 
will be running, we don't need a lock here.
 
So there is no need of a specific lock for tag allocation.

Regards,
Viswas G

-Original Message-
From: Tomas Henzl [mailto:the...@redhat.com] 
Sent: Thursday, June 26, 2014 8:48 PM
To: linux-scsi@vger.kernel.org
Cc: zzzAnand Kumar Santhanam(Nov-20-2013); Vasanthalakshmi Tharmarajan; Suresh 
Thiagarajan; Viswas G; Tomas Henzl
Subject: [PATCH 3/4] pm8001: add a new spinlock to protect the CCB

Patch adds a new spinlock to protect the ccb management.
It may happen that concurrent threads become the same tag value from the 
'alloc' function', the spinlock prevents this situation.

Signed-off-by: Tomas Henzl the...@redhat.com
---
 drivers/scsi/pm8001/pm8001_init.c | 1 +  drivers/scsi/pm8001/pm8001_sas.c  | 7 
++-  drivers/scsi/pm8001/pm8001_sas.h  | 1 +
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/pm8001/pm8001_init.c 
b/drivers/scsi/pm8001/pm8001_init.c
index c4f31b21..56b61e5 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -246,6 +246,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,  
{
int i;
spin_lock_init(pm8001_ha-lock);
+   spin_lock_init(pm8001_ha-bitmap_lock);
PM8001_INIT_DBG(pm8001_ha,
pm8001_printk(pm8001_alloc: PHY:%x\n,
pm8001_ha-chip-n_phy));
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index be55859..34cea82 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -77,11 +77,16 @@ inline int pm8001_tag_alloc(struct pm8001_hba_info 
*pm8001_ha, u32 *tag_out)  {
unsigned int tag;
void *bitmap = pm8001_ha-tags;
+   unsigned long flags;
 
+   spin_lock_irqsave(pm8001_ha-bitmap_lock, flags);
tag = find_first_zero_bit(bitmap, pm8001_ha-tags_num);
-   if (tag = pm8001_ha-tags_num)
+   if (tag = pm8001_ha-tags_num) {
+   spin_unlock_irqrestore(pm8001_ha-bitmap_lock, flags);
return -SAS_QUEUE_FULL;
+   }
set_bit(tag, bitmap);
+   spin_unlock_irqrestore(pm8001_ha-bitmap_lock, flags);
*tag_out = tag;
return 0;
 }
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 14106ad..f6b2ac5 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -475,6 +475,7 @@ struct pm8001_hba_info {
struct list_headlist;
unsigned long   flags;
spinlock_t  lock;/* host-wide lock */
+   spinlock_t  bitmap_lock;
struct pci_dev  *pdev;/* our device */
struct device   *dev;
struct pm8001_hba_memspace io_mem[6];
--
1.8.3.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] pm80xx: Spinlock fix

2014-01-16 Thread Viswas G
From dfaae38ba7b6b7260fb3209d2dd12d70f0a8e306 Mon Sep 17 00:00:00 2001
From: Suresh Thiagarajan suresh.thiagara...@pmcs.com
Date: Thu, 16 Jan 2014 15:26:21 +0530
Subject: [PATCH V2] pm80xx: Spinlock fix

spin_lock_irqsave for the HBA lock is called in one function where flag
is local to that function. Another function is called from the first
function where lock has to be released using spin_unlock_irqrestore for 
calling task_done of libsas. In the second function also flag is declared
and used. For calling task_done there is no need to enable the irq. So 
instead of using spin_lock_irqsave and spin_unlock_irqrestore, spin_lock
and spin_unlock is used now. This also avoids passing the flags across all
the functions where HBA lock is being used. Also removed redundant code. 


Reported-by: Jason Seba jason.seb...@gmail.com
Signed-off-by: Oleg Nesterov o...@redhat.com
Signed-off-by: Suresh Thiagarajan suresh.thiagara...@pmcs.com
Signed-off-by: Viswas G viswa...@pmcs.com
---
 drivers/scsi/pm8001/pm8001_hwi.c |   84 ++
 drivers/scsi/pm8001/pm8001_sas.h |   12 +
 drivers/scsi/pm8001/pm80xx_hwi.c |   84 ++
 3 files changed, 38 insertions(+), 142 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 46ace52..d6a4b17 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -2502,11 +2502,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
ts-resp = SAS_TASK_UNDELIVERED;
ts-stat = SAS_QUEUE_FULL;
-   pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-   mb();/*in order to force CPU ordering*/
-   spin_unlock_irq(pm8001_ha-lock);
-   t-task_done(t);
-   spin_lock_irq(pm8001_ha-lock);
+   pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
return;
}
break;
@@ -2522,11 +2518,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS);
ts-resp = SAS_TASK_UNDELIVERED;
ts-stat = SAS_QUEUE_FULL;
-   pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-   mb();/*ditto*/
-   spin_unlock_irq(pm8001_ha-lock);
-   t-task_done(t);
-   spin_lock_irq(pm8001_ha-lock);
+   pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
return;
}
break;
@@ -2550,11 +2542,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY);
ts-resp = SAS_TASK_UNDELIVERED;
ts-stat = SAS_QUEUE_FULL;
-   pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-   mb();/* ditto*/
-   spin_unlock_irq(pm8001_ha-lock);
-   t-task_done(t);
-   spin_lock_irq(pm8001_ha-lock);
+   pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
return;
}
break;
@@ -2617,11 +2605,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
IO_DS_NON_OPERATIONAL);
ts-resp = SAS_TASK_UNDELIVERED;
ts-stat = SAS_QUEUE_FULL;
-   pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-   mb();/*ditto*/
-   spin_unlock_irq(pm8001_ha-lock);
-   t-task_done(t);
-   spin_lock_irq(pm8001_ha-lock);
+   pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
return;
}
break;
@@ -2641,11 +2625,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
IO_DS_IN_ERROR);
ts-resp = SAS_TASK_UNDELIVERED;
ts-stat = SAS_QUEUE_FULL;
-   pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
-   mb();/*ditto*/
-   spin_unlock_irq(pm8001_ha-lock);
-   t-task_done(t);
-   spin_lock_irq(pm8001_ha-lock);
+   pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag);
return;
}
break;
@@ -2674,20 +2654,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, 
void *piomb)
 resp 0x%x stat 0x%x but aborted by upper layer!\n

[PATCH] pm80xx: Spinlock fix

2013-12-18 Thread Viswas G
From 9338d4bc92b23b4c283f9bd6812646ab74866a40 Mon Sep 17 00:00:00 2001
From: Suresh Thiagarajan suresh.thiagara...@pmcs.com
Date: Mon, 16 Dec 2013 21:15:20 +0530
Subject: [PATCH] pm80xx: Spinlock fix

spin_unlock was used instead of spin_unlock_irqrestore. To fix this 
lock_flags per-adapter is added and used across all the places where 
pm8001_ha-lock is used.

Reported-by: Jason Seba jason.seb...@gmail.com
Signed-off-by: Suresh Thiagarajan suresh.thiagara...@pmcs.com
Signed-off-by: Viswas G viswa...@pmcs.com
---
 drivers/scsi/pm8001/pm8001_hwi.c |  158 ++
 drivers/scsi/pm8001/pm8001_sas.c |   50 ++--
 drivers/scsi/pm8001/pm8001_sas.h |1 +
 drivers/scsi/pm8001/pm80xx_hwi.c |   69 ++---
 4 files changed, 160 insertions(+), 118 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 0a1296a..3901c40 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -411,7 +411,6 @@ static void mpi_set_phys_g3_with_ssc(struct pm8001_hba_info 
*pm8001_ha,
 u32 SSCbit)
 {
u32 value, offset, i;
-   unsigned long flags;
 
 #define SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR 0x0003
 #define SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR 0x0004
@@ -425,10 +424,10 @@ static void mpi_set_phys_g3_with_ssc(struct 
pm8001_hba_info *pm8001_ha,
 * Using shifted destination address 0x3_:0x1074 + 0x4000*N (N=0:3)
 * Using shifted destination address 0x4_:0x1074 + 0x4000*(N-4) (N=4:7)
 */
-   spin_lock_irqsave(pm8001_ha-lock, flags);
+   spin_lock_irqsave(pm8001_ha-lock, pm8001_ha-lock_flags);
if (-1 == pm8001_bar4_shift(pm8001_ha,
SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR)) {
-   spin_unlock_irqrestore(pm8001_ha-lock, flags);
+   spin_unlock_irqrestore(pm8001_ha-lock, pm8001_ha-lock_flags);
return;
}
 
@@ -439,7 +438,7 @@ static void mpi_set_phys_g3_with_ssc(struct pm8001_hba_info 
*pm8001_ha,
/* shift membase 3 for SAS2_SETTINGS_LOCAL_PHY 4 - 7 */
if (-1 == pm8001_bar4_shift(pm8001_ha,
SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR)) {
-   spin_unlock_irqrestore(pm8001_ha-lock, flags);
+   spin_unlock_irqrestore(pm8001_ha-lock, pm8001_ha-lock_flags);
return;
}
for (i = 4; i  8; i++) {
@@ -466,7 +465,7 @@ static void mpi_set_phys_g3_with_ssc(struct pm8001_hba_info 
*pm8001_ha,
 
/*set the shifted destination address to 0x0 to avoid error operation */
pm8001_bar4_shift(pm8001_ha, 0x0);
-   spin_unlock_irqrestore(pm8001_ha-lock, flags);
+   spin_unlock_irqrestore(pm8001_ha-lock, pm8001_ha-lock_flags);
return;
 }
 
@@ -481,7 +480,6 @@ static void mpi_set_open_retry_interval_reg(struct 
pm8001_hba_info *pm8001_ha,
u32 offset;
u32 value;
u32 i;
-   unsigned long flags;
 
 #define OPEN_RETRY_INTERVAL_PHY_0_3_SHIFT_ADDR 0x0003
 #define OPEN_RETRY_INTERVAL_PHY_4_7_SHIFT_ADDR 0x0004
@@ -490,11 +488,11 @@ static void mpi_set_open_retry_interval_reg(struct 
pm8001_hba_info *pm8001_ha,
 #define OPEN_RETRY_INTERVAL_REG_MASK 0x
 
value = interval  OPEN_RETRY_INTERVAL_REG_MASK;
-   spin_lock_irqsave(pm8001_ha-lock, flags);
+   spin_lock_irqsave(pm8001_ha-lock, pm8001_ha-lock_flags);
/* shift bar and set the OPEN_REJECT(RETRY) interval time of PHY 0 -3.*/
if (-1 == pm8001_bar4_shift(pm8001_ha,
 OPEN_RETRY_INTERVAL_PHY_0_3_SHIFT_ADDR)) {
-   spin_unlock_irqrestore(pm8001_ha-lock, flags);
+   spin_unlock_irqrestore(pm8001_ha-lock, pm8001_ha-lock_flags);
return;
}
for (i = 0; i  4; i++) {
@@ -504,7 +502,7 @@ static void mpi_set_open_retry_interval_reg(struct 
pm8001_hba_info *pm8001_ha,
 
if (-1 == pm8001_bar4_shift(pm8001_ha,
 OPEN_RETRY_INTERVAL_PHY_4_7_SHIFT_ADDR)) {
-   spin_unlock_irqrestore(pm8001_ha-lock, flags);
+   spin_unlock_irqrestore(pm8001_ha-lock, pm8001_ha-lock_flags);
return;
}
for (i = 4; i  8; i++) {
@@ -513,7 +511,7 @@ static void mpi_set_open_retry_interval_reg(struct 
pm8001_hba_info *pm8001_ha,
}
/*set the shifted destination address to 0x0 to avoid error operation */
pm8001_bar4_shift(pm8001_ha, 0x0);
-   spin_unlock_irqrestore(pm8001_ha-lock, flags);
+   spin_unlock_irqrestore(pm8001_ha-lock, pm8001_ha-lock_flags);
return;
 }
 
@@ -768,11 +766,11 @@ static u32 soft_reset_ready_check(struct pm8001_hba_info 
*pm8001_ha)
PM8001_INIT_DBG(pm8001_ha,
pm8001_printk(Firmware is ready for reset .\n));
} else {
-   unsigned long flags;
/* Trigger NMI twice via

[PATCH v2 0/2] pm8001 driver code cleanup

2013-12-09 Thread Viswas G
We are resubmitting the following patches in the new patch set

pm80xx : Removing redundant code snippets pm80xx : Fixed return value issue

Please discard the previous patches we submitted for the same.

[PATCH 5/6] pm80xx : Removing redundant code snippets
http://marc.info/?l=linux-scsim=138493235925253w=2

[PATCH 6/6] pm80xx : Fixed return value issue
http://marc.info/?l=linux-scsim=138493243028701w=2

Sorry for the confusion.

This patch set has to be applied after the below patch set submitted by Anand.

http://marc.info/?l=linux-scsim=138434875025909w=2


Viswas G (2):
  pm80xx : Removing redundant code snippets
  pm80xx : Fixed return value issue

 drivers/scsi/pm8001/pm8001_ctl.c |   38 --
 drivers/scsi/pm8001/pm8001_hwi.c |   15 +--
 drivers/scsi/pm8001/pm80xx_hwi.c |   15 ---
 3 files changed, 21 insertions(+), 47 deletions(-)

--
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/2] pm80xx : Removing redundant code snippets

2013-12-09 Thread Viswas G
Removed redundant code snippets in pm8001_hwi.c and
pm8001_ctl.c

Signed-off-by: Viswas G viswa...@pmcs.com
Reviewed-by: Jack Wang jinpu.w...@profitbricks.com
---
 drivers/scsi/pm8001/pm8001_ctl.c |   34 ++
 drivers/scsi/pm8001/pm8001_hwi.c |7 +--
 2 files changed, 11 insertions(+), 30 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index a04b4ff..1738965 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -323,24 +323,17 @@ static ssize_t pm8001_ctl_ib_queue_log_show(struct device 
*cdev,
int offset;
char *str = buf;
int start = 0;
-#define IB_MEMMAP(c)   \
-   (*(u32 *)((u8 *)pm8001_ha- \
-   memoryMap.region[IB].virt_ptr + \
+#define IB_MEMMAP(c)   \
+   (*(u32 *)((u8 *)pm8001_ha- \
+   memoryMap.region[IB].virt_ptr + \
pm8001_ha-evtlog_ib_offset + (c)))
 
for (offset = 0; offset  IB_OB_READ_TIMES; offset++) {
-   if (pm8001_ha-chip_id != chip_8001)
-   str += sprintf(str, 0x%08x\n, IB_MEMMAP(start));
-   else
-   str += sprintf(str, 0x%08x\n, IB_MEMMAP(start));
+   str += sprintf(str, 0x%08x\n, IB_MEMMAP(start));
start = start + 4;
}
pm8001_ha-evtlog_ib_offset += SYSFS_OFFSET;
-   if pm8001_ha-evtlog_ib_offset) % (PM80XX_IB_OB_QUEUE_SIZE)) == 0)
-(pm8001_ha-chip_id != chip_8001))
-   pm8001_ha-evtlog_ib_offset = 0;
-   if pm8001_ha-evtlog_ib_offset) % (PM8001_IB_OB_QUEUE_SIZE)) == 0)
-(pm8001_ha-chip_id == chip_8001))
+   if (((pm8001_ha-evtlog_ib_offset) % (PM80XX_IB_OB_QUEUE_SIZE)) == 0)
pm8001_ha-evtlog_ib_offset = 0;
 
return str - buf;
@@ -363,24 +356,17 @@ static ssize_t pm8001_ctl_ob_queue_log_show(struct device 
*cdev,
int offset;
char *str = buf;
int start = 0;
-#define OB_MEMMAP(c)   \
-   (*(u32 *)((u8 *)pm8001_ha- \
-   memoryMap.region[OB].virt_ptr + \
+#define OB_MEMMAP(c)   \
+   (*(u32 *)((u8 *)pm8001_ha- \
+   memoryMap.region[OB].virt_ptr + \
pm8001_ha-evtlog_ob_offset + (c)))
 
for (offset = 0; offset  IB_OB_READ_TIMES; offset++) {
-   if (pm8001_ha-chip_id != chip_8001)
-   str += sprintf(str, 0x%08x\n, OB_MEMMAP(start));
-   else
-   str += sprintf(str, 0x%08x\n, OB_MEMMAP(start));
+   str += sprintf(str, 0x%08x\n, OB_MEMMAP(start));
start = start + 4;
}
pm8001_ha-evtlog_ob_offset += SYSFS_OFFSET;
-   if pm8001_ha-evtlog_ob_offset) % (PM80XX_IB_OB_QUEUE_SIZE)) == 0)
-(pm8001_ha-chip_id != chip_8001))
-   pm8001_ha-evtlog_ob_offset = 0;
-   if pm8001_ha-evtlog_ob_offset) % (PM8001_IB_OB_QUEUE_SIZE)) == 0)
-(pm8001_ha-chip_id == chip_8001))
+   if (((pm8001_ha-evtlog_ob_offset) % (PM80XX_IB_OB_QUEUE_SIZE)) == 0)
pm8001_ha-evtlog_ob_offset = 0;
 
return str - buf;
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 0a1296a..2aa0681 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -5072,13 +5072,8 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, 
char *buf)
direct_data += sprintf(direct_data, %08x , value);
}
/* Shift back to BAR4 original address */
-   if (pm8001_ha-chip_id == chip_8001) {
-   if (-1 == pm8001_bar4_shift(pm8001_ha, 0))
+   if (-1 == pm8001_bar4_shift(pm8001_ha, 0))
return 1;
-   } else {
-   if (-1 == pm80xx_bar4_shift(pm8001_ha, 0))
-   return 1;
-   }
pm8001_ha-fatal_forensic_shift_offset += 1024;
 
if (pm8001_ha-fatal_forensic_shift_offset = 0x10)
-- 
1.7.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/2] pm80xx : Fixed return value issue

2013-12-09 Thread Viswas G
pm80xx_get_gsm_dump() was returning 1 in error case
instead of negative error value.

Signed-off-by: Viswas G viswa...@pmcs.com
Reviewed-by: Jack Wang jinpu.w...@profitbricks.com
Acked-by: TomasHenzl the...@redhat.com
---
 drivers/scsi/pm8001/pm8001_ctl.c |4 ++--
 drivers/scsi/pm8001/pm8001_hwi.c |8 
 drivers/scsi/pm8001/pm80xx_hwi.c |   15 ---
 3 files changed, 10 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 1738965..28b4e81 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -452,7 +452,7 @@ static DEVICE_ATTR(iop_log, S_IRUGO, 
pm8001_ctl_iop_log_show, NULL);
 static ssize_t pm8001_ctl_fatal_log_show(struct device *cdev,
struct device_attribute *attr, char *buf)
 {
-   u32 count;
+   ssize_t count;
 
count = pm80xx_get_fatal_dump(cdev, attr, buf);
return count;
@@ -470,7 +470,7 @@ static DEVICE_ATTR(fatal_log, S_IRUGO, 
pm8001_ctl_fatal_log_show, NULL);
 static ssize_t pm8001_ctl_gsm_log_show(struct device *cdev,
struct device_attribute *attr, char *buf)
 {
-   u32 count;
+   ssize_t count;
 
count = pm8001_get_gsm_dump(cdev, SYSFS_OFFSET, buf);
return count;
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 2aa0681..46ace52 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -5020,7 +5020,7 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, char 
*buf)
/* check max is 1 Mbytes */
if ((length  0x10) || (gsm_dump_offset  3) ||
((gsm_dump_offset + length)  0x100))
-   return 1;
+   return -EINVAL;
 
if (pm8001_ha-chip_id == chip_8001)
bar = 2;
@@ -5048,12 +5048,12 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, 
char *buf)
gsm_base = GSM_BASE;
if (-1 == pm8001_bar4_shift(pm8001_ha,
(gsm_base + shift_value)))
-   return 1;
+   return -EIO;
} else {
gsm_base = 0;
if (-1 == pm80xx_bar4_shift(pm8001_ha,
(gsm_base + shift_value)))
-   return 1;
+   return -EIO;
}
gsm_dump_offset = (gsm_dump_offset + offset) 
0x;
@@ -5073,7 +5073,7 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, char 
*buf)
}
/* Shift back to BAR4 original address */
if (-1 == pm8001_bar4_shift(pm8001_ha, 0))
-   return 1;
+   return -EIO;
pm8001_ha-fatal_forensic_shift_offset += 1024;
 
if (pm8001_ha-fatal_forensic_shift_offset = 0x10)
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index c950dc5..65de79c 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -91,7 +91,6 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
struct pm8001_hba_info *pm8001_ha = sha-lldd_ha;
void __iomem *fatal_table_address = pm8001_ha-fatal_tbl_addr;
-   u32 status = 1;
u32 accum_len , reg_val, index, *temp;
unsigned long start;
u8 *direct_data;
@@ -111,13 +110,10 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
direct_data = (u8 *)fatal_error_data;
pm8001_ha-forensic_info.data_type = TYPE_NON_FATAL;
pm8001_ha-forensic_info.data_buf.direct_len = SYSFS_OFFSET;
-   pm8001_ha-forensic_info.data_buf.direct_offset = 0;
pm8001_ha-forensic_info.data_buf.read_len = 0;
 
pm8001_ha-forensic_info.data_buf.direct_data = direct_data;
-   }
-
-   if (pm8001_ha-forensic_info.data_buf.direct_offset == 0) {
+
/* start to get data */
/* Program the MEMBASE II Shifting Register with 0x00.*/
pm8001_cw32(pm8001_ha, 0, MEMBASE_II_SHIFT_REGISTER,
@@ -126,6 +122,7 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
pm8001_ha-forensic_fatal_step = 0;
pm8001_ha-fatal_bar_loc = 0;
}
+
/* Read until accum_len is retrived */
accum_len = pm8001_mr32(fatal_table_address,
MPI_FATAL_EDUMP_TABLE_ACCUM_LEN);
@@ -135,7 +132,7 @@ ssize_t pm80xx_get_fatal_dump(struct device *cdev,
PM8001_IO_DBG(pm8001_ha,
pm8001_printk(Possible PCI issue 0x%x not expected\n

[PATCH 0/2] pm8001 driver code cleanup

2013-11-26 Thread Viswas G
We are resubmitting the following patches in the new patch set

pm80xx : Removing redundant code snippets
pm80xx : Fixed return value issue 

Please discard the previous patches we submitted for the same.

[PATCH 5/6] pm80xx : Removing redundant code snippets
http://marc.info/?l=linux-scsim=138493235925253w=2

[PATCH 6/6] pm80xx : Fixed return value issue
http://marc.info/?l=linux-scsim=138493243028701w=2

Sorry for the confusion.

This patch set has to be applied after the below patch set 
submitted by Anand.

http://marc.info/?l=linux-scsim=138434875025909w=2


Viswas G (2):
  pm80xx : Removing redundant code snippets
  pm80xx : Fixed return value issue.

 drivers/scsi/pm8001/pm8001_ctl.c |   26 ++
 drivers/scsi/pm8001/pm8001_hwi.c |   15 +--
 2 files changed, 15 insertions(+), 26 deletions(-)

--
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/2] pm80xx : Removing redundant code snippets

2013-11-26 Thread Viswas G
Removed redundant code snippets in pm8001_hwi.c
and pm8001_ctl.c

Signed-off-by: Viswas G viswa...@pmcs.com
---
 drivers/scsi/pm8001/pm8001_ctl.c |   22 --
 drivers/scsi/pm8001/pm8001_hwi.c |7 +--
 2 files changed, 9 insertions(+), 20 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index a04b4ff..1e055ae 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -323,16 +323,13 @@ static ssize_t pm8001_ctl_ib_queue_log_show(struct device 
*cdev,
int offset;
char *str = buf;
int start = 0;
-#define IB_MEMMAP(c)   \
-   (*(u32 *)((u8 *)pm8001_ha- \
-   memoryMap.region[IB].virt_ptr + \
+#define IB_MEMMAP(c)   \
+   (*(u32 *)((u8 *)pm8001_ha- \
+   memoryMap.region[IB].virt_ptr + \
pm8001_ha-evtlog_ib_offset + (c)))
 
for (offset = 0; offset  IB_OB_READ_TIMES; offset++) {
-   if (pm8001_ha-chip_id != chip_8001)
-   str += sprintf(str, 0x%08x\n, IB_MEMMAP(start));
-   else
-   str += sprintf(str, 0x%08x\n, IB_MEMMAP(start));
+   str += sprintf(str, 0x%08x\n, IB_MEMMAP(start));
start = start + 4;
}
pm8001_ha-evtlog_ib_offset += SYSFS_OFFSET;
@@ -363,16 +360,13 @@ static ssize_t pm8001_ctl_ob_queue_log_show(struct device 
*cdev,
int offset;
char *str = buf;
int start = 0;
-#define OB_MEMMAP(c)   \
-   (*(u32 *)((u8 *)pm8001_ha- \
-   memoryMap.region[OB].virt_ptr + \
+#define OB_MEMMAP(c)   \
+   (*(u32 *)((u8 *)pm8001_ha- \
+   memoryMap.region[OB].virt_ptr + \
pm8001_ha-evtlog_ob_offset + (c)))
 
for (offset = 0; offset  IB_OB_READ_TIMES; offset++) {
-   if (pm8001_ha-chip_id != chip_8001)
-   str += sprintf(str, 0x%08x\n, OB_MEMMAP(start));
-   else
-   str += sprintf(str, 0x%08x\n, OB_MEMMAP(start));
+   str += sprintf(str, 0x%08x\n, OB_MEMMAP(start));
start = start + 4;
}
pm8001_ha-evtlog_ob_offset += SYSFS_OFFSET;
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 0a1296a..2aa0681 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -5072,13 +5072,8 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, 
char *buf)
direct_data += sprintf(direct_data, %08x , value);
}
/* Shift back to BAR4 original address */
-   if (pm8001_ha-chip_id == chip_8001) {
-   if (-1 == pm8001_bar4_shift(pm8001_ha, 0))
+   if (-1 == pm8001_bar4_shift(pm8001_ha, 0))
return 1;
-   } else {
-   if (-1 == pm80xx_bar4_shift(pm8001_ha, 0))
-   return 1;
-   }
pm8001_ha-fatal_forensic_shift_offset += 1024;
 
if (pm8001_ha-fatal_forensic_shift_offset = 0x10)
-- 
1.7.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/2] pm80xx : Fixed return value issue.

2013-11-26 Thread Viswas G
pm80xx_get_gsm_dump() was returning 1 in error case instead of
negative error value.

Signed-off-by: Viswas G viswa...@pmcs.com
---
 drivers/scsi/pm8001/pm8001_ctl.c |4 ++--
 drivers/scsi/pm8001/pm8001_hwi.c |8 
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 1e055ae..ce91852 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -460,7 +460,7 @@ static DEVICE_ATTR(iop_log, S_IRUGO, 
pm8001_ctl_iop_log_show, NULL);
 static ssize_t pm8001_ctl_fatal_log_show(struct device *cdev,
struct device_attribute *attr, char *buf)
 {
-   u32 count;
+   ssize_t count;
 
count = pm80xx_get_fatal_dump(cdev, attr, buf);
return count;
@@ -478,7 +478,7 @@ static DEVICE_ATTR(fatal_log, S_IRUGO, 
pm8001_ctl_fatal_log_show, NULL);
 static ssize_t pm8001_ctl_gsm_log_show(struct device *cdev,
struct device_attribute *attr, char *buf)
 {
-   u32 count;
+   ssize_t count;
 
count = pm8001_get_gsm_dump(cdev, SYSFS_OFFSET, buf);
return count;
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index 2aa0681..46ace52 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -5020,7 +5020,7 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, char 
*buf)
/* check max is 1 Mbytes */
if ((length  0x10) || (gsm_dump_offset  3) ||
((gsm_dump_offset + length)  0x100))
-   return 1;
+   return -EINVAL;
 
if (pm8001_ha-chip_id == chip_8001)
bar = 2;
@@ -5048,12 +5048,12 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, 
char *buf)
gsm_base = GSM_BASE;
if (-1 == pm8001_bar4_shift(pm8001_ha,
(gsm_base + shift_value)))
-   return 1;
+   return -EIO;
} else {
gsm_base = 0;
if (-1 == pm80xx_bar4_shift(pm8001_ha,
(gsm_base + shift_value)))
-   return 1;
+   return -EIO;
}
gsm_dump_offset = (gsm_dump_offset + offset) 
0x;
@@ -5073,7 +5073,7 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, char 
*buf)
}
/* Shift back to BAR4 original address */
if (-1 == pm8001_bar4_shift(pm8001_ha, 0))
-   return 1;
+   return -EIO;
pm8001_ha-fatal_forensic_shift_offset += 1024;
 
if (pm8001_ha-fatal_forensic_shift_offset = 0x10)
-- 
1.7.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 6/6] pm80xx : Fixed return value issue

2013-11-20 Thread Viswas G
Hi Tomas,

Patches 1-4 are submitted with subject [PATCH V2 0/4]: pm8001 driver bug 
fixes.

As this patch has to be applied after those four patches, we submitted this as 
5/6 and 6/6.

We will resend the modified  patch.

Regards,
Viswas G
 
 
-Original Message-
From: Tomas Henzl [mailto:the...@redhat.com] 
Sent: Wednesday, November 20, 2013 10:16 PM
To: Viswas G; linux-scsi@vger.kernel.org
Cc: xjtu...@gmail.com; Vasanthalakshmi Tharmarajan; Suresh Thiagarajan
Subject: Re: [PATCH 6/6] pm80xx : Fixed return value issue

On 11/20/2013 08:22 AM, Viswas G wrote:
 pm8001_get_gsm_dump() was returning 1 in error case instead of 
 negative error code.

Hi,

the pm8001_get_gsm_dum return value is used here I think:

static ssize_t pm8001_ctl_gsm_log_show(struct device *cdev,
   struct device_attribute *attr, char *buf) {
   u32 count;

   count = pm8001_get_gsm_dump(cdev, SYSFS_OFFSET, buf);
---
could you also change the 'count' from unsigned to a signed type?

Maybe in some cases another errno would make more sense (ENODEV, EIO?), but 
I'll leave this up to you.

I have noticed in this series only patches 5/6 and 6/6, I miss the 1-4/6, could 
you help me find them ? What are the subjects of 1-4/6?

Thanks, Tomas


 Signed-off-by: Viswas G viswa...@pmcs.com
 ---
  drivers/scsi/pm8001/pm8001_hwi.c |8 
  1 files changed, 4 insertions(+), 4 deletions(-)

 diff --git a/drivers/scsi/pm8001/pm8001_hwi.c 
 b/drivers/scsi/pm8001/pm8001_hwi.c
 index f6ea277..e2932ef 100644
 --- a/drivers/scsi/pm8001/pm8001_hwi.c
 +++ b/drivers/scsi/pm8001/pm8001_hwi.c
 @@ -5020,7 +5020,7 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, 
 char* buf)
   /* check max is 1 Mbytes */
   if ((length  0x10) || (gsm_dump_offset  3) ||
   ((gsm_dump_offset + length)  0x100))
 - return 1;
 + return -EINVAL;
  
   if (pm8001_ha-chip_id == chip_8001)
   bar = 2;
 @@ -5048,12 +5048,12 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, 
 char* buf)
   gsm_base = GSM_BASE;
   if (-1 == pm8001_bar4_shift(pm8001_ha,
   (gsm_base + shift_value)))
 - return 1;
 + return -EINVAL;
   } else {
   gsm_base = 0;
   if (-1 == pm80xx_bar4_shift(pm8001_ha,
   (gsm_base + shift_value)))
 - return 1;
 + return -EINVAL;
   }
   gsm_dump_offset = (gsm_dump_offset + offset) 
   0x;
 @@ -5073,7 +5073,7 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, 
 char* buf)
   }
   /* Shift back to BAR4 original address */
   if (-1 == pm8001_bar4_shift(pm8001_ha, 0))
 - return 1;
 + return -EINVAL;
   pm8001_ha-fatal_forensic_shift_offset += 1024;
  
   if (pm8001_ha-fatal_forensic_shift_offset = 0x10)

--
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/6] pm80xx : Removing redundant code snippets

2013-11-19 Thread Viswas G
Removed redundant code snipptes in pm8001_hwi.c
and pm8001_ctl.c

Signed-off-by: Viswas G viswa...@pmcs.com
---
 drivers/scsi/pm8001/pm8001_ctl.c |   22 --
 drivers/scsi/pm8001/pm8001_hwi.c |7 +--
 2 files changed, 9 insertions(+), 20 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index a04b4ff..1e055ae 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -323,16 +323,13 @@ static ssize_t pm8001_ctl_ib_queue_log_show(struct device 
*cdev,
int offset;
char *str = buf;
int start = 0;
-#define IB_MEMMAP(c)   \
-   (*(u32 *)((u8 *)pm8001_ha- \
-   memoryMap.region[IB].virt_ptr + \
+#define IB_MEMMAP(c)   \
+   (*(u32 *)((u8 *)pm8001_ha- \
+   memoryMap.region[IB].virt_ptr + \
pm8001_ha-evtlog_ib_offset + (c)))
 
for (offset = 0; offset  IB_OB_READ_TIMES; offset++) {
-   if (pm8001_ha-chip_id != chip_8001)
-   str += sprintf(str, 0x%08x\n, IB_MEMMAP(start));
-   else
-   str += sprintf(str, 0x%08x\n, IB_MEMMAP(start));
+   str += sprintf(str, 0x%08x\n, IB_MEMMAP(start));
start = start + 4;
}
pm8001_ha-evtlog_ib_offset += SYSFS_OFFSET;
@@ -363,16 +360,13 @@ static ssize_t pm8001_ctl_ob_queue_log_show(struct device 
*cdev,
int offset;
char *str = buf;
int start = 0;
-#define OB_MEMMAP(c)   \
-   (*(u32 *)((u8 *)pm8001_ha- \
-   memoryMap.region[OB].virt_ptr + \
+#define OB_MEMMAP(c)   \
+   (*(u32 *)((u8 *)pm8001_ha- \
+   memoryMap.region[OB].virt_ptr + \
pm8001_ha-evtlog_ob_offset + (c)))
 
for (offset = 0; offset  IB_OB_READ_TIMES; offset++) {
-   if (pm8001_ha-chip_id != chip_8001)
-   str += sprintf(str, 0x%08x\n, OB_MEMMAP(start));
-   else
-   str += sprintf(str, 0x%08x\n, OB_MEMMAP(start));
+   str += sprintf(str, 0x%08x\n, OB_MEMMAP(start));
start = start + 4;
}
pm8001_ha-evtlog_ob_offset += SYSFS_OFFSET;
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index b23f49d..f6ea277 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -5072,13 +5072,8 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, 
char* buf)
direct_data += sprintf(direct_data, %08x , value);
}
/* Shift back to BAR4 original address */
-   if (pm8001_ha-chip_id == chip_8001) {
-   if (-1 == pm8001_bar4_shift(pm8001_ha, 0))
+   if (-1 == pm8001_bar4_shift(pm8001_ha, 0))
return 1;
-   } else {
-   if (-1 == pm80xx_bar4_shift(pm8001_ha, 0))
-   return 1;
-   }
pm8001_ha-fatal_forensic_shift_offset += 1024;
 
if (pm8001_ha-fatal_forensic_shift_offset = 0x10)
-- 
1.7.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 6/6] pm80xx : Fixed return value issue

2013-11-19 Thread Viswas G
pm8001_get_gsm_dump() was returning 1 in error case
instead of negative error code.

Signed-off-by: Viswas G viswa...@pmcs.com
---
 drivers/scsi/pm8001/pm8001_hwi.c |8 
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index f6ea277..e2932ef 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -5020,7 +5020,7 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, 
char* buf)
/* check max is 1 Mbytes */
if ((length  0x10) || (gsm_dump_offset  3) ||
((gsm_dump_offset + length)  0x100))
-   return 1;
+   return -EINVAL;
 
if (pm8001_ha-chip_id == chip_8001)
bar = 2;
@@ -5048,12 +5048,12 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, 
char* buf)
gsm_base = GSM_BASE;
if (-1 == pm8001_bar4_shift(pm8001_ha,
(gsm_base + shift_value)))
-   return 1;
+   return -EINVAL;
} else {
gsm_base = 0;
if (-1 == pm80xx_bar4_shift(pm8001_ha,
(gsm_base + shift_value)))
-   return 1;
+   return -EINVAL;
}
gsm_dump_offset = (gsm_dump_offset + offset) 
0x;
@@ -5073,7 +5073,7 @@ pm8001_get_gsm_dump(struct device *cdev, u32 length, 
char* buf)
}
/* Shift back to BAR4 original address */
if (-1 == pm8001_bar4_shift(pm8001_ha, 0))
-   return 1;
+   return -EINVAL;
pm8001_ha-fatal_forensic_shift_offset += 1024;
 
if (pm8001_ha-fatal_forensic_shift_offset = 0x10)
-- 
1.7.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 11/11] pm80xx : gpio feature support for motherboard controllers

2013-11-14 Thread Viswas G
Hi James,

Can you please share your opinion on this ?

Regards
Viswas G


-Original Message-
From: Jack Wang [mailto:xjtu...@gmail.com] 
Sent: Monday, November 11, 2013 2:28 PM
To: Viswas G; James Bottomley
Cc: linux-scsi@vger.kernel.org; Sangeetha Gnanasekaran; Nikith Ganigarakoppal; 
Anand Kumar Santhanam; Suresh Thiagarajan
Subject: Re: [PATCH 11/11] pm80xx : gpio feature support for motherboard 
controllers

Hi James,

About this gpio feature, do you think it's OK to implement with IOCTL or we can 
use exist bsg interface in libsas and add another function call?

Regards,
Jack

On 11/11/2013 06:57 AM, Viswas G wrote:
 Hi Jack,
 
 The GPIO feature we implemented here is for controlling and configuring the 
 GPIO pins present in the HBA and it is not related to the GPIO registers 
 present in the SGPIO. Following is one of the GPIO operations we do from 
 application.
 
 When application wants to know the insertion/removal of a SAS cable in any of 
 the port, it configures the GPIO for corresponding port to generate event for 
 SAS cable insertion or removal using the IOCTL to the HBA driver and waits by 
 calling poll function. When driver receives the GPIO event for the SAS cable 
 insertion or removal then it intimates the application.
 
 We are using IOCTL instead of sysfs interface since we have to pass 
 structures between user space and kernel space. Again, in the kernel space, 
 we have to parse user buffer from application and convert it to the 
 corresponding data structure. We wanted to avoid the parsing complexity by 
 using ioctl interface.
 
 Regards,
 Viswas G
 
 
 -Original Message-
 From: Jack Wang [mailto:xjtu...@gmail.com]
 Sent: Monday, November 04, 2013 4:00 PM
 To: Viswas G
 Cc: linux-scsi@vger.kernel.org; Sangeetha Gnanasekaran; Nikith 
 Ganigarakoppal; Anand Kumar Santhanam; Suresh Thiagarajan
 Subject: Re: [PATCH 11/11] pm80xx : gpio feature support for 
 motherboard controllers
 
 On 11/04/2013 11:13 AM, Viswas G wrote:
 Hi Jack,

 We wanted to control the GPIO in the HBA only. Bsg interface gets created 
 only for enclosure or expander. 

 For our HBA, bsg interface will not be created since it does not have an 
 enclosure target inside. That's why we wanted to use IOCTL. Please advise.

 Best Regards,
 Viswas G

 Hi Viswas,
 
 No, bsg interface also support HBA.
 Here is two example output from LSI mpt2sas:
 
 smp_rep_manufacturer /dev/bsg/sas_host0 Report manufacturer response:
   SAS-1.1 format: 0
   vendor identification: LSI
   product identification: Virtual SMP Port
   product revision level:
 smp_read_gpio /dev/bsg/sas_host0
 Read GPIO register response:
   GPIO_CFG[0]:
 version: 0
 GPIO enable: 1
 cfg register count: 2
 gp register count: 1
 supported drive count: 16
 
 Regards,
 Jack
 
 -Original Message-
 From: Jack Wang [mailto:xjtu...@gmail.com]
 Sent: Tuesday, October 29, 2013 3:49 PM
 To: Viswas G
 Cc: linux-scsi@vger.kernel.org; Sangeetha Gnanasekaran; Nikith 
 Ganigarakoppal; Anand Kumar Santhanam
 Subject: Re: [PATCH 11/11] pm80xx : gpio feature support for 
 motherboard controllers

 Hi Viswas,

 As ioctl interface is not welcome for new feature, that's why we removed 
 ioctl interface when pm8001 accepted into mainline.

 I suggest you use bsg interface for this, see sas_host_smp.c for details.

 Regards,
 Jack

 On 10/22/2013 02:20 PM, Viswas G wrote:

 Signed-off-by: Viswas G viswa...@pmcs.com
 ---
  drivers/scsi/pm8001/pm8001_ctl.c  |  248
 -
  drivers/scsi/pm8001/pm8001_ctl.h  |   55 
  drivers/scsi/pm8001/pm8001_init.c |   37 ++
  drivers/scsi/pm8001/pm8001_sas.h  |   30 +
  drivers/scsi/pm8001/pm80xx_hwi.c  |  106 
  drivers/scsi/pm8001/pm80xx_hwi.h  |   49 +++
  6 files changed, 524 insertions(+), 1 deletions(-)

 diff --git a/drivers/scsi/pm8001/pm8001_ctl.c
 b/drivers/scsi/pm8001/pm8001_ctl.c
 index 247cb1c..3c9ca21 100644
 --- a/drivers/scsi/pm8001/pm8001_ctl.c
 +++ b/drivers/scsi/pm8001/pm8001_ctl.c
 @@ -40,7 +40,8 @@
  #include linux/firmware.h
  #include linux/slab.h
  #include pm8001_sas.h
 -#include pm8001_ctl.h
 +
 +int pm8001_major = -1;

  /* scsi host attributes */

 @@ -759,3 +760,248 @@ struct device_attribute *pm8001_host_attrs[] = {
 NULL,
  };

 +/**
 + * pm8001_open - open the configuration file
 + * @inode: inode being opened
 + * @file: file handle attached
 + *
 + * Called when the configuration device is opened. Does the needed
 + * set up on the handle and then returns
 + *
 + */
 +static int pm8001_open(struct inode *inode, struct file *file) {
 +   struct pm8001_hba_info *pm8001_ha;
 +   unsigned minor_number = iminor(inode);
 +   int err = -ENODEV;
 +
 +   list_for_each_entry(pm8001_ha, hba_list, list) {
 +   if (pm8001_ha-id == minor_number) {
 +   file-private_data = pm8001_ha;
 +   err = 0;
 +   break

RE: [PATCH 11/11] pm80xx : gpio feature support for motherboard controllers

2013-11-10 Thread Viswas G
Hi Jack,

The GPIO feature we implemented here is for controlling and configuring the 
GPIO pins present in the HBA and it is not related to the GPIO registers 
present in the SGPIO. Following is one of the GPIO operations we do from 
application.

When application wants to know the insertion/removal of a SAS cable in any of 
the port, it configures the GPIO for corresponding port to generate event for 
SAS cable insertion or removal using the IOCTL to the HBA driver and waits by 
calling poll function. When driver receives the GPIO event for the SAS cable 
insertion or removal then it intimates the application.

We are using IOCTL instead of sysfs interface since we have to pass structures 
between user space and kernel space. Again, in the kernel space, we have to 
parse user buffer from application and convert it to the corresponding data 
structure. We wanted to avoid the parsing complexity by using ioctl interface.

Regards,
Viswas G


-Original Message-
From: Jack Wang [mailto:xjtu...@gmail.com] 
Sent: Monday, November 04, 2013 4:00 PM
To: Viswas G
Cc: linux-scsi@vger.kernel.org; Sangeetha Gnanasekaran; Nikith Ganigarakoppal; 
Anand Kumar Santhanam; Suresh Thiagarajan
Subject: Re: [PATCH 11/11] pm80xx : gpio feature support for motherboard 
controllers

On 11/04/2013 11:13 AM, Viswas G wrote:
 Hi Jack,
 
 We wanted to control the GPIO in the HBA only. Bsg interface gets created 
 only for enclosure or expander. 
 
 For our HBA, bsg interface will not be created since it does not have an 
 enclosure target inside. That's why we wanted to use IOCTL. Please advise.
 
 Best Regards,
 Viswas G
 
Hi Viswas,

No, bsg interface also support HBA.
Here is two example output from LSI mpt2sas:

smp_rep_manufacturer /dev/bsg/sas_host0
Report manufacturer response:
  SAS-1.1 format: 0
  vendor identification: LSI
  product identification: Virtual SMP Port
  product revision level:
smp_read_gpio /dev/bsg/sas_host0
Read GPIO register response:
  GPIO_CFG[0]:
version: 0
GPIO enable: 1
cfg register count: 2
gp register count: 1
supported drive count: 16

Regards,
Jack

 -Original Message-
 From: Jack Wang [mailto:xjtu...@gmail.com] 
 Sent: Tuesday, October 29, 2013 3:49 PM
 To: Viswas G
 Cc: linux-scsi@vger.kernel.org; Sangeetha Gnanasekaran; Nikith 
 Ganigarakoppal; Anand Kumar Santhanam
 Subject: Re: [PATCH 11/11] pm80xx : gpio feature support for motherboard 
 controllers
 
 Hi Viswas,
 
 As ioctl interface is not welcome for new feature, that's why we removed 
 ioctl interface when pm8001 accepted into mainline.
 
 I suggest you use bsg interface for this, see sas_host_smp.c for details.
 
 Regards,
 Jack
 
 On 10/22/2013 02:20 PM, Viswas G wrote:

 Signed-off-by: Viswas G viswa...@pmcs.com
 ---
  drivers/scsi/pm8001/pm8001_ctl.c  |  248
 -
  drivers/scsi/pm8001/pm8001_ctl.h  |   55 
  drivers/scsi/pm8001/pm8001_init.c |   37 ++
  drivers/scsi/pm8001/pm8001_sas.h  |   30 +
  drivers/scsi/pm8001/pm80xx_hwi.c  |  106 
  drivers/scsi/pm8001/pm80xx_hwi.h  |   49 +++
  6 files changed, 524 insertions(+), 1 deletions(-)

 diff --git a/drivers/scsi/pm8001/pm8001_ctl.c
 b/drivers/scsi/pm8001/pm8001_ctl.c
 index 247cb1c..3c9ca21 100644
 --- a/drivers/scsi/pm8001/pm8001_ctl.c
 +++ b/drivers/scsi/pm8001/pm8001_ctl.c
 @@ -40,7 +40,8 @@
  #include linux/firmware.h
  #include linux/slab.h
  #include pm8001_sas.h
 -#include pm8001_ctl.h
 +
 +int pm8001_major = -1;

  /* scsi host attributes */

 @@ -759,3 +760,248 @@ struct device_attribute *pm8001_host_attrs[] = {
 NULL,
  };

 +/**
 + * pm8001_open - open the configuration file
 + * @inode: inode being opened
 + * @file: file handle attached
 + *
 + * Called when the configuration device is opened. Does the needed
 + * set up on the handle and then returns
 + *
 + */
 +static int pm8001_open(struct inode *inode, struct file *file) {
 +   struct pm8001_hba_info *pm8001_ha;
 +   unsigned minor_number = iminor(inode);
 +   int err = -ENODEV;
 +
 +   list_for_each_entry(pm8001_ha, hba_list, list) {
 +   if (pm8001_ha-id == minor_number) {
 +   file-private_data = pm8001_ha;
 +   err = 0;
 +   break;
 +   }
 +   }
 +
 +   return err;
 +}
 +
 +/**
 + * pm8001_close - close the configuration file
 + * @inode: inode being opened
 + * @file: file handle attached
 + *
 + * Called when the configuration device is closed. Does the needed
 + * set up on the handle and then returns
 + *
 + */
 +static int pm8001_close(struct inode *inode, struct file *file) {
 +   return 0;
 +}
 +
 +static long pm8001_info_ioctl(struct pm8001_hba_info *pm8001_ha,
 + unsigned long arg) {
 +   u32 ret = 0;
 +   struct ioctl_info_buffer info_buf;
 +   union main_cfg_table main_tbl =  pm8001_ha-main_cfg_tbl;
 +
 +   strcpy

RE: [PATCH 11/11] pm80xx : gpio feature support for motherboard controllers

2013-11-04 Thread Viswas G
Hi Jack,

We wanted to control the GPIO in the HBA only. Bsg interface gets created only 
for enclosure or expander. 

For our HBA, bsg interface will not be created since it does not have an 
enclosure target inside. That's why we wanted to use IOCTL. Please advise.

Best Regards,
Viswas G

-Original Message-
From: Jack Wang [mailto:xjtu...@gmail.com] 
Sent: Tuesday, October 29, 2013 3:49 PM
To: Viswas G
Cc: linux-scsi@vger.kernel.org; Sangeetha Gnanasekaran; Nikith Ganigarakoppal; 
Anand Kumar Santhanam
Subject: Re: [PATCH 11/11] pm80xx : gpio feature support for motherboard 
controllers

Hi Viswas,

As ioctl interface is not welcome for new feature, that's why we removed ioctl 
interface when pm8001 accepted into mainline.

I suggest you use bsg interface for this, see sas_host_smp.c for details.

Regards,
Jack

On 10/22/2013 02:20 PM, Viswas G wrote:
 
 Signed-off-by: Viswas G viswa...@pmcs.com
 ---
  drivers/scsi/pm8001/pm8001_ctl.c  |  248
 -
  drivers/scsi/pm8001/pm8001_ctl.h  |   55 
  drivers/scsi/pm8001/pm8001_init.c |   37 ++
  drivers/scsi/pm8001/pm8001_sas.h  |   30 +
  drivers/scsi/pm8001/pm80xx_hwi.c  |  106 
  drivers/scsi/pm8001/pm80xx_hwi.h  |   49 +++
  6 files changed, 524 insertions(+), 1 deletions(-)
 
 diff --git a/drivers/scsi/pm8001/pm8001_ctl.c
 b/drivers/scsi/pm8001/pm8001_ctl.c
 index 247cb1c..3c9ca21 100644
 --- a/drivers/scsi/pm8001/pm8001_ctl.c
 +++ b/drivers/scsi/pm8001/pm8001_ctl.c
 @@ -40,7 +40,8 @@
  #include linux/firmware.h
  #include linux/slab.h
  #include pm8001_sas.h
 -#include pm8001_ctl.h
 +
 +int pm8001_major = -1;
 
  /* scsi host attributes */
 
 @@ -759,3 +760,248 @@ struct device_attribute *pm8001_host_attrs[] = {
 NULL,
  };
 
 +/**
 + * pm8001_open - open the configuration file
 + * @inode: inode being opened
 + * @file: file handle attached
 + *
 + * Called when the configuration device is opened. Does the needed
 + * set up on the handle and then returns
 + *
 + */
 +static int pm8001_open(struct inode *inode, struct file *file) {
 +   struct pm8001_hba_info *pm8001_ha;
 +   unsigned minor_number = iminor(inode);
 +   int err = -ENODEV;
 +
 +   list_for_each_entry(pm8001_ha, hba_list, list) {
 +   if (pm8001_ha-id == minor_number) {
 +   file-private_data = pm8001_ha;
 +   err = 0;
 +   break;
 +   }
 +   }
 +
 +   return err;
 +}
 +
 +/**
 + * pm8001_close - close the configuration file
 + * @inode: inode being opened
 + * @file: file handle attached
 + *
 + * Called when the configuration device is closed. Does the needed
 + * set up on the handle and then returns
 + *
 + */
 +static int pm8001_close(struct inode *inode, struct file *file) {
 +   return 0;
 +}
 +
 +static long pm8001_info_ioctl(struct pm8001_hba_info *pm8001_ha,
 + unsigned long arg) {
 +   u32 ret = 0;
 +   struct ioctl_info_buffer info_buf;
 +   union main_cfg_table main_tbl =  pm8001_ha-main_cfg_tbl;
 +
 +   strcpy(info_buf.information.sz_name, DRV_NAME);
 +
 +   info_buf.information.usmajor_revision = DRV_MAJOR;
 +   info_buf.information.usminor_revision = DRV_MINOR;
 +   info_buf.information.usbuild_revision = DRV_BUILD;
 +   if (pm8001_ha-chip_id == chip_8001) {
 +   info_buf.information.maxoutstandingIO =
 +   main_tbl.pm8001_tbl.max_out_io;
 +   info_buf.information.maxdevices =
 +   (main_tbl.pm8001_tbl.max_sgl  16)  0x;
 +   } else {
 +   info_buf.information.maxoutstandingIO =
 +   main_tbl.pm80xx_tbl.max_out_io;
 +   info_buf.information.maxdevices =
 +   (main_tbl.pm80xx_tbl.max_sgl  16)  0x;
 +   }
 +   info_buf.header.return_code = ADPT_IOCTL_CALL_SUCCESS;
 +
 +   if (copy_to_user((void *)arg, (void *)info_buf,
 +sizeof(struct ioctl_info_buffer))) {
 +   ret = ADPT_IOCTL_CALL_FAILED;
 +   }
 +
 +   return ret;
 +}
 +
 +static long pm8001_gpio_ioctl(struct pm8001_hba_info *pm8001_ha,
 + unsigned long arg) {
 +   struct gpio_buffer buffer;
 +   struct pm8001_gpio *payload;
 +   struct gpio_ioctl_resp *gpio_resp;
 +   DECLARE_COMPLETION_ONSTACK(completion);
 +   unsigned long timeout;
 +   u32 ret = 0, operation;
 +
 +   mutex_lock(pm8001_ha-ioctl_mutex);
 +
 +   if (copy_from_user(buffer, (struct gpio_buffer *)arg,
 +   sizeof(struct gpio_buffer))) {
 +   ret = ADPT_IOCTL_CALL_FAILED;
 +   goto exit;
 +   }
 +
 +   pm8001_ha-ioctl_completion = completion;
 +   payload = buffer.gpio_payload;
 +   operation = payload-operation;
 +   ret = PM8001_CHIP_DISP-gpio_req(pm8001_ha, payload);
 +   if (ret != 0

[PATCH 11/11] pm80xx : gpio feature support for motherboard controllers

2013-10-22 Thread Viswas G

Signed-off-by: Viswas G viswa...@pmcs.com
---
 drivers/scsi/pm8001/pm8001_ctl.c  |  248 -
 drivers/scsi/pm8001/pm8001_ctl.h  |   55 
 drivers/scsi/pm8001/pm8001_init.c |   37 ++
 drivers/scsi/pm8001/pm8001_sas.h  |   30 +
 drivers/scsi/pm8001/pm80xx_hwi.c  |  106 
 drivers/scsi/pm8001/pm80xx_hwi.h  |   49 +++
 6 files changed, 524 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 247cb1c..3c9ca21 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -40,7 +40,8 @@
 #include linux/firmware.h
 #include linux/slab.h
 #include pm8001_sas.h
-#include pm8001_ctl.h
+
+int pm8001_major = -1;
 
 /* scsi host attributes */
 
@@ -759,3 +760,248 @@ struct device_attribute *pm8001_host_attrs[] = {
NULL,
 };
 
+/**
+ * pm8001_open - open the configuration file
+ * @inode: inode being opened
+ * @file: file handle attached
+ *
+ * Called when the configuration device is opened. Does the needed
+ * set up on the handle and then returns
+ *
+ */
+static int pm8001_open(struct inode *inode, struct file *file)
+{
+   struct pm8001_hba_info *pm8001_ha;
+   unsigned minor_number = iminor(inode);
+   int err = -ENODEV;
+
+   list_for_each_entry(pm8001_ha, hba_list, list) {
+   if (pm8001_ha-id == minor_number) {
+   file-private_data = pm8001_ha;
+   err = 0;
+   break;
+   }
+   }
+
+   return err;
+}
+
+/**
+ * pm8001_close - close the configuration file
+ * @inode: inode being opened
+ * @file: file handle attached
+ *
+ * Called when the configuration device is closed. Does the needed
+ * set up on the handle and then returns
+ *
+ */
+static int pm8001_close(struct inode *inode, struct file *file)
+{
+   return 0;
+}
+
+static long pm8001_info_ioctl(struct pm8001_hba_info *pm8001_ha,
+ unsigned long arg)
+{
+   u32 ret = 0;
+   struct ioctl_info_buffer info_buf;
+   union main_cfg_table main_tbl =  pm8001_ha-main_cfg_tbl;
+
+   strcpy(info_buf.information.sz_name, DRV_NAME);
+
+   info_buf.information.usmajor_revision = DRV_MAJOR;
+   info_buf.information.usminor_revision = DRV_MINOR;
+   info_buf.information.usbuild_revision = DRV_BUILD;
+   if (pm8001_ha-chip_id == chip_8001) {
+   info_buf.information.maxoutstandingIO =
+   main_tbl.pm8001_tbl.max_out_io;
+   info_buf.information.maxdevices =
+   (main_tbl.pm8001_tbl.max_sgl  16)  0x;
+   } else {
+   info_buf.information.maxoutstandingIO =
+   main_tbl.pm80xx_tbl.max_out_io;
+   info_buf.information.maxdevices =
+   (main_tbl.pm80xx_tbl.max_sgl  16)  0x;
+   }
+   info_buf.header.return_code = ADPT_IOCTL_CALL_SUCCESS;
+
+   if (copy_to_user((void *)arg, (void *)info_buf,
+sizeof(struct ioctl_info_buffer))) {
+   ret = ADPT_IOCTL_CALL_FAILED;
+   }
+
+   return ret;
+}
+
+static long pm8001_gpio_ioctl(struct pm8001_hba_info *pm8001_ha,
+ unsigned long arg)
+{
+   struct gpio_buffer buffer;
+   struct pm8001_gpio *payload;
+   struct gpio_ioctl_resp *gpio_resp;
+   DECLARE_COMPLETION_ONSTACK(completion);
+   unsigned long timeout;
+   u32 ret = 0, operation;
+
+   mutex_lock(pm8001_ha-ioctl_mutex);
+
+   if (copy_from_user(buffer, (struct gpio_buffer *)arg,
+   sizeof(struct gpio_buffer))) {
+   ret = ADPT_IOCTL_CALL_FAILED;
+   goto exit;
+   }
+
+   pm8001_ha-ioctl_completion = completion;
+   payload = buffer.gpio_payload;
+   operation = payload-operation;
+   ret = PM8001_CHIP_DISP-gpio_req(pm8001_ha, payload);
+   if (ret != 0) {
+   ret = ADPT_IOCTL_CALL_FAILED;
+   goto exit;
+   }
+
+   timeout = (unsigned long)buffer.header.timeout * 1000;
+
+   mod_timer(pm8001_ha-ioctl_timer, jiffies + msecs_to_jiffies(timeout));
+
+   wait_for_completion(completion);
+
+   if (pm8001_ha-ioctl_timer_expired) {
+   ret = ADPT_IOCTL_CALL_TIMEOUT;
+   goto exit;
+   }
+   gpio_resp = pm8001_ha-gpio_resp;
+
+   buffer.header.return_code = ADPT_IOCTL_CALL_SUCCESS;
+
+   if (operation == GPIO_READ) {
+   payload-rd_wr_val  = gpio_resp-gpio_rd_val;
+   payload-input_enable   = gpio_resp-gpio_in_enabled;
+   payload-pinsetup1  = gpio_resp-gpio_pinsetup1;
+   payload-pinsetup2  = gpio_resp-gpio_pinsetup2;
+   payload-event_level= gpio_resp-gpio_evt_change;
+   payload-event_rising_edge  = gpio_resp-gpio_evt_rise