diff options
author | Jens Axboe <jens.axboe@oracle.com> | 2007-05-09 07:02:43 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2007-10-16 05:14:18 -0400 |
commit | a0441891373fe2db582075a4639fdfcccea470c1 (patch) | |
tree | 3455f63574e8053875e73611c87e6582970a3276 /drivers/scsi/qla1280.c | |
parent | b0f655d0ef02468232b69acad1d935db921db46b (diff) |
qla1280: sg chaining support
Interesting hardware setup...
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/scsi/qla1280.c')
-rw-r--r-- | drivers/scsi/qla1280.c | 66 |
1 files changed, 37 insertions, 29 deletions
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index fba8aa8a81b5..1f17dec7d6fc 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c | |||
@@ -2775,7 +2775,7 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
2775 | struct device_reg __iomem *reg = ha->iobase; | 2775 | struct device_reg __iomem *reg = ha->iobase; |
2776 | struct scsi_cmnd *cmd = sp->cmd; | 2776 | struct scsi_cmnd *cmd = sp->cmd; |
2777 | cmd_a64_entry_t *pkt; | 2777 | cmd_a64_entry_t *pkt; |
2778 | struct scatterlist *sg = NULL; | 2778 | struct scatterlist *sg = NULL, *s; |
2779 | __le32 *dword_ptr; | 2779 | __le32 *dword_ptr; |
2780 | dma_addr_t dma_handle; | 2780 | dma_addr_t dma_handle; |
2781 | int status = 0; | 2781 | int status = 0; |
@@ -2889,13 +2889,16 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
2889 | * Load data segments. | 2889 | * Load data segments. |
2890 | */ | 2890 | */ |
2891 | if (seg_cnt) { /* If data transfer. */ | 2891 | if (seg_cnt) { /* If data transfer. */ |
2892 | int remseg = seg_cnt; | ||
2892 | /* Setup packet address segment pointer. */ | 2893 | /* Setup packet address segment pointer. */ |
2893 | dword_ptr = (u32 *)&pkt->dseg_0_address; | 2894 | dword_ptr = (u32 *)&pkt->dseg_0_address; |
2894 | 2895 | ||
2895 | if (cmd->use_sg) { /* If scatter gather */ | 2896 | if (cmd->use_sg) { /* If scatter gather */ |
2896 | /* Load command entry data segments. */ | 2897 | /* Load command entry data segments. */ |
2897 | for (cnt = 0; cnt < 2 && seg_cnt; cnt++, seg_cnt--) { | 2898 | for_each_sg(sg, s, seg_cnt, cnt) { |
2898 | dma_handle = sg_dma_address(sg); | 2899 | if (cnt == 2) |
2900 | break; | ||
2901 | dma_handle = sg_dma_address(s); | ||
2899 | #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) | 2902 | #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) |
2900 | if (ha->flags.use_pci_vchannel) | 2903 | if (ha->flags.use_pci_vchannel) |
2901 | sn_pci_set_vchan(ha->pdev, | 2904 | sn_pci_set_vchan(ha->pdev, |
@@ -2906,12 +2909,12 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
2906 | cpu_to_le32(pci_dma_lo32(dma_handle)); | 2909 | cpu_to_le32(pci_dma_lo32(dma_handle)); |
2907 | *dword_ptr++ = | 2910 | *dword_ptr++ = |
2908 | cpu_to_le32(pci_dma_hi32(dma_handle)); | 2911 | cpu_to_le32(pci_dma_hi32(dma_handle)); |
2909 | *dword_ptr++ = cpu_to_le32(sg_dma_len(sg)); | 2912 | *dword_ptr++ = cpu_to_le32(sg_dma_len(s)); |
2910 | sg++; | ||
2911 | dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n", | 2913 | dprintk(3, "S/G Segment phys_addr=%x %x, len=0x%x\n", |
2912 | cpu_to_le32(pci_dma_hi32(dma_handle)), | 2914 | cpu_to_le32(pci_dma_hi32(dma_handle)), |
2913 | cpu_to_le32(pci_dma_lo32(dma_handle)), | 2915 | cpu_to_le32(pci_dma_lo32(dma_handle)), |
2914 | cpu_to_le32(sg_dma_len(sg))); | 2916 | cpu_to_le32(sg_dma_len(sg_next(s)))); |
2917 | remseg--; | ||
2915 | } | 2918 | } |
2916 | dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather " | 2919 | dprintk(5, "qla1280_64bit_start_scsi: Scatter/gather " |
2917 | "command packet data - b %i, t %i, l %i \n", | 2920 | "command packet data - b %i, t %i, l %i \n", |
@@ -2926,7 +2929,9 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
2926 | dprintk(3, "S/G Building Continuation...seg_cnt=0x%x " | 2929 | dprintk(3, "S/G Building Continuation...seg_cnt=0x%x " |
2927 | "remains\n", seg_cnt); | 2930 | "remains\n", seg_cnt); |
2928 | 2931 | ||
2929 | while (seg_cnt > 0) { | 2932 | while (remseg > 0) { |
2933 | /* Update sg start */ | ||
2934 | sg = s; | ||
2930 | /* Adjust ring index. */ | 2935 | /* Adjust ring index. */ |
2931 | ha->req_ring_index++; | 2936 | ha->req_ring_index++; |
2932 | if (ha->req_ring_index == REQUEST_ENTRY_CNT) { | 2937 | if (ha->req_ring_index == REQUEST_ENTRY_CNT) { |
@@ -2952,9 +2957,10 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
2952 | (u32 *)&((struct cont_a64_entry *) pkt)->dseg_0_address; | 2957 | (u32 *)&((struct cont_a64_entry *) pkt)->dseg_0_address; |
2953 | 2958 | ||
2954 | /* Load continuation entry data segments. */ | 2959 | /* Load continuation entry data segments. */ |
2955 | for (cnt = 0; cnt < 5 && seg_cnt; | 2960 | for_each_sg(sg, s, remseg, cnt) { |
2956 | cnt++, seg_cnt--) { | 2961 | if (cnt == 5) |
2957 | dma_handle = sg_dma_address(sg); | 2962 | break; |
2963 | dma_handle = sg_dma_address(s); | ||
2958 | #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) | 2964 | #if defined(CONFIG_IA64_GENERIC) || defined(CONFIG_IA64_SGI_SN2) |
2959 | if (ha->flags.use_pci_vchannel) | 2965 | if (ha->flags.use_pci_vchannel) |
2960 | sn_pci_set_vchan(ha->pdev, | 2966 | sn_pci_set_vchan(ha->pdev, |
@@ -2966,12 +2972,12 @@ qla1280_64bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
2966 | *dword_ptr++ = | 2972 | *dword_ptr++ = |
2967 | cpu_to_le32(pci_dma_hi32(dma_handle)); | 2973 | cpu_to_le32(pci_dma_hi32(dma_handle)); |
2968 | *dword_ptr++ = | 2974 | *dword_ptr++ = |
2969 | cpu_to_le32(sg_dma_len(sg)); | 2975 | cpu_to_le32(sg_dma_len(s)); |
2970 | dprintk(3, "S/G Segment Cont. phys_addr=%x %x, len=0x%x\n", | 2976 | dprintk(3, "S/G Segment Cont. phys_addr=%x %x, len=0x%x\n", |
2971 | cpu_to_le32(pci_dma_hi32(dma_handle)), | 2977 | cpu_to_le32(pci_dma_hi32(dma_handle)), |
2972 | cpu_to_le32(pci_dma_lo32(dma_handle)), | 2978 | cpu_to_le32(pci_dma_lo32(dma_handle)), |
2973 | cpu_to_le32(sg_dma_len(sg))); | 2979 | cpu_to_le32(sg_dma_len(s))); |
2974 | sg++; | 2980 | remseg--; |
2975 | } | 2981 | } |
2976 | dprintk(5, "qla1280_64bit_start_scsi: " | 2982 | dprintk(5, "qla1280_64bit_start_scsi: " |
2977 | "continuation packet data - b %i, t " | 2983 | "continuation packet data - b %i, t " |
@@ -3062,7 +3068,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
3062 | struct device_reg __iomem *reg = ha->iobase; | 3068 | struct device_reg __iomem *reg = ha->iobase; |
3063 | struct scsi_cmnd *cmd = sp->cmd; | 3069 | struct scsi_cmnd *cmd = sp->cmd; |
3064 | struct cmd_entry *pkt; | 3070 | struct cmd_entry *pkt; |
3065 | struct scatterlist *sg = NULL; | 3071 | struct scatterlist *sg = NULL, *s; |
3066 | __le32 *dword_ptr; | 3072 | __le32 *dword_ptr; |
3067 | int status = 0; | 3073 | int status = 0; |
3068 | int cnt; | 3074 | int cnt; |
@@ -3188,6 +3194,7 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
3188 | * Load data segments. | 3194 | * Load data segments. |
3189 | */ | 3195 | */ |
3190 | if (seg_cnt) { | 3196 | if (seg_cnt) { |
3197 | int remseg = seg_cnt; | ||
3191 | /* Setup packet address segment pointer. */ | 3198 | /* Setup packet address segment pointer. */ |
3192 | dword_ptr = &pkt->dseg_0_address; | 3199 | dword_ptr = &pkt->dseg_0_address; |
3193 | 3200 | ||
@@ -3196,22 +3203,25 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
3196 | qla1280_dump_buffer(1, (char *)sg, 4 * 16); | 3203 | qla1280_dump_buffer(1, (char *)sg, 4 * 16); |
3197 | 3204 | ||
3198 | /* Load command entry data segments. */ | 3205 | /* Load command entry data segments. */ |
3199 | for (cnt = 0; cnt < 4 && seg_cnt; cnt++, seg_cnt--) { | 3206 | for_each_sg(sg, s, seg_cnt, cnt) { |
3207 | if (cnt == 4) | ||
3208 | break; | ||
3200 | *dword_ptr++ = | 3209 | *dword_ptr++ = |
3201 | cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); | 3210 | cpu_to_le32(pci_dma_lo32(sg_dma_address(s))); |
3202 | *dword_ptr++ = | 3211 | *dword_ptr++ = cpu_to_le32(sg_dma_len(s)); |
3203 | cpu_to_le32(sg_dma_len(sg)); | ||
3204 | dprintk(3, "S/G Segment phys_addr=0x%lx, len=0x%x\n", | 3212 | dprintk(3, "S/G Segment phys_addr=0x%lx, len=0x%x\n", |
3205 | (pci_dma_lo32(sg_dma_address(sg))), | 3213 | (pci_dma_lo32(sg_dma_address(s))), |
3206 | (sg_dma_len(sg))); | 3214 | (sg_dma_len(s))); |
3207 | sg++; | 3215 | remseg--; |
3208 | } | 3216 | } |
3209 | /* | 3217 | /* |
3210 | * Build continuation packets. | 3218 | * Build continuation packets. |
3211 | */ | 3219 | */ |
3212 | dprintk(3, "S/G Building Continuation" | 3220 | dprintk(3, "S/G Building Continuation" |
3213 | "...seg_cnt=0x%x remains\n", seg_cnt); | 3221 | "...seg_cnt=0x%x remains\n", seg_cnt); |
3214 | while (seg_cnt > 0) { | 3222 | while (remseg > 0) { |
3223 | /* Continue from end point */ | ||
3224 | sg = s; | ||
3215 | /* Adjust ring index. */ | 3225 | /* Adjust ring index. */ |
3216 | ha->req_ring_index++; | 3226 | ha->req_ring_index++; |
3217 | if (ha->req_ring_index == REQUEST_ENTRY_CNT) { | 3227 | if (ha->req_ring_index == REQUEST_ENTRY_CNT) { |
@@ -3239,18 +3249,16 @@ qla1280_32bit_start_scsi(struct scsi_qla_host *ha, struct srb * sp) | |||
3239 | &((struct cont_entry *) pkt)->dseg_0_address; | 3249 | &((struct cont_entry *) pkt)->dseg_0_address; |
3240 | 3250 | ||
3241 | /* Load continuation entry data segments. */ | 3251 | /* Load continuation entry data segments. */ |
3242 | for (cnt = 0; cnt < 7 && seg_cnt; | 3252 | for_each_sg(sg, s, remseg, cnt) { |
3243 | cnt++, seg_cnt--) { | ||
3244 | *dword_ptr++ = | 3253 | *dword_ptr++ = |
3245 | cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))); | 3254 | cpu_to_le32(pci_dma_lo32(sg_dma_address(s))); |
3246 | *dword_ptr++ = | 3255 | *dword_ptr++ = |
3247 | cpu_to_le32(sg_dma_len(sg)); | 3256 | cpu_to_le32(sg_dma_len(s)); |
3248 | dprintk(1, | 3257 | dprintk(1, |
3249 | "S/G Segment Cont. phys_addr=0x%x, " | 3258 | "S/G Segment Cont. phys_addr=0x%x, " |
3250 | "len=0x%x\n", | 3259 | "len=0x%x\n", |
3251 | cpu_to_le32(pci_dma_lo32(sg_dma_address(sg))), | 3260 | cpu_to_le32(pci_dma_lo32(sg_dma_address(s))), |
3252 | cpu_to_le32(sg_dma_len(sg))); | 3261 | cpu_to_le32(sg_dma_len(s))); |
3253 | sg++; | ||
3254 | } | 3262 | } |
3255 | dprintk(5, "qla1280_32bit_start_scsi: " | 3263 | dprintk(5, "qla1280_32bit_start_scsi: " |
3256 | "continuation packet data - " | 3264 | "continuation packet data - " |