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 | |
| 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')
| -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); |
