On Tue, Sep 06, 2005 at 04:40:28PM -0700, Ravikiran G Thirumalai wrote:
> Patch to convert ide core code to use hwgroup lock instead of a global
> ide_lock.
>
> Index: linux-2.6.13/drivers/ide/ide-io.c
> ===================================================================
> --- linux-2.6.13.orig/drivers/ide/ide-io.c 2005-09-06 11:22:29.000000000 -0700
> @@ -1211,11 +1214,11 @@
> */
> if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
> disable_irq_nosync(hwif->irq);
> - spin_unlock(&ide_lock);
> + spin_unlock(&hwgroup->lock);
> local_irq_enable();
> /* allow other IRQs while we start this request */
> startstop = start_request(drive, rq);
> - spin_lock_irq(&ide_lock);
> + spin_unlock_irq(&hwgroup->lock);
^^^^^^^^^^^^^^^^^^^^^^^
My bad,
Fixed patch attached.
Thanks,
Kiran
Patch to convert ide core code to use hwgroup lock instead of a global
ide_lock.
Signed-off-by: Vaibhav V. Nivargi <[email protected]>
Signed-off-by: Alok N. Kataria <[email protected]>
Signed-off-by: Ravikiran Thirumalai <[email protected]>
Signed-off-by: Shai Fultheim <[email protected]>
Index: linux-2.6.13/drivers/ide/ide-cd.c
===================================================================
--- linux-2.6.13.orig/drivers/ide/ide-cd.c 2005-09-06 15:08:07.000000000 -0700
+++ linux-2.6.13/drivers/ide/ide-cd.c 2005-09-06 15:16:15.000000000 -0700
@@ -590,7 +590,8 @@
static void cdrom_end_request (ide_drive_t *drive, int uptodate)
{
- struct request *rq = HWGROUP(drive)->rq;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ struct request *rq = hwgroup->rq;
int nsectors = rq->hard_cur_sectors;
if ((rq->flags & REQ_SENSE) && uptodate) {
@@ -612,10 +613,10 @@
/*
* now end failed request
*/
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
end_that_request_chunk(failed, 0, failed->data_len);
end_that_request_last(failed);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
}
cdrom_analyze_sense_data(drive, failed, sense);
@@ -636,7 +637,8 @@
Returns 1 if the request was ended. */
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
{
- struct request *rq = HWGROUP(drive)->rq;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ struct request *rq = hwgroup->rq;
int stat, err, sense_key;
/* Check for errors. */
@@ -698,10 +700,10 @@
* request sense has completed
*/
if (stat & ERR_STAT) {
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
cdrom_queue_request_sense(drive, rq->sense, rq);
} else
@@ -741,9 +743,9 @@
* take a breather relying on the
* unplug timer to kick us again
*/
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
blk_plug_device(drive->queue);
- spin_unlock_irqrestore(&ide_lock,flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return 1;
}
}
@@ -839,6 +841,7 @@
ide_startstop_t startstop;
struct cdrom_info *info = drive->driver_data;
ide_hwif_t *hwif = drive->hwif;
+ ide_hwgroup_t *hwgroup = hwif->hwgroup;
/* Wait for the controller to be idle. */
if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY))
@@ -866,10 +869,10 @@
unsigned long flags;
/* packet command */
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
hwif->OUTBSYNC(drive, WIN_PACKETCMD, IDE_COMMAND_REG);
ndelay(400);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return (*handler) (drive);
}
@@ -1609,7 +1612,8 @@
static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
{
struct cdrom_info *info = drive->driver_data;
- struct request *rq = HWGROUP(drive)->rq;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ struct request *rq = hwgroup->rq;
int dma_error, dma, stat, ireason, len, thislen;
u8 lowcyl, highcyl;
xfer_func_t *xferfunc;
@@ -1737,11 +1741,11 @@
if (!rq->data_len)
post_transform_command(rq);
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
blkdev_dequeue_request(rq);
end_that_request_last(rq);
HWGROUP(drive)->rq = NULL;
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return ide_stopped;
}
Index: linux-2.6.13/drivers/ide/ide-disk.c
===================================================================
--- linux-2.6.13.orig/drivers/ide/ide-disk.c 2005-09-06 15:08:07.000000000 -0700
+++ linux-2.6.13/drivers/ide/ide-disk.c 2005-09-06 15:16:15.000000000 -0700
@@ -786,11 +786,12 @@
static int set_nowerr(ide_drive_t *drive, int arg)
{
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
drive->nowerr = arg;
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
return 0;
}
Index: linux-2.6.13/drivers/ide/ide-io.c
===================================================================
--- linux-2.6.13.orig/drivers/ide/ide-io.c 2005-09-06 15:08:07.000000000 -0700
+++ linux-2.6.13/drivers/ide/ide-io.c 2005-09-06 22:35:09.000000000 -0700
@@ -112,9 +112,10 @@
struct request *rq;
unsigned long flags;
int ret = 1;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
- spin_lock_irqsave(&ide_lock, flags);
- rq = HWGROUP(drive)->rq;
+ spin_lock_irqsave(&hwgroup->lock, flags);
+ rq = hwgroup->rq;
if (!nr_sectors)
nr_sectors = rq->hard_cur_sectors;
@@ -124,7 +125,7 @@
else
ret = __ide_end_request(drive, rq, uptodate, nr_sectors);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return ret;
}
EXPORT_SYMBOL(ide_end_request);
@@ -233,12 +234,13 @@
static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
{
unsigned long flags;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
#ifdef DEBUG_PM
printk("%s: completing PM request, %s\n", drive->name,
blk_pm_suspend_request(rq) ? "suspend" : "resume");
#endif
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
if (blk_pm_suspend_request(rq)) {
blk_stop_queue(drive->queue);
} else {
@@ -248,7 +250,7 @@
blkdev_dequeue_request(rq);
HWGROUP(drive)->rq = NULL;
end_that_request_last(rq);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
}
/*
@@ -305,10 +307,11 @@
ide_hwif_t *hwif = HWIF(drive);
unsigned long flags;
struct request *rq;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
- spin_lock_irqsave(&ide_lock, flags);
- rq = HWGROUP(drive)->rq;
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
+ rq = hwgroup->rq;
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
if (rq->flags & REQ_DRIVE_CMD) {
u8 *args = (u8 *) rq->buffer;
@@ -375,12 +378,12 @@
return;
}
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
blkdev_dequeue_request(rq);
- HWGROUP(drive)->rq = NULL;
+ hwgroup->rq = NULL;
rq->errors = err;
end_that_request_last(rq);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
}
EXPORT_SYMBOL(ide_end_drive_cmd);
@@ -1062,7 +1065,7 @@
/*
* Issue a new request to a drive from hwgroup
- * Caller must have already done spin_lock_irqsave(&ide_lock, ..);
+ * Caller must have already done spin_lock_irqsave(&hwgroup->lock, ..);
*
* A hwgroup is a serialized group of IDE interfaces. Usually there is
* exactly one hwif (interface) per hwgroup, but buggy controllers (eg. CMD640)
@@ -1074,7 +1077,7 @@
* possibly along with many other devices. This is especially common in
* PCI-based systems with off-board IDE controller cards.
*
- * The IDE driver uses the single global ide_lock spinlock to protect
+ * The IDE driver uses a per-hwgroup spinlock to protect
* access to the request queues, and to protect the hwgroup->busy flag.
*
* The first thread into the driver for a particular hwgroup sets the
@@ -1090,7 +1093,7 @@
* will start the next request from the queue. If no more work remains,
* the driver will clear the hwgroup->busy flag and exit.
*
- * The ide_lock (spinlock) is used to protect all access to the
+ * The per-hwgroup spinlock(hwgroup->lock) is used to protect all access to the
* hwgroup->busy flag, but is otherwise not needed for most processing in
* the driver. This makes the driver much more friendlier to shared IRQs
* than previous designs, while remaining 100% (?) SMP safe and capable.
@@ -1105,7 +1108,7 @@
/* for atari only: POSSIBLY BROKEN HERE(?) */
ide_get_lock(ide_intr, hwgroup);
- /* caller must own ide_lock */
+ /* caller must own hwgroup->lock */
BUG_ON(!irqs_disabled());
while (!hwgroup->busy) {
@@ -1211,11 +1214,11 @@
*/
if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
disable_irq_nosync(hwif->irq);
- spin_unlock(&ide_lock);
+ spin_unlock(&hwgroup->lock);
local_irq_enable();
/* allow other IRQs while we start this request */
startstop = start_request(drive, rq);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
if (masked_irq != IDE_NO_IRQ && hwif->irq != masked_irq)
enable_irq(hwif->irq);
if (startstop == ide_stopped)
@@ -1309,7 +1312,7 @@
unsigned long flags;
unsigned long wait = -1;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
if ((handler = hwgroup->handler) == NULL) {
/*
@@ -1340,7 +1343,7 @@
/* reset timer */
hwgroup->timer.expires = jiffies + wait;
add_timer(&hwgroup->timer);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return;
}
}
@@ -1350,7 +1353,7 @@
* the handler() function, which means we need to
* globally mask the specific IRQ:
*/
- spin_unlock(&ide_lock);
+ spin_unlock(&hwgroup->lock);
hwif = HWIF(drive);
#if DISABLE_IRQ_NOSYNC
disable_irq_nosync(hwif->irq);
@@ -1377,14 +1380,14 @@
ide_error(drive, "irq timeout", hwif->INB(IDE_STATUS_REG));
}
drive->service_time = jiffies - drive->service_start;
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
enable_irq(hwif->irq);
if (startstop == ide_stopped)
hwgroup->busy = 0;
}
}
ide_do_request(hwgroup, IDE_NO_IRQ);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
}
/**
@@ -1481,11 +1484,11 @@
ide_handler_t *handler;
ide_startstop_t startstop;
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
hwif = hwgroup->hwif;
if (!ide_ack_intr(hwif)) {
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return IRQ_NONE;
}
@@ -1523,7 +1526,7 @@
(void) hwif->INB(hwif->io_ports[IDE_STATUS_OFFSET]);
#endif /* CONFIG_BLK_DEV_IDEPCI */
}
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return IRQ_NONE;
}
drive = hwgroup->drive;
@@ -1534,7 +1537,7 @@
*
* [Note - this can occur if the drive is hot unplugged]
*/
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return IRQ_HANDLED;
}
if (!drive_is_ready(drive)) {
@@ -1545,7 +1548,7 @@
* their status register is up to date. Hopefully we have
* enough advance overhead that the latter isn't a problem.
*/
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return IRQ_NONE;
}
if (!hwgroup->busy) {
@@ -1554,13 +1557,13 @@
}
hwgroup->handler = NULL;
del_timer(&hwgroup->timer);
- spin_unlock(&ide_lock);
+ spin_unlock(&hwgroup->lock);
if (drive->unmask)
local_irq_enable();
/* service this interrupt, may set handler for next interrupt */
startstop = handler(drive);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
/*
* Note that handler() may have set things up for another
@@ -1579,7 +1582,7 @@
"on exit\n", drive->name);
}
}
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return IRQ_HANDLED;
}
@@ -1654,7 +1657,7 @@
rq->end_io = blk_end_sync_rq;
}
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
if (action == ide_preempt)
hwgroup->rq = NULL;
if (action == ide_preempt || action == ide_head_wait) {
@@ -1663,7 +1666,7 @@
}
__elv_add_request(drive->queue, rq, where, 0);
ide_do_request(hwgroup, IDE_NO_IRQ);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
err = 0;
if (must_wait) {
Index: linux-2.6.13/drivers/ide/ide-iops.c
===================================================================
--- linux-2.6.13.orig/drivers/ide/ide-iops.c 2005-09-06 15:08:07.000000000 -0700
+++ linux-2.6.13/drivers/ide/ide-iops.c 2005-09-06 15:16:15.000000000 -0700
@@ -945,9 +945,10 @@
unsigned int timeout, ide_expiry_t *expiry)
{
unsigned long flags;
- spin_lock_irqsave(&ide_lock, flags);
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
+ spin_lock_irqsave(&hwgroup->lock, flags);
__ide_set_handler(drive, handler, timeout, expiry);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
}
EXPORT_SYMBOL(ide_set_handler);
@@ -972,7 +973,7 @@
ide_hwgroup_t *hwgroup = HWGROUP(drive);
ide_hwif_t *hwif = HWIF(drive);
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
if(hwgroup->handler)
BUG();
@@ -988,7 +989,7 @@
devices
*/
ndelay(400);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
}
EXPORT_SYMBOL(ide_execute_command);
@@ -1168,10 +1169,11 @@
ide_hwif_t *hwif;
ide_hwgroup_t *hwgroup;
- spin_lock_irqsave(&ide_lock, flags);
hwif = HWIF(drive);
hwgroup = HWGROUP(drive);
+ spin_lock_irqsave(&hwgroup->lock, flags);
+
/* We must not reset with running handlers */
if(hwgroup->handler != NULL)
BUG();
@@ -1186,7 +1188,7 @@
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
hwgroup->polling = 1;
__ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return ide_started;
}
@@ -1199,7 +1201,7 @@
#if OK_TO_RESET_CONTROLLER
if (!IDE_CONTROL_REG) {
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return ide_stopped;
}
@@ -1239,7 +1241,7 @@
#endif /* OK_TO_RESET_CONTROLLER */
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
return ide_started;
}
Index: linux-2.6.13/drivers/ide/ide-lib.c
===================================================================
--- linux-2.6.13.orig/drivers/ide/ide-lib.c 2005-09-06 15:08:07.000000000 -0700
+++ linux-2.6.13/drivers/ide/ide-lib.c 2005-09-06 15:16:15.000000000 -0700
@@ -450,12 +450,11 @@
struct request *rq;
u8 opcode = 0;
int found = 0;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
- spin_lock(&ide_lock);
- rq = NULL;
- if (HWGROUP(drive))
- rq = HWGROUP(drive)->rq;
- spin_unlock(&ide_lock);
+ spin_lock(&hwgroup->lock);
+ rq = hwgroup->rq;
+ spin_unlock(&hwgroup->lock);
if (!rq)
return;
if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
Index: linux-2.6.13/drivers/ide/ide-probe.c
===================================================================
--- linux-2.6.13.orig/drivers/ide/ide-probe.c 2005-09-06 15:12:58.000000000 -0700
+++ linux-2.6.13/drivers/ide/ide-probe.c 2005-09-06 15:16:15.000000000 -0700
@@ -985,7 +985,8 @@
* do not.
*/
- q = blk_init_queue_node(do_ide_request, &ide_lock, hwif_to_node(hwif));
+ q = blk_init_queue_node(do_ide_request, &(HWGROUP(drive)->lock),
+ hwif_to_node(hwif));
if (!q)
return 1;
@@ -1099,10 +1100,10 @@
* linked list, the first entry is the hwif that owns
* hwgroup->handler - do not change that.
*/
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
hwif->next = hwgroup->hwif->next;
hwgroup->hwif->next = hwif;
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
} else {
hwgroup = kmalloc_node(sizeof(ide_hwgroup_t), GFP_KERNEL,
hwif_to_node(hwif->drives[0].hwif));
@@ -1112,6 +1113,7 @@
hwif->hwgroup = hwgroup;
memset(hwgroup, 0, sizeof(ide_hwgroup_t));
+ spin_lock_init(&hwgroup->lock);
hwgroup->hwif = hwif->next = hwif;
hwgroup->rq = NULL;
hwgroup->handler = NULL;
@@ -1159,7 +1161,7 @@
printk(KERN_ERR "ide: failed to init %s\n",drive->name);
continue;
}
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
if (!hwgroup->drive) {
/* first drive for hwgroup. */
drive->next = drive;
@@ -1169,7 +1171,7 @@
drive->next = hwgroup->drive->next;
hwgroup->drive->next = drive;
}
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
}
#if !defined(__mc68000__) && !defined(CONFIG_APUS) && !defined(__sparc__)
@@ -1193,13 +1195,13 @@
up(&ide_cfg_sem);
return 0;
out_unlink:
- spin_lock_irq(&ide_lock);
if (hwif->next == hwif) {
BUG_ON(match);
BUG_ON(hwgroup->hwif != hwif);
kfree(hwgroup);
} else {
ide_hwif_t *g;
+ spin_lock_irq(&hwgroup->lock);
g = hwgroup->hwif;
while (g->next != hwif)
g = g->next;
@@ -1210,8 +1212,8 @@
hwgroup->hwif = g;
}
BUG_ON(hwgroup->hwif == hwif);
+ spin_unlock_irq(&hwgroup->lock);
}
- spin_unlock_irq(&ide_lock);
out_up:
up(&ide_cfg_sem);
return 1;
@@ -1316,8 +1318,9 @@
static void drive_release_dev (struct device *dev)
{
ide_drive_t *drive = container_of(dev, ide_drive_t, gendev);
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
if (drive->devfs_name[0] != '\0') {
devfs_remove(drive->devfs_name);
drive->devfs_name[0] = '\0';
@@ -1329,11 +1332,11 @@
}
drive->present = 0;
/* Messed up locking ... */
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
blk_cleanup_queue(drive->queue);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
drive->queue = NULL;
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
up(&drive->gendev_rel_sem);
}
Index: linux-2.6.13/drivers/ide/ide.c
===================================================================
--- linux-2.6.13.orig/drivers/ide/ide.c 2005-09-06 15:08:07.000000000 -0700
+++ linux-2.6.13/drivers/ide/ide.c 2005-09-06 15:16:15.000000000 -0700
@@ -175,7 +175,13 @@
static int initializing; /* set while initializing built-in drivers */
DECLARE_MUTEX(ide_cfg_sem);
- __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
+
+/*
+ * Global ide_lock is broken down to per HWGROUP lock. For controller
+ * serialization when hwgroups are not present, use per-controller
+ * spinlocks. See drivers/ide/pci/piix.c
+ */
+ __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock __deprecated);
#ifdef CONFIG_BLK_DEV_IDEPCI
static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
@@ -587,10 +593,15 @@
BUG_ON(in_interrupt());
BUG_ON(irqs_disabled());
down(&ide_cfg_sem);
- spin_lock_irq(&ide_lock);
hwif = &ide_hwifs[index];
- if (!hwif->present)
- goto abort;
+ hwgroup = hwif->hwgroup;
+ spin_lock_irq(&hwgroup->lock);
+ if (!hwif->present) {
+ spin_unlock_irq(&hwgroup->lock);
+ up(&ide_cfg_sem);
+ return;
+ }
+
for (unit = 0; unit < MAX_DRIVES; ++unit) {
drive = &hwif->drives[unit];
if (!drive->present) {
@@ -600,18 +611,17 @@
}
continue;
}
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
device_unregister(&drive->gendev);
down(&drive->gendev_rel_sem);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
}
hwif->present = 0;
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
destroy_proc_ide_interface(hwif);
- hwgroup = hwif->hwgroup;
/*
* free the irq if we were the only hwif using it
*/
@@ -624,7 +634,7 @@
if (irq_count == 1)
free_irq(hwif->irq, hwgroup);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
/*
* Note that we only release the standard ports,
* and do not even try to handle any extra ports
@@ -638,6 +648,7 @@
*/
if (hwif->next == hwif) {
BUG_ON(hwgroup->hwif != hwif);
+ spin_unlock_irq(&hwgroup->lock);
kfree(hwgroup);
} else {
/* There is another interface in hwgroup.
@@ -657,10 +668,9 @@
hwgroup->hwif = g;
}
BUG_ON(hwgroup->hwif == hwif);
+ spin_unlock_irq(&hwgroup->lock);
}
- /* More messed up locking ... */
- spin_unlock_irq(&ide_lock);
device_unregister(&hwif->gendev);
down(&hwif->gendev_rel_sem);
@@ -670,7 +680,6 @@
blk_unregister_region(MKDEV(hwif->major, 0), MAX_DRIVES<<PARTN_BITS);
kfree(hwif->sg_table);
unregister_blkdev(hwif->major, hwif->name);
- spin_lock_irq(&ide_lock);
if (hwif->dma_base) {
(void) ide_release_dma(hwif);
@@ -692,9 +701,6 @@
init_hwif_default(hwif, index);
ide_hwif_restore(hwif, &tmp_hwif);
-
-abort:
- spin_unlock_irq(&ide_lock);
up(&ide_cfg_sem);
}
@@ -1012,9 +1018,10 @@
{
int val = -EINVAL;
unsigned long flags;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
if ((setting->rw & SETTING_READ)) {
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
switch(setting->data_type) {
case TYPE_BYTE:
val = *((u8 *) setting->data);
@@ -1027,7 +1034,7 @@
val = *((u32 *) setting->data);
break;
}
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
}
return val;
}
@@ -1037,7 +1044,7 @@
* @drive: drive in the group
*
* Wait for an IDE device group to go non busy and then return
- * holding the ide_lock which guards the hwgroup->busy status
+ * holding the hwgroup->lock which guards the hwgroup->busy status
* and right to use it.
*/
@@ -1046,11 +1053,11 @@
ide_hwgroup_t *hwgroup = HWGROUP(drive);
unsigned long timeout = jiffies + (3 * HZ);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
while (hwgroup->busy) {
unsigned long lflags;
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
local_irq_set(lflags);
if (time_after(jiffies, timeout)) {
local_irq_restore(lflags);
@@ -1058,7 +1065,7 @@
return -EBUSY;
}
local_irq_restore(lflags);
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
}
return 0;
}
@@ -1087,6 +1094,7 @@
{
int i;
u32 *p;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
@@ -1114,7 +1122,7 @@
*p = val;
break;
}
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
return 0;
}
@@ -1260,6 +1268,7 @@
ide_driver_t *drv;
int err = 0;
void __user *p = (void __user *)arg;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
down(&ide_setting_sem);
if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) {
@@ -1377,18 +1386,18 @@
* spot if we miss one somehow
*/
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
ide_abort(drive, "drive reset");
- if(HWGROUP(drive)->handler)
+ if(hwgroup->handler)
BUG();
/* Ensure nothing gets queued after we
drop the lock. Reset will clear the busy */
- HWGROUP(drive)->busy = 1;
- spin_unlock_irqrestore(&ide_lock, flags);
+ hwgroup->busy = 1;
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
(void) ide_do_reset(drive);
return 0;
@@ -1874,21 +1883,22 @@
* Disconnect a drive from the driver it was attached to and then
* clean up the various proc files and other objects attached to it.
*
- * Takes ide_setting_sem and ide_lock.
+ * Takes ide_setting_sem and hwgroup->lock.
* Caller must hold none of the locks.
*/
void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver)
{
unsigned long flags;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
down(&ide_setting_sem);
- spin_lock_irqsave(&ide_lock, flags);
+ spin_lock_irqsave(&hwgroup->lock, flags);
#ifdef CONFIG_PROC_FS
ide_remove_proc_entries(drive->proc, driver->proc);
#endif
auto_remove_settings(drive);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&hwgroup->lock, flags);
up(&ide_setting_sem);
}
Index: linux-2.6.13/drivers/scsi/ide-scsi.c
===================================================================
--- linux-2.6.13.orig/drivers/scsi/ide-scsi.c 2005-09-06 15:08:07.000000000 -0700
+++ linux-2.6.13/drivers/scsi/ide-scsi.c 2005-09-06 15:16:15.000000000 -0700
@@ -956,6 +956,7 @@
ide_drive_t *drive = scsi->drive;
int busy;
int ret = FAILED;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
/* In idescsi_eh_abort we try to gently pry our command from the ide subsystem */
@@ -974,7 +975,7 @@
if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
printk (KERN_WARNING "ide-scsi: drive did%s become ready\n", busy?" not":"");
- spin_lock_irq(&ide_lock);
+ spin_lock_irq(&hwgroup->lock);
/* If there is no pc running we're done (our interrupt took care of it) */
if (!scsi->pc) {
@@ -1000,7 +1001,7 @@
}
ide_unlock:
- spin_unlock_irq(&ide_lock);
+ spin_unlock_irq(&hwgroup->lock);
no_drive:
if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
printk (KERN_WARNING "ide-scsi: abort returns %s\n", ret == SUCCESS?"success":"failed");
@@ -1015,6 +1016,7 @@
ide_drive_t *drive = scsi->drive;
int ready = 0;
int ret = SUCCESS;
+ ide_hwgroup_t *hwgroup = HWGROUP(drive);
/* In idescsi_eh_reset we forcefully remove the command from the ide subsystem and reset the device. */
@@ -1028,11 +1030,11 @@
}
spin_lock_irq(cmd->device->host->host_lock);
- spin_lock(&ide_lock);
+ spin_lock(&hwgroup->lock);
- if (!scsi->pc || (req = scsi->pc->rq) != HWGROUP(drive)->rq || !HWGROUP(drive)->handler) {
+ if (!scsi->pc || (req = scsi->pc->rq) != hwgroup->rq || !hwgroup->handler) {
printk (KERN_WARNING "ide-scsi: No active request in idescsi_eh_reset\n");
- spin_unlock(&ide_lock);
+ spin_unlock(&hwgroup->lock);
spin_unlock_irq(cmd->device->host->host_lock);
return FAILED;
}
@@ -1052,10 +1054,10 @@
end_that_request_last(req);
}
- HWGROUP(drive)->rq = NULL;
- HWGROUP(drive)->handler = NULL;
- HWGROUP(drive)->busy = 1; /* will set this to zero when ide reset finished */
- spin_unlock(&ide_lock);
+ hwgroup->rq = NULL;
+ hwgroup->handler = NULL;
+ hwgroup->busy = 1; /* will set this to zero when ide reset finished */
+ spin_unlock(&hwgroup->lock);
ide_do_reset(drive);
Index: linux-2.6.13/include/linux/ide.h
===================================================================
--- linux-2.6.13.orig/include/linux/ide.h 2005-09-06 15:08:07.000000000 -0700
+++ linux-2.6.13/include/linux/ide.h 2005-09-06 15:16:15.000000000 -0700
@@ -961,6 +961,7 @@
int pio_clock;
unsigned char cmd_buf[4];
+ spinlock_t lock;
} ide_hwgroup_t;
/* structure attached to the request for IDE_TASK_CMDS */
@@ -1480,12 +1481,12 @@
/*
* Structure locking:
*
- * ide_cfg_sem and ide_lock together protect changes to
+ * ide_cfg_sem and hwgroup->lock together protect changes to
* ide_hwif_t->{next,hwgroup}
* ide_drive_t->next
*
- * ide_hwgroup_t->busy: ide_lock
- * ide_hwgroup_t->hwif: ide_lock
+ * ide_hwgroup_t->busy: hwgroup->lock
+ * ide_hwgroup_t->hwif: hwgroup->lock
* ide_hwif_t->mate: constant, no locking
* ide_drive_t->hwif: constant, no locking
*/
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
|
|