diff options
author | Yang, Bo <Bo.Yang@lsi.com> | 2009-10-06 16:43:28 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-10-29 13:03:20 -0400 |
commit | f4c9a1317d32bb0af7546ef0c1dcc3be52dc8d0a (patch) | |
tree | 2c0f83b914aaf34902365d244728d6a22808bfd7 /drivers/scsi/megaraid/megaraid_sas.c | |
parent | 7bebf5c79cb62766c76c6c1b9c77b86496fd363e (diff) |
[SCSI] megaraid_sas: add the IEEE SGE support to SAS2 controller
To increase the performance, megaraid sas driver added the IEEE SGE
support to support SAS2 controller.
Signed-off-by Bo Yang<bo.yang@lsi.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas.c')
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 80 |
1 files changed, 73 insertions, 7 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 5afd65121725..4c04a68bad6c 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c | |||
@@ -696,6 +696,35 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
696 | return sge_count; | 696 | return sge_count; |
697 | } | 697 | } |
698 | 698 | ||
699 | /** | ||
700 | * megasas_make_sgl_skinny - Prepares IEEE SGL | ||
701 | * @instance: Adapter soft state | ||
702 | * @scp: SCSI command from the mid-layer | ||
703 | * @mfi_sgl: SGL to be filled in | ||
704 | * | ||
705 | * If successful, this function returns the number of SG elements. Otherwise, | ||
706 | * it returnes -1. | ||
707 | */ | ||
708 | static int | ||
709 | megasas_make_sgl_skinny(struct megasas_instance *instance, | ||
710 | struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl) | ||
711 | { | ||
712 | int i; | ||
713 | int sge_count; | ||
714 | struct scatterlist *os_sgl; | ||
715 | |||
716 | sge_count = scsi_dma_map(scp); | ||
717 | |||
718 | if (sge_count) { | ||
719 | scsi_for_each_sg(scp, os_sgl, sge_count, i) { | ||
720 | mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl); | ||
721 | mfi_sgl->sge_skinny[i].phys_addr = | ||
722 | sg_dma_address(os_sgl); | ||
723 | } | ||
724 | } | ||
725 | return sge_count; | ||
726 | } | ||
727 | |||
699 | /** | 728 | /** |
700 | * megasas_get_frame_count - Computes the number of frames | 729 | * megasas_get_frame_count - Computes the number of frames |
701 | * @frame_type : type of frame- io or pthru frame | 730 | * @frame_type : type of frame- io or pthru frame |
@@ -704,7 +733,8 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
704 | * Returns the number of frames required for numnber of sge's (sge_count) | 733 | * Returns the number of frames required for numnber of sge's (sge_count) |
705 | */ | 734 | */ |
706 | 735 | ||
707 | static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type) | 736 | static u32 megasas_get_frame_count(struct megasas_instance *instance, |
737 | u8 sge_count, u8 frame_type) | ||
708 | { | 738 | { |
709 | int num_cnt; | 739 | int num_cnt; |
710 | int sge_bytes; | 740 | int sge_bytes; |
@@ -714,6 +744,10 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type) | |||
714 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : | 744 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : |
715 | sizeof(struct megasas_sge32); | 745 | sizeof(struct megasas_sge32); |
716 | 746 | ||
747 | if (instance->flag_ieee) { | ||
748 | sge_sz = sizeof(struct megasas_sge_skinny); | ||
749 | } | ||
750 | |||
717 | /* | 751 | /* |
718 | * Main frame can contain 2 SGEs for 64-bit SGLs and | 752 | * Main frame can contain 2 SGEs for 64-bit SGLs and |
719 | * 3 SGEs for 32-bit SGLs for ldio & | 753 | * 3 SGEs for 32-bit SGLs for ldio & |
@@ -721,12 +755,16 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type) | |||
721 | * 2 SGEs for 32-bit SGLs for pthru frame | 755 | * 2 SGEs for 32-bit SGLs for pthru frame |
722 | */ | 756 | */ |
723 | if (unlikely(frame_type == PTHRU_FRAME)) { | 757 | if (unlikely(frame_type == PTHRU_FRAME)) { |
724 | if (IS_DMA64) | 758 | if (instance->flag_ieee == 1) { |
759 | num_cnt = sge_count - 1; | ||
760 | } else if (IS_DMA64) | ||
725 | num_cnt = sge_count - 1; | 761 | num_cnt = sge_count - 1; |
726 | else | 762 | else |
727 | num_cnt = sge_count - 2; | 763 | num_cnt = sge_count - 2; |
728 | } else { | 764 | } else { |
729 | if (IS_DMA64) | 765 | if (instance->flag_ieee == 1) { |
766 | num_cnt = sge_count - 1; | ||
767 | } else if (IS_DMA64) | ||
730 | num_cnt = sge_count - 2; | 768 | num_cnt = sge_count - 2; |
731 | else | 769 | else |
732 | num_cnt = sge_count - 3; | 770 | num_cnt = sge_count - 3; |
@@ -775,6 +813,10 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
775 | else if (scp->sc_data_direction == PCI_DMA_NONE) | 813 | else if (scp->sc_data_direction == PCI_DMA_NONE) |
776 | flags = MFI_FRAME_DIR_NONE; | 814 | flags = MFI_FRAME_DIR_NONE; |
777 | 815 | ||
816 | if (instance->flag_ieee == 1) { | ||
817 | flags |= MFI_FRAME_IEEE; | ||
818 | } | ||
819 | |||
778 | /* | 820 | /* |
779 | * Prepare the DCDB frame | 821 | * Prepare the DCDB frame |
780 | */ | 822 | */ |
@@ -804,7 +846,11 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
804 | /* | 846 | /* |
805 | * Construct SGL | 847 | * Construct SGL |
806 | */ | 848 | */ |
807 | if (IS_DMA64) { | 849 | if (instance->flag_ieee == 1) { |
850 | pthru->flags |= MFI_FRAME_SGL64; | ||
851 | pthru->sge_count = megasas_make_sgl_skinny(instance, scp, | ||
852 | &pthru->sgl); | ||
853 | } else if (IS_DMA64) { | ||
808 | pthru->flags |= MFI_FRAME_SGL64; | 854 | pthru->flags |= MFI_FRAME_SGL64; |
809 | pthru->sge_count = megasas_make_sgl64(instance, scp, | 855 | pthru->sge_count = megasas_make_sgl64(instance, scp, |
810 | &pthru->sgl); | 856 | &pthru->sgl); |
@@ -823,7 +869,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
823 | * Compute the total number of frames this command consumes. FW uses | 869 | * Compute the total number of frames this command consumes. FW uses |
824 | * this number to pull sufficient number of frames from host memory. | 870 | * this number to pull sufficient number of frames from host memory. |
825 | */ | 871 | */ |
826 | cmd->frame_count = megasas_get_frame_count(pthru->sge_count, | 872 | cmd->frame_count = megasas_get_frame_count(instance, pthru->sge_count, |
827 | PTHRU_FRAME); | 873 | PTHRU_FRAME); |
828 | 874 | ||
829 | return cmd->frame_count; | 875 | return cmd->frame_count; |
@@ -854,6 +900,10 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
854 | else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) | 900 | else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) |
855 | flags = MFI_FRAME_DIR_READ; | 901 | flags = MFI_FRAME_DIR_READ; |
856 | 902 | ||
903 | if (instance->flag_ieee == 1) { | ||
904 | flags |= MFI_FRAME_IEEE; | ||
905 | } | ||
906 | |||
857 | /* | 907 | /* |
858 | * Prepare the Logical IO frame: 2nd bit is zero for all read cmds | 908 | * Prepare the Logical IO frame: 2nd bit is zero for all read cmds |
859 | */ | 909 | */ |
@@ -924,7 +974,11 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
924 | /* | 974 | /* |
925 | * Construct SGL | 975 | * Construct SGL |
926 | */ | 976 | */ |
927 | if (IS_DMA64) { | 977 | if (instance->flag_ieee) { |
978 | ldio->flags |= MFI_FRAME_SGL64; | ||
979 | ldio->sge_count = megasas_make_sgl_skinny(instance, scp, | ||
980 | &ldio->sgl); | ||
981 | } else if (IS_DMA64) { | ||
928 | ldio->flags |= MFI_FRAME_SGL64; | 982 | ldio->flags |= MFI_FRAME_SGL64; |
929 | ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); | 983 | ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); |
930 | } else | 984 | } else |
@@ -941,7 +995,8 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
941 | * Compute the total number of frames this command consumes. FW uses | 995 | * Compute the total number of frames this command consumes. FW uses |
942 | * this number to pull sufficient number of frames from host memory. | 996 | * this number to pull sufficient number of frames from host memory. |
943 | */ | 997 | */ |
944 | cmd->frame_count = megasas_get_frame_count(ldio->sge_count, IO_FRAME); | 998 | cmd->frame_count = megasas_get_frame_count(instance, |
999 | ldio->sge_count, IO_FRAME); | ||
945 | 1000 | ||
946 | return cmd->frame_count; | 1001 | return cmd->frame_count; |
947 | } | 1002 | } |
@@ -1929,6 +1984,10 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) | |||
1929 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : | 1984 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : |
1930 | sizeof(struct megasas_sge32); | 1985 | sizeof(struct megasas_sge32); |
1931 | 1986 | ||
1987 | if (instance->flag_ieee) { | ||
1988 | sge_sz = sizeof(struct megasas_sge_skinny); | ||
1989 | } | ||
1990 | |||
1932 | /* | 1991 | /* |
1933 | * Calculated the number of 64byte frames required for SGL | 1992 | * Calculated the number of 64byte frames required for SGL |
1934 | */ | 1993 | */ |
@@ -2725,6 +2784,11 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, | |||
2725 | dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h; | 2784 | dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h; |
2726 | dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail); | 2785 | dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail); |
2727 | 2786 | ||
2787 | if (instance->aen_cmd != NULL) { | ||
2788 | megasas_return_cmd(instance, cmd); | ||
2789 | return 0; | ||
2790 | } | ||
2791 | |||
2728 | /* | 2792 | /* |
2729 | * Store reference to the cmd used to register for AEN. When an | 2793 | * Store reference to the cmd used to register for AEN. When an |
2730 | * application wants us to register for AEN, we have to abort this | 2794 | * application wants us to register for AEN, we have to abort this |
@@ -2895,6 +2959,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2895 | *instance->producer = 0; | 2959 | *instance->producer = 0; |
2896 | *instance->consumer = 0; | 2960 | *instance->consumer = 0; |
2897 | megasas_poll_wait_aen = 0; | 2961 | megasas_poll_wait_aen = 0; |
2962 | instance->flag_ieee = 0; | ||
2898 | 2963 | ||
2899 | instance->evt_detail = pci_alloc_consistent(pdev, | 2964 | instance->evt_detail = pci_alloc_consistent(pdev, |
2900 | sizeof(struct | 2965 | sizeof(struct |
@@ -2933,6 +2998,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2933 | 2998 | ||
2934 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | 2999 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
2935 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | 3000 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { |
3001 | instance->flag_ieee = 1; | ||
2936 | sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS); | 3002 | sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS); |
2937 | } else | 3003 | } else |
2938 | sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); | 3004 | sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); |