diff options
author | Mark Salyzyn <mark_salyzyn@xyratex.com> | 2012-01-17 09:18:57 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 09:08:51 -0500 |
commit | d95d00016f8f51dc502cadb263d861bd8c0212bb (patch) | |
tree | aa60333c6d9aa97f3dc1f32f0fce3f3f08baa939 /drivers/scsi/pm8001 | |
parent | 5c4fb76af31e9dabcd132a0e69ed3799df1304c3 (diff) |
[SCSI] pm8001: Add FUNC_GET_EVENTS
Jack noticed I dropped a patch fragment associated with a flags automatic
variable in mpi_set_phys_g3_with_ssc (ooops) and that the pre-emptive locking
that piggy-backed this patch was not in-fact necessary because of underlying
atomic accesses to the hardware. Here is the updated patch fixing these two
issues.
The pm8001 driver is missing the FUNC_GET_EVENTS handler in the phy control
function. Since the pm8001_bar4_shift function was not designed to be called
at runtime, added locking surrounding the adjustment for all accesses.
Signed-off-by: Mark Salyzyn <mark_salyzyn@xyratex.com>
Acked-by: Jack Wang <jack_wang@usish.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/pm8001')
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 85 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.c | 24 | ||||
-rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.h | 1 |
3 files changed, 83 insertions, 27 deletions
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index b7b92f7be2aa..f3c44b96c1c9 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
@@ -338,26 +338,25 @@ update_outbnd_queue_table(struct pm8001_hba_info *pm8001_ha, int number) | |||
338 | } | 338 | } |
339 | 339 | ||
340 | /** | 340 | /** |
341 | * bar4_shift - function is called to shift BAR base address | 341 | * pm8001_bar4_shift - function is called to shift BAR base address |
342 | * @pm8001_ha : our hba card information | 342 | * @pm8001_ha : our hba card infomation |
343 | * @shiftValue : shifting value in memory bar. | 343 | * @shiftValue : shifting value in memory bar. |
344 | */ | 344 | */ |
345 | static int bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue) | 345 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue) |
346 | { | 346 | { |
347 | u32 regVal; | 347 | u32 regVal; |
348 | u32 max_wait_count; | 348 | unsigned long start; |
349 | 349 | ||
350 | /* program the inbound AXI translation Lower Address */ | 350 | /* program the inbound AXI translation Lower Address */ |
351 | pm8001_cw32(pm8001_ha, 1, SPC_IBW_AXI_TRANSLATION_LOW, shiftValue); | 351 | pm8001_cw32(pm8001_ha, 1, SPC_IBW_AXI_TRANSLATION_LOW, shiftValue); |
352 | 352 | ||
353 | /* confirm the setting is written */ | 353 | /* confirm the setting is written */ |
354 | max_wait_count = 1 * 1000 * 1000; /* 1 sec */ | 354 | start = jiffies + HZ; /* 1 sec */ |
355 | do { | 355 | do { |
356 | udelay(1); | ||
357 | regVal = pm8001_cr32(pm8001_ha, 1, SPC_IBW_AXI_TRANSLATION_LOW); | 356 | regVal = pm8001_cr32(pm8001_ha, 1, SPC_IBW_AXI_TRANSLATION_LOW); |
358 | } while ((regVal != shiftValue) && (--max_wait_count)); | 357 | } while ((regVal != shiftValue) && time_before(jiffies, start)); |
359 | 358 | ||
360 | if (!max_wait_count) { | 359 | if (regVal != shiftValue) { |
361 | PM8001_INIT_DBG(pm8001_ha, | 360 | PM8001_INIT_DBG(pm8001_ha, |
362 | pm8001_printk("TIMEOUT:SPC_IBW_AXI_TRANSLATION_LOW" | 361 | pm8001_printk("TIMEOUT:SPC_IBW_AXI_TRANSLATION_LOW" |
363 | " = 0x%x\n", regVal)); | 362 | " = 0x%x\n", regVal)); |
@@ -375,6 +374,7 @@ static void __devinit | |||
375 | mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit) | 374 | mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit) |
376 | { | 375 | { |
377 | u32 value, offset, i; | 376 | u32 value, offset, i; |
377 | unsigned long flags; | ||
378 | 378 | ||
379 | #define SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR 0x00030000 | 379 | #define SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR 0x00030000 |
380 | #define SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR 0x00040000 | 380 | #define SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR 0x00040000 |
@@ -388,16 +388,23 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit) | |||
388 | * Using shifted destination address 0x3_0000:0x1074 + 0x4000*N (N=0:3) | 388 | * Using shifted destination address 0x3_0000:0x1074 + 0x4000*N (N=0:3) |
389 | * Using shifted destination address 0x4_0000:0x1074 + 0x4000*(N-4) (N=4:7) | 389 | * Using shifted destination address 0x4_0000:0x1074 + 0x4000*(N-4) (N=4:7) |
390 | */ | 390 | */ |
391 | if (-1 == bar4_shift(pm8001_ha, SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR)) | 391 | spin_lock_irqsave(&pm8001_ha->lock, flags); |
392 | if (-1 == pm8001_bar4_shift(pm8001_ha, | ||
393 | SAS2_SETTINGS_LOCAL_PHY_0_3_SHIFT_ADDR)) { | ||
394 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
392 | return; | 395 | return; |
396 | } | ||
393 | 397 | ||
394 | for (i = 0; i < 4; i++) { | 398 | for (i = 0; i < 4; i++) { |
395 | offset = SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET + 0x4000 * i; | 399 | offset = SAS2_SETTINGS_LOCAL_PHY_0_3_OFFSET + 0x4000 * i; |
396 | pm8001_cw32(pm8001_ha, 2, offset, 0x80001501); | 400 | pm8001_cw32(pm8001_ha, 2, offset, 0x80001501); |
397 | } | 401 | } |
398 | /* shift membase 3 for SAS2_SETTINGS_LOCAL_PHY 4 - 7 */ | 402 | /* shift membase 3 for SAS2_SETTINGS_LOCAL_PHY 4 - 7 */ |
399 | if (-1 == bar4_shift(pm8001_ha, SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR)) | 403 | if (-1 == pm8001_bar4_shift(pm8001_ha, |
404 | SAS2_SETTINGS_LOCAL_PHY_4_7_SHIFT_ADDR)) { | ||
405 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
400 | return; | 406 | return; |
407 | } | ||
401 | for (i = 4; i < 8; i++) { | 408 | for (i = 4; i < 8; i++) { |
402 | offset = SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET + 0x4000 * (i-4); | 409 | offset = SAS2_SETTINGS_LOCAL_PHY_4_7_OFFSET + 0x4000 * (i-4); |
403 | pm8001_cw32(pm8001_ha, 2, offset, 0x80001501); | 410 | pm8001_cw32(pm8001_ha, 2, offset, 0x80001501); |
@@ -421,7 +428,8 @@ mpi_set_phys_g3_with_ssc(struct pm8001_hba_info *pm8001_ha, u32 SSCbit) | |||
421 | pm8001_cw32(pm8001_ha, 2, 0xd8, 0x8000C016); | 428 | pm8001_cw32(pm8001_ha, 2, 0xd8, 0x8000C016); |
422 | 429 | ||
423 | /*set the shifted destination address to 0x0 to avoid error operation */ | 430 | /*set the shifted destination address to 0x0 to avoid error operation */ |
424 | bar4_shift(pm8001_ha, 0x0); | 431 | pm8001_bar4_shift(pm8001_ha, 0x0); |
432 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
425 | return; | 433 | return; |
426 | } | 434 | } |
427 | 435 | ||
@@ -437,6 +445,7 @@ mpi_set_open_retry_interval_reg(struct pm8001_hba_info *pm8001_ha, | |||
437 | u32 offset; | 445 | u32 offset; |
438 | u32 value; | 446 | u32 value; |
439 | u32 i; | 447 | u32 i; |
448 | unsigned long flags; | ||
440 | 449 | ||
441 | #define OPEN_RETRY_INTERVAL_PHY_0_3_SHIFT_ADDR 0x00030000 | 450 | #define OPEN_RETRY_INTERVAL_PHY_0_3_SHIFT_ADDR 0x00030000 |
442 | #define OPEN_RETRY_INTERVAL_PHY_4_7_SHIFT_ADDR 0x00040000 | 451 | #define OPEN_RETRY_INTERVAL_PHY_4_7_SHIFT_ADDR 0x00040000 |
@@ -445,24 +454,30 @@ mpi_set_open_retry_interval_reg(struct pm8001_hba_info *pm8001_ha, | |||
445 | #define OPEN_RETRY_INTERVAL_REG_MASK 0x0000FFFF | 454 | #define OPEN_RETRY_INTERVAL_REG_MASK 0x0000FFFF |
446 | 455 | ||
447 | value = interval & OPEN_RETRY_INTERVAL_REG_MASK; | 456 | value = interval & OPEN_RETRY_INTERVAL_REG_MASK; |
457 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
448 | /* shift bar and set the OPEN_REJECT(RETRY) interval time of PHY 0 -3.*/ | 458 | /* shift bar and set the OPEN_REJECT(RETRY) interval time of PHY 0 -3.*/ |
449 | if (-1 == bar4_shift(pm8001_ha, | 459 | if (-1 == pm8001_bar4_shift(pm8001_ha, |
450 | OPEN_RETRY_INTERVAL_PHY_0_3_SHIFT_ADDR)) | 460 | OPEN_RETRY_INTERVAL_PHY_0_3_SHIFT_ADDR)) { |
461 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
451 | return; | 462 | return; |
463 | } | ||
452 | for (i = 0; i < 4; i++) { | 464 | for (i = 0; i < 4; i++) { |
453 | offset = OPEN_RETRY_INTERVAL_PHY_0_3_OFFSET + 0x4000 * i; | 465 | offset = OPEN_RETRY_INTERVAL_PHY_0_3_OFFSET + 0x4000 * i; |
454 | pm8001_cw32(pm8001_ha, 2, offset, value); | 466 | pm8001_cw32(pm8001_ha, 2, offset, value); |
455 | } | 467 | } |
456 | 468 | ||
457 | if (-1 == bar4_shift(pm8001_ha, | 469 | if (-1 == pm8001_bar4_shift(pm8001_ha, |
458 | OPEN_RETRY_INTERVAL_PHY_4_7_SHIFT_ADDR)) | 470 | OPEN_RETRY_INTERVAL_PHY_4_7_SHIFT_ADDR)) { |
471 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
459 | return; | 472 | return; |
473 | } | ||
460 | for (i = 4; i < 8; i++) { | 474 | for (i = 4; i < 8; i++) { |
461 | offset = OPEN_RETRY_INTERVAL_PHY_4_7_OFFSET + 0x4000 * (i-4); | 475 | offset = OPEN_RETRY_INTERVAL_PHY_4_7_OFFSET + 0x4000 * (i-4); |
462 | pm8001_cw32(pm8001_ha, 2, offset, value); | 476 | pm8001_cw32(pm8001_ha, 2, offset, value); |
463 | } | 477 | } |
464 | /*set the shifted destination address to 0x0 to avoid error operation */ | 478 | /*set the shifted destination address to 0x0 to avoid error operation */ |
465 | bar4_shift(pm8001_ha, 0x0); | 479 | pm8001_bar4_shift(pm8001_ha, 0x0); |
480 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
466 | return; | 481 | return; |
467 | } | 482 | } |
468 | 483 | ||
@@ -688,8 +703,11 @@ static u32 soft_reset_ready_check(struct pm8001_hba_info *pm8001_ha) | |||
688 | PM8001_INIT_DBG(pm8001_ha, | 703 | PM8001_INIT_DBG(pm8001_ha, |
689 | pm8001_printk("Firmware is ready for reset .\n")); | 704 | pm8001_printk("Firmware is ready for reset .\n")); |
690 | } else { | 705 | } else { |
691 | /* Trigger NMI twice via RB6 */ | 706 | unsigned long flags; |
692 | if (-1 == bar4_shift(pm8001_ha, RB6_ACCESS_REG)) { | 707 | /* Trigger NMI twice via RB6 */ |
708 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
709 | if (-1 == pm8001_bar4_shift(pm8001_ha, RB6_ACCESS_REG)) { | ||
710 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
693 | PM8001_FAIL_DBG(pm8001_ha, | 711 | PM8001_FAIL_DBG(pm8001_ha, |
694 | pm8001_printk("Shift Bar4 to 0x%x failed\n", | 712 | pm8001_printk("Shift Bar4 to 0x%x failed\n", |
695 | RB6_ACCESS_REG)); | 713 | RB6_ACCESS_REG)); |
@@ -715,8 +733,10 @@ static u32 soft_reset_ready_check(struct pm8001_hba_info *pm8001_ha) | |||
715 | PM8001_FAIL_DBG(pm8001_ha, | 733 | PM8001_FAIL_DBG(pm8001_ha, |
716 | pm8001_printk("SCRATCH_PAD3 value = 0x%x\n", | 734 | pm8001_printk("SCRATCH_PAD3 value = 0x%x\n", |
717 | pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3))); | 735 | pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3))); |
736 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
718 | return -1; | 737 | return -1; |
719 | } | 738 | } |
739 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
720 | } | 740 | } |
721 | return 0; | 741 | return 0; |
722 | } | 742 | } |
@@ -733,6 +753,7 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) | |||
733 | u32 regVal, toggleVal; | 753 | u32 regVal, toggleVal; |
734 | u32 max_wait_count; | 754 | u32 max_wait_count; |
735 | u32 regVal1, regVal2, regVal3; | 755 | u32 regVal1, regVal2, regVal3; |
756 | unsigned long flags; | ||
736 | 757 | ||
737 | /* step1: Check FW is ready for soft reset */ | 758 | /* step1: Check FW is ready for soft reset */ |
738 | if (soft_reset_ready_check(pm8001_ha) != 0) { | 759 | if (soft_reset_ready_check(pm8001_ha) != 0) { |
@@ -743,7 +764,9 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) | |||
743 | /* step 2: clear NMI status register on AAP1 and IOP, write the same | 764 | /* step 2: clear NMI status register on AAP1 and IOP, write the same |
744 | value to clear */ | 765 | value to clear */ |
745 | /* map 0x60000 to BAR4(0x20), BAR2(win) */ | 766 | /* map 0x60000 to BAR4(0x20), BAR2(win) */ |
746 | if (-1 == bar4_shift(pm8001_ha, MBIC_AAP1_ADDR_BASE)) { | 767 | spin_lock_irqsave(&pm8001_ha->lock, flags); |
768 | if (-1 == pm8001_bar4_shift(pm8001_ha, MBIC_AAP1_ADDR_BASE)) { | ||
769 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
747 | PM8001_FAIL_DBG(pm8001_ha, | 770 | PM8001_FAIL_DBG(pm8001_ha, |
748 | pm8001_printk("Shift Bar4 to 0x%x failed\n", | 771 | pm8001_printk("Shift Bar4 to 0x%x failed\n", |
749 | MBIC_AAP1_ADDR_BASE)); | 772 | MBIC_AAP1_ADDR_BASE)); |
@@ -754,7 +777,8 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) | |||
754 | pm8001_printk("MBIC - NMI Enable VPE0 (IOP)= 0x%x\n", regVal)); | 777 | pm8001_printk("MBIC - NMI Enable VPE0 (IOP)= 0x%x\n", regVal)); |
755 | pm8001_cw32(pm8001_ha, 2, MBIC_NMI_ENABLE_VPE0_IOP, 0x0); | 778 | pm8001_cw32(pm8001_ha, 2, MBIC_NMI_ENABLE_VPE0_IOP, 0x0); |
756 | /* map 0x70000 to BAR4(0x20), BAR2(win) */ | 779 | /* map 0x70000 to BAR4(0x20), BAR2(win) */ |
757 | if (-1 == bar4_shift(pm8001_ha, MBIC_IOP_ADDR_BASE)) { | 780 | if (-1 == pm8001_bar4_shift(pm8001_ha, MBIC_IOP_ADDR_BASE)) { |
781 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
758 | PM8001_FAIL_DBG(pm8001_ha, | 782 | PM8001_FAIL_DBG(pm8001_ha, |
759 | pm8001_printk("Shift Bar4 to 0x%x failed\n", | 783 | pm8001_printk("Shift Bar4 to 0x%x failed\n", |
760 | MBIC_IOP_ADDR_BASE)); | 784 | MBIC_IOP_ADDR_BASE)); |
@@ -796,7 +820,8 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) | |||
796 | 820 | ||
797 | /* read required registers for confirmming */ | 821 | /* read required registers for confirmming */ |
798 | /* map 0x0700000 to BAR4(0x20), BAR2(win) */ | 822 | /* map 0x0700000 to BAR4(0x20), BAR2(win) */ |
799 | if (-1 == bar4_shift(pm8001_ha, GSM_ADDR_BASE)) { | 823 | if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_ADDR_BASE)) { |
824 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
800 | PM8001_FAIL_DBG(pm8001_ha, | 825 | PM8001_FAIL_DBG(pm8001_ha, |
801 | pm8001_printk("Shift Bar4 to 0x%x failed\n", | 826 | pm8001_printk("Shift Bar4 to 0x%x failed\n", |
802 | GSM_ADDR_BASE)); | 827 | GSM_ADDR_BASE)); |
@@ -862,7 +887,8 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) | |||
862 | /* step 5: delay 10 usec */ | 887 | /* step 5: delay 10 usec */ |
863 | udelay(10); | 888 | udelay(10); |
864 | /* step 5-b: set GPIO-0 output control to tristate anyway */ | 889 | /* step 5-b: set GPIO-0 output control to tristate anyway */ |
865 | if (-1 == bar4_shift(pm8001_ha, GPIO_ADDR_BASE)) { | 890 | if (-1 == pm8001_bar4_shift(pm8001_ha, GPIO_ADDR_BASE)) { |
891 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
866 | PM8001_INIT_DBG(pm8001_ha, | 892 | PM8001_INIT_DBG(pm8001_ha, |
867 | pm8001_printk("Shift Bar4 to 0x%x failed\n", | 893 | pm8001_printk("Shift Bar4 to 0x%x failed\n", |
868 | GPIO_ADDR_BASE)); | 894 | GPIO_ADDR_BASE)); |
@@ -878,7 +904,8 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) | |||
878 | 904 | ||
879 | /* Step 6: Reset the IOP and AAP1 */ | 905 | /* Step 6: Reset the IOP and AAP1 */ |
880 | /* map 0x00000 to BAR4(0x20), BAR2(win) */ | 906 | /* map 0x00000 to BAR4(0x20), BAR2(win) */ |
881 | if (-1 == bar4_shift(pm8001_ha, SPC_TOP_LEVEL_ADDR_BASE)) { | 907 | if (-1 == pm8001_bar4_shift(pm8001_ha, SPC_TOP_LEVEL_ADDR_BASE)) { |
908 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
882 | PM8001_FAIL_DBG(pm8001_ha, | 909 | PM8001_FAIL_DBG(pm8001_ha, |
883 | pm8001_printk("SPC Shift Bar4 to 0x%x failed\n", | 910 | pm8001_printk("SPC Shift Bar4 to 0x%x failed\n", |
884 | SPC_TOP_LEVEL_ADDR_BASE)); | 911 | SPC_TOP_LEVEL_ADDR_BASE)); |
@@ -915,7 +942,8 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) | |||
915 | 942 | ||
916 | /* step 11: reads and sets the GSM Configuration and Reset Register */ | 943 | /* step 11: reads and sets the GSM Configuration and Reset Register */ |
917 | /* map 0x0700000 to BAR4(0x20), BAR2(win) */ | 944 | /* map 0x0700000 to BAR4(0x20), BAR2(win) */ |
918 | if (-1 == bar4_shift(pm8001_ha, GSM_ADDR_BASE)) { | 945 | if (-1 == pm8001_bar4_shift(pm8001_ha, GSM_ADDR_BASE)) { |
946 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
919 | PM8001_FAIL_DBG(pm8001_ha, | 947 | PM8001_FAIL_DBG(pm8001_ha, |
920 | pm8001_printk("SPC Shift Bar4 to 0x%x failed\n", | 948 | pm8001_printk("SPC Shift Bar4 to 0x%x failed\n", |
921 | GSM_ADDR_BASE)); | 949 | GSM_ADDR_BASE)); |
@@ -968,7 +996,8 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) | |||
968 | 996 | ||
969 | /* step 13: bring the IOP and AAP1 out of reset */ | 997 | /* step 13: bring the IOP and AAP1 out of reset */ |
970 | /* map 0x00000 to BAR4(0x20), BAR2(win) */ | 998 | /* map 0x00000 to BAR4(0x20), BAR2(win) */ |
971 | if (-1 == bar4_shift(pm8001_ha, SPC_TOP_LEVEL_ADDR_BASE)) { | 999 | if (-1 == pm8001_bar4_shift(pm8001_ha, SPC_TOP_LEVEL_ADDR_BASE)) { |
1000 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
972 | PM8001_FAIL_DBG(pm8001_ha, | 1001 | PM8001_FAIL_DBG(pm8001_ha, |
973 | pm8001_printk("Shift Bar4 to 0x%x failed\n", | 1002 | pm8001_printk("Shift Bar4 to 0x%x failed\n", |
974 | SPC_TOP_LEVEL_ADDR_BASE)); | 1003 | SPC_TOP_LEVEL_ADDR_BASE)); |
@@ -1010,6 +1039,7 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) | |||
1010 | pm8001_printk("SCRATCH_PAD3 value = 0x%x\n", | 1039 | pm8001_printk("SCRATCH_PAD3 value = 0x%x\n", |
1011 | pm8001_cr32(pm8001_ha, 0, | 1040 | pm8001_cr32(pm8001_ha, 0, |
1012 | MSGU_SCRATCH_PAD_3))); | 1041 | MSGU_SCRATCH_PAD_3))); |
1042 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
1013 | return -1; | 1043 | return -1; |
1014 | } | 1044 | } |
1015 | 1045 | ||
@@ -1039,9 +1069,12 @@ pm8001_chip_soft_rst(struct pm8001_hba_info *pm8001_ha, u32 signature) | |||
1039 | pm8001_printk("SCRATCH_PAD3 value = 0x%x\n", | 1069 | pm8001_printk("SCRATCH_PAD3 value = 0x%x\n", |
1040 | pm8001_cr32(pm8001_ha, 0, | 1070 | pm8001_cr32(pm8001_ha, 0, |
1041 | MSGU_SCRATCH_PAD_3))); | 1071 | MSGU_SCRATCH_PAD_3))); |
1072 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
1042 | return -1; | 1073 | return -1; |
1043 | } | 1074 | } |
1044 | } | 1075 | } |
1076 | pm8001_bar4_shift(pm8001_ha, 0); | ||
1077 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
1045 | 1078 | ||
1046 | PM8001_INIT_DBG(pm8001_ha, | 1079 | PM8001_INIT_DBG(pm8001_ha, |
1047 | pm8001_printk("SPC soft reset Complete\n")); | 1080 | pm8001_printk("SPC soft reset Complete\n")); |
@@ -1157,8 +1190,8 @@ pm8001_chip_msix_interrupt_disable(struct pm8001_hba_info *pm8001_ha, | |||
1157 | msi_index = int_vec_idx * MSIX_TABLE_ELEMENT_SIZE; | 1190 | msi_index = int_vec_idx * MSIX_TABLE_ELEMENT_SIZE; |
1158 | msi_index += MSIX_TABLE_BASE; | 1191 | msi_index += MSIX_TABLE_BASE; |
1159 | pm8001_cw32(pm8001_ha, 0, msi_index, MSIX_INTERRUPT_DISABLE); | 1192 | pm8001_cw32(pm8001_ha, 0, msi_index, MSIX_INTERRUPT_DISABLE); |
1160 | |||
1161 | } | 1193 | } |
1194 | |||
1162 | /** | 1195 | /** |
1163 | * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt | 1196 | * pm8001_chip_interrupt_enable - enable PM8001 chip interrupt |
1164 | * @pm8001_ha: our hba card information | 1197 | * @pm8001_ha: our hba card information |
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 7ae22a67bd31..ab0704e39040 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c | |||
@@ -166,6 +166,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, | |||
166 | struct pm8001_hba_info *pm8001_ha = NULL; | 166 | struct pm8001_hba_info *pm8001_ha = NULL; |
167 | struct sas_phy_linkrates *rates; | 167 | struct sas_phy_linkrates *rates; |
168 | DECLARE_COMPLETION_ONSTACK(completion); | 168 | DECLARE_COMPLETION_ONSTACK(completion); |
169 | unsigned long flags; | ||
169 | pm8001_ha = sas_phy->ha->lldd_ha; | 170 | pm8001_ha = sas_phy->ha->lldd_ha; |
170 | pm8001_ha->phy[phy_id].enable_completion = &completion; | 171 | pm8001_ha->phy[phy_id].enable_completion = &completion; |
171 | switch (func) { | 172 | switch (func) { |
@@ -209,8 +210,29 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, | |||
209 | case PHY_FUNC_DISABLE: | 210 | case PHY_FUNC_DISABLE: |
210 | PM8001_CHIP_DISP->phy_stop_req(pm8001_ha, phy_id); | 211 | PM8001_CHIP_DISP->phy_stop_req(pm8001_ha, phy_id); |
211 | break; | 212 | break; |
213 | case PHY_FUNC_GET_EVENTS: | ||
214 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
215 | if (-1 == pm8001_bar4_shift(pm8001_ha, | ||
216 | (phy_id < 4) ? 0x30000 : 0x40000)) { | ||
217 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
218 | return -EINVAL; | ||
219 | } | ||
220 | { | ||
221 | struct sas_phy *phy = sas_phy->phy; | ||
222 | uint32_t *qp = (uint32_t *)(((char *) | ||
223 | pm8001_ha->io_mem[2].memvirtaddr) | ||
224 | + 0x1034 + (0x4000 * (phy_id & 3))); | ||
225 | |||
226 | phy->invalid_dword_count = qp[0]; | ||
227 | phy->running_disparity_error_count = qp[1]; | ||
228 | phy->loss_of_dword_sync_count = qp[3]; | ||
229 | phy->phy_reset_problem_count = qp[4]; | ||
230 | } | ||
231 | pm8001_bar4_shift(pm8001_ha, 0); | ||
232 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
233 | return 0; | ||
212 | default: | 234 | default: |
213 | rc = -ENOSYS; | 235 | rc = -EOPNOTSUPP; |
214 | } | 236 | } |
215 | msleep(300); | 237 | msleep(300); |
216 | return rc; | 238 | return rc; |
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 93959febe205..83a48f3247b8 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h | |||
@@ -488,6 +488,7 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr, | |||
488 | dma_addr_t *pphys_addr, u32 *pphys_addr_hi, u32 *pphys_addr_lo, | 488 | dma_addr_t *pphys_addr, u32 *pphys_addr_hi, u32 *pphys_addr_lo, |
489 | u32 mem_size, u32 align); | 489 | u32 mem_size, u32 align); |
490 | 490 | ||
491 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | ||
491 | 492 | ||
492 | /* ctl shared API */ | 493 | /* ctl shared API */ |
493 | extern struct device_attribute *pm8001_host_attrs[]; | 494 | extern struct device_attribute *pm8001_host_attrs[]; |