From: <he...@us...> - 2005-07-03 09:44:42
|
Update of /cvsroot/gc-linux/linux/drivers/block/gcn-di In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24356 Modified Files: gcn-di.c Log Message: Do not completely lock the system while doing the "last user done" motor off. Now, in the worst case, a process opening the dvd device while the mentioned motor off is in progress will have to sleep a bit. But the rest of the system will be responsive. Index: gcn-di.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/block/gcn-di/gcn-di.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- gcn-di.c 13 Jun 2005 22:55:45 -0000 1.5 +++ gcn-di.c 3 Jul 2005 09:44:34 -0000 1.6 @@ -1276,7 +1276,7 @@ } /* - * Configures the drive to accept DVD-R media. + * Configures the drive to accept DVD-R and DVD+R media. */ static void di_make_interoperable(struct di_device *ddev) { @@ -1337,15 +1337,18 @@ static void di_motor_off(unsigned long ddev0) { struct di_device *ddev = (struct di_device *)ddev0; - struct di_command cmd; + struct di_command *cmd; + unsigned long flags; /* postpone a bit the motor off if there are pending commands */ - if (!ddev->cmd) { - di_op_stopmotor(&cmd, ddev); - di_run_command(&cmd); - di_wait_for_dma_transfer_raw(ddev); - di_complete_transfer(ddev, DI_SR_TCINT); + spin_lock_irqsave(&ddev->lock, flags); + if (!ddev->cmd && ddev->ref_count == 0) { + ddev->cmd = cmd = &ddev->status; + spin_unlock_irqrestore(&ddev->lock, flags); + di_op_stopmotor(cmd, ddev); + di_prepare_command(cmd, 1); } else { + spin_unlock_irqrestore(&ddev->lock, flags); mod_timer(&ddev->motor_off_timer, jiffies + 1*HZ); } } @@ -1599,6 +1602,8 @@ static int di_open(struct inode *inode, struct file *filp) { struct di_device *ddev = inode->i_bdev->bd_disk->private_data; + struct di_command *cmd; + DECLARE_COMPLETION(complete); unsigned long flags; int retval = 0; @@ -1623,6 +1628,19 @@ goto out_unlock; } + /* + * If we have a pending command, that's a previously scheduled + * motor off. Wait for it to terminate before going on. + */ + if (ddev->cmd) { + cmd = ddev->cmd; + cmd->done_data = &complete; + cmd->done = di_wait_done; + spin_unlock_irqrestore(&ddev->queue_lock, flags); + wait_for_completion(&complete); + spin_lock_irqsave(&ddev->queue_lock, flags); + } + /* this will take care of validating the media */ check_disk_change(inode->i_bdev); if (!ddev->nr_sectors) { |