aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/node.c2
-rw-r--r--drivers/cdrom/gscd.c2
-rw-r--r--drivers/char/moxa.c8
-rw-r--r--drivers/char/tty_io.c808
-rw-r--r--drivers/char/tty_ioctl.c59
-rw-r--r--drivers/char/vt_ioctl.c2
-rw-r--r--drivers/ieee1394/ohci1394.c4
-rw-r--r--drivers/md/dm-raid1.c4
-rw-r--r--drivers/md/md.c13
-rw-r--r--drivers/md/raid1.c7
-rw-r--r--drivers/mtd/nand/ams-delta.c10
-rw-r--r--drivers/mtd/nand/nand_base.c6
-rw-r--r--drivers/rtc/rtc-s3c.c124
-rw-r--r--drivers/scsi/ide-scsi.c2
-rw-r--r--drivers/video/imacfb.c4
-rw-r--r--drivers/video/matrox/g450_pll.c8
16 files changed, 916 insertions, 147 deletions
diff --git a/drivers/base/node.c b/drivers/base/node.c
index d7de1753e09..e9b0957f15d 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -64,7 +64,7 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf)
"Node %d Mapped: %8lu kB\n"
"Node %d AnonPages: %8lu kB\n"
"Node %d PageTables: %8lu kB\n"
- "Node %d NFS Unstable: %8lu kB\n"
+ "Node %d NFS_Unstable: %8lu kB\n"
"Node %d Bounce: %8lu kB\n"
"Node %d Slab: %8lu kB\n",
nid, K(i.totalram),
diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c
index b6ee50a2916..fa708248976 100644
--- a/drivers/cdrom/gscd.c
+++ b/drivers/cdrom/gscd.c
@@ -266,7 +266,7 @@ repeat:
goto out;
if (req->cmd != READ) {
- printk("GSCD: bad cmd %lu\n", rq_data_dir(req));
+ printk("GSCD: bad cmd %u\n", rq_data_dir(req));
end_request(req, 0);
goto repeat;
}
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 4ea7bd5f4f5..a369dd6877d 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -142,6 +142,7 @@ typedef struct _moxa_board_conf {
static moxa_board_conf moxa_boards[MAX_BOARDS];
static void __iomem *moxaBaseAddr[MAX_BOARDS];
+static int loadstat[MAX_BOARDS];
struct moxa_str {
int type;
@@ -1688,6 +1689,8 @@ int MoxaDriverPoll(void)
if (moxaCard == 0)
return (-1);
for (card = 0; card < MAX_BOARDS; card++) {
+ if (loadstat[card] == 0)
+ continue;
if ((ports = moxa_boards[card].numPorts) == 0)
continue;
if (readb(moxaIntPend[card]) == 0xff) {
@@ -2903,6 +2906,7 @@ static int moxaloadcode(int cardno, unsigned char __user *tmp, int len)
}
break;
}
+ loadstat[cardno] = 1;
return (0);
}
@@ -2920,7 +2924,7 @@ static int moxaloadc218(int cardno, void __iomem *baseAddr, int len)
len1 = len >> 1;
ptr = (ushort *) moxaBuff;
for (i = 0; i < len1; i++)
- usum += *(ptr + i);
+ usum += le16_to_cpu(*(ptr + i));
retry = 0;
do {
len1 = len >> 1;
@@ -2992,7 +2996,7 @@ static int moxaloadc320(int cardno, void __iomem *baseAddr, int len, int *numPor
wlen = len >> 1;
uptr = (ushort *) moxaBuff;
for (i = 0; i < wlen; i++)
- usum += uptr[i];
+ usum += le16_to_cpu(uptr[i]);
retry = 0;
j = 0;
do {
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index bfdb90242a9..bb0d9199e99 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -153,6 +153,15 @@ int tty_ioctl(struct inode * inode, struct file * file,
static int tty_fasync(int fd, struct file * filp, int on);
static void release_mem(struct tty_struct *tty, int idx);
+/**
+ * alloc_tty_struct - allocate a tty object
+ *
+ * Return a new empty tty structure. The data fields have not
+ * been initialized in any way but has been zeroed
+ *
+ * Locking: none
+ * FIXME: use kzalloc
+ */
static struct tty_struct *alloc_tty_struct(void)
{
@@ -166,6 +175,15 @@ static struct tty_struct *alloc_tty_struct(void)
static void tty_buffer_free_all(struct tty_struct *);
+/**
+ * free_tty_struct - free a disused tty
+ * @tty: tty struct to free
+ *
+ * Free the write buffers, tty queue and tty memory itself.
+ *
+ * Locking: none. Must be called after tty is definitely unused
+ */
+
static inline void free_tty_struct(struct tty_struct *tty)
{
kfree(tty->write_buf);
@@ -175,6 +193,17 @@ static inline void free_tty_struct(struct tty_struct *tty)
#define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base)
+/**
+ * tty_name - return tty naming
+ * @tty: tty structure
+ * @buf: buffer for output
+ *
+ * Convert a tty structure into a name. The name reflects the kernel
+ * naming policy and if udev is in use may not reflect user space
+ *
+ * Locking: none
+ */
+
char *tty_name(struct tty_struct *tty, char *buf)
{
if (!tty) /* Hmm. NULL pointer. That's fun. */
@@ -235,6 +264,28 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
* Tty buffer allocation management
*/
+
+/**
+ * tty_buffer_free_all - free buffers used by a tty
+ * @tty: tty to free from
+ *
+ * Remove all the buffers pending on a tty whether queued with data
+ * or in the free ring. Must be called when the tty is no longer in use
+ *
+ * Locking: none
+ */
+
+
+/**
+ * tty_buffer_free_all - free buffers used by a tty
+ * @tty: tty to free from
+ *
+ * Remove all the buffers pending on a tty whether queued with data
+ * or in the free ring. Must be called when the tty is no longer in use
+ *
+ * Locking: none
+ */
+
static void tty_buffer_free_all(struct tty_struct *tty)
{
struct tty_buffer *thead;
@@ -247,19 +298,47 @@ static void tty_buffer_free_all(struct tty_struct *tty)
kfree(thead);
}
tty->buf.tail = NULL;
+ tty->buf.memory_used = 0;
}
+/**
+ * tty_buffer_init - prepare a tty buffer structure
+ * @tty: tty to initialise
+ *
+ * Set up the initial state of the buffer management for a tty device.
+ * Must be called before the other tty buffer functions are used.
+ *
+ * Locking: none
+ */
+
static void tty_buffer_init(struct tty_struct *tty)
{
spin_lock_init(&tty->buf.lock);
tty->buf.head = NULL;
tty->buf.tail = NULL;
tty->buf.free = NULL;
+ tty->buf.memory_used = 0;
}
-static struct tty_buffer *tty_buffer_alloc(size_t size)
+/**
+ * tty_buffer_alloc - allocate a tty buffer
+ * @tty: tty device
+ * @size: desired size (characters)
+ *
+ * Allocate a new tty buffer to hold the desired number of characters.
+ * Return NULL if out of memory or the allocation would exceed the
+ * per device queue
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
+
+static struct tty_buffer *tty_buffer_alloc(struct tty_struct *tty, size_t size)
{
- struct tty_buffer *p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
+ struct tty_buffer *p;
+
+ if (tty->buf.memory_used + size > 65536)
+ return NULL;
+ p = kmalloc(sizeof(struct tty_buffer) + 2 * size, GFP_ATOMIC);
if(p == NULL)
return NULL;
p->used = 0;
@@ -269,17 +348,27 @@ static struct tty_buffer *tty_buffer_alloc(size_t size)
p->read = 0;
p->char_buf_ptr = (char *)(p->data);
p->flag_buf_ptr = (unsigned char *)p->char_buf_ptr + size;
-/* printk("Flip create %p\n", p); */
+ tty->buf.memory_used += size;
return p;
}
-/* Must be called with the tty_read lock held. This needs to acquire strategy
- code to decide if we should kfree or relink a given expired buffer */
+/**
+ * tty_buffer_free - free a tty buffer
+ * @tty: tty owning the buffer
+ * @b: the buffer to free
+ *
+ * Free a tty buffer, or add it to the free list according to our
+ * internal strategy
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
{
/* Dumb strategy for now - should keep some stats */
-/* printk("Flip dispose %p\n", b); */
+ tty->buf.memory_used -= b->size;
+ WARN_ON(tty->buf.memory_used < 0);
+
if(b->size >= 512)
kfree(b);
else {
@@ -288,6 +377,18 @@ static void tty_buffer_free(struct tty_struct *tty, struct tty_buffer *b)
}
}
+/**
+ * tty_buffer_find - find a free tty buffer
+ * @tty: tty owning the buffer
+ * @size: characters wanted
+ *
+ * Locate an existing suitable tty buffer or if we are lacking one then
+ * allocate a new one. We round our buffers off in 256 character chunks
+ * to get better allocation behaviour.
+ *
+ * Locking: Caller must hold tty->buf.lock
+ */
+
static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
{
struct tty_buffer **tbh = &tty->buf.free;
@@ -299,20 +400,28 @@ static struct tty_buffer *tty_buffer_find(struct tty_struct *tty, size_t size)
t->used = 0;
t->commit = 0;
t->read = 0;
- /* DEBUG ONLY */
-/* memset(t->data, '*', size); */
-/* printk("Flip recycle %p\n", t); */
+ tty->buf.memory_used += t->size;
return t;
}
tbh = &((*tbh)->next);
}
/* Round the buffer size out */
size = (size + 0xFF) & ~ 0xFF;
- return tty_buffer_alloc(size);
+ return tty_buffer_alloc(tty, size);
/* Should possibly check if this fails for the largest buffer we
have queued and recycle that ? */
}
+/**
+ * tty_buffer_request_room - grow tty buffer if needed
+ * @tty: tty structure
+ * @size: size desired
+ *
+ * Make at least size bytes of linear space available for the tty
+ * buffer. If we fail return the size we managed to find.
+ *
+ * Locking: Takes tty->buf.lock
+ */
int tty_buffer_request_room(struct tty_struct *tty, size_t size)
{
struct tty_buffer *b, *n;
@@ -347,6 +456,18 @@ int tty_buffer_request_room(struct tty_struct *tty, size_t size)
}
EXPORT_SYMBOL_GPL(tty_buffer_request_room);
+/**
+ * tty_insert_flip_string - Add characters to the tty buffer
+ * @tty: tty structure
+ * @chars: characters
+ * @size: size
+ *
+ * Queue a series of bytes to the tty buffering. All the characters
+ * passed are marked as without error. Returns the number added.
+ *
+ * Locking: Called functions may take tty->buf.lock
+ */
+
int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
size_t size)
{
@@ -370,6 +491,20 @@ int tty_insert_flip_string(struct tty_struct *tty, const unsigned char *chars,
}
EXPORT_SYMBOL(tty_insert_flip_string);
+/**
+ * tty_insert_flip_string_flags - Add characters to the tty buffer
+ * @tty: tty structure
+ * @chars: characters
+ * @flags: flag bytes
+ * @size: size
+ *
+ * Queue a series of bytes to the tty buffering. For each character
+ * the flags array indicates the status of the character. Returns the
+ * number added.
+ *
+ * Locking: Called functions may take tty->buf.lock
+ */
+
int tty_insert_flip_string_flags(struct tty_struct *tty,
const unsigned char *chars, const char *flags, size_t size)
{
@@ -394,6 +529,17 @@ int tty_insert_flip_string_flags(struct tty_struct *tty,
}
EXPORT_SYMBOL(tty_insert_flip_string_flags);
+/**
+ * tty_schedule_flip - push characters to ldisc
+ * @tty: tty to push from
+ *
+ * Takes any pending buffers and transfers their ownership to the
+ * ldisc side of the queue. It then schedules those characters for
+ * processing by the line discipline.
+ *
+ * Locking: Takes tty->buf.lock
+ */
+
void tty_schedule_flip(struct tty_struct *tty)
{
unsigned long flags;
@@ -405,12 +551,19 @@ void tty_schedule_flip(struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_schedule_flip);
-/*
+/**
+ * tty_prepare_flip_string - make room for characters
+ * @tty: tty
+ * @chars: return pointer for character write area
+ * @size: desired size
+ *
* Prepare a block of space in the buffer for data. Returns the length
* available and buffer pointer to the space which is now allocated and
* accounted for as ready for normal characters. This is used for drivers
* that need their own block copy routines into the buffer. There is no
* guarantee the buffer is a DMA target!
+ *
+ * Locking: May call functions taking tty->buf.lock
*/
int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_t size)
@@ -427,12 +580,20 @@ int tty_prepare_flip_string(struct tty_struct *tty, unsigned char **chars, size_
EXPORT_SYMBOL_GPL(tty_prepare_flip_string);
-/*
+/**
+ * tty_prepare_flip_string_flags - make room for characters
+ * @tty: tty
+ * @chars: return pointer for character write area
+ * @flags: return pointer for status flag write area
+ * @size: desired size
+ *
* Prepare a block of space in the buffer for data. Returns the length
* available and buffer pointer to the space which is now allocated and
* accounted for as ready for characters. This is used for drivers
* that need their own block copy routines into the buffer. There is no
* guarantee the buffer is a DMA target!
+ *
+ * Locking: May call functions taking tty->buf.lock
*/
int tty_prepare_flip_string_flags(struct tty_struct *tty, unsigned char **chars, char **flags, size_t size)
@@ -451,10 +612,16 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags);
-/*
+/**
+ * tty_set_termios_ldisc - set ldisc field
+ * @tty: tty structure
+ * @num: line discipline number
+ *
* This is probably overkill for real world processors but
* they are not on hot paths so a little discipline won't do
* any harm.
+ *
+ * Locking: takes termios_sem
*/
static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
@@ -474,6 +641,19 @@ static DEFINE_SPINLOCK(tty_ldisc_lock);
static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */
+/**
+ * tty_register_ldisc - install a line discipline
+ * @disc: ldisc number
+ * @new_ldisc: pointer to the ldisc object
+ *
+ * Installs a new line discipline into the kernel. The discipline
+ * is set up as unreferenced and then made available to the kernel
+ * from this point onwards.
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
{
unsigned long flags;
@@ -493,6 +673,18 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
}
EXPORT_SYMBOL(tty_register_ldisc);
+/**
+ * tty_unregister_ldisc - unload a line discipline
+ * @disc: ldisc number
+ * @new_ldisc: pointer to the ldisc object
+ *
+ * Remove a line discipline from the kernel providing it is not
+ * currently in use.
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
int tty_unregister_ldisc(int disc)
{
unsigned long flags;
@@ -512,6 +704,19 @@ int tty_unregister_ldisc(int disc)
}
EXPORT_SYMBOL(tty_unregister_ldisc);
+/**
+ * tty_ldisc_get - take a reference to an ldisc
+ * @disc: ldisc number
+ *
+ * Takes a reference to a line discipline. Deals with refcounts and
+ * module locking counts. Returns NULL if the discipline is not available.
+ * Returns a pointer to the discipline and bumps the ref count if it is
+ * available
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
struct tty_ldisc *tty_ldisc_get(int disc)
{
unsigned long flags;
@@ -540,6 +745,17 @@ struct tty_ldisc *tty_ldisc_get(int disc)
EXPORT_SYMBOL_GPL(tty_ldisc_get);
+/**
+ * tty_ldisc_put - drop ldisc reference
+ * @disc: ldisc number
+ *
+ * Drop a reference to a line discipline. Manage refcounts and
+ * module usage counts
+ *
+ * Locking:
+ * takes tty_ldisc_lock to guard against ldisc races
+ */
+
void tty_ldisc_put(int disc)
{
struct tty_ldisc *ld;
@@ -557,6 +773,19 @@ void tty_ldisc_put(int disc)
EXPORT_SYMBOL_GPL(tty_ldisc_put);
+/**
+ * tty_ldisc_assign - set ldisc on a tty
+ * @tty: tty to assign
+ * @ld: line discipline
+ *
+ * Install an instance of a line discipline into a tty structure. The
+ * ldisc must have a reference count above zero to ensure it remains/
+ * The tty instance refcount starts at zero.
+ *
+ * Locking:
+ * Caller must hold references
+ */
+
static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
{
tty->ldisc = *ld;
@@ -571,6 +800,8 @@ static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld)
* the tty ldisc. Return 0 on failure or 1 on success. This is
* used to implement both the waiting and non waiting versions
* of tty_ldisc_ref
+ *
+ * Locking: takes tty_ldisc_lock
*/
static int tty_ldisc_try(struct tty_struct *tty)
@@ -602,6 +833,8 @@ static int tty_ldisc_try(struct tty_struct *tty)
* must also be careful not to hold other locks that will deadlock
* against a discipline change, such as an existing ldisc reference
* (which we check for)
+ *
+ * Locking: call functions take tty_ldisc_lock
*/
struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty)
@@ -622,6 +855,8 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait);
* Dereference the line discipline for the terminal and take a
* reference to it. If the line discipline is in flux then
* return NULL. Can be called from IRQ and timer functions.
+ *
+ * Locking: called functions take tty_ldisc_lock
*/
struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty)
@@ -639,6 +874,8 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref);
*
* Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May
* be called in IRQ context.
+ *
+ * Locking: takes tty_ldisc_lock
*/
void tty_ldisc_deref(struct tty_ldisc *ld)
@@ -683,6 +920,9 @@ static void tty_ldisc_enable(struct tty_struct *tty)
*
* Set the discipline of a tty line. Must be called from a process
* context.
+ *
+ * Locking: takes tty_ldisc_lock.
+ * called functions take termios_sem
*/
static int tty_set_ldisc(struct tty_struct *tty, int ldisc)
@@ -846,9 +1086,17 @@ restart:
return retval;
}
-/*
- * This routine returns a tty driver structure, given a device number
+/**
+ * get_tty_driver - find device of a tty
+ * @dev_t: device identifier
+ * @index: returns the index of the tty
+ *
+ * This routine returns a tty driver structure, given a device number
+ * and also passes back the index number.
+ *
+ * Locking: caller must hold tty_mutex
*/
+
static struct tty_driver *get_tty_driver(dev_t device, int *index)
{
struct tty_driver *p;
@@ -863,11 +1111,17 @@ static struct tty_driver *get_tty_driver(dev_t device, int *index)
return NULL;
}
-/*
- * If we try to write to, or set the state of, a terminal and we're
- * not in the foreground, send a SIGTTOU. If the signal is blocked or
- * ignored, go ahead and perform the operation. (POSIX 7.2)
+/**
+ * tty_check_change - check for POSIX terminal changes
+ * @tty: tty to check
+ *
+ * If we try to write to, or set the state of, a terminal and we're
+ * not in the foreground, send a SIGTTOU. If the signal is blocked or
+ * ignored, go ahead and perform the operation. (POSIX 7.2)
+ *
+ * Locking: none
*/
+
int tty_check_change(struct tty_struct * tty)
{
if (current->signal->tty != tty)
@@ -1005,10 +1259,27 @@ void tty_ldisc_flush(struct tty_struct *tty)
EXPORT_SYMBOL_GPL(tty_ldisc_flush);
-/*
- * This can be called by the "eventd" kernel thread. That is process synchronous,
- * but doesn't hold any locks, so we need to make sure we have the appropriate
- * locks for what we're doing..
+/**
+ * do_tty_hangup - actual handler for hangup events
+ * @data: tty device
+ *
+ * This can be called by the "eventd" kernel thread. That is process
+ * synchronous but doesn't hold any locks, so we need to make sure we
+ * have the appropriate locks for what we're doing.
+ *
+ * The hangup event clears any pending redirections onto the hung up
+ * device. It ensures future writes will error and it does the needed
+ * line discipline hangup and signal delivery. The tty object itself
+ * remains intact.
+ *
+ * Locking:
+ * BKL
+ * redirect lock for undoing redirection
+ * file list lock for manipulating list of ttys
+ * tty_ldisc_lock from called functions
+ * termios_sem resetting termios data
+ * tasklist_lock to walk task list for hangup event
+ *
*/
static void do_tty_hangup(void *data)
{
@@ -1133,6 +1404,14 @@ static void do_tty_hangup(void *data)
fput(f);
}
+/**
+ * tty_hangup - trigger a hangup event
+ * @tty: tty to hangup
+ *
+ * A carrier loss (virtual or otherwise) has occurred on this like
+ * schedule a hangup sequence to run after this event.
+ */
+
void tty_hangup(struct tty_struct * tty)
{
#ifdef TTY_DEBUG_HANGUP
@@ -1145,6 +1424,15 @@ void tty_hangup(struct tty_struct * tty)
EXPORT_SYMBOL(tty_hangup);
+/**
+ * tty_vhangup - process vhangup
+ * @tty: tty to hangup
+ *
+ * The user has asked via system call for the terminal to be hung up.
+ * We do this synchronously so that when the syscall returns the process
+ * is complete. That guarantee is neccessary for security reasons.
+ */
+
void tty_vhangup(struct tty_struct * tty)
{
#ifdef TTY_DEBUG_HANGUP
@@ -1156,6 +1444,14 @@ void tty_vhangup(struct tty_struct * tty)
}
EXPORT_SYMBOL(tty_vhangup);
+/**
+ * tty_hung_up_p - was tty hung up
+ * @filp: file pointer of tty
+ *
+ * Return true if the tty has been subject to a vhangup or a carrier
+ * loss
+ */
+
int tty_hung_up_p(struct file * filp)
{
return (filp->f_op == &hung_up_tty_fops);
@@ -1163,19 +1459,28 @@ int tty_hung_up_p(struct file * filp)
EXPORT_SYMBOL(tty_hung_up_p);
-/*
- * This function is typically called only by the session leader, when
- * it wants to disassociate itself from its controlling tty.
+/**
+ * disassociate_ctty - disconnect controlling tty
+ * @on_exit: true if exiting so need to "hang up" the session
+ *
+ * This function is typically called only by the session leader, when
+ * it wants to disassociate itself from its controlling tty.
*
- * It performs the following functions:
+ * It performs the following functions:
* (1) Sends a SIGHUP and SIGCONT to the foreground process group
* (2) Clears the tty from being controlling the session
* (3) Clears the controlling tty for all processes in the
* session group.
*
- * The argument on_exit is set to 1 if called when a process is
- * exiting; it is 0 if called by the ioctl TIOCNOTTY.
+ * The argument on_exit is set to 1 if called when a process is
+ * exiting; it is 0 if called by the ioctl TIOCNOTTY.
+ *
+ * Locking: tty_mutex is taken to protect current->signal->tty
+ * BKL is taken for hysterical raisins
+ * Tasklist lock is taken (under tty_mutex) to walk process
+ * lists for the session.
*/
+
void disassociate_ctty(int on_exit)
{
struct tty_struct *tty;
@@ -1222,6 +1527,25 @@ void disassociate_ctty(int on_exit)
unlock_kernel();
}
+
+/**
+ * stop_tty - propogate flow control
+ * @tty: tty to stop
+ *
+ * Perform flow control to the driver. For PTY/TTY pairs we
+ * must also propogate the TIOCKPKT status. May be called
+ * on an already stopped device and will not re-call the driver
+ * method.
+ *
+ * This functionality is used by both the line disciplines for
+ * halting incoming flow and by the driver. It may therefore be
+ * called from any context, may be under the tty atomic_write_lock
+ * but not always.
+ *
+ * Locking:
+ * Broken. Relies on BKL which is unsafe here.
+ */
+
void stop_tty(struct tty_struct *tty)
{
if (tty->stopped)
@@ -1238,6 +1562,19 @@ void stop_tty(struct tty_struct *tty)
EXPORT_SYMBOL(stop_tty);
+/**
+ * start_tty - propogate flow control
+ * @tty: tty to start
+ *
+ * Start a tty that has been stopped if at all possible. Perform
+ * any neccessary wakeups and propogate the TIOCPKT status. If this
+ * is the tty was previous stopped and is being started then the
+ * driver start method is invoked and the line discipline woken.
+ *
+ * Locking:
+ * Broken. Relies on BKL which is unsafe here.
+ */
+
void start_tty(struct tty_struct *tty)
{
if (!tty->stopped || tty->flow_stopped)
@@ -1258,6 +1595,23 @@ void start_tty(struct tty_struct *tty)
EXPORT_SYMBOL(start_tty);
+/**
+ * tty_read - read method for tty device files
+ * @file: pointer to tty file
+ * @buf: user buffer
+ * @count: size of user buffer
+ * @ppos: unused
+ *
+ * Perform the read system call function on this terminal device. Checks
+ * for hung up devices before calling the line discipline method.
+ *
+ * Locking:
+ * Locks the line discipline internally while needed
+ * For historical reasons the line discipline read method is
+ * invoked under the BKL. This will go away in time so do not rely on it
+ * in new code. Multiple read calls may be outstanding in parallel.
+ */
+
static ssize_t tty_read(struct file * file, char __user * buf, size_t count,
loff_t *ppos)
{
@@ -1302,6 +1656,7 @@ static inline ssize_t do_tty_write(
ssize_t ret = 0, written = 0;
unsigned int chunk;
+ /* FIXME: O_NDELAY ... */
if (mutex_lock_interruptible(&tty->atomic_write_lock)) {
return -ERESTARTSYS;
}
@@ -1318,6 +1673,9 @@ static inline ssize_t do_tty_write(
* layer has problems with bigger chunks. It will
* claim to be able to handle more characters than
* it actually does.
+ *
+ * FIXME: This can probably go away now except that 64K chunks
+ * are too likely to fail unless switched to vmalloc...
*/
chunk = 2048;
if (test_bit(TTY_NO_WRITE_SPLIT, &tty->flags))
@@ -1375,6 +1733,24 @@ static inline ssize_t do_tty_write(
}
+/**
+ * tty_write - write method for tty device file
+ * @file: tty file pointer
+ * @buf: user data to write
+ * @count: bytes to write
+ * @ppos: unused
+ *
+ * Write data to a tty device via the line discipline.
+ *
+ * Locking:
+ * Locks the line discipline as required
+ * Writes to the tty driver are serialized by the atomic_write_lock
+ * and are then processed in chunks to the device. The line discipline
+ * write method will not be involked in parallel for each device
+ * The line discipline write method is called under the big
+ * kernel lock for historical reasons. New code should not rely on this.
+ */
+
static ssize_t tty_write(struct file * file, const char __user * buf, size_t count,
loff_t *ppos)
{
@@ -1422,7 +1798,18 @@ ssize_t redirected_tty_write(struct file * file, const char __user * buf, size_t
static char ptychar[] = "pqrstuvwxyzabcde";
-static inline void pty_line_name(struct tty_driver *driver, int index, char *p)
+/**
+ * pty_line_name - generate name for a pty
+ * @driver: the tty driver in use
+ * @index: the minor number
+ * @p: output buffer of at least 6 bytes
+ *
+ * Generate a name from a driver reference and write it to the output
+ * buffer.
+ *
+ * Locking: None
+ */
+static void pty_line_name(struct tty_driver *driver, int index, char *p)
{
int i = index + driver->name_base;
/* ->name is initialized to "ttyp", but "tty" is expected */
@@ -1431,24 +1818,53 @@ static inline void pty_line_name(struct tty_driver *driver, int index, char *p)
ptychar[i >> 4 & 0xf], i & 0xf);
}
-static inline void tty_line_name(struct tty_driver *driver, int index, char *p)
+/**
+ * pty_line_name - generate name for a tty
+ * @driver: the tty driver in use
+ * @index: the minor number
+ * @p: output buffer of at least 7 bytes
+ *
+ * Generate a name from a driver reference and write it to the output
+ * buffer.
+ *
+ * Locking: None
+ */
+static void tty_line_name(struct tty_driver *driver, int index, char *p)
{
sprintf(p, "%s%d", driver->name, index + driver->name_base);
}
-/*
+/**
+ * init_dev - initialise a tty device
+ * @driver: tty driver we are opening a device on
+ * @idx: device index
+ * @tty: returned tty structure
+ *
+ * Prepare a tty device. This may not be a "new" clean device but
+ * could also be an active device. The pty drivers require special
+ * handling because of this.
+ *
+ * Locking:
+ * The function is called under the tty_mutex, which
+ * protects us from the tty struct or driver itself going away.
+ *
+ * On exit the tty device has the line discipline attached and
+ * a reference count of 1. If a pair was created for pty/tty use
+ * and the other was a pty master then it too has a reference count of 1.
+ *
* WSH 06/09/97: Rewritten to remove races and properly clean up after a
* failed open. The new code protects the open with a mutex, so it's
* really quite straightforward. The mutex locking can probably be
* relaxed for the (most common) case of reopening a tty.
*/
+
static int init_dev(struct tty_driver *driver, int idx,
struct tty_struct **ret_tty)
{
struct tty_struct *tty, *o_tty;
struct termios *tp, **tp_loc, *o_tp, **o_tp_loc;
struct termios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc;
- int retval=0;
+ int retval = 0;
/* check whether we're reopening an existing tty */
if (driver->flags & TTY_DRIVER_DEVPTS_MEM) {
@@ -1662,10 +2078,20 @@ release_mem_out:
goto end_init;
}
-/*
- * Releases memory associated with a tty structure, and clears out the
- * driver table slots.
+/**
+ * release_mem - release tty structure memory
+ *
+ * Releases memory associated with a tty structure, and clears out the
+ * driver table slots. This function is called when a device is no longer
+ * in use. It also gets called when setup of a device fails.
+ *
+ * Locking:
+ * tty_mutex - sometimes only
+ * takes the file list lock internally when working on the list
+ * of ttys that the driver keeps.
+ * FIXME: should we require tty_mutex is held here ??
*/
+
static void release_mem(struct tty_struct *tty, int idx)
{
struct tty_struct *o_tty;
@@ -2006,18 +2432,27 @@ static void release_dev(struct file * filp)
}
-/*
- * tty_open and tty_release keep up the tty count that contains the
- * number of opens done on a tty. We cannot use the inode-count, as
- * different inodes might point to the same tty.
+/**
+ * tty_open - open a tty device
+ * @inode: inode of device file
+ * @filp: file pointer to tty
+ *
+ * tty_open and tty_release keep up the tty count that contains the
+ * number of opens done on a tty. We cannot use the inode-count, as
+ * different inodes might point to the same tty.
*
- * Open-counting is needed for pty masters, as well as for keeping
- * track of serial lines: DTR is dropped when the last close happens.
- * (This is not done solely through tty->count, now. - Ted 1/27/92)
+ * Open-counting is needed for pty masters, as well as for keeping
+ * track of serial lines: DTR is dropped when the last close happens.
+ * (This is not done solely through tty->count, now. - Ted 1/27/92)
*
- * The termios state of a pty is reset on first open so that
- * settings don't persist across reuse.
+ * The termios state of a pty is reset on first open so that
+ * settings don't persist across reuse.
+ *
+ * Locking: tty_mutex protects current->signal->tty, get_tty_driver and
+ * init_dev work. tty->count should protect the rest.
+ * task_lock is held to update task details for sessions
*/
+
static int tty_open(struct inode * inode, struct file * filp)
{
struct tty_struct *tty;
@@ -2132,6 +2567,18 @@ got_driver:
}
#ifdef CONFIG_UNIX98_PTYS
+/**
+ * ptmx_open - open a unix 98 pty master
+ * @inode: inode of device file
+ * @filp: file pointer to tty
+ *
+ * Allocate a unix98 pty master device from the ptmx driver.
+ *
+ * Locking: tty_mutex protects theinit_dev work. tty->count should
+ protect the rest.
+ * allocated_ptys_lock handles the list of free pty numbers
+ */
+
static int ptmx_open(struct inode * inode, struct file * filp)
{
struct tty_struct *tty;
@@ -2191,6 +2638,18 @@ out:
}
#endif
+/**
+ * tty_release - vfs callback for close
+ * @inode: inode of tty
+ * @filp: file pointer for handle to tty
+ *
+ * Called the last time each file handle is closed that references
+ * this tty. There may however be several such references.
+ *
+ * Locking:
+ * Takes bkl. See release_dev
+ */
+
static int tty_release(struct inode * inode, struct file * filp)
{
lock_kernel();
@@ -2199,7 +2658,18 @@ static int tty_release(struct inode * inode, struct file * filp)
return 0;
}
-/* No kernel lock held - fine */
+/**
+ * tty_poll - check tty status
+ * @filp: file being polled
+ * @wait: poll wait structures to update
+ *
+ * Call the line discipline polling method to obtain the poll
+ * status of the device.
+ *
+ * Locking: locks called line discipline but ldisc poll method
+ * may be re-entered freely by other callers.
+ */
+
static unsigned int tty_poll(struct file * filp, poll_table * wait)
{
struct tty_struct * tty;
@@ -2243,6 +2713,21 @@ static int tty_fasync(int fd, struct file * filp, int on)
return 0;
}
+/**
+ * tiocsti - fake input character
+ * @tty: tty to fake input into
+ * @p: pointer to character
+ *
+ * Fake input to a tty device. Does the neccessary locking and
+ * input management.
+ *
+ * FIXME: does not honour flow control ??
+ *
+ * Locking:
+ * Called functions take tty_ldisc_lock
+ * current->signal->tty check is safe without locks
+ */
+
static int tiocsti(struct tty_struct *tty, char __user *p)
{
char ch, mbz = 0;
@@ -2258,6 +2743,18 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
return 0;
}
+/**
+ * tiocgwinsz - implement window query ioctl
+ * @tty; tty
+ * @arg: user buffer for result
+ *
+ * Copies the kernel idea of the window size into the user buffer. No
+ * locking is done.
+ *
+ * FIXME: Returning random values racing a window size set is wrong
+ * should lock here against that
+ */
+
static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
{
if (copy_to_user(arg, &tty->winsize, sizeof(*arg)))
@@ -2265,6 +2762,24 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user * arg)
return 0;
}
+/**
+ * tiocswinsz - implement window size set ioctl
+ * @tty; tty
+ * @arg: user buffer for result
+ *
+ * Copies the user idea of the window size to the kernel. Traditionally
+ * this is just advisory information but for the Linux console it
+ * actually has driver level meaning and triggers a VC resize.
+ *
+ * Locking:
+ * The console_sem is used to ensure we do not try and resize
+ * the console twice at once.
+ * FIXME: Two racing size sets may leave the console and kernel
+ * parameters disagreeing. Is this exploitable ?
+ * FIXME: Random values racing a window size get is wrong
+ * should lock here against that
+ */
+
static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
struct winsize __user * arg)
{
@@ -2294,6 +2809,15 @@ static int tiocswinsz(struct tty_struct *tty, struct tty_struct *real_tty,
return 0;
}
+/**
+ * tioccons - allow admin to move logical console
+ * @file: the file to become console
+ *
+ * Allow the adminstrator to move the redirected console device
+ *
+ * Locking: uses redirect_lock to guard the redirect information
+ */
+
static int tioccons(struct file *file)
{
if (!capable(CAP_SYS_ADMIN))
@@ -2319,6 +2843,17 @@ static int tioccons(struct file *file)
return 0;
}
+/**
+ * fionbio - non blocking ioctl
+ * @file: file to set blocking value
+ * @p: user parameter
+ *
+ * Historical tty interfaces had a blocking control ioctl before
+ * the generic functionality existed. This piece of history is preserved
+ * in the expected tty API of posix OS's.
+ *
+ * Locking: none, the open fle handle ensures it won't go away.
+ */
static int fionbio(struct file *file, int __user *p)
{
@@ -2334,6 +2869,23 @@ static int fionbio(struct file *file, int __user *p)
return 0;
}
+/**
+ * tiocsctty - set controlling tty
+ * @tty: tty structure
+ * @arg: user argument
+ *
+ * This ioctl is used to manage job control. It permits a session
+ * leader to set this tty as the controlling tty for the session.
+ *
+ * Locking:
+ * Takes tasklist lock internally to walk sessions
+ * Takes task_lock() when updating signal->tty
+ *
+ * FIXME: tty_mutex is needed to protect signal->tty references.
+ * FIXME: why task_lock on the signal->tty reference ??
+ *
+ */
+
static int tiocsctty(struct tty_struct *tty, int arg)
{
struct task_struct *p;
@@ -2374,6 +2926,18 @@ static int tiocsctty(struct tty_struct *tty, int arg)
return 0;
}
+/**
+ * tiocgpgrp - get process group
+ * @tty: tty passed by user
+ * @real_tty: tty side of the tty pased by the user if a pty else the tty
+ * @p: returned pid
+ *
+ * Obtain the process group of the tty. If there is no process group
+ * return an error.
+ *
+ * Locking: none. Reference to ->signal->tty is safe.
+ */
+
static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
{
/*
@@ -2385,6 +2949,20 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
return put_user(real_tty->pgrp, p);
}
+/**
+ * tiocspgrp - attempt to set process group
+ * @tty: tty passed by user
+ * @real_tty: tty side device matching tty passed by user
+ * @p: pid pointer
+ *
+ * Set the process group of the tty to the session passed. Only
+ * permitted where the tty session is our session.
+ *
+ * Locking: None
+ *
+ * FIXME: current->signal->tty referencing is unsafe.
+ */
+
static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
{
pid_t pgrp;
@@ -2408,6 +2986,18 @@ static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
return 0;
}
+/**
+ * tiocgsid - get session id
+ * @tty: tty passed by user
+ * @real_tty: tty side of the tty pased by the user if a pty else the tty
+ * @p: pointer to returned session id
+ *
+ * Obtain the session id of the tty. If there is no session
+ * return an error.
+ *
+ * Locking: none. Reference to ->signal->tty is safe.
+ */
+
static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
{
/*
@@ -2421,6 +3011,16 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _
return put_user(real_tty->session, p);
}
+/**
+ * tiocsetd - set line discipline
+ * @tty: tty device
+ * @p: pointer to user data
+ *
+ * Set the line discipline according to user request.
+ *
+ * Locking: see tty_set_ldisc, this function is just a helper
+ */
+
static int tiocsetd(struct tty_struct *tty, int __user *p)
{
int ldisc;
@@ -2430,6 +3030,21 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
return tty_set_ldisc(tty, ldisc);
}
+/**
+ * send_break - performed time break
+ * @tty: device to break on
+ * @duration: timeout in mS
+ *
+ * Perform a timed break on hardware that lacks its own driver level
+ * timed break functionality.
+ *
+ * Locking:
+ * None
+ *
+ * FIXME:
+ * What if two overlap
+ */
+
static int send_break(struct tty_struct *tty, unsigned int duration)
{
tty->driver->break_ctl(tty, -1);
@@ -2442,8 +3057,19 @@ static int send_break(struct tty_struct *tty, unsigned int duration)
return 0;
}
-static int
-tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
+/**
+ * tiocmget - get modem status
+ * @tty: tty device
+ * @file: user file pointer
+ * @p: pointer to result
+ *
+ * Obtain the modem status bits from the tty driver if the feature
+ * is supported. Return -EINVAL if it is not available.
+ *
+ * Locking: none (up to the driver)
+ */
+
+static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
{
int retval = -EINVAL;
@@ -2456,8 +3082,20 @@ tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p)
return retval;
}
-static int
-tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd,
+/**
+ * tiocmset - set modem status
+ * @tty: tty device
+ * @file: user file pointer
+ * @cmd: command - clear bits, set bits or set all
+ * @p: pointer to desired bits
+ *
+ * Set the modem status bits from the tty driver if the feature
+ * is supported. Return -EINVAL if it is not available.
+ *
+ * Locking: none (up to the driver)
+ */
+
+static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int cmd,
unsigned __user *p)
{
int retval = -EINVAL;
@@ -2573,6 +3211,7 @@ int tty_ioctl(struct inode * inode, struct file * file,
clear_bit(TTY_EXCLUSIVE, &tty->flags);
return 0;
case TIOCNOTTY:
+ /* FIXME: taks lock or tty_mutex ? */
if (current->signal->tty != tty)
return -ENOTTY;
if (current->signal->leader)
@@ -2753,9 +3392,16 @@ void do_SAK(struct tty_struct *tty)
EXPORT_SYMBOL(do_SAK);
-/*
- * This routine is called out of the software interrupt to flush data
- * from the buffer chain to the line discipline.
+/**
+ * flush_to_ldisc
+ * @private_: tty structure passed from work queue.
+ *
+ * This routine is called out of the software interrupt to flush data
+ * from the buffer chain to the line discipline.
+ *
+ * Locking: holds tty->buf.lock to guard buffer list. Drops the lock
+ * while invoking the line discipline receive_buf method. The
+ * receive_buf method is single threaded for each tty instance.
*/
static void flush_to_ldisc(void *private_)
@@ -2831,6 +3477,8 @@ static int n_baud_table = ARRAY_SIZE(baud_table);
* Convert termios baud rate data into a speed. This should be called
* with the termios lock held if this termios is a terminal termios
* structure. May change the termios data.
+ *
+ * Locking: none
*/
int tty_termios_baud_rate(struct termios *termios)
@@ -2859,6 +3507,8 @@ EXPORT_SYMBOL(tty_termios_baud_rate);
* Returns the baud rate as an integer for this terminal. The
* termios lock must be held by the caller and the terminal bit
* flags may be updated.
+ *
+ * Locking: none
*/
int tty_get_baud_rate(struct tty_struct *tty)
@@ -2888,6 +3538,8 @@ EXPORT_SYMBOL(tty_get_baud_rate);
*
* In the event of the queue being busy for flipping the work will be
* held off and retried later.
+ *
+ * Locking: tty buffer lock. Driver locks in low latency mode.
*/
void tty_flip_buffer_push(struct tty_struct *tty)
@@ -2907,9 +3559,16 @@ void tty_flip_buffer_push(struct tty_struct *tty)
EXPORT_SYMBOL(tty_flip_buffer_push);
-/*
- * This subroutine initializes a tty structure.
+/**
+ * initialize_tty_struct
+ * @tty: tty to initialize
+ *
+ * This subroutine initializes a tty structure that has been newly
+ * allocated.
+ *
+ * Locking: none - tty in question must not be exposed at this point
*/
+
static void initialize_tty_struct(struct tty_struct *tty)
{
memset(tty, 0, sizeof(struct tty_struct));
@@ -2935,6 +3594,7 @@ static void initialize_tty_struct(struct tty_struct *tty)
/*
* The default put_char routine if the driver did not define one.
*/
+
static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
{
tty->driver->write(tty, &ch, 1);
@@ -2943,19 +3603,23 @@ static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
static struct class *tty_class;
/**
- * tty_register_device - register a tty device
- * @driver: the tty driver that describes the tty device
- * @index: the index in the tty driver for this tty device
- * @device: a struct device that is associated with this tty device.
- * This field is optional, if there is no known struct device for this
- * tty device it can be set to NULL safely.
+ * tty_register_device - register a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
+ * @device: a struct device that is associated with this tty device.
+ * This field is optional, if there is no known struct device
+ * for this tty device it can be set to NULL safely.
*
- * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error).
+ * Returns a pointer to the class device (or ERR_PTR(-EFOO) on error).
*
- * This call is required to be made to register an individual tty device if
- * the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If that
- * bit is not set, this function should not be called by a tty driver.
+ * This call is required to be made to register an individual tty device
+ * if the tty driver's flags have the TTY_DRIVER_DYNAMIC_DEV bit set. If
+ * that bit is not set, this function should not be called by a tty
+ * driver.
+ *
+ * Locking: ??
*/
+
struct class_device *tty_register_device(struct tty_driver *driver,
unsigned index, struct device *device)
{
@@ -2977,13 +3641,16 @@ struct class_device *tty_register_device(struct tty_driver *driver,
}
/**
- * tty_unregister_device - unregister a tty device
- * @driver: the tty driver that describes the tty device
- * @index: the index in the tty driver for this tty device
+ * tty_unregister_device - unregister a tty device
+ * @driver: the tty driver that describes the tty device
+ * @index: the index in the tty driver for this tty device
*
- * If a tty device is registered with a call to tty_register_device() then
- * this function must be made when the tty device is gone.
+ * If a tty device is registered with a call to tty_register_device() then
+ * this function must be called when the tty device is gone.
+ *
+ * Locking: ??
*/
+
void tty_unregister_device(struct tty_driver *driver, unsigned index)
{
class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
@@ -3094,7 +3761,6 @@ int tty_register_driver(struct tty_driver *driver)
driver->cdev.owner = driver->owner;
error = cdev_add(&driver->cdev, dev, driver->num);
if (error) {
- cdev_del(&driver->cdev);
unregister_chrdev_region(dev, driver->num);
driver->ttys = NULL;
driver->termios = driver->termios_locked = NULL;
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index f19cf9d7792..4ad47d321bd 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -36,6 +36,18 @@
#define TERMIOS_WAIT 2
#define TERMIOS_TERMIO 4
+
+/**
+ * tty_wait_until_sent - wait for I/O to finish
+ * @tty: tty we are waiting for
+ * @timeout: how long we will wait
+ *
+ * Wait for characters pending in a tty driver to hit the wire, or
+ * for a timeout to occur (eg due to flow control)
+ *
+ * Locking: none
+ */
+
void tty_wait_until_sent(struct tty_struct * tty, long timeout)
{
DECLARE_WAITQUEUE(wait, current);
@@ -94,6 +106,18 @@ static void unset_locked_termios(struct termios *termios,
old->c_cc[i] : termios->c_cc[i];
}
+/**
+ * change_termios - update termios values
+ * @tty: tty to update
+ * @new_termios: desired new value
+ *
+ * Perform updates to the termios values set on this terminal. There
+ * is a bit of layering violation here with n_tty in terms of the
+ * internal knowledge of this function.
+ *
+ * Locking: termios_sem
+ */
+
static void change_termios(struct tty_struct * tty, struct termios * new_termios)
{
int canon_change;
@@ -155,6 +179,19 @@ static void change_termios(struct tty_struct * tty, struct termios * new_termios
up(&tty->termios_sem);
}
+/**
+ * set_termios - set termios values for a tty
+ * @tty: terminal device
+ * @arg: user data
+ * @opt: option information
+ *
+ * Helper function to prepare termios data and run neccessary other
+ * functions before using change_termios to do the actual changes.
+ *
+ * Locking:
+ * Called functions take ldisc and termios_sem locks
+ */
+
static int set_termios(struct tty_struct * tty, void __user *arg, int opt)
{
struct termios tmp_termios;
@@ -284,6 +321,17 @@ static void set_sgflags(struct termios * termios, int flags)
}
}
+/**
+ * set_sgttyb - set legacy terminal values
+ * @tty: tty structure
+ * @sgttyb: pointer to old style terminal structure
+ *
+ * Updates a terminal from the legacy BSD style terminal information
+ * structure.
+ *
+ * Locking: termios_sem
+ */
+
static int set_sgttyb(struct tty_struct * tty, struct sgttyb __user * sgttyb)
{
int retval;
@@ -369,9 +417,16 @@ static int set_ltchars(struct tty_struct * tty, struct ltchars __user * ltchars)
}
#endif
-/*
- * Send a high priority character to the tty.
+/**
+ * send_prio_char - send priority character
+ *
+ * Send a high priority character to the tty even if stopped
+ *
+ * Locking: none
+ *
+ * FIXME: overlapping calls with start/stop tty lose state of tty
*/
+
static void send_prio_char(struct tty_struct *tty, char ch)
{
int was_stopped = tty->stopped;
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index eccffaf26fa..a5628a8b662 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -1011,6 +1011,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
return -EPERM;
vt_dont_switch = 0;
return 0;
+ case VT_GETHIFONTMASK:
+ return put_user(vc->vc_hi_font_mask, (unsigned short __user *)arg);
default:
return -ENOIOCTLCMD;
}
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index d4bad6704bb..448df277337 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -3552,6 +3552,8 @@ static int ohci1394_pci_resume (struct pci_dev *pdev)
static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
{
+ pci_save_state(pdev);
+
#ifdef CONFIG_PPC_PMAC
if (machine_is(powermac)) {
struct device_node *of_node;
@@ -3563,8 +3565,6 @@ static int ohci1394_pci_suspend (struct pci_dev *pdev, pm_message_t state)
}
#endif
- pci_save_state(pdev);
-
return 0;
}
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index be48cedf986..c54de989eb0 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -255,7 +255,9 @@ static struct region *__rh_alloc(struct region_hash *rh, region_t region)
struct region *reg, *nreg;
read_unlock(&rh->hash_lock);
- nreg = mempool_alloc(rh->region_pool, GFP_NOIO);
+ nreg = mempool_alloc(rh->region_pool, GFP_ATOMIC);
+ if (unlikely(!nreg))
+ nreg = kmalloc(sizeof(struct region), GFP_NOIO);
nreg->state = rh->log->type->in_sync(rh->log, region, 1) ?
RH_CLEAN : RH_NOSYNC;
nreg->rh = rh;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index b6d16022a53..8dbab2ef388 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -1597,6 +1597,19 @@ void md_update_sb(mddev_t * mddev)
repeat:
spin_lock_irq(&mddev->write_lock);
+
+ if (mddev->degraded && mddev->sb_dirty == 3)
+ /* If the array is degraded, then skipping spares is both
+ * dangerous and fairly pointless.
+ * Dangerous because a device that was removed from the array
+ * might have a event_count that still looks up-to-date,
+ * so it can be re-added without a resync.
+ * Pointless because if there are any spares to skip,
+ * then a recovery will happen and soon that array won't
+ * be degraded any more and the spare can go back to sleep then.
+ */
+ mddev->sb_dirty = 1;
+
sync_req = mddev->in_sync;
mddev->utime = get_seconds();
if (mddev->sb_dirty == 3)
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 1efe22a2d04..87bfe9e7d8c 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1625,15 +1625,16 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
return 0;
}
- /* before building a request, check if we can skip these blocks..
- * This call the bitmap_start_sync doesn't actually record anything
- */
if (mddev->bitmap == NULL &&
mddev->recovery_cp == MaxSector &&
+ !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) &&
conf->fullsync == 0) {
*skipped = 1;
return max_sector - sector_nr;
}
+ /* before building a request, check if we can skip these blocks..
+ * This call the bitmap_start_sync doesn't actually record anything
+ */
if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
!conf->fullsync && !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
/* We can skip this block, and probably several more */
diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c
index d7897dc6b3c..a0ba07c36ee 100644
--- a/drivers/mtd/nand/ams-delta.c
+++ b/drivers/mtd/nand/ams-delta.c
@@ -130,11 +130,13 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd,
if (ctrl & NAND_CTRL_CHANGE) {
unsigned long bits;
- bits = (~ctrl & NAND_NCE) << 2;
- bits |= (ctrl & NAND_CLE) << 7;
- bits |= (ctrl & NAND_ALE) << 6;
+ bits = (~ctrl & NAND_NCE) ? AMS_DELTA_LATCH2_NAND_NCE : 0;
+ bits |= (ctrl & NAND_CLE) ? AMS_DELTA_LATCH2_NAND_CLE : 0;
+ bits |= (ctrl & NAND_ALE) ? AMS_DELTA_LATCH2_NAND_ALE : 0;
- ams_delta_latch2_write(0xC2, bits);
+ ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE |
+ AMS_DELTA_LATCH2_NAND_ALE |
+ AMS_DELTA_LATCH2_NAND_NCE, bits);
}
if (cmd != NAND_CMD_NONE)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 62b861304e0..c8cbc00243f 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1093,9 +1093,10 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
ret = nand_do_read_ops(mtd, from, &chip->ops);
+ *retlen = chip->ops.retlen;
+
nand_release_device(mtd);
- *retlen = chip->ops.retlen;
return ret;
}
@@ -1691,9 +1692,10 @@ static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,
ret = nand_do_write_ops(mtd, to, &chip->ops);
+ *retlen = chip->ops.retlen;
+
nand_release_device(mtd);
- *retlen = chip->ops.retlen;
return ret;
}
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index d6d1bff52b8..2c7de79c83b 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -69,12 +69,12 @@ static void s3c_rtc_setaie(int to)
pr_debug("%s: aie=%d\n", __FUNCTION__, to);
- tmp = readb(S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
+ tmp = readb(s3c_rtc_base + S3C2410_RTCALM) & ~S3C2410_RTCALM_ALMEN;
if (to)
tmp |= S3C2410_RTCALM_ALMEN;
- writeb(tmp, S3C2410_RTCALM);
+ writeb(tmp, s3c_rtc_base + S3C2410_RTCALM);
}
static void s3c_rtc_setpie(int to)
@@ -84,12 +84,12 @@ static void s3c_rtc_setpie(int to)
pr_debug("%s: pie=%d\n", __FUNCTION__, to);
spin_lock_irq(&s3c_rtc_pie_lock);
- tmp = readb(S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
+ tmp = readb(s3c_rtc_base + S3C2410_TICNT) & ~S3C2410_TICNT_ENABLE;
if (to)
tmp |= S3C2410_TICNT_ENABLE;
- writeb(tmp, S3C2410_TICNT);
+ writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
spin_unlock_irq(&s3c_rtc_pie_lock);
}
@@ -98,13 +98,13 @@ static void s3c_rtc_setfreq(int freq)
unsigned int tmp;
spin_lock_irq(&s3c_rtc_pie_lock);
- tmp = readb(S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
+ tmp = readb(s3c_rtc_base + S3C2410_TICNT) & S3C2410_TICNT_ENABLE;
s3c_rtc_freq = freq;
tmp |= (128 / freq)-1;
- writeb(tmp, S3C2410_TICNT);
+ writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
spin_unlock_irq(&s3c_rtc_pie_lock);
}
@@ -113,14 +113,15 @@ static void s3c_rtc_setfreq(int freq)
static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
{
unsigned int have_retried = 0;
+ void __iomem *base = s3c_rtc_base;
retry_get_time:
- rtc_tm->tm_min = readb(S3C2410_RTCMIN);
- rtc_tm->tm_hour = readb(S3C2410_RTCHOUR);
- rtc_tm->tm_mday = readb(S3C2410_RTCDATE);
- rtc_tm->tm_mon = readb(S3C2410_RTCMON);
- rtc_tm->tm_year = readb(S3C2410_RTCYEAR);
- rtc_tm->tm_sec = readb(S3C2410_RTCSEC);
+ rtc_tm->tm_min = readb(base + S3C2410_RTCMIN);
+ rtc_tm->tm_hour = readb(base + S3C2410_RTCHOUR);
+ rtc_tm->tm_mday = readb(base + S3C2410_RTCDATE);
+ rtc_tm->tm_mon = readb(base + S3C2410_RTCMON);
+ rtc_tm->tm_year = readb(base + S3C2410_RTCYEAR);
+ rtc_tm->tm_sec = readb(base + S3C2410_RTCSEC);
/* the only way to work out wether the system was mid-update
* when we read it is to check the second counter, and if it
@@ -151,17 +152,26 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
{
- /* the rtc gets round the y2k problem by just not supporting it */
+ void __iomem *base = s3c_rtc_base;
+ int year = tm->tm_year - 100;
- if (tm->tm_year < 100)
+ pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n",
+ tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ /* we get around y2k by simply not supporting it */
+
+ if (year < 0 || year >= 100) {
+ dev_err(dev, "rtc only supports 100 years\n");
return -EINVAL;
+ }
- writeb(BIN2BCD(tm->tm_sec), S3C2410_RTCSEC);
- writeb(BIN2BCD(tm->tm_min), S3C2410_RTCMIN);
- writeb(BIN2BCD(tm->tm_hour), S3C2410_RTCHOUR);
- writeb(BIN2BCD(tm->tm_mday), S3C2410_RTCDATE);
- writeb(BIN2BCD(tm->tm_mon + 1), S3C2410_RTCMON);
- writeb(BIN2BCD(tm->tm_year - 100), S3C2410_RTCYEAR);
+ writeb(BIN2BCD(tm->tm_sec), base + S3C2410_RTCSEC);
+ writeb(BIN2BCD(tm->tm_min), base + S3C2410_RTCMIN);
+ writeb(BIN2BCD(tm->tm_hour), base + S3C2410_RTCHOUR);
+ writeb(BIN2BCD(tm->tm_mday), base + S3C2410_RTCDATE);
+ writeb(BIN2BCD(tm->tm_mon + 1), base + S3C2410_RTCMON);
+ writeb(BIN2BCD(year), base + S3C2410_RTCYEAR);
return 0;
}
@@ -169,16 +179,17 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct rtc_time *alm_tm = &alrm->time;
+ void __iomem *base = s3c_rtc_base;
unsigned int alm_en;
- alm_tm->tm_sec = readb(S3C2410_ALMSEC);
- alm_tm->tm_min = readb(S3C2410_ALMMIN);
- alm_tm->tm_hour = readb(S3C2410_ALMHOUR);
- alm_tm->tm_mon = readb(S3C2410_ALMMON);
- alm_tm->tm_mday = readb(S3C2410_ALMDATE);
- alm_tm->tm_year = readb(S3C2410_ALMYEAR);
+ alm_tm->tm_sec = readb(base + S3C2410_ALMSEC);
+ alm_tm->tm_min = readb(base + S3C2410_ALMMIN);
+ alm_tm->tm_hour = readb(base + S3C2410_ALMHOUR);
+ alm_tm->tm_mon = readb(base + S3C2410_ALMMON);
+ alm_tm->tm_mday = readb(base + S3C2410_ALMDATE);
+ alm_tm->tm_year = readb(base + S3C2410_ALMYEAR);
- alm_en = readb(S3C2410_RTCALM);
+ alm_en = readb(base + S3C2410_RTCALM);
pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
alm_en,
@@ -226,6 +237,7 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct rtc_time *tm = &alrm->time;
+ void __iomem *base = s3c_rtc_base;
unsigned int alrm_en;
pr_debug("s3c_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
@@ -234,32 +246,32 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
- alrm_en = readb(S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
- writeb(0x00, S3C2410_RTCALM);
+ alrm_en = readb(base + S3C2410_RTCALM) & S3C2410_RTCALM_ALMEN;
+ writeb(0x00, base + S3C2410_RTCALM);
if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
alrm_en |= S3C2410_RTCALM_SECEN;
- writeb(BIN2BCD(tm->tm_sec), S3C2410_ALMSEC);
+ writeb(BIN2BCD(tm->tm_sec), base + S3C2410_ALMSEC);
}
if (tm->tm_min < 60 && tm->tm_min >= 0) {
alrm_en |= S3C2410_RTCALM_MINEN;
- writeb(BIN2BCD(tm->tm_min), S3C2410_ALMMIN);
+ writeb(BIN2BCD(tm->tm_min), base + S3C2410_ALMMIN);
}
if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
alrm_en |= S3C2410_RTCALM_HOUREN;
- writeb(BIN2BCD(tm->tm_hour), S3C2410_ALMHOUR);
+ writeb(BIN2BCD(tm->tm_hour), base + S3C2410_ALMHOUR);
}
pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en);
- writeb(alrm_en, S3C2410_RTCALM);
+ writeb(alrm_en, base + S3C2410_RTCALM);
if (0) {
- alrm_en = readb(S3C2410_RTCALM);
+ alrm_en = readb(base + S3C2410_RTCALM);
alrm_en &= ~S3C2410_RTCALM_ALMEN;
- writeb(alrm_en, S3C2410_RTCALM);
+ writeb(alrm_en, base + S3C2410_RTCALM);
disable_irq_wake(s3c_rtc_alarmno);
}
@@ -319,8 +331,8 @@ static int s3c_rtc_ioctl(struct device *dev,
static int s3c_rtc_proc(struct device *dev, struct seq_file *seq)
{
- unsigned int rtcalm = readb(S3C2410_RTCALM);
- unsigned int ticnt = readb (S3C2410_TICNT);
+ unsigned int rtcalm = readb(s3c_rtc_base + S3C2410_RTCALM);
+ unsigned int ticnt = readb(s3c_rtc_base + S3C2410_TICNT);
seq_printf(seq, "alarm_IRQ\t: %s\n",
(rtcalm & S3C2410_RTCALM_ALMEN) ? "yes" : "no" );
@@ -387,39 +399,40 @@ static struct rtc_class_ops s3c_rtcops = {
static void s3c_rtc_enable(struct platform_device *pdev, int en)
{
+ void __iomem *base = s3c_rtc_base;
unsigned int tmp;
if (s3c_rtc_base == NULL)
return;
if (!en) {
- tmp = readb(S3C2410_RTCCON);
- writeb(tmp & ~S3C2410_RTCCON_RTCEN, S3C2410_RTCCON);
+ tmp = readb(base + S3C2410_RTCCON);
+ writeb(tmp & ~S3C2410_RTCCON_RTCEN, base + S3C2410_RTCCON);
- tmp = readb(S3C2410_TICNT);
- writeb(tmp & ~S3C2410_TICNT_ENABLE, S3C2410_TICNT);
+ tmp = readb(base + S3C2410_TICNT);
+ writeb(tmp & ~S3C2410_TICNT_ENABLE, base + S3C2410_TICNT);
} else {
/* re-enable the device, and check it is ok */
- if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){
+ if ((readb(base+S3C2410_RTCCON) & S3C2410_RTCCON_RTCEN) == 0){
dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
- tmp = readb(S3C2410_RTCCON);
- writeb(tmp | S3C2410_RTCCON_RTCEN , S3C2410_RTCCON);
+ tmp = readb(base + S3C2410_RTCCON);
+ writeb(tmp|S3C2410_RTCCON_RTCEN, base+S3C2410_RTCCON);
}
- if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){
+ if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CNTSEL)){
dev_info(&pdev->dev, "removing RTCCON_CNTSEL\n");
- tmp = readb(S3C2410_RTCCON);
- writeb(tmp& ~S3C2410_RTCCON_CNTSEL , S3C2410_RTCCON);
+ tmp = readb(base + S3C2410_RTCCON);
+ writeb(tmp& ~S3C2410_RTCCON_CNTSEL, base+S3C2410_RTCCON);
}
- if ((readb(S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){
+ if ((readb(base + S3C2410_RTCCON) & S3C2410_RTCCON_CLKRST)){
dev_info(&pdev->dev, "removing RTCCON_CLKRST\n");
- tmp = readb(S3C2410_RTCCON);
- writeb(tmp & ~S3C2410_RTCCON_CLKRST, S3C2410_RTCCON);
+ tmp = readb(base + S3C2410_RTCCON);
+ writeb(tmp & ~S3C2410_RTCCON_CLKRST, base+S3C2410_RTCCON);
}
}
}
@@ -475,8 +488,8 @@ static int s3c_rtc_probe(struct platform_device *pdev)
}
s3c_rtc_mem = request_mem_region(res->start,
- res->end-res->start+1,
- pdev->name);
+ res->end-res->start+1,
+ pdev->name);
if (s3c_rtc_mem == NULL) {
dev_err(&pdev->dev, "failed to reserve memory region\n");
@@ -495,7 +508,8 @@ static int s3c_rtc_probe(struct platform_device *pdev)
s3c_rtc_enable(pdev, 1);
- pr_debug("s3c2410_rtc: RTCCON=%02x\n", readb(S3C2410_RTCCON));
+ pr_debug("s3c2410_rtc: RTCCON=%02x\n",
+ readb(s3c_rtc_base + S3C2410_RTCCON));
s3c_rtc_setfreq(s3c_rtc_freq);
@@ -543,7 +557,7 @@ static int s3c_rtc_suspend(struct platform_device *pdev, pm_message_t state)
/* save TICNT for anyone using periodic interrupts */
- ticnt_save = readb(S3C2410_TICNT);
+ ticnt_save = readb(s3c_rtc_base + S3C2410_TICNT);
/* calculate time delta for suspend */
@@ -567,7 +581,7 @@ static int s3c_rtc_resume(struct platform_device *pdev)
rtc_tm_to_time(&tm, &time.tv_sec);
restore_time_delta(&s3c_rtc_delta, &time);
- writeb(ticnt_save, S3C2410_TICNT);
+ writeb(ticnt_save, s3c_rtc_base + S3C2410_TICNT);
return 0;
}
#else
diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
index f7b5d7372d2..94d1de55607 100644
--- a/drivers/scsi/ide-scsi.c
+++ b/drivers/scsi/ide-scsi.c
@@ -517,7 +517,7 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
/* No more interrupts */
if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
- local_irq_enable();
+ local_irq_enable_in_hardirq();
if (status.b.check)
rq->errors++;
idescsi_end_request (drive, 1, 0);
diff --git a/drivers/video/imacfb.c b/drivers/video/imacfb.c
index b485bece5fc..18ea4a54910 100644
--- a/drivers/video/imacfb.c
+++ b/drivers/video/imacfb.c
@@ -71,10 +71,10 @@ static int set_system(struct dmi_system_id *id)
static struct dmi_system_id __initdata dmi_system_table[] = {
{ set_system, "iMac4,1", {
DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
- DMI_MATCH(DMI_BIOS_VERSION,"iMac4,1") }, (void*)M_I17},
+ DMI_MATCH(DMI_PRODUCT_NAME,"iMac4,1") }, (void*)M_I17},
{ set_system, "MacBookPro1,1", {
DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
- DMI_MATCH(DMI_BIOS_VERSION,"MacBookPro1,1") }, (void*)M_I17},
+ DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro1,1") }, (void*)M_I17},
{ set_system, "MacBook1,1", {
DMI_MATCH(DMI_BIOS_VENDOR,"Apple Computer, Inc."),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBook1,1")}, (void *)M_MACBOOK},
diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c
index 440272ad10e..7c76e079ca7 100644
--- a/drivers/video/matrox/g450_pll.c
+++ b/drivers/video/matrox/g450_pll.c
@@ -331,7 +331,15 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll,
tmp |= M1064_XPIXCLKCTRL_PLL_UP;
}
matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp);
+#ifdef __powerpc__
+ /* This is necessary to avoid jitter on PowerPC
+ * (OpenFirmware) systems, but apparently
+ * introduces jitter, at least on a x86-64
+ * using DVI.
+ * A simple workaround is disable for non-PPC.
+ */
matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL, 0);
+#endif /* __powerpc__ */
matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl);
matroxfb_DAC_unlock_irqrestore(flags);