diff options
Diffstat (limited to 'drivers/scsi/ide-scsi.c')
-rw-r--r-- | drivers/scsi/ide-scsi.c | 44 |
1 files changed, 35 insertions, 9 deletions
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 805cccd042b67..2e2486b035dd9 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -98,6 +98,8 @@ typedef struct idescsi_pc_s { typedef struct ide_scsi_obj { ide_drive_t *drive; + ide_driver_t *driver; + struct gendisk *disk; struct Scsi_Host *host; idescsi_pc_t *pc; /* Current packet command */ @@ -108,7 +110,8 @@ typedef struct ide_scsi_obj { static DECLARE_MUTEX(idescsi_ref_sem); -#define ide_scsi_g(disk) ((disk)->private_data) +#define ide_scsi_g(disk) \ + container_of((disk)->private_data, struct ide_scsi_obj, driver) static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk) { @@ -323,9 +326,12 @@ static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_co printk ("ide-scsi: %s: queue cmd = ", drive->name); hexdump(pc->c, 6); } + rq->rq_disk = scsi->disk; return ide_do_drive_cmd(drive, rq, ide_preempt); } +static int idescsi_end_request(ide_drive_t *, int, int); + static ide_startstop_t idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) { @@ -334,7 +340,9 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG); rq->errors++; - DRIVER(drive)->end_request(drive, 0, 0); + + idescsi_end_request(drive, 0, 0); + return ide_stopped; } @@ -346,7 +354,9 @@ idescsi_atapi_abort(ide_drive_t *drive, struct request *rq) ((idescsi_pc_t *) rq->special)->scsi_cmd->serial_number); #endif rq->errors |= ERROR_MAX; - DRIVER(drive)->end_request(drive, 0, 0); + + idescsi_end_request(drive, 0, 0); + return ide_stopped; } @@ -718,17 +728,20 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) static int idescsi_cleanup (ide_drive_t *drive) { struct Scsi_Host *scsihost = drive->driver_data; - struct gendisk *g = drive->disk; + struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); + struct gendisk *g = scsi->disk; if (ide_unregister_subdriver(drive)) return 1; + ide_unregister_region(g); + drive->driver_data = NULL; g->private_data = NULL; - g->fops = ide_fops; + put_disk(g); scsi_remove_host(scsihost); - ide_scsi_put(scsihost_to_idescsi(scsihost)); + ide_scsi_put(scsi); return 0; } @@ -910,6 +923,7 @@ static int idescsi_queue (struct scsi_cmnd *cmd, rq->special = (char *) pc; rq->flags = REQ_SPECIAL; spin_unlock_irq(host->host_lock); + rq->rq_disk = scsi->disk; (void) ide_do_drive_cmd (drive, rq, ide_end); spin_lock_irq(host->host_lock); return 0; @@ -1085,9 +1099,9 @@ static int idescsi_attach(ide_drive_t *drive) { idescsi_scsi_t *idescsi; struct Scsi_Host *host; - struct gendisk *g = drive->disk; + struct gendisk *g; static int warned; - int err; + int err = -ENOMEM; if (!warned && drive->media == ide_cdrom) { printk(KERN_WARNING "ide-scsi is deprecated for cd burning! Use ide-cd and give dev=/dev/hdX as device\n"); @@ -1100,6 +1114,12 @@ static int idescsi_attach(ide_drive_t *drive) !(host = scsi_host_alloc(&idescsi_template,sizeof(idescsi_scsi_t)))) return 1; + g = alloc_disk(1 << PARTN_BITS); + if (!g) + goto out_host_put; + + ide_init_disk(g, drive); + host->max_id = 1; #if IDESCSI_DEBUG_LOG @@ -1114,21 +1134,27 @@ static int idescsi_attach(ide_drive_t *drive) drive->driver_data = host; idescsi = scsihost_to_idescsi(host); idescsi->drive = drive; + idescsi->driver = &idescsi_driver; idescsi->host = host; + idescsi->disk = g; + g->private_data = &idescsi->driver; err = ide_register_subdriver(drive, &idescsi_driver); if (!err) { idescsi_setup (drive, idescsi); g->fops = &idescsi_ops; - g->private_data = idescsi; + ide_register_region(g); err = scsi_add_host(host, &drive->gendev); if (!err) { scsi_scan_host(host); return 0; } /* fall through on error */ + ide_unregister_region(g); ide_unregister_subdriver(drive); } + put_disk(g); +out_host_put: scsi_host_put(host); return err; } |