aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wilcox <matthew@wil.cx>2007-10-02 21:55:25 -0400
committerJames Bottomley <jejb@mulgrave.localdomain>2007-10-12 14:53:02 -0400
commit05848b6e66ee237c4496c2b49821d2622b0f677e (patch)
tree49055abae9e9387934be0734aa8ff3eb3ee4664d
parent41d2493d3478942f891b21dff60951ff939c08d9 (diff)
[SCSI] advansys: Fix simultaneous calls to ->queuecommand
The narrow board used two global structures to set up a command; unfortunately they weren't locked, so with two boards in the machine, one call to queuecommand could corrupt the data being used by the other call to queuecommand. Fix this by allocating asc_scsi_q on the stack (64 bytes) and using kmalloc for the asc_sg_head (2k) Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/advansys.c88
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
386typedef struct asc_scsi_q { 386typedef 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. */
2560static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 }; 2560static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
2561 2561
2562/*
2563 * Global structures required to issue a command.
2564 */
2565static ASC_SCSI_Q asc_scsi_q = { {0} };
2566static ASC_SG_HEAD asc_sg_head = { 0 };
2567
2568#ifdef ADVANSYS_DEBUG 2562#ifdef ADVANSYS_DEBUG
2569static int asc_dbglvl = 3; 2563static 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/* 10189static 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 */
10203static 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;