Commit 72be09b0 authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.12pre6

parent c59591e1
......@@ -11946,7 +11946,7 @@ CONFIG_USB_ACM
Support for user-space parallel port device drivers
CONFIG_PPDEV
Saying Y to this adds support for /dev/parport device nodes. This
is needed for programs that want portable access to the parallel
is needed for programs that want low-level access to the parallel
port, for instance deviceid (which displays Plug-and-Play device
IDs) and vlp (which makes a Linux computer act as though it's a
printer).
......
......@@ -30,6 +30,8 @@
* RSTATUS read_status
* NEGOT parport_negotiate
* YIELD parport_yield_blocking
* WCTLONIRQ on interrupt, set control lines
* CLRIRQ clear (and return) interrupt count
* read/write read or write in current IEEE 1284 protocol
* select wait for interrupt (in readfds)
*/
......@@ -53,9 +55,11 @@
struct pp_struct {
struct pardevice * pdev;
wait_queue_head_t irq_wait;
int got_irq;
atomic_t irqc;
int mode;
unsigned int flags;
int irqresponse;
unsigned char irqctl;
};
/* pp_struct.flags bitfields */
......@@ -287,7 +291,13 @@ static ssize_t pp_write (struct file * file, const char * buf, size_t count,
static void pp_irq (int irq, void * private, struct pt_regs * unused)
{
struct pp_struct * pp = (struct pp_struct *) private;
pp->got_irq = 1;
if (pp->irqresponse) {
parport_write_control (pp->pdev->port, pp->irqctl);
pp->irqresponse = 0;
}
atomic_inc (&pp->irqc);
wake_up_interruptible (&pp->irq_wait);
}
......@@ -459,11 +469,36 @@ static int pp_ioctl(struct inode *inode, struct file *file,
case PPNEGOT:
if (copy_from_user (&mode, (int *) arg, sizeof (mode)))
return -EFAULT;
/* FIXME: validate mode */
ret = parport_negotiate (port, mode);
switch ((ret = parport_negotiate (port, mode))) {
case 0: break;
case -1: /* handshake failed, peripheral not IEEE 1284 */
ret = -EIO;
break;
case 1: /* handshake succeeded, peripheral rejected mode */
ret = -ENXIO;
break;
}
enable_irq (pp);
return ret;
case PPWCTLONIRQ:
if (copy_from_user (&reg, (unsigned char *) arg,
sizeof (reg)))
return -EFAULT;
/* Remember what to set the control lines to, for next
* time we get an interrupt. */
pp->irqctl = reg;
pp->irqresponse = 1;
return 0;
case PPCLRIRQ:
ret = atomic_read (&pp->irqc);
if (copy_to_user ((int *) arg, &ret, sizeof (ret)))
return -EFAULT;
atomic_sub (ret, &pp->irqc);
return 0;
default:
printk (KERN_DEBUG CHRDEV "%x: What? (cmd=0x%x)\n", minor,
cmd);
......@@ -488,7 +523,7 @@ static int pp_open (struct inode * inode, struct file * file)
pp->mode = IEEE1284_MODE_COMPAT;
pp->flags = 0;
pp->got_irq = 0;
atomic_set (&pp->irqc, 0);
init_waitqueue_head (&pp->irq_wait);
/* Defer the actual device registration until the first claim.
......@@ -531,10 +566,10 @@ static unsigned int pp_poll (struct file * file, poll_table * wait)
{
struct pp_struct *pp = file->private_data;
unsigned int mask = 0;
if (pp->got_irq) {
pp->got_irq = 0;
if (atomic_read (&pp->irqc))
mask |= POLLIN | POLLRDNORM;
}
poll_wait (file, &pp->irq_wait, wait);
return mask;
}
......
......@@ -63,3 +63,9 @@ struct ppdev_frob_struct {
/* Negotiate a particular IEEE 1284 mode. */
#define PPNEGOT _IOW(PP_IOCTL, 0x91, int)
/* Set control lines when an interrupt occurs. */
#define PPWCTLONIRQ _IOW(PP_IOCTL, 0x92, unsigned char)
/* Clear (and return) interrupt count. */
#define PPCLRIRQ _IOR(PP_IOCTL, 0x93, int)
This diff is collapsed.
......@@ -1521,6 +1521,7 @@ static int __init probe_one_port(unsigned long int base,
int irq, int dma)
{
struct parport_pc_private *priv;
struct parport_operations *ops;
struct parport tmp;
struct parport *p = &tmp;
int probedirq = PARPORT_IRQ_NONE;
......@@ -1530,6 +1531,14 @@ static int __init probe_one_port(unsigned long int base,
printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base);
return 0;
}
ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL);
if (!ops) {
printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n",
base);
kfree (priv);
return 0;
}
memcpy (ops, &parport_pc_ops, sizeof (struct parport_operations));
priv->ctr = 0xc;
priv->ctr_writable = 0xff;
priv->ecr = 0;
......@@ -1540,7 +1549,7 @@ static int __init probe_one_port(unsigned long int base,
p->irq = irq;
p->dma = dma;
p->modes = PARPORT_MODE_PCSPP;
p->ops = &parport_pc_ops;
p->ops = ops;
p->private_data = priv;
p->physport = p;
if (base_hi && !check_region(base_hi,3)) {
......@@ -1564,8 +1573,9 @@ static int __init probe_one_port(unsigned long int base,
parport_PS2_supported (p);
if (!(p = parport_register_port(base, PARPORT_IRQ_NONE,
PARPORT_DMA_NONE, &parport_pc_ops))) {
PARPORT_DMA_NONE, ops))) {
kfree (priv);
kfree (ops);
return 0;
}
......@@ -1697,34 +1707,6 @@ static int __init probe_one_port(unsigned long int base,
/* Look for PCI parallel port cards. */
static int __init parport_pc_init_pci (int irq, int dma)
{
/* These need to go in pci.h: */
#ifndef PCI_VENDOR_ID_SIIG
#define PCI_VENDOR_ID_SIIG 0x131f
#define PCI_DEVICE_ID_SIIG_1S1P_10x_550 0x1010
#define PCI_DEVICE_ID_SIIG_1S1P_10x_650 0x1011
#define PCI_DEVICE_ID_SIIG_1S1P_10x_850 0x1012
#define PCI_DEVICE_ID_SIIG_1P_10x 0x1020
#define PCI_DEVICE_ID_SIIG_2P_10x 0x1021
#define PCI_DEVICE_ID_SIIG_2S1P_10x_550 0x1034
#define PCI_DEVICE_ID_SIIG_2S1P_10x_650 0x1035
#define PCI_DEVICE_ID_SIIG_2S1P_10x_850 0x1036
#define PCI_DEVICE_ID_SIIG_1P_20x 0x2020
#define PCI_DEVICE_ID_SIIG_2P_20x 0x2021
#define PCI_DEVICE_ID_SIIG_2P1S_20x_550 0x2040
#define PCI_DEVICE_ID_SIIG_2P1S_20x_650 0x2041
#define PCI_DEVICE_ID_SIIG_2P1S_20x_850 0x2042
#define PCI_DEVICE_ID_SIIG_1S1P_20x_550 0x2010
#define PCI_DEVICE_ID_SIIG_1S1P_20x_650 0x2011
#define PCI_DEVICE_ID_SIIG_1S1P_20x_850 0x2012
#define PCI_DEVICE_ID_SIIG_2S1P_20x_550 0x2060
#define PCI_DEVICE_ID_SIIG_2S1P_20x_650 0x2061
#define PCI_DEVICE_ID_SIIG_2S1P_20x_850 0x2062
#define PCI_VENDOR_ID_LAVA 0x1407
#define PCI_DEVICE_ID_LAVA_PARALLEL 0x8000
#define PCI_DEVICE_ID_LAVA_DUAL_PAR_A 0x8001 /* The Lava Dual Parallel is */
#define PCI_DEVICE_ID_LAVA_DUAL_PAR_B 0x8002 /* two PCI devices on a card */
#endif
struct {
unsigned int vendor;
unsigned int device;
......@@ -1896,6 +1878,7 @@ void cleanup_module(void)
if (priv->dma_buf)
free_page((unsigned long) priv->dma_buf);
kfree (p->private_data);
kfree (p->ops); /* hope no-one cached it */
parport_unregister_port(p);
}
p = tmp;
......
......@@ -24,6 +24,7 @@
#include <linux/kernel.h>
#include <linux/malloc.h>
#include <linux/sched.h>
#include <linux/kmod.h>
#include <asm/spinlock.h>
#include <asm/irq.h>
......@@ -41,6 +42,51 @@ spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED;
static struct parport_driver *driver_chain = NULL;
spinlock_t driverlist_lock = SPIN_LOCK_UNLOCKED;
/* What you can do to a port that's gone away.. */
static void dead_write_lines (struct parport *p, unsigned char b){}
static unsigned char dead_read_lines (struct parport *p) { return 0; }
static unsigned char dead_frob_lines (struct parport *p, unsigned char b,
unsigned char c) { return 0; }
static void dead_onearg (struct parport *p){}
static void dead_irq (int i, void *p, struct pt_regs *r) { }
static void dead_initstate (struct pardevice *d, struct parport_state *s) { }
static void dead_state (struct parport *p, struct parport_state *s) { }
static void dead_noargs (void) { }
static void dead_fill (struct inode *i, int f) { }
static size_t dead_write (struct parport *p, const void *b, size_t l, int f)
{ return 0; }
static size_t dead_read (struct parport *p, void *b, size_t l, int f)
{ return 0; }
static struct parport_operations dead_ops = {
dead_write_lines, /* data */
dead_read_lines,
dead_write_lines, /* control */
dead_read_lines,
dead_frob_lines,
dead_read_lines, /* status */
dead_onearg, /* enable_irq */
dead_onearg, /* disable_irq */
dead_onearg, /* data_forward */
dead_onearg, /* data_reverse */
dead_irq,
dead_initstate, /* init_state */
dead_state,
dead_state,
dead_noargs, /* xxx_use_count */
dead_noargs,
dead_fill, /* fill_inode */
dead_write, /* epp */
dead_read,
dead_write,
dead_read,
dead_write, /* ecp */
dead_read,
dead_write,
dead_write, /* compat */
dead_read, /* nibble */
dead_read /* byte */
};
static void call_driver_chain(int attach, struct parport *port)
{
struct parport_driver *drv;
......@@ -90,6 +136,18 @@ void parport_unregister_driver (struct parport_driver *arg)
/* Return a list of all the ports we know about. */
struct parport *parport_enumerate(void)
{
/* Attempt to make things work on 2.2 systems. */
if (!portlist) {
request_module ("parport_lowlevel");
if (portlist)
/* The user has a parport_lowlevel alias in
* conf.modules. Warn them that it won't work
* for long. */
printk (KERN_WARNING
"parport: 'parport_lowlevel' is deprecated; "
"see parport.txt\n");
}
return portlist;
}
......@@ -188,10 +246,31 @@ void parport_announce_port (struct parport *port)
call_driver_chain (1, port);
}
static void free_port (struct parport *port)
{
int d;
for (d = 0; d < 5; d++) {
if (port->probe_info[d].class_name)
kfree (port->probe_info[d].class_name);
if (port->probe_info[d].mfr)
kfree (port->probe_info[d].mfr);
if (port->probe_info[d].model)
kfree (port->probe_info[d].model);
if (port->probe_info[d].cmdset)
kfree (port->probe_info[d].cmdset);
if (port->probe_info[d].description)
kfree (port->probe_info[d].description);
}
kfree(port->name);
kfree(port);
}
void parport_unregister_port(struct parport *port)
{
struct parport *p;
int d;
port->ops = &dead_ops;
/* Spread the word. */
call_driver_chain (0, port);
......@@ -217,21 +296,8 @@ void parport_unregister_port(struct parport *port)
}
spin_unlock(&parportlist_lock);
for (d = 0; d < 5; d++) {
if (port->probe_info[d].class_name)
kfree (port->probe_info[d].class_name);
if (port->probe_info[d].mfr)
kfree (port->probe_info[d].mfr);
if (port->probe_info[d].model)
kfree (port->probe_info[d].model);
if (port->probe_info[d].cmdset)
kfree (port->probe_info[d].cmdset);
if (port->probe_info[d].description)
kfree (port->probe_info[d].description);
}
kfree(port->name);
kfree(port);
if (!port->devices)
free_port (port);
}
struct pardevice *parport_register_device(struct parport *port, const char *name,
......@@ -361,6 +427,11 @@ void parport_unregister_device(struct pardevice *dev)
dec_parport_count();
port->ops->dec_use_count();
/* If this was the last device on a port that's already gone away,
* free up the resources. */
if (port->ops == &dead_ops && !port->devices)
free_port (port);
}
int parport_claim(struct pardevice *dev)
......
......@@ -583,7 +583,7 @@ printk("cpia_open\n");
cpia->fbuf = rvmalloc(2 * MAX_FRAME_SIZE);
if (!cpia->fbuf)
return -ENOMEM;
goto open_err_ret;
cpia->frame[0].state = FRAME_DONE;
cpia->frame[1].state = FRAME_DONE;
......@@ -595,15 +595,15 @@ printk("cpia_open\n");
cpia->sbuf[0].data = kmalloc(STREAM_BUF_SIZE, GFP_KERNEL);
if (!cpia->sbuf[0].data)
return -ENOMEM;
goto open_err_on0;
cpia->sbuf[1].data = kmalloc(STREAM_BUF_SIZE, GFP_KERNEL);
if (!cpia->sbuf[1].data)
return -ENOMEM;
goto open_err_on1;
cpia->sbuf[2].data = kmalloc(STREAM_BUF_SIZE, GFP_KERNEL);
if (!cpia->sbuf[2].data)
return -ENOMEM;
goto open_err_on2;
printk("sbuf[0] @ %p\n", cpia->sbuf[0].data);
printk("sbuf[1] @ %p\n", cpia->sbuf[1].data);
......@@ -617,6 +617,15 @@ printk("cpia_open\n");
cpia_init_isoc(cpia);
return 0;
open_err_on2:
kfree (cpia->sbuf[1].data);
open_err_on1:
kfree (cpia->sbuf[0].data);
open_err_on0:
rvfree(cpia->fbuf, 2 * MAX_FRAME_SIZE);
open_err_ret:
return -ENOMEM;
}
static void cpia_close(struct video_device *dev)
......
......@@ -361,7 +361,7 @@ static void* uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb
unsigned int destination, status;
/* Destination: pipe destination with INPUT */
destination = (pipe & PIPE_DEVEP_MASK) | 0x69;
destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe);
/* Status: slow/fast, Interrupt, Active, Short Packet Detect Infinite Errors */
status = (pipe & (1 << 26)) | (1 << 24) | (1 << 23) | (1 << 29) | (0 << 27);
......@@ -371,7 +371,7 @@ static void* uhci_request_irq(struct usb_device *usb_dev, unsigned int pipe, usb
interrupt_qh->element);
td->link = 1;
td->status = status; /* In */
td->status = status;
td->info = destination | ((usb_maxpacket(usb_dev, pipe) - 1) << 21) |
(usb_gettoggle(usb_dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)) << 19);
td->buffer = virt_to_bus(dev->data);
......@@ -633,12 +633,8 @@ static void *uhci_allocate_isochronous(struct usb_device *usb_dev, unsigned int
td = &isodesc->td[i];
/* The "pipe" thing contains the destination in bits 8--18 */
destination = (pipe & PIPE_DEVEP_MASK);
if (usb_pipeout(pipe))
destination |= 0xE1; /* OUT */
else
destination |= 0x69; /* IN */
destination = (pipe & PIPE_DEVEP_MASK)
| usb_packetid (pipe); /* add IN or OUT */
/* Status: slow/fast, Active, Isochronous */
status = (pipe & (1 << 26)) | (1 << 23) | (1 << 25);
......@@ -1010,18 +1006,8 @@ static int uhci_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *da
if (len > maxsze * 31)
printk("Warning, too much data for a bulk packet, crashing (%d/%d)\n", len, maxsze);
/* The "pipe" thing contains the destination in bits 8--18, 0x69 is IN */
/*
IS THIS NECCESARY? PERHAPS WE CAN JUST USE THE PIPE
LOOK AT: usb_pipeout and the pipe bits
I FORGOT WHAT IT EXACTLY DOES
*/
if (usb_pipeout(pipe)) {
destination = (pipe & PIPE_DEVEP_MASK) | 0xE1;
}
else {
destination = (pipe & PIPE_DEVEP_MASK) | 0x69;
}
/* The "pipe" thing contains the destination in bits 8--18 */
destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe);
/* Status: slow/fast, Active, Short Packet Detect Three Errors */
status = (pipe & (1 << 26)) | (1 << 23) | (1 << 29) | (3 << 27);
......
......@@ -406,6 +406,7 @@ extern int usb_compress_isochronous (struct usb_device *usb_dev, void *_isodesc)
#define usb_packetid(pipe) (((pipe) & 0x80) ? 0x69 : 0xE1)
#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1)
#define usb_pipein(pipe) (((pipe) >> 7) & 1)
#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f)
#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff)
#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf)
......
......@@ -1956,27 +1956,6 @@ static int sync_old_buffers(void)
return 0;
}
struct mm_struct * start_lazy_tlb(void)
{
struct mm_struct *mm = current->mm;
atomic_inc(&mm->mm_count);
current->mm = NULL;
/* active_mm is still 'mm' */
return mm;
}
void end_lazy_tlb(struct mm_struct *mm)
{
struct mm_struct *active_mm = current->active_mm;
current->mm = mm;
if (mm != active_mm) {
current->active_mm = mm;
switch_mm(active_mm, mm);
}
mmdrop(active_mm);
}
/* This is the interface to bdflush. As we get more sophisticated, we can
* pass tuning parameters to this "process", to adjust how it behaves.
* We would want to verify each parameter, however, to make sure that it
......
......@@ -994,9 +994,35 @@
#define PCI_VENDOR_ID_CBOARDS 0x1307
#define PCI_DEVICE_ID_CBOARDS_DAS1602_16 0x0001
#define PCI_VENDOR_ID_SIIG 0x131f
#define PCI_DEVICE_ID_SIIG_1S1P_10x_550 0x1010
#define PCI_DEVICE_ID_SIIG_1S1P_10x_650 0x1011
#define PCI_DEVICE_ID_SIIG_1S1P_10x_850 0x1012
#define PCI_DEVICE_ID_SIIG_1P_10x 0x1020
#define PCI_DEVICE_ID_SIIG_2P_10x 0x1021
#define PCI_DEVICE_ID_SIIG_2S1P_10x_550 0x1034
#define PCI_DEVICE_ID_SIIG_2S1P_10x_650 0x1035
#define PCI_DEVICE_ID_SIIG_2S1P_10x_850 0x1036
#define PCI_DEVICE_ID_SIIG_1P_20x 0x2020
#define PCI_DEVICE_ID_SIIG_2P_20x 0x2021
#define PCI_DEVICE_ID_SIIG_2P1S_20x_550 0x2040
#define PCI_DEVICE_ID_SIIG_2P1S_20x_650 0x2041
#define PCI_DEVICE_ID_SIIG_2P1S_20x_850 0x2042
#define PCI_DEVICE_ID_SIIG_1S1P_20x_550 0x2010
#define PCI_DEVICE_ID_SIIG_1S1P_20x_650 0x2011
#define PCI_DEVICE_ID_SIIG_1S1P_20x_850 0x2012
#define PCI_DEVICE_ID_SIIG_2S1P_20x_550 0x2060
#define PCI_DEVICE_ID_SIIG_2S1P_20x_650 0x2061
#define PCI_DEVICE_ID_SIIG_2S1P_20x_850 0x2062
#define PCI_VENDOR_ID_NETGEAR 0x1385
#define PCI_DEVICE_ID_NETGEAR_GA620 0x620a
#define PCI_VENDOR_ID_LAVA 0x1407
#define PCI_DEVICE_ID_LAVA_PARALLEL 0x8000
#define PCI_DEVICE_ID_LAVA_DUAL_PAR_A 0x8001 /* The Lava Dual Parallel is */
#define PCI_DEVICE_ID_LAVA_DUAL_PAR_B 0x8002 /* two PCI devices on a card */
#define PCI_VENDOR_ID_SYMPHONY 0x1c1c
#define PCI_DEVICE_ID_SYMPHONY_101 0x0001
......
......@@ -617,6 +617,9 @@ extern inline int capable(int cap)
*/
extern struct mm_struct * mm_alloc(void);
extern struct mm_struct * start_lazy_tlb(void);
extern void end_lazy_tlb(struct mm_struct *mm);
/* mmdrop drops the mm and the page tables */
extern inline void FASTCALL(__mmdrop(struct mm_struct *));
static inline void mmdrop(struct mm_struct * mm)
......
......@@ -26,13 +26,17 @@ static void release(struct task_struct * p)
{
if (p != current) {
#ifdef __SMP__
int has_cpu;
/*
* Wait to make sure the process isn't on the
* runqueue (active on some other CPU still)
*/
do {
barrier();
} while (p->has_cpu);
spin_lock_irq(&runqueue_lock);
has_cpu = p->has_cpu;
spin_unlock_irq(&runqueue_lock);
} while (has_cpu);
#endif
free_uid(p);
unhash_process(p);
......@@ -257,6 +261,31 @@ void exit_itimers(struct task_struct *tsk)
__exit_itimers(tsk);
}
/*
* We can use these to temporarily drop into
* "lazy TLB" mode and back.
*/
struct mm_struct * start_lazy_tlb(void)
{
struct mm_struct *mm = current->mm;
current->mm = NULL;
/* active_mm is still 'mm' */
atomic_inc(&mm->mm_count);
return mm;
}
void end_lazy_tlb(struct mm_struct *mm)
{
struct mm_struct *active_mm = current->active_mm;
current->mm = mm;
if (mm != active_mm) {
current->active_mm = mm;
switch_mm(active_mm, mm);
}
mmdrop(active_mm);
}
/*
* Turn us into a lazy TLB process if we
* aren't already..
......@@ -266,12 +295,10 @@ static inline void __exit_mm(struct task_struct * tsk)
struct mm_struct * mm = tsk->mm;
if (mm) {
atomic_inc(&init_mm.mm_count);
atomic_inc(&mm->mm_count);
mm_release();
if (mm != tsk->active_mm) BUG();
tsk->mm = NULL;
tsk->active_mm = &init_mm;
switch_mm(mm, &init_mm);
mmput(mm);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment