diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/advansys.c | 88 |
1 files changed, 39 insertions, 49 deletions
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 3dd785617602..fd4d6695fea9 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c | |||
@@ -380,7 +380,7 @@ typedef struct asc_sg_head { | |||
380 | ushort queue_cnt; | 380 | ushort queue_cnt; |
381 | ushort entry_to_copy; | 381 | ushort entry_to_copy; |
382 | ushort res; | 382 | ushort res; |
383 | ASC_SG_LIST sg_list[ASC_MAX_SG_LIST]; | 383 | ASC_SG_LIST sg_list[0]; |
384 | } ASC_SG_HEAD; | 384 | } ASC_SG_HEAD; |
385 | 385 | ||
386 | typedef struct asc_scsi_q { | 386 | typedef struct asc_scsi_q { |
@@ -2559,12 +2559,6 @@ static int asc_board_count; | |||
2559 | /* Overrun buffer used by all narrow boards. */ | 2559 | /* Overrun buffer used by all narrow boards. */ |
2560 | static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 }; | 2560 | static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 }; |
2561 | 2561 | ||
2562 | /* | ||
2563 | * Global structures required to issue a command. | ||
2564 | */ | ||
2565 | static ASC_SCSI_Q asc_scsi_q = { {0} }; | ||
2566 | static ASC_SG_HEAD asc_sg_head = { 0 }; | ||
2567 | |||
2568 | #ifdef ADVANSYS_DEBUG | 2562 | #ifdef ADVANSYS_DEBUG |
2569 | static int asc_dbglvl = 3; | 2563 | static int asc_dbglvl = 3; |
2570 | 2564 | ||
@@ -10192,39 +10186,28 @@ static int advansys_slave_configure(struct scsi_device *sdev) | |||
10192 | return 0; | 10186 | return 0; |
10193 | } | 10187 | } |
10194 | 10188 | ||
10195 | /* | 10189 | static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp, |
10196 | * Build a request structure for the Asc Library (Narrow Board). | 10190 | struct asc_scsi_q *asc_scsi_q) |
10197 | * | ||
10198 | * The global structures 'asc_scsi_q' and 'asc_sg_head' are | ||
10199 | * used to build the request. | ||
10200 | * | ||
10201 | * If an error occurs, then return ASC_ERROR. | ||
10202 | */ | ||
10203 | static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) | ||
10204 | { | 10191 | { |
10205 | /* | 10192 | memset(asc_scsi_q, 0, sizeof(*asc_scsi_q)); |
10206 | * Mutually exclusive access is required to 'asc_scsi_q' and | ||
10207 | * 'asc_sg_head' until after the request is started. | ||
10208 | */ | ||
10209 | memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q)); | ||
10210 | 10193 | ||
10211 | /* | 10194 | /* |
10212 | * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'. | 10195 | * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'. |
10213 | */ | 10196 | */ |
10214 | asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp); | 10197 | asc_scsi_q->q2.srb_ptr = ASC_VADDR_TO_U32(scp); |
10215 | 10198 | ||
10216 | /* | 10199 | /* |
10217 | * Build the ASC_SCSI_Q request. | 10200 | * Build the ASC_SCSI_Q request. |
10218 | */ | 10201 | */ |
10219 | asc_scsi_q.cdbptr = &scp->cmnd[0]; | 10202 | asc_scsi_q->cdbptr = &scp->cmnd[0]; |
10220 | asc_scsi_q.q2.cdb_len = scp->cmd_len; | 10203 | asc_scsi_q->q2.cdb_len = scp->cmd_len; |
10221 | asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id); | 10204 | asc_scsi_q->q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id); |
10222 | asc_scsi_q.q1.target_lun = scp->device->lun; | 10205 | asc_scsi_q->q1.target_lun = scp->device->lun; |
10223 | asc_scsi_q.q2.target_ix = | 10206 | asc_scsi_q->q2.target_ix = |
10224 | ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun); | 10207 | ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun); |
10225 | asc_scsi_q.q1.sense_addr = | 10208 | asc_scsi_q->q1.sense_addr = |
10226 | cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); | 10209 | cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); |
10227 | asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer); | 10210 | asc_scsi_q->q1.sense_len = sizeof(scp->sense_buffer); |
10228 | 10211 | ||
10229 | /* | 10212 | /* |
10230 | * If there are any outstanding requests for the current target, | 10213 | * If there are any outstanding requests for the current target, |
@@ -10239,9 +10222,9 @@ static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) | |||
10239 | */ | 10222 | */ |
10240 | if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) && | 10223 | if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) && |
10241 | (boardp->reqcnt[scp->device->id] % 255) == 0) { | 10224 | (boardp->reqcnt[scp->device->id] % 255) == 0) { |
10242 | asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG; | 10225 | asc_scsi_q->q2.tag_code = MSG_ORDERED_TAG; |
10243 | } else { | 10226 | } else { |
10244 | asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG; | 10227 | asc_scsi_q->q2.tag_code = MSG_SIMPLE_TAG; |
10245 | } | 10228 | } |
10246 | 10229 | ||
10247 | /* | 10230 | /* |
@@ -10257,12 +10240,12 @@ static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) | |||
10257 | dma_map_single(boardp->dev, scp->request_buffer, | 10240 | dma_map_single(boardp->dev, scp->request_buffer, |
10258 | scp->request_bufflen, | 10241 | scp->request_bufflen, |
10259 | scp->sc_data_direction) : 0; | 10242 | scp->sc_data_direction) : 0; |
10260 | asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle); | 10243 | asc_scsi_q->q1.data_addr = cpu_to_le32(scp->SCp.dma_handle); |
10261 | asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen); | 10244 | asc_scsi_q->q1.data_cnt = cpu_to_le32(scp->request_bufflen); |
10262 | ASC_STATS_ADD(scp->device->host, cont_xfer, | 10245 | ASC_STATS_ADD(scp->device->host, cont_xfer, |
10263 | ASC_CEILING(scp->request_bufflen, 512)); | 10246 | ASC_CEILING(scp->request_bufflen, 512)); |
10264 | asc_scsi_q.q1.sg_queue_cnt = 0; | 10247 | asc_scsi_q->q1.sg_queue_cnt = 0; |
10265 | asc_scsi_q.sg_head = NULL; | 10248 | asc_scsi_q->sg_head = NULL; |
10266 | } else { | 10249 | } else { |
10267 | /* | 10250 | /* |
10268 | * CDB scatter-gather request list. | 10251 | * CDB scatter-gather request list. |
@@ -10270,6 +10253,7 @@ static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) | |||
10270 | int sgcnt; | 10253 | int sgcnt; |
10271 | int use_sg; | 10254 | int use_sg; |
10272 | struct scatterlist *slp; | 10255 | struct scatterlist *slp; |
10256 | struct asc_sg_head *asc_sg_head; | ||
10273 | 10257 | ||
10274 | slp = (struct scatterlist *)scp->request_buffer; | 10258 | slp = (struct scatterlist *)scp->request_buffer; |
10275 | use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg, | 10259 | use_sg = dma_map_sg(boardp->dev, slp, scp->use_sg, |
@@ -10287,28 +10271,31 @@ static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) | |||
10287 | 10271 | ||
10288 | ASC_STATS(scp->device->host, sg_cnt); | 10272 | ASC_STATS(scp->device->host, sg_cnt); |
10289 | 10273 | ||
10290 | /* | 10274 | asc_sg_head = kzalloc(sizeof(asc_scsi_q->sg_head) + |
10291 | * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q | 10275 | use_sg * sizeof(struct asc_sg_list), GFP_ATOMIC); |
10292 | * structure to point to it. | 10276 | if (!asc_sg_head) { |
10293 | */ | 10277 | dma_unmap_sg(boardp->dev, slp, scp->use_sg, |
10294 | memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD)); | 10278 | scp->sc_data_direction); |
10279 | scp->result = HOST_BYTE(DID_SOFT_ERROR); | ||
10280 | return ASC_ERROR; | ||
10281 | } | ||
10295 | 10282 | ||
10296 | asc_scsi_q.q1.cntl |= QC_SG_HEAD; | 10283 | asc_scsi_q->q1.cntl |= QC_SG_HEAD; |
10297 | asc_scsi_q.sg_head = &asc_sg_head; | 10284 | asc_scsi_q->sg_head = asc_sg_head; |
10298 | asc_scsi_q.q1.data_cnt = 0; | 10285 | asc_scsi_q->q1.data_cnt = 0; |
10299 | asc_scsi_q.q1.data_addr = 0; | 10286 | asc_scsi_q->q1.data_addr = 0; |
10300 | /* This is a byte value, otherwise it would need to be swapped. */ | 10287 | /* This is a byte value, otherwise it would need to be swapped. */ |
10301 | asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg; | 10288 | asc_sg_head->entry_cnt = asc_scsi_q->q1.sg_queue_cnt = use_sg; |
10302 | ASC_STATS_ADD(scp->device->host, sg_elem, | 10289 | ASC_STATS_ADD(scp->device->host, sg_elem, |
10303 | asc_sg_head.entry_cnt); | 10290 | asc_sg_head->entry_cnt); |
10304 | 10291 | ||
10305 | /* | 10292 | /* |
10306 | * Convert scatter-gather list into ASC_SG_HEAD list. | 10293 | * Convert scatter-gather list into ASC_SG_HEAD list. |
10307 | */ | 10294 | */ |
10308 | for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) { | 10295 | for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) { |
10309 | asc_sg_head.sg_list[sgcnt].addr = | 10296 | asc_sg_head->sg_list[sgcnt].addr = |
10310 | cpu_to_le32(sg_dma_address(slp)); | 10297 | cpu_to_le32(sg_dma_address(slp)); |
10311 | asc_sg_head.sg_list[sgcnt].bytes = | 10298 | asc_sg_head->sg_list[sgcnt].bytes = |
10312 | cpu_to_le32(sg_dma_len(slp)); | 10299 | cpu_to_le32(sg_dma_len(slp)); |
10313 | ASC_STATS_ADD(scp->device->host, sg_xfer, | 10300 | ASC_STATS_ADD(scp->device->host, sg_xfer, |
10314 | ASC_CEILING(sg_dma_len(slp), 512)); | 10301 | ASC_CEILING(sg_dma_len(slp), 512)); |
@@ -11338,14 +11325,17 @@ static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) | |||
11338 | 11325 | ||
11339 | if (ASC_NARROW_BOARD(boardp)) { | 11326 | if (ASC_NARROW_BOARD(boardp)) { |
11340 | ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var; | 11327 | ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var; |
11328 | struct asc_scsi_q asc_scsi_q; | ||
11341 | 11329 | ||
11342 | /* asc_build_req() can not return ASC_BUSY. */ | 11330 | /* asc_build_req() can not return ASC_BUSY. */ |
11343 | if (asc_build_req(boardp, scp) == ASC_ERROR) { | 11331 | ret = asc_build_req(boardp, scp, &asc_scsi_q); |
11332 | if (ret == ASC_ERROR) { | ||
11344 | ASC_STATS(scp->device->host, build_error); | 11333 | ASC_STATS(scp->device->host, build_error); |
11345 | return ASC_ERROR; | 11334 | return ASC_ERROR; |
11346 | } | 11335 | } |
11347 | 11336 | ||
11348 | ret = AscExeScsiQueue(asc_dvc, &asc_scsi_q); | 11337 | ret = AscExeScsiQueue(asc_dvc, &asc_scsi_q); |
11338 | kfree(asc_scsi_q.sg_head); | ||
11349 | err_code = asc_dvc->err_code; | 11339 | err_code = asc_dvc->err_code; |
11350 | } else { | 11340 | } else { |
11351 | ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var; | 11341 | ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var; |