aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/pm8001/pm8001_hwi.c
diff options
context:
space:
mode:
authorjack_wang <jack_wang@usish.com>2009-11-05 09:32:31 -0500
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 13:01:30 -0500
commitd0b68041bdd0e5ea6dae1210541bf124443d72ec (patch)
tree2bad62cf3df725f9d0b818d68569d24abee4f7ab /drivers/scsi/pm8001/pm8001_hwi.c
parentd139b9bd0e52dda14fd13412e7096e68b56d0076 (diff)
[SCSI] pm8001: add reinitialize SPC parameters before phy start
Signed-off-by: Jack Wang <jack_wang@usish.com> Signed-off-by: Lindar Liu <lindar_liu@usish.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_hwi.c')
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c76
1 files changed, 64 insertions, 12 deletions
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index aa5756fe0574..d18c2635995f 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -57,9 +57,9 @@ static void __devinit read_main_config_table(struct pm8001_hba_info *pm8001_ha)
57 pm8001_ha->main_cfg_tbl.ctrl_cap_flag = pm8001_mr32(address, 0x14); 57 pm8001_ha->main_cfg_tbl.ctrl_cap_flag = pm8001_mr32(address, 0x14);
58 pm8001_ha->main_cfg_tbl.gst_offset = pm8001_mr32(address, 0x18); 58 pm8001_ha->main_cfg_tbl.gst_offset = pm8001_mr32(address, 0x18);
59 pm8001_ha->main_cfg_tbl.inbound_queue_offset = 59 pm8001_ha->main_cfg_tbl.inbound_queue_offset =
60 pm8001_mr32(address, 0x1C); 60 pm8001_mr32(address, MAIN_IBQ_OFFSET);
61 pm8001_ha->main_cfg_tbl.outbound_queue_offset = 61 pm8001_ha->main_cfg_tbl.outbound_queue_offset =
62 pm8001_mr32(address, 0x20); 62 pm8001_mr32(address, MAIN_OBQ_OFFSET);
63 pm8001_ha->main_cfg_tbl.hda_mode_flag = 63 pm8001_ha->main_cfg_tbl.hda_mode_flag =
64 pm8001_mr32(address, MAIN_HDA_FLAGS_OFFSET); 64 pm8001_mr32(address, MAIN_HDA_FLAGS_OFFSET);
65 65
@@ -124,7 +124,7 @@ read_inbnd_queue_table(struct pm8001_hba_info *pm8001_ha)
124 int i; 124 int i;
125 void __iomem *address = pm8001_ha->inbnd_q_tbl_addr; 125 void __iomem *address = pm8001_ha->inbnd_q_tbl_addr;
126 for (i = 0; i < inbQ_num; i++) { 126 for (i = 0; i < inbQ_num; i++) {
127 u32 offset = i * 0x24; 127 u32 offset = i * 0x20;
128 pm8001_ha->inbnd_q_tbl[i].pi_pci_bar = 128 pm8001_ha->inbnd_q_tbl[i].pi_pci_bar =
129 get_pci_bar_index(pm8001_mr32(address, (offset + 0x14))); 129 get_pci_bar_index(pm8001_mr32(address, (offset + 0x14)));
130 pm8001_ha->inbnd_q_tbl[i].pi_offset = 130 pm8001_ha->inbnd_q_tbl[i].pi_offset =
@@ -231,7 +231,7 @@ init_default_table_values(struct pm8001_hba_info *pm8001_ha)
231 pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr = 231 pm8001_ha->outbnd_q_tbl[i].pi_lower_base_addr =
232 pm8001_ha->memoryMap.region[PI].phys_addr_lo; 232 pm8001_ha->memoryMap.region[PI].phys_addr_lo;
233 pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay = 233 pm8001_ha->outbnd_q_tbl[i].interrup_vec_cnt_delay =
234 0 | (0 << 16) | (0 << 24); 234 0 | (10 << 16) | (0 << 24);
235 pm8001_ha->outbnd_q_tbl[i].pi_virt = 235 pm8001_ha->outbnd_q_tbl[i].pi_virt =
236 pm8001_ha->memoryMap.region[PI].virt_ptr; 236 pm8001_ha->memoryMap.region[PI].virt_ptr;
237 offsetob = i * 0x24; 237 offsetob = i * 0x24;
@@ -375,13 +375,16 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
375{ 375{
376 u32 offset; 376 u32 offset;
377 u32 value; 377 u32 value;
378 u32 i; 378 u32 i, j;
379 u32 bit_cnt;
379 380
380#define SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR 0x00030000 381#define SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR 0x00030000
381#define SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR 0x00040000 382#define SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR 0x00040000
382#define SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET 0x1074 383#define SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET 0x1074
383#define SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET 0x1074 384#define SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET 0x1074
384#define PHY_SSC_BIT_SHIFT 13 385#define PHY_G3_WITHOUT_SSC_BIT_SHIFT 12
386#define PHY_G3_WITH_SSC_BIT_SHIFT 13
387#define SNW3_PHY_CAPABILITIES_PARITY 31
385 388
386 /* 389 /*
387 * Using shifted destination address 0x3_0000:0x1074 + 0x4000*N (N=0:3) 390 * 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 for (i = 0; i < 4; i++) { 396 for (i = 0; i < 4; i++) {
394 offset = SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET + 0x4000 * i; 397 offset = SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET + 0x4000 * i;
395 value = pm8001_cr32(pm8001_ha, 2, offset); 398 value = pm8001_cr32(pm8001_ha, 2, offset);
396 if (SSCbit) 399 if (SSCbit) {
397 value = value | (0x00000001 << PHY_SSC_BIT_SHIFT); 400 value |= 0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT;
401 value &= ~(0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT);
402 } else {
403 value |= 0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT;
404 value &= ~(0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT);
405 }
406 bit_cnt = 0;
407 for (j = 0; j < 31; j++)
408 if ((value >> j) & 0x00000001)
409 bit_cnt++;
410 if (bit_cnt % 2)
411 value &= ~(0x00000001 << SNW3_PHY_CAPABILITIES_PARITY);
398 else 412 else
399 value = value & (~(0x00000001<<PHY_SSC_BIT_SHIFT)); 413 value |= 0x00000001 << SNW3_PHY_CAPABILITIES_PARITY;
414
400 pm8001_cw32(pm8001_ha, 2, offset, value); 415 pm8001_cw32(pm8001_ha, 2, offset, value);
401 } 416 }
402 417
@@ -408,10 +423,22 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit)
408 for (i = 4; i < 8; i++) { 423 for (i = 4; i < 8; i++) {
409 offset = SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET + 0x4000 * (i-4); 424 offset = SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET + 0x4000 * (i-4);
410 value = pm8001_cr32(pm8001_ha, 2, offset); 425 value = pm8001_cr32(pm8001_ha, 2, offset);
411 if (SSCbit) 426 if (SSCbit) {
412 value = value | (0x00000001 << PHY_SSC_BIT_SHIFT); 427 value |= 0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT;
428 value &= ~(0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT);
429 } else {
430 value |= 0x00000001 << PHY_G3_WITHOUT_SSC_BIT_SHIFT;
431 value &= ~(0x00000001 << PHY_G3_WITH_SSC_BIT_SHIFT);
432 }
433 bit_cnt = 0;
434 for (j = 0; j < 31; j++)
435 if ((value >> j) & 0x00000001)
436 bit_cnt++;
437 if (bit_cnt % 2)
438 value &= ~(0x00000001 << SNW3_PHY_CAPABILITIES_PARITY);
413 else 439 else
414 value = value & (~(0x00000001<<PHY_SSC_BIT_SHIFT)); 440 value |= 0x00000001 << SNW3_PHY_CAPABILITIES_PARITY;
441
415 pm8001_cw32(pm8001_ha, 2, offset, value); 442 pm8001_cw32(pm8001_ha, 2, offset, value);
416 } 443 }
417 444
@@ -4338,6 +4365,30 @@ pm8001_chip_set_dev_state_req(struct pm8001_hba_info *pm8001_ha,
4338 payload.nds = cpu_to_le32(state); 4365 payload.nds = cpu_to_le32(state);
4339 mpi_build_cmd(pm8001_ha, circularQ, opc, &payload); 4366 mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
4340 return 0; 4367 return 0;
4368}
4369
4370static int
4371pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha)
4372{
4373 struct sas_re_initialization_req payload;
4374 struct inbound_queue_table *circularQ;
4375 struct pm8001_ccb_info *ccb;
4376 int rc;
4377 u32 tag;
4378 u32 opc = OPC_INB_SAS_RE_INITIALIZE;
4379 memset(&payload, 0, sizeof(payload));
4380 rc = pm8001_tag_alloc(pm8001_ha, &tag);
4381 if (rc)
4382 return -1;
4383 ccb = &pm8001_ha->ccb_info[tag];
4384 ccb->ccb_tag = tag;
4385 circularQ = &pm8001_ha->inbnd_q_tbl[0];
4386 payload.tag = cpu_to_le32(tag);
4387 payload.SSAHOLT = cpu_to_le32(0xd << 25);
4388 payload.sata_hol_tmo = cpu_to_le32(80);
4389 payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff);
4390 rc = mpi_build_cmd(pm8001_ha, circularQ, opc, &payload);
4391 return rc;
4341 4392
4342} 4393}
4343 4394
@@ -4367,5 +4418,6 @@ const struct pm8001_dispatch pm8001_8001_dispatch = {
4367 .set_nvmd_req = pm8001_chip_set_nvmd_req, 4418 .set_nvmd_req = pm8001_chip_set_nvmd_req,
4368 .fw_flash_update_req = pm8001_chip_fw_flash_update_req, 4419 .fw_flash_update_req = pm8001_chip_fw_flash_update_req,
4369 .set_dev_state_req = pm8001_chip_set_dev_state_req, 4420 .set_dev_state_req = pm8001_chip_set_dev_state_req,
4421 .sas_re_init_req = pm8001_chip_sas_re_initialization,
4370}; 4422};
4371 4423