diff options
author | jack_wang <jack_wang@usish.com> | 2009-11-05 09:32:31 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:01:30 -0500 |
commit | d0b68041bdd0e5ea6dae1210541bf124443d72ec (patch) | |
tree | 2bad62cf3df725f9d0b818d68569d24abee4f7ab /drivers/scsi/pm8001/pm8001_hwi.c | |
parent | d139b9bd0e52dda14fd13412e7096e68b56d0076 (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.c | 76 |
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 | |||
4370 | static int | ||
4371 | pm8001_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 | ||