| /* |
| * scsi_lib.c Copyright (C) 1999 Eric Youngdale |
| * |
| * SCSI queueing library. |
| * Initial versions: Eric Youngdale (eric@andante.org). |
| * Based upon conversations with large numbers |
| * of people at Linux Expo. |
| */ |
| |
| /* |
| * The fundamental purpose of this file is to contain a library of utility |
| * routines that can be used by low-level drivers. Ultimately the idea |
| * is that there should be a sufficiently rich number of functions that it |
| * would be possible for a driver author to fashion a queueing function for |
| * a low-level driver if they wished. Note however that this file also |
| * contains the "default" versions of these functions, as we don't want to |
| * go through and retrofit queueing functions into all 30 some-odd drivers. |
| */ |
| |
| #include <linux/module.h> |
| |
| #include <linux/sched.h> |
| #include <linux/timer.h> |
| #include <linux/string.h> |
| #include <linux/slab.h> |
| #include <linux/ioport.h> |
| #include <linux/kernel.h> |
| #include <linux/stat.h> |
| #include <linux/blk.h> |
| #include <linux/interrupt.h> |
| #include <linux/delay.h> |
| #include <linux/smp_lock.h> |
| #include <linux/completion.h> |
| |
| |
| #define __KERNEL_SYSCALLS__ |
| |
| #include <linux/unistd.h> |
| |
| #include <asm/system.h> |
| #include <asm/irq.h> |
| #include <asm/dma.h> |
| |
| #include "scsi.h" |
| #include "hosts.h" |
| #include "constants.h" |
| #include <scsi/scsi_ioctl.h> |
| |
| /* |
| * This entire source file deals with the new queueing code. |
| */ |
| |
| /* |
| * Function: __scsi_insert_special() |
| * |
| * Purpose: worker for scsi_insert_special_*() |
| * |
| * Arguments: q - request queue where request should be inserted |
| * rq - request to be inserted |
| * data - private data |
| * at_head - insert request at head or tail of queue |
| * |
| * Lock status: Assumed that queue lock is not held upon entry. |
| * |
| * Returns: Nothing |
| */ |
| static void __scsi_insert_special(request_queue_t *q, struct request *rq, |
| void *data, int at_head) |
| { |
| unsigned long flags; |
| |
| ASSERT_LOCK(q->queue_lock, 0); |
| |
| /* |
| * tell I/O scheduler that this isn't a regular read/write (ie it |
| * must not attempt merges on this) and that it acts as a soft |
| * barrier |
| */ |
| rq->flags = REQ_SPECIAL | REQ_BARRIER; |
| |
| rq->special = data; |
| rq->q = NULL; |
| rq->bio = rq->biotail = NULL; |
| rq->nr_phys_segments = 0; |
| |
| /* |
| * We have the option of inserting the head or the tail of the queue. |
| * Typically we use the tail for new ioctls and so forth. We use the |
| * head of the queue for things like a QUEUE_FULL message from a |
| * device, or a host that is unable to accept a particular command. |
| */ |
| spin_lock_irqsave(q->queue_lock, flags); |
| _elv_add_request(q, rq, !at_head, 0); |
| q->request_fn(q); |
| spin_unlock_irqrestore(q->queue_lock, flags); |
| } |
| |
| |
| /* |
| * Function: scsi_insert_special_cmd() |
| * |
| * Purpose: Insert pre-formed command into request queue. |
| * |
| * Arguments: SCpnt - command that is ready to be queued. |
| * at_head - boolean. True if we should insert at head |
| * of queue, false if we should insert at tail. |
| * |
| * Lock status: Assumed that lock is not held upon entry. |
| * |
| * Returns: Nothing |
| * |
| * Notes: This function is called from character device and from |
| * ioctl types of functions where the caller knows exactly |
| * what SCSI command needs to be issued. The idea is that |
| * we merely inject the command into the queue (at the head |
| * for now), and then call the queue request function to actually |
| * process it. |
| */ |
| int scsi_insert_special_cmd(Scsi_Cmnd * SCpnt, int at_head) |
| { |
| request_queue_t *q = &SCpnt->device->request_queue; |
| |
| __scsi_insert_special(q, &SCpnt->request, SCpnt, at_head); |
| return 0; |
| } |
| |
| /* |
| * Function: scsi_insert_special_req() |
| * |
| * Purpose: Insert pre-formed request into request queue. |
| * |
| * Arguments: SRpnt - request that is ready to be queued. |
| * at_head - boolean. True if we should insert at head |
| * of queue, false if we should insert at tail. |
| * |
| * Lock status: Assumed that lock is not held upon entry. |
| * |
| * Returns: Nothing |
| * |
| * Notes: This function is called from character device and from |
| * ioctl types of functions where the caller knows exactly |
| * what SCSI command needs to be issued. The idea is that |
| * we merely inject the command into the queue (at the head |
| * for now), and then call the queue request function to actually |
| * process it. |
| */ |
| int scsi_insert_special_req(Scsi_Request * SRpnt, int at_head) |
| { |
| request_queue_t *q = &SRpnt->sr_device->request_queue; |
| |
| __scsi_insert_special(q, &SRpnt->sr_request, SRpnt, at_head); |
| return 0; |
| } |
| |
| /* |
| * Function: scsi_init_cmd_errh() |
| * |
| * Purpose: Initialize SCpnt fields related to error handling. |
| * |
| * Arguments: SCpnt - command that is ready to be queued. |
| * |
| * Returns: Nothing |
| * |
| * Notes: This function has the job of initializing a number of |
| * fields related to error handling. Typically this will |
| * be called once for each command, as required. |
| */ |
| int scsi_init_cmd_errh(Scsi_Cmnd * SCpnt) |
| { |
| SCpnt->owner = SCSI_OWNER_MIDLEVEL; |
| SCpnt->reset_chain = NULL; |
| SCpnt->serial_number = 0; |
| SCpnt->serial_number_at_timeout = 0; |
| SCpnt->flags = 0; |
| SCpnt->retries = 0; |
| |
| SCpnt->abort_reason = 0; |
| |
| memset((void *) SCpnt->sense_buffer, 0, sizeof SCpnt->sense_buffer); |
| |
| if (SCpnt->cmd_len == 0) |
| SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]); |
| |
| /* |
| * We need saved copies of a number of fields - this is because |
| * error handling may need to overwrite these with different values |
| * to run different commands, and once error handling is complete, |
| * we will need to restore these values prior to running the actual |
| * command. |
| */ |
| SCpnt->old_use_sg = SCpnt->use_sg; |
| SCpnt->old_cmd_len = SCpnt->cmd_len; |
| SCpnt->sc_old_data_direction = SCpnt->sc_data_direction; |
| SCpnt->old_underflow = SCpnt->underflow; |
| memcpy((void *) SCpnt->data_cmnd, |
| (const void *) SCpnt->cmnd, sizeof(SCpnt->cmnd)); |
| SCpnt->buffer = SCpnt->request_buffer; |
| SCpnt->bufflen = SCpnt->request_bufflen; |
| |
| SCpnt->reset_chain = NULL; |
| |
| SCpnt->internal_timeout = NORMAL_TIMEOUT; |
| SCpnt->abort_reason = 0; |
| |
| return 1; |
| } |
| |
| /* |
| * Function: scsi_queue_next_request() |
| * |
| * Purpose: Handle post-processing of completed commands. |
| * |
| * Arguments: SCpnt - command that may need to be requeued. |
| * |
| * Returns: Nothing |
| * |
| * Notes: After command completion, there may be blocks left |
| * over which weren't finished by the previous command |
| * this can be for a number of reasons - the main one is |
| * that a medium error occurred, and the sectors after |
| * the bad block need to be re-read. |
| * |
| * If SCpnt is NULL, it means that the previous command |
| * was completely finished, and we should simply start |
| * a new command, if possible. |
| * |
| * This is where a lot of special case code has begun to |
| * accumulate. It doesn't really affect readability or |
| * anything, but it might be considered architecturally |
| * inelegant. If more of these special cases start to |
| * accumulate, I am thinking along the lines of implementing |
| * an atexit() like technology that gets run when commands |
| * complete. I am not convinced that it is worth the |
| * added overhead, however. Right now as things stand, |
| * there are simple conditional checks, and most hosts |
| * would skip past. |
| * |
| * Another possible solution would be to tailor different |
| * handler functions, sort of like what we did in scsi_merge.c. |
| * This is probably a better solution, but the number of different |
| * permutations grows as 2**N, and if too many more special cases |
| * get added, we start to get screwed. |
| */ |
| void scsi_queue_next_request(request_queue_t * q, Scsi_Cmnd * SCpnt) |
| { |
| int all_clear; |
| unsigned long flags; |
| Scsi_Device *SDpnt; |
| struct Scsi_Host *SHpnt; |
| |
| ASSERT_LOCK(q->queue_lock, 0); |
| |
| spin_lock_irqsave(q->queue_lock, flags); |
| if (SCpnt != NULL) { |
| |
| /* |
| * For some reason, we are not done with this request. |
| * This happens for I/O errors in the middle of the request, |
| * in which case we need to request the blocks that come after |
| * the bad sector. |
| */ |
| SCpnt->request.special = (void *) SCpnt; |
| _elv_add_request(q, &SCpnt->request, 0, 0); |
| } |
| |
| /* |
| * Just hit the requeue function for the queue. |
| */ |
| q->request_fn(q); |
| |
| SDpnt = (Scsi_Device *) q->queuedata; |
| SHpnt = SDpnt->host; |
| |
| /* |
| * If this is a single-lun device, and we are currently finished |
| * with this device, then see if we need to get another device |
| * started. FIXME(eric) - if this function gets too cluttered |
| * with special case code, then spin off separate versions and |
| * use function pointers to pick the right one. |
| */ |
| if (SDpnt->single_lun && blk_queue_empty(q) && SDpnt->device_busy ==0) { |
| request_queue_t *q; |
| |
| for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { |
| if (((SHpnt->can_queue > 0) |
| && (SHpnt->host_busy >= SHpnt->can_queue)) |
| || (SHpnt->host_blocked) |
| || (SHpnt->host_self_blocked) |
| || (SDpnt->device_blocked)) { |
| break; |
| } |
| |
| q = &SDpnt->request_queue; |
| q->request_fn(q); |
| } |
| } |
| |
| /* |
| * Now see whether there are other devices on the bus which |
| * might be starved. If so, hit the request function. If we |
| * don't find any, then it is safe to reset the flag. If we |
| * find any device that it is starved, it isn't safe to reset the |
| * flag as the queue function releases the lock and thus some |
| * other device might have become starved along the way. |
| */ |
| all_clear = 1; |
| if (SHpnt->some_device_starved) { |
| for (SDpnt = SHpnt->host_queue; SDpnt; SDpnt = SDpnt->next) { |
| request_queue_t *q; |
| if ((SHpnt->can_queue > 0 && (SHpnt->host_busy >= SHpnt->can_queue)) |
| || (SHpnt->host_blocked) |
| || (SHpnt->host_self_blocked)) { |
| break; |
| } |
| if (SDpnt->device_blocked || !SDpnt->starved) { |
| continue; |
| } |
| q = &SDpnt->request_queue; |
| q->request_fn(q); |
| all_clear = 0; |
| } |
| if (SDpnt == NULL && all_clear) { |
| SHpnt->some_device_starved = 0; |
| } |
| } |
| spin_unlock_irqrestore(q->queue_lock, flags); |
| } |
| |
| /* |
| * Function: scsi_end_request() |
| * |
| * Purpose: Post-processing of completed commands called from interrupt |
| * handler or a bottom-half handler. |
| * |
| * Arguments: SCpnt - command that is complete. |
| * uptodate - 1 if I/O indicates success, 0 for I/O error. |
| * sectors - number of sectors we want to mark. |
| * requeue - indicates whether we should requeue leftovers. |
| * frequeue - indicates that if we release the command block |
| * that the queue request function should be called. |
| * |
| * Lock status: Assumed that lock is not held upon entry. |
| * |
| * Returns: Nothing |
| * |
| * Notes: This is called for block device requests in order to |
| * mark some number of sectors as complete. |
| * |
| * We are guaranteeing that the request queue will be goosed |
| * at some point during this call. |
| */ |
| static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt, |
| int uptodate, |
| int sectors, |
| int requeue, |
| int frequeue) |
| { |
| request_queue_t *q = &SCpnt->device->request_queue; |
| struct request *req = &SCpnt->request; |
| |
| ASSERT_LOCK(q->queue_lock, 0); |
| |
| /* |
| * If there are blocks left over at the end, set up the command |
| * to queue the remainder of them. |
| */ |
| if (end_that_request_first(req, uptodate, sectors)) { |
| if (!requeue) |
| return SCpnt; |
| |
| /* |
| * Bleah. Leftovers again. Stick the leftovers in |
| * the front of the queue, and goose the queue again. |
| */ |
| scsi_queue_next_request(q, SCpnt); |
| return SCpnt; |
| } |
| |
| /* |
| * This request is done. If there is someone blocked waiting for this |
| * request, wake them up. |
| */ |
| if (req->waiting) |
| complete(req->waiting); |
| |
| add_blkdev_randomness(major(req->rq_dev)); |
| |
| /* |
| * This will goose the queue request function at the end, so we don't |
| * need to worry about launching another command. |
| */ |
| __scsi_release_command(SCpnt); |
| |
| if (frequeue) |
| scsi_queue_next_request(q, NULL); |
| |
| return NULL; |
| } |
| |
| /* |
| * Function: scsi_end_request() |
| * |
| * Purpose: Post-processing of completed commands called from interrupt |
| * handler or a bottom-half handler. |
| * |
| * Arguments: SCpnt - command that is complete. |
| * uptodate - 1 if I/O indicates success, 0 for I/O error. |
| * sectors - number of sectors we want to mark. |
| * |
| * Lock status: Assumed that lock is not held upon entry. |
| * |
| * Returns: Nothing |
| * |
| * Notes: This is called for block device requests in order to |
| * mark some number of sectors as complete. |
| * |
| * We are guaranteeing that the request queue will be goosed |
| * at some point during this call. |
| */ |
| Scsi_Cmnd *scsi_end_request(Scsi_Cmnd * SCpnt, int uptodate, int sectors) |
| { |
| return __scsi_end_request(SCpnt, uptodate, sectors, 1, 1); |
| } |
| |
| /* |
| * Function: scsi_release_buffers() |
| * |
| * Purpose: Completion processing for block device I/O requests. |
| * |
| * Arguments: SCpnt - command that we are bailing. |
| * |
| * Lock status: Assumed that no lock is held upon entry. |
| * |
| * Returns: Nothing |
| * |
| * Notes: In the event that an upper level driver rejects a |
| * command, we must release resources allocated during |
| * the __init_io() function. Primarily this would involve |
| * the scatter-gather table, and potentially any bounce |
| * buffers. |
| */ |
| static void scsi_release_buffers(Scsi_Cmnd * SCpnt) |
| { |
| struct request *req = &SCpnt->request; |
| |
| ASSERT_LOCK(SCpnt->host->host_lock, 0); |
| |
| /* |
| * Free up any indirection buffers we allocated for DMA purposes. |
| */ |
| if (SCpnt->use_sg) { |
| struct scatterlist *sgpnt; |
| |
| sgpnt = (struct scatterlist *) SCpnt->request_buffer; |
| scsi_free_sgtable(SCpnt->request_buffer, SCpnt->sglist_len); |
| } else { |
| if (SCpnt->request_buffer != req->buffer) |
| kfree(SCpnt->request_buffer); |
| } |
| |
| /* |
| * Zero these out. They now point to freed memory, and it is |
| * dangerous to hang onto the pointers. |
| */ |
| SCpnt->buffer = NULL; |
| SCpnt->bufflen = 0; |
| SCpnt->request_buffer = NULL; |
| SCpnt->request_bufflen = 0; |
| } |
| |
| /* |
| * Function: scsi_io_completion() |
| * |
| * Purpose: Completion processing for block device I/O requests. |
| * |
| * Arguments: SCpnt - command that is finished. |
| * |
| * Lock status: Assumed that no lock is held upon entry. |
| * |
| * Returns: Nothing |
| * |
| * Notes: This function is matched in terms of capabilities to |
| * the function that created the scatter-gather list. |
| * In other words, if there are no bounce buffers |
| * (the normal case for most drivers), we don't need |
| * the logic to deal with cleaning up afterwards. |
| */ |
| void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors, |
| int block_sectors) |
| { |
| int result = SCpnt->result; |
| int this_count = SCpnt->bufflen >> 9; |
| request_queue_t *q = &SCpnt->device->request_queue; |
| struct request *req = &SCpnt->request; |
| |
| /* |
| * We must do one of several things here: |
| * |
| * Call scsi_end_request. This will finish off the specified |
| * number of sectors. If we are done, the command block will |
| * be released, and the queue function will be goosed. If we |
| * are not done, then scsi_end_request will directly goose |
| * the queue. |
| * |
| * We can just use scsi_queue_next_request() here. This |
| * would be used if we just wanted to retry, for example. |
| * |
| */ |
| ASSERT_LOCK(q->queue_lock, 0); |
| |
| /* |
| * Free up any indirection buffers we allocated for DMA purposes. |
| * For the case of a READ, we need to copy the data out of the |
| * bounce buffer and into the real buffer. |
| */ |
| if (SCpnt->use_sg) { |
| struct scatterlist *sgpnt; |
| |
| sgpnt = (struct scatterlist *) SCpnt->buffer; |
| scsi_free_sgtable(SCpnt->buffer, SCpnt->sglist_len); |
| } else { |
| if (SCpnt->buffer != req->buffer) { |
| if (rq_data_dir(req) == READ) { |
| unsigned long flags; |
| char *to = bio_kmap_irq(req->bio, &flags); |
| |
| memcpy(to, SCpnt->buffer, SCpnt->bufflen); |
| bio_kunmap_irq(to, &flags); |
| } |
| kfree(SCpnt->buffer); |
| } |
| } |
| |
| /* |
| * Zero these out. They now point to freed memory, and it is |
| * dangerous to hang onto the pointers. |
| */ |
| SCpnt->buffer = NULL; |
| SCpnt->bufflen = 0; |
| SCpnt->request_buffer = NULL; |
| SCpnt->request_bufflen = 0; |
| |
| /* |
| * Next deal with any sectors which we were able to correctly |
| * handle. |
| */ |
| if (good_sectors > 0) { |
| SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, %d sectors done.\n", |
| req->nr_sectors, good_sectors)); |
| SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n ", SCpnt->use_sg)); |
| |
| req->errors = 0; |
| /* |
| * If multiple sectors are requested in one buffer, then |
| * they will have been finished off by the first command. |
| * If not, then we have a multi-buffer command. |
| * |
| * If block_sectors != 0, it means we had a medium error |
| * of some sort, and that we want to mark some number of |
| * sectors as not uptodate. Thus we want to inhibit |
| * requeueing right here - we will requeue down below |
| * when we handle the bad sectors. |
| */ |
| SCpnt = __scsi_end_request(SCpnt, |
| 1, |
| good_sectors, |
| result == 0, |
| 1); |
| |
| /* |
| * If the command completed without error, then either finish off the |
| * rest of the command, or start a new one. |
| */ |
| if (result == 0 || SCpnt == NULL ) { |
| return; |
| } |
| } |
| /* |
| * Now, if we were good little boys and girls, Santa left us a request |
| * sense buffer. We can extract information from this, so we |
| * can choose a block to remap, etc. |
| */ |
| if (driver_byte(result) != 0) { |
| if (suggestion(result) == SUGGEST_REMAP) { |
| #ifdef REMAP |
| /* |
| * Not yet implemented. A read will fail after being remapped, |
| * a write will call the strategy routine again. |
| */ |
| if (SCpnt->device->remap) { |
| result = 0; |
| } |
| #endif |
| } |
| if ((SCpnt->sense_buffer[0] & 0x7f) == 0x70) { |
| /* |
| * If the device is in the process of becoming ready, |
| * retry. |
| */ |
| if (SCpnt->sense_buffer[12] == 0x04 && |
| SCpnt->sense_buffer[13] == 0x01) { |
| scsi_queue_next_request(q, SCpnt); |
| return; |
| } |
| if ((SCpnt->sense_buffer[2] & 0xf) == UNIT_ATTENTION) { |
| if (SCpnt->device->removable) { |
| /* detected disc change. set a bit |
| * and quietly refuse further access. |
| */ |
| SCpnt->device->changed = 1; |
| SCpnt = scsi_end_request(SCpnt, 0, this_count); |
| return; |
| } else { |
| /* |
| * Must have been a power glitch, or a |
| * bus reset. Could not have been a |
| * media change, so we just retry the |
| * request and see what happens. |
| */ |
| scsi_queue_next_request(q, SCpnt); |
| return; |
| } |
| } |
| } |
| /* If we had an ILLEGAL REQUEST returned, then we may have |
| * performed an unsupported command. The only thing this should be |
| * would be a ten byte read where only a six byte read was supported. |
| * Also, on a system where READ CAPACITY failed, we have have read |
| * past the end of the disk. |
| */ |
| |
| switch (SCpnt->sense_buffer[2]) { |
| case ILLEGAL_REQUEST: |
| if (SCpnt->device->ten) { |
| SCpnt->device->ten = 0; |
| /* |
| * This will cause a retry with a 6-byte |
| * command. |
| */ |
| scsi_queue_next_request(q, SCpnt); |
| result = 0; |
| } else { |
| SCpnt = scsi_end_request(SCpnt, 0, this_count); |
| return; |
| } |
| break; |
| case NOT_READY: |
| printk(KERN_INFO "Device %s not ready.\n", |
| kdevname(req->rq_dev)); |
| SCpnt = scsi_end_request(SCpnt, 0, this_count); |
| return; |
| break; |
| case MEDIUM_ERROR: |
| case VOLUME_OVERFLOW: |
| printk("scsi%d: ERROR on channel %d, id %d, lun %d, CDB: ", |
| SCpnt->host->host_no, (int) SCpnt->channel, |
| (int) SCpnt->target, (int) SCpnt->lun); |
| print_command(SCpnt->cmnd); |
| print_sense("sd", SCpnt); |
| SCpnt = scsi_end_request(SCpnt, 0, block_sectors); |
| return; |
| default: |
| break; |
| } |
| } /* driver byte != 0 */ |
| if (host_byte(result) == DID_RESET) { |
| /* |
| * Third party bus reset or reset for error |
| * recovery reasons. Just retry the request |
| * and see what happens. |
| */ |
| scsi_queue_next_request(q, SCpnt); |
| return; |
| } |
| if (result) { |
| struct Scsi_Device_Template *STpnt; |
| |
| STpnt = scsi_get_request_dev(&SCpnt->request); |
| printk("SCSI %s error : host %d channel %d id %d lun %d return code = %x\n", |
| (STpnt ? STpnt->name : "device"), |
| SCpnt->device->host->host_no, |
| SCpnt->device->channel, |
| SCpnt->device->id, |
| SCpnt->device->lun, result); |
| |
| if (driver_byte(result) & DRIVER_SENSE) |
| print_sense("sd", SCpnt); |
| /* |
| * Mark a single buffer as not uptodate. Queue the remainder. |
| * We sometimes get this cruft in the event that a medium error |
| * isn't properly reported. |
| */ |
| SCpnt = scsi_end_request(SCpnt, 0, req->current_nr_sectors); |
| return; |
| } |
| } |
| |
| /* |
| * Function: scsi_get_request_dev() |
| * |
| * Purpose: Find the upper-level driver that is responsible for this |
| * request |
| * |
| * Arguments: request - I/O request we are preparing to queue. |
| * |
| * Lock status: No locks assumed to be held, but as it happens the |
| * q->queue_lock is held when this is called. |
| * |
| * Returns: Nothing |
| * |
| * Notes: The requests in the request queue may have originated |
| * from any block device driver. We need to find out which |
| * one so that we can later form the appropriate command. |
| */ |
| struct Scsi_Device_Template *scsi_get_request_dev(struct request *req) |
| { |
| struct Scsi_Device_Template *spnt; |
| kdev_t dev = req->rq_dev; |
| int major = major(dev); |
| |
| for (spnt = scsi_devicelist; spnt; spnt = spnt->next) { |
| /* |
| * Search for a block device driver that supports this |
| * major. |
| */ |
| if (spnt->blk && spnt->major == major) { |
| return spnt; |
| } |
| /* |
| * I am still not entirely satisfied with this solution, |
| * but it is good enough for now. Disks have a number of |
| * major numbers associated with them, the primary |
| * 8, which we test above, and a secondary range of 7 |
| * different consecutive major numbers. If this ever |
| * becomes insufficient, then we could add another function |
| * to the structure, and generalize this completely. |
| */ |
| if( spnt->min_major != 0 |
| && spnt->max_major != 0 |
| && major >= spnt->min_major |
| && major <= spnt->max_major ) |
| { |
| return spnt; |
| } |
| } |
| return NULL; |
| } |
| |
| /* |
| * Function: scsi_request_fn() |
| * |
| * Purpose: Generic version of request function for SCSI hosts. |
| * |
| * Arguments: q - Pointer to actual queue. |
| * |
| * Returns: Nothing |
| * |
| * Lock status: IO request lock assumed to be held when called. |
| * |
| * Notes: The theory is that this function is something which individual |
| * drivers could also supply if they wished to. The problem |
| * is that we have 30 some odd low-level drivers in the kernel |
| * tree already, and it would be most difficult to retrofit |
| * this crap into all of them. Thus this function has the job |
| * of acting as a generic queue manager for all of those existing |
| * drivers. |
| */ |
| void scsi_request_fn(request_queue_t * q) |
| { |
| struct request *req; |
| Scsi_Cmnd *SCpnt; |
| Scsi_Request *SRpnt; |
| Scsi_Device *SDpnt; |
| struct Scsi_Host *SHpnt; |
| struct Scsi_Device_Template *STpnt; |
| |
| ASSERT_LOCK(q->queue_lock, 1); |
| |
| SDpnt = (Scsi_Device *) q->queuedata; |
| if (!SDpnt) { |
| panic("Missing device"); |
| } |
| SHpnt = SDpnt->host; |
| |
| /* |
| * To start with, we keep looping until the queue is empty, or until |
| * the host is no longer able to accept any more requests. |
| */ |
| while (1 == 1) { |
| /* |
| * Check this again - each time we loop through we will have |
| * released the lock and grabbed it again, so each time |
| * we need to check to see if the queue is plugged or not. |
| */ |
| if (SHpnt->in_recovery || blk_queue_plugged(q)) |
| return; |
| |
| /* |
| * If the device cannot accept another request, then quit. |
| */ |
| if (SDpnt->device_blocked) { |
| break; |
| } |
| if ((SHpnt->can_queue > 0 && (SHpnt->host_busy >= SHpnt->can_queue)) |
| || (SHpnt->host_blocked) |
| || (SHpnt->host_self_blocked)) { |
| /* |
| * If we are unable to process any commands at all for |
| * this device, then we consider it to be starved. |
| * What this means is that there are no outstanding |
| * commands for this device and hence we need a |
| * little help getting it started again |
| * once the host isn't quite so busy. |
| */ |
| if (SDpnt->device_busy == 0) { |
| SDpnt->starved = 1; |
| SHpnt->some_device_starved = 1; |
| } |
| break; |
| } else { |
| SDpnt->starved = 0; |
| } |
| |
| /* |
| * FIXME(eric) |
| * I am not sure where the best place to do this is. We need |
| * to hook in a place where we are likely to come if in user |
| * space. Technically the error handling thread should be |
| * doing this crap, but the error handler isn't used by |
| * most hosts. |
| */ |
| if (SDpnt->was_reset) { |
| /* |
| * We need to relock the door, but we might |
| * be in an interrupt handler. Only do this |
| * from user space, since we do not want to |
| * sleep from an interrupt. |
| * |
| * FIXME(eric) - have the error handler thread do |
| * this work. |
| */ |
| SDpnt->was_reset = 0; |
| if (SDpnt->removable && !in_interrupt()) { |
| spin_unlock_irq(q->queue_lock); |
| scsi_ioctl(SDpnt, SCSI_IOCTL_DOORLOCK, 0); |
| spin_lock_irq(q->queue_lock); |
| continue; |
| } |
| } |
| |
| /* |
| * If we couldn't find a request that could be queued, then we |
| * can also quit. |
| */ |
| if (blk_queue_empty(q)) |
| break; |
| |
| /* |
| * get next queueable request. |
| */ |
| req = elv_next_request(q); |
| |
| /* |
| * Find the actual device driver associated with this command. |
| * The SPECIAL requests are things like character device or |
| * ioctls, which did not originate from ll_rw_blk. Note that |
| * the special field is also used to indicate the SCpnt for |
| * the remainder of a partially fulfilled request that can |
| * come up when there is a medium error. We have to treat |
| * these two cases differently. We differentiate by looking |
| * at request.cmd, as this tells us the real story. |
| */ |
| if (req->flags & REQ_SPECIAL) { |
| STpnt = NULL; |
| SCpnt = (Scsi_Cmnd *) req->special; |
| SRpnt = (Scsi_Request *) req->special; |
| |
| if( SRpnt->sr_magic == SCSI_REQ_MAGIC ) { |
| SCpnt = scsi_allocate_device(SRpnt->sr_device, |
| FALSE, FALSE); |
| if (!SCpnt) |
| break; |
| scsi_init_cmd_from_req(SCpnt, SRpnt); |
| } |
| |
| } else if (req->flags & REQ_CMD) { |
| SRpnt = NULL; |
| STpnt = scsi_get_request_dev(req); |
| if (!STpnt) { |
| panic("Unable to find device associated with request"); |
| } |
| /* |
| * Now try and find a command block that we can use. |
| */ |
| if (req->special) { |
| SCpnt = (Scsi_Cmnd *) req->special; |
| } else { |
| SCpnt = scsi_allocate_device(SDpnt, FALSE, FALSE); |
| } |
| /* |
| * If so, we are ready to do something. Bump the count |
| * while the queue is locked and then break out of the |
| * loop. Otherwise loop around and try another request. |
| */ |
| if (!SCpnt) |
| break; |
| } else { |
| blk_dump_rq_flags(req, "SCSI bad req"); |
| break; |
| } |
| |
| /* |
| * Now bump the usage count for both the host and the |
| * device. |
| */ |
| SHpnt->host_busy++; |
| SDpnt->device_busy++; |
| |
| /* |
| * Finally, before we release the lock, we copy the |
| * request to the command block, and remove the |
| * request from the request list. Note that we always |
| * operate on the queue head - there is absolutely no |
| * reason to search the list, because all of the commands |
| * in this queue are for the same device. |
| */ |
| blkdev_dequeue_request(req); |
| |
| if (req != &SCpnt->request && req != &SRpnt->sr_request ) { |
| memcpy(&SCpnt->request, req, sizeof(struct request)); |
| |
| /* |
| * We have copied the data out of the request block - |
| * it is now in a field in SCpnt. Release the request |
| * block. |
| */ |
| blkdev_release_request(req); |
| } |
| /* |
| * Now it is finally safe to release the lock. We are |
| * not going to noodle the request list until this |
| * request has been queued and we loop back to queue |
| * another. |
| */ |
| req = NULL; |
| spin_unlock_irq(q->queue_lock); |
| |
| if (SCpnt->request.flags & REQ_CMD) { |
| /* |
| * This will do a couple of things: |
| * 1) Fill in the actual SCSI command. |
| * 2) Fill in any other upper-level specific fields |
| * (timeout). |
| * |
| * If this returns 0, it means that the request failed |
| * (reading past end of disk, reading offline device, |
| * etc). This won't actually talk to the device, but |
| * some kinds of consistency checking may cause the |
| * request to be rejected immediately. |
| */ |
| if (STpnt == NULL) |
| STpnt = scsi_get_request_dev(&SCpnt->request); |
| |
| /* |
| * This sets up the scatter-gather table (allocating if |
| * required). |
| */ |
| if (!scsi_init_io(SCpnt)) { |
| spin_lock_irq(q->queue_lock); |
| SHpnt->host_busy--; |
| SDpnt->device_busy--; |
| if (SDpnt->device_busy == 0) { |
| SDpnt->starved = 1; |
| SHpnt->some_device_starved = 1; |
| } |
| SCpnt->request.special = SCpnt; |
| SCpnt->request.flags |= REQ_SPECIAL; |
| _elv_add_request(q, &SCpnt->request, 0, 0); |
| break; |
| } |
| |
| /* |
| * Initialize the actual SCSI command for this request. |
| */ |
| if (!STpnt->init_command(SCpnt)) { |
| scsi_release_buffers(SCpnt); |
| SCpnt = __scsi_end_request(SCpnt, 0, |
| SCpnt->request.nr_sectors, 0, 0); |
| if( SCpnt != NULL ) |
| { |
| panic("Should not have leftover blocks\n"); |
| } |
| spin_lock_irq(q->queue_lock); |
| SHpnt->host_busy--; |
| SDpnt->device_busy--; |
| continue; |
| } |
| } |
| /* |
| * Finally, initialize any error handling parameters, and set up |
| * the timers for timeouts. |
| */ |
| scsi_init_cmd_errh(SCpnt); |
| |
| /* |
| * Dispatch the command to the low-level driver. |
| */ |
| scsi_dispatch_cmd(SCpnt); |
| |
| /* |
| * Now we need to grab the lock again. We are about to mess |
| * with the request queue and try to find another command. |
| */ |
| spin_lock_irq(q->queue_lock); |
| } |
| } |
| |
| /* |
| * Function: scsi_block_requests() |
| * |
| * Purpose: Utility function used by low-level drivers to prevent further |
| * commands from being queued to the device. |
| * |
| * Arguments: SHpnt - Host in question |
| * |
| * Returns: Nothing |
| * |
| * Lock status: No locks are assumed held. |
| * |
| * Notes: There is no timer nor any other means by which the requests |
| * get unblocked other than the low-level driver calling |
| * scsi_unblock_requests(). |
| */ |
| void scsi_block_requests(struct Scsi_Host * SHpnt) |
| { |
| SHpnt->host_self_blocked = TRUE; |
| } |
| |
| /* |
| * Function: scsi_unblock_requests() |
| * |
| * Purpose: Utility function used by low-level drivers to allow further |
| * commands from being queued to the device. |
| * |
| * Arguments: SHpnt - Host in question |
| * |
| * Returns: Nothing |
| * |
| * Lock status: No locks are assumed held. |
| * |
| * Notes: There is no timer nor any other means by which the requests |
| * get unblocked other than the low-level driver calling |
| * scsi_unblock_requests(). |
| * |
| * This is done as an API function so that changes to the |
| * internals of the scsi mid-layer won't require wholesale |
| * changes to drivers that use this feature. |
| */ |
| void scsi_unblock_requests(struct Scsi_Host * SHpnt) |
| { |
| Scsi_Device *SDloop; |
| |
| SHpnt->host_self_blocked = FALSE; |
| /* Now that we are unblocked, try to start the queues. */ |
| for (SDloop = SHpnt->host_queue; SDloop; SDloop = SDloop->next) |
| scsi_queue_next_request(&SDloop->request_queue, NULL); |
| } |
| |
| /* |
| * Function: scsi_report_bus_reset() |
| * |
| * Purpose: Utility function used by low-level drivers to report that |
| * they have observed a bus reset on the bus being handled. |
| * |
| * Arguments: SHpnt - Host in question |
| * channel - channel on which reset was observed. |
| * |
| * Returns: Nothing |
| * |
| * Lock status: No locks are assumed held. |
| * |
| * Notes: This only needs to be called if the reset is one which |
| * originates from an unknown location. Resets originated |
| * by the mid-level itself don't need to call this, but there |
| * should be no harm. |
| * |
| * The main purpose of this is to make sure that a CHECK_CONDITION |
| * is properly treated. |
| */ |
| void scsi_report_bus_reset(struct Scsi_Host * SHpnt, int channel) |
| { |
| Scsi_Device *SDloop; |
| for (SDloop = SHpnt->host_queue; SDloop; SDloop = SDloop->next) { |
| if (channel == SDloop->channel) { |
| SDloop->was_reset = 1; |
| SDloop->expecting_cc_ua = 1; |
| } |
| } |
| } |
| |
| /* |
| * FIXME(eric) - these are empty stubs for the moment. I need to re-implement |
| * host blocking from scratch. The theory is that hosts that wish to block |
| * will register/deregister using these functions instead of the old way |
| * of setting the wish_block flag. |
| * |
| * The details of the implementation remain to be settled, however the |
| * stubs are here now so that the actual drivers will properly compile. |
| */ |
| void scsi_register_blocked_host(struct Scsi_Host * SHpnt) |
| { |
| } |
| |
| void scsi_deregister_blocked_host(struct Scsi_Host * SHpnt) |
| { |
| } |