diff options
Diffstat (limited to 'drivers/ide')
-rw-r--r-- | drivers/ide/ide-cd.c | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 282f1580fca9..74c6087ada38 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -1647,6 +1647,17 @@ static int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) | |||
1647 | return 1; | 1647 | return 1; |
1648 | } | 1648 | } |
1649 | 1649 | ||
1650 | /* | ||
1651 | * Called from blk_end_request_callback() after the data of the request | ||
1652 | * is completed and before the request is completed. | ||
1653 | * By returning value '1', blk_end_request_callback() returns immediately | ||
1654 | * without completing the request. | ||
1655 | */ | ||
1656 | static int cdrom_newpc_intr_dummy_cb(struct request *rq) | ||
1657 | { | ||
1658 | return 1; | ||
1659 | } | ||
1660 | |||
1650 | typedef void (xfer_func_t)(ide_drive_t *, void *, u32); | 1661 | typedef void (xfer_func_t)(ide_drive_t *, void *, u32); |
1651 | 1662 | ||
1652 | /* | 1663 | /* |
@@ -1685,9 +1696,13 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1685 | return ide_error(drive, "dma error", stat); | 1696 | return ide_error(drive, "dma error", stat); |
1686 | } | 1697 | } |
1687 | 1698 | ||
1688 | end_that_request_chunk(rq, 1, rq->data_len); | 1699 | spin_lock_irqsave(&ide_lock, flags); |
1689 | rq->data_len = 0; | 1700 | if (__blk_end_request(rq, 0, rq->data_len)) |
1690 | goto end_request; | 1701 | BUG(); |
1702 | HWGROUP(drive)->rq = NULL; | ||
1703 | spin_unlock_irqrestore(&ide_lock, flags); | ||
1704 | |||
1705 | return ide_stopped; | ||
1691 | } | 1706 | } |
1692 | 1707 | ||
1693 | /* | 1708 | /* |
@@ -1705,8 +1720,15 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1705 | /* | 1720 | /* |
1706 | * If DRQ is clear, the command has completed. | 1721 | * If DRQ is clear, the command has completed. |
1707 | */ | 1722 | */ |
1708 | if ((stat & DRQ_STAT) == 0) | 1723 | if ((stat & DRQ_STAT) == 0) { |
1709 | goto end_request; | 1724 | spin_lock_irqsave(&ide_lock, flags); |
1725 | if (__blk_end_request(rq, 0, 0)) | ||
1726 | BUG(); | ||
1727 | HWGROUP(drive)->rq = NULL; | ||
1728 | spin_unlock_irqrestore(&ide_lock, flags); | ||
1729 | |||
1730 | return ide_stopped; | ||
1731 | } | ||
1710 | 1732 | ||
1711 | /* | 1733 | /* |
1712 | * check which way to transfer data | 1734 | * check which way to transfer data |
@@ -1759,7 +1781,14 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1759 | rq->data_len -= blen; | 1781 | rq->data_len -= blen; |
1760 | 1782 | ||
1761 | if (rq->bio) | 1783 | if (rq->bio) |
1762 | end_that_request_chunk(rq, 1, blen); | 1784 | /* |
1785 | * The request can't be completed until DRQ is cleared. | ||
1786 | * So complete the data, but don't complete the request | ||
1787 | * using the dummy function for the callback feature | ||
1788 | * of blk_end_request_callback(). | ||
1789 | */ | ||
1790 | blk_end_request_callback(rq, 0, blen, | ||
1791 | cdrom_newpc_intr_dummy_cb); | ||
1763 | else | 1792 | else |
1764 | rq->data += blen; | 1793 | rq->data += blen; |
1765 | } | 1794 | } |
@@ -1780,14 +1809,6 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
1780 | 1809 | ||
1781 | ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL); | 1810 | ide_set_handler(drive, cdrom_newpc_intr, rq->timeout, NULL); |
1782 | return ide_started; | 1811 | return ide_started; |
1783 | |||
1784 | end_request: | ||
1785 | spin_lock_irqsave(&ide_lock, flags); | ||
1786 | blkdev_dequeue_request(rq); | ||
1787 | end_that_request_last(rq, 1); | ||
1788 | HWGROUP(drive)->rq = NULL; | ||
1789 | spin_unlock_irqrestore(&ide_lock, flags); | ||
1790 | return ide_stopped; | ||
1791 | } | 1812 | } |
1792 | 1813 | ||
1793 | static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) | 1814 | static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) |