From 9521288f8924b87cd20ddf10ede6ed17bbe67392 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:35:01 -0500 Subject: [PATCH] Import 2.3.99pre9-5 --- Documentation/Configure.help | 8 - Documentation/DocBook/parportbook.tmpl | 454 +++++++++++++++++++------ arch/i386/config.in | 1 - arch/i386/kernel/apm.c | 50 ++- drivers/net/setup.c | 15 +- drivers/net/slhc.c | 7 - drivers/parport/ChangeLog | 4 + drivers/usb/pegasus.c | 50 ++- drivers/usb/serial/Makefile | 22 +- drivers/usb/serial/digi_acceleport.c | 4 - drivers/usb/serial/ftdi_sio.c | 6 - drivers/usb/serial/keyspan_pda.c | 4 - drivers/usb/serial/omninet.c | 6 - drivers/usb/serial/usbserial.c | 4 + drivers/usb/serial/visor.c | 7 - drivers/usb/serial/whiteheat.c | 6 - drivers/usb/usb-ohci.c | 154 +++++---- drivers/usb/usb-ohci.h | 2 +- fs/cramfs/inode.c | 56 +-- include/net/slhc.h | 6 - kernel/ksyms.c | 1 + net/core/dev.c | 1 - 22 files changed, 564 insertions(+), 304 deletions(-) delete mode 100644 include/net/slhc.h diff --git a/Documentation/Configure.help b/Documentation/Configure.help index 311a4a4a079e..4d7b936a3d12 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -12468,14 +12468,6 @@ CONFIG_APM_DISPLAY_BLANK backlight at all, or it might print a lot of errors to the console, especially if you are using gpm. -Ignore multiple suspend/standby events -CONFIG_APM_IGNORE_MULTIPLE_SUSPEND - This option is necessary on the IBM Thinkpad 560, but should work on - all other laptops. When the APM BIOS returns multiple suspend or - standby events while one is already being processed they will be - ignored. Without this the Thinkpad 560 has troubles with the user - level daemon apmd, and with the PCMCIA package pcmcia-cs. - Ignore multiple suspend/resume cycles CONFIG_APM_IGNORE_SUSPEND_BOUNCE This option is necessary on the Dell Inspiron 3200 and others, but diff --git a/Documentation/DocBook/parportbook.tmpl b/Documentation/DocBook/parportbook.tmpl index 8d7791df5c8b..bf4d77873c05 100644 --- a/Documentation/DocBook/parportbook.tmpl +++ b/Documentation/DocBook/parportbook.tmpl @@ -62,7 +62,7 @@ The first parallel port support for Linux came with the line - printer driver, lp. The printer driver is a + printer driver, lp. The printer driver is a character special device, and (in Linux 2.0) had support for writing, via write, and configuration and statistics reporting via ioctl. @@ -152,7 +152,7 @@ --> - The parport code in Linux 2.2 was designed to + The parport code in Linux 2.2 was designed to meet these problems of architectural differences in parallel ports, of port-sharing between devices with pass-through ports, and of lack of support for IEEE 1284 transfer modes. @@ -161,7 +161,7 @@ - There are two layers to the parport + There are two layers to the parport subsystem, only one of which deals directly with the hardware. The other layer deals with sharing and IEEE 1284 transfer modes. In this way, parallel support for a particular architecture comes @@ -172,13 +172,13 @@ - The sharing model provided by the parport + The sharing model provided by the parport subsystem is one of exclusive access. A device driver, such as - the printer driver, must ask the parport + the printer driver, must ask the parport layer for access to the port, and can only use the port once access has been granted. When it has finished a transaction, it can tell the - parport layer that it may release the port + parport layer that it may release the port for other device drivers to use. @@ -299,10 +299,10 @@ Sharing core - At the core of the parport subsystem is the + At the core of the parport subsystem is the sharing mechanism (see drivers/parport/share.c). This module, - parport, is responsible for keeping track of + parport, is responsible for keeping track of which ports there are in the system, which device drivers might be interested in new ports, and whether or not each port is available for use (or if not, which driver is currently using it). @@ -314,10 +314,10 @@ Parports and their overrides - The generic parport sharing code doesn't + The generic parport sharing code doesn't directly handle the parallel port hardware. That is done instead - by low-level parport drivers. - The function of a low-level parport driver is + by low-level parport drivers. + The function of a low-level parport driver is to detect parallel ports, register them with the sharing code, and provide a list of access functions for each port. @@ -340,11 +340,11 @@ Stacked on top of the sharing mechanism, but still in the - parport module, are functions for + parport module, are functions for transferring data. They are provided for the device drivers to use, and are very much like library routines. Since these transfer functions are provided by the generic - parport core they must use the lowest + parport core they must use the lowest common denominator set of access functions: they can set the control lines, examine the status lines, and use the data lines. With some parallel ports the data lines can only be set @@ -356,7 +356,7 @@ - The low-level parport drivers also provide + The low-level parport drivers also provide IEEE 1284 transfer functions, as names in the access function list. The low-level driver can just name the generic IEEE 1284 transfer functions for this. Some parallel ports can do IEEE 1284 @@ -373,7 +373,7 @@ When a parallel port device driver (such as - lp) initialises it tells the sharing layer + lp) initialises it tells the sharing layer about itself using parport_register_driver. The information is put into a struct parport_driver, which is put into a linked list. The @@ -441,7 +441,7 @@ the draft specifies the on-the-wire protocol for daisy-chaining and multiplexing, and also suggests a programming interface for using it. That interface (or most of it) has been implemented in - the parport code in Linux. + the parport code in Linux. @@ -494,20 +494,27 @@ parport_device_coords. - + + +#include <parport.h> + + int parport_device_num int parport int mux int daisy - + + - + + int parport_device_coords int devnum int *parport int *mux int *daisy - + + Any parallel port peripheral will be connected directly or @@ -524,18 +531,25 @@ parport_find_class. - + + +#include <parport.h> + + int parport_find_device const char *mfg const char *mdl int from - + + - + + int parport_find_class parport_device_class cls int from - + + These functions take a device number (in addition to some other @@ -572,7 +586,7 @@ This section is written from the point of view of the device driver programmer, who might be writing a driver for a printer or a scanner or else anything that plugs into the parallel port. It - explains how to use the parport interface to + explains how to use the parport interface to find parallel ports, use them, and share them with other device drivers. @@ -585,55 +599,62 @@ The interactions between the device driver and the - parport layer are as follows. First, the + parport layer are as follows. First, the device driver registers its existence with - parport, in order to get told about any + parport, in order to get told about any parallel ports that have been (or will be) detected. When it gets told about a parallel port, it then tells - parport that it wants to drive a device on + parport that it wants to drive a device on that port. Thereafter it can claim exclusive access to the port in order to talk to its device. So, the first thing for the device driver to do is tell - parport that it wants to know what parallel + parport that it wants to know what parallel ports are on the system. To do this, it uses the parport_register_device function: - - + +#include <parport.h> + struct parport_driver { const char *name; void (*attach) (struct parport *); void (*detach) (struct parport *); struct parport_driver *next; }; - ]]> + - + int parport_register_driver struct parport_driver *driver - + + In other words, the device driver passes pointers to a couple of - functions to parport, and - parport calls attach for + functions to parport, and + parport calls attach for each port that's detected (and detach for each port that disappears---yes, this can happen). The next thing that happens is that the device driver tells - parport that it thinks there's a device on the + parport that it thinks there's a device on the port that it can drive. This typically will happen in the driver's attach function, and is done with parport_register_device: - + + +#include <parport.h> + + struct pardevice *parport_register_device struct parport *port const char *name @@ -645,7 +666,8 @@ struct parport_driver { int, void *, struct pt_regs * int flags void *handle - + + The port comes from the parameter supplied @@ -705,7 +727,7 @@ struct parport_driver { The flags are for telling - parport any requirements or hints that are + parport any requirements or hints that are useful. The only useful value here (other than 0, which is the usual value) is PARPORT_DEV_EXCL. The point of that flag is @@ -738,7 +760,11 @@ struct parport_driver { than a pointer to a struct parport. - + + +#include <parport.h> + + struct pardevice *parport_open int devnum int (*pf) @@ -749,14 +775,18 @@ struct parport_driver { int, void *, struct pt_regs * int flags void *handle - + + - + + void parport_close struct pardevice *dev - + + - + + struct pardevice *parport_register_device struct parport *port const char *name @@ -768,12 +798,15 @@ struct parport_driver { int, void *, struct pt_regs * int flags void *handle - + + - + + void parport_unregister_device struct pardevice *dev - + + The intended use of these functions is during driver initialisation @@ -799,20 +832,29 @@ while ((devnum = parport_find_class (PARPORT_CLASS_DIGCAM, port. - + + +#include <parport.h> + + int parport_claim struct pardevice *dev - + + - + + int parport_claim_or_block struct pardevice *dev - + + - + + void parport_release struct pardevice *dev - + + To claim access to the port, use parport_claim @@ -866,15 +908,22 @@ while ((devnum = parport_find_class (PARPORT_CLASS_DIGCAM, a /proc entry. - + + +#include <parport.h> + + int parport_yield struct pardevice *dev - + + - + + int parport_yield_blocking struct pardevice *dev - + + The first of these, parport_yield, will not @@ -919,14 +968,14 @@ port->ops->write_data (port, d); - The device driver registers itself with parport. + The device driver registers itself with parport. A low-level driver finds a parallel port and registers it with - parport (these first two things can happen + parport (these first two things can happen in either order). This registration creates a struct parport which is linked onto a list of known ports. @@ -934,7 +983,7 @@ port->ops->write_data (port, d); - parport calls the + parport calls the attach function of each registered device driver, passing it the pointer to the new struct parport. @@ -944,7 +993,7 @@ port->ops->write_data (port, d); The device driver gets a handle from - parport, for use with + parport, for use with parport_claim/release. This handle takes the form of a pointer to a struct pardevice, representing a particular device on the @@ -993,18 +1042,18 @@ port->ops->write_data (port, d); - The printer driver, lp is a character special - device driver and a parport client. As a + The printer driver, lp is a character special + device driver and a parport client. As a character special device driver it registers a struct file_operations using register_chrdev, with pointers filled in for write, ioctl, open and release. As a client of - parport, it registers a struct + parport, it registers a struct parport_driver using parport_register_driver, so that - parport knows to call + parport knows to call lp_attach when a new parallel port is discovered (and lp_detach when it goes away). @@ -1012,8 +1061,8 @@ port->ops->write_data (port, d); The parallel port console functionality is also implemented in - lp.c, but that won't be covered here (it's - quite simple though). + drivers/char/lp.c, but that won't be covered + here (it's quite simple though). @@ -1037,7 +1086,7 @@ port->ops->write_data (port, d); After successfully registering itself as a character special device driver, the printer driver registers itself as a - parport client using + parport client using parport_register_driver. It passes a pointer to this structure: @@ -1076,14 +1125,14 @@ static struct parport_driver lp_driver = { The other interesting piece of the printer driver, from the point - of view of parport, is + of view of parport, is lp_write. In this function, the user space process has data that it wants printed, and the printer driver - hands it off to the parport code to deal with. + hands it off to the parport code to deal with. - The parport functions it uses that we have not + The parport functions it uses that we have not seen yet are parport_negotiate, parport_set_timeout, and parport_write. These functions are part of @@ -1106,11 +1155,16 @@ static struct parport_driver lp_driver = { parport_negotiate. - + + +#include <parport.h> + + int parport_negotiate struct parport *port int mode - + + The modes parameter is a symbolic constant @@ -1132,7 +1186,7 @@ static struct parport_driver lp_driver = { The main work is done in the write-loop. In particular, the line - that hands the data over to parport reads: + that hands the data over to parport reads: @@ -1147,19 +1201,26 @@ static struct parport_driver lp_driver = { successfully written: - + + +#include <parport.h> + + ssize_t parport_write struct parport *port const void *buf size_t len - + + - + + ssize_t parport_read struct parport *port void *buf size_t len - + + (parport_read does what it sounds like, but @@ -1186,49 +1247,106 @@ struct parport_operations { [...] /* Block read/write */ - size_t (*epp_write_data) (struct parport *port, const void *buf, + size_t (*epp_write_data) (struct parport *port, + const void *buf, size_t len, int flags); - size_t (*epp_read_data) (struct parport *port, void *buf, size_t len, + size_t (*epp_read_data) (struct parport *port, + void *buf, size_t len, int flags); - size_t (*epp_write_addr) (struct parport *port, const void *buf, + size_t (*epp_write_addr) (struct parport *port, + const void *buf, size_t len, int flags); - size_t (*epp_read_addr) (struct parport *port, void *buf, size_t len, + size_t (*epp_read_addr) (struct parport *port, + void *buf, size_t len, int flags); - size_t (*ecp_write_data) (struct parport *port, const void *buf, + size_t (*ecp_write_data) (struct parport *port, + const void *buf, size_t len, int flags); - size_t (*ecp_read_data) (struct parport *port, void *buf, size_t len, + size_t (*ecp_read_data) (struct parport *port, + void *buf, size_t len, int flags); - size_t (*ecp_write_addr) (struct parport *port, const void *buf, + size_t (*ecp_write_addr) (struct parport *port, + const void *buf, size_t len, int flags); - size_t (*compat_write_data) (struct parport *port, const void *buf, + size_t (*compat_write_data) (struct parport *port, + const void *buf, size_t len, int flags); - size_t (*nibble_read_data) (struct parport *port, void *buf, - size_t len, int flags); - size_t (*byte_read_data) (struct parport *port, void *buf, - size_t len, int flags); + size_t (*nibble_read_data) (struct parport *port, + void *buf, size_t len, + int flags); + size_t (*byte_read_data) (struct parport *port, + void *buf, size_t len, + int flags); }; ]]> - The transfer code in parport will tolerate a + The transfer code in parport will tolerate a data transfer stall only for so long, and this timeout can be specified with parport_set_timeout, which returns the previous timeout: - + + +#include <parport.h> + + long parport_set_timeout struct pardevice *dev long inactivity - + + This timeout is specific to the device, and is restored on parport_claim. + + The next function to look at is the one that allows processes to + read from /dev/lp0: + lp_read. It's short, like + lp_write. + + + + The semantics of reading from a line printer device are as follows: + + + + + + Switch to reverse nibble mode. + + + + + + Try to read data from the peripheral using reverse nibble mode, + until either the user-provided buffer is full or the peripheral + indicates that there is no more data. + + + + + + If there was data, stop, and return it. + + + + + + Otherwise, we tried to read data and there was none. If the user + opened the device node with the O_NONBLOCK + flag, return. Otherwise wait until an interrupt occurs on the + port (or a timeout elapses). + + + + @@ -1260,7 +1378,7 @@ struct parport_operations { - In contrast, the ppdev driver (accessed via + In contrast, the ppdev driver (accessed via /dev/parport0) allows you to: @@ -1344,11 +1462,13 @@ struct parport_operations { Programming interface - The ppdev interface is largely the same as - that of other character special devices, in that it supports + The ppdev interface is largely the same as that + of other character special devices, in that it supports open, close, read, write, and - ioctl. + ioctl. The constants for the + ioctl commands are in + include/linux/ppdev.h. @@ -1379,7 +1499,7 @@ struct parport_operations { Most of the control is done, naturally enough, via the ioctl call. Using ioctl, the user-land driver can control both - the ppdev driver in the kernel and the + the ppdev driver in the kernel and the physical parallel port itself. The ioctl call takes as parameters a file descriptor (the one returned from opening the device node), a command, and optionally (a pointer @@ -1395,7 +1515,7 @@ struct parport_operations { writer, you will need to do this before you are able to actually change the state of the parallel port in any way. Note that some operations only affect the - ppdev driver and not the port, such as + ppdev driver and not the port, such as PPSETMODE; they can be performed while access to the port is not claimed. @@ -1486,7 +1606,7 @@ struct parport_operations { The ioctl parameter should be a pointer to an int; values for this are in - parport.h and include: + incluce/linux/parport.h and include: @@ -1566,7 +1686,7 @@ struct parport_operations { Sets the control lines. The ioctl parameter is a pointer to an unsigned char, the bitwise OR of the control line values in - parport.h. + include/linux/parport.h. @@ -1591,7 +1711,7 @@ struct parport_operations { The control lines bits are defined in - parport.h: + include/linux/parport.h: @@ -1619,7 +1739,7 @@ struct parport_operations { course, each driver could remember what state the control lines are supposed to be in (they are never changed by anything else), but in order to provide - PPRCONTROL, ppdev + PPRCONTROL, ppdev must remember the state of the control lines anyway. @@ -1728,7 +1848,7 @@ struct ppdev_frob_struct { - Clears the interrupt count. The ppdev + Clears the interrupt count. The ppdev driver keeps a count of interrupts as they are triggered. PPCLRIRQ stores this count in an int, a pointer to which is passed in as the @@ -1790,7 +1910,7 @@ struct ppdev_frob_struct { select - The ppdev driver provides user-land device + The ppdev driver provides user-land device drivers with the ability to wait for interrupts, and this is done using poll (and select, which is implemented in terms of poll). @@ -1799,7 +1919,7 @@ struct ppdev_frob_struct { When a user-land device driver wants to wait for an interrupt, it sleeps with poll. When the interrupt - arrives, ppdev wakes it up (with a + arrives, ppdev wakes it up (with a read event, although strictly speaking there is nothing to actually read). @@ -1813,7 +1933,7 @@ struct ppdev_frob_struct { Presented here are two demonstrations of how to write a simple - printer driver for ppdev. Firstly we will + printer driver for ppdev. Firstly we will use the write function, and after that we will drive the control and data lines directly. @@ -1998,7 +2118,7 @@ ssize_t write_printer (int fd, const void *ptr, size_t count) ]]> - To show a bit more of the ppdev interface, + To show a bit more of the ppdev interface, here is a small piece of code that is intended to mimic the printer's side of printer protocol. @@ -2048,6 +2168,43 @@ ssize_t write_printer (int fd, const void *ptr, size_t count) } ]]> + + And here is an example (with no error checking at all) to show how + to read data from the port, using ECP mode, with optional + negotiation to ECP mode first. + + + + @@ -2078,6 +2235,85 @@ ssize_t write_printer (int fd, const void *ptr, size_t count) !Fdrivers/parport/ieee1284.c parport_set_timeout + + + + The Linux 2.2 Parallel Port Subsystem + + + + Although the interface described in this document is largely new + with the 2.4 kernel, the sharing mechanism is available in the 2.2 + kernel as well. The functions available in 2.2 are: + + + + + + parport_register_device + + + + + + parport_unregister_device + + + + + + parport_claim + + + + + + parport_claim_or_block + + + + + + parport_release + + + + + + parport_yield + + + + + + parport_yield_blocking + + + + + + In addition, negotiation to reverse nibble mode is supported: + + + + + int parport_ieee1284_nibble_mode_ok + struct parport *port + unsigned char mode + + + + + The only valid values for mode are 0 (for + reverse nibble mode) and 4 (for Device ID in reverse nibble mode). + + + + This function is obsoleted by + parport_negotiate in Linux 2.4, and has been + removed. + + diff --git a/arch/i386/config.in b/arch/i386/config.in index 8f4782ca80f9..1208a6b82a6c 100644 --- a/arch/i386/config.in +++ b/arch/i386/config.in @@ -180,7 +180,6 @@ if [ "$CONFIG_APM" != "n" ]; then bool ' Enable PM at boot time' CONFIG_APM_DO_ENABLE bool ' Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE bool ' Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK - bool ' Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND bool ' Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE bool ' RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT bool ' Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 99e2587565ad..b1e0e8b7c612 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -132,6 +132,9 @@ * 1.13: Changes for new pm_ interfaces (Andy Henroid * ). * Modularize the code. + * Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS + * is now the way life works). + * Fix thinko in suspend() (wrong return). * * APM 1.1 Reference: * @@ -308,9 +311,7 @@ static int clock_slowed = 0; #endif static int suspends_pending = 0; static int standbys_pending = 0; -#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND static int waiting_for_resume = 0; -#endif #ifdef CONFIG_APM_RTC_IS_GMT # define clock_cmos_diff 0 @@ -866,22 +867,22 @@ static void reinit_timer(void) static int suspend(void) { int err; - int ret; struct apm_user *as; get_time_diff(); err = apm_set_power_state(APM_STATE_SUSPEND); reinit_timer(); set_time(); - ret = (err == APM_SUCCESS) || (err == APM_NO_ERROR); - if (!ret) + if (err == APM_NO_ERROR) + err = APM_SUCCESS; + if (err != APM_SUCCESS) apm_error("suspend", err); for (as = user_list; as != NULL; as = as->next) { as->suspend_wait = 0; - as->suspend_result = (ret ? 0 : -EIO); + as->suspend_result = ((err == APM_SUCCESS) ? 0 : -EIO); } wake_up_interruptible(&apm_suspend_waitqueue); - return ret; + return err; } static void standby(void) @@ -962,14 +963,7 @@ static void check_events(void) switch (event) { case APM_SYS_STANDBY: case APM_USER_STANDBY: -#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND - if (waiting_for_resume) - break; -#endif if (send_event(event, NULL)) { -#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND - waiting_for_resume = 1; -#endif if (standbys_pending <= 0) standby(); } @@ -986,14 +980,18 @@ static void check_events(void) if (ignore_bounce) break; #endif -#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND + /* + * If we are already processing a SUSPEND, + * then further SUSPEND events from the BIOS + * will be ignored. We also return here to + * cope with the fact that the Thinkpads keep + * sending a SUSPEND event until something else + * happens! + */ if (waiting_for_resume) - break; -#endif + return; if (send_event(event, NULL)) { -#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND waiting_for_resume = 1; -#endif if (suspends_pending <= 0) (void) suspend(); } @@ -1002,9 +1000,7 @@ static void check_events(void) case APM_NORMAL_RESUME: case APM_CRITICAL_RESUME: case APM_STANDBY_RESUME: -#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND waiting_for_resume = 0; -#endif #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE last_resume = jiffies; ignore_bounce = 1; @@ -1036,8 +1032,10 @@ static void apm_event_handler(void) int err; if ((standbys_pending > 0) || (suspends_pending > 0)) { - if ((apm_bios_info.version > 0x100) && (pending_count-- < 0)) { + if ((apm_bios_info.version > 0x100) && (pending_count-- <= 0)) { pending_count = 4; + if (debug) + printk(KERN_DEBUG "apm: setting state busy\n"); err = apm_set_power_state(APM_STATE_BUSY); if (err) apm_error("busy", err); @@ -1097,7 +1095,7 @@ static void apm_mainloop(void) static int check_apm_user(struct apm_user *as, const char *func) { if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) { - printk(KERN_ERR "apm: %s passed bad filp", func); + printk(KERN_ERR "apm: %s passed bad filp\n", func); return 1; } return 0; @@ -1200,7 +1198,7 @@ static int do_ioctl(struct inode * inode, struct file *filp, } else if (!send_event(APM_USER_SUSPEND, as)) return -EAGAIN; if (suspends_pending <= 0) { - if (!suspend()) + if (suspend() != APM_SUCCESS) return -EIO; } else { as->suspend_wait = 1; @@ -1251,7 +1249,7 @@ static int do_release(struct inode * inode, struct file * filp) as1 = as1->next) ; if (as1 == NULL) - printk(KERN_ERR "apm: filp not in user list"); + printk(KERN_ERR "apm: filp not in user list\n"); else as1->next = as->next; } @@ -1268,7 +1266,7 @@ static int do_open(struct inode * inode, struct file * filp) as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL); if (as == NULL) { - printk(KERN_ERR "apm: cannot allocate struct of size %d bytes", + printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n", sizeof(*as)); MOD_DEC_USE_COUNT; return -ENOMEM; diff --git a/drivers/net/setup.c b/drivers/net/setup.c index a5442e68a794..b4e5da200129 100644 --- a/drivers/net/setup.c +++ b/drivers/net/setup.c @@ -12,7 +12,6 @@ extern int mkiss_init_ctrl_dev(void); extern int slip_init_ctrl_dev(void); extern int strip_init_ctrl_dev(void); extern int x25_asy_init_ctrl_dev(void); -extern int slhc_install(void); extern int dmascc_init(void); extern int yam_init(void); @@ -78,22 +77,12 @@ struct net_probe pci_probes[] __initdata = { #endif #if defined(CONFIG_COMX) {comx_init, 0}, -#endif /* - * SLHC if present needs attaching so other people see it - * even if not opened. - */ +#endif + #if defined(CONFIG_LANMEDIA) {lmc_setup, 0}, #endif -#ifdef CONFIG_INET -#if (defined(CONFIG_SLIP) && defined(CONFIG_SLIP_COMPRESSED)) \ - || defined(CONFIG_PPP) \ - || (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP)) - {slhc_install, 0}, -#endif -#endif - /* * * Wireless non-HAM diff --git a/drivers/net/slhc.c b/drivers/net/slhc.c index ccc8a93d662c..10df972259ca 100644 --- a/drivers/net/slhc.c +++ b/drivers/net/slhc.c @@ -77,7 +77,6 @@ #include #include #include -#include #include #include #include @@ -751,12 +750,6 @@ void cleanup_module(void) return; } -#else /* MODULE */ -int __init slhc_install(void) -{ - return 0; -} - #endif /* MODULE */ #else /* CONFIG_INET */ diff --git a/drivers/parport/ChangeLog b/drivers/parport/ChangeLog index 0d1fd72e6d43..97b7c53c99d9 100644 --- a/drivers/parport/ChangeLog +++ b/drivers/parport/ChangeLog @@ -1,3 +1,7 @@ +2000-05-16 Tim Waugh + + * share.c (parport_claim): Fix SMP race. + 2000-05-15 Gunther Mayer * parport_pc.c (parport_pc_compat_write_block_pio): Check for diff --git a/drivers/usb/pegasus.c b/drivers/usb/pegasus.c index 7f4459d2f0b7..b40a947edc83 100644 --- a/drivers/usb/pegasus.c +++ b/drivers/usb/pegasus.c @@ -16,7 +16,7 @@ #include -static const char *version = __FILE__ ": v0.3.9 2000/04/11 Written by Petko Manolov (petkan@spct.net)\n"; +static const char *version = __FILE__ ": v0.3.12 2000/05/22 (C) 1999-2000 Petko Manolov (petkan@spct.net)\n"; #define PEGASUS_MTU 1500 @@ -24,12 +24,15 @@ static const char *version = __FILE__ ": v0.3.9 2000/04/11 Written by Petko Mano #define SROM_WRITE 0x01 #define SROM_READ 0x02 #define PEGASUS_TX_TIMEOUT (HZ*5) +#define PEGASUS_RESET 1 #define ALIGN(x) x __attribute__((aligned(L1_CACHE_BYTES))) + struct pegasus { struct usb_device *usb; struct net_device *net; struct net_device_stats stats; + int flags; spinlock_t pegasus_lock; struct urb rx_urb, tx_urb, intr_urb; unsigned char ALIGN(rx_buff[PEGASUS_MAX_MTU]); @@ -44,9 +47,11 @@ struct usb_eth_dev { void *private; }; + static int loopback = 0; static int multicast_filter_limit = 32; + MODULE_AUTHOR("Petko Manolov "); MODULE_DESCRIPTION("ADMtek AN986 Pegasus USB Ethernet driver"); MODULE_PARM(loopback, "i"); @@ -98,6 +103,7 @@ static int pegasus_read_phy_word(struct usb_device *dev, __u8 index, __u16 *regd return 1; } + static int pegasus_write_phy_word(struct usb_device *dev, __u8 index, __u16 regdata) { int i; @@ -115,6 +121,7 @@ static int pegasus_write_phy_word(struct usb_device *dev, __u8 index, __u16 regd return 1; } + static int pegasus_rw_srom_word(struct usb_device *dev, __u8 index, __u16 *retdata, __u8 direction) { int i; @@ -134,6 +141,7 @@ static int pegasus_rw_srom_word(struct usb_device *dev, __u8 index, __u16 *retda return 1; } + static int pegasus_get_node_id(struct usb_device *dev, __u8 *id) { int i; @@ -143,6 +151,7 @@ static int pegasus_get_node_id(struct usb_device *dev, __u8 *id) return 0; } + static int pegasus_reset_mac(struct usb_device *dev) { __u8 data = 0x8; @@ -165,6 +174,7 @@ static int pegasus_reset_mac(struct usb_device *dev) return 1; } + static int pegasus_start_net(struct net_device *dev, struct usb_device *usb) { __u16 partmedia, temp; @@ -195,13 +205,14 @@ static int pegasus_start_net(struct net_device *dev, struct usb_device *usb) data[0] = 0xc9; data[1] = (partmedia & 0x100) ? 0x30 : ((partmedia & 0x80) ? 0x10 : 0); - data[2] = (loopback & 1) ? 0x08 : 0x00; + data[2] = (loopback & 1) ? 0x09 : 0x01; pegasus_set_registers(usb, 0, 3, data); return 0; } + static void pegasus_read_bulk(struct urb *urb) { struct pegasus *pegasus = urb->context; @@ -253,15 +264,16 @@ goon: warn("(prb)failed rx_urb %d", res); } + static void pegasus_irq(urb_t *urb) { - if(urb->status) { - __u8 *d = urb->transfer_buffer; - printk("txst0 %x, txst1 %x, rxst %x, rxlst0 %x, rxlst1 %x, wakest %x", - d[0], d[1], d[2], d[3], d[4], d[5]); - } + __u8 *d = urb->transfer_buffer; + + if ( d[0] ) + dbg("txst0=0x%2x", d[0]); } + static void pegasus_write_bulk(struct urb *urb) { struct pegasus *pegasus = urb->context; @@ -280,12 +292,15 @@ static void pegasus_tx_timeout(struct net_device *net) struct pegasus *pegasus = net->priv; warn("%s: Tx timed out. Reseting...", net->name); + usb_unlink_urb(&pegasus->tx_urb); pegasus->stats.tx_errors++; net->trans_start = jiffies; + pegasus->flags |= PEGASUS_RESET; netif_wake_queue(net); } + static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net) { struct pegasus *pegasus = net->priv; @@ -317,11 +332,13 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net) return 0; } + static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev) { return &((struct pegasus *)dev->priv)->stats; } + static int pegasus_open(struct net_device *net) { struct pegasus *pegasus = (struct pegasus *)net->priv; @@ -334,8 +351,10 @@ static int pegasus_open(struct net_device *net) if ((res = usb_submit_urb(&pegasus->rx_urb))) warn("(open)failed rx_urb %d", res); - -/* usb_submit_urb(&pegasus->intr_urb);*/ + + if ((res = usb_submit_urb(&pegasus->intr_urb))) + warn("(open)failed intr_urb %d", res); + netif_start_queue(net); MOD_INC_USE_COUNT; @@ -343,6 +362,7 @@ static int pegasus_open(struct net_device *net) return 0; } + static int pegasus_close(struct net_device *net) { struct pegasus *pegasus = net->priv; @@ -351,13 +371,14 @@ static int pegasus_close(struct net_device *net) usb_unlink_urb(&pegasus->rx_urb); usb_unlink_urb(&pegasus->tx_urb); -/* usb_unlink_urb(&pegasus->intr_urb); */ + usb_unlink_urb(&pegasus->intr_urb); MOD_DEC_USE_COUNT; return 0; } + static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) { __u16 *data = (__u16 *)&rq->ifr_data; @@ -379,6 +400,7 @@ static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) } } + static void pegasus_set_rx_mode(struct net_device *net) { struct pegasus *pegasus = net->priv; @@ -400,6 +422,7 @@ static void pegasus_set_rx_mode(struct net_device *net) netif_wake_queue(net); } + static int check_device_ids( __u16 vendor, __u16 product ) { int i=0; @@ -413,6 +436,7 @@ static int check_device_ids( __u16 vendor, __u16 product ) return -1; } + static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum) { struct net_device *net; @@ -463,7 +487,7 @@ static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum) pegasus->tx_buff, PEGASUS_MAX_MTU, pegasus_write_bulk, pegasus); FILL_INT_URB(&pegasus->intr_urb, dev, usb_rcvintpipe(dev, 3), - pegasus->intr_buff, 8, pegasus_irq, pegasus, 250); + pegasus->intr_buff, 8, pegasus_irq, pegasus, 500); printk(KERN_INFO "%s: %s\n", net->name, usb_dev_id[dev_indx].name); @@ -471,6 +495,7 @@ static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum) return pegasus; } + static void pegasus_disconnect(struct usb_device *dev, void *ptr) { struct pegasus *pegasus = ptr; @@ -487,11 +512,12 @@ static void pegasus_disconnect(struct usb_device *dev, void *ptr) usb_unlink_urb(&pegasus->rx_urb); usb_unlink_urb(&pegasus->tx_urb); -/* usb_unlink_urb(&pegasus->intr_urb);*/ + usb_unlink_urb(&pegasus->intr_urb); kfree(pegasus); } + static struct usb_driver pegasus_driver = { name: "pegasus", probe: pegasus_probe, diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index fa69fa52aa0a..7d24c34f915f 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -4,8 +4,26 @@ O_TARGET := usb-serial.o M_OBJS := usb-serial.o -O_OBJS := usbserial.o visor.o whiteheat.o ftdi_sio.o keyspan_pda.o omninet.o digi_acceleport.o +O_OBJS := usbserial.o MOD_LIST_NAME := USB_SERIAL_MODULES +ifeq ($(CONFIG_USB_SERIAL_VISOR),y) + O_OBJS += visor.o +endif +ifeq ($(CONFIG_USB_SERIAL_WHITEHEAT),y) + O_OBJS += whiteheat.o +endif +ifeq ($(CONFIG_USB_SERIAL_FTDI_SIO),y) + O_OBJS += ftdi_sio.o +endif +ifeq ($(CONFIG_USB_SERIAL_KEYSPAN_PDA),y) + O_OBJS += keyspan_pda.o +endif +ifeq ($(CONFIG_USB_SERIAL_OMNINET),y) + O_OBJS += omninet.o +endif +ifeq ($(CONFIG_USB_SERIAL_DIGI_ACCELEPORT),y) + O_OBJS += digi_acceleport.o +endif + include $(TOPDIR)/Rules.make - diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 618898b0c40d..fe2d2013b325 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -47,9 +47,6 @@ */ #include - -#ifdef CONFIG_USB_SERIAL_DIGI_ACCELEPORT - #include #include #include @@ -1276,4 +1273,3 @@ resubmit: } -#endif /* CONFIG_USB_SERIAL_DIGI_ACCELEPORT */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index cdad3cabe3b7..8aec735697bc 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -32,9 +32,6 @@ #include - -#ifdef CONFIG_USB_SERIAL_FTDI_SIO - #include #include #include @@ -723,6 +720,3 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns return 0; } /* ftdi_sio_ioctl */ -#endif /* CONFIG_USB_SERIAL_FTDI_SIO */ - - diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index f91e1b592a45..c18137ffa39a 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -18,9 +18,6 @@ #include - -#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA - #include #include #include @@ -700,4 +697,3 @@ struct usb_serial_device_type keyspan_pda_device = { shutdown: keyspan_pda_shutdown, }; -#endif /* CONFIG_USB_SERIAL_KEYSPAN_PDA */ diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 9eb6767f08f1..2e5e50849f14 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -13,9 +13,6 @@ */ #include - -#ifdef CONFIG_USB_SERIAL_OMNINET - #include #include #include @@ -336,6 +333,3 @@ static void omninet_write_bulk_callback (struct urb *urb) return; } -#endif /* CONFIG_USB_SERIAL_OMNINET */ - - diff --git a/drivers/usb/serial/usbserial.c b/drivers/usb/serial/usbserial.c index 9fe65ae8dcf9..b2e18bd8eb94 100644 --- a/drivers/usb/serial/usbserial.c +++ b/drivers/usb/serial/usbserial.c @@ -14,6 +14,10 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (05/22/2000) gkh + * Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be + * removed from the individual device source files. + * * (05/03/2000) gkh * Added the Digi Acceleport driver from Al Borchers and Peter Berger. * diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 979a56f01194..5cfb4c42ab5c 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -20,9 +20,6 @@ */ #include - -#ifdef CONFIG_USB_SERIAL_VISOR - #include #include #include @@ -207,7 +204,3 @@ static int visor_startup (struct usb_serial *serial) return (0); } - -#endif /* CONFIG_USB_SERIAL_VISOR*/ - - diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 58f761fbfe1f..c168efa02dfe 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -21,9 +21,6 @@ */ #include - -#ifdef CONFIG_USB_SERIAL_WHITEHEAT - #include #include #include @@ -407,6 +404,3 @@ static void whiteheat_shutdown (struct usb_serial *serial) return; } -#endif /* CONFIG_USB_SERIAL_WHITEHEAT */ - - diff --git a/drivers/usb/usb-ohci.c b/drivers/usb/usb-ohci.c index ebe22a9d3019..a37e805f0f01 100644 --- a/drivers/usb/usb-ohci.c +++ b/drivers/usb/usb-ohci.c @@ -92,7 +92,6 @@ static void urb_rm_priv (urb_t * urb) kfree (urb->hcpriv); urb->hcpriv = NULL; - wake_up (&op_wakeup); } /*-------------------------------------------------------------------------*/ @@ -493,6 +492,8 @@ static int sohci_submit_urb (urb_t * urb) urb->start_frame = ((ed->state == ED_OPER)? (ed->last_iso + 1): (le16_to_cpu (ohci->hcca.frame_no) + 10)) & 0xffff; } + urb->status = USB_ST_URB_PENDING; + urb->actual_length = 0; if (ed->state != ED_OPER) /* link the ed into a chain if is not already */ ep_link (ohci, ed); @@ -527,6 +528,8 @@ static int sohci_unlink_urb (urb_t * urb) urb_print (urb, "UNLINK", 1); #endif + usb_dec_dev_use (urb->dev); + if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) return rh_unlink_urb (urb); /* a request to the virtual root hub */ @@ -544,19 +547,23 @@ static int sohci_unlink_urb (urb_t * urb) ep_rm_ed (urb->dev, urb_priv->ed); urb_priv->ed->state |= ED_URB_DEL; spin_unlock_irqrestore (&usb_ed_lock, flags); - - add_wait_queue (&op_wakeup, &wait); - current->state = TASK_UNINTERRUPTIBLE; - if (!schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */ - err("unlink URB timeout!"); - remove_wait_queue (&op_wakeup, &wait); - } else + if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) { + add_wait_queue (&op_wakeup, &wait); + current->state = TASK_UNINTERRUPTIBLE; + if (!schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */ + err("unlink URB timeout!"); + remove_wait_queue (&op_wakeup, &wait); + urb->status = -ENOENT; + } else + urb->status = -EINPROGRESS; + } else { urb_rm_priv (urb); - - urb->status = -ENOENT; // mark urb as killed - if (urb->complete) - urb->complete ((struct urb *) urb); - usb_dec_dev_use (urb->dev); + if (urb->complete && (urb->transfer_flags & USB_ASYNC_UNLINK)) { + urb->complete (urb); + urb->status = 0; + } else + urb->status = -ENOENT; + } } return 0; } @@ -965,7 +972,7 @@ static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed) /* prepare a TD */ -static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int type, int index) +static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int index) { volatile td_t * td, * td_pt; urb_priv_t * urb_priv = urb->hcpriv; @@ -982,7 +989,6 @@ static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int t td->index = index; td->urb = urb; td->hwINFO = cpu_to_le32 (info); - td->type = type; if ((td->ed->type & 3) == PIPE_ISOCHRONOUS) { td->hwCBP = cpu_to_le32 (((!data || !len)? 0 : virt_to_bus (data)) & 0xFFFFF000); @@ -1029,12 +1035,12 @@ static void td_submit_urb (urb_t * urb) info = usb_pipeout (urb->pipe)? TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; while(data_len > 4096) { - td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); + td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, cnt); data += 4096; data_len -= 4096; cnt++; } info = usb_pipeout (urb->pipe)? TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; - td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); + td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt); cnt++; writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ break; @@ -1042,20 +1048,20 @@ static void td_submit_urb (urb_t * urb) case PIPE_INTERRUPT: info = usb_pipeout (urb->pipe)? TD_CC | TD_DP_OUT | toggle: TD_CC | TD_R | TD_DP_IN | toggle; - td_fill (info, data, data_len, urb, ST_ADDR | ADD_LEN, cnt++); + td_fill (info, data, data_len, urb, cnt++); break; case PIPE_CONTROL: info = TD_CC | TD_DP_SETUP | TD_T_DATA0; - td_fill (info, ctrl, 8, urb, ST_ADDR, cnt++); + td_fill (info, ctrl, 8, urb, cnt++); if (data_len > 0) { info = usb_pipeout (urb->pipe)? TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; - td_fill (info, data, data_len, urb, ADD_LEN, cnt++); + td_fill (info, data, data_len, urb, cnt++); } info = usb_pipeout (urb->pipe)? TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; - td_fill (info, NULL, 0, urb, 0, cnt++); + td_fill (info, NULL, 0, urb, cnt++); writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ break; @@ -1063,7 +1069,7 @@ static void td_submit_urb (urb_t * urb) for (cnt = 0; cnt < urb->number_of_packets; cnt++) { td_fill (TD_CC|TD_ISO | ((urb->start_frame + cnt) & 0xffff), (__u8 *) data + urb->iso_frame_desc[cnt].offset, - urb->iso_frame_desc[cnt].length, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); + urb->iso_frame_desc[cnt].length, urb, cnt); } break; } @@ -1074,7 +1080,55 @@ static void td_submit_urb (urb_t * urb) /*-------------------------------------------------------------------------* * Done List handling functions *-------------------------------------------------------------------------*/ - + + +/* calculate the transfer length and update the urb */ + +static void dl_transfer_length(td_t * td) +{ + __u32 tdINFO, tdBE, tdCBP; + __u16 tdPSW; + urb_t * urb = td->urb; + urb_priv_t * urb_priv = urb->hcpriv; + int dlen = 0; + int cc = 0; + + tdINFO = le32_to_cpup (&td->hwINFO); + tdBE = le32_to_cpup (&td->hwBE); + tdCBP = le32_to_cpup (&td->hwCBP); + + + if (tdINFO & TD_ISO) { + tdPSW = le16_to_cpu (td->hwPSW[0]); + cc = (tdPSW >> 12) & 0xF; + if (cc < 0xE) { + if (usb_pipeout(urb->pipe)) { + dlen = urb->iso_frame_desc[td->index].length; + } else { + dlen = tdPSW & 0x3ff; + } + urb->actual_length += dlen; + urb->iso_frame_desc[td->index].actual_length = dlen; + if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN)) + cc = TD_CC_NOERROR; + + urb->iso_frame_desc[td->index].status = cc_to_error[cc]; + } + } else { /* BULK, INT, CONTROL DATA */ + if (!(usb_pipetype (urb->pipe) == PIPE_CONTROL && + ((td->index == 0) || (td->index == urb_priv->length - 1)))) { + if (tdBE != 0) { + if (td->hwCBP == 0) + urb->actual_length = bus_to_virt (tdBE) - urb->transfer_buffer + 1; + else + urb->actual_length = bus_to_virt (tdCBP) - urb->transfer_buffer; + } + } + } +} + +/*-------------------------------------------------------------------------*/ + /* replies to the request have to be on a FIFO basis so * we reverse the reversed done-list */ @@ -1128,6 +1182,7 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame) unsigned long flags; ed_t * ed; __u32 edINFO; + __u32 tdINFO; td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP; __u32 * td_p; int ctrl = 0, bulk = 0; @@ -1139,16 +1194,25 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame) tdHeadP = bus_to_virt (le32_to_cpup (&ed->hwHeadP) & 0xfffffff0); edINFO = le32_to_cpup (&ed->hwINFO); td_p = &ed->hwHeadP; - + for (td = tdHeadP; td != tdTailP; td = td_next) { urb_t * urb = td->urb; urb_priv_t * urb_priv = td->urb->hcpriv; td_next = bus_to_virt (le32_to_cpup (&td->hwNextTD) & 0xfffffff0); if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) { + tdINFO = le32_to_cpup (&td->hwINFO); + if (TD_CC_GET (tdINFO) < 0xE) dl_transfer_length (td); *td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3)); if(++ (urb_priv->td_cnt) == urb_priv->length) urb_rm_priv (urb); + if (urb->transfer_flags & USB_ASYNC_UNLINK) { + usb_dec_dev_use (urb->dev); + urb->status = -ECONNRESET; + urb->complete (urb); + } else { + wake_up (&op_wakeup); + } } else { td_p = &td->hwNextTD; } @@ -1165,7 +1229,7 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame) } else { ed->state &= ~ED_URB_DEL; - ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP); + ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP); } if ((ed->type & 3) == CTRL) ctrl |= 1; @@ -1183,6 +1247,8 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame) spin_unlock_irqrestore (&usb_ed_lock, flags); } + + /*-------------------------------------------------------------------------*/ /* td done list */ @@ -1191,12 +1257,11 @@ static void dl_done_list (ohci_t * ohci, td_t * td_list) { td_t * td_list_next = NULL; ed_t * ed; - int dlen = 0; int cc = 0; urb_t * urb; urb_priv_t * urb_priv; - __u32 tdINFO, tdBE, tdCBP, edHeadP, edTailP; - __u16 tdPSW; + __u32 tdINFO, edHeadP, edTailP; + unsigned long flags; while (td_list) { @@ -1205,40 +1270,11 @@ static void dl_done_list (ohci_t * ohci, td_t * td_list) urb = td_list->urb; urb_priv = urb->hcpriv; tdINFO = le32_to_cpup (&td_list->hwINFO); - tdBE = le32_to_cpup (&td_list->hwBE); - tdCBP = le32_to_cpup (&td_list->hwCBP); ed = td_list->ed; - if (td_list->type & ST_ADDR) - urb->actual_length = 0; - - if (td_list->type & ADD_LEN) { /* accumulate length of multi td transfers */ - if (tdINFO & TD_ISO) { - tdPSW = le16_to_cpu (td_list->hwPSW[0]); - cc = (tdPSW >> 12) & 0xF; - if (cc < 0xE) { - if (usb_pipeout(urb->pipe)) { - dlen = urb->iso_frame_desc[td_list->index].length; - } else { - dlen = tdPSW & 0x3ff; - } - urb->actual_length += dlen; - urb->iso_frame_desc[td_list->index].actual_length = dlen; - if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN)) - cc = TD_CC_NOERROR; - - urb->iso_frame_desc[td_list->index].status = cc_to_error[cc]; - } - } else { - if (tdBE != 0) { - if (td_list->hwCBP == 0) - urb->actual_length = bus_to_virt (tdBE) - urb->transfer_buffer + 1; - else - urb->actual_length = bus_to_virt (tdCBP) - urb->transfer_buffer; - } - } - } + dl_transfer_length(td_list); + /* error code of transfer */ cc = TD_CC_GET (tdINFO); if( cc == TD_CC_STALL) usb_endpoint_halt(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); diff --git a/drivers/usb/usb-ohci.h b/drivers/usb/usb-ohci.h index e854e0c1d3d1..3ac5dafb24cb 100644 --- a/drivers/usb/usb-ohci.h +++ b/drivers/usb/usb-ohci.h @@ -432,7 +432,7 @@ static int ep_unlink(ohci_t * ohci, ed_t * ed); static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load); static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed); /* td */ -static void td_fill(unsigned int info, void * data, int len, urb_t * urb, int type, int index); +static void td_fill(unsigned int info, void * data, int len, urb_t * urb, int index); static void td_submit_urb(urb_t * urb); /* root hub */ static int rh_submit_urb(urb_t * urb); diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 279b0bfef762..550b54295432 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -84,15 +84,17 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod #define NEXT_BUFFER(_ix) ((_ix) ^ 1) /* - * BLKS_PER_BUF_SHIFT must be at least 1 to allow for "compressed" - * data that takes up more space than the original. 1 is guaranteed - * to suffice, though. Larger values provide more read-ahead and - * proportionally less wastage at the end of the buffer. + * BLKS_PER_BUF_SHIFT should be at least 2 to allow for "compressed" + * data that takes up more space than the original and with unlucky + * alignment. */ -#define BLKS_PER_BUF_SHIFT (2) -#define BLKS_PER_BUF (1 << BLKS_PER_BUF_SHIFT) -static unsigned char read_buffers[READ_BUFFERS][BLKS_PER_BUF][PAGE_CACHE_SIZE]; +#define BLKS_PER_BUF_SHIFT (2) +#define BLKS_PER_BUF (1 << BLKS_PER_BUF_SHIFT) +#define BUFFER_SIZE (BLKS_PER_BUF*PAGE_CACHE_SIZE) + +static unsigned char read_buffers[READ_BUFFERS][BUFFER_SIZE]; static unsigned buffer_blocknr[READ_BUFFERS]; +static struct super_block * buffer_dev[READ_BUFFERS]; static int next_buffer = 0; /* @@ -102,19 +104,27 @@ static int next_buffer = 0; static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len) { struct buffer_head * bh_array[BLKS_PER_BUF]; - unsigned i, blocknr, last_blocknr, buffer; + unsigned i, blocknr, buffer; + char *data; if (!len) return NULL; blocknr = offset >> PAGE_CACHE_SHIFT; - last_blocknr = (offset + len - 1) >> PAGE_CACHE_SHIFT; - if (last_blocknr - blocknr >= BLKS_PER_BUF) - goto eek; resume: offset &= PAGE_CACHE_SIZE - 1; + + /* Check if an existing buffer already has the data.. */ for (i = 0; i < READ_BUFFERS; i++) { - if ((blocknr >= buffer_blocknr[i]) && - (last_blocknr - buffer_blocknr[i] < BLKS_PER_BUF)) - return &read_buffers[i][blocknr - buffer_blocknr[i]][offset]; + unsigned int blk_offset; + + if (buffer_dev[i] != sb) + continue; + if (blocknr < buffer_blocknr[i]) + continue; + blk_offset = (blocknr - buffer_blocknr[i]) << PAGE_CACHE_SHIFT; + blk_offset += offset; + if (blk_offset + len > BUFFER_SIZE) + continue; + return read_buffers[i] + blk_offset; } /* Ok, read in BLKS_PER_BUF pages completely first. */ @@ -125,24 +135,18 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i buffer = next_buffer; next_buffer = NEXT_BUFFER(buffer); buffer_blocknr[buffer] = blocknr; + buffer_dev[buffer] = sb; + data = read_buffers[buffer]; for (i = 0; i < BLKS_PER_BUF; i++) { struct buffer_head * bh = bh_array[i]; if (bh) { - memcpy(read_buffers[buffer][i], bh->b_data, PAGE_CACHE_SIZE); + memcpy(data, bh->b_data, PAGE_CACHE_SIZE); bforget(bh); } else - memset(read_buffers[buffer][i], 0, PAGE_CACHE_SIZE); + memset(data, 0, PAGE_CACHE_SIZE); + data += PAGE_CACHE_SIZE; } - return read_buffers[buffer][0] + offset; - - eek: - printk(KERN_ERR - "cramfs (device %s): requested chunk (%u:+%u) bigger than buffer\n", - bdevname(sb->s_dev), offset, len); - /* TODO: return EIO to process or kill the current process - instead of resuming. */ - *((int *)0) = 0; /* XXX: doesn't work on all archs */ - goto resume; + return read_buffers[buffer] + offset; } diff --git a/include/net/slhc.h b/include/net/slhc.h deleted file mode 100644 index c7b39db5560b..000000000000 --- a/include/net/slhc.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __NET_SLHC_H -#define __NET_SLHC_H - -extern void slhc_install(void); - -#endif diff --git a/kernel/ksyms.c b/kernel/ksyms.c index d5660d90c7cb..597d292f5fb1 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -118,6 +118,7 @@ EXPORT_SYMBOL(kfree); EXPORT_SYMBOL(kfree_s); EXPORT_SYMBOL(vmalloc); EXPORT_SYMBOL(vfree); +EXPORT_SYMBOL(__vmalloc); EXPORT_SYMBOL(mem_map); EXPORT_SYMBOL(remap_page_range); EXPORT_SYMBOL(max_mapnr); diff --git a/net/core/dev.c b/net/core/dev.c index ff5ff69dd712..bd3670a93c14 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -79,7 +79,6 @@ #include #include #include -#include #include #include #include -- 2.39.5