Commit d0b68041 authored by jack_wang's avatar jack_wang Committed by James Bottomley

[SCSI] pm8001: add reinitialize SPC parameters before phy start

Signed-off-by: default avatarJack Wang <jack_wang@usish.com>
Signed-off-by: default avatarLindar Liu <lindar_liu@usish.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent d139b9bd
...@@ -57,9 +57,9 @@ static void __devinit read_main_config_table(struct pm8001_hba_info *pm8001_ha) ...@@ -57,9 +57,9 @@ static void __devinit read_main_config_table(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->main_cfg_tbl.ctrl_cap_flag = pm8001_mr32(address, 0x14); pm8001_ha->main_cfg_tbl.ctrl_cap_flag = pm8001_mr32(address, 0x14);
pm8001_ha->main_cfg_tbl.gst_offset = pm8001_mr32(address, 0x18); pm8001_ha->main_cfg_tbl.gst_offset = pm8001_mr32(address, 0x18);
pm8001_ha->main_cfg_tbl.inbound_queue_offset = pm8001_ha->main_cfg_tbl.inbound_queue_offset =
pm8001_mr32(address, 0x1C); pm8001_mr32(address, MAIN_IBQ_OFFSET);
pm8001_ha->main_cfg_tbl.outbound_queue_offset = pm8001_ha->main_cfg_tbl.outbound_queue_offset =
pm8001_mr32(address, 0x20); pm8001_mr32(address, MAIN_OBQ_OFFSET);
pm8001_ha->main_cfg_tbl.hda_mode_flag = pm8001_ha->main_cfg_tbl.hda_mode_flag =
pm8001_mr32(address, MAIN_HDA_FLAGS_OFFSET); pm8001_mr32(address, MAIN_HDA_FLAGS_OFFSET);
...@@ -124,7 +124,7 @@ read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha) ...@@ -124,7 +124,7 @@ read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
int i; int i;
void __iomem *address = pm8001_ha->inbnd_q_tbl_addr; void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
for (i = 0; i < inbQ_num; i++) { for (i = 0; i < inbQ_num; i++) {
u32 offset = i * 0x24; u32 offset = i * 0x20;
pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
get_pci_bar_index(pm8001_mr32(address, (offset + 0x14))); get_pci_bar_index(pm8001_mr32(address, (offset + 0x14)));
pm8001_ha->inbnd_q_tbl[i].pi_offset = pm8001_ha->inbnd_q_tbl[i].pi_offset =
...@@ -231,7 +231,7 @@ init_default_table_values(struct pm8001_hba_info *pm8001_ha) ...@@ -231,7 +231,7 @@ init_default_table_values(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr = pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr =
pm8001_ha->memoryMap.region[PI].phys_addr_lo; pm8001_ha->memoryMap.region[PI].phys_addr_lo;
pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay =
0 | (0 << 16) | (0 << 24); 0 | (10 << 16) | (0 << 24);
pm8001_ha->outbnd_q_tbl[i].pi_virt = pm8001_ha->outbnd_q_tbl[i].pi_virt =
pm8001_ha->memoryMap.region[PI].virt_ptr; pm8001_ha->memoryMap.region[PI].virt_ptr;
offsetob = i * 0x24; offsetob = i * 0x24;
...@@ -375,13 +375,16 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit) ...@@ -375,13 +375,16 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
{ {
u32 offset; u32 offset;
u32 value; 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_0_3_SHIFT_ADDR 0x00030000
#define SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR 0x00040000 #define SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR 0x00040000
#define SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET 0x1074 #define SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET 0x1074
#define SAS2_SETTINGS_LOCAL_PHY_4_7_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) * 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) ...@@ -393,10 +396,22 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
offset = SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET + 0x4000 * i; offset = SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET + 0x4000 * i;
value = pm8001_cr32(pm8001_ha, 2, offset); value = pm8001_cr32(pm8001_ha, 2, offset);
if (SSCbit) if (SSCbit) {
value = value | (0x00000001 << PHY_SSC_BIT_SHIFT); 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 else
value = value & (~(0x00000001<<PHY_SSC_BIT_SHIFT)); value |= 0x00000001 << SNW3_PHY_CAPABILITIES_PARITY;
pm8001_cw32(pm8001_ha, 2, offset, value); 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) ...@@ -408,10 +423,22 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
for (i = 4; i < 8; i++) { for (i = 4; i < 8; i++) {
offset = SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET + 0x4000 * (i-4); offset = SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET + 0x4000 * (i-4);
value = pm8001_cr32(pm8001_ha, 2, offset); value = pm8001_cr32(pm8001_ha, 2, offset);
if (SSCbit) if (SSCbit) {
value = value | (0x00000001 << PHY_SSC_BIT_SHIFT); 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 else
value = value & (~(0x00000001<<PHY_SSC_BIT_SHIFT)); value |= 0x00000001 << SNW3_PHY_CAPABILITIES_PARITY;
pm8001_cw32(pm8001_ha, 2, offset, value); pm8001_cw32(pm8001_ha, 2, offset, value);
} }
...@@ -4338,6 +4365,30 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha, ...@@ -4338,6 +4365,30 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
payload.nds = cpu_to_le32(state); payload.nds = cpu_to_le32(state);
mpi_build_cmd(pm8001_ha, circularQ, opc, &payload); mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
return 0; 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 = { ...@@ -4367,5 +4418,6 @@ const struct pm8001_dispatch pm8001_8001_dispatch = {
.set_nvmd_req = pm8001_chip_set_nvmd_req, .set_nvmd_req = pm8001_chip_set_nvmd_req,
.fw_flash_update_req = pm8001_chip_fw_flash_update_req, .fw_flash_update_req = pm8001_chip_fw_flash_update_req,
.set_dev_state_req = pm8001_chip_set_dev_state_req, .set_dev_state_req = pm8001_chip_set_dev_state_req,
.sas_re_init_req = pm8001_chip_sas_re_initialization,
}; };
...@@ -490,6 +490,25 @@ struct set_dev_state_req { ...@@ -490,6 +490,25 @@ struct set_dev_state_req {
u32 reserved[12]; u32 reserved[12];
} __attribute__((packed, aligned(4))); } __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 * brief the data structure of SATA Start Command
......
...@@ -240,6 +240,7 @@ void pm8001_scan_start(struct Scsi_Host *shost) ...@@ -240,6 +240,7 @@ void pm8001_scan_start(struct Scsi_Host *shost)
struct pm8001_hba_info *pm8001_ha; struct pm8001_hba_info *pm8001_ha;
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
pm8001_ha = sha->lldd_ha; pm8001_ha = sha->lldd_ha;
PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha);
for (i = 0; i < pm8001_ha->chip->n_phy; ++i) for (i = 0; i < pm8001_ha->chip->n_phy; ++i)
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i); PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i);
} }
......
...@@ -153,6 +153,7 @@ struct pm8001_dispatch { ...@@ -153,6 +153,7 @@ struct pm8001_dispatch {
u32 state); u32 state);
int (*sas_diag_execute_req)(struct pm8001_hba_info *pm8001_ha, int (*sas_diag_execute_req)(struct pm8001_hba_info *pm8001_ha,
u32 state); u32 state);
int (*sas_re_init_req)(struct pm8001_hba_info *pm8001_ha);
}; };
struct pm8001_chip_info { struct pm8001_chip_info {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment