summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/i386/config.in4
-rw-r--r--arch/ppc/config.in1
-rw-r--r--arch/ppc64/kernel/pSeries_lpar.c9
-rw-r--r--drivers/char/hvc_console.c26
-rw-r--r--drivers/scsi/README.st29
-rw-r--r--drivers/scsi/scsi_lib.c2
-rw-r--r--drivers/scsi/st.c342
-rw-r--r--drivers/scsi/st.h17
-rw-r--r--include/asm-arm/tlb.h2
-rw-r--r--include/asm-i386/tlb.h2
-rw-r--r--include/asm-ia64/tlb.h2
-rw-r--r--include/asm-m68k/tlb.h2
-rw-r--r--include/asm-s390/tlb.h2
-rw-r--r--include/asm-s390x/tlb.h2
-rw-r--r--include/asm-sparc64/tlb.h2
-rw-r--r--include/asm-x86_64/tlb.h2
-rw-r--r--include/linux/trdevice.h1
-rw-r--r--include/linux/writeback.h5
-rw-r--r--mm/memory.c2
-rw-r--r--mm/rmap.c2
-rw-r--r--net/802/tr.c3
-rw-r--r--net/sunrpc/xprt.c4
22 files changed, 255 insertions, 208 deletions
diff --git a/arch/i386/config.in b/arch/i386/config.in
index 497404ef3ab1..d1c238813604 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -185,10 +185,6 @@ choice 'High Memory Support' \
4GB CONFIG_HIGHMEM4G \
64GB CONFIG_HIGHMEM64G" off
-if [ "$CONFIG_HIGHMEM4G" = "y" -o "$CONFIG_HIGHMEM64G" = "y" ]; then
- bool 'Use high memory pte support' CONFIG_HIGHPTE
-fi
-
if [ "$CONFIG_HIGHMEM4G" = "y" ]; then
define_bool CONFIG_HIGHMEM y
fi
diff --git a/arch/ppc/config.in b/arch/ppc/config.in
index 47d44bbd3fc2..071430604929 100644
--- a/arch/ppc/config.in
+++ b/arch/ppc/config.in
@@ -263,7 +263,6 @@ mainmenu_option next_comment
comment 'General setup'
bool 'High memory support' CONFIG_HIGHMEM
-dep_bool ' Support for PTEs in high memory' CONFIG_HIGHPTE $CONFIG_HIGHMEM
bool 'Prompt for advanced kernel configuration options' CONFIG_ADVANCED_OPTIONS
if [ "$CONFIG_ADVANCED_OPTIONS" = "y" ]; then
if [ "$CONFIG_HIGHMEM" = "y" ]; then
diff --git a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
index ea528fe1dd33..725079abb839 100644
--- a/arch/ppc64/kernel/pSeries_lpar.c
+++ b/arch/ppc64/kernel/pSeries_lpar.c
@@ -356,8 +356,13 @@ static int udbg_getc_pollLP(void)
/* get some more chars. */
inbuflen = 0;
rc = plpar_get_term_char(vtermno, &inbuflen, buf);
- if (inbuflen == 0 && rc == H_Success)
- return -1;
+ if (rc != H_Success)
+ inbuflen = 0; /* otherwise inbuflen is garbage */
+ }
+ if (inbuflen <= 0 || inbuflen > 16) {
+ /* Catch error case as well as other oddities (corruption) */
+ inbuflen = 0;
+ return -1;
}
ch = buf[0];
for (i = 1; i < inbuflen; i++) /* shuffle them down. */
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 64c0718655a5..515bf2a68889 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -22,6 +22,7 @@
#include <linux/console.h>
#include <linux/major.h>
#include <linux/kernel.h>
+#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/sched.h>
@@ -46,6 +47,9 @@ static struct tty_struct *hvc_table[MAX_NR_HVC_CONSOLES];
static struct termios *hvc_termios[MAX_NR_HVC_CONSOLES];
static struct termios *hvc_termios_locked[MAX_NR_HVC_CONSOLES];
static int hvc_offset;
+#ifdef CONFIG_MAGIC_SYSRQ
+static int sysrq_pressed;
+#endif
#define N_OUTBUF 16
@@ -98,6 +102,14 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
spin_unlock_irqrestore(&hp->lock, flags);
}
+static void hvc_hangup(struct tty_struct *tty)
+{
+ struct hvc_struct *hp = tty->driver_data;
+
+ hp->count = 0;
+ hp->tty = NULL;
+}
+
/* called with hp->lock held */
static void hvc_push(struct hvc_struct *hp)
{
@@ -186,8 +198,19 @@ static void hvc_poll(int index)
n = hvc_get_chars(index + hvc_offset, buf, sizeof(buf));
if (n <= 0)
break;
- for (i = 0; i < n; ++i)
+ for (i = 0; i < n; ++i) {
+#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
+ if (buf[i] == '\x0f') { /* ^O -- should support a sequence */
+ sysrq_pressed = 1;
+ continue;
+ } else if (sysrq_pressed) {
+ handle_sysrq(buf[i], NULL, NULL, tty);
+ sysrq_pressed = 0;
+ continue;
+ }
+#endif
tty_insert_flip_char(tty, buf[i], 0);
+ }
}
if (tty->flip.count)
tty_schedule_flip(tty);
@@ -246,6 +269,7 @@ int __init hvc_init(void)
hvc_driver.open = hvc_open;
hvc_driver.close = hvc_close;
hvc_driver.write = hvc_write;
+ hvc_driver.hangup = hvc_hangup;
hvc_driver.write_room = hvc_write_room;
hvc_driver.chars_in_buffer = hvc_chars_in_buffer;
diff --git a/drivers/scsi/README.st b/drivers/scsi/README.st
index 702a5b178b61..5c582fc7e37e 100644
--- a/drivers/scsi/README.st
+++ b/drivers/scsi/README.st
@@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver.
The driver is currently maintained by Kai M{kisara (email
Kai.Makisara@metla.fi)
-Last modified: Tue Jun 18 18:13:50 2002 by makisara
+Last modified: Mon Jul 15 16:30:40 2002 by makisara
BASICS
@@ -118,7 +118,6 @@ allowed if ST_BUFFER_WRITES is non-zero. Buffer allocation uses chunks of
memory having sizes 2^n * (page size). Because of this the actual
buffer size may be larger than the minimum allowable buffer size.
-
Asynchronous writing. Writing the buffer contents to the tape is
started and the write call returns immediately. The status is checked
at the next tape operation.
@@ -163,12 +162,24 @@ is smaller than the number of segments used in phases 1 and 2,
extending the buffer will always fail.
+EOM BEHAVIOUR WHEN WRITING
+
+When the end of medium early warning is encountered, the current write
+is finished and the number of bytes is returned. The next write
+returns -1 and errno is set to ENOSPC. To enable writing a trailer,
+the next write is allowed to proceed and, if successful, the number of
+bytes is returned. After this, -1 and the number of bytes are
+alternately returned until the physical end of medium (or some other
+error) is encountered.
+
+
MODULE PARAMETERS
The buffer size, write threshold, and the maximum number of allocated buffers
are configurable when the driver is loaded as a module. The keywords are:
-buffer_kbs=xxx the buffer size in kilobytes is set to xxx
+buffer_kbs=xxx the buffer size for fixed block mode is set
+ to xxx kilobytes
write_threshold_kbs=xxx the write threshold in kilobytes set to xxx
max_buffers=xxx the maximum number of tape buffer set to xxx
max_sg_segs=xxx the maximum number of scatter/gather
@@ -188,17 +199,15 @@ a comma (no spaces allowed). A colon can be used instead of the equal
mark. The definition is prepended by the string st=. Here is an
example:
- st=buffer_kbs:64,max_buffers:2
+ st=buffer_kbs:64,write_threhold_kbs:60
The following syntax used by the old kernel versions is also supported:
- st=aa[,bb[,cc[,dd]]]
+ st=aa[,bb[,dd]]
where
- aa is the buffer size in 1024 byte units
+ aa is the buffer size for fixed block mode in 1024 byte units
bb is the write threshold in 1024 byte units
- cc is the maximum number of tape buffers to allocate (the number of
- buffers is bounded also by the number of drives detected)
dd is the maximum number of scatter/gather segments
@@ -231,7 +240,9 @@ MTOFFL Set device off line (often rewind plus eject).
MTNOP Do nothing except flush the buffers.
MTRETEN Re-tension tape.
MTEOM Space to end of recorded data.
-MTERASE Erase tape.
+MTERASE Erase tape. If the argument is zero, the short erase command
+ is used. The long erase command is used with all other values
+ of the argument.
MTSEEK Seek to tape block count. Uses Tandberg-compatible seek (QFA)
for SCSI-1 drives and SCSI-2 seek for SCSI-2 drives. The file and
block numbers in the status are not valid after a seek.
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 5fbe664e65ea..0bbb215e7a8d 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -360,7 +360,7 @@ static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt,
{
request_queue_t *q = &SCpnt->device->request_queue;
struct request *req = SCpnt->request;
- int flags;
+ unsigned long flags;
ASSERT_LOCK(q->queue_lock, 0);
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index 6310d0f1b182..9ba9b04048ba 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -12,13 +12,13 @@
Copyright 1992 - 2002 Kai Makisara
email Kai.Makisara@metla.fi
- Last modified: Sat Jun 15 13:01:56 2002 by makisara
+ Last modified: Mon Jul 22 13:27:21 2002 by makisara
Some small formal changes - aeb, 950809
Last modified: 18-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support
*/
-static char *verstr = "20020615";
+static char *verstr = "20020722";
#include <linux/module.h>
@@ -76,11 +76,11 @@ MODULE_DESCRIPTION("SCSI Tape Driver");
MODULE_LICENSE("GPL");
MODULE_PARM(buffer_kbs, "i");
-MODULE_PARM_DESC(buffer_kbs, "Default driver buffer size (KB; 32)");
+MODULE_PARM_DESC(buffer_kbs, "Default driver buffer size for fixed block mode (KB; 32)");
MODULE_PARM(write_threshold_kbs, "i");
MODULE_PARM_DESC(write_threshold_kbs, "Asynchronous write threshold (KB; 30)");
MODULE_PARM(max_sg_segs, "i");
-MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (32)");
+MODULE_PARM_DESC(max_sg_segs, "Maximum number of scatter/gather segments to use (64)");
#ifndef MODULE
static struct st_dev_parm {
@@ -139,25 +139,26 @@ static Scsi_Tape **scsi_tapes = NULL;
static int modes_defined;
-static ST_buffer *new_tape_buffer(int, int);
+static ST_buffer *new_tape_buffer(int, int, int);
static int enlarge_buffer(ST_buffer *, int, int);
static void normalize_buffer(ST_buffer *);
static int append_to_buffer(const char *, ST_buffer *, int);
static int from_buffer(ST_buffer *, char *, int);
+static void buf_to_sg(ST_buffer *, unsigned int);
static int st_attach(Scsi_Device *);
static int st_detect(Scsi_Device *);
static void st_detach(Scsi_Device *);
static struct Scsi_Device_Template st_template = {
- module: THIS_MODULE,
- name: "tape",
- tag: "st",
- scsi_type: TYPE_TAPE,
- major: SCSI_TAPE_MAJOR,
- detect: st_detect,
- attach: st_attach,
- detach: st_detach
+ .module = THIS_MODULE,
+ .name = "tape",
+ .tag = "st",
+ .scsi_type = TYPE_TAPE,
+ .major = SCSI_TAPE_MAJOR,
+ .detect = st_detect,
+ .attach = st_attach,
+ .detach = st_detach
};
static int st_compression(Scsi_Tape *, int);
@@ -361,12 +362,11 @@ static Scsi_Request *
if (SRpnt->sr_device->scsi_level <= SCSI_2)
cmd[1] |= (SRpnt->sr_device->lun << 5) & 0xe0;
init_completion(&STp->wait);
- SRpnt->sr_use_sg = (bytes > (STp->buffer)->sg[0].length) ?
- (STp->buffer)->use_sg : 0;
+ SRpnt->sr_use_sg = (bytes > (STp->buffer)->frp[0].length);
if (SRpnt->sr_use_sg) {
+ buf_to_sg(STp->buffer, bytes);
+ SRpnt->sr_use_sg = (STp->buffer)->sg_segs;
bp = (char *) &((STp->buffer)->sg[0]);
- if ((STp->buffer)->sg_segs < SRpnt->sr_use_sg)
- SRpnt->sr_use_sg = (STp->buffer)->sg_segs;
} else
bp = (STp->buffer)->b_data;
SRpnt->sr_data_direction = direction;
@@ -550,7 +550,6 @@ static int flush_buffer(Scsi_Tape *STp, int seek_next)
if (STp->ready != ST_READY)
return 0;
-
STps = &(STp->ps[STp->partition]);
if (STps->rw == ST_WRITING) /* Writing */
return flush_write_buffer(STp);
@@ -1226,14 +1225,15 @@ static ssize_t
ssize_t total;
ssize_t i, do_count, blks, transfer;
ssize_t retval;
- int write_threshold;
- int doing_write = 0;
+ int undone;
+ int async_write;
unsigned char cmd[MAX_COMMAND_SIZE];
const char *b_point;
Scsi_Request *SRpnt = NULL;
Scsi_Tape *STp;
ST_mode *STm;
ST_partstat *STps;
+ ST_buffer *STbp;
int dev = TAPE_NR(inode->i_rdev);
read_lock(&st_dev_arr_lock);
@@ -1286,12 +1286,13 @@ static ssize_t
}
}
- if ((STp->buffer)->writing) {
+ STbp = STp->buffer;
+ if (STbp->writing) {
write_behind_check(STp);
- if ((STp->buffer)->syscall_result) {
+ if (STbp->syscall_result) {
DEBC(printk(ST_DEB_MSG "st%d: Async write error (write) %x.\n",
- dev, (STp->buffer)->midlevel_result));
- if ((STp->buffer)->midlevel_result == INT_MAX)
+ dev, STbp->midlevel_result));
+ if (STbp->midlevel_result == INT_MAX)
STps->eof = ST_EOM_OK;
else
STps->eof = ST_EOM_ERROR;
@@ -1299,6 +1300,7 @@ static ssize_t
}
if (STps->eof == ST_EOM_OK) {
+ STps->eof = ST_EOD_1; /* allow next write */
retval = (-ENOSPC);
goto out;
}
@@ -1316,19 +1318,6 @@ static ssize_t
goto out;
}
- if (!STm->do_buffer_writes) {
-#if 0
- if (STp->block_size != 0 && (count % STp->block_size) != 0) {
- retval = (-EINVAL); /* Write must be integral number of blocks */
- goto out;
- }
-#endif
- write_threshold = 1;
- } else
- write_threshold = (STp->buffer)->buffer_blocks * STp->block_size;
- if (!STm->do_async_writes)
- write_threshold--;
-
total = count;
memset(cmd, 0, MAX_COMMAND_SIZE);
@@ -1338,29 +1327,44 @@ static ssize_t
STps->rw = ST_WRITING;
b_point = buf;
- while ((STp->block_size == 0 && !STm->do_async_writes && count > 0) ||
- (STp->block_size != 0 &&
- (STp->buffer)->buffer_bytes + count > write_threshold)) {
- doing_write = 1;
+ while (count > 0) {
+
if (STp->block_size == 0)
do_count = count;
else {
- do_count = (STp->buffer)->buffer_blocks * STp->block_size -
- (STp->buffer)->buffer_bytes;
+ do_count = STbp->buffer_blocks * STp->block_size -
+ STbp->buffer_bytes;
if (do_count > count)
do_count = count;
}
- i = append_to_buffer(b_point, STp->buffer, do_count);
+ i = append_to_buffer(b_point, STbp, do_count);
if (i) {
retval = i;
goto out;
}
+ count -= do_count;
+ filp->f_pos += do_count;
+ b_point += do_count;
+
+ async_write = STm->do_async_writes && STps->eof < ST_EOM_OK;
+ if (STp->block_size != 0)
+ async_write &= count == 0 &&
+ (!STm->do_buffer_writes ||
+ STbp->buffer_bytes >= STp->write_threshold);
+
+ if (STp->block_size != 0 && STm->do_buffer_writes && STps->eof < ST_EOM_OK &&
+ STbp->buffer_bytes < STbp->buffer_size) {
+ STp->dirty = TRUE;
+ /* Don't write a buffer that is not full enough. */
+ if (!async_write && count == 0)
+ break;
+ }
if (STp->block_size == 0)
blks = transfer = do_count;
else {
- blks = (STp->buffer)->buffer_bytes /
+ blks = STbp->buffer_bytes /
STp->block_size;
transfer = blks * STp->block_size;
}
@@ -1369,47 +1373,59 @@ static ssize_t
cmd[4] = blks;
SRpnt = st_do_scsi(SRpnt, STp, cmd, transfer, SCSI_DATA_WRITE,
- STp->timeout, MAX_WRITE_RETRIES, TRUE);
+ STp->timeout, MAX_WRITE_RETRIES, !async_write);
if (!SRpnt) {
- retval = (STp->buffer)->syscall_result;
+ retval = STbp->syscall_result;
goto out;
}
+ if (async_write) {
+ STbp->writing = transfer;
+ STp->dirty = !(STbp->writing ==
+ STbp->buffer_bytes);
+ SRpnt = NULL; /* Prevent releasing this request! */
+ DEB( STp->write_pending = 1; )
+ break;
+ }
- if ((STp->buffer)->syscall_result != 0) {
+ if (STbp->syscall_result != 0) {
DEBC(printk(ST_DEB_MSG "st%d: Error on write:\n", dev));
if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70 &&
(SRpnt->sr_sense_buffer[2] & 0x40)) {
if ((SRpnt->sr_sense_buffer[0] & 0x80) != 0)
- transfer = (SRpnt->sr_sense_buffer[3] << 24) |
+ undone = (SRpnt->sr_sense_buffer[3] << 24) |
(SRpnt->sr_sense_buffer[4] << 16) |
(SRpnt->sr_sense_buffer[5] << 8) |
SRpnt->sr_sense_buffer[6];
else if (STp->block_size == 0 &&
(SRpnt->sr_sense_buffer[2] & 0x0f) ==
VOLUME_OVERFLOW)
- transfer = do_count;
+ undone = do_count;
else
- transfer = 0;
+ undone = 0;
if (STp->block_size != 0)
- transfer *= STp->block_size;
- if (transfer <= do_count) {
- filp->f_pos += do_count - transfer;
- count -= do_count - transfer;
- if (STps->drv_block >= 0) {
- if (STp->block_size == 0 &&
- transfer < do_count)
- STps->drv_block++;
- else if (STp->block_size != 0)
- STps->drv_block +=
- (do_count - transfer) /
- STp->block_size;
- }
+ undone *= STp->block_size;
+ filp->f_pos -= undone;
+ if (undone <= do_count) {
+ /* Only data from this write is not written */
+ count -= undone;
+ do_count -= undone;
+ if (STp->block_size)
+ blks = (transfer - undone) / STp->block_size;
STps->eof = ST_EOM_OK;
- retval = (-ENOSPC); /* EOM within current request */
+ /* Continue in fixed block mode if all written
+ in this request but still something left to write
+ (retval left to zero)
+ */
+ if (STp->block_size == 0 ||
+ undone > 0 || count == 0)
+ retval = (-ENOSPC); /* EOM within current request */
DEBC(printk(ST_DEB_MSG
"st%d: EOM with %d bytes unwritten.\n",
dev, transfer));
} else {
+ /* Previously buffered data not written */
+ count -= do_count;
+ blks = do_count = 0;
STps->eof = ST_EOM_ERROR;
STps->drv_block = (-1); /* Too cautious? */
retval = (-EIO); /* EOM for old data */
@@ -1418,80 +1434,33 @@ static ssize_t
dev));
}
} else {
+ filp->f_pos -= do_count;
STps->drv_block = (-1); /* Too cautious? */
retval = (-EIO);
}
- scsi_release_request(SRpnt);
- SRpnt = NULL;
- (STp->buffer)->buffer_bytes = 0;
- STp->dirty = 0;
- if (count < total)
- retval = total - count;
- goto out;
}
- filp->f_pos += do_count;
- b_point += do_count;
- count -= do_count;
+
if (STps->drv_block >= 0) {
if (STp->block_size == 0)
- STps->drv_block++;
+ STps->drv_block += (do_count > 0);
else
STps->drv_block += blks;
}
- (STp->buffer)->buffer_bytes = 0;
- STp->dirty = 0;
- }
- if (count != 0) {
- STp->dirty = 1;
- i = append_to_buffer(b_point, STp->buffer, count);
- if (i) {
- retval = i;
- goto out;
- }
- filp->f_pos += count;
- count = 0;
- }
- if (doing_write && (STp->buffer)->syscall_result != 0) {
- retval = (STp->buffer)->syscall_result;
- goto out;
- }
-
- if (STm->do_async_writes &&
- (((STp->buffer)->buffer_bytes >= STp->write_threshold &&
- (STp->buffer)->buffer_bytes >= STp->block_size) ||
- STp->block_size == 0)) {
- /* Schedule an asynchronous write */
- if (STp->block_size == 0)
- (STp->buffer)->writing = (STp->buffer)->buffer_bytes;
- else
- (STp->buffer)->writing = ((STp->buffer)->buffer_bytes /
- STp->block_size) * STp->block_size;
- STp->dirty = !((STp->buffer)->writing ==
- (STp->buffer)->buffer_bytes);
-
- if (STp->block_size == 0)
- blks = (STp->buffer)->writing;
- else
- blks = (STp->buffer)->writing / STp->block_size;
- cmd[2] = blks >> 16;
- cmd[3] = blks >> 8;
- cmd[4] = blks;
- DEB( STp->write_pending = 1; )
+ STbp->buffer_bytes = 0;
+ STp->dirty = 0;
- SRpnt = st_do_scsi(SRpnt, STp, cmd, (STp->buffer)->writing,
- SCSI_DATA_WRITE, STp->timeout,
- MAX_WRITE_RETRIES, FALSE);
- if (SRpnt == NULL) {
- retval = (STp->buffer)->syscall_result;
+ if (retval) {
+ if (count < total)
+ retval = total - count;
goto out;
}
- SRpnt = NULL; /* Prevent releasing this request! */
-
}
- STps->at_sm &= (total == 0);
- if (total > 0)
+
+ if (STps->eof == ST_EOD_1)
+ STps->eof = ST_EOM_OK;
+ else
STps->eof = ST_NOEOF;
retval = total;
@@ -2425,7 +2394,7 @@ static int st_int_ioctl(Scsi_Tape *STp, unsigned int cmd_in, unsigned long arg)
if (STp->write_prot)
return (-EACCES);
cmd[0] = ERASE;
- cmd[1] = 1; /* To the end of tape */
+ cmd[1] = (arg ? 1 : 0); /* Long erase with non-zero argument */
if (STp->immediate) {
cmd[1] |= 2; /* Don't wait for completion */
timeout = STp->timeout;
@@ -3296,7 +3265,7 @@ static int st_ioctl(struct inode *inode, struct file *file,
/* Try to allocate a new tape buffer. Calling function must not hold
dev_arr_lock. */
static ST_buffer *
- new_tape_buffer(int from_initialization, int need_dma)
+ new_tape_buffer(int from_initialization, int need_dma, int max_sg)
{
int i, priority, got = 0, segs = 0;
ST_buffer *tb;
@@ -3306,26 +3275,29 @@ static ST_buffer *
else
priority = GFP_KERNEL;
- i = sizeof(ST_buffer) + (st_max_sg_segs - 1) * sizeof(struct scatterlist);
+ i = sizeof(ST_buffer) + (max_sg - 1) * sizeof(struct scatterlist) +
+ max_sg * sizeof(struct st_buf_fragment);
tb = kmalloc(i, priority);
if (!tb) {
printk(KERN_NOTICE "st: Can't allocate new tape buffer.\n");
return NULL;
}
- tb->sg_segs = tb->orig_sg_segs = segs;
+ memset(tb, 0, i);
+ tb->frp_segs = tb->orig_frp_segs = segs;
+ tb->use_sg = max_sg;
if (segs > 0)
tb->b_data = page_address(tb->sg[0].page);
+ tb->frp = (struct st_buf_fragment *)(&(tb->sg[0]) + max_sg);
tb->in_use = TRUE;
tb->dma = need_dma;
tb->buffer_size = got;
- tb->writing = 0;
return tb;
}
-/* Try to allocate a temporary enlarged tape buffer */
+/* Try to allocate enough space in the tape buffer */
static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma)
{
int segs, nbr, max_segs, b_size, priority, order, got;
@@ -3333,12 +3305,11 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma)
if (new_size <= STbuffer->buffer_size)
return TRUE;
- normalize_buffer(STbuffer);
+ if (STbuffer->buffer_size <= PAGE_SIZE)
+ normalize_buffer(STbuffer); /* Avoid extra segment */
max_segs = STbuffer->use_sg;
- if (max_segs > st_max_sg_segs)
- max_segs = st_max_sg_segs;
- nbr = max_segs - STbuffer->sg_segs;
+ nbr = max_segs - STbuffer->frp_segs;
if (nbr <= 0)
return FALSE;
@@ -3350,12 +3321,10 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma)
order++, b_size *= 2)
; /* empty */
- for (segs = STbuffer->sg_segs, got = STbuffer->buffer_size;
+ for (segs = STbuffer->frp_segs, got = STbuffer->buffer_size;
segs < max_segs && got < new_size;) {
- STbuffer->sg[segs].page = alloc_pages(priority, order);
- /* printk("st: allocated %x, order %d\n", STbuffer->sg[segs].page, order); */
- STbuffer->sg[segs].offset = 0;
- if (STbuffer->sg[segs].page == NULL) {
+ STbuffer->frp[segs].page = alloc_pages(priority, order);
+ if (STbuffer->frp[segs].page == NULL) {
if (new_size - got <= (max_segs - segs) * b_size / 2) {
b_size /= 2; /* Large enough for the rest of the buffers */
order--;
@@ -3367,16 +3336,16 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma)
normalize_buffer(STbuffer);
return FALSE;
}
- STbuffer->sg[segs].length = b_size;
- STbuffer->sg_segs += 1;
+ STbuffer->frp[segs].length = b_size;
+ STbuffer->frp_segs += 1;
got += b_size;
STbuffer->buffer_size = got;
segs++;
}
- STbuffer->b_data = page_address(STbuffer->sg[0].page);
+ STbuffer->b_data = page_address(STbuffer->frp[0].page);
DEBC(printk(ST_DEB_MSG
"st: Succeeded to enlarge buffer at %p to %d bytes (segs %d->%d, %d).\n",
- STbuffer, got, STbuffer->orig_sg_segs, STbuffer->sg_segs, b_size));
+ STbuffer, got, STbuffer->orig_frp_segs, STbuffer->frp_segs, b_size));
return TRUE;
}
@@ -3385,22 +3354,20 @@ static int enlarge_buffer(ST_buffer * STbuffer, int new_size, int need_dma)
/* Release the extra buffer */
static void normalize_buffer(ST_buffer * STbuffer)
{
- int i, order, b_size;
+ int i, order;
- for (i = STbuffer->orig_sg_segs; i < STbuffer->sg_segs; i++) {
- for (b_size=PAGE_SIZE, order=0; b_size < STbuffer->sg[i].length;
- order++, b_size *= 2)
- ; /* empty */
- /* printk("st: freeing %x, order %d\n", STbuffer->sg[i].page, order); */
- __free_pages(STbuffer->sg[i].page, order);
- STbuffer->buffer_size -= STbuffer->sg[i].length;
+ for (i = STbuffer->orig_frp_segs; i < STbuffer->frp_segs; i++) {
+ order = get_order(STbuffer->frp[i].length);
+ __free_pages(STbuffer->frp[i].page, order);
+ STbuffer->buffer_size -= STbuffer->frp[i].length;
}
DEB(
- if (debugging && STbuffer->orig_sg_segs < STbuffer->sg_segs)
- printk(ST_DEB_MSG "st: Buffer at %p normalized to %d bytes (segs %d).\n",
- STbuffer, STbuffer->buffer_size, STbuffer->sg_segs);
+ if (debugging && STbuffer->orig_frp_segs < STbuffer->frp_segs)
+ printk(ST_DEB_MSG "st: Buffer at %p normalized to %d bytes (segs %d->%d).\n",
+ STbuffer, STbuffer->buffer_size, STbuffer->frp_segs, STbuffer->orig_frp_segs);
) /* end DEB */
- STbuffer->sg_segs = STbuffer->orig_sg_segs;
+ STbuffer->frp_segs = STbuffer->orig_frp_segs;
+ STbuffer->frp_sg_current = 0;
}
@@ -3411,16 +3378,16 @@ static int append_to_buffer(const char *ubp, ST_buffer * st_bp, int do_count)
int i, cnt, res, offset;
for (i = 0, offset = st_bp->buffer_bytes;
- i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
- offset -= st_bp->sg[i].length;
- if (i == st_bp->sg_segs) { /* Should never happen */
+ i < st_bp->frp_segs && offset >= st_bp->frp[i].length; i++)
+ offset -= st_bp->frp[i].length;
+ if (i == st_bp->frp_segs) { /* Should never happen */
printk(KERN_WARNING "st: append_to_buffer offset overflow.\n");
return (-EIO);
}
- for (; i < st_bp->sg_segs && do_count > 0; i++) {
- cnt = st_bp->sg[i].length - offset < do_count ?
- st_bp->sg[i].length - offset : do_count;
- res = copy_from_user(page_address(st_bp->sg[i].page) + offset, ubp, cnt);
+ for (; i < st_bp->frp_segs && do_count > 0; i++) {
+ cnt = st_bp->frp[i].length - offset < do_count ?
+ st_bp->frp[i].length - offset : do_count;
+ res = copy_from_user(page_address(st_bp->frp[i].page) + offset, ubp, cnt);
if (res)
return (-EFAULT);
do_count -= cnt;
@@ -3444,16 +3411,16 @@ static int from_buffer(ST_buffer * st_bp, char *ubp, int do_count)
int i, cnt, res, offset;
for (i = 0, offset = st_bp->read_pointer;
- i < st_bp->sg_segs && offset >= st_bp->sg[i].length; i++)
- offset -= st_bp->sg[i].length;
- if (i == st_bp->sg_segs) { /* Should never happen */
+ i < st_bp->frp_segs && offset >= st_bp->frp[i].length; i++)
+ offset -= st_bp->frp[i].length;
+ if (i == st_bp->frp_segs) { /* Should never happen */
printk(KERN_WARNING "st: from_buffer offset overflow.\n");
return (-EIO);
}
- for (; i < st_bp->sg_segs && do_count > 0; i++) {
- cnt = st_bp->sg[i].length - offset < do_count ?
- st_bp->sg[i].length - offset : do_count;
- res = copy_to_user(ubp, page_address(st_bp->sg[i].page) + offset, cnt);
+ for (; i < st_bp->frp_segs && do_count > 0; i++) {
+ cnt = st_bp->frp[i].length - offset < do_count ?
+ st_bp->frp[i].length - offset : do_count;
+ res = copy_to_user(ubp, page_address(st_bp->frp[i].page) + offset, cnt);
if (res)
return (-EFAULT);
do_count -= cnt;
@@ -3471,6 +3438,33 @@ static int from_buffer(ST_buffer * st_bp, char *ubp, int do_count)
}
+/* Fill the s/g list up to the length required for this transfer */
+static void buf_to_sg(ST_buffer *STbp, unsigned int length)
+{
+ int i;
+ unsigned int count;
+ struct scatterlist *sg;
+ struct st_buf_fragment *frp;
+
+ if (length == STbp->frp_sg_current)
+ return; /* work already done */
+
+ sg = &(STbp->sg[0]);
+ frp = STbp->frp;
+ for (i=count=0; count < length; i++) {
+ sg[i].page = frp[i].page;
+ if (length - count > frp[i].length)
+ sg[i].length = frp[i].length;
+ else
+ sg[i].length = length - count;
+ count += sg[i].length;
+ sg[i].offset = 0;
+ }
+ STbp->sg_segs = i;
+ STbp->frp_sg_current = length;
+}
+
+
/* Validate the options from command line or module parameters */
static void validate_options(void)
{
@@ -3587,7 +3581,10 @@ static int st_attach(Scsi_Device * SDp)
return 1;
}
- buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma);
+ i = SDp->host->sg_tablesize;
+ if (st_max_sg_segs < i)
+ i = st_max_sg_segs;
+ buffer = new_tape_buffer(TRUE, (SDp->host)->unchecked_isa_dma, i);
if (buffer == NULL) {
printk(KERN_ERR "st: Can't allocate new tape buffer. Device not attached.\n");
return 1;
@@ -3702,7 +3699,6 @@ static int st_attach(Scsi_Device * SDp)
else
tpnt->tape_type = MT_ISSCSI2;
- buffer->use_sg = tpnt->device->host->sg_tablesize;
tpnt->buffer = buffer;
tpnt->inited = 0;
@@ -3714,7 +3710,7 @@ static int st_attach(Scsi_Device * SDp)
tpnt->use_pf = (SDp->scsi_level >= SCSI_2);
tpnt->density = 0;
tpnt->do_auto_lock = ST_AUTO_LOCK;
- tpnt->can_bsr = ST_IN_FILE_POS;
+ tpnt->can_bsr = (SDp->scsi_level > 2 ? 1 : ST_IN_FILE_POS); /* BSR mandatory in SCSI3 */
tpnt->can_partitions = 0;
tpnt->two_fm = ST_TWO_FM;
tpnt->fast_mteom = ST_FAST_MTEOM;
@@ -3802,7 +3798,7 @@ static void st_detach(Scsi_Device * SDp)
put_device(&tpnt->driverfs_dev_n[mode]);
}
if (tpnt->buffer) {
- tpnt->buffer->orig_sg_segs = 0;
+ tpnt->buffer->orig_frp_segs = 0;
normalize_buffer(tpnt->buffer);
kfree(tpnt->buffer);
}
diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h
index b5fcd14b9cfb..5ad510146b80 100644
--- a/drivers/scsi/st.h
+++ b/drivers/scsi/st.h
@@ -21,12 +21,20 @@ typedef struct {
int syscall_result;
Scsi_Request *last_SRpnt;
unsigned char *b_data;
- unsigned short use_sg; /* zero or number of segments for this adapter */
- unsigned short sg_segs; /* total number of allocated segments */
- unsigned short orig_sg_segs; /* number of segments allocated at first try */
+ unsigned short use_sg; /* zero or maximum number of s/g segments for this adapter */
+ unsigned short sg_segs; /* number of segments in s/g list */
+ unsigned short orig_frp_segs; /* number of segments allocated at first try */
+ unsigned short frp_segs; /* number of buffer segments */
+ unsigned int frp_sg_current; /* driver buffer length currently in s/g list */
+ struct st_buf_fragment *frp; /* the allocated buffer fragment list */
struct scatterlist sg[1]; /* MUST BE last item */
} ST_buffer;
+/* The tape buffer fragment descriptor */
+struct st_buf_fragment {
+ struct page *page;
+ unsigned int length;
+};
/* The tape mode definition */
typedef struct {
@@ -147,6 +155,9 @@ typedef struct {
#define ST_EOD 7
/* EOD hit while reading => ST_EOD_1 => return zero => ST_EOD_2 =>
return zero => ST_EOD, return ENOSPC */
+/* When writing: ST_EOM_OK == early warning found, write OK
+ ST_EOD_1 == allow trying new write after early warning
+ ST_EOM_ERROR == early warning found, not able to write all */
/* Values of rw */
#define ST_IDLE 0
diff --git a/include/asm-arm/tlb.h b/include/asm-arm/tlb.h
index a70a0be8c8df..a7c2473b92f5 100644
--- a/include/asm-arm/tlb.h
+++ b/include/asm-arm/tlb.h
@@ -11,7 +11,7 @@
#define tlb_end_vma(tlb,vma) \
flush_tlb_range(vma, vma->vm_start, vma->vm_end)
-#define tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
+#define tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
#include <asm-generic/tlb.h>
diff --git a/include/asm-i386/tlb.h b/include/asm-i386/tlb.h
index 844c3d4c9aaa..0cd54638cc97 100644
--- a/include/asm-i386/tlb.h
+++ b/include/asm-i386/tlb.h
@@ -7,7 +7,7 @@
*/
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
-#define tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
+#define tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
/*
* .. because we flush the whole mm when it
diff --git a/include/asm-ia64/tlb.h b/include/asm-ia64/tlb.h
index 3b85d222f5a2..d9d97ef65969 100644
--- a/include/asm-ia64/tlb.h
+++ b/include/asm-ia64/tlb.h
@@ -1,7 +1,7 @@
/* XXX fix me! */
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
-#define tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
+#define tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
#include <asm-generic/tlb.h>
diff --git a/include/asm-m68k/tlb.h b/include/asm-m68k/tlb.h
index 51cfcd3c4855..c90d49d13b74 100644
--- a/include/asm-m68k/tlb.h
+++ b/include/asm-m68k/tlb.h
@@ -7,7 +7,7 @@
*/
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
-#define tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
+#define tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
/*
* .. because we flush the whole mm when it
diff --git a/include/asm-s390/tlb.h b/include/asm-s390/tlb.h
index 7ac1229d2cae..91d6dd2fcf1c 100644
--- a/include/asm-s390/tlb.h
+++ b/include/asm-s390/tlb.h
@@ -7,7 +7,7 @@
*/
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
-#define tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
+#define tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
/*
* .. because we flush the whole mm when it
diff --git a/include/asm-s390x/tlb.h b/include/asm-s390x/tlb.h
index e5ed8cf3ac60..84dfa35034ae 100644
--- a/include/asm-s390x/tlb.h
+++ b/include/asm-s390x/tlb.h
@@ -7,7 +7,7 @@
*/
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
-#define tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
+#define tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
/*
* .. because we flush the whole mm when it
diff --git a/include/asm-sparc64/tlb.h b/include/asm-sparc64/tlb.h
index cffe5312e94a..2a7db43c6fd7 100644
--- a/include/asm-sparc64/tlb.h
+++ b/include/asm-sparc64/tlb.h
@@ -16,7 +16,7 @@ do { if (!(tlb)->fullmm) \
flush_tlb_range(vma, vma->vm_start, vma->vm_end); \
} while (0)
-#define tlb_remove_tlb_entry(tlb, pte, address) \
+#define tlb_remove_tlb_entry(tlb, ptep, address) \
do { } while (0)
#include <asm-generic/tlb.h>
diff --git a/include/asm-x86_64/tlb.h b/include/asm-x86_64/tlb.h
index f76b9061ff8c..9a549844a7ff 100644
--- a/include/asm-x86_64/tlb.h
+++ b/include/asm-x86_64/tlb.h
@@ -4,7 +4,7 @@
#define tlb_start_vma(tlb, vma) do { } while (0)
#define tlb_end_vma(tlb, vma) do { } while (0)
-#define tlb_remove_tlb_entry(tlb, pte, address) do { } while (0)
+#define tlb_remove_tlb_entry(tlb, ptep, address) do { } while (0)
#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
diff --git a/include/linux/trdevice.h b/include/linux/trdevice.h
index f91119ab066d..4df6addff7c8 100644
--- a/include/linux/trdevice.h
+++ b/include/linux/trdevice.h
@@ -33,6 +33,7 @@ extern int tr_header(struct sk_buff *skb, struct net_device *dev,
void *saddr, unsigned len);
extern int tr_rebuild_header(struct sk_buff *skb);
extern unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev);
+extern void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh, struct net_device *dev);
extern struct net_device *init_trdev(struct net_device *dev, int sizeof_priv);
extern struct net_device *alloc_trdev(int sizeof_priv);
extern int register_trdev(struct net_device *dev);
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index af3ec94cb2ad..7b1ae2718f3e 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -8,6 +8,8 @@
#ifndef WRITEBACK_H
#define WRITEBACK_H
+struct backing_dev_info;
+
extern spinlock_t inode_lock;
extern struct list_head inode_in_use;
extern struct list_head inode_unused;
@@ -38,6 +40,9 @@ void wake_up_inode(struct inode *inode);
void __wait_on_inode(struct inode * inode);
void sync_inodes_sb(struct super_block *, int wait);
void sync_inodes(int wait);
+void writeback_backing_dev(struct backing_dev_info *bdi, int *nr_to_write,
+ enum writeback_sync_modes sync_mode,
+ unsigned long *older_than_this);
/* writeback.h requires fs.h; it, too, is not included from here. */
static inline void wait_on_inode(struct inode *inode)
diff --git a/mm/memory.c b/mm/memory.c
index 2937caaa907d..ea9ec1c8d6ce 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -344,7 +344,7 @@ static void zap_pte_range(mmu_gather_t *tlb, pmd_t * pmd, unsigned long address,
unsigned long pfn = pte_pfn(pte);
pte = ptep_get_and_clear(ptep);
- tlb_remove_tlb_entry(tlb, pte, address+offset);
+ tlb_remove_tlb_entry(tlb, ptep, address+offset);
if (pfn_valid(pfn)) {
struct page *page = pfn_to_page(pfn);
if (!PageReserved(page)) {
diff --git a/mm/rmap.c b/mm/rmap.c
index 98dd16cae14a..64a5123cde16 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -163,7 +163,7 @@ void page_add_rmap(struct page * page, pte_t * ptep)
void page_remove_rmap(struct page * page, pte_t * ptep)
{
struct pte_chain * pc, * prev_pc = NULL;
- unsigned long pfn = pte_pfn(*ptep);
+ unsigned long pfn = page_to_pfn(page);
if (!page || !ptep)
BUG();
diff --git a/net/802/tr.c b/net/802/tr.c
index 6249e319efab..31cfc898bee3 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -36,7 +36,6 @@
#include <linux/init.h>
#include <net/arp.h>
-static void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh, struct net_device *dev);
static void tr_add_rif_info(struct trh_hdr *trh, struct net_device *dev);
static void rif_check_expire(unsigned long dummy);
@@ -230,7 +229,7 @@ unsigned short tr_type_trans(struct sk_buff *skb, struct net_device *dev)
* We try to do source routing...
*/
-static void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_device *dev)
+void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_device *dev)
{
int i, slack;
unsigned int hash;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 40f0e0f6df32..559cbd03e9cc 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -966,10 +966,10 @@ xprt_write_space(struct sock *sk)
return;
if (!xprt_test_and_set_wspace(xprt)) {
- spin_lock(&xprt->sock_lock);
+ spin_lock_bh(&xprt->sock_lock);
if (xprt->snd_task && xprt->snd_task->tk_rpcwait == &xprt->pending)
rpc_wake_up_task(xprt->snd_task);
- spin_unlock(&xprt->sock_lock);
+ spin_unlock_bh(&xprt->sock_lock);
}
if (test_bit(SOCK_NOSPACE, &sock->flags)) {