From d3301874083874f8a0ac88aa1bb7da6b62df34d2 Mon Sep 17 00:00:00 2001 From: Mike Anderson Date: Thu, 16 Jun 2005 11:12:38 -0700 Subject: [SCSI] host state model update: replace old host bitmap state Migrate the current SCSI host state model to a model like SCSI device is using. Signed-off-by: Mike Anderson Rejections fixed up and Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7a91ca3d32a..060010bccab 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -348,7 +348,7 @@ void scsi_device_unbusy(struct scsi_device *sdev) spin_lock_irqsave(shost->host_lock, flags); shost->host_busy--; - if (unlikely(test_bit(SHOST_RECOVERY, &shost->shost_state) && + if (unlikely((shost->shost_state == SHOST_RECOVERY) && shost->host_failed)) scsi_eh_wakeup(shost); spin_unlock(shost->host_lock); @@ -1207,7 +1207,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, struct Scsi_Host *shost, struct scsi_device *sdev) { - if (test_bit(SHOST_RECOVERY, &shost->shost_state)) + if (shost->shost_state == SHOST_RECOVERY) return 0; if (shost->host_busy == 0 && shost->host_blocked) { /* -- cgit v1.2.3-70-g09d2 From e537a36d528053f6b9dbe6c88e763e835c0d3517 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 5 Jun 2005 02:07:14 -0500 Subject: [SCSI] use scatter lists for all block pc requests and simplify hw handlers Here's the proof of concept for this one. It converts scsi_wait_req to do correct REQ_BLOCK_PC submission (and works nicely in my setup). The final goal should be to eliminate struct scsi_request, but that can't be done until the character submission paths of sg and st are also modified. There's some loss of functionality to this: retries are no longer controllable (except by setting REQ_FASTFAIL) and the wait_req API needs to be altered, but it looks very nice. Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 96 ++++++++++++++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 37 deletions(-) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7a91ca3d32a..253c1a98d15 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -232,23 +232,6 @@ void scsi_do_req(struct scsi_request *sreq, const void *cmnd, } EXPORT_SYMBOL(scsi_do_req); -static void scsi_wait_done(struct scsi_cmnd *cmd) -{ - struct request *req = cmd->request; - struct request_queue *q = cmd->device->request_queue; - unsigned long flags; - - req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */ - - spin_lock_irqsave(q->queue_lock, flags); - if (blk_rq_tagged(req)) - blk_queue_end_tag(q, req); - spin_unlock_irqrestore(q->queue_lock, flags); - - if (req->waiting) - complete(req->waiting); -} - /* This is the end routine we get to if a command was never attached * to the request. Simply complete the request without changing * rq_status; this will cause a DRIVER_ERROR. */ @@ -263,19 +246,36 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer, unsigned bufflen, int timeout, int retries) { DECLARE_COMPLETION(wait); - - sreq->sr_request->waiting = &wait; - sreq->sr_request->rq_status = RQ_SCSI_BUSY; - sreq->sr_request->end_io = scsi_wait_req_end_io; - scsi_do_req(sreq, cmnd, buffer, bufflen, scsi_wait_done, - timeout, retries); + struct request *req; + + if (bufflen) + req = blk_rq_map_kern(sreq->sr_device->request_queue, + sreq->sr_data_direction == DMA_TO_DEVICE, + buffer, bufflen, __GFP_WAIT); + else + req = blk_get_request(sreq->sr_device->request_queue, READ, + __GFP_WAIT); + req->flags |= REQ_NOMERGE; + req->waiting = &wait; + req->end_io = scsi_wait_req_end_io; + req->cmd_len = COMMAND_SIZE(((u8 *)cmnd)[0]); + req->sense = sreq->sr_sense_buffer; + req->sense_len = 0; + memcpy(req->cmd, cmnd, req->cmd_len); + req->timeout = timeout; + req->flags |= REQ_BLOCK_PC; + req->rq_disk = NULL; + blk_insert_request(sreq->sr_device->request_queue, req, + sreq->sr_data_direction == DMA_TO_DEVICE, NULL); wait_for_completion(&wait); sreq->sr_request->waiting = NULL; - if (sreq->sr_request->rq_status != RQ_SCSI_DONE) + sreq->sr_result = req->errors; + if (req->errors) sreq->sr_result |= (DRIVER_ERROR << 24); - __scsi_release_request(sreq); + blk_put_request(req); } + EXPORT_SYMBOL(scsi_wait_req); /* @@ -878,11 +878,12 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, return; } if (result) { - printk(KERN_INFO "SCSI error : <%d %d %d %d> return code " - "= 0x%x\n", cmd->device->host->host_no, - cmd->device->channel, - cmd->device->id, - cmd->device->lun, result); + if (!(req->flags & REQ_SPECIAL)) + printk(KERN_INFO "SCSI error : <%d %d %d %d> return code " + "= 0x%x\n", cmd->device->host->host_no, + cmd->device->channel, + cmd->device->id, + cmd->device->lun, result); if (driver_byte(result) & DRIVER_SENSE) scsi_print_sense("", cmd); @@ -1020,6 +1021,12 @@ static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk, return -EOPNOTSUPP; } +static void scsi_generic_done(struct scsi_cmnd *cmd) +{ + BUG_ON(!blk_pc_request(cmd->request)); + scsi_io_completion(cmd, cmd->result == 0 ? cmd->bufflen : 0, 0); +} + static int scsi_prep_fn(struct request_queue *q, struct request *req) { struct scsi_device *sdev = q->queuedata; @@ -1061,7 +1068,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) * these two cases differently. We differentiate by looking * at request->cmd, as this tells us the real story. */ - if (req->flags & REQ_SPECIAL) { + if (req->flags & REQ_SPECIAL && req->special) { struct scsi_request *sreq = req->special; if (sreq->sr_magic == SCSI_REQ_MAGIC) { @@ -1073,7 +1080,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) cmd = req->special; } else if (req->flags & (REQ_CMD | REQ_BLOCK_PC)) { - if(unlikely(specials_only)) { + if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) { if(specials_only == SDEV_QUIESCE || specials_only == SDEV_BLOCK) return BLKPREP_DEFER; @@ -1142,11 +1149,26 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) /* * Initialize the actual SCSI command for this request. */ - drv = *(struct scsi_driver **)req->rq_disk->private_data; - if (unlikely(!drv->init_command(cmd))) { - scsi_release_buffers(cmd); - scsi_put_command(cmd); - return BLKPREP_KILL; + if (req->rq_disk) { + drv = *(struct scsi_driver **)req->rq_disk->private_data; + if (unlikely(!drv->init_command(cmd))) { + scsi_release_buffers(cmd); + scsi_put_command(cmd); + return BLKPREP_KILL; + } + } else { + memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); + if (rq_data_dir(req) == WRITE) + cmd->sc_data_direction = DMA_TO_DEVICE; + else if (req->data_len) + cmd->sc_data_direction = DMA_FROM_DEVICE; + else + cmd->sc_data_direction = DMA_NONE; + + cmd->transfersize = req->data_len; + cmd->allowed = 3; + cmd->timeout_per_command = req->timeout; + cmd->done = scsi_generic_done; } } -- cgit v1.2.3-70-g09d2 From 8e6401187ef7fb1edc2740832b48bf47ed2c90f2 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 15 Jun 2005 18:16:09 -0500 Subject: update scsi_wait_req to new format for blk_rq_map_kern() Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 253c1a98d15..60f07b6a5ff 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -246,15 +246,18 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer, unsigned bufflen, int timeout, int retries) { DECLARE_COMPLETION(wait); + int write = sreq->sr_data_direction == DMA_TO_DEVICE; struct request *req; - if (bufflen) - req = blk_rq_map_kern(sreq->sr_device->request_queue, - sreq->sr_data_direction == DMA_TO_DEVICE, - buffer, bufflen, __GFP_WAIT); - else - req = blk_get_request(sreq->sr_device->request_queue, READ, - __GFP_WAIT); + req = blk_get_request(sreq->sr_device->request_queue, write, + __GFP_WAIT); + if (bufflen && blk_rq_map_kern(sreq->sr_device->request_queue, req, + buffer, bufflen, __GFP_WAIT)) { + sreq->sr_result = DRIVER_ERROR << 24; + blk_put_request(req); + return; + } + req->flags |= REQ_NOMERGE; req->waiting = &wait; req->end_io = scsi_wait_req_end_io; -- cgit v1.2.3-70-g09d2 From 392160335c798bbe94ab3aae6ea0c85d32b81bbc Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 15 Jun 2005 18:48:29 -0500 Subject: [SCSI] use scatter lists for all block pc requests and simplify hw handlers Original From: Mike Christie Add scsi_execute_req() as a replacement for scsi_wait_req() Fixed up various pieces (added REQ_SPECIAL and caught req use after free) Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 51 +++++++++++++++++++- drivers/scsi/scsi_scan.c | 112 +++++++++++++++++++------------------------- include/scsi/scsi_request.h | 3 ++ 3 files changed, 102 insertions(+), 64 deletions(-) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 60f07b6a5ff..b8212c563fe 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -246,7 +246,7 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer, unsigned bufflen, int timeout, int retries) { DECLARE_COMPLETION(wait); - int write = sreq->sr_data_direction == DMA_TO_DEVICE; + int write = (sreq->sr_data_direction == DMA_TO_DEVICE); struct request *req; req = blk_get_request(sreq->sr_device->request_queue, write, @@ -281,6 +281,55 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer, EXPORT_SYMBOL(scsi_wait_req); +/** + * scsi_execute_req - insert request and wait for the result + * @sdev: scsi device + * @cmd: scsi command + * @data_direction: data direction + * @buffer: data buffer + * @bufflen: len of buffer + * @sense: optional sense buffer + * @timeout: request timeout in seconds + * @retries: number of times to retry request + * + * scsi_execute_req returns the req->errors value which is the + * the scsi_cmnd result field. + **/ +int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd, + int data_direction, void *buffer, unsigned bufflen, + unsigned char *sense, int timeout, int retries) +{ + struct request *req; + int write = (data_direction == DMA_TO_DEVICE); + int ret = DRIVER_ERROR << 24; + + req = blk_get_request(sdev->request_queue, write, __GFP_WAIT); + + if (bufflen && blk_rq_map_kern(sdev->request_queue, req, + buffer, bufflen, __GFP_WAIT)) + goto out; + + req->cmd_len = COMMAND_SIZE(cmd[0]); + memcpy(req->cmd, cmd, req->cmd_len); + req->sense = sense; + req->sense_len = 0; + req->timeout = timeout; + req->flags |= REQ_BLOCK_PC | REQ_SPECIAL; + + /* + * head injection *required* here otherwise quiesce won't work + */ + blk_execute_rq(req->q, NULL, req, 1); + + ret = req->errors; + out: + blk_put_request(req); + + return ret; +} + +EXPORT_SYMBOL(scsi_execute_req); + /* * Function: scsi_init_cmd_errh() * diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 48edd67982a..d2ca4b8fbc1 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -111,15 +111,14 @@ MODULE_PARM_DESC(inq_timeout, /** * scsi_unlock_floptical - unlock device via a special MODE SENSE command - * @sreq: used to send the command + * @sdev: scsi device to send command to * @result: area to store the result of the MODE SENSE * * Description: - * Send a vendor specific MODE SENSE (not a MODE SELECT) command using - * @sreq to unlock a device, storing the (unused) results into result. + * Send a vendor specific MODE SENSE (not a MODE SELECT) command. * Called for BLIST_KEY devices. **/ -static void scsi_unlock_floptical(struct scsi_request *sreq, +static void scsi_unlock_floptical(struct scsi_device *sdev, unsigned char *result) { unsigned char scsi_cmd[MAX_COMMAND_SIZE]; @@ -129,11 +128,10 @@ static void scsi_unlock_floptical(struct scsi_request *sreq, scsi_cmd[1] = 0; scsi_cmd[2] = 0x2e; scsi_cmd[3] = 0; - scsi_cmd[4] = 0x2a; /* size */ + scsi_cmd[4] = 0x2a; /* size */ scsi_cmd[5] = 0; - sreq->sr_cmd_len = 0; - sreq->sr_data_direction = DMA_FROM_DEVICE; - scsi_wait_req(sreq, scsi_cmd, result, 0x2a /* size */, SCSI_TIMEOUT, 3); + scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, result, 0x2a, NULL, + SCSI_TIMEOUT, 3); } /** @@ -433,26 +431,26 @@ void scsi_target_reap(struct scsi_target *starget) /** * scsi_probe_lun - probe a single LUN using a SCSI INQUIRY - * @sreq: used to send the INQUIRY + * @sdev: scsi_device to probe * @inq_result: area to store the INQUIRY result + * @result_len: len of inq_result * @bflags: store any bflags found here * * Description: - * Probe the lun associated with @sreq using a standard SCSI INQUIRY; + * Probe the lun associated with @req using a standard SCSI INQUIRY; * - * If the INQUIRY is successful, sreq->sr_result is zero and: the + * If the INQUIRY is successful, zero is returned and the * INQUIRY data is in @inq_result; the scsi_level and INQUIRY length - * are copied to the Scsi_Device at @sreq->sr_device (sdev); - * any flags value is stored in *@bflags. + * are copied to the Scsi_Device any flags value is stored in *@bflags. **/ -static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, - int *bflags) +static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result, + int result_len, int *bflags) { - struct scsi_device *sdev = sreq->sr_device; /* a bit ugly */ + char sense[SCSI_SENSE_BUFFERSIZE]; unsigned char scsi_cmd[MAX_COMMAND_SIZE]; int first_inquiry_len, try_inquiry_len, next_inquiry_len; int response_len = 0; - int pass, count; + int pass, count, result; struct scsi_sense_hdr sshdr; *bflags = 0; @@ -475,28 +473,28 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, memset(scsi_cmd, 0, 6); scsi_cmd[0] = INQUIRY; scsi_cmd[4] = (unsigned char) try_inquiry_len; - sreq->sr_cmd_len = 0; - sreq->sr_data_direction = DMA_FROM_DEVICE; + memset(sense, 0, sizeof(sense)); memset(inq_result, 0, try_inquiry_len); - scsi_wait_req(sreq, (void *) scsi_cmd, (void *) inq_result, - try_inquiry_len, - HZ/2 + HZ*scsi_inq_timeout, 3); + + result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, + inq_result, try_inquiry_len, sense, + HZ / 2 + HZ * scsi_inq_timeout, 3); SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " "with code 0x%x\n", - sreq->sr_result ? "failed" : "successful", - sreq->sr_result)); + result ? "failed" : "successful", result)); - if (sreq->sr_result) { + if (result) { /* * not-ready to ready transition [asc/ascq=0x28/0x0] * or power-on, reset [asc/ascq=0x29/0x0], continue. * INQUIRY should not yield UNIT_ATTENTION * but many buggy devices do so anyway. */ - if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && - scsi_request_normalize_sense(sreq, &sshdr)) { + if ((driver_byte(result) & DRIVER_SENSE) && + scsi_normalize_sense(sense, sizeof(sense), + &sshdr)) { if ((sshdr.sense_key == UNIT_ATTENTION) && ((sshdr.asc == 0x28) || (sshdr.asc == 0x29)) && @@ -507,7 +505,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, break; } - if (sreq->sr_result == 0) { + if (result == 0) { response_len = (unsigned char) inq_result[4] + 5; if (response_len > 255) response_len = first_inquiry_len; /* sanity */ @@ -556,8 +554,8 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, /* If the last transfer attempt got an error, assume the * peripheral doesn't exist or is dead. */ - if (sreq->sr_result) - return; + if (result) + return -EIO; /* Don't report any more data than the device says is valid */ sdev->inquiry_len = min(try_inquiry_len, response_len); @@ -593,7 +591,7 @@ static void scsi_probe_lun(struct scsi_request *sreq, char *inq_result, (sdev->scsi_level == 1 && (inq_result[3] & 0x0f) == 1)) sdev->scsi_level++; - return; + return 0; } /** @@ -800,9 +798,8 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, void *hostdata) { struct scsi_device *sdev; - struct scsi_request *sreq; unsigned char *result; - int bflags, res = SCSI_SCAN_NO_RESPONSE; + int bflags, res = SCSI_SCAN_NO_RESPONSE, result_len = 256; struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); /* @@ -831,16 +828,13 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, sdev = scsi_alloc_sdev(starget, lun, hostdata); if (!sdev) goto out; - sreq = scsi_allocate_request(sdev, GFP_ATOMIC); - if (!sreq) - goto out_free_sdev; - result = kmalloc(256, GFP_ATOMIC | + + result = kmalloc(result_len, GFP_ATOMIC | ((shost->unchecked_isa_dma) ? __GFP_DMA : 0)); if (!result) - goto out_free_sreq; + goto out_free_sdev; - scsi_probe_lun(sreq, result, &bflags); - if (sreq->sr_result) + if (scsi_probe_lun(sdev, result, result_len, &bflags)) goto out_free_result; /* @@ -868,7 +862,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, if (res == SCSI_SCAN_LUN_PRESENT) { if (bflags & BLIST_KEY) { sdev->lockable = 0; - scsi_unlock_floptical(sreq, result); + scsi_unlock_floptical(sdev, result); } if (bflagsp) *bflagsp = bflags; @@ -876,8 +870,6 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, out_free_result: kfree(result); - out_free_sreq: - scsi_release_request(sreq); out_free_sdev: if (res == SCSI_SCAN_LUN_PRESENT) { if (sdevp) { @@ -1065,13 +1057,14 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, int rescan) { char devname[64]; + char sense[SCSI_SENSE_BUFFERSIZE]; unsigned char scsi_cmd[MAX_COMMAND_SIZE]; unsigned int length; unsigned int lun; unsigned int num_luns; unsigned int retries; + int result; struct scsi_lun *lunp, *lun_data; - struct scsi_request *sreq; u8 *data; struct scsi_sense_hdr sshdr; struct scsi_target *starget = scsi_target(sdev); @@ -1089,10 +1082,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, if (bflags & BLIST_NOLUN) return 0; - sreq = scsi_allocate_request(sdev, GFP_ATOMIC); - if (!sreq) - goto out; - sprintf(devname, "host %d channel %d id %d", sdev->host->host_no, sdev->channel, sdev->id); @@ -1110,7 +1099,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, lun_data = kmalloc(length, GFP_ATOMIC | (sdev->host->unchecked_isa_dma ? __GFP_DMA : 0)); if (!lun_data) - goto out_release_request; + goto out; scsi_cmd[0] = REPORT_LUNS; @@ -1129,8 +1118,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, scsi_cmd[10] = 0; /* reserved */ scsi_cmd[11] = 0; /* control */ - sreq->sr_cmd_len = 0; - sreq->sr_data_direction = DMA_FROM_DEVICE; /* * We can get a UNIT ATTENTION, for example a power on/reset, so @@ -1146,29 +1133,30 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" " REPORT LUNS to %s (try %d)\n", devname, retries)); - scsi_wait_req(sreq, scsi_cmd, lun_data, length, - SCSI_TIMEOUT + 4*HZ, 3); + + memset(sense, 0, sizeof(sense)); + result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, + lun_data, length, sense, + SCSI_TIMEOUT + 4 * HZ, 3); + SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" - " %s (try %d) result 0x%x\n", sreq->sr_result - ? "failed" : "successful", retries, - sreq->sr_result)); - if (sreq->sr_result == 0) + " %s (try %d) result 0x%x\n", result + ? "failed" : "successful", retries, result)); + if (result == 0) break; - else if (scsi_request_normalize_sense(sreq, &sshdr)) { + else if (scsi_normalize_sense(sense, sizeof(sense), &sshdr)) { if (sshdr.sense_key != UNIT_ATTENTION) break; } } - if (sreq->sr_result) { + if (result) { /* * The device probably does not support a REPORT LUN command */ kfree(lun_data); - scsi_release_request(sreq); return 1; } - scsi_release_request(sreq); /* * Get the length from the first four bytes of lun_data. @@ -1242,8 +1230,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, kfree(lun_data); return 0; - out_release_request: - scsi_release_request(sreq); out: /* * We are out of memory, don't try scanning any further. diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h index 98719407d55..d64903a617c 100644 --- a/include/scsi/scsi_request.h +++ b/include/scsi/scsi_request.h @@ -54,6 +54,9 @@ extern void scsi_do_req(struct scsi_request *, const void *cmnd, void *buffer, unsigned bufflen, void (*done) (struct scsi_cmnd *), int timeout, int retries); +extern int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd, + int data_direction, void *buffer, unsigned bufflen, + unsigned char *sense, int timeout, int retries); struct scsi_mode_data { __u32 length; -- cgit v1.2.3-70-g09d2 From 1cf72699c1530c3e4ac3d58344f6a6a40a2f46d3 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 28 Aug 2005 11:27:01 -0500 Subject: [SCSI] convert the remaining mid-layer pieces to scsi_execute_req After this, we just have some drivers, all the ULDs and the SPI transport class using scsi_wait_req(). Signed-off-by: James Bottomley --- drivers/scsi/scsi_ioctl.c | 46 ++++++++-------------- drivers/scsi/scsi_lib.c | 94 ++++++++++++++++----------------------------- drivers/scsi/sd.c | 5 ++- drivers/scsi/sr.c | 2 +- include/scsi/scsi_device.h | 13 ++++++- include/scsi/scsi_request.h | 15 -------- 6 files changed, 64 insertions(+), 111 deletions(-) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index f5bf5c07be9..5f399c9c68e 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -88,25 +88,21 @@ static int ioctl_probe(struct Scsi_Host *host, void __user *buffer) static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, int timeout, int retries) { - struct scsi_request *sreq; int result; struct scsi_sense_hdr sshdr; + char sense[SCSI_SENSE_BUFFERSIZE]; SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); - sreq = scsi_allocate_request(sdev, GFP_KERNEL); - if (!sreq) { - printk(KERN_WARNING "SCSI internal ioctl failed, no memory\n"); - return -ENOMEM; - } - sreq->sr_data_direction = DMA_NONE; - scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); + memset(sense, 0, sizeof(*sense)); + result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, + sense, timeout, retries); - SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", sreq->sr_result)); + SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", result)); - if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && - (scsi_request_normalize_sense(sreq, &sshdr))) { + if ((driver_byte(result) & DRIVER_SENSE) && + (scsi_normalize_sense(sense, sizeof(*sense), &sshdr))) { switch (sshdr.sense_key) { case ILLEGAL_REQUEST: if (cmd[0] == ALLOW_MEDIUM_REMOVAL) @@ -125,7 +121,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, case UNIT_ATTENTION: if (sdev->removable) { sdev->changed = 1; - sreq->sr_result = 0; /* This is no longer considered an error */ + result = 0; /* This is no longer considered an error */ break; } default: /* Fall through for non-removable media */ @@ -135,15 +131,13 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, sdev->channel, sdev->id, sdev->lun, - sreq->sr_result); - scsi_print_req_sense(" ", sreq); + result); + __scsi_print_sense(" ", sense, sizeof(*sense)); break; } } - result = sreq->sr_result; SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); - scsi_release_request(sreq); return result; } @@ -208,8 +202,8 @@ int scsi_ioctl_send_command(struct scsi_device *sdev, { char *buf; unsigned char cmd[MAX_COMMAND_SIZE]; + unsigned char sense[SCSI_SENSE_BUFFERSIZE]; char __user *cmd_in; - struct scsi_request *sreq; unsigned char opcode; unsigned int inlen, outlen, cmdlen; unsigned int needed, buf_needed; @@ -321,31 +315,23 @@ int scsi_ioctl_send_command(struct scsi_device *sdev, break; } - sreq = scsi_allocate_request(sdev, GFP_KERNEL); - if (!sreq) { - result = -EINTR; - goto error; - } - - sreq->sr_data_direction = data_direction; - scsi_wait_req(sreq, cmd, buf, needed, timeout, retries); - + result = scsi_execute_req(sdev, cmd, data_direction, buf, needed, + sense, timeout, retries); + /* * If there was an error condition, pass the info back to the user. */ - result = sreq->sr_result; if (result) { - int sb_len = sizeof(sreq->sr_sense_buffer); + int sb_len = sizeof(*sense); sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len; - if (copy_to_user(cmd_in, sreq->sr_sense_buffer, sb_len)) + if (copy_to_user(cmd_in, sense, sb_len)) result = -EFAULT; } else { if (copy_to_user(cmd_in, buf, outlen)) result = -EFAULT; } - scsi_release_request(sreq); error: kfree(buf); return result; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 278e0c99b2a..3f3accd6cd4 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1615,7 +1615,7 @@ void scsi_exit_queue(void) /** * __scsi_mode_sense - issue a mode sense, falling back from 10 to * six bytes if necessary. - * @sreq: SCSI request to fill in with the MODE_SENSE + * @sdev: SCSI device to be queried * @dbd: set if mode sense will allow block descriptors to be returned * @modepage: mode page being requested * @buffer: request buffer (may not be smaller than eight bytes) @@ -1623,26 +1623,38 @@ void scsi_exit_queue(void) * @timeout: command timeout * @retries: number of retries before failing * @data: returns a structure abstracting the mode header data + * @sense: place to put sense data (or NULL if no sense to be collected). + * must be SCSI_SENSE_BUFFERSIZE big. * * Returns zero if unsuccessful, or the header offset (either 4 * or 8 depending on whether a six or ten byte command was * issued) if successful. **/ int -__scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, +scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char *buffer, int len, int timeout, int retries, - struct scsi_mode_data *data) { + struct scsi_mode_data *data, char *sense) { unsigned char cmd[12]; int use_10_for_ms; int header_length; + int result; + char *sense_buffer = NULL; memset(data, 0, sizeof(*data)); memset(&cmd[0], 0, 12); cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */ cmd[2] = modepage; + if (!sense) { + sense_buffer = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); + if (!sense_buffer) { + dev_printk(KERN_ERR, &sdev->sdev_gendev, "failed to allocate sense buffer\n"); + return 0; + } + sense = sense_buffer; + } retry: - use_10_for_ms = sreq->sr_device->use_10_for_ms; + use_10_for_ms = sdev->use_10_for_ms; if (use_10_for_ms) { if (len < 8) @@ -1660,36 +1672,35 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, header_length = 4; } - sreq->sr_cmd_len = 0; - memset(sreq->sr_sense_buffer, 0, sizeof(sreq->sr_sense_buffer)); - sreq->sr_data_direction = DMA_FROM_DEVICE; + memset(sense, 0, SCSI_SENSE_BUFFERSIZE); memset(buffer, 0, len); - scsi_wait_req(sreq, cmd, buffer, len, timeout, retries); + result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, + sense, timeout, retries); /* This code looks awful: what it's doing is making sure an * ILLEGAL REQUEST sense return identifies the actual command * byte as the problem. MODE_SENSE commands can return * ILLEGAL REQUEST if the code page isn't supported */ - if (use_10_for_ms && !scsi_status_is_good(sreq->sr_result) && - (driver_byte(sreq->sr_result) & DRIVER_SENSE)) { + if (use_10_for_ms && !scsi_status_is_good(result) && + (driver_byte(result) & DRIVER_SENSE)) { struct scsi_sense_hdr sshdr; - if (scsi_request_normalize_sense(sreq, &sshdr)) { + if (scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) { if ((sshdr.sense_key == ILLEGAL_REQUEST) && (sshdr.asc == 0x20) && (sshdr.ascq == 0)) { /* * Invalid command operation code */ - sreq->sr_device->use_10_for_ms = 0; + sdev->use_10_for_ms = 0; goto retry; } } } - if(scsi_status_is_good(sreq->sr_result)) { + if(scsi_status_is_good(result)) { data->header_length = header_length; if(use_10_for_ms) { data->length = buffer[0]*256 + buffer[1] + 2; @@ -1706,73 +1717,34 @@ __scsi_mode_sense(struct scsi_request *sreq, int dbd, int modepage, } } - return sreq->sr_result; -} -EXPORT_SYMBOL(__scsi_mode_sense); - -/** - * scsi_mode_sense - issue a mode sense, falling back from 10 to - * six bytes if necessary. - * @sdev: scsi device to send command to. - * @dbd: set if mode sense will disable block descriptors in the return - * @modepage: mode page being requested - * @buffer: request buffer (may not be smaller than eight bytes) - * @len: length of request buffer. - * @timeout: command timeout - * @retries: number of retries before failing - * - * Returns zero if unsuccessful, or the header offset (either 4 - * or 8 depending on whether a six or ten byte command was - * issued) if successful. - **/ -int -scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, - unsigned char *buffer, int len, int timeout, int retries, - struct scsi_mode_data *data) -{ - struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); - int ret; - - if (!sreq) - return -1; - - ret = __scsi_mode_sense(sreq, dbd, modepage, buffer, len, - timeout, retries, data); - - scsi_release_request(sreq); - - return ret; + kfree(sense_buffer); + return result; } EXPORT_SYMBOL(scsi_mode_sense); int scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries) { - struct scsi_request *sreq; char cmd[] = { TEST_UNIT_READY, 0, 0, 0, 0, 0, }; + char sense[SCSI_SENSE_BUFFERSIZE]; int result; - sreq = scsi_allocate_request(sdev, GFP_KERNEL); - if (!sreq) - return -ENOMEM; - - sreq->sr_data_direction = DMA_NONE; - scsi_wait_req(sreq, cmd, NULL, 0, timeout, retries); + result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, sense, + timeout, retries); - if ((driver_byte(sreq->sr_result) & DRIVER_SENSE) && sdev->removable) { + if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) { struct scsi_sense_hdr sshdr; - if ((scsi_request_normalize_sense(sreq, &sshdr)) && + if ((scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, + &sshdr)) && ((sshdr.sense_key == UNIT_ATTENTION) || (sshdr.sense_key == NOT_READY))) { sdev->changed = 1; - sreq->sr_result = 0; + result = 0; } } - result = sreq->sr_result; - scsi_release_request(sreq); return result; } EXPORT_SYMBOL(scsi_test_unit_ready); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 0410e1bf109..15c2039059c 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1299,8 +1299,9 @@ static inline int sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage, unsigned char *buffer, int len, struct scsi_mode_data *data) { - return __scsi_mode_sense(SRpnt, dbd, modepage, buffer, len, - SD_TIMEOUT, SD_MAX_RETRIES, data); + return scsi_mode_sense(SRpnt->sr_device, dbd, modepage, buffer, len, + SD_TIMEOUT, SD_MAX_RETRIES, data, + SRpnt->sr_sense_buffer); } /* diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 2f259f24952..8cbe6e00418 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -817,7 +817,7 @@ static void get_capabilities(struct scsi_cd *cd) /* ask for mode page 0x2a */ rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128, - SR_TIMEOUT, 3, &data); + SR_TIMEOUT, 3, &data, NULL); if (!scsi_status_is_good(rc)) { /* failed, drive doesn't have capabilities mode page */ diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 835af8ecbb7..9181068883c 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -8,9 +8,17 @@ struct request_queue; struct scsi_cmnd; -struct scsi_mode_data; struct scsi_lun; +struct scsi_mode_data { + __u32 length; + __u16 block_descriptor_length; + __u8 medium_type; + __u8 device_specific; + __u8 header_length; + __u8 longlba:1; +}; + /* * sdev state: If you alter this, you also need to alter scsi_sysfs.c * (for the ascii descriptions) and the state model enforcer: @@ -228,7 +236,8 @@ extern int scsi_set_medium_removal(struct scsi_device *, char); extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char *buffer, int len, int timeout, - int retries, struct scsi_mode_data *data); + int retries, struct scsi_mode_data *data, + char *sense); extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries); extern int scsi_device_set_state(struct scsi_device *sdev, diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h index d64903a617c..f5dfdfec9fe 100644 --- a/include/scsi/scsi_request.h +++ b/include/scsi/scsi_request.h @@ -58,19 +58,4 @@ extern int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd, int data_direction, void *buffer, unsigned bufflen, unsigned char *sense, int timeout, int retries); -struct scsi_mode_data { - __u32 length; - __u16 block_descriptor_length; - __u8 medium_type; - __u8 device_specific; - __u8 header_length; - __u8 longlba:1; -}; - -extern int __scsi_mode_sense(struct scsi_request *SRpnt, int dbd, - int modepage, unsigned char *buffer, int len, - int timeout, int retries, - struct scsi_mode_data *data); - - #endif /* _SCSI_SCSI_REQUEST_H */ -- cgit v1.2.3-70-g09d2 From 33aa687db90dd8541bd5e9a762eebf880eaee767 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 28 Aug 2005 11:31:14 -0500 Subject: [SCSI] convert SPI transport class to scsi_execute This one's slightly more difficult. The transport class uses REQ_FAILFAST, so another interface (scsi_execute) had to be invented to take the extra flag. Also, the sense functions are shifted around to allow spi_execute to place data directly into a struct scsi_sense_hdr. With this change, there's probably a lot of unnecessary sense buffer allocation going on which we can fix later. Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 6 +- drivers/scsi/scsi_lib.c | 13 ++-- drivers/scsi/scsi_transport_spi.c | 124 ++++++++++++++++++-------------------- include/scsi/scsi_device.h | 13 ++++ include/scsi/scsi_eh.h | 8 +++ include/scsi/scsi_request.h | 4 -- 6 files changed, 90 insertions(+), 78 deletions(-) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index e9c451ba71f..2686d5672e5 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1847,12 +1847,16 @@ EXPORT_SYMBOL(scsi_reset_provider); int scsi_normalize_sense(const u8 *sense_buffer, int sb_len, struct scsi_sense_hdr *sshdr) { - if (!sense_buffer || !sb_len || (sense_buffer[0] & 0x70) != 0x70) + if (!sense_buffer || !sb_len) return 0; memset(sshdr, 0, sizeof(struct scsi_sense_hdr)); sshdr->response_code = (sense_buffer[0] & 0x7f); + + if (!scsi_sense_valid(sshdr)) + return 0; + if (sshdr->response_code >= 0x72) { /* * descriptor format diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 3f3accd6cd4..42edf29223a 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -282,7 +282,7 @@ void scsi_wait_req(struct scsi_request *sreq, const void *cmnd, void *buffer, EXPORT_SYMBOL(scsi_wait_req); /** - * scsi_execute_req - insert request and wait for the result + * scsi_execute - insert request and wait for the result * @sdev: scsi device * @cmd: scsi command * @data_direction: data direction @@ -291,13 +291,14 @@ EXPORT_SYMBOL(scsi_wait_req); * @sense: optional sense buffer * @timeout: request timeout in seconds * @retries: number of times to retry request + * @flags: or into request flags; * * scsi_execute_req returns the req->errors value which is the * the scsi_cmnd result field. **/ -int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd, - int data_direction, void *buffer, unsigned bufflen, - unsigned char *sense, int timeout, int retries) +int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, + int data_direction, void *buffer, unsigned bufflen, + unsigned char *sense, int timeout, int retries, int flags) { struct request *req; int write = (data_direction == DMA_TO_DEVICE); @@ -314,7 +315,7 @@ int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd, req->sense = sense; req->sense_len = 0; req->timeout = timeout; - req->flags |= REQ_BLOCK_PC | REQ_SPECIAL; + req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL; /* * head injection *required* here otherwise quiesce won't work @@ -328,7 +329,7 @@ int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd, return ret; } -EXPORT_SYMBOL(scsi_execute_req); +EXPORT_SYMBOL(scsi_execute); /* * Function: scsi_init_cmd_errh() diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 89f6b7feb9c..874042f1899 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -28,7 +28,7 @@ #include "scsi_priv.h" #include #include -#include +#include #include #include #include @@ -108,25 +108,33 @@ static int sprint_frac(char *dest, int value, int denom) /* Modification of scsi_wait_req that will clear UNIT ATTENTION conditions * resulting from (likely) bus and device resets */ -static void spi_wait_req(struct scsi_request *sreq, const void *cmd, - void *buffer, unsigned bufflen) +static int spi_execute(struct scsi_device *sdev, const void *cmd, + enum dma_data_direction dir, + void *buffer, unsigned bufflen, + struct scsi_sense_hdr *sshdr) { - int i; + int i, result; + unsigned char sense[SCSI_SENSE_BUFFERSIZE]; for(i = 0; i < DV_RETRIES; i++) { - sreq->sr_request->flags |= REQ_FAILFAST; - - scsi_wait_req(sreq, cmd, buffer, bufflen, - DV_TIMEOUT, /* retries */ 1); - if (sreq->sr_result & DRIVER_SENSE) { - struct scsi_sense_hdr sshdr; - if (scsi_request_normalize_sense(sreq, &sshdr) - && sshdr.sense_key == UNIT_ATTENTION) + /* FIXME: need to set REQ_FAILFAST */ + result = scsi_execute(sdev, cmd, dir, buffer, bufflen, + sense, DV_TIMEOUT, /* retries */ 1, + REQ_FAILFAST); + if (result & DRIVER_SENSE) { + struct scsi_sense_hdr sshdr_tmp; + if (!sshdr) + sshdr = &sshdr_tmp; + + if (scsi_normalize_sense(sense, sizeof(*sense), + sshdr) + && sshdr->sense_key == UNIT_ATTENTION) continue; } break; } + return result; } static struct { @@ -546,13 +554,13 @@ enum spi_compare_returns { /* This is for read/write Domain Validation: If the device supports * an echo buffer, we do read/write tests to it */ static enum spi_compare_returns -spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, +spi_dv_device_echo_buffer(struct scsi_device *sdev, u8 *buffer, u8 *ptr, const int retries) { - struct scsi_device *sdev = sreq->sr_device; int len = ptr - buffer; - int j, k, r; + int j, k, r, result; unsigned int pattern = 0x0000ffff; + struct scsi_sense_hdr sshdr; const char spi_write_buffer[] = { WRITE_BUFFER, 0x0a, 0, 0, 0, 0, 0, len >> 8, len & 0xff, 0 @@ -597,14 +605,12 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, } for (r = 0; r < retries; r++) { - sreq->sr_cmd_len = 0; /* wait_req to fill in */ - sreq->sr_data_direction = DMA_TO_DEVICE; - spi_wait_req(sreq, spi_write_buffer, buffer, len); - if(sreq->sr_result || !scsi_device_online(sdev)) { - struct scsi_sense_hdr sshdr; + result = spi_execute(sdev, spi_write_buffer, DMA_TO_DEVICE, + buffer, len, &sshdr); + if(result || !scsi_device_online(sdev)) { scsi_device_set_state(sdev, SDEV_QUIESCE); - if (scsi_request_normalize_sense(sreq, &sshdr) + if (scsi_sense_valid(&sshdr) && sshdr.sense_key == ILLEGAL_REQUEST /* INVALID FIELD IN CDB */ && sshdr.asc == 0x24 && sshdr.ascq == 0x00) @@ -616,14 +622,13 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, return SPI_COMPARE_SKIP_TEST; - SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result); + SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", result); return SPI_COMPARE_FAILURE; } memset(ptr, 0, len); - sreq->sr_cmd_len = 0; /* wait_req to fill in */ - sreq->sr_data_direction = DMA_FROM_DEVICE; - spi_wait_req(sreq, spi_read_buffer, ptr, len); + spi_execute(sdev, spi_read_buffer, DMA_FROM_DEVICE, + ptr, len, NULL); scsi_device_set_state(sdev, SDEV_QUIESCE); if (memcmp(buffer, ptr, len) != 0) @@ -635,25 +640,22 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer, /* This is for the simplest form of Domain Validation: a read test * on the inquiry data from the device */ static enum spi_compare_returns -spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer, +spi_dv_device_compare_inquiry(struct scsi_device *sdev, u8 *buffer, u8 *ptr, const int retries) { - int r; - const int len = sreq->sr_device->inquiry_len; - struct scsi_device *sdev = sreq->sr_device; + int r, result; + const int len = sdev->inquiry_len; const char spi_inquiry[] = { INQUIRY, 0, 0, 0, len, 0 }; for (r = 0; r < retries; r++) { - sreq->sr_cmd_len = 0; /* wait_req to fill in */ - sreq->sr_data_direction = DMA_FROM_DEVICE; - memset(ptr, 0, len); - spi_wait_req(sreq, spi_inquiry, ptr, len); + result = spi_execute(sdev, spi_inquiry, DMA_FROM_DEVICE, + ptr, len, NULL); - if(sreq->sr_result || !scsi_device_online(sdev)) { + if(result || !scsi_device_online(sdev)) { scsi_device_set_state(sdev, SDEV_QUIESCE); return SPI_COMPARE_FAILURE; } @@ -674,12 +676,11 @@ spi_dv_device_compare_inquiry(struct scsi_request *sreq, u8 *buffer, } static enum spi_compare_returns -spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, +spi_dv_retrain(struct scsi_device *sdev, u8 *buffer, u8 *ptr, enum spi_compare_returns - (*compare_fn)(struct scsi_request *, u8 *, u8 *, int)) + (*compare_fn)(struct scsi_device *, u8 *, u8 *, int)) { - struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); - struct scsi_device *sdev = sreq->sr_device; + struct spi_internal *i = to_spi_internal(sdev->host->transportt); struct scsi_target *starget = sdev->sdev_target; int period = 0, prevperiod = 0; enum spi_compare_returns retval; @@ -687,7 +688,7 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, for (;;) { int newperiod; - retval = compare_fn(sreq, buffer, ptr, DV_LOOPS); + retval = compare_fn(sdev, buffer, ptr, DV_LOOPS); if (retval == SPI_COMPARE_SUCCESS || retval == SPI_COMPARE_SKIP_TEST) @@ -733,9 +734,9 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr, } static int -spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) +spi_dv_device_get_echo_buffer(struct scsi_device *sdev, u8 *buffer) { - int l; + int l, result; /* first off do a test unit ready. This can error out * because of reservations or some other reason. If it @@ -751,18 +752,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) }; - sreq->sr_cmd_len = 0; - sreq->sr_data_direction = DMA_NONE; - /* We send a set of three TURs to clear any outstanding * unit attention conditions if they exist (Otherwise the * buffer tests won't be happy). If the TUR still fails * (reservation conflict, device not ready, etc) just * skip the write tests */ for (l = 0; ; l++) { - spi_wait_req(sreq, spi_test_unit_ready, NULL, 0); + result = spi_execute(sdev, spi_test_unit_ready, DMA_NONE, + NULL, 0, NULL); - if(sreq->sr_result) { + if(result) { if(l >= 3) return 0; } else { @@ -771,12 +770,10 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) } } - sreq->sr_cmd_len = 0; - sreq->sr_data_direction = DMA_FROM_DEVICE; + result = spi_execute(sdev, spi_read_buffer_descriptor, + DMA_FROM_DEVICE, buffer, 4, NULL); - spi_wait_req(sreq, spi_read_buffer_descriptor, buffer, 4); - - if (sreq->sr_result) + if (result) /* Device has no echo buffer */ return 0; @@ -784,17 +781,16 @@ spi_dv_device_get_echo_buffer(struct scsi_request *sreq, u8 *buffer) } static void -spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) +spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) { - struct spi_internal *i = to_spi_internal(sreq->sr_host->transportt); - struct scsi_device *sdev = sreq->sr_device; + struct spi_internal *i = to_spi_internal(sdev->host->transportt); struct scsi_target *starget = sdev->sdev_target; int len = sdev->inquiry_len; /* first set us up for narrow async */ DV_SET(offset, 0); DV_SET(width, 0); - if (spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS) + if (spi_dv_device_compare_inquiry(sdev, buffer, buffer, DV_LOOPS) != SPI_COMPARE_SUCCESS) { SPI_PRINTK(starget, KERN_ERR, "Domain Validation Initial Inquiry Failed\n"); /* FIXME: should probably offline the device here? */ @@ -806,7 +802,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) scsi_device_wide(sdev)) { i->f->set_width(starget, 1); - if (spi_dv_device_compare_inquiry(sreq, buffer, + if (spi_dv_device_compare_inquiry(sdev, buffer, buffer + len, DV_LOOPS) != SPI_COMPARE_SUCCESS) { @@ -827,7 +823,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) len = 0; if (scsi_device_dt(sdev)) - len = spi_dv_device_get_echo_buffer(sreq, buffer); + len = spi_dv_device_get_echo_buffer(sdev, buffer); retry: @@ -853,7 +849,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) if (len == 0) { SPI_PRINTK(starget, KERN_INFO, "Domain Validation skipping write tests\n"); - spi_dv_retrain(sreq, buffer, buffer + len, + spi_dv_retrain(sdev, buffer, buffer + len, spi_dv_device_compare_inquiry); return; } @@ -863,7 +859,7 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) len = SPI_MAX_ECHO_BUFFER_SIZE; } - if (spi_dv_retrain(sreq, buffer, buffer + len, + if (spi_dv_retrain(sdev, buffer, buffer + len, spi_dv_device_echo_buffer) == SPI_COMPARE_SKIP_TEST) { /* OK, the stupid drive can't do a write echo buffer @@ -886,16 +882,12 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer) void spi_dv_device(struct scsi_device *sdev) { - struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL); struct scsi_target *starget = sdev->sdev_target; u8 *buffer; const int len = SPI_MAX_ECHO_BUFFER_SIZE*2; - if (unlikely(!sreq)) - return; - if (unlikely(scsi_device_get(sdev))) - goto out_free_req; + return; buffer = kmalloc(len, GFP_KERNEL); @@ -916,7 +908,7 @@ spi_dv_device(struct scsi_device *sdev) SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n"); - spi_dv_device_internal(sreq, buffer); + spi_dv_device_internal(sdev, buffer); SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n"); @@ -931,8 +923,6 @@ spi_dv_device(struct scsi_device *sdev) kfree(buffer); out_put: scsi_device_put(sdev); - out_free_req: - scsi_release_request(sreq); } EXPORT_SYMBOL(spi_dv_device); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 9181068883c..5ad08b70763 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -256,6 +256,19 @@ extern void int_to_scsilun(unsigned int, struct scsi_lun *); extern const char *scsi_device_state_name(enum scsi_device_state); extern int scsi_is_sdev_device(const struct device *); extern int scsi_is_target_device(const struct device *); +extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, + int data_direction, void *buffer, unsigned bufflen, + unsigned char *sense, int timeout, int retries, + int flag); + +static inline int +scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, + int data_direction, void *buffer, unsigned bufflen, + unsigned char *sense, int timeout, int retries) +{ + return scsi_execute(sdev, cmd, data_direction, buffer, bufflen, sense, + timeout, retries, 0); +} static inline int scsi_device_online(struct scsi_device *sdev) { return sdev->sdev_state != SDEV_OFFLINE; diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index 80557f879e3..b24d224281b 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -26,6 +26,14 @@ struct scsi_sense_hdr { /* See SPC-3 section 4.5 */ u8 additional_length; /* always 0 for fixed sense format */ }; +static inline int scsi_sense_valid(struct scsi_sense_hdr *sshdr) +{ + if (!sshdr) + return 0; + + return (sshdr->response_code & 0x70) == 0x70; +} + extern void scsi_add_timer(struct scsi_cmnd *, int, void (*)(struct scsi_cmnd *)); diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h index f5dfdfec9fe..6a140020d7c 100644 --- a/include/scsi/scsi_request.h +++ b/include/scsi/scsi_request.h @@ -54,8 +54,4 @@ extern void scsi_do_req(struct scsi_request *, const void *cmnd, void *buffer, unsigned bufflen, void (*done) (struct scsi_cmnd *), int timeout, int retries); -extern int scsi_execute_req(struct scsi_device *sdev, unsigned char *cmd, - int data_direction, void *buffer, unsigned bufflen, - unsigned char *sense, int timeout, int retries); - #endif /* _SCSI_SCSI_REQUEST_H */ -- cgit v1.2.3-70-g09d2 From ea73a9f23906c374b697cd5b0d64f6dceced63de Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 28 Aug 2005 11:33:52 -0500 Subject: [SCSI] convert sd to scsi_execute_req (and update the scsi_execute_req API) This one removes struct scsi_request entirely from sd. In the process, I noticed we have no callers of scsi_wait_req who don't immediately normalise the sense, so I updated the API to make it take a struct scsi_sense_hdr instead of simply a big sense buffer. Signed-off-by: James Bottomley --- drivers/scsi/constants.c | 48 +++++++------- drivers/scsi/scsi_ioctl.c | 15 ++--- drivers/scsi/scsi_lib.c | 67 +++++++++++-------- drivers/scsi/scsi_scan.c | 13 ++-- drivers/scsi/sd.c | 160 ++++++++++++++++++--------------------------- include/scsi/scsi_dbg.h | 2 + include/scsi/scsi_device.h | 14 ++-- 7 files changed, 146 insertions(+), 173 deletions(-) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 0d58d3538bd..f6be2c1c394 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1156,6 +1156,31 @@ scsi_show_extd_sense(unsigned char asc, unsigned char ascq) } } +void +scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr) +{ + const char *sense_txt; + /* An example of deferred is when an earlier write to disk cache + * succeeded, but now the disk discovers that it cannot write the + * data to the magnetic media. + */ + const char *error = scsi_sense_is_deferred(sshdr) ? + "<>" : "Current"; + printk(KERN_INFO "%s: %s", name, error); + if (sshdr->response_code >= 0x72) + printk(" [descriptor]"); + + sense_txt = scsi_sense_key_string(sshdr->sense_key); + if (sense_txt) + printk(": sense key: %s\n", sense_txt); + else + printk(": sense key=0x%x\n", sshdr->sense_key); + printk(KERN_INFO " "); + scsi_show_extd_sense(sshdr->asc, sshdr->ascq); + printk("\n"); +} +EXPORT_SYMBOL(scsi_print_sense_hdr); + /* Print sense information */ void __scsi_print_sense(const char *name, const unsigned char *sense_buffer, @@ -1163,8 +1188,6 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer, { int k, num, res; unsigned int info; - const char *error; - const char *sense_txt; struct scsi_sense_hdr ssh; res = scsi_normalize_sense(sense_buffer, sense_len, &ssh); @@ -1182,26 +1205,7 @@ __scsi_print_sense(const char *name, const unsigned char *sense_buffer, printk("\n"); return; } - - /* An example of deferred is when an earlier write to disk cache - * succeeded, but now the disk discovers that it cannot write the - * data to the magnetic media. - */ - error = scsi_sense_is_deferred(&ssh) ? - "<>" : "Current"; - printk(KERN_INFO "%s: %s", name, error); - if (ssh.response_code >= 0x72) - printk(" [descriptor]"); - - sense_txt = scsi_sense_key_string(ssh.sense_key); - if (sense_txt) - printk(": sense key: %s\n", sense_txt); - else - printk(": sense key=0x%x\n", ssh.sense_key); - printk(KERN_INFO " "); - scsi_show_extd_sense(ssh.asc, ssh.ascq); - printk("\n"); - + scsi_print_sense_hdr(name, &ssh); if (ssh.response_code < 0x72) { /* only decode extras for "fixed" format now */ char buff[80]; diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 5f399c9c68e..179a767d221 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -90,19 +90,16 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, { int result; struct scsi_sense_hdr sshdr; - char sense[SCSI_SENSE_BUFFERSIZE]; SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); - - memset(sense, 0, sizeof(*sense)); result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, - sense, timeout, retries); + &sshdr, timeout, retries); SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", result)); if ((driver_byte(result) & DRIVER_SENSE) && - (scsi_normalize_sense(sense, sizeof(*sense), &sshdr))) { + (scsi_sense_valid(&sshdr))) { switch (sshdr.sense_key) { case ILLEGAL_REQUEST: if (cmd[0] == ALLOW_MEDIUM_REMOVAL) @@ -132,7 +129,7 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, sdev->id, sdev->lun, result); - __scsi_print_sense(" ", sense, sizeof(*sense)); + scsi_print_sense_hdr(" ", &sshdr); break; } } @@ -315,9 +312,9 @@ int scsi_ioctl_send_command(struct scsi_device *sdev, break; } - result = scsi_execute_req(sdev, cmd, data_direction, buf, needed, - sense, timeout, retries); - + result = scsi_execute(sdev, cmd, data_direction, buf, needed, + sense, timeout, retries, 0); + /* * If there was an error condition, pass the info back to the user. */ diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 42edf29223a..bdea26b56dc 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -293,8 +293,8 @@ EXPORT_SYMBOL(scsi_wait_req); * @retries: number of times to retry request * @flags: or into request flags; * - * scsi_execute_req returns the req->errors value which is the - * the scsi_cmnd result field. + * returns the req->errors value which is the the scsi_cmnd result + * field. **/ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, int data_direction, void *buffer, unsigned bufflen, @@ -328,9 +328,31 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, return ret; } - EXPORT_SYMBOL(scsi_execute); + +int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, + int data_direction, void *buffer, unsigned bufflen, + struct scsi_sense_hdr *sshdr, int timeout, int retries) +{ + char *sense = NULL; + + if (sshdr) { + sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); + if (!sense) + return DRIVER_ERROR << 24; + memset(sense, 0, sizeof(*sense)); + } + int result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, + sense, timeout, retries, 0); + if (sshdr) + scsi_normalize_sense(sense, sizeof(*sense), sshdr); + + kfree(sense); + return result; +} +EXPORT_SYMBOL(scsi_execute_req); + /* * Function: scsi_init_cmd_errh() * @@ -1614,7 +1636,7 @@ void scsi_exit_queue(void) } } /** - * __scsi_mode_sense - issue a mode sense, falling back from 10 to + * scsi_mode_sense - issue a mode sense, falling back from 10 to * six bytes if necessary. * @sdev: SCSI device to be queried * @dbd: set if mode sense will allow block descriptors to be returned @@ -1634,26 +1656,22 @@ void scsi_exit_queue(void) int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char *buffer, int len, int timeout, int retries, - struct scsi_mode_data *data, char *sense) { + struct scsi_mode_data *data, struct scsi_sense_hdr *sshdr) { unsigned char cmd[12]; int use_10_for_ms; int header_length; int result; - char *sense_buffer = NULL; + struct scsi_sense_hdr my_sshdr; memset(data, 0, sizeof(*data)); memset(&cmd[0], 0, 12); cmd[1] = dbd & 0x18; /* allows DBD and LLBA bits */ cmd[2] = modepage; - if (!sense) { - sense_buffer = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); - if (!sense_buffer) { - dev_printk(KERN_ERR, &sdev->sdev_gendev, "failed to allocate sense buffer\n"); - return 0; - } - sense = sense_buffer; - } + /* caller might not be interested in sense, but we need it */ + if (!sshdr) + sshdr = &my_sshdr; + retry: use_10_for_ms = sdev->use_10_for_ms; @@ -1673,12 +1691,10 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, header_length = 4; } - memset(sense, 0, SCSI_SENSE_BUFFERSIZE); - memset(buffer, 0, len); result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, - sense, timeout, retries); + sshdr, timeout, retries); /* This code looks awful: what it's doing is making sure an * ILLEGAL REQUEST sense return identifies the actual command @@ -1687,11 +1703,9 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, if (use_10_for_ms && !scsi_status_is_good(result) && (driver_byte(result) & DRIVER_SENSE)) { - struct scsi_sense_hdr sshdr; - - if (scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) { - if ((sshdr.sense_key == ILLEGAL_REQUEST) && - (sshdr.asc == 0x20) && (sshdr.ascq == 0)) { + if (scsi_sense_valid(sshdr)) { + if ((sshdr->sense_key == ILLEGAL_REQUEST) && + (sshdr->asc == 0x20) && (sshdr->ascq == 0)) { /* * Invalid command operation code */ @@ -1718,7 +1732,6 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, } } - kfree(sense_buffer); return result; } EXPORT_SYMBOL(scsi_mode_sense); @@ -1729,17 +1742,15 @@ scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries) char cmd[] = { TEST_UNIT_READY, 0, 0, 0, 0, 0, }; - char sense[SCSI_SENSE_BUFFERSIZE]; + struct scsi_sense_hdr sshdr; int result; - result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, sense, + result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, &sshdr, timeout, retries); if ((driver_byte(result) & DRIVER_SENSE) && sdev->removable) { - struct scsi_sense_hdr sshdr; - if ((scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, - &sshdr)) && + if ((scsi_sense_valid(&sshdr)) && ((sshdr.sense_key == UNIT_ATTENTION) || (sshdr.sense_key == NOT_READY))) { sdev->changed = 1; diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 0048beaffc9..19c9a232a75 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -446,7 +446,6 @@ void scsi_target_reap(struct scsi_target *starget) static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result, int result_len, int *bflags) { - char sense[SCSI_SENSE_BUFFERSIZE]; unsigned char scsi_cmd[MAX_COMMAND_SIZE]; int first_inquiry_len, try_inquiry_len, next_inquiry_len; int response_len = 0; @@ -474,11 +473,10 @@ static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result, scsi_cmd[0] = INQUIRY; scsi_cmd[4] = (unsigned char) try_inquiry_len; - memset(sense, 0, sizeof(sense)); memset(inq_result, 0, try_inquiry_len); result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, - inq_result, try_inquiry_len, sense, + inq_result, try_inquiry_len, &sshdr, HZ / 2 + HZ * scsi_inq_timeout, 3); SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " @@ -493,8 +491,7 @@ static int scsi_probe_lun(struct scsi_device *sdev, char *inq_result, * but many buggy devices do so anyway. */ if ((driver_byte(result) & DRIVER_SENSE) && - scsi_normalize_sense(sense, sizeof(sense), - &sshdr)) { + scsi_sense_valid(&sshdr)) { if ((sshdr.sense_key == UNIT_ATTENTION) && ((sshdr.asc == 0x28) || (sshdr.asc == 0x29)) && @@ -1057,7 +1054,6 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, int rescan) { char devname[64]; - char sense[SCSI_SENSE_BUFFERSIZE]; unsigned char scsi_cmd[MAX_COMMAND_SIZE]; unsigned int length; unsigned int lun; @@ -1134,9 +1130,8 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, " REPORT LUNS to %s (try %d)\n", devname, retries)); - memset(sense, 0, sizeof(sense)); result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, - lun_data, length, sense, + lun_data, length, &sshdr, SCSI_TIMEOUT + 4 * HZ, 3); SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" @@ -1144,7 +1139,7 @@ static int scsi_report_lun_scan(struct scsi_device *sdev, int bflags, ? "failed" : "successful", retries, result)); if (result == 0) break; - else if (scsi_normalize_sense(sense, sizeof(sense), &sshdr)) { + else if (scsi_sense_valid(&sshdr)) { if (sshdr.sense_key != UNIT_ATTENTION) break; } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 15c2039059c..611ccde8477 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -59,7 +59,6 @@ #include #include #include -#include #include #include "scsi_logging.h" @@ -125,7 +124,7 @@ static int sd_issue_flush(struct device *, sector_t *); static void sd_end_flush(request_queue_t *, struct request *); static int sd_prepare_flush(request_queue_t *, struct request *); static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, - struct scsi_request *SRpnt, unsigned char *buffer); + unsigned char *buffer); static struct scsi_driver sd_template = { .owner = THIS_MODULE, @@ -682,19 +681,13 @@ not_present: static int sd_sync_cache(struct scsi_device *sdp) { - struct scsi_request *sreq; int retries, res; + struct scsi_sense_hdr sshdr; if (!scsi_device_online(sdp)) return -ENODEV; - sreq = scsi_allocate_request(sdp, GFP_KERNEL); - if (!sreq) { - printk("FAILED\n No memory for request\n"); - return -ENOMEM; - } - sreq->sr_data_direction = DMA_NONE; for (retries = 3; retries > 0; --retries) { unsigned char cmd[10] = { 0 }; @@ -703,22 +696,20 @@ static int sd_sync_cache(struct scsi_device *sdp) * Leave the rest of the command zero to indicate * flush everything. */ - scsi_wait_req(sreq, cmd, NULL, 0, SD_TIMEOUT, SD_MAX_RETRIES); - if (sreq->sr_result == 0) + res = scsi_execute_req(sdp, cmd, DMA_NONE, NULL, 0, &sshdr, + SD_TIMEOUT, SD_MAX_RETRIES); + if (res == 0) break; } - res = sreq->sr_result; - if (res) { - printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " + if (res) { printk(KERN_WARNING "FAILED\n status = %x, message = %02x, " "host = %d, driver = %02x\n ", status_byte(res), msg_byte(res), host_byte(res), driver_byte(res)); if (driver_byte(res) & DRIVER_SENSE) - scsi_print_req_sense("sd", sreq); + scsi_print_sense_hdr("sd", &sshdr); } - scsi_release_request(sreq); return res; } @@ -957,22 +948,19 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) scsi_io_completion(SCpnt, good_bytes, block_sectors << 9); } -static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp) +static int media_not_present(struct scsi_disk *sdkp, + struct scsi_sense_hdr *sshdr) { - struct scsi_sense_hdr sshdr; - if (!srp->sr_result) - return 0; - if (!(driver_byte(srp->sr_result) & DRIVER_SENSE)) + if (!scsi_sense_valid(sshdr)) return 0; /* not invoked for commands that could return deferred errors */ - if (scsi_request_normalize_sense(srp, &sshdr)) { - if (sshdr.sense_key != NOT_READY && - sshdr.sense_key != UNIT_ATTENTION) - return 0; - if (sshdr.asc != 0x3A) /* medium not present */ - return 0; - } + if (sshdr->sense_key != NOT_READY && + sshdr->sense_key != UNIT_ATTENTION) + return 0; + if (sshdr->asc != 0x3A) /* medium not present */ + return 0; + set_media_not_present(sdkp); return 1; } @@ -981,8 +969,8 @@ static int media_not_present(struct scsi_disk *sdkp, struct scsi_request *srp) * spinup disk - called only in sd_revalidate_disk() */ static void -sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, - struct scsi_request *SRpnt, unsigned char *buffer) { +sd_spinup_disk(struct scsi_disk *sdkp, char *diskname) +{ unsigned char cmd[10]; unsigned long spintime_value = 0; int retries, spintime; @@ -1001,18 +989,13 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, cmd[0] = TEST_UNIT_READY; memset((void *) &cmd[1], 0, 9); - SRpnt->sr_cmd_len = 0; - memset(SRpnt->sr_sense_buffer, 0, - SCSI_SENSE_BUFFERSIZE); - SRpnt->sr_data_direction = DMA_NONE; + the_result = scsi_execute_req(sdkp->device, cmd, + DMA_NONE, NULL, 0, + &sshdr, SD_TIMEOUT, + SD_MAX_RETRIES); - scsi_wait_req (SRpnt, (void *) cmd, (void *) buffer, - 0/*512*/, SD_TIMEOUT, SD_MAX_RETRIES); - - the_result = SRpnt->sr_result; if (the_result) - sense_valid = scsi_request_normalize_sense( - SRpnt, &sshdr); + sense_valid = scsi_sense_valid(&sshdr); retries++; } while (retries < 3 && (!scsi_status_is_good(the_result) || @@ -1024,7 +1007,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, * any media in it, don't bother with any of the rest of * this crap. */ - if (media_not_present(sdkp, SRpnt)) + if (media_not_present(sdkp, &sshdr)) return; if ((driver_byte(the_result) & DRIVER_SENSE) == 0) { @@ -1063,14 +1046,9 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, cmd[1] = 1; /* Return immediately */ memset((void *) &cmd[2], 0, 8); cmd[4] = 1; /* Start spin cycle */ - SRpnt->sr_cmd_len = 0; - memset(SRpnt->sr_sense_buffer, 0, - SCSI_SENSE_BUFFERSIZE); - - SRpnt->sr_data_direction = DMA_NONE; - scsi_wait_req(SRpnt, (void *)cmd, - (void *) buffer, 0/*512*/, - SD_TIMEOUT, SD_MAX_RETRIES); + scsi_execute_req(sdkp->device, cmd, DMA_NONE, + NULL, 0, &sshdr, + SD_TIMEOUT, SD_MAX_RETRIES); spintime_value = jiffies; } spintime = 1; @@ -1083,7 +1061,7 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, if(!spintime) { printk(KERN_NOTICE "%s: Unit Not Ready, " "sense:\n", diskname); - scsi_print_req_sense("", SRpnt); + scsi_print_sense_hdr("", &sshdr); } break; } @@ -1104,14 +1082,15 @@ sd_spinup_disk(struct scsi_disk *sdkp, char *diskname, */ static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname, - struct scsi_request *SRpnt, unsigned char *buffer) { + unsigned char *buffer) +{ unsigned char cmd[16]; - struct scsi_device *sdp = sdkp->device; int the_result, retries; int sector_size = 0; int longrc = 0; struct scsi_sense_hdr sshdr; int sense_valid = 0; + struct scsi_device *sdp = sdkp->device; repeat: retries = 3; @@ -1128,20 +1107,15 @@ repeat: memset((void *) buffer, 0, 8); } - SRpnt->sr_cmd_len = 0; - memset(SRpnt->sr_sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); - SRpnt->sr_data_direction = DMA_FROM_DEVICE; - - scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer, - longrc ? 12 : 8, SD_TIMEOUT, SD_MAX_RETRIES); + the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE, + buffer, longrc ? 12 : 8, &sshdr, + SD_TIMEOUT, SD_MAX_RETRIES); - if (media_not_present(sdkp, SRpnt)) + if (media_not_present(sdkp, &sshdr)) return; - the_result = SRpnt->sr_result; if (the_result) - sense_valid = scsi_request_normalize_sense(SRpnt, - &sshdr); + sense_valid = scsi_sense_valid(&sshdr); retries--; } while (the_result && retries); @@ -1156,7 +1130,7 @@ repeat: driver_byte(the_result)); if (driver_byte(the_result) & DRIVER_SENSE) - scsi_print_req_sense("sd", SRpnt); + scsi_print_sense_hdr("sd", &sshdr); else printk("%s : sense not available. \n", diskname); @@ -1296,12 +1270,13 @@ got_data: /* called with buffer of length 512 */ static inline int -sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage, - unsigned char *buffer, int len, struct scsi_mode_data *data) +sd_do_mode_sense(struct scsi_device *sdp, int dbd, int modepage, + unsigned char *buffer, int len, struct scsi_mode_data *data, + struct scsi_sense_hdr *sshdr) { - return scsi_mode_sense(SRpnt->sr_device, dbd, modepage, buffer, len, + return scsi_mode_sense(sdp, dbd, modepage, buffer, len, SD_TIMEOUT, SD_MAX_RETRIES, data, - SRpnt->sr_sense_buffer); + sshdr); } /* @@ -1310,25 +1285,27 @@ sd_do_mode_sense(struct scsi_request *SRpnt, int dbd, int modepage, */ static void sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, - struct scsi_request *SRpnt, unsigned char *buffer) { + unsigned char *buffer) +{ int res; + struct scsi_device *sdp = sdkp->device; struct scsi_mode_data data; set_disk_ro(sdkp->disk, 0); - if (sdkp->device->skip_ms_page_3f) { + if (sdp->skip_ms_page_3f) { printk(KERN_NOTICE "%s: assuming Write Enabled\n", diskname); return; } - if (sdkp->device->use_192_bytes_for_3f) { - res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 192, &data); + if (sdp->use_192_bytes_for_3f) { + res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 192, &data, NULL); } else { /* * First attempt: ask for all pages (0x3F), but only 4 bytes. * We have to start carefully: some devices hang if we ask * for more than is available. */ - res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 4, &data); + res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 4, &data, NULL); /* * Second attempt: ask for page 0 When only page 0 is @@ -1337,14 +1314,14 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, * CDB. */ if (!scsi_status_is_good(res)) - res = sd_do_mode_sense(SRpnt, 0, 0, buffer, 4, &data); + res = sd_do_mode_sense(sdp, 0, 0, buffer, 4, &data, NULL); /* * Third attempt: ask 255 bytes, as we did earlier. */ if (!scsi_status_is_good(res)) - res = sd_do_mode_sense(SRpnt, 0, 0x3F, buffer, 255, - &data); + res = sd_do_mode_sense(sdp, 0, 0x3F, buffer, 255, + &data, NULL); } if (!scsi_status_is_good(res)) { @@ -1366,19 +1343,20 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, char *diskname, */ static void sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, - struct scsi_request *SRpnt, unsigned char *buffer) + unsigned char *buffer) { int len = 0, res; + struct scsi_device *sdp = sdkp->device; int dbd; int modepage; struct scsi_mode_data data; struct scsi_sense_hdr sshdr; - if (sdkp->device->skip_ms_page_8) + if (sdp->skip_ms_page_8) goto defaults; - if (sdkp->device->type == TYPE_RBC) { + if (sdp->type == TYPE_RBC) { modepage = 6; dbd = 8; } else { @@ -1387,7 +1365,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, } /* cautiously ask */ - res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data); + res = sd_do_mode_sense(sdp, dbd, modepage, buffer, 4, &data, &sshdr); if (!scsi_status_is_good(res)) goto bad_sense; @@ -1408,7 +1386,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, len += data.header_length + data.block_descriptor_length; /* Get the data */ - res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, len, &data); + res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); if (scsi_status_is_good(res)) { const char *types[] = { @@ -1440,7 +1418,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname, } bad_sense: - if (scsi_request_normalize_sense(SRpnt, &sshdr) && + if (scsi_sense_valid(&sshdr) && sshdr.sense_key == ILLEGAL_REQUEST && sshdr.asc == 0x24 && sshdr.ascq == 0x0) printk(KERN_NOTICE "%s: cache data unavailable\n", @@ -1465,7 +1443,6 @@ static int sd_revalidate_disk(struct gendisk *disk) { struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdp = sdkp->device; - struct scsi_request *sreq; unsigned char *buffer; SCSI_LOG_HLQUEUE(3, printk("sd_revalidate_disk: disk=%s\n", disk->disk_name)); @@ -1477,18 +1454,11 @@ static int sd_revalidate_disk(struct gendisk *disk) if (!scsi_device_online(sdp)) goto out; - sreq = scsi_allocate_request(sdp, GFP_KERNEL); - if (!sreq) { - printk(KERN_WARNING "(sd_revalidate_disk:) Request allocation " - "failure.\n"); - goto out; - } - buffer = kmalloc(512, GFP_KERNEL | __GFP_DMA); if (!buffer) { printk(KERN_WARNING "(sd_revalidate_disk:) Memory allocation " "failure.\n"); - goto out_release_request; + goto out; } /* defaults, until the device tells us otherwise */ @@ -1499,25 +1469,23 @@ static int sd_revalidate_disk(struct gendisk *disk) sdkp->WCE = 0; sdkp->RCD = 0; - sd_spinup_disk(sdkp, disk->disk_name, sreq, buffer); + sd_spinup_disk(sdkp, disk->disk_name); /* * Without media there is no reason to ask; moreover, some devices * react badly if we do. */ if (sdkp->media_present) { - sd_read_capacity(sdkp, disk->disk_name, sreq, buffer); + sd_read_capacity(sdkp, disk->disk_name, buffer); if (sdp->removable) sd_read_write_protect_flag(sdkp, disk->disk_name, - sreq, buffer); - sd_read_cache_type(sdkp, disk->disk_name, sreq, buffer); + buffer); + sd_read_cache_type(sdkp, disk->disk_name, buffer); } set_capacity(disk, sdkp->capacity); kfree(buffer); - out_release_request: - scsi_release_request(sreq); out: return 0; } diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h index 12e90934a7a..b090a11d7e1 100644 --- a/include/scsi/scsi_dbg.h +++ b/include/scsi/scsi_dbg.h @@ -3,8 +3,10 @@ struct scsi_cmnd; struct scsi_request; +struct scsi_sense_hdr; extern void scsi_print_command(struct scsi_cmnd *); +extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *); extern void __scsi_print_command(unsigned char *); extern void scsi_print_sense(const char *, struct scsi_cmnd *); extern void scsi_print_req_sense(const char *, struct scsi_request *); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 5ad08b70763..da63722c012 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -9,6 +9,7 @@ struct request_queue; struct scsi_cmnd; struct scsi_lun; +struct scsi_sense_hdr; struct scsi_mode_data { __u32 length; @@ -237,7 +238,7 @@ extern int scsi_set_medium_removal(struct scsi_device *, char); extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, unsigned char *buffer, int len, int timeout, int retries, struct scsi_mode_data *data, - char *sense); + struct scsi_sense_hdr *); extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout, int retries); extern int scsi_device_set_state(struct scsi_device *sdev, @@ -260,15 +261,10 @@ extern int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, int data_direction, void *buffer, unsigned bufflen, unsigned char *sense, int timeout, int retries, int flag); +extern int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, + int data_direction, void *buffer, unsigned bufflen, + struct scsi_sense_hdr *, int timeout, int retries); -static inline int -scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, - int data_direction, void *buffer, unsigned bufflen, - unsigned char *sense, int timeout, int retries) -{ - return scsi_execute(sdev, cmd, data_direction, buffer, bufflen, sense, - timeout, retries, 0); -} static inline int scsi_device_online(struct scsi_device *sdev) { return sdev->sdev_state != SDEV_OFFLINE; -- cgit v1.2.3-70-g09d2 From 1ccb48bb163853c24840c0a50c2a6df1affe029c Mon Sep 17 00:00:00 2001 From: "akpm@osdl.org" Date: Sun, 26 Jun 2005 00:12:51 -0700 Subject: [SCSI] fix C syntax problem in scsi_lib.c Older gcc's require variable definitions at the beginning of a block. Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index bdea26b56dc..58da7f64c22 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -336,14 +336,15 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, struct scsi_sense_hdr *sshdr, int timeout, int retries) { char *sense = NULL; - + int result; + if (sshdr) { sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); if (!sense) return DRIVER_ERROR << 24; memset(sense, 0, sizeof(*sense)); } - int result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, + result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, sense, timeout, retries, 0); if (sshdr) scsi_normalize_sense(sense, sizeof(*sense), sshdr); -- cgit v1.2.3-70-g09d2 From e514385be2b355c1f3fc6385a98a6a0fc04235ae Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Tue, 9 Aug 2005 11:55:36 -0500 Subject: [SCSI] fix sense buffer length handling problem The new bio code was incorrectly converted from stack allocated to kmalloc'd buffer handling. There are two places where it incorrectly uses sizeof(*sense) to get the size of the sense buffer. This actually produces one, so no sense data was ever getting back, causing failure in things like disk spin up. Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 58da7f64c22..72a47ce7a1d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -342,12 +342,12 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd, sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); if (!sense) return DRIVER_ERROR << 24; - memset(sense, 0, sizeof(*sense)); + memset(sense, 0, SCSI_SENSE_BUFFERSIZE); } result = scsi_execute(sdev, cmd, data_direction, buffer, bufflen, sense, timeout, retries, 0); if (sshdr) - scsi_normalize_sense(sense, sizeof(*sense), sshdr); + scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, sshdr); kfree(sense); return result; -- cgit v1.2.3-70-g09d2 From 3173d8c342971a03857d8af749a3f57da7d06b57 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 4 Sep 2005 11:32:05 -0500 Subject: [SCSI] quieten messages on scsi_execute commands scsi_io_completion() can be a bit noisy about certain conditions. Previously this wasn't a problem for internally generated commands, since they never hit it. However, since we do all SCSI commands via bios, now they do. user CD testers like magicdev are now getting not ready messages every time they touch the CD to see if there's anything in it. Fix this by making all scsi_execute commands REQ_QUIET and making scsi_finish_io() not say anything for REQ_QUIET. Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers/scsi/scsi_lib.c') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 72a47ce7a1d..77f2d444f7e 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -315,7 +315,7 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, req->sense = sense; req->sense_len = 0; req->timeout = timeout; - req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL; + req->flags |= flags | REQ_BLOCK_PC | REQ_SPECIAL | REQ_QUIET; /* * head injection *required* here otherwise quiesce won't work @@ -927,17 +927,20 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, scsi_requeue_command(q, cmd); return; } - printk(KERN_INFO "Device %s not ready.\n", - req->rq_disk ? req->rq_disk->disk_name : ""); + if (!(req->flags & REQ_QUIET)) + dev_printk(KERN_INFO, + &cmd->device->sdev_gendev, + "Device not ready.\n"); cmd = scsi_end_request(cmd, 0, this_count, 1); return; case VOLUME_OVERFLOW: - printk(KERN_INFO "Volume overflow <%d %d %d %d> CDB: ", - cmd->device->host->host_no, - (int)cmd->device->channel, - (int)cmd->device->id, (int)cmd->device->lun); - __scsi_print_command(cmd->data_cmnd); - scsi_print_sense("", cmd); + if (!(req->flags & REQ_QUIET)) { + dev_printk(KERN_INFO, + &cmd->device->sdev_gendev, + "Volume overflow, CDB: "); + __scsi_print_command(cmd->data_cmnd); + scsi_print_sense("", cmd); + } cmd = scsi_end_request(cmd, 0, block_bytes, 1); return; default: @@ -954,15 +957,13 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes, return; } if (result) { - if (!(req->flags & REQ_SPECIAL)) - printk(KERN_INFO "SCSI error : <%d %d %d %d> return code " - "= 0x%x\n", cmd->device->host->host_no, - cmd->device->channel, - cmd->device->id, - cmd->device->lun, result); - - if (driver_byte(result) & DRIVER_SENSE) - scsi_print_sense("", cmd); + if (!(req->flags & REQ_QUIET)) { + dev_printk(KERN_INFO, &cmd->device->sdev_gendev, + "SCSI error: return code = 0x%x\n", result); + + if (driver_byte(result) & DRIVER_SENSE) + scsi_print_sense("", cmd); + } /* * Mark a single buffer as not uptodate. Queue the remainder. * We sometimes get this cruft in the event that a medium error -- cgit v1.2.3-70-g09d2