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 | |
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')
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 76 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.h | 19 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.c | 1 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.h | 1 |
4 files changed, 85 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 | ||
diff --git a/drivers/scsi/pm8001/pm8001_hwi.h b/drivers/scsi/pm8001/pm8001_hwi.h index 3690a2ba0eb2..96e4daa68b8f 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.h +++ b/drivers/scsi/pm8001/pm8001_hwi.h | |||
@@ -490,6 +490,25 @@ struct set_dev_state_req { | |||
490 | u32 reserved[12]; | 490 | u32 reserved[12]; |
491 | } __attribute__((packed, aligned(4))); | 491 | } __attribute__((packed, aligned(4))); |
492 | 492 | ||
493 | /* | ||
494 | * brief the data structure of sas_re_initialization | ||
495 | */ | ||
496 | struct sas_re_initialization_req { | ||
497 | |||
498 | __le32 tag; | ||
499 | __le32 SSAHOLT;/* bit29-set max port; | ||
500 | ** bit28-set open reject cmd retries. | ||
501 | ** bit27-set open reject data retries. | ||
502 | ** bit26-set open reject option, remap:1 or not:0. | ||
503 | ** bit25-set sata head of line time out. | ||
504 | */ | ||
505 | __le32 reserved_maxPorts; | ||
506 | __le32 open_reject_cmdretries_data_retries;/* cmd retries: 31-bit16; | ||
507 | * data retries: bit15-bit0. | ||
508 | */ | ||
509 | __le32 sata_hol_tmo; | ||
510 | u32 reserved1[10]; | ||
511 | } __attribute__((packed, aligned(4))); | ||
493 | 512 | ||
494 | /* | 513 | /* |
495 | * brief the data structure of SATA Start Command | 514 | * 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 7bf30fa6963a..1e840fd15160 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) | |||
240 | struct pm8001_hba_info *pm8001_ha; | 240 | struct pm8001_hba_info *pm8001_ha; |
241 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); | 241 | struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); |
242 | pm8001_ha = sha->lldd_ha; | 242 | pm8001_ha = sha->lldd_ha; |
243 | PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha); | ||
243 | for (i = 0; i < pm8001_ha->chip->n_phy; ++i) | 244 | for (i = 0; i < pm8001_ha->chip->n_phy; ++i) |
244 | PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i); | 245 | PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i); |
245 | } | 246 | } |
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 14c676bbb533..ed6dbd193aa1 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h | |||
@@ -153,6 +153,7 @@ struct pm8001_dispatch { | |||
153 | u32 state); | 153 | u32 state); |
154 | int (*sas_diag_execute_req)(struct pm8001_hba_info *pm8001_ha, | 154 | int (*sas_diag_execute_req)(struct pm8001_hba_info *pm8001_ha, |
155 | u32 state); | 155 | u32 state); |
156 | int (*sas_re_init_req)(struct pm8001_hba_info *pm8001_ha); | ||
156 | }; | 157 | }; |
157 | 158 | ||
158 | struct pm8001_chip_info { | 159 | struct pm8001_chip_info { |