/* * 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. */ #define __NO_VERSION__ #include #include #include #include #include #include #include #include #include #include #include #include #include #define __KERNEL_SYSCALLS__ #include #include #include #include #include "scsi.h" #include "hosts.h" #include "constants.h" #include /* * 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 io_request_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(&io_request_lock, 0); rq->cmd = SPECIAL; rq->special = data; rq->q = NULL; rq->nr_segments = 0; rq->elevator_sequence = 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(&io_request_lock, flags); if (at_head) list_add(&rq->queue, &q->queue_head); else list_add_tail(&rq->queue, &q->queue_head); q->request_fn(q); spin_unlock_irqrestore(&io_request_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) { ASSERT_LOCK(&io_request_lock, 0); 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(&io_request_lock, 0); spin_lock_irqsave(&io_request_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; list_add(&SCpnt->request.queue, &q->queue_head); } /* * 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 && list_empty(&q->queue_head) && 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(&io_request_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) { struct request *req; struct buffer_head *bh; Scsi_Device * SDpnt; int nsect; ASSERT_LOCK(&io_request_lock, 0); req = &SCpnt->request; req->errors = 0; if (!uptodate) { printk(" I/O error: dev %s, sector %lu\n", kdevname(req->rq_dev), req->sector); } do { if ((bh = req->bh) != NULL) { nsect = bh->b_size >> 9; blk_finished_io(nsect); req->bh = bh->b_reqnext; bh->b_reqnext = NULL; sectors -= nsect; bh->b_end_io(bh, uptodate); if ((bh = req->bh) != NULL) { req->hard_sector += nsect; req->hard_nr_sectors -= nsect; req->sector += nsect; req->nr_sectors -= nsect; req->current_nr_sectors = bh->b_size >> 9; if (req->nr_sectors < req->current_nr_sectors) { req->nr_sectors = req->current_nr_sectors; printk("scsi_end_request: buffer-list destroyed\n"); } } } } while (sectors && bh); /* * If there are blocks left over at the end, set up the command * to queue the remainder of them. */ if (req->bh) { request_queue_t *q; if( !requeue ) { return SCpnt; } q = &SCpnt->device->request_queue; req->buffer = bh->b_data; /* * 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. Typically used to wake up processes trying * to swap a page into memory. */ if (req->waiting != NULL) { complete(req->waiting); } add_blkdev_randomness(MAJOR(req->rq_dev)); SDpnt = SCpnt->device; /* * 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 ) { request_queue_t *q; q = &SDpnt->request_queue; 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) { ASSERT_LOCK(&io_request_lock, 0); /* * Free up any indirection buffers we allocated for DMA purposes. */ if (SCpnt->use_sg) { struct scatterlist *sgpnt; void **bbpnt; int i; sgpnt = (struct scatterlist *) SCpnt->request_buffer; bbpnt = SCpnt->bounce_buffers; if (bbpnt) { for (i = 0; i < SCpnt->use_sg; i++) { if (bbpnt[i]) scsi_free(sgpnt[i].address, sgpnt[i].length); } } scsi_free(SCpnt->request_buffer, SCpnt->sglist_len); } else { if (SCpnt->request_buffer != SCpnt->request.buffer) { scsi_free(SCpnt->request_buffer, SCpnt->request_bufflen); } } /* * 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; /* * 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(&io_request_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; void **bbpnt; int i; sgpnt = (struct scatterlist *) SCpnt->buffer; bbpnt = SCpnt->bounce_buffers; if (bbpnt) { for (i = 0; i < SCpnt->use_sg; i++) { if (bbpnt[i]) { if (SCpnt->request.cmd == READ) { memcpy(bbpnt[i], sgpnt[i].address, sgpnt[i].length); } scsi_free(sgpnt[i].address, sgpnt[i].length); } } } scsi_free(SCpnt->buffer, SCpnt->sglist_len); } else { if (SCpnt->buffer != SCpnt->request.buffer) { if (SCpnt->request.cmd == READ) { memcpy(SCpnt->request.buffer, SCpnt->buffer, SCpnt->bufflen); } scsi_free(SCpnt->buffer, SCpnt->bufflen); } } /* * 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", SCpnt->request.nr_sectors, good_sectors)); SCSI_LOG_HLCOMPLETE(1, printk("use_sg is %d\n ", SCpnt->use_sg)); SCpnt->request.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(SCpnt->request.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, SCpnt->request.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 * io_request_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); ASSERT_LOCK(&io_request_lock, 1); 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(&io_request_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 || q->plugged) 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(&io_request_lock); scsi_ioctl(SDpnt, SCSI_IOCTL_DOORLOCK, 0); spin_lock_irq(&io_request_lock); continue; } } /* * If we couldn't find a request that could be queued, then we * can also quit. */ if (list_empty(&q->queue_head)) break; /* * Loop through all of the requests in this queue, and find * one that is queueable. */ req = blkdev_entry_next_request(&q->queue_head); /* * 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->cmd == 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 { 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 != NULL ) { SCpnt = (Scsi_Cmnd *) req->special; /* * We need to recount the number of * scatter-gather segments here - the * normal case code assumes this to be * correct, as it would be a performance * lose to always recount. Handling * errors is always unusual, of course. */ recount_segments(SCpnt); } 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; } } /* * 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(&io_request_lock); if (SCpnt->request.cmd != SPECIAL) { /* * 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(req); } /* * This sets up the scatter-gather table (allocating if * required). Hosts that need bounce buffers will also * get those allocated here. */ if (!SDpnt->scsi_init_io_fn(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(&io_request_lock); SHpnt->host_busy--; SDpnt->device_busy--; continue; } /* * 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(&io_request_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(&io_request_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) { }