*/
/* Data buffer size chosen based on the tape's recommendation */
- int stage_size;
+ int buffer_size;
idetape_stage_t *merge_stage;
int merge_stage_size;
struct idetape_bh *bh;
char *b_data;
int b_count;
- /* Pipeline parameters. */
- int pages_per_stage;
+ int pages_per_buffer;
/* Wasted space in each stage */
int excess_bh_size;
}
}
-/* Free a stage along with its related buffers completely. */
-static void __idetape_kfree_stage(idetape_stage_t *stage)
+/* Free data buffers completely. */
+static void ide_tape_kfree_buffer(idetape_stage_t *stage)
{
struct idetape_bh *prev_bh, *bh = stage->bh;
- int size;
-
- while (bh != NULL) {
- if (bh->b_data != NULL) {
- size = (int) bh->b_size;
- while (size > 0) {
- free_page((unsigned long) bh->b_data);
- size -= PAGE_SIZE;
- bh->b_data += PAGE_SIZE;
- }
+
+ while (bh) {
+ u32 size = bh->b_size;
+
+ while (size) {
+ unsigned int order = fls(size >> PAGE_SHIFT)-1;
+
+ if (bh->b_data)
+ free_pages((unsigned long)bh->b_data, order);
+
+ size &= (order-1);
+ bh->b_data += (1 << order) * PAGE_SIZE;
}
prev_bh = bh;
bh = bh->b_reqnext;
pc->buf = NULL;
pc->buf_size = length * tape->blk_size;
pc->req_xfer = pc->buf_size;
- if (pc->req_xfer == tape->stage_size)
+ if (pc->req_xfer == tape->buffer_size)
pc->flags |= PC_FLAG_DMA_RECOMMENDED;
}
pc->buf = NULL;
pc->buf_size = length * tape->blk_size;
pc->req_xfer = pc->buf_size;
- if (pc->req_xfer == tape->stage_size)
+ if (pc->req_xfer == tape->buffer_size)
pc->flags |= PC_FLAG_DMA_RECOMMENDED;
}
/*
* The function below uses __get_free_pages to allocate a data buffer of size
- * tape->stage_size (or a bit more). We attempt to combine sequential pages as
+ * tape->buffer_size (or a bit more). We attempt to combine sequential pages as
* much as possible.
*
* It returns a pointer to the newly allocated buffer, or NULL in case of
{
idetape_stage_t *stage;
struct idetape_bh *prev_bh, *bh;
- int pages = tape->pages_per_stage;
+ int pages = tape->pages_per_buffer;
unsigned int order, b_allocd;
char *b_data = NULL;
atomic_sub(tape->excess_bh_size, &bh->b_count);
return stage;
abort:
- __idetape_kfree_stage(stage);
+ ide_tape_kfree_buffer(stage);
return NULL;
}
return 1;
}
-static int __idetape_discard_read_pipeline(ide_drive_t *drive)
+static void __idetape_discard_read_pipeline(ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
if (tape->chrdev_dir != IDETAPE_DIR_READ)
- return 0;
+ return;
clear_bit(IDETAPE_FLAG_FILEMARK, &tape->flags);
tape->merge_stage_size = 0;
if (tape->merge_stage != NULL) {
- __idetape_kfree_stage(tape->merge_stage);
+ ide_tape_kfree_buffer(tape->merge_stage);
tape->merge_stage = NULL;
}
tape->chrdev_dir = IDETAPE_DIR_NONE;
-
- return 0;
}
/*
int restore_position)
{
idetape_tape_t *tape = drive->driver_data;
- int cnt;
int seek, position;
- cnt = __idetape_discard_read_pipeline(drive);
+ __idetape_discard_read_pipeline(drive);
if (restore_position) {
position = idetape_read_position(drive);
- seek = position > cnt ? position - cnt : 0;
+ seek = position > 0 ? position : 0;
if (idetape_position_tape(drive, seek, 0, 0)) {
printk(KERN_INFO "ide-tape: %s: position_tape failed in"
" discard_pipeline()\n", tape->name);
" but we are not writing.\n");
return;
}
- if (tape->merge_stage_size > tape->stage_size) {
+ if (tape->merge_stage_size > tape->buffer_size) {
printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n");
- tape->merge_stage_size = tape->stage_size;
+ tape->merge_stage_size = tape->buffer_size;
}
if (tape->merge_stage_size) {
blocks = tape->merge_stage_size / tape->blk_size;
tape->merge_stage_size = 0;
}
if (tape->merge_stage != NULL) {
- __idetape_kfree_stage(tape->merge_stage);
+ ide_tape_kfree_buffer(tape->merge_stage);
tape->merge_stage = NULL;
}
tape->chrdev_dir = IDETAPE_DIR_NONE;
REQ_IDETAPE_READ, 0,
tape->merge_stage->bh);
if (bytes_read < 0) {
- __idetape_kfree_stage(tape->merge_stage);
+ ide_tape_kfree_buffer(tape->merge_stage);
tape->merge_stage = NULL;
tape->chrdev_dir = IDETAPE_DIR_NONE;
return bytes_read;
unsigned int count;
bh = tape->merge_stage->bh;
- count = min(tape->stage_size, bcount);
+ count = min(tape->buffer_size, bcount);
bcount -= count;
blocks = count / tape->blk_size;
while (count) {
tape->merge_stage_size -= actually_read;
count -= actually_read;
}
- while (count >= tape->stage_size) {
+ while (count >= tape->buffer_size) {
bytes_read = idetape_add_chrdev_read_request(drive, ctl);
if (bytes_read <= 0)
goto finish;
REQ_IDETAPE_WRITE, 0,
tape->merge_stage->bh);
if (retval < 0) {
- __idetape_kfree_stage(tape->merge_stage);
+ ide_tape_kfree_buffer(tape->merge_stage);
tape->merge_stage = NULL;
tape->chrdev_dir = IDETAPE_DIR_NONE;
return retval;
if (count == 0)
return (0);
if (tape->merge_stage_size) {
- if (tape->merge_stage_size >= tape->stage_size) {
+ if (tape->merge_stage_size >= tape->buffer_size) {
printk(KERN_ERR "ide-tape: bug: merge buf too big\n");
tape->merge_stage_size = 0;
}
actually_written = min((unsigned int)
- (tape->stage_size - tape->merge_stage_size),
+ (tape->buffer_size - tape->merge_stage_size),
(unsigned int)count);
if (idetape_copy_stage_from_user(tape, buf, actually_written))
ret = -EFAULT;
tape->merge_stage_size += actually_written;
count -= actually_written;
- if (tape->merge_stage_size == tape->stage_size) {
+ if (tape->merge_stage_size == tape->buffer_size) {
ssize_t retval;
tape->merge_stage_size = 0;
retval = idetape_add_chrdev_write_request(drive, ctl);
return (retval);
}
}
- while (count >= tape->stage_size) {
+ while (count >= tape->buffer_size) {
ssize_t retval;
- if (idetape_copy_stage_from_user(tape, buf, tape->stage_size))
+ if (idetape_copy_stage_from_user(tape, buf, tape->buffer_size))
ret = -EFAULT;
- buf += tape->stage_size;
- count -= tape->stage_size;
+ buf += tape->buffer_size;
+ count -= tape->buffer_size;
retval = idetape_add_chrdev_write_request(drive, ctl);
- actually_written += tape->stage_size;
+ actually_written += tape->buffer_size;
if (retval <= 0)
return (retval);
}
if (tape->merge_stage != NULL) {
idetape_pad_zeros(drive, tape->blk_size *
(tape->user_bs_factor - 1));
- __idetape_kfree_stage(tape->merge_stage);
+ ide_tape_kfree_buffer(tape->merge_stage);
tape->merge_stage = NULL;
}
idetape_write_filemark(drive);
1, 2, (u16 *)&tape->caps[16], NULL);
ide_add_setting(drive, "speed", SETTING_READ, TYPE_SHORT, 0, 0xffff,
1, 1, (u16 *)&tape->caps[14], NULL);
- ide_add_setting(drive, "stage", SETTING_READ, TYPE_INT, 0, 0xffff, 1,
- 1024, &tape->stage_size, NULL);
+ ide_add_setting(drive, "buffer_size", SETTING_READ, TYPE_INT, 0, 0xffff,
+ 1, 1024, &tape->buffer_size, NULL);
ide_add_setting(drive, "tdsc", SETTING_RW, TYPE_INT, IDETAPE_DSC_RW_MIN,
IDETAPE_DSC_RW_MAX, 1000, HZ, &tape->best_dsc_rw_freq,
NULL);
{
unsigned long t;
int speed;
- int stage_size;
+ int buffer_size;
u8 gcw[2];
u16 *ctl = (u16 *)&tape->caps[12];
idetape_get_mode_sense_results(drive);
ide_tape_get_bsize_from_bdesc(drive);
tape->user_bs_factor = 1;
- tape->stage_size = *ctl * tape->blk_size;
- while (tape->stage_size > 0xffff) {
+ tape->buffer_size = *ctl * tape->blk_size;
+ while (tape->buffer_size > 0xffff) {
printk(KERN_NOTICE "ide-tape: decreasing stage size\n");
*ctl /= 2;
- tape->stage_size = *ctl * tape->blk_size;
+ tape->buffer_size = *ctl * tape->blk_size;
}
- stage_size = tape->stage_size;
- tape->pages_per_stage = stage_size / PAGE_SIZE;
- if (stage_size % PAGE_SIZE) {
- tape->pages_per_stage++;
- tape->excess_bh_size = PAGE_SIZE - stage_size % PAGE_SIZE;
+ buffer_size = tape->buffer_size;
+ tape->pages_per_buffer = buffer_size / PAGE_SIZE;
+ if (buffer_size % PAGE_SIZE) {
+ tape->pages_per_buffer++;
+ tape->excess_bh_size = PAGE_SIZE - buffer_size % PAGE_SIZE;
}
/* select the "best" DSC read/write polling freq */
speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]);
- t = (IDETAPE_FIFO_THRESHOLD * tape->stage_size * HZ) / (speed * 1000);
+ t = (IDETAPE_FIFO_THRESHOLD * tape->buffer_size * HZ) / (speed * 1000);
/*
* Ensure that the number we got makes sense; limit it within
printk(KERN_INFO "ide-tape: %s <-> %s: %dKBps, %d*%dkB buffer, "
"%lums tDSC%s\n",
drive->name, tape->name, *(u16 *)&tape->caps[14],
- (*(u16 *)&tape->caps[16] * 512) / tape->stage_size,
- tape->stage_size / 1024,
+ (*(u16 *)&tape->caps[16] * 512) / tape->buffer_size,
+ tape->buffer_size / 1024,
tape->best_dsc_rw_freq * 1000 / HZ,
drive->using_dma ? ", DMA":"");