Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 102138
b: refs/heads/master
c: 79e36a9
h: refs/heads/master
v: v3
  • Loading branch information
Elias Oltmanns authored and Bartlomiej Zolnierkiewicz committed Jul 16, 2008
1 parent e792c50 commit 4a6a3c1
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 33 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 72a3d651b2fe341a8ae2ca164c395aa3007350cd
refs/heads/master: 79e36a9f54aaf4a52eb2d9520953aa3960e99294
23 changes: 22 additions & 1 deletion trunk/drivers/ide/ide-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,18 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive,
return ide_stopped;
}

static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq)
{
switch (rq->cmd[0]) {
case REQ_DRIVE_RESET:
return ide_do_reset(drive);
default:
blk_dump_rq_flags(rq, "ide_special_rq - bad request");
ide_end_request(drive, 0, 0);
return ide_stopped;
}
}

static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
{
struct request_pm_state *pm = rq->data;
Expand Down Expand Up @@ -869,7 +881,16 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq)
pm->pm_step == ide_pm_state_completed)
ide_complete_pm_request(drive, rq);
return startstop;
}
} else if (!rq->rq_disk && blk_special_request(rq))
/*
* TODO: Once all ULDs have been modified to
* check for specific op codes rather than
* blindly accepting any special request, the
* check for ->rq_disk above may be replaced
* by a more suitable mechanism or even
* dropped entirely.
*/
return ide_special_rq(drive, rq);

drv = *(ide_driver_t **)rq->rq_disk->private_data;
return drv->do_request(drive, rq, block);
Expand Down
18 changes: 13 additions & 5 deletions trunk/drivers/ide/ide-iops.c
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,14 @@ void ide_execute_pkt_cmd(ide_drive_t *drive)
}
EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);

static inline void ide_complete_drive_reset(ide_drive_t *drive)
{
struct request *rq = drive->hwif->hwgroup->rq;

if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
ide_end_request(drive, 1, 0);
}

/* needed below */
static ide_startstop_t do_reset1 (ide_drive_t *, int);

Expand Down Expand Up @@ -940,7 +948,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
}
/* done polling */
hwgroup->polling = 0;
hwgroup->resetting = 0;
ide_complete_drive_reset(drive);
return ide_stopped;
}

Expand All @@ -961,7 +969,7 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
if (port_ops->reset_poll(drive)) {
printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
hwif->name, drive->name);
return ide_stopped;
goto out;
}
}

Expand Down Expand Up @@ -1004,7 +1012,8 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
}
}
hwgroup->polling = 0; /* done polling */
hwgroup->resetting = 0; /* done reset attempt */
out:
ide_complete_drive_reset(drive);
return ide_stopped;
}

Expand Down Expand Up @@ -1090,7 +1099,6 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)

/* For an ATAPI device, first try an ATAPI SRST. */
if (drive->media != ide_disk && !do_not_try_atapi) {
hwgroup->resetting = 1;
pre_reset(drive);
SELECT_DRIVE(drive);
udelay (20);
Expand All @@ -1112,10 +1120,10 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)

if (io_ports->ctl_addr == 0) {
spin_unlock_irqrestore(&ide_lock, flags);
ide_complete_drive_reset(drive);
return ide_stopped;
}

hwgroup->resetting = 1;
/*
* Note that we also set nIEN while resetting the device,
* to mask unwanted interrupts from the interface during the reset.
Expand Down
41 changes: 15 additions & 26 deletions trunk/drivers/ide/ide.c
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,19 @@ static int generic_ide_resume(struct device *dev)
return err;
}

static void generic_drive_reset(ide_drive_t *drive)
{
struct request *rq;

rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
rq->cmd_type = REQ_TYPE_SPECIAL;
rq->cmd_len = 1;
rq->cmd[0] = REQ_DRIVE_RESET;
rq->cmd_flags |= REQ_SOFTBARRIER;
blk_execute_rq(drive->queue, NULL, rq, 1);
blk_put_request(rq);
}

int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
unsigned int cmd, unsigned long arg)
{
Expand Down Expand Up @@ -603,33 +616,9 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
if (!capable(CAP_SYS_ADMIN))
return -EACCES;

/*
* Abort the current command on the
* group if there is one, taking
* care not to allow anything else
* to be queued and to die on the
* spot if we miss one somehow
*/

spin_lock_irqsave(&ide_lock, flags);

if (HWGROUP(drive)->resetting) {
spin_unlock_irqrestore(&ide_lock, flags);
return -EBUSY;
}

ide_abort(drive, "drive reset");

BUG_ON(HWGROUP(drive)->handler);

/* Ensure nothing gets queued after we
drop the lock. Reset will clear the busy */

HWGROUP(drive)->busy = 1;
spin_unlock_irqrestore(&ide_lock, flags);
(void) ide_do_reset(drive);

generic_drive_reset(drive);
return 0;

case HDIO_GET_BUSSTATE:
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
Expand Down
6 changes: 6 additions & 0 deletions trunk/include/linux/ide.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,12 @@ struct ide_io_ports {
#define WAIT_CMD (10*HZ) /* 10sec - maximum wait for an IRQ to happen */
#define WAIT_MIN_SLEEP (2*HZ/100) /* 20msec - minimum sleep time */

/*
* Op codes for special requests to be handled by ide_special_rq().
* Values should be in the range of 0x20 to 0x3f.
*/
#define REQ_DRIVE_RESET 0x20

/*
* Check for an interrupt and acknowledge the interrupt status
*/
Expand Down

0 comments on commit 4a6a3c1

Please sign in to comment.