diff options
author | Borislav Petkov <petkovbb@googlemail.com> | 2008-04-27 09:38:34 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-04-27 09:38:34 -0400 |
commit | 077e3bdb9ec34d7cb5751b5be81a4a0f6f0eb5dc (patch) | |
tree | 69a6666e92a8cf3da482abdebc8a7022740f654c /drivers/ide/ide-tape.c | |
parent | 01a63aebe4dcfcbe983c40a475e4650a4ae614de (diff) |
ide-tape: remove tape->merge_stage
Get rid of the pipeline merge stage but retain the chrdev req caching
functionality by using a merge buffer tape->merge_bh which is flushed in chunks
of several blocks at a time. Also, remove last references to pipelining, e.g.
typedef idetape_stage_s.
Signed-off-by: Borislav Petkov <petkovbb@gmail.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-tape.c')
-rw-r--r-- | drivers/ide/ide-tape.c | 107 |
1 files changed, 46 insertions, 61 deletions
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 0b8765c22d7a..29870c415110 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -215,13 +215,6 @@ enum { | |||
215 | IDETAPE_FLAG_MEDIUM_PRESENT = (1 << 6), | 215 | IDETAPE_FLAG_MEDIUM_PRESENT = (1 << 6), |
216 | }; | 216 | }; |
217 | 217 | ||
218 | /* A pipeline stage. */ | ||
219 | typedef struct idetape_stage_s { | ||
220 | struct request rq; /* The corresponding request */ | ||
221 | struct idetape_bh *bh; /* The data buffers */ | ||
222 | struct idetape_stage_s *next; /* Pointer to the next stage */ | ||
223 | } idetape_stage_t; | ||
224 | |||
225 | /* | 218 | /* |
226 | * Most of our global data which we need to save even as we leave the driver due | 219 | * Most of our global data which we need to save even as we leave the driver due |
227 | * to an interrupt or a timer event is stored in the struct defined below. | 220 | * to an interrupt or a timer event is stored in the struct defined below. |
@@ -309,9 +302,11 @@ typedef struct ide_tape_obj { | |||
309 | 302 | ||
310 | /* Data buffer size chosen based on the tape's recommendation */ | 303 | /* Data buffer size chosen based on the tape's recommendation */ |
311 | int buffer_size; | 304 | int buffer_size; |
312 | idetape_stage_t *merge_stage; | 305 | /* merge buffer */ |
306 | struct idetape_bh *merge_bh; | ||
313 | /* size of the merge buffer */ | 307 | /* size of the merge buffer */ |
314 | int merge_bh_size; | 308 | int merge_bh_size; |
309 | /* pointer to current buffer head within the merge buffer */ | ||
315 | struct idetape_bh *bh; | 310 | struct idetape_bh *bh; |
316 | char *b_data; | 311 | char *b_data; |
317 | int b_count; | 312 | int b_count; |
@@ -585,9 +580,9 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) | |||
585 | } | 580 | } |
586 | 581 | ||
587 | /* Free data buffers completely. */ | 582 | /* Free data buffers completely. */ |
588 | static void ide_tape_kfree_buffer(idetape_stage_t *stage) | 583 | static void ide_tape_kfree_buffer(idetape_tape_t *tape) |
589 | { | 584 | { |
590 | struct idetape_bh *prev_bh, *bh = stage->bh; | 585 | struct idetape_bh *prev_bh, *bh = tape->merge_bh; |
591 | 586 | ||
592 | while (bh) { | 587 | while (bh) { |
593 | u32 size = bh->b_size; | 588 | u32 size = bh->b_size; |
@@ -605,7 +600,7 @@ static void ide_tape_kfree_buffer(idetape_stage_t *stage) | |||
605 | bh = bh->b_reqnext; | 600 | bh = bh->b_reqnext; |
606 | kfree(prev_bh); | 601 | kfree(prev_bh); |
607 | } | 602 | } |
608 | kfree(stage); | 603 | kfree(tape->merge_bh); |
609 | } | 604 | } |
610 | 605 | ||
611 | static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects) | 606 | static int idetape_end_request(ide_drive_t *drive, int uptodate, int nr_sects) |
@@ -1299,22 +1294,16 @@ out: | |||
1299 | * It returns a pointer to the newly allocated buffer, or NULL in case of | 1294 | * It returns a pointer to the newly allocated buffer, or NULL in case of |
1300 | * failure. | 1295 | * failure. |
1301 | */ | 1296 | */ |
1302 | static idetape_stage_t *ide_tape_kmalloc_buffer(idetape_tape_t *tape, int full, | 1297 | static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape, |
1303 | int clear) | 1298 | int full, int clear) |
1304 | { | 1299 | { |
1305 | idetape_stage_t *stage; | 1300 | struct idetape_bh *prev_bh, *bh, *merge_bh; |
1306 | struct idetape_bh *prev_bh, *bh; | ||
1307 | int pages = tape->pages_per_buffer; | 1301 | int pages = tape->pages_per_buffer; |
1308 | unsigned int order, b_allocd; | 1302 | unsigned int order, b_allocd; |
1309 | char *b_data = NULL; | 1303 | char *b_data = NULL; |
1310 | 1304 | ||
1311 | stage = kmalloc(sizeof(idetape_stage_t), GFP_KERNEL); | 1305 | merge_bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); |
1312 | if (!stage) | 1306 | bh = merge_bh; |
1313 | return NULL; | ||
1314 | stage->next = NULL; | ||
1315 | |||
1316 | stage->bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); | ||
1317 | bh = stage->bh; | ||
1318 | if (bh == NULL) | 1307 | if (bh == NULL) |
1319 | goto abort; | 1308 | goto abort; |
1320 | 1309 | ||
@@ -1374,9 +1363,9 @@ static idetape_stage_t *ide_tape_kmalloc_buffer(idetape_tape_t *tape, int full, | |||
1374 | bh->b_size -= tape->excess_bh_size; | 1363 | bh->b_size -= tape->excess_bh_size; |
1375 | if (full) | 1364 | if (full) |
1376 | atomic_sub(tape->excess_bh_size, &bh->b_count); | 1365 | atomic_sub(tape->excess_bh_size, &bh->b_count); |
1377 | return stage; | 1366 | return merge_bh; |
1378 | abort: | 1367 | abort: |
1379 | ide_tape_kfree_buffer(stage); | 1368 | ide_tape_kfree_buffer(tape); |
1380 | return NULL; | 1369 | return NULL; |
1381 | } | 1370 | } |
1382 | 1371 | ||
@@ -1444,11 +1433,11 @@ static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf, | |||
1444 | return ret; | 1433 | return ret; |
1445 | } | 1434 | } |
1446 | 1435 | ||
1447 | static void idetape_init_merge_stage(idetape_tape_t *tape) | 1436 | static void idetape_init_merge_buffer(idetape_tape_t *tape) |
1448 | { | 1437 | { |
1449 | struct idetape_bh *bh = tape->merge_stage->bh; | 1438 | struct idetape_bh *bh = tape->merge_bh; |
1439 | tape->bh = tape->merge_bh; | ||
1450 | 1440 | ||
1451 | tape->bh = bh; | ||
1452 | if (tape->chrdev_dir == IDETAPE_DIR_WRITE) | 1441 | if (tape->chrdev_dir == IDETAPE_DIR_WRITE) |
1453 | atomic_set(&bh->b_count, 0); | 1442 | atomic_set(&bh->b_count, 0); |
1454 | else { | 1443 | else { |
@@ -1651,9 +1640,9 @@ static void __ide_tape_discard_merge_buffer(ide_drive_t *drive) | |||
1651 | 1640 | ||
1652 | clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags); | 1641 | clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags); |
1653 | tape->merge_bh_size = 0; | 1642 | tape->merge_bh_size = 0; |
1654 | if (tape->merge_stage != NULL) { | 1643 | if (tape->merge_bh != NULL) { |
1655 | ide_tape_kfree_buffer(tape->merge_stage); | 1644 | ide_tape_kfree_buffer(tape); |
1656 | tape->merge_stage = NULL; | 1645 | tape->merge_bh = NULL; |
1657 | } | 1646 | } |
1658 | 1647 | ||
1659 | tape->chrdev_dir = IDETAPE_DIR_NONE; | 1648 | tape->chrdev_dir = IDETAPE_DIR_NONE; |
@@ -1725,8 +1714,8 @@ static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, | |||
1725 | if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0) | 1714 | if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0) |
1726 | return 0; | 1715 | return 0; |
1727 | 1716 | ||
1728 | if (tape->merge_stage) | 1717 | if (tape->merge_bh) |
1729 | idetape_init_merge_stage(tape); | 1718 | idetape_init_merge_buffer(tape); |
1730 | if (rq.errors == IDETAPE_ERROR_GENERAL) | 1719 | if (rq.errors == IDETAPE_ERROR_GENERAL) |
1731 | return -EIO; | 1720 | return -EIO; |
1732 | return (tape->blk_size * (blocks-rq.current_nr_sectors)); | 1721 | return (tape->blk_size * (blocks-rq.current_nr_sectors)); |
@@ -1777,7 +1766,7 @@ static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks) | |||
1777 | debug_log(DBG_CHRDEV, "Enter %s\n", __func__); | 1766 | debug_log(DBG_CHRDEV, "Enter %s\n", __func__); |
1778 | 1767 | ||
1779 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, | 1768 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, |
1780 | blocks, tape->merge_stage->bh); | 1769 | blocks, tape->merge_bh); |
1781 | } | 1770 | } |
1782 | 1771 | ||
1783 | static void ide_tape_flush_merge_buffer(ide_drive_t *drive) | 1772 | static void ide_tape_flush_merge_buffer(ide_drive_t *drive) |
@@ -1787,7 +1776,7 @@ static void ide_tape_flush_merge_buffer(ide_drive_t *drive) | |||
1787 | struct idetape_bh *bh; | 1776 | struct idetape_bh *bh; |
1788 | 1777 | ||
1789 | if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { | 1778 | if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { |
1790 | printk(KERN_ERR "ide-tape: bug: Trying to empty write pipeline," | 1779 | printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer" |
1791 | " but we are not writing.\n"); | 1780 | " but we are not writing.\n"); |
1792 | return; | 1781 | return; |
1793 | } | 1782 | } |
@@ -1827,9 +1816,9 @@ static void ide_tape_flush_merge_buffer(ide_drive_t *drive) | |||
1827 | (void) idetape_add_chrdev_write_request(drive, blocks); | 1816 | (void) idetape_add_chrdev_write_request(drive, blocks); |
1828 | tape->merge_bh_size = 0; | 1817 | tape->merge_bh_size = 0; |
1829 | } | 1818 | } |
1830 | if (tape->merge_stage != NULL) { | 1819 | if (tape->merge_bh != NULL) { |
1831 | ide_tape_kfree_buffer(tape->merge_stage); | 1820 | ide_tape_kfree_buffer(tape); |
1832 | tape->merge_stage = NULL; | 1821 | tape->merge_bh = NULL; |
1833 | } | 1822 | } |
1834 | tape->chrdev_dir = IDETAPE_DIR_NONE; | 1823 | tape->chrdev_dir = IDETAPE_DIR_NONE; |
1835 | } | 1824 | } |
@@ -1845,13 +1834,13 @@ static int idetape_init_read(ide_drive_t *drive) | |||
1845 | ide_tape_flush_merge_buffer(drive); | 1834 | ide_tape_flush_merge_buffer(drive); |
1846 | idetape_flush_tape_buffers(drive); | 1835 | idetape_flush_tape_buffers(drive); |
1847 | } | 1836 | } |
1848 | if (tape->merge_stage || tape->merge_bh_size) { | 1837 | if (tape->merge_bh || tape->merge_bh_size) { |
1849 | printk(KERN_ERR "ide-tape: merge_bh_size should be" | 1838 | printk(KERN_ERR "ide-tape: merge_bh_size should be" |
1850 | " 0 now\n"); | 1839 | " 0 now\n"); |
1851 | tape->merge_bh_size = 0; | 1840 | tape->merge_bh_size = 0; |
1852 | } | 1841 | } |
1853 | tape->merge_stage = ide_tape_kmalloc_buffer(tape, 0, 0); | 1842 | tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0); |
1854 | if (!tape->merge_stage) | 1843 | if (!tape->merge_bh) |
1855 | return -ENOMEM; | 1844 | return -ENOMEM; |
1856 | tape->chrdev_dir = IDETAPE_DIR_READ; | 1845 | tape->chrdev_dir = IDETAPE_DIR_READ; |
1857 | 1846 | ||
@@ -1864,10 +1853,10 @@ static int idetape_init_read(ide_drive_t *drive) | |||
1864 | if (drive->dsc_overlap) { | 1853 | if (drive->dsc_overlap) { |
1865 | bytes_read = idetape_queue_rw_tail(drive, | 1854 | bytes_read = idetape_queue_rw_tail(drive, |
1866 | REQ_IDETAPE_READ, 0, | 1855 | REQ_IDETAPE_READ, 0, |
1867 | tape->merge_stage->bh); | 1856 | tape->merge_bh); |
1868 | if (bytes_read < 0) { | 1857 | if (bytes_read < 0) { |
1869 | ide_tape_kfree_buffer(tape->merge_stage); | 1858 | ide_tape_kfree_buffer(tape); |
1870 | tape->merge_stage = NULL; | 1859 | tape->merge_bh = NULL; |
1871 | tape->chrdev_dir = IDETAPE_DIR_NONE; | 1860 | tape->chrdev_dir = IDETAPE_DIR_NONE; |
1872 | return bytes_read; | 1861 | return bytes_read; |
1873 | } | 1862 | } |
@@ -1891,7 +1880,7 @@ static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks) | |||
1891 | idetape_init_read(drive); | 1880 | idetape_init_read(drive); |
1892 | 1881 | ||
1893 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks, | 1882 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks, |
1894 | tape->merge_stage->bh); | 1883 | tape->merge_bh); |
1895 | } | 1884 | } |
1896 | 1885 | ||
1897 | static void idetape_pad_zeros(ide_drive_t *drive, int bcount) | 1886 | static void idetape_pad_zeros(ide_drive_t *drive, int bcount) |
@@ -1903,7 +1892,7 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount) | |||
1903 | while (bcount) { | 1892 | while (bcount) { |
1904 | unsigned int count; | 1893 | unsigned int count; |
1905 | 1894 | ||
1906 | bh = tape->merge_stage->bh; | 1895 | bh = tape->merge_bh; |
1907 | count = min(tape->buffer_size, bcount); | 1896 | count = min(tape->buffer_size, bcount); |
1908 | bcount -= count; | 1897 | bcount -= count; |
1909 | blocks = count / tape->blk_size; | 1898 | blocks = count / tape->blk_size; |
@@ -1915,7 +1904,7 @@ static void idetape_pad_zeros(ide_drive_t *drive, int bcount) | |||
1915 | bh = bh->b_reqnext; | 1904 | bh = bh->b_reqnext; |
1916 | } | 1905 | } |
1917 | idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks, | 1906 | idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks, |
1918 | tape->merge_stage->bh); | 1907 | tape->merge_bh); |
1919 | } | 1908 | } |
1920 | } | 1909 | } |
1921 | 1910 | ||
@@ -2000,10 +1989,6 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op, | |||
2000 | ide_tape_discard_merge_buffer(drive, 0); | 1989 | ide_tape_discard_merge_buffer(drive, 0); |
2001 | } | 1990 | } |
2002 | 1991 | ||
2003 | /* | ||
2004 | * The filemark was not found in our internal pipeline; now we can issue | ||
2005 | * the space command. | ||
2006 | */ | ||
2007 | switch (mt_op) { | 1992 | switch (mt_op) { |
2008 | case MTFSF: | 1993 | case MTFSF: |
2009 | case MTBSF: | 1994 | case MTBSF: |
@@ -2123,16 +2108,16 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
2123 | if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { | 2108 | if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { |
2124 | if (tape->chrdev_dir == IDETAPE_DIR_READ) | 2109 | if (tape->chrdev_dir == IDETAPE_DIR_READ) |
2125 | ide_tape_discard_merge_buffer(drive, 1); | 2110 | ide_tape_discard_merge_buffer(drive, 1); |
2126 | if (tape->merge_stage || tape->merge_bh_size) { | 2111 | if (tape->merge_bh || tape->merge_bh_size) { |
2127 | printk(KERN_ERR "ide-tape: merge_bh_size " | 2112 | printk(KERN_ERR "ide-tape: merge_bh_size " |
2128 | "should be 0 now\n"); | 2113 | "should be 0 now\n"); |
2129 | tape->merge_bh_size = 0; | 2114 | tape->merge_bh_size = 0; |
2130 | } | 2115 | } |
2131 | tape->merge_stage = ide_tape_kmalloc_buffer(tape, 0, 0); | 2116 | tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0); |
2132 | if (!tape->merge_stage) | 2117 | if (!tape->merge_bh) |
2133 | return -ENOMEM; | 2118 | return -ENOMEM; |
2134 | tape->chrdev_dir = IDETAPE_DIR_WRITE; | 2119 | tape->chrdev_dir = IDETAPE_DIR_WRITE; |
2135 | idetape_init_merge_stage(tape); | 2120 | idetape_init_merge_buffer(tape); |
2136 | 2121 | ||
2137 | /* | 2122 | /* |
2138 | * Issue a write 0 command to ensure that DSC handshake is | 2123 | * Issue a write 0 command to ensure that DSC handshake is |
@@ -2143,10 +2128,10 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
2143 | if (drive->dsc_overlap) { | 2128 | if (drive->dsc_overlap) { |
2144 | ssize_t retval = idetape_queue_rw_tail(drive, | 2129 | ssize_t retval = idetape_queue_rw_tail(drive, |
2145 | REQ_IDETAPE_WRITE, 0, | 2130 | REQ_IDETAPE_WRITE, 0, |
2146 | tape->merge_stage->bh); | 2131 | tape->merge_bh); |
2147 | if (retval < 0) { | 2132 | if (retval < 0) { |
2148 | ide_tape_kfree_buffer(tape->merge_stage); | 2133 | ide_tape_kfree_buffer(tape); |
2149 | tape->merge_stage = NULL; | 2134 | tape->merge_bh = NULL; |
2150 | tape->chrdev_dir = IDETAPE_DIR_NONE; | 2135 | tape->chrdev_dir = IDETAPE_DIR_NONE; |
2151 | return retval; | 2136 | return retval; |
2152 | } | 2137 | } |
@@ -2508,12 +2493,12 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor) | |||
2508 | idetape_tape_t *tape = drive->driver_data; | 2493 | idetape_tape_t *tape = drive->driver_data; |
2509 | 2494 | ||
2510 | ide_tape_flush_merge_buffer(drive); | 2495 | ide_tape_flush_merge_buffer(drive); |
2511 | tape->merge_stage = ide_tape_kmalloc_buffer(tape, 1, 0); | 2496 | tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1, 0); |
2512 | if (tape->merge_stage != NULL) { | 2497 | if (tape->merge_bh != NULL) { |
2513 | idetape_pad_zeros(drive, tape->blk_size * | 2498 | idetape_pad_zeros(drive, tape->blk_size * |
2514 | (tape->user_bs_factor - 1)); | 2499 | (tape->user_bs_factor - 1)); |
2515 | ide_tape_kfree_buffer(tape->merge_stage); | 2500 | ide_tape_kfree_buffer(tape); |
2516 | tape->merge_stage = NULL; | 2501 | tape->merge_bh = NULL; |
2517 | } | 2502 | } |
2518 | idetape_write_filemark(drive); | 2503 | idetape_write_filemark(drive); |
2519 | idetape_flush_tape_buffers(drive); | 2504 | idetape_flush_tape_buffers(drive); |