summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ide-scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ide-scsi.c')
-rw-r--r--drivers/scsi/ide-scsi.c65
1 files changed, 32 insertions, 33 deletions
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index f843c1383a4b..b40a673985aa 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -84,7 +84,6 @@ typedef struct ide_scsi_obj {
struct Scsi_Host *host;
struct ide_atapi_pc *pc; /* Current packet command */
- unsigned long flags; /* Status/Action flags */
unsigned long transform; /* SCSI cmd translation layer */
unsigned long log; /* log flags */
} idescsi_scsi_t;
@@ -102,8 +101,13 @@ static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk)
mutex_lock(&idescsi_ref_mutex);
scsi = ide_scsi_g(disk);
- if (scsi)
+ if (scsi) {
scsi_host_get(scsi->host);
+ if (ide_device_get(scsi->drive)) {
+ scsi_host_put(scsi->host);
+ scsi = NULL;
+ }
+ }
mutex_unlock(&idescsi_ref_mutex);
return scsi;
}
@@ -111,6 +115,7 @@ static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk)
static void ide_scsi_put(struct ide_scsi_obj *scsi)
{
mutex_lock(&idescsi_ref_mutex);
+ ide_device_put(scsi->drive);
scsi_host_put(scsi->host);
mutex_unlock(&idescsi_ref_mutex);
}
@@ -126,23 +131,14 @@ static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive)
}
/*
- * Per ATAPI device status bits.
- */
-#define IDESCSI_DRQ_INTERRUPT 0 /* DRQ interrupt device */
-
-/*
- * ide-scsi requests.
- */
-#define IDESCSI_PC_RQ 90
-
-/*
* PIO data transfer routine using the scatter gather table.
*/
static void ide_scsi_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
unsigned int bcount, int write)
{
ide_hwif_t *hwif = drive->hwif;
- xfer_func_t *xf = write ? hwif->output_data : hwif->input_data;
+ const struct ide_tp_ops *tp_ops = hwif->tp_ops;
+ xfer_func_t *xf = write ? tp_ops->output_data : tp_ops->input_data;
char *buf;
int count;
@@ -211,15 +207,15 @@ static int idescsi_check_condition(ide_drive_t *drive,
/* stuff a sense request in front of our current request */
pc = kzalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
- rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
+ rq = blk_get_request(drive->queue, READ, GFP_ATOMIC);
buf = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);
if (!pc || !rq || !buf) {
kfree(buf);
- kfree(rq);
+ if (rq)
+ blk_put_request(rq);
kfree(pc);
return -ENOMEM;
}
- blk_rq_init(NULL, rq);
rq->special = (char *) pc;
pc->rq = rq;
pc->buf = buf;
@@ -228,7 +224,6 @@ static int idescsi_check_condition(ide_drive_t *drive,
rq->cmd_type = REQ_TYPE_SENSE;
rq->cmd_flags |= REQ_PREEMPT;
pc->timeout = jiffies + WAIT_READY;
- pc->callback = ide_scsi_callback;
/* NOTE! Save the failed packet command in "rq->buffer" */
rq->buffer = (void *) failed_cmd->special;
pc->scsi_cmd = ((struct ide_atapi_pc *) failed_cmd->special)->scsi_cmd;
@@ -237,6 +232,8 @@ static int idescsi_check_condition(ide_drive_t *drive,
ide_scsi_hex_dump(pc->c, 6);
}
rq->rq_disk = scsi->disk;
+ rq->ref_count++;
+ memcpy(rq->cmd, pc->c, 12);
ide_do_drive_cmd(drive, rq);
return 0;
}
@@ -246,10 +243,9 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
{
ide_hwif_t *hwif = drive->hwif;
- if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
+ if (hwif->tp_ops->read_status(hwif) & (BUSY_STAT | DRQ_STAT))
/* force an abort */
- hwif->OUTBSYNC(hwif, WIN_IDLEIMMEDIATE,
- hwif->io_ports.command_addr);
+ hwif->tp_ops->exec_command(hwif, WIN_IDLEIMMEDIATE);
rq->errors++;
@@ -283,7 +279,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
SCSI_SENSE_BUFFERSIZE);
kfree(pc->buf);
kfree(pc);
- kfree(rq);
+ blk_put_request(rq);
pc = opc;
rq = pc->rq;
pc->scsi_cmd->result = (CHECK_CONDITION << 1) |
@@ -314,7 +310,7 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
pc->done(pc->scsi_cmd);
spin_unlock_irqrestore(host->host_lock, flags);
kfree(pc);
- kfree(rq);
+ blk_put_request(rq);
scsi->pc = NULL;
return 0;
}
@@ -421,10 +417,6 @@ static ide_startstop_t idescsi_do_request (ide_drive_t *drive, struct request *r
if (blk_sense_request(rq) || blk_special_request(rq)) {
struct ide_atapi_pc *pc = (struct ide_atapi_pc *)rq->special;
- idescsi_scsi_t *scsi = drive_to_idescsi(drive);
-
- if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags))
- pc->flags |= PC_FLAG_DRQ_INTERRUPT;
if (drive->using_dma && !idescsi_map_sg(drive, pc))
pc->flags |= PC_FLAG_DMA_OK;
@@ -460,11 +452,14 @@ static inline void idescsi_add_settings(ide_drive_t *drive) { ; }
static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
{
if (drive->id && (drive->id->config & 0x0060) == 0x20)
- set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
+ set_bit(IDE_AFLAG_DRQ_INTERRUPT, &drive->atapi_flags);
clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform);
#if IDESCSI_DEBUG_LOG
set_bit(IDESCSI_LOG_CMD, &scsi->log);
#endif /* IDESCSI_DEBUG_LOG */
+
+ drive->pc_callback = ide_scsi_callback;
+
idescsi_add_settings(drive);
}
@@ -589,6 +584,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
ide_drive_t *drive = scsi->drive;
struct request *rq = NULL;
struct ide_atapi_pc *pc = NULL;
+ int write = cmd->sc_data_direction == DMA_TO_DEVICE;
if (!drive) {
scmd_printk (KERN_ERR, cmd, "drive not present\n");
@@ -596,7 +592,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
}
scsi = drive_to_idescsi(drive);
pc = kmalloc(sizeof(struct ide_atapi_pc), GFP_ATOMIC);
- rq = kmalloc(sizeof(struct request), GFP_ATOMIC);
+ rq = blk_get_request(drive->queue, write, GFP_ATOMIC);
if (rq == NULL || pc == NULL) {
printk (KERN_ERR "ide-scsi: %s: out of memory\n", drive->name);
goto abort;
@@ -616,7 +612,6 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
pc->scsi_cmd = cmd;
pc->done = done;
pc->timeout = jiffies + cmd->timeout_per_command;
- pc->callback = ide_scsi_callback;
if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number);
@@ -627,16 +622,18 @@ static int idescsi_queue (struct scsi_cmnd *cmd,
}
}
- blk_rq_init(NULL, rq);
rq->special = (char *) pc;
rq->cmd_type = REQ_TYPE_SPECIAL;
spin_unlock_irq(host->host_lock);
+ rq->ref_count++;
+ memcpy(rq->cmd, pc->c, 12);
blk_execute_rq_nowait(drive->queue, scsi->disk, rq, 0, NULL);
spin_lock_irq(host->host_lock);
return 0;
abort:
kfree (pc);
- kfree (rq);
+ if (rq)
+ blk_put_request(rq);
cmd->result = DID_ERROR << 16;
done(cmd);
return 0;
@@ -684,7 +681,9 @@ static int idescsi_eh_abort (struct scsi_cmnd *cmd)
if (blk_sense_request(scsi->pc->rq))
kfree(scsi->pc->buf);
- kfree(scsi->pc->rq);
+ /* we need to call blk_put_request twice. */
+ blk_put_request(scsi->pc->rq);
+ blk_put_request(scsi->pc->rq);
kfree(scsi->pc);
scsi->pc = NULL;
@@ -736,7 +735,7 @@ static int idescsi_eh_reset (struct scsi_cmnd *cmd)
kfree(scsi->pc->buf);
kfree(scsi->pc);
scsi->pc = NULL;
- kfree(req);
+ blk_put_request(req);
/* now nuke the drive queue */
while ((req = elv_next_request(drive->queue))) {