[PATCH Resend 1/3] pm8001:add reinitialize SPC parameters before phy start

jack_wang
2009-10-30T13:50:28Z

[-- Attachment #1: Type: text/plain, Size: 0 bytes --]

[-- Attachment #2: 0001-add-reinitialize-SPC-parameters-before-phy-start.patch --]
[-- Type: application/octet-stream, Size: 6535 bytes --]

>From e827a9bc8d20f1aac0609c2b61a3d56082a5e127 Mon Sep 17 00:00:00 2001
From: Jack Wang <jack_wang@usish.com>
Date: Fri, 30 Oct 2009 16:42:21 +0800
Subject: [PATCH 1/3] add reinitialize SPC parameters before phy start

We should reinitialize SPC patameters to enhance some disks will cause open
retry timeout and sata head of line blocking timeout issues. We also need set
g3_with_ssc bit properly.

Signed-off-by: Jack Wang <jack_wang@usish.com>
Signed-off-by: Lindar Liu <lindar_liu@usish.com>
---
drivers/scsi/pm8001/pm8001_hwi.c | 68 +++++++++++++++++++++++++++++++++----
drivers/scsi/pm8001/pm8001_hwi.h | 19 ++++++++++
drivers/scsi/pm8001/pm8001_sas.c | 1 +
drivers/scsi/pm8001/pm8001_sas.h | 1 +
4 files changed, 81 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index aa5756f..c4a2ca4 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -375,13 +375,16 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
{
u32 offset;
u32 value;
- u32 i;
+ u32 i, j;
+ u32 bit_cnt;

#define SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR 0x00030000
#define SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR 0x00040000
#define SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET 0x1074
#define SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET 0x1074
-#define PHY_SSC_BIT_SHIFT 13
+#define PHY_G3_WITHOUT_SSC_BIT_SHIFT 12
+#define PHY_G3_WITH_SSC_BIT_SHIFT 13
+#define SNW3_PHY_CAPABILITIES_PARITY 31

/*
* Using shifted destination address 0x3_0000:0x1074 + 0x4000*N (N=0:3)
@@ -393,10 +396,22 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
for (i = 0; i < 4; i++) {
offset = SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET + 0x4000 * i;
value = pm8001_cr32(pm8001_ha, 2, offset);
- if (SSCbit)
- value = value | (0x00000001 << PHY_SSC_BIT_SHIFT);
+ if (SSCbit) {
+ value |= 0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT;
+ value &= ~(0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT);
+ } else {
+ value |= 0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT;
+ value &= ~(0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT);
+ }
+ bit_cnt = 0;
+ for (j = 0; j < 31; j++)
+ if ((value >> j) & 0x00000001)
+ bit_cnt++;
+ if (bit_cnt % 2)
+ value &= ~(0x00000001 << SNW3_PHY_CAPABILITIES_PARITY);
else
- value = value & (~(0x00000001<<PHY_SSC_BIT_SHIFT));
+ value |= 0x00000001 << SNW3_PHY_CAPABILITIES_PARITY;
+
pm8001_cw32(pm8001_ha, 2, offset, value);
}

@@ -408,10 +423,22 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
for (i = 4; i < 8; i++) {
offset = SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET + 0x4000 * (i-4);
value = pm8001_cr32(pm8001_ha, 2, offset);
- if (SSCbit)
- value = value | (0x00000001 << PHY_SSC_BIT_SHIFT);
+ if (SSCbit) {
+ value |= 0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT;
+ value &= ~(0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT);
+ } else {
+ value |= 0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT;
+ value &= ~(0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT);
+ }
+ bit_cnt = 0;
+ for (j = 0; j < 31; j++)
+ if ((value >> j) & 0x00000001)
+ bit_cnt++;
+ if (bit_cnt % 2)
+ value &= ~(0x00000001 << SNW3_PHY_CAPABILITIES_PARITY);
else
- value = value & (~(0x00000001<<PHY_SSC_BIT_SHIFT));
+ value |= 0x00000001 << SNW3_PHY_CAPABILITIES_PARITY;
+
pm8001_cw32(pm8001_ha, 2, offset, value);
}

@@ -4338,6 +4365,30 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
payload.nds = cpu_to_le32(state);
mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
return 0;
+}
+
+static int
+pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
+{
+ struct sas_re_initialization_req payload;
+ struct inbound_queue_table *circularQ;
+ struct pm8001_ccb_info *ccb;
+ int rc;
+ u32 tag;
+ u32 opc = OPC_INB_SAS_RE_INITIALIZE;
+ memset(&payload, 0, sizeof(payload));
+ rc = pm8001_tag_alloc(pm8001_ha, &tag);
+ if (rc)
+ return -1;
+ ccb = &pm8001_ha->ccb_info[tag];
+ ccb->ccb_tag = tag;
+ circularQ = &pm8001_ha->inbnd_q_tbl[0];
+ payload.tag = cpu_to_le32(tag);
+ payload.SSAHOLT = cpu_to_le32(0xd << 25);
+ payload.sata_hol_tmo = cpu_to_le32(80);
+ payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff);
+ rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
+ return rc;

}

@@ -4367,5 +4418,6 @@ const struct pm8001_dispatch pm8001_8001_dispatch = {
.set_nvmd_req = pm8001_chip_set_nvmd_req,
.fw_flash_update_req = pm8001_chip_fw_flash_update_req,
.set_dev_state_req = pm8001_chip_set_dev_state_req,
+ .sas_re_init_req = pm8001_chip_sas_re_initialization,
};

diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h
index 3690a2b..eebeca8 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.h
+++ b/drivers/scsi/pm8001/pm8001_hwi.h
@@ -490,6 +490,25 @@ struct set_dev_state_req {
u32 reserved[12];
} __attribute__((packed, aligned(4)));

+/*
+ * brief the data structure of sas_re_initialization
+ */
+struct sas_re_initialization_req {
+
+ __le32 tag;
+ __le32 SSAHOLT;/* bit29-set max port;
+ ** bit28-set open reject cmd retries.
+ ** bit27-set open reject data retries.
+ ** bit26-set open reject option, remap:1 or not:0.
+ ** bit25-set sata head of line time out.
+ */
+ __le32 reserved_maxPorts;
+ __le32 open_reject_cmdretries_data_retries;/* cmd retries: 31-bit16;
+ * data retries: bit15-bit0.
+ */
+ __le32 sata_hol_tmo;
+ u32 reserved1[10];
+} __attribute__((packed, aligned(4)));

/*
* brief the data structure of SATA Start Command
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index 7bf30fa..1e840fd 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -240,6 +240,7 @@ void pm8001_scan_start(struct Scsi_Host *shost)
struct pm8001_hba_info *pm8001_ha;
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
pm8001_ha = sha->lldd_ha;
+ PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha);
for (i = 0; i < pm8001_ha->chip->n_phy; ++i)
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i);
}
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 14c676b..ed6dbd1 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -153,6 +153,7 @@ struct pm8001_dispatch {
u32 state);
int (*sas_diag_execute_req)(struct pm8001_hba_info *pm8001_ha,
u32 state);
+ int (*sas_re_init_req)(struct pm8001_hba_info *pm8001_ha);
};

struct pm8001_chip_info {
--
1.6.4.msysgit.0