diff options
Diffstat (limited to 'drivers/scsi/pm8001')
| -rw-r--r-- | drivers/scsi/pm8001/pm8001_defs.h | 2 | ||||
| -rw-r--r-- | drivers/scsi/pm8001/pm8001_init.c | 216 | ||||
| -rw-r--r-- | drivers/scsi/pm8001/pm8001_sas.h | 6 | ||||
| -rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.c | 34 |
4 files changed, 243 insertions, 15 deletions
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h index f14ec6e042b9..199527dbaaa1 100644 --- a/drivers/scsi/pm8001/pm8001_defs.h +++ b/drivers/scsi/pm8001/pm8001_defs.h | |||
| @@ -51,6 +51,8 @@ enum chip_flavors { | |||
| 51 | chip_8076, | 51 | chip_8076, |
| 52 | chip_8077, | 52 | chip_8077, |
| 53 | chip_8006, | 53 | chip_8006, |
| 54 | chip_8070, | ||
| 55 | chip_8072 | ||
| 54 | }; | 56 | }; |
| 55 | 57 | ||
| 56 | enum phy_speed { | 58 | enum phy_speed { |
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index 5c0356fb6310..062ab34b86f8 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c | |||
| @@ -58,6 +58,8 @@ static const struct pm8001_chip_info pm8001_chips[] = { | |||
| 58 | [chip_8076] = {0, 16, &pm8001_80xx_dispatch,}, | 58 | [chip_8076] = {0, 16, &pm8001_80xx_dispatch,}, |
| 59 | [chip_8077] = {0, 16, &pm8001_80xx_dispatch,}, | 59 | [chip_8077] = {0, 16, &pm8001_80xx_dispatch,}, |
| 60 | [chip_8006] = {0, 16, &pm8001_80xx_dispatch,}, | 60 | [chip_8006] = {0, 16, &pm8001_80xx_dispatch,}, |
| 61 | [chip_8070] = {0, 8, &pm8001_80xx_dispatch,}, | ||
| 62 | [chip_8072] = {0, 16, &pm8001_80xx_dispatch,}, | ||
| 61 | }; | 63 | }; |
| 62 | static int pm8001_id; | 64 | static int pm8001_id; |
| 63 | 65 | ||
| @@ -88,7 +90,6 @@ static struct scsi_host_template pm8001_sht = { | |||
| 88 | .target_destroy = sas_target_destroy, | 90 | .target_destroy = sas_target_destroy, |
| 89 | .ioctl = sas_ioctl, | 91 | .ioctl = sas_ioctl, |
| 90 | .shost_attrs = pm8001_host_attrs, | 92 | .shost_attrs = pm8001_host_attrs, |
| 91 | .use_blk_tags = 1, | ||
| 92 | .track_queue_depth = 1, | 93 | .track_queue_depth = 1, |
| 93 | }; | 94 | }; |
| 94 | 95 | ||
| @@ -480,7 +481,8 @@ static struct pm8001_hba_info *pm8001_pci_alloc(struct pci_dev *pdev, | |||
| 480 | 481 | ||
| 481 | #ifdef PM8001_USE_TASKLET | 482 | #ifdef PM8001_USE_TASKLET |
| 482 | /* Tasklet for non msi-x interrupt handler */ | 483 | /* Tasklet for non msi-x interrupt handler */ |
| 483 | if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001)) | 484 | if ((!pdev->msix_cap || !pci_msi_enabled()) |
| 485 | || (pm8001_ha->chip_id == chip_8001)) | ||
| 484 | tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet, | 486 | tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet, |
| 485 | (unsigned long)&(pm8001_ha->irq_vector[0])); | 487 | (unsigned long)&(pm8001_ha->irq_vector[0])); |
| 486 | else | 488 | else |
| @@ -634,6 +636,11 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) | |||
| 634 | payload.minor_function = 0; | 636 | payload.minor_function = 0; |
| 635 | payload.length = 128; | 637 | payload.length = 128; |
| 636 | } | 638 | } |
| 639 | } else if ((pm8001_ha->chip_id == chip_8070 || | ||
| 640 | pm8001_ha->chip_id == chip_8072) && | ||
| 641 | pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) { | ||
| 642 | payload.minor_function = 4; | ||
| 643 | payload.length = 4096; | ||
| 637 | } else { | 644 | } else { |
| 638 | payload.minor_function = 1; | 645 | payload.minor_function = 1; |
| 639 | payload.length = 4096; | 646 | payload.length = 4096; |
| @@ -660,6 +667,11 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) | |||
| 660 | else if (deviceid == 0x0042) | 667 | else if (deviceid == 0x0042) |
| 661 | pm8001_ha->sas_addr[j] = | 668 | pm8001_ha->sas_addr[j] = |
| 662 | payload.func_specific[0x010 + i]; | 669 | payload.func_specific[0x010 + i]; |
| 670 | } else if ((pm8001_ha->chip_id == chip_8070 || | ||
| 671 | pm8001_ha->chip_id == chip_8072) && | ||
| 672 | pm8001_ha->pdev->subsystem_vendor == PCI_VENDOR_ID_ATTO) { | ||
| 673 | pm8001_ha->sas_addr[j] = | ||
| 674 | payload.func_specific[0x010 + i]; | ||
| 663 | } else | 675 | } else |
| 664 | pm8001_ha->sas_addr[j] = | 676 | pm8001_ha->sas_addr[j] = |
| 665 | payload.func_specific[0x804 + i]; | 677 | payload.func_specific[0x804 + i]; |
| @@ -720,6 +732,153 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) | |||
| 720 | return 0; | 732 | return 0; |
| 721 | } | 733 | } |
| 722 | 734 | ||
| 735 | struct pm8001_mpi3_phy_pg_trx_config { | ||
| 736 | u32 LaneLosCfg; | ||
| 737 | u32 LanePgaCfg1; | ||
| 738 | u32 LanePisoCfg1; | ||
| 739 | u32 LanePisoCfg2; | ||
| 740 | u32 LanePisoCfg3; | ||
| 741 | u32 LanePisoCfg4; | ||
| 742 | u32 LanePisoCfg5; | ||
| 743 | u32 LanePisoCfg6; | ||
| 744 | u32 LaneBctCtrl; | ||
| 745 | }; | ||
| 746 | |||
| 747 | /** | ||
| 748 | * pm8001_get_internal_phy_settings : Retrieves the internal PHY settings | ||
| 749 | * @pm8001_ha : our adapter | ||
| 750 | * @phycfg : PHY config page to populate | ||
| 751 | */ | ||
| 752 | static | ||
| 753 | void pm8001_get_internal_phy_settings(struct pm8001_hba_info *pm8001_ha, | ||
| 754 | struct pm8001_mpi3_phy_pg_trx_config *phycfg) | ||
| 755 | { | ||
| 756 | phycfg->LaneLosCfg = 0x00000132; | ||
| 757 | phycfg->LanePgaCfg1 = 0x00203949; | ||
| 758 | phycfg->LanePisoCfg1 = 0x000000FF; | ||
| 759 | phycfg->LanePisoCfg2 = 0xFF000001; | ||
| 760 | phycfg->LanePisoCfg3 = 0xE7011300; | ||
| 761 | phycfg->LanePisoCfg4 = 0x631C40C0; | ||
| 762 | phycfg->LanePisoCfg5 = 0xF8102036; | ||
| 763 | phycfg->LanePisoCfg6 = 0xF74A1000; | ||
| 764 | phycfg->LaneBctCtrl = 0x00FB33F8; | ||
| 765 | } | ||
| 766 | |||
| 767 | /** | ||
| 768 | * pm8001_get_external_phy_settings : Retrieves the external PHY settings | ||
| 769 | * @pm8001_ha : our adapter | ||
| 770 | * @phycfg : PHY config page to populate | ||
| 771 | */ | ||
| 772 | static | ||
| 773 | void pm8001_get_external_phy_settings(struct pm8001_hba_info *pm8001_ha, | ||
| 774 | struct pm8001_mpi3_phy_pg_trx_config *phycfg) | ||
| 775 | { | ||
| 776 | phycfg->LaneLosCfg = 0x00000132; | ||
| 777 | phycfg->LanePgaCfg1 = 0x00203949; | ||
| 778 | phycfg->LanePisoCfg1 = 0x000000FF; | ||
| 779 | phycfg->LanePisoCfg2 = 0xFF000001; | ||
| 780 | phycfg->LanePisoCfg3 = 0xE7011300; | ||
| 781 | phycfg->LanePisoCfg4 = 0x63349140; | ||
| 782 | phycfg->LanePisoCfg5 = 0xF8102036; | ||
| 783 | phycfg->LanePisoCfg6 = 0xF80D9300; | ||
| 784 | phycfg->LaneBctCtrl = 0x00FB33F8; | ||
| 785 | } | ||
| 786 | |||
| 787 | /** | ||
| 788 | * pm8001_get_phy_mask : Retrieves the mask that denotes if a PHY is int/ext | ||
| 789 | * @pm8001_ha : our adapter | ||
| 790 | * @phymask : The PHY mask | ||
| 791 | */ | ||
| 792 | static | ||
| 793 | void pm8001_get_phy_mask(struct pm8001_hba_info *pm8001_ha, int *phymask) | ||
| 794 | { | ||
| 795 | switch (pm8001_ha->pdev->subsystem_device) { | ||
| 796 | case 0x0070: /* H1280 - 8 external 0 internal */ | ||
| 797 | case 0x0072: /* H12F0 - 16 external 0 internal */ | ||
| 798 | *phymask = 0x0000; | ||
| 799 | break; | ||
| 800 | |||
| 801 | case 0x0071: /* H1208 - 0 external 8 internal */ | ||
| 802 | case 0x0073: /* H120F - 0 external 16 internal */ | ||
| 803 | *phymask = 0xFFFF; | ||
| 804 | break; | ||
| 805 | |||
| 806 | case 0x0080: /* H1244 - 4 external 4 internal */ | ||
| 807 | *phymask = 0x00F0; | ||
| 808 | break; | ||
| 809 | |||
| 810 | case 0x0081: /* H1248 - 4 external 8 internal */ | ||
| 811 | *phymask = 0x0FF0; | ||
| 812 | break; | ||
| 813 | |||
| 814 | case 0x0082: /* H1288 - 8 external 8 internal */ | ||
| 815 | *phymask = 0xFF00; | ||
| 816 | break; | ||
| 817 | |||
| 818 | default: | ||
| 819 | PM8001_INIT_DBG(pm8001_ha, | ||
| 820 | pm8001_printk("Unknown subsystem device=0x%.04x", | ||
| 821 | pm8001_ha->pdev->subsystem_device)); | ||
| 822 | } | ||
| 823 | } | ||
| 824 | |||
| 825 | /** | ||
| 826 | * pm8001_set_phy_settings_ven_117c_12Gb : Configure ATTO 12Gb PHY settings | ||
| 827 | * @pm8001_ha : our adapter | ||
| 828 | */ | ||
| 829 | static | ||
| 830 | int pm8001_set_phy_settings_ven_117c_12G(struct pm8001_hba_info *pm8001_ha) | ||
| 831 | { | ||
| 832 | struct pm8001_mpi3_phy_pg_trx_config phycfg_int; | ||
| 833 | struct pm8001_mpi3_phy_pg_trx_config phycfg_ext; | ||
| 834 | int phymask = 0; | ||
| 835 | int i = 0; | ||
| 836 | |||
| 837 | memset(&phycfg_int, 0, sizeof(phycfg_int)); | ||
| 838 | memset(&phycfg_ext, 0, sizeof(phycfg_ext)); | ||
| 839 | |||
| 840 | pm8001_get_internal_phy_settings(pm8001_ha, &phycfg_int); | ||
| 841 | pm8001_get_external_phy_settings(pm8001_ha, &phycfg_ext); | ||
| 842 | pm8001_get_phy_mask(pm8001_ha, &phymask); | ||
| 843 | |||
| 844 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { | ||
| 845 | if (phymask & (1 << i)) {/* Internal PHY */ | ||
| 846 | pm8001_set_phy_profile_single(pm8001_ha, i, | ||
| 847 | sizeof(phycfg_int) / sizeof(u32), | ||
| 848 | (u32 *)&phycfg_int); | ||
| 849 | |||
| 850 | } else { /* External PHY */ | ||
| 851 | pm8001_set_phy_profile_single(pm8001_ha, i, | ||
| 852 | sizeof(phycfg_ext) / sizeof(u32), | ||
| 853 | (u32 *)&phycfg_ext); | ||
| 854 | } | ||
| 855 | } | ||
| 856 | |||
| 857 | return 0; | ||
| 858 | } | ||
| 859 | |||
| 860 | /** | ||
| 861 | * pm8001_configure_phy_settings : Configures PHY settings based on vendor ID. | ||
| 862 | * @pm8001_ha : our hba. | ||
| 863 | */ | ||
| 864 | static int pm8001_configure_phy_settings(struct pm8001_hba_info *pm8001_ha) | ||
| 865 | { | ||
| 866 | switch (pm8001_ha->pdev->subsystem_vendor) { | ||
| 867 | case PCI_VENDOR_ID_ATTO: | ||
| 868 | if (pm8001_ha->pdev->device == 0x0042) /* 6Gb */ | ||
| 869 | return 0; | ||
| 870 | else | ||
| 871 | return pm8001_set_phy_settings_ven_117c_12G(pm8001_ha); | ||
| 872 | |||
| 873 | case PCI_VENDOR_ID_ADAPTEC2: | ||
| 874 | case 0: | ||
| 875 | return 0; | ||
| 876 | |||
| 877 | default: | ||
| 878 | return pm8001_get_phy_settings_info(pm8001_ha); | ||
| 879 | } | ||
| 880 | } | ||
| 881 | |||
| 723 | #ifdef PM8001_USE_MSIX | 882 | #ifdef PM8001_USE_MSIX |
| 724 | /** | 883 | /** |
| 725 | * pm8001_setup_msix - enable MSI-X interrupt | 884 | * pm8001_setup_msix - enable MSI-X interrupt |
| @@ -792,7 +951,7 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) | |||
| 792 | pdev = pm8001_ha->pdev; | 951 | pdev = pm8001_ha->pdev; |
| 793 | 952 | ||
| 794 | #ifdef PM8001_USE_MSIX | 953 | #ifdef PM8001_USE_MSIX |
| 795 | if (pdev->msix_cap) | 954 | if (pdev->msix_cap && pci_msi_enabled()) |
| 796 | return pm8001_setup_msix(pm8001_ha); | 955 | return pm8001_setup_msix(pm8001_ha); |
| 797 | else { | 956 | else { |
| 798 | PM8001_INIT_DBG(pm8001_ha, | 957 | PM8001_INIT_DBG(pm8001_ha, |
| @@ -803,6 +962,8 @@ static u32 pm8001_request_irq(struct pm8001_hba_info *pm8001_ha) | |||
| 803 | 962 | ||
| 804 | intx: | 963 | intx: |
| 805 | /* initialize the INT-X interrupt */ | 964 | /* initialize the INT-X interrupt */ |
| 965 | pm8001_ha->irq_vector[0].irq_id = 0; | ||
| 966 | pm8001_ha->irq_vector[0].drv_inst = pm8001_ha; | ||
| 806 | rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED, | 967 | rc = request_irq(pdev->irq, pm8001_interrupt_handler_intx, IRQF_SHARED, |
| 807 | DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost)); | 968 | DRV_NAME, SHOST_TO_SAS_HA(pm8001_ha->shost)); |
| 808 | return rc; | 969 | return rc; |
| @@ -902,12 +1063,9 @@ static int pm8001_pci_probe(struct pci_dev *pdev, | |||
| 902 | 1063 | ||
| 903 | pm8001_init_sas_add(pm8001_ha); | 1064 | pm8001_init_sas_add(pm8001_ha); |
| 904 | /* phy setting support for motherboard controller */ | 1065 | /* phy setting support for motherboard controller */ |
| 905 | if (pdev->subsystem_vendor != PCI_VENDOR_ID_ADAPTEC2 && | 1066 | if (pm8001_configure_phy_settings(pm8001_ha)) |
| 906 | pdev->subsystem_vendor != 0) { | 1067 | goto err_out_shost; |
| 907 | rc = pm8001_get_phy_settings_info(pm8001_ha); | 1068 | |
| 908 | if (rc) | ||
| 909 | goto err_out_shost; | ||
| 910 | } | ||
| 911 | pm8001_post_sas_ha_init(shost, chip); | 1069 | pm8001_post_sas_ha_init(shost, chip); |
| 912 | rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); | 1070 | rc = sas_register_ha(SHOST_TO_SAS_HA(shost)); |
| 913 | if (rc) | 1071 | if (rc) |
| @@ -937,10 +1095,10 @@ static void pm8001_pci_remove(struct pci_dev *pdev) | |||
| 937 | struct pm8001_hba_info *pm8001_ha; | 1095 | struct pm8001_hba_info *pm8001_ha; |
| 938 | int i, j; | 1096 | int i, j; |
| 939 | pm8001_ha = sha->lldd_ha; | 1097 | pm8001_ha = sha->lldd_ha; |
| 1098 | scsi_remove_host(pm8001_ha->shost); | ||
| 940 | sas_unregister_ha(sha); | 1099 | sas_unregister_ha(sha); |
| 941 | sas_remove_host(pm8001_ha->shost); | 1100 | sas_remove_host(pm8001_ha->shost); |
| 942 | list_del(&pm8001_ha->list); | 1101 | list_del(&pm8001_ha->list); |
| 943 | scsi_remove_host(pm8001_ha->shost); | ||
| 944 | PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF); | 1102 | PM8001_CHIP_DISP->interrupt_disable(pm8001_ha, 0xFF); |
| 945 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); | 1103 | PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); |
| 946 | 1104 | ||
| @@ -956,7 +1114,8 @@ static void pm8001_pci_remove(struct pci_dev *pdev) | |||
| 956 | #endif | 1114 | #endif |
| 957 | #ifdef PM8001_USE_TASKLET | 1115 | #ifdef PM8001_USE_TASKLET |
| 958 | /* For non-msix and msix interrupts */ | 1116 | /* For non-msix and msix interrupts */ |
| 959 | if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001)) | 1117 | if ((!pdev->msix_cap || !pci_msi_enabled()) || |
| 1118 | (pm8001_ha->chip_id == chip_8001)) | ||
| 960 | tasklet_kill(&pm8001_ha->tasklet[0]); | 1119 | tasklet_kill(&pm8001_ha->tasklet[0]); |
| 961 | else | 1120 | else |
| 962 | for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) | 1121 | for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) |
| @@ -1005,7 +1164,8 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
| 1005 | #endif | 1164 | #endif |
| 1006 | #ifdef PM8001_USE_TASKLET | 1165 | #ifdef PM8001_USE_TASKLET |
| 1007 | /* For non-msix and msix interrupts */ | 1166 | /* For non-msix and msix interrupts */ |
| 1008 | if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001)) | 1167 | if ((!pdev->msix_cap || !pci_msi_enabled()) || |
| 1168 | (pm8001_ha->chip_id == chip_8001)) | ||
| 1009 | tasklet_kill(&pm8001_ha->tasklet[0]); | 1169 | tasklet_kill(&pm8001_ha->tasklet[0]); |
| 1010 | else | 1170 | else |
| 1011 | for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) | 1171 | for (j = 0; j < PM8001_MAX_MSIX_VEC; j++) |
| @@ -1074,7 +1234,8 @@ static int pm8001_pci_resume(struct pci_dev *pdev) | |||
| 1074 | goto err_out_disable; | 1234 | goto err_out_disable; |
| 1075 | #ifdef PM8001_USE_TASKLET | 1235 | #ifdef PM8001_USE_TASKLET |
| 1076 | /* Tasklet for non msi-x interrupt handler */ | 1236 | /* Tasklet for non msi-x interrupt handler */ |
| 1077 | if ((!pdev->msix_cap) || (pm8001_ha->chip_id == chip_8001)) | 1237 | if ((!pdev->msix_cap || !pci_msi_enabled()) || |
| 1238 | (pm8001_ha->chip_id == chip_8001)) | ||
| 1078 | tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet, | 1239 | tasklet_init(&pm8001_ha->tasklet[0], pm8001_tasklet, |
| 1079 | (unsigned long)&(pm8001_ha->irq_vector[0])); | 1240 | (unsigned long)&(pm8001_ha->irq_vector[0])); |
| 1080 | else | 1241 | else |
| @@ -1087,6 +1248,19 @@ static int pm8001_pci_resume(struct pci_dev *pdev) | |||
| 1087 | for (i = 1; i < pm8001_ha->number_of_intr; i++) | 1248 | for (i = 1; i < pm8001_ha->number_of_intr; i++) |
| 1088 | PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i); | 1249 | PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i); |
| 1089 | } | 1250 | } |
| 1251 | |||
| 1252 | /* Chip documentation for the 8070 and 8072 SPCv */ | ||
| 1253 | /* states that a 500ms minimum delay is required */ | ||
| 1254 | /* before issuing commands. Otherwise, the firmare */ | ||
| 1255 | /* will enter an unrecoverable state. */ | ||
| 1256 | |||
| 1257 | if (pm8001_ha->chip_id == chip_8070 || | ||
| 1258 | pm8001_ha->chip_id == chip_8072) { | ||
| 1259 | mdelay(500); | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | /* Spin up the PHYs */ | ||
| 1263 | |||
| 1090 | pm8001_ha->flags = PM8001F_RUN_TIME; | 1264 | pm8001_ha->flags = PM8001F_RUN_TIME; |
| 1091 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { | 1265 | for (i = 0; i < pm8001_ha->chip->n_phy; i++) { |
| 1092 | pm8001_ha->phy[i].enable_completion = &completion; | 1266 | pm8001_ha->phy[i].enable_completion = &completion; |
| @@ -1165,6 +1339,20 @@ static struct pci_device_id pm8001_pci_table[] = { | |||
| 1165 | PCI_VENDOR_ID_ADAPTEC2, 0x0808, 0, 0, chip_8077 }, | 1339 | PCI_VENDOR_ID_ADAPTEC2, 0x0808, 0, 0, chip_8077 }, |
| 1166 | { PCI_VENDOR_ID_ADAPTEC2, 0x8074, | 1340 | { PCI_VENDOR_ID_ADAPTEC2, 0x8074, |
| 1167 | PCI_VENDOR_ID_ADAPTEC2, 0x0404, 0, 0, chip_8074 }, | 1341 | PCI_VENDOR_ID_ADAPTEC2, 0x0404, 0, 0, chip_8074 }, |
| 1342 | { PCI_VENDOR_ID_ATTO, 0x8070, | ||
| 1343 | PCI_VENDOR_ID_ATTO, 0x0070, 0, 0, chip_8070 }, | ||
| 1344 | { PCI_VENDOR_ID_ATTO, 0x8070, | ||
| 1345 | PCI_VENDOR_ID_ATTO, 0x0071, 0, 0, chip_8070 }, | ||
| 1346 | { PCI_VENDOR_ID_ATTO, 0x8072, | ||
| 1347 | PCI_VENDOR_ID_ATTO, 0x0072, 0, 0, chip_8072 }, | ||
| 1348 | { PCI_VENDOR_ID_ATTO, 0x8072, | ||
| 1349 | PCI_VENDOR_ID_ATTO, 0x0073, 0, 0, chip_8072 }, | ||
| 1350 | { PCI_VENDOR_ID_ATTO, 0x8070, | ||
| 1351 | PCI_VENDOR_ID_ATTO, 0x0080, 0, 0, chip_8070 }, | ||
| 1352 | { PCI_VENDOR_ID_ATTO, 0x8072, | ||
| 1353 | PCI_VENDOR_ID_ATTO, 0x0081, 0, 0, chip_8072 }, | ||
| 1354 | { PCI_VENDOR_ID_ATTO, 0x8072, | ||
| 1355 | PCI_VENDOR_ID_ATTO, 0x0082, 0, 0, chip_8072 }, | ||
| 1168 | {} /* terminate list */ | 1356 | {} /* terminate list */ |
| 1169 | }; | 1357 | }; |
| 1170 | 1358 | ||
| @@ -1220,7 +1408,7 @@ MODULE_AUTHOR("Anand Kumar Santhanam <AnandKumar.Santhanam@pmcs.com>"); | |||
| 1220 | MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>"); | 1408 | MODULE_AUTHOR("Sangeetha Gnanasekaran <Sangeetha.Gnanasekaran@pmcs.com>"); |
| 1221 | MODULE_AUTHOR("Nikith Ganigarakoppal <Nikith.Ganigarakoppal@pmcs.com>"); | 1409 | MODULE_AUTHOR("Nikith Ganigarakoppal <Nikith.Ganigarakoppal@pmcs.com>"); |
| 1222 | MODULE_DESCRIPTION( | 1410 | MODULE_DESCRIPTION( |
| 1223 | "PMC-Sierra PM8001/8006/8081/8088/8089/8074/8076/8077 " | 1411 | "PMC-Sierra PM8001/8006/8081/8088/8089/8074/8076/8077/8070/8072 " |
| 1224 | "SAS/SATA controller driver"); | 1412 | "SAS/SATA controller driver"); |
| 1225 | MODULE_VERSION(DRV_VERSION); | 1413 | MODULE_VERSION(DRV_VERSION); |
| 1226 | MODULE_LICENSE("GPL"); | 1414 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index e2e97db38ae8..6628cc38316c 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h | |||
| @@ -106,7 +106,9 @@ do { \ | |||
| 106 | #define DEV_IS_EXPANDER(type) ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE)) | 106 | #define DEV_IS_EXPANDER(type) ((type == SAS_EDGE_EXPANDER_DEVICE) || (type == SAS_FANOUT_EXPANDER_DEVICE)) |
| 107 | #define IS_SPCV_12G(dev) ((dev->device == 0X8074) \ | 107 | #define IS_SPCV_12G(dev) ((dev->device == 0X8074) \ |
| 108 | || (dev->device == 0X8076) \ | 108 | || (dev->device == 0X8076) \ |
| 109 | || (dev->device == 0X8077)) | 109 | || (dev->device == 0X8077) \ |
| 110 | || (dev->device == 0X8070) \ | ||
| 111 | || (dev->device == 0X8072)) | ||
| 110 | 112 | ||
| 111 | #define PM8001_NAME_LENGTH 32/* generic length of strings */ | 113 | #define PM8001_NAME_LENGTH 32/* generic length of strings */ |
| 112 | extern struct list_head hba_list; | 114 | extern struct list_head hba_list; |
| @@ -708,6 +710,8 @@ int pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha); | |||
| 708 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | 710 | int pm8001_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); |
| 709 | void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, | 711 | void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, |
| 710 | u32 length, u8 *buf); | 712 | u32 length, u8 *buf); |
| 713 | void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha, | ||
| 714 | u32 phy, u32 length, u32 *buf); | ||
| 711 | int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); | 715 | int pm80xx_bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue); |
| 712 | ssize_t pm80xx_get_fatal_dump(struct device *cdev, | 716 | ssize_t pm80xx_get_fatal_dump(struct device *cdev, |
| 713 | struct device_attribute *attr, char *buf); | 717 | struct device_attribute *attr, char *buf); |
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 9a389f1508de..eb4fee61df72 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c | |||
| @@ -1267,6 +1267,8 @@ pm80xx_chip_soft_rst(struct pm8001_hba_info *pm8001_ha) | |||
| 1267 | /* check iButton feature support for motherboard controller */ | 1267 | /* check iButton feature support for motherboard controller */ |
| 1268 | if (pm8001_ha->pdev->subsystem_vendor != | 1268 | if (pm8001_ha->pdev->subsystem_vendor != |
| 1269 | PCI_VENDOR_ID_ADAPTEC2 && | 1269 | PCI_VENDOR_ID_ADAPTEC2 && |
| 1270 | pm8001_ha->pdev->subsystem_vendor != | ||
| 1271 | PCI_VENDOR_ID_ATTO && | ||
| 1270 | pm8001_ha->pdev->subsystem_vendor != 0) { | 1272 | pm8001_ha->pdev->subsystem_vendor != 0) { |
| 1271 | ibutton0 = pm8001_cr32(pm8001_ha, 0, | 1273 | ibutton0 = pm8001_cr32(pm8001_ha, 0, |
| 1272 | MSGU_HOST_SCRATCH_PAD_6); | 1274 | MSGU_HOST_SCRATCH_PAD_6); |
| @@ -4576,6 +4578,38 @@ void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, | |||
| 4576 | } | 4578 | } |
| 4577 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n")); | 4579 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk("phy settings completed\n")); |
| 4578 | } | 4580 | } |
| 4581 | |||
| 4582 | void pm8001_set_phy_profile_single(struct pm8001_hba_info *pm8001_ha, | ||
| 4583 | u32 phy, u32 length, u32 *buf) | ||
| 4584 | { | ||
| 4585 | u32 tag, opc; | ||
| 4586 | int rc, i; | ||
| 4587 | struct set_phy_profile_req payload; | ||
| 4588 | struct inbound_queue_table *circularQ; | ||
| 4589 | |||
| 4590 | memset(&payload, 0, sizeof(payload)); | ||
| 4591 | |||
| 4592 | rc = pm8001_tag_alloc(pm8001_ha, &tag); | ||
| 4593 | if (rc) | ||
| 4594 | PM8001_INIT_DBG(pm8001_ha, pm8001_printk("Invalid tag")); | ||
| 4595 | |||
| 4596 | circularQ = &pm8001_ha->inbnd_q_tbl[0]; | ||
| 4597 | opc = OPC_INB_SET_PHY_PROFILE; | ||
| 4598 | |||
| 4599 | payload.tag = cpu_to_le32(tag); | ||
| 4600 | payload.ppc_phyid = (((SAS_PHY_ANALOG_SETTINGS_PAGE & 0xF) << 8) | ||
| 4601 | | (phy & 0xFF)); | ||
| 4602 | |||
| 4603 | for (i = 0; i < length; i++) | ||
| 4604 | payload.reserved[i] = cpu_to_le32(*(buf + i)); | ||
| 4605 | |||
| 4606 | rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); | ||
| 4607 | if (rc) | ||
| 4608 | pm8001_tag_free(pm8001_ha, tag); | ||
| 4609 | |||
| 4610 | PM8001_INIT_DBG(pm8001_ha, | ||
| 4611 | pm8001_printk("PHY %d settings applied", phy)); | ||
| 4612 | } | ||
| 4579 | const struct pm8001_dispatch pm8001_80xx_dispatch = { | 4613 | const struct pm8001_dispatch pm8001_80xx_dispatch = { |
| 4580 | .name = "pmc80xx", | 4614 | .name = "pmc80xx", |
| 4581 | .chip_init = pm80xx_chip_init, | 4615 | .chip_init = pm80xx_chip_init, |
