Commit 9910fd91 authored by Linus Torvalds's avatar Linus Torvalds

v2.4.0.7 -> v2.4.0.8

  - USB hotplug updates/fixes
  - boots on real i386 machines
  - fix n_tty "canon" mode SMP race
  - FAT fat_cache SMP race fix
parent 3175e85b
...@@ -2625,13 +2625,14 @@ CONFIG_HOTPLUG ...@@ -2625,13 +2625,14 @@ CONFIG_HOTPLUG
One well known example of this is PCMCIA- or PC-cards, credit-card One well known example of this is PCMCIA- or PC-cards, credit-card
size devices such as network cards, modems or hard drives which are size devices such as network cards, modems or hard drives which are
plugged into slots found on all modern laptop computers. plugged into slots found on all modern laptop computers. Another
example, used on modern desktops as well as laptops, is USB.
Another example, used on modern desktops as well as laptops, is USB.
Enable HOTPLUG with USB and KMOD, and your kernel will automatically Enable HOTPLUG and KMOD, and build a modular kernel. Get agent
call out to a user mode "policy agent" to load modules and set up software (at http://linux-hotplug.sourceforge.net) and install it.
software needed to use USB devices you plug in. Get agent software Then your kernel will automatically call out to a user mode "policy
(at http://www.linux-usb.org/policy.html) and install it. agent" (/sbin/hotplug) to load modules and set up software needed
to use devices as you hotplug them.
PCMCIA/Cardbus support PCMCIA/Cardbus support
CONFIG_PCMCIA CONFIG_PCMCIA
......
USB HOTPLUGGING LINUX HOTPLUGGING
In hotpluggable busses like USB (and Cardbus PCI), end-users plug devices In hotpluggable busses like USB (and Cardbus PCI), end-users plug devices
into the bus with power on. In most cases, users expect the devices to become into the bus with power on. In most cases, users expect the devices to become
...@@ -8,7 +8,7 @@ immediately usable. That means the system must do many things, including: ...@@ -8,7 +8,7 @@ immediately usable. That means the system must do many things, including:
loading a kernel module; newer drivers can use modutils to loading a kernel module; newer drivers can use modutils to
publish their device (and class) support to user utilities. publish their device (and class) support to user utilities.
- Bind a driver to that device. That's done using the USB - Bind a driver to that device. Bus frameworks do that using a
device driver's probe() routine. device driver's probe() routine.
- Tell other subsystems to configure the new device. Print - Tell other subsystems to configure the new device. Print
...@@ -26,6 +26,10 @@ Those triggered actions must support a system's administrative policies; ...@@ -26,6 +26,10 @@ Those triggered actions must support a system's administrative policies;
such programs are called "policy agents" here. Typically they involve such programs are called "policy agents" here. Typically they involve
shell scripts that dispatch to more familiar administration tools. shell scripts that dispatch to more familiar administration tools.
Because some of those actions rely on information about drivers (metadata)
that is currently available only when the drivers are dynamically linked,
you get the best hotplugging when you configure a highly modular system.
KERNEL HOTPLUG HELPER (/sbin/hotplug) KERNEL HOTPLUG HELPER (/sbin/hotplug)
...@@ -40,9 +44,14 @@ some kernel event. That name is used as the first key for further event ...@@ -40,9 +44,14 @@ some kernel event. That name is used as the first key for further event
dispatch; any other argument and environment parameters are specified by dispatch; any other argument and environment parameters are specified by
the subsystem making that invocation. the subsystem making that invocation.
A reference implementation of a /sbin/hotplug script is available at the Hotplug software and other resources is available at:
http://www.linux-usb.org website, which works USB for but also knows how to
delegate to any /etc/hotplug/$TYPE.agent policy agent present. http://linux-hotplug.sourceforge.net
Mailing list information is also available at that site.
--------------------------------------------------------------------------
USB POLICY AGENT USB POLICY AGENT
......
...@@ -223,7 +223,7 @@ Generic Serial driver ...@@ -223,7 +223,7 @@ Generic Serial driver
To enable the generic driver to recognize your device, build the driver To enable the generic driver to recognize your device, build the driver
as a module and load it by the following invocation: as a module and load it by the following invocation:
insmod usb-serial vendor=0x#### product=0x#### insmod usbserial vendor=0x#### product=0x####
where the #### is replaced with the hex representation of your device's where the #### is replaced with the hex representation of your device's
vendor id and product id. vendor id and product id.
......
VERSION = 2 VERSION = 2
PATCHLEVEL = 4 PATCHLEVEL = 4
SUBLEVEL = 1 SUBLEVEL = 1
EXTRAVERSION =-pre7 EXTRAVERSION =-pre8
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
......
...@@ -86,6 +86,15 @@ static inline void free_buf(unsigned char *buf) ...@@ -86,6 +86,15 @@ static inline void free_buf(unsigned char *buf)
free_page((unsigned long) buf); free_page((unsigned long) buf);
} }
static inline void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty)
{
if (tty->read_cnt < N_TTY_BUF_SIZE) {
tty->read_buf[tty->read_head] = c;
tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
tty->read_cnt++;
}
}
static inline void put_tty_queue(unsigned char c, struct tty_struct *tty) static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
{ {
unsigned long flags; unsigned long flags;
...@@ -94,11 +103,7 @@ static inline void put_tty_queue(unsigned char c, struct tty_struct *tty) ...@@ -94,11 +103,7 @@ static inline void put_tty_queue(unsigned char c, struct tty_struct *tty)
* Why didn't anyone see this one comming? --AJK * Why didn't anyone see this one comming? --AJK
*/ */
spin_lock_irqsave(&tty->read_lock, flags); spin_lock_irqsave(&tty->read_lock, flags);
if (tty->read_cnt < N_TTY_BUF_SIZE) { put_tty_queue_nolock(c, tty);
tty->read_buf[tty->read_head] = c;
tty->read_head = (tty->read_head + 1) & (N_TTY_BUF_SIZE-1);
tty->read_cnt++;
}
spin_unlock_irqrestore(&tty->read_lock, flags); spin_unlock_irqrestore(&tty->read_lock, flags);
} }
...@@ -499,6 +504,8 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty, ...@@ -499,6 +504,8 @@ static inline void n_tty_receive_parity_error(struct tty_struct *tty,
static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
{ {
unsigned long flags;
if (tty->raw) { if (tty->raw) {
put_tty_queue(c, tty); put_tty_queue(c, tty);
return; return;
...@@ -651,10 +658,12 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) ...@@ -651,10 +658,12 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
put_tty_queue(c, tty); put_tty_queue(c, tty);
handle_newline: handle_newline:
spin_lock_irqsave(&tty->read_lock, flags);
set_bit(tty->read_head, &tty->read_flags); set_bit(tty->read_head, &tty->read_flags);
put_tty_queue(c, tty); put_tty_queue_nolock(c, tty);
tty->canon_head = tty->read_head; tty->canon_head = tty->read_head;
tty->canon_data++; tty->canon_data++;
spin_unlock_irqrestore(&tty->read_lock, flags);
kill_fasync(&tty->fasync, SIGIO, POLL_IN); kill_fasync(&tty->fasync, SIGIO, POLL_IN);
if (waitqueue_active(&tty->read_wait)) if (waitqueue_active(&tty->read_wait))
wake_up_interruptible(&tty->read_wait); wake_up_interruptible(&tty->read_wait);
...@@ -1055,12 +1064,6 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file, ...@@ -1055,12 +1064,6 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file,
tty->read_tail = ((tty->read_tail+1) & tty->read_tail = ((tty->read_tail+1) &
(N_TTY_BUF_SIZE-1)); (N_TTY_BUF_SIZE-1));
tty->read_cnt--; tty->read_cnt--;
spin_unlock_irqrestore(&tty->read_lock, flags);
if (!eol || (c != __DISABLED_CHAR)) {
put_user(c, b++);
nr--;
}
if (eol) { if (eol) {
/* this test should be redundant: /* this test should be redundant:
* we shouldn't be reading data if * we shouldn't be reading data if
...@@ -1068,8 +1071,15 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file, ...@@ -1068,8 +1071,15 @@ static ssize_t read_chan(struct tty_struct *tty, struct file *file,
*/ */
if (--tty->canon_data < 0) if (--tty->canon_data < 0)
tty->canon_data = 0; tty->canon_data = 0;
break;
} }
spin_unlock_irqrestore(&tty->read_lock, flags);
if (!eol || (c != __DISABLED_CHAR)) {
put_user(c, b++);
nr--;
}
if (eol)
break;
} }
} else { } else {
int uncopied; int uncopied;
......
...@@ -247,6 +247,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -247,6 +247,7 @@ ioctl_rio(struct inode *inode, struct file *file, unsigned int cmd,
return 0; return 0;
err_out: err_out:
up(&(rio->lock));
return retval; return retval;
} }
...@@ -389,7 +390,7 @@ read_rio(struct file *file, char *buffer, size_t count, loff_t * ppos) ...@@ -389,7 +390,7 @@ read_rio(struct file *file, char *buffer, size_t count, loff_t * ppos)
result, partial, this_read); result, partial, this_read);
return -EIO; return -EIO;
} else { } else {
unlock_kernel(); up(&(rio->lock));
return (0); return (0);
} }
......
...@@ -22,6 +22,7 @@ if [ "$CONFIG_USB_SERIAL" != "n" ]; then ...@@ -22,6 +22,7 @@ if [ "$CONFIG_USB_SERIAL" != "n" ]; then
bool ' USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19 bool ' USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19
bool ' USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X bool ' USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X
bool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W bool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W
bool ' USB Keyspan USA-49W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA49W
fi fi
dep_tristate ' USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL
......
...@@ -15,7 +15,13 @@ ...@@ -15,7 +15,13 @@
* *
* See Documentation/usb/usb-serial.txt for more information on using this driver * See Documentation/usb/usb-serial.txt for more information on using this driver
* *
* (12/29/2000) gkh * (12/12/2000) gkh
* Removed MOD_INC and MOD_DEC from poll and disconnect functions, and
* moved them to the serial_open and serial_close functions.
* Also fixed bug with there not being a MOD_DEC for the generic driver
* (thanks to Gary Brubaker for finding this.)
*
* (11/29/2000) gkh
* Small NULL pointer initialization cleanup which saves a bit of disk image * Small NULL pointer initialization cleanup which saves a bit of disk image
* *
* (11/01/2000) Adam J. Richter * (11/01/2000) Adam J. Richter
...@@ -471,6 +477,8 @@ static int serial_open (struct tty_struct *tty, struct file * filp) ...@@ -471,6 +477,8 @@ static int serial_open (struct tty_struct *tty, struct file * filp)
return -ENODEV; return -ENODEV;
} }
MOD_INC_USE_COUNT;
/* set up our port structure making the tty driver remember our port object, and us it */ /* set up our port structure making the tty driver remember our port object, and us it */
portNumber = MINOR(tty->device) - serial->minor; portNumber = MINOR(tty->device) - serial->minor;
port = &serial->port[portNumber]; port = &serial->port[portNumber];
...@@ -508,6 +516,8 @@ static void serial_close(struct tty_struct *tty, struct file * filp) ...@@ -508,6 +516,8 @@ static void serial_close(struct tty_struct *tty, struct file * filp)
} else { } else {
generic_close(port, filp); generic_close(port, filp);
} }
MOD_DEC_USE_COUNT;
} }
...@@ -721,12 +731,13 @@ static int generic_open (struct usb_serial_port *port, struct file *filp) ...@@ -721,12 +731,13 @@ static int generic_open (struct usb_serial_port *port, struct file *filp)
if (port_paranoia_check (port, __FUNCTION__)) if (port_paranoia_check (port, __FUNCTION__))
return -ENODEV; return -ENODEV;
MOD_INC_USE_COUNT;
dbg(__FUNCTION__ " - port %d", port->number); dbg(__FUNCTION__ " - port %d", port->number);
spin_lock_irqsave (&port->port_lock, flags); spin_lock_irqsave (&port->port_lock, flags);
++port->open_count; ++port->open_count;
MOD_INC_USE_COUNT;
if (!port->active) { if (!port->active) {
port->active = 1; port->active = 1;
...@@ -776,6 +787,7 @@ static void generic_close (struct usb_serial_port *port, struct file * filp) ...@@ -776,6 +787,7 @@ static void generic_close (struct usb_serial_port *port, struct file * filp)
} }
spin_unlock_irqrestore (&port->port_lock, flags); spin_unlock_irqrestore (&port->port_lock, flags);
MOD_DEC_USE_COUNT;
} }
...@@ -1069,7 +1081,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1069,7 +1081,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
} }
/* found all that we need */ /* found all that we need */
MOD_INC_USE_COUNT;
info("%s converter detected", type->name); info("%s converter detected", type->name);
#ifdef CONFIG_USB_SERIAL_GENERIC #ifdef CONFIG_USB_SERIAL_GENERIC
...@@ -1077,7 +1088,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1077,7 +1088,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
num_ports = num_bulk_out; num_ports = num_bulk_out;
if (num_ports == 0) { if (num_ports == 0) {
err("Generic device with no bulk out, not allowed."); err("Generic device with no bulk out, not allowed.");
MOD_DEC_USE_COUNT;
return NULL; return NULL;
} }
} else } else
...@@ -1087,7 +1097,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1087,7 +1097,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
serial = get_free_serial (num_ports, &minor); serial = get_free_serial (num_ports, &minor);
if (serial == NULL) { if (serial == NULL) {
err("No more free serial devices"); err("No more free serial devices");
MOD_DEC_USE_COUNT;
return NULL; return NULL;
} }
...@@ -1233,7 +1242,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum, ...@@ -1233,7 +1242,6 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum,
/* free up any memory that we allocated */ /* free up any memory that we allocated */
kfree (serial); kfree (serial);
MOD_DEC_USE_COUNT;
return NULL; return NULL;
} }
...@@ -1300,7 +1308,6 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr) ...@@ -1300,7 +1308,6 @@ static void usb_serial_disconnect(struct usb_device *dev, void *ptr)
info("device disconnected"); info("device disconnected");
} }
MOD_DEC_USE_COUNT;
} }
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
* *
* See Documentation/usb/usb-serial.txt for more information on using this driver * See Documentation/usb/usb-serial.txt for more information on using this driver
* *
* (12/12/2000) gkh
* Moved MOD_DEC to end of visor_close to be nicer, as the final write
* message can sleep.
*
* (11/12/2000) gkh * (11/12/2000) gkh
* Fixed bug with data being dropped on the floor by forcing tty->low_latency * Fixed bug with data being dropped on the floor by forcing tty->low_latency
* to be on. Hopefully this fixes the OHCI issue! * to be on. Hopefully this fixes the OHCI issue!
...@@ -214,7 +218,6 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) ...@@ -214,7 +218,6 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
spin_lock_irqsave (&port->port_lock, flags); spin_lock_irqsave (&port->port_lock, flags);
--port->open_count; --port->open_count;
MOD_DEC_USE_COUNT;
if (port->open_count <= 0) { if (port->open_count <= 0) {
transfer_buffer = kmalloc (0x12, GFP_KERNEL); transfer_buffer = kmalloc (0x12, GFP_KERNEL);
...@@ -237,6 +240,8 @@ static void visor_close (struct usb_serial_port *port, struct file * filp) ...@@ -237,6 +240,8 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
/* Uncomment the following line if you want to see some statistics in your syslog */ /* Uncomment the following line if you want to see some statistics in your syslog */
/* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */ /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */
MOD_DEC_USE_COUNT;
} }
......
/* Driver for USB Mass Storage compliant devices /* Driver for USB Mass Storage compliant devices
* Debugging Functions Header File * Debugging Functions Header File
* *
* $Id: debug.h,v 1.5 2000/09/04 02:12:47 groovyjava Exp $ * $Id: debug.h,v 1.6 2001/01/12 23:51:04 mdharm Exp $
* *
* Current development and maintenance by: * Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
......
...@@ -248,7 +248,7 @@ static int bus_reset( Scsi_Cmnd *srb ) ...@@ -248,7 +248,7 @@ static int bus_reset( Scsi_Cmnd *srb )
for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) { for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) {
struct usb_interface *intf = struct usb_interface *intf =
&us->pusb_dev->actconfig->interface[i]; &us->pusb_dev->actconfig->interface[i];
const struct usb_device_id *id; struct usb_device_id *id;
/* if this is an unclaimed interface, skip it */ /* if this is an unclaimed interface, skip it */
if (!intf->driver) { if (!intf->driver) {
......
/* Driver for USB Mass Storage compliant devices
* Ununsual Devices File
*
* $Id: unusual_devs.h,v 1.1 2000/12/05 05:38:31 mdharm Exp $
*
* Current development and maintenance by:
* (c) 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
*
* Initial work by:
* (c) 2000 Adam J. Richter (adam@yggdrasil.com), Yggdrasil Computing, Inc.
*
* Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
* information about this driver.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* IMPORTANT NOTE: This file must be included in another file which does
* both of the following things for it to work:
* (1) <include/config.h> _must_ be included before this file
* (2) The macro UNUSUAL_DEV() must be defined before this file is included
*/
/* If you edit this file, please try to keep it sorted first by VendorID,
* then by ProductID.
*/
UNUSUAL_DEV( 0x03ee, 0x0000, 0x0000, 0x0245,
"Mitsumi",
"CD-R/RW Drive",
US_SC_8020, US_PR_CBI, NULL, 0),
UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200,
"HP",
"CD-Writer+",
US_SC_8070, US_PR_CB, NULL, 0),
#ifdef CONFIG_USB_STORAGE_HP8200e
UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001,
"HP",
"CD-Writer+ 8200e",
US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0),
#endif
UNUSUAL_DEV( 0x04e6, 0x0001, 0x0200, 0x0200,
"Matshita",
"LS-120",
US_SC_8020, US_PR_CB, NULL, 0),
UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100,
"Shuttle",
"eUSCSI Bridge",
US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
US_FL_SCM_MULT_TARG ),
#ifdef CONFIG_USB_STORAGE_SDDR09
UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999,
"Sandisk",
"ImageMate SDDR09",
US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
US_FL_SINGLE_LUN | US_FL_START_STOP ),
#endif
#ifdef CONFIG_USB_STORAGE_DPCM
UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100,
"Microtech",
"CameraMate (DPCM_USB)",
US_SC_SCSI, US_PR_DPCM_USB, NULL,
US_FL_START_STOP ),
#endif
UNUSUAL_DEV( 0x04e6, 0x0006, 0x0100, 0x0200,
"Shuttle",
"eUSB MMC Adapter",
US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN),
UNUSUAL_DEV( 0x04e6, 0x0007, 0x0100, 0x0200,
"Sony",
"Hifd",
US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN),
UNUSUAL_DEV( 0x04e6, 0x0009, 0x0200, 0x0200,
"Shuttle",
"eUSB ATA/ATAPI Adapter",
US_SC_8020, US_PR_CB, NULL, 0),
UNUSUAL_DEV( 0x04e6, 0x000a, 0x0200, 0x0200,
"Shuttle",
"eUSB CompactFlash Adapter",
US_SC_8020, US_PR_CB, NULL, 0),
UNUSUAL_DEV( 0x04e6, 0x000B, 0x0100, 0x0100,
"Shuttle",
"eUSCSI Bridge",
US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
US_FL_SCM_MULT_TARG ),
UNUSUAL_DEV( 0x04e6, 0x000C, 0x0100, 0x0100,
"Shuttle",
"eUSCSI Bridge",
US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
US_FL_SCM_MULT_TARG ),
UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200,
"Shuttle",
"CD-RW Device",
US_SC_8020, US_PR_CB, NULL, 0),
UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0210,
"Sony",
"DSC-S30/S70/505V/F505",
US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE ),
UNUSUAL_DEV( 0x054c, 0x002d, 0x0100, 0x0100,
"Sony",
"Memorystick MSAC-US1",
US_SC_UFI, US_PR_CB, NULL,
US_FL_SINGLE_LUN | US_FL_START_STOP ),
UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299,
"Y-E Data",
"Flashbuster-U",
US_SC_UFI, US_PR_CB, NULL,
US_FL_SINGLE_LUN),
UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999,
"Y-E Data",
"Flashbuster-U",
US_SC_UFI, US_PR_CBI, NULL,
US_FL_SINGLE_LUN),
UNUSUAL_DEV( 0x059f, 0xa601, 0x0200, 0x0200,
"LaCie",
"USB Hard Disk",
US_SC_RBC, US_PR_CB, NULL, 0 ),
UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0100,
"In-System",
"USB/IDE Bridge (ATAPI ONLY!)",
US_SC_8070, US_PR_BULK, NULL, 0 ),
UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100,
"TEAC",
"Floppy Drive",
US_SC_UFI, US_PR_CB, NULL, 0 ),
#ifdef CONFIG_USB_STORAGE_SDDR09
UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100,
"Olympus",
"Camedia MAUSB-2",
US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
US_FL_SINGLE_LUN | US_FL_START_STOP ),
#endif
UNUSUAL_DEV( 0x0693, 0x0002, 0x0100, 0x0100,
"Hagiwara",
"FlashGate SmartMedia",
US_SC_SCSI, US_PR_BULK, NULL, 0 ),
UNUSUAL_DEV( 0x0693, 0x0005, 0x0100, 0x0100,
"Hagiwara",
"Flashgate",
US_SC_SCSI, US_PR_BULK, NULL, 0 ),
UNUSUAL_DEV( 0x0781, 0x0001, 0x0200, 0x0200,
"Sandisk",
"ImageMate SDDR-05a",
US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN | US_FL_START_STOP),
UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100,
"Sandisk",
"ImageMate SDDR-12",
US_SC_SCSI, US_PR_CB, NULL,
US_FL_SINGLE_LUN ),
#ifdef CONFIG_USB_STORAGE_SDDR09
UNUSUAL_DEV( 0x0781, 0x0200, 0x0100, 0x0100,
"Sandisk",
"ImageMate SDDR-09",
US_SC_SCSI, US_PR_EUSB_SDDR09, NULL,
US_FL_SINGLE_LUN | US_FL_START_STOP ),
#endif
UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009,
"Sandisk",
"ImageMate SDDR-31",
US_SC_SCSI, US_PR_BULK, NULL,
US_FL_IGNORE_SER),
UNUSUAL_DEV( 0x07af, 0x0004, 0x0100, 0x0100,
"Microtech",
"USB-SCSI-DB25",
US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
US_FL_SCM_MULT_TARG ),
#ifdef CONFIG_USB_STORAGE_FREECOM
UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999,
"Freecom",
"USB-IDE",
US_SC_QIC, US_PR_FREECOM, freecom_init, 0),
#endif
UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100,
"Microtech",
"USB-SCSI-HD50",
US_SC_SCSI, US_PR_BULK, usb_stor_euscsi_init,
US_FL_SCM_MULT_TARG ),
#ifdef CONFIG_USB_STORAGE_DPCM
UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100,
"Microtech",
"CameraMate (DPCM_USB)",
US_SC_SCSI, US_PR_DPCM_USB, NULL,
US_FL_START_STOP ),
#endif
This diff is collapsed.
/* Driver for USB Mass Storage compliant devices /* Driver for USB Mass Storage compliant devices
* Main Header File * Main Header File
* *
* $Id: usb.h,v 1.11 2000/11/13 22:38:55 mdharm Exp $ * $Id: usb.h,v 1.12 2000/12/05 03:33:49 mdharm Exp $
* *
* Current development and maintenance by: * Current development and maintenance by:
* (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
...@@ -84,13 +84,6 @@ struct us_data; ...@@ -84,13 +84,6 @@ struct us_data;
*/ */
struct us_unusual_dev { struct us_unusual_dev {
/* we search the list based on these parameters */
__u16 idVendor;
__u16 idProduct;
__u16 bcdDeviceMin;
__u16 bcdDeviceMax;
/* the list specifies these parameters */
const char* vendorName; const char* vendorName;
const char* productName; const char* productName;
__u8 useProtocol; __u8 useProtocol;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#endif #endif
static struct fat_cache *fat_cache,cache[FAT_CACHE]; static struct fat_cache *fat_cache,cache[FAT_CACHE];
static spinlock_t fat_cache_lock = SPIN_LOCK_UNLOCKED;
/* Returns the this'th FAT entry, -1 if it is an end-of-file entry. If /* Returns the this'th FAT entry, -1 if it is an end-of-file entry. If
new_value is != -1, that FAT entry is replaced by it. */ new_value is != -1, that FAT entry is replaced by it. */
...@@ -133,13 +134,16 @@ int default_fat_access(struct super_block *sb,int nr,int new_value) ...@@ -133,13 +134,16 @@ int default_fat_access(struct super_block *sb,int nr,int new_value)
return next; return next;
} }
void fat_cache_init(void) void fat_cache_init(void)
{ {
static int initialized = 0; static int initialized = 0;
int count; int count;
if (initialized) return; spin_lock(&fat_cache_lock);
if (initialized) {
spin_unlock(&fat_cache_lock);
return;
}
fat_cache = &cache[0]; fat_cache = &cache[0];
for (count = 0; count < FAT_CACHE; count++) { for (count = 0; count < FAT_CACHE; count++) {
cache[count].device = 0; cache[count].device = 0;
...@@ -147,6 +151,7 @@ void fat_cache_init(void) ...@@ -147,6 +151,7 @@ void fat_cache_init(void)
&cache[count+1]; &cache[count+1];
} }
initialized = 1; initialized = 1;
spin_unlock(&fat_cache_lock);
} }
...@@ -157,6 +162,7 @@ void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu) ...@@ -157,6 +162,7 @@ void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu)
if (!first) if (!first)
return; return;
spin_lock(&fat_cache_lock);
for (walk = fat_cache; walk; walk = walk->next) for (walk = fat_cache; walk; walk = walk->next)
if (inode->i_dev == walk->device if (inode->i_dev == walk->device
&& walk->start_cluster == first && walk->start_cluster == first
...@@ -166,8 +172,12 @@ void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu) ...@@ -166,8 +172,12 @@ void fat_cache_lookup(struct inode *inode,int cluster,int *f_clu,int *d_clu)
#ifdef DEBUG #ifdef DEBUG
printk("cache hit: %d (%d)\n",walk->file_cluster,*d_clu); printk("cache hit: %d (%d)\n",walk->file_cluster,*d_clu);
#endif #endif
if ((*f_clu = walk->file_cluster) == cluster) return; if ((*f_clu = walk->file_cluster) == cluster) {
spin_unlock(&fat_cache_lock);
return;
} }
}
spin_unlock(&fat_cache_lock);
#ifdef DEBUG #ifdef DEBUG
printk("cache miss\n"); printk("cache miss\n");
#endif #endif
...@@ -197,6 +207,7 @@ void fat_cache_add(struct inode *inode,int f_clu,int d_clu) ...@@ -197,6 +207,7 @@ void fat_cache_add(struct inode *inode,int f_clu,int d_clu)
int first = MSDOS_I(inode)->i_start; int first = MSDOS_I(inode)->i_start;
last = NULL; last = NULL;
spin_lock(&fat_cache_lock);
for (walk = fat_cache; walk->next; walk = (last = walk)->next) for (walk = fat_cache; walk->next; walk = (last = walk)->next)
if (inode->i_dev == walk->device if (inode->i_dev == walk->device
&& walk->start_cluster == first && walk->start_cluster == first
...@@ -204,17 +215,22 @@ void fat_cache_add(struct inode *inode,int f_clu,int d_clu) ...@@ -204,17 +215,22 @@ void fat_cache_add(struct inode *inode,int f_clu,int d_clu)
if (walk->disk_cluster != d_clu) { if (walk->disk_cluster != d_clu) {
printk("FAT cache corruption inode=%ld\n", printk("FAT cache corruption inode=%ld\n",
inode->i_ino); inode->i_ino);
spin_unlock(&fat_cache_lock);
fat_cache_inval_inode(inode); fat_cache_inval_inode(inode);
return; return;
} }
/* update LRU */ /* update LRU */
if (last == NULL) return; if (last == NULL) {
spin_unlock(&fat_cache_lock);
return;
}
last->next = walk->next; last->next = walk->next;
walk->next = fat_cache; walk->next = fat_cache;
fat_cache = walk; fat_cache = walk;
#ifdef DEBUG #ifdef DEBUG
list_cache(); list_cache();
#endif #endif
spin_unlock(&fat_cache_lock);
return; return;
} }
walk->device = inode->i_dev; walk->device = inode->i_dev;
...@@ -224,6 +240,7 @@ list_cache(); ...@@ -224,6 +240,7 @@ list_cache();
last->next = NULL; last->next = NULL;
walk->next = fat_cache; walk->next = fat_cache;
fat_cache = walk; fat_cache = walk;
spin_unlock(&fat_cache_lock);
#ifdef DEBUG #ifdef DEBUG
list_cache(); list_cache();
#endif #endif
...@@ -238,10 +255,12 @@ void fat_cache_inval_inode(struct inode *inode) ...@@ -238,10 +255,12 @@ void fat_cache_inval_inode(struct inode *inode)
struct fat_cache *walk; struct fat_cache *walk;
int first = MSDOS_I(inode)->i_start; int first = MSDOS_I(inode)->i_start;
spin_lock(&fat_cache_lock);
for (walk = fat_cache; walk; walk = walk->next) for (walk = fat_cache; walk; walk = walk->next)
if (walk->device == inode->i_dev if (walk->device == inode->i_dev
&& walk->start_cluster == first) && walk->start_cluster == first)
walk->device = 0; walk->device = 0;
spin_unlock(&fat_cache_lock);
} }
...@@ -249,9 +268,11 @@ void fat_cache_inval_dev(kdev_t device) ...@@ -249,9 +268,11 @@ void fat_cache_inval_dev(kdev_t device)
{ {
struct fat_cache *walk; struct fat_cache *walk;
spin_lock(&fat_cache_lock);
for (walk = fat_cache; walk; walk = walk->next) for (walk = fat_cache; walk; walk = walk->next)
if (walk->device == device) if (walk->device == device)
walk->device = 0; walk->device = 0;
spin_unlock(&fat_cache_lock);
} }
......
...@@ -1853,6 +1853,7 @@ static int reiserfs_commit_write(struct file *f, struct page *page, ...@@ -1853,6 +1853,7 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
struct reiserfs_transaction_handle th ; struct reiserfs_transaction_handle th ;
reiserfs_wait_on_write_block(inode->i_sb) ; reiserfs_wait_on_write_block(inode->i_sb) ;
lock_kernel();
prevent_flush_page_lock(page, inode) ; prevent_flush_page_lock(page, inode) ;
ret = generic_commit_write(f, page, from, to) ; ret = generic_commit_write(f, page, from, to) ;
/* we test for O_SYNC here so we can commit the transaction /* we test for O_SYNC here so we can commit the transaction
...@@ -1866,6 +1867,7 @@ static int reiserfs_commit_write(struct file *f, struct page *page, ...@@ -1866,6 +1867,7 @@ static int reiserfs_commit_write(struct file *f, struct page *page,
journal_end_sync(&th, inode->i_sb, 1) ; journal_end_sync(&th, inode->i_sb, 1) ;
} }
allow_flush_page_lock(page, inode) ; allow_flush_page_lock(page, inode) ;
unlock_kernel();
return ret ; return ret ;
} }
......
...@@ -54,6 +54,7 @@ extern void wait_for_keypress(void); ...@@ -54,6 +54,7 @@ extern void wait_for_keypress(void);
extern int root_mountflags; extern int root_mountflags;
static int do_remount_sb(struct super_block *sb, int flags, char * data); static int do_remount_sb(struct super_block *sb, int flags, char * data);
static int do_remount(const char *dir, int flags, char * data);
/* this is initialized in init/main.c */ /* this is initialized in init/main.c */
kdev_t ROOT_DEV; kdev_t ROOT_DEV;
...@@ -1025,15 +1026,12 @@ static int do_umount(struct vfsmount *mnt, int umount_root, int flags) ...@@ -1025,15 +1026,12 @@ static int do_umount(struct vfsmount *mnt, int umount_root, int flags)
* call reboot(9). Then init(8) could umount root and exec /reboot. * call reboot(9). Then init(8) could umount root and exec /reboot.
*/ */
if (mnt == current->fs->rootmnt && !umount_root) { if (mnt == current->fs->rootmnt && !umount_root) {
int retval = 0;
/* /*
* Special case for "unmounting" root ... * Special case for "unmounting" root ...
* we just try to remount it readonly. * we just try to remount it readonly.
*/ */
mntput(mnt); mntput(mnt);
if (!(sb->s_flags & MS_RDONLY)) return do_remount("/", MS_RDONLY, NULL);
retval = do_remount_sb(sb, MS_RDONLY, 0);
return retval;
} }
spin_lock(&dcache_lock); spin_lock(&dcache_lock);
......
...@@ -386,6 +386,7 @@ extern void clear_page_tables(struct mm_struct *, unsigned long, int); ...@@ -386,6 +386,7 @@ extern void clear_page_tables(struct mm_struct *, unsigned long, int);
struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int no_share); struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, int no_share);
struct file *shmem_file_setup(char * name, loff_t size); struct file *shmem_file_setup(char * name, loff_t size);
extern void shmem_lock(struct file * file, int lock);
extern int shmem_zero_setup(struct vm_area_struct *); extern int shmem_zero_setup(struct vm_area_struct *);
extern void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size); extern void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size);
......
...@@ -117,11 +117,43 @@ shmem_truncate_part (swp_entry_t * dir, unsigned long size, ...@@ -117,11 +117,43 @@ shmem_truncate_part (swp_entry_t * dir, unsigned long size,
return 0; return 0;
} }
/*
* shmem_recalc_inode - recalculate the size of an inode
*
* @inode: inode to recalc
*
* We have to calculate the free blocks since the mm can drop pages
* behind our back
*
* But we know that normally
* inodes->i_blocks == inode->i_mapping->nrpages + info->swapped
*
* So the mm freed
* inodes->i_blocks - (inode->i_mapping->nrpages + info->swapped)
*
* It has to be called with the spinlock held.
*/
static void shmem_recalc_inode(struct inode * inode)
{
unsigned long freed;
freed = inode->i_blocks -
(inode->i_mapping->nrpages + inode->u.shmem_i.swapped);
if (freed){
struct shmem_sb_info * info = &inode->i_sb->u.shmem_sb;
inode->i_blocks -= freed;
spin_lock (&info->stat_lock);
info->free_blocks += freed;
spin_unlock (&info->stat_lock);
}
}
static void shmem_truncate (struct inode * inode) static void shmem_truncate (struct inode * inode)
{ {
int clear_base; int clear_base;
unsigned long start; unsigned long start;
unsigned long mmfreed, freed = 0; unsigned long freed = 0;
swp_entry_t **base, **ptr; swp_entry_t **base, **ptr;
struct shmem_inode_info * info = &inode->u.shmem_i; struct shmem_inode_info * info = &inode->u.shmem_i;
...@@ -154,26 +186,9 @@ static void shmem_truncate (struct inode * inode) ...@@ -154,26 +186,9 @@ static void shmem_truncate (struct inode * inode)
info->i_indirect = 0; info->i_indirect = 0;
out: out:
/*
* We have to calculate the free blocks since we do not know
* how many pages the mm discarded
*
* But we know that normally
* inodes->i_blocks == inode->i_mapping->nrpages + info->swapped
*
* So the mm freed
* inodes->i_blocks - (inode->i_mapping->nrpages + info->swapped)
*/
mmfreed = inode->i_blocks - (inode->i_mapping->nrpages + info->swapped);
info->swapped -= freed; info->swapped -= freed;
inode->i_blocks -= freed + mmfreed; shmem_recalc_inode(inode);
spin_unlock (&info->lock); spin_unlock (&info->lock);
spin_lock (&inode->i_sb->u.shmem_sb.stat_lock);
inode->i_sb->u.shmem_sb.free_blocks += freed + mmfreed;
spin_unlock (&inode->i_sb->u.shmem_sb.stat_lock);
} }
static void shmem_delete_inode(struct inode * inode) static void shmem_delete_inode(struct inode * inode)
...@@ -208,6 +223,7 @@ static int shmem_writepage(struct page * page) ...@@ -208,6 +223,7 @@ static int shmem_writepage(struct page * page)
return 1; return 1;
spin_lock(&info->lock); spin_lock(&info->lock);
shmem_recalc_inode(page->mapping->host);
entry = shmem_swp_entry (info, page->index); entry = shmem_swp_entry (info, page->index);
if (!entry) /* this had been allocted on page allocation */ if (!entry) /* this had been allocted on page allocation */
BUG(); BUG();
...@@ -269,6 +285,9 @@ struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, i ...@@ -269,6 +285,9 @@ struct page * shmem_nopage(struct vm_area_struct * vma, unsigned long address, i
entry = shmem_swp_entry (info, idx); entry = shmem_swp_entry (info, idx);
if (!entry) if (!entry)
goto oom; goto oom;
spin_lock (&info->lock);
shmem_recalc_inode(inode);
spin_unlock (&info->lock);
if (entry->val) { if (entry->val) {
unsigned long flags; unsigned long flags;
......
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