Beispiel #1
0
void blk_add_driver_data(struct request_queue *q,
			 struct request *rq,
			 void *data, size_t len)
{
	struct blk_trace *bt = q->blk_trace;

	if (likely(!bt))
		return;

	if (blk_pc_request(rq))
		__blk_add_trace(bt, 0, blk_rq_bytes(rq), 0,
				BLK_TA_DRV_DATA, rq->errors, len, data);
	else
		__blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), 0,
				BLK_TA_DRV_DATA, rq->errors, len, data);
}
Beispiel #2
0
static int ide_floppy_callback(ide_drive_t *drive, int dsc)
{
	struct ide_disk_obj *floppy = drive->driver_data;
	struct ide_atapi_pc *pc = drive->pc;
	struct request *rq = pc->rq;
	int uptodate = pc->error ? 0 : 1;

	ide_debug_log(IDE_DBG_FUNC, "enter");

	if (drive->failed_pc == pc)
		drive->failed_pc = NULL;

	if (pc->c[0] == GPCMD_READ_10 || pc->c[0] == GPCMD_WRITE_10 ||
	    (rq && blk_pc_request(rq)))
		uptodate = 1; 
	else if (pc->c[0] == GPCMD_REQUEST_SENSE) {

		u8 *buf = bio_data(rq->bio);

		if (!pc->error) {
			floppy->sense_key = buf[2] & 0x0F;
			floppy->asc = buf[12];
			floppy->ascq = buf[13];
			floppy->progress_indication = buf[15] & 0x80 ?
				(u16)get_unaligned((u16 *)&buf[16]) : 0x10000;

			if (drive->failed_pc)
				ide_debug_log(IDE_DBG_PC, "pc = %x",
					      drive->failed_pc->c[0]);

			ide_debug_log(IDE_DBG_SENSE, "sense key = %x, asc = %x,"
				      "ascq = %x", floppy->sense_key,
				      floppy->asc, floppy->ascq);
		} else
			printk(KERN_ERR PFX "Error in REQUEST SENSE itself - "
			       "Aborting request!\n");
	}

	if (blk_special_request(rq))
		rq->errors = uptodate ? 0 : IDE_DRV_ERROR_GENERAL;

	return uptodate;
}
Beispiel #3
0
/**
 * blk_add_trace_rq - Add a trace for a request oriented action
 * @q:		queue the io is for
 * @rq:		the source request
 * @what:	the action
 *
 * Description:
 *     Records an action against a request. Will log the bio offset + size.
 *
 **/
static void blk_add_trace_rq(struct request_queue *q, struct request *rq,
				    u32 what)
{
	struct blk_trace *bt = q->blk_trace;
	int rw = rq->cmd_flags & 0x03;

	if (likely(!bt))
		return;

	if (blk_discard_rq(rq))
		rw |= (1 << BIO_RW_DISCARD);

	if (blk_pc_request(rq)) {
		what |= BLK_TC_ACT(BLK_TC_PC);
		__blk_add_trace(bt, 0, rq->data_len, rw, what, rq->errors,
				sizeof(rq->cmd), rq->cmd);
	} else  {
		what |= BLK_TC_ACT(BLK_TC_FS);
		__blk_add_trace(bt, rq->hard_sector, rq->hard_nr_sectors << 9,
				rw, what, rq->errors, 0, NULL);
	}
}
static int card_prep_request(struct request_queue *q, struct request *req)
{
	struct card_queue *cq = q->queuedata;
	int ret = BLKPREP_KILL;

	if (!cq) {
		//printk(KERN_ERR "[card_prep_request] %s: killing request - no device/host\n", req->rq_disk->disk_name);
		return BLKPREP_KILL;
	}
	
	if (blk_special_request(req)) {
		/*
		 * Special commands already have the command
		 * blocks already setup in req->special.
		 */
		BUG_ON(!req->special);

		ret = BLKPREP_OK;
	} else if (blk_fs_request(req) || blk_pc_request(req)) {
		/*
		 * Block I/O requests need translating according
		 * to the protocol.
		 */
		ret = cq->prep_fn(cq, req);
	} else {
		/*
		 * Everything else is invalid.
		 */
		blk_dump_rq_flags(req, "CARD bad request");
	}

	if (ret == BLKPREP_OK)
		req->cmd_flags |= REQ_DONTPREP;

	return ret;
}
Beispiel #5
0
void blk_dump_cmd(char *buf, struct request *rq)
{
	int i, end;
	int len = rq->cmd_len;
	unsigned char *cmd = rq->cmd;

	if (!blk_pc_request(rq)) {
		buf[0] = '\0';
		return;
	}

	for (end = len - 1; end >= 0; end--)
		if (cmd[end])
			break;
	end++;

	for (i = 0; i < len; i++) {
		buf += sprintf(buf, "%s%02x", i == 0 ? "" : " ", cmd[i]);
		if (i == end && end != len - 1) {
			sprintf(buf, " ..");
			break;
		}
	}
}
Beispiel #6
0
static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive,
					     struct request *rq, sector_t block)
{
	struct ide_disk_obj *floppy = drive->driver_data;
	struct ide_cmd cmd;
	struct ide_atapi_pc *pc;

	ide_debug_log(IDE_DBG_FUNC, "enter, cmd: 0x%x\n", rq->cmd[0]);

	if (drive->debug_mask & IDE_DBG_RQ)
		blk_dump_rq_flags(rq, (rq->rq_disk
					? rq->rq_disk->disk_name
					: "dev?"));

	if (rq->errors >= ERROR_MAX) {
		if (drive->failed_pc) {
			ide_floppy_report_error(floppy, drive->failed_pc);
			drive->failed_pc = NULL;
		} else
			printk(KERN_ERR PFX "%s: I/O error\n", drive->name);

		if (blk_special_request(rq)) {
			rq->errors = 0;
			ide_complete_rq(drive, 0, blk_rq_bytes(rq));
			return ide_stopped;
		} else
			goto out_end;
	}
	if (blk_fs_request(rq)) {
		if (((long)blk_rq_pos(rq) % floppy->bs_factor) ||
		    (blk_rq_sectors(rq) % floppy->bs_factor)) {
			printk(KERN_ERR PFX "%s: unsupported r/w rq size\n",
				drive->name);
			goto out_end;
		}
		pc = &floppy->queued_pc;
		idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block);
	} else if (blk_special_request(rq) || blk_sense_request(rq)) {
		pc = (struct ide_atapi_pc *)rq->special;
	} else if (blk_pc_request(rq)) {
		pc = &floppy->queued_pc;
		idefloppy_blockpc_cmd(floppy, pc, rq);
	} else
		BUG();

	ide_prep_sense(drive, rq);

	memset(&cmd, 0, sizeof(cmd));

	if (rq_data_dir(rq))
		cmd.tf_flags |= IDE_TFLAG_WRITE;

	cmd.rq = rq;

	if (blk_fs_request(rq) || blk_rq_bytes(rq)) {
		ide_init_sg_cmd(&cmd, blk_rq_bytes(rq));
		ide_map_sg(drive, &cmd);
	}

	pc->rq = rq;

	return ide_floppy_issue_pc(drive, &cmd, pc);
out_end:
	drive->failed_pc = NULL;
	if (blk_fs_request(rq) == 0 && rq->errors == 0)
		rq->errors = -EIO;
	ide_complete_rq(drive, -EIO, blk_rq_bytes(rq));
	return ide_stopped;
}
Beispiel #7
0
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
	ide_hwif_t *hwif = drive->hwif;
	struct ide_cmd *cmd = &hwif->cmd;
	struct request *rq = hwif->rq;
	ide_expiry_t *expiry = NULL;
	int dma_error = 0, dma, stat, thislen, uptodate = 0;
	int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc, nsectors;
	int sense = blk_sense_request(rq);
	unsigned int timeout;
	u16 len;
	u8 ireason;

	ide_debug_log(IDE_DBG_PC, "cmd[0]: 0x%x, write: 0x%x",
				  rq->cmd[0], write);

	/* check for errors */
	dma = drive->dma;
	if (dma) {
		drive->dma = 0;
		drive->waiting_for_dma = 0;
		dma_error = hwif->dma_ops->dma_end(drive);
		ide_dma_unmap_sg(drive, cmd);
		if (dma_error) {
			printk(KERN_ERR PFX "%s: DMA %s error\n", drive->name,
					write ? "write" : "read");
			ide_dma_off(drive);
		}
	}

	rc = cdrom_decode_status(drive, 0, &stat);
	if (rc) {
		if (rc == 2)
			goto out_end;
		return ide_stopped;
	}

	/* using dma, transfer is complete now */
	if (dma) {
		if (dma_error)
			return ide_error(drive, "dma error", stat);
		uptodate = 1;
		goto out_end;
	}

	ide_read_bcount_and_ireason(drive, &len, &ireason);

	thislen = blk_fs_request(rq) ? len : cmd->nleft;
	if (thislen > len)
		thislen = len;

	ide_debug_log(IDE_DBG_PC, "DRQ: stat: 0x%x, thislen: %d",
				  stat, thislen);

	/* If DRQ is clear, the command has completed. */
	if ((stat & ATA_DRQ) == 0) {
		if (blk_fs_request(rq)) {
			/*
			 * If we're not done reading/writing, complain.
			 * Otherwise, complete the command normally.
			 */
			uptodate = 1;
			if (cmd->nleft > 0) {
				printk(KERN_ERR PFX "%s: %s: data underrun "
					"(%u bytes)\n", drive->name, __func__,
					cmd->nleft);
				if (!write)
					rq->cmd_flags |= REQ_FAILED;
				uptodate = 0;
			}
		} else if (!blk_pc_request(rq)) {
			ide_cd_request_sense_fixup(drive, cmd);
			/* complain if we still have data left to transfer */
			uptodate = cmd->nleft ? 0 : 1;
			if (uptodate == 0)
				rq->cmd_flags |= REQ_FAILED;
		}
		goto out_end;
	}

	/* check which way to transfer data */
	rc = ide_cd_check_ireason(drive, rq, len, ireason, write);
	if (rc)
		goto out_end;

	cmd->last_xfer_len = 0;

	ide_debug_log(IDE_DBG_PC, "data transfer, rq->cmd_type: 0x%x, "
				  "ireason: 0x%x",
				  rq->cmd_type, ireason);

	/* transfer data */
	while (thislen > 0) {
		int blen = min_t(int, thislen, cmd->nleft);

		if (cmd->nleft == 0)
			break;

		ide_pio_bytes(drive, cmd, write, blen);
		cmd->last_xfer_len += blen;

		thislen -= blen;
		len -= blen;

		if (sense && write == 0)
			rq->sense_len += blen;
	}

	/* pad, if necessary */
	if (len > 0) {
		if (blk_fs_request(rq) == 0 || write == 0)
			ide_pad_transfer(drive, write, len);
		else {
			printk(KERN_ERR PFX "%s: confused, missing data\n",
				drive->name);
			blk_dump_rq_flags(rq, "cdrom_newpc_intr");
		}
	}

	if (blk_pc_request(rq)) {
		timeout = rq->timeout;
	} else {
		timeout = ATAPI_WAIT_PC;
		if (!blk_fs_request(rq))
			expiry = ide_cd_expiry;
	}

	hwif->expiry = expiry;
	ide_set_handler(drive, cdrom_newpc_intr, timeout);
	return ide_started;

out_end:
	if (blk_pc_request(rq) && rc == 0) {
		unsigned int dlen = rq->data_len;

		rq->data_len = 0;

		if (blk_end_request(rq, 0, dlen))
			BUG();

		hwif->rq = NULL;
	} else {
		if (sense && uptodate)
			ide_cd_complete_failed_rq(drive, rq);

		if (blk_fs_request(rq)) {
			if (cmd->nleft == 0)
				uptodate = 1;
		} else {
			if (uptodate <= 0 && rq->errors == 0)
				rq->errors = -EIO;
		}

		if (uptodate == 0)
			ide_cd_error_cmd(drive, cmd);

		/* make sure it's fully ended */
		if (blk_pc_request(rq))
			nsectors = (rq->data_len + 511) >> 9;
		else
			nsectors = rq->hard_nr_sectors;

		if (nsectors == 0)
			nsectors = 1;

		if (blk_fs_request(rq) == 0) {
			rq->data_len -= (cmd->nbytes - cmd->nleft);
			if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE))
				rq->data_len += cmd->last_xfer_len;
		}

		ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9);

		if (sense && rc == 2)
			ide_error(drive, "request sense failure", stat);
	}
Beispiel #8
0
/*
 * Returns:
 * 0: if the request should be continued.
 * 1: if the request will be going through error recovery.
 * 2: if the request should be ended.
 */
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
	ide_hwif_t *hwif = drive->hwif;
	struct request *rq = hwif->rq;
	int stat, err, sense_key;

	/* check for errors */
	stat = hwif->tp_ops->read_status(hwif);

	if (stat_ret)
		*stat_ret = stat;

	if (OK_STAT(stat, good_stat, BAD_R_STAT))
		return 0;

	/* get the IDE error register */
	err = ide_read_error(drive);
	sense_key = err >> 4;

	ide_debug_log(IDE_DBG_RQ, "stat: 0x%x, good_stat: 0x%x, cmd[0]: 0x%x, "
				  "rq->cmd_type: 0x%x, err: 0x%x",
				  stat, good_stat, rq->cmd[0], rq->cmd_type,
				  err);

	if (blk_sense_request(rq)) {
		/*
		 * We got an error trying to get sense info from the drive
		 * (probably while trying to recover from a former error).
		 * Just give up.
		 */
		rq->cmd_flags |= REQ_FAILED;
		return 2;
	} else if (blk_pc_request(rq) || rq->cmd_type == REQ_TYPE_ATA_PC) {
		/* All other functions, except for READ. */

		/*
		 * if we have an error, pass back CHECK_CONDITION as the
		 * scsi status byte
		 */
		if (blk_pc_request(rq) && !rq->errors)
			rq->errors = SAM_STAT_CHECK_CONDITION;

		/* check for tray open */
		if (sense_key == NOT_READY) {
			cdrom_saw_media_change(drive);
		} else if (sense_key == UNIT_ATTENTION) {
			/* check for media change */
			cdrom_saw_media_change(drive);
			return 0;
		} else if (sense_key == ILLEGAL_REQUEST &&
			   rq->cmd[0] == GPCMD_START_STOP_UNIT) {
			/*
			 * Don't print error message for this condition--
			 * SFF8090i indicates that 5/24/00 is the correct
			 * response to a request to close the tray if the
			 * drive doesn't have that capability.
			 * cdrom_log_sense() knows this!
			 */
		} else if (!(rq->cmd_flags & REQ_QUIET)) {
			/* otherwise, print an error */
			ide_dump_status(drive, "packet command error", stat);
		}

		rq->cmd_flags |= REQ_FAILED;

		/*
		 * instead of playing games with moving completions around,
		 * remove failed request completely and end it when the
		 * request sense has completed
		 */
		goto end_request;

	} else if (blk_fs_request(rq)) {
		int do_end_request = 0;

		/* handle errors from READ and WRITE requests */

		if (blk_noretry_request(rq))
			do_end_request = 1;

		if (sense_key == NOT_READY) {
			/* tray open */
			if (rq_data_dir(rq) == READ) {
				cdrom_saw_media_change(drive);

				/* fail the request */
				printk(KERN_ERR PFX "%s: tray open\n",
						drive->name);
				do_end_request = 1;
			} else {
				struct cdrom_info *info = drive->driver_data;

				/*
				 * Allow the drive 5 seconds to recover, some
				 * devices will return this error while flushing
				 * data from cache.
				 */
				if (!rq->errors)
					info->write_timeout = jiffies +
							ATAPI_WAIT_WRITE_BUSY;
				rq->errors = 1;
				if (time_after(jiffies, info->write_timeout))
					do_end_request = 1;
				else {
					struct request_queue *q = drive->queue;
					unsigned long flags;

					/*
					 * take a breather relying on the unplug
					 * timer to kick us again
					 */
					spin_lock_irqsave(q->queue_lock, flags);
					blk_plug_device(q);
					spin_unlock_irqrestore(q->queue_lock, flags);

					return 1;
				}
			}
		} else if (sense_key == UNIT_ATTENTION) {
			/* media change */
			cdrom_saw_media_change(drive);

			/*
			 * Arrange to retry the request but be sure to give up
			 * if we've retried too many times.
			 */
			if (++rq->errors > ERROR_MAX)
				do_end_request = 1;
		} else if (sense_key == ILLEGAL_REQUEST ||
			   sense_key == DATA_PROTECT) {
			/*
			 * No point in retrying after an illegal request or data
			 * protect error.
			 */
			ide_dump_status(drive, "command error", stat);
			do_end_request = 1;
		} else if (sense_key == MEDIUM_ERROR) {
			/*
			 * No point in re-trying a zillion times on a bad
			 * sector. If we got here the error is not correctable.
			 */
			ide_dump_status(drive, "media error (bad sector)",
					stat);
			do_end_request = 1;
		} else if (sense_key == BLANK_CHECK) {
			/* disk appears blank ?? */
			ide_dump_status(drive, "media error (blank)", stat);
			do_end_request = 1;
		} else if ((err & ~ATA_ABORTED) != 0) {
			/* go to the default handler for other errors */
			ide_error(drive, "cdrom_decode_status", stat);
			return 1;
		} else if ((++rq->errors > ERROR_MAX)) {
			/* we've racked up too many retries, abort */
			do_end_request = 1;
		}

		/*
		 * End a request through request sense analysis when we have
		 * sense data. We need this in order to perform end of media
		 * processing.
		 */
		if (do_end_request)
			goto end_request;

		/*
		 * If we got a CHECK_CONDITION status, queue
		 * a request sense command.
		 */
		if (stat & ATA_ERR)
			cdrom_queue_request_sense(drive, NULL, NULL);
		return 1;
	} else {
		blk_dump_rq_flags(rq, PFX "bad rq");
		return 2;
	}

end_request:
	if (stat & ATA_ERR) {
		struct request_queue *q = drive->queue;
		unsigned long flags;

		spin_lock_irqsave(q->queue_lock, flags);
		blkdev_dequeue_request(rq);
		spin_unlock_irqrestore(q->queue_lock, flags);

		hwif->rq = NULL;

		cdrom_queue_request_sense(drive, rq->sense, rq);
		return 1;
	} else
		return 2;
}
Beispiel #9
0
/**
 *	sd_init_command - build a scsi (read or write) command from
 *	information in the request structure.
 *	@SCpnt: pointer to mid-level's per scsi command structure that
 *	contains request and into which the scsi command is written
 *
 *	Returns 1 if successful and 0 if error (or cannot be done now).
 **/
static int sd_init_command(struct scsi_cmnd * SCpnt)
{
	unsigned int this_count, timeout;
	struct gendisk *disk;
	sector_t block;
	struct scsi_device *sdp = SCpnt->device;
	struct request *rq = SCpnt->request;

	timeout = sdp->timeout;

	/*
	 * SG_IO from block layer already setup, just copy cdb basically
	 */
	if (blk_pc_request(rq)) {
		scsi_setup_blk_pc_cmnd(SCpnt, SD_PASSTHROUGH_RETRIES);
		if (rq->timeout)
			timeout = rq->timeout;

		goto queue;
	}

	/*
	 * we only do REQ_CMD and REQ_BLOCK_PC
	 */
	if (!blk_fs_request(rq))
		return 0;

	disk = rq->rq_disk;
	block = rq->sector;
	this_count = SCpnt->request_bufflen >> 9;

	SCSI_LOG_HLQUEUE(1, printk("sd_init_command: disk=%s, block=%llu, "
			    "count=%d\n", disk->disk_name,
			 (unsigned long long)block, this_count));

	if (!sdp || !scsi_device_online(sdp) ||
 	    block + rq->nr_sectors > get_capacity(disk)) {
		SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", 
				 rq->nr_sectors));
		SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
		return 0;
	}

	if (sdp->changed) {
		/*
		 * quietly refuse to do anything to a changed disc until 
		 * the changed bit has been reset
		 */
		/* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */
		return 0;
	}
	SCSI_LOG_HLQUEUE(2, printk("%s : block=%llu\n",
				   disk->disk_name, (unsigned long long)block));

	/*
	 * If we have a 1K hardware sectorsize, prevent access to single
	 * 512 byte sectors.  In theory we could handle this - in fact
	 * the scsi cdrom driver must be able to handle this because
	 * we typically use 1K blocksizes, and cdroms typically have
	 * 2K hardware sectorsizes.  Of course, things are simpler
	 * with the cdrom, since it is read-only.  For performance
	 * reasons, the filesystems should be able to handle this
	 * and not force the scsi disk driver to use bounce buffers
	 * for this.
	 */
	if (sdp->sector_size == 1024) {
		if ((block & 1) || (rq->nr_sectors & 1)) {
			printk(KERN_ERR "sd: Bad block number requested");
			return 0;
		} else {
			block = block >> 1;
			this_count = this_count >> 1;
		}
	}
	if (sdp->sector_size == 2048) {
		if ((block & 3) || (rq->nr_sectors & 3)) {
			printk(KERN_ERR "sd: Bad block number requested");
			return 0;
		} else {
			block = block >> 2;
			this_count = this_count >> 2;
		}
	}
	if (sdp->sector_size == 4096) {
		if ((block & 7) || (rq->nr_sectors & 7)) {
			printk(KERN_ERR "sd: Bad block number requested");
			return 0;
		} else {
			block = block >> 3;
			this_count = this_count >> 3;
		}
	}
	if (rq_data_dir(rq) == WRITE) {
		if (!sdp->writeable) {
			return 0;
		}
		SCpnt->cmnd[0] = WRITE_6;
		SCpnt->sc_data_direction = DMA_TO_DEVICE;
	} else if (rq_data_dir(rq) == READ) {
		SCpnt->cmnd[0] = READ_6;
		SCpnt->sc_data_direction = DMA_FROM_DEVICE;
	} else {
		printk(KERN_ERR "sd: Unknown command %lx\n", rq->flags);
/* overkill 	panic("Unknown sd command %lx\n", rq->flags); */
		return 0;
	}

	SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", 
		disk->disk_name, (rq_data_dir(rq) == WRITE) ? 
		"writing" : "reading", this_count, rq->nr_sectors));

	SCpnt->cmnd[1] = 0;
	
	if (block > 0xffffffff) {
		SCpnt->cmnd[0] += READ_16 - READ_6;
		SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0;
		SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0;
		SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0;
		SCpnt->cmnd[5] = sizeof(block) > 4 ? (unsigned char) (block >> 32) & 0xff : 0;
		SCpnt->cmnd[6] = (unsigned char) (block >> 24) & 0xff;
		SCpnt->cmnd[7] = (unsigned char) (block >> 16) & 0xff;
		SCpnt->cmnd[8] = (unsigned char) (block >> 8) & 0xff;
		SCpnt->cmnd[9] = (unsigned char) block & 0xff;
		SCpnt->cmnd[10] = (unsigned char) (this_count >> 24) & 0xff;
		SCpnt->cmnd[11] = (unsigned char) (this_count >> 16) & 0xff;
		SCpnt->cmnd[12] = (unsigned char) (this_count >> 8) & 0xff;
		SCpnt->cmnd[13] = (unsigned char) this_count & 0xff;
		SCpnt->cmnd[14] = SCpnt->cmnd[15] = 0;
	} else if ((this_count > 0xff) || (block > 0x1fffff) ||