From 21033193a4bb45e499e58c70dff0408a2149c274 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 7 Dec 2003 19:10:51 -0800 Subject: [PATCH] USB: register usb-serial ports in the proper place in sysfs They should be bound to the interface the driver is attached to, not the device. --- drivers/usb/serial/usb-serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 96747544c788..ec610ee4aa1c 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1242,7 +1242,7 @@ int usb_serial_probe(struct usb_interface *interface, /* register all of the individual ports with the driver core */ for (i = 0; i < num_ports; ++i) { port = serial->port[i]; - port->dev.parent = &serial->dev->dev; + port->dev.parent = &interface->dev; port->dev.driver = NULL; port->dev.bus = &usb_serial_bus_type; port->dev.release = &port_release; -- cgit v1.2.3 From 41888e962af026a557c4a274d41b86fb5d27c4ee Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 7 Dec 2003 21:28:46 -0800 Subject: [PATCH] USB: fix remove device after set_configuration If a device can't be configured, the current test9 code forgets to clean it out of sysfs. This resolves that issue, so the retry in usb_new_device() stands a chance of working. The enumeration code still doesn't handle such errors well, but at least this way that hub port can be used for another device. --- drivers/usb/core/usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 3fad1ec8b4a3..4bccdf023348 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -1120,6 +1120,7 @@ int usb_new_device(struct usb_device *dev, struct device *parent) if (err) { dev_err(&dev->dev, "can't set config #%d, error %d\n", dev->config[0].desc.bConfigurationValue, err); + device_del(&dev->dev); goto fail; } -- cgit v1.2.3 From 830a91c95e5c62d8d9be53d37fa63b8f73371265 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 7 Dec 2003 21:58:14 -0800 Subject: [PATCH] USB: fix race with hub devices disconnecting while stuff is still happening to them. --- drivers/usb/core/hub.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index dc12ba0c9722..f665eadd35e7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -692,6 +692,9 @@ static int hub_port_status(struct usb_device *dev, int port, struct usb_hub *hub = usb_get_intfdata(dev->actconfig->interface[0]); int ret; + if (!hub) + return -ENODEV; + ret = get_port_status(dev, port + 1, &hub->status->port); if (ret < 0) dev_err (hubdev (dev), -- cgit v1.2.3 From bc26e4e4e8ead1de0c183883a38ae8603f6e173e Mon Sep 17 00:00:00 2001 From: Matthew Dharm Date: Mon, 8 Dec 2003 17:35:37 -0800 Subject: [PATCH] USB storage: fix for jumpshot and datafab devices This patch fixes some obvious errors in the jumpshot and datafab drivers. This should close out Bugzilla bug #1408 > Date: Mon, 1 Dec 2003 12:14:53 -0500 (EST) > From: Alan Stern > Subject: Patch from Eduard Hasenleithner > To: Matthew Dharm > cc: USB Storage List > > Matt: > > Did you see this patch? It was posted to the usb-development mailing list > about a week ago, before I started making all my changes. It is clearly > correct and necessary. > > Alan Stern --- drivers/usb/storage/datafab.c | 2 +- drivers/usb/storage/jumpshot.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 02b13b3867c1..5036f7a32fa2 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -387,7 +387,7 @@ static int datafab_id_device(struct us_data *us, // we'll go ahead and extract the media capacity while we're here... // - rc = datafab_bulk_read(us, reply, sizeof(reply)); + rc = datafab_bulk_read(us, reply, 512); if (rc == USB_STOR_XFER_GOOD) { // capacity is at word offset 57-58 // diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index 3b75a8a43eda..8149f27640be 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -317,7 +317,7 @@ static int jumpshot_id_device(struct us_data *us, } // read the reply - rc = jumpshot_bulk_read(us, reply, sizeof(reply)); + rc = jumpshot_bulk_read(us, reply, 512); if (rc != USB_STOR_XFER_GOOD) { rc = USB_STOR_TRANSPORT_ERROR; goto leave; -- cgit v1.2.3 From cee0c0dde7a644f8ecf201bc341e58e1772741b5 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Mon, 8 Dec 2003 17:42:34 -0800 Subject: [PATCH] USB: mark the scanner driver as obsolete On Mon, Dec 01, 2003 at 11:21:58AM -0800, Greg KH wrote: > Can't you use xsane without the scanner kernel driver? I thought the > latest versions used libusb/usbfs to talk directly to the hardware. > Because of this, the USB scanner driver is marked to be removed from the > kernel sometime in the near future. After a bit of mucking around (and possibly finding a bug with debian's libusb/xsane/hotplug interaction, nothing seems to run /etc/hotplug/usb/libusbscanner and thus only root can scan, anyone whose got this working please let me know), the problem does not exist if I only use libusb xsane. How about the following: --- drivers/usb/image/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/image/Kconfig b/drivers/usb/image/Kconfig index efe964efe12e..6263370d3ed9 100644 --- a/drivers/usb/image/Kconfig +++ b/drivers/usb/image/Kconfig @@ -18,13 +18,15 @@ config USB_MDC800 module will be called mdc800. config USB_SCANNER - tristate "USB Scanner support" + tristate "USB Scanner support (OBSOLETE)" depends on USB help Say Y here if you want to connect a USB scanner to your computer's USB port. Please read for more information. + This driver has been obsoleted by support via libusb. + To compile this driver as a module, choose M here: the module will be called scanner. -- cgit v1.2.3 From 697a025dc3c84aa4e389498ef2a6a8897bafacd7 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 8 Dec 2003 18:00:49 -0800 Subject: [PATCH] USB: fix sleping in interrupt bug in auerswald driver this fixes two instances of GFP_KERNEL from completion handlers. --- drivers/usb/misc/auerswald.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c index 4ef570f5cb84..a8f581e58df5 100644 --- a/drivers/usb/misc/auerswald.c +++ b/drivers/usb/misc/auerswald.c @@ -324,7 +324,7 @@ static void auerchain_complete (struct urb * urb, struct pt_regs *regs) urb = acep->urbp; dbg ("auerchain_complete: submitting next urb from chain"); urb->status = 0; /* needed! */ - result = usb_submit_urb(urb, GFP_KERNEL); + result = usb_submit_urb(urb, GFP_ATOMIC); /* check for submit errors */ if (result) { @@ -402,7 +402,7 @@ static int auerchain_submit_urb_list (pauerchain_t acp, struct urb * urb, int ea if (acep) { dbg("submitting urb immediate"); urb->status = 0; /* needed! */ - result = usb_submit_urb(urb, GFP_KERNEL); + result = usb_submit_urb(urb, GFP_ATOMIC); /* check for submit errors */ if (result) { urb->status = result; -- cgit v1.2.3 From 41b98670535687b465df7ae1da75f2911415e61a Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 8 Dec 2003 18:18:07 -0800 Subject: [PATCH] USB: fix race with signal delivery in usbfs apart from locking bugs, there are other races. This fixes one with signal delivery. The signal should be delivered _before_ the reciever is woken. --- drivers/usb/core/devio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index ecef33242859..68ca2b2abfee 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -261,7 +261,6 @@ static void async_completed(struct urb *urb, struct pt_regs *regs) spin_lock(&ps->lock); list_move_tail(&as->asynclist, &ps->async_completed); spin_unlock(&ps->lock); - wake_up(&ps->wait); if (as->signr) { sinfo.si_signo = as->signr; sinfo.si_errno = as->urb->status; @@ -269,6 +268,7 @@ static void async_completed(struct urb *urb, struct pt_regs *regs) sinfo.si_addr = (void *)as->userurb; send_sig_info(as->signr, &sinfo, as->task); } + wake_up(&ps->wait); } static void destroy_async (struct dev_state *ps, struct list_head *list) -- cgit v1.2.3 From f6b1ebe8146930855211c8e5ffdc986cc90c0502 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 8 Dec 2003 23:41:57 -0800 Subject: [PATCH] USB: fix bug not setting device state following usb_device_reset() --- drivers/usb/core/hub.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f665eadd35e7..eba7d9fca67a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1345,6 +1345,7 @@ int usb_physical_reset_device(struct usb_device *dev) dev->devpath, ret); return ret; } + dev->state = USB_STATE_CONFIGURED; for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *intf = dev->actconfig->interface[i]; -- cgit v1.2.3 From 08bceb43a596101b03501cebd1e6de166e846393 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 9 Dec 2003 01:40:44 -0800 Subject: [PATCH] USB: Fix connect/disconnect race This patch was integrated by you in 2.4 six months ago. Unfortunately it never got into 2.5. Without it you can end up with crashes such as http://bugs.debian.org/218670 --- drivers/usb/core/hub.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index eba7d9fca67a..d019f21cec37 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -929,7 +929,6 @@ static void hub_port_connect_change(struct usb_hub *hubstate, int port, break; } - hub->children[port] = dev; dev->state = USB_STATE_POWERED; /* Reset the device, and detect its speed */ @@ -982,8 +981,10 @@ static void hub_port_connect_change(struct usb_hub *hubstate, int port, dev->dev.parent = dev->parent->dev.parent->parent; /* Run it through the hoops (find a driver, etc) */ - if (!usb_new_device(dev, &hub->dev)) + if (!usb_new_device(dev, &hub->dev)) { + hub->children[port] = dev; goto done; + } /* Free the configuration if there was an error */ usb_put_dev(dev); @@ -992,7 +993,6 @@ static void hub_port_connect_change(struct usb_hub *hubstate, int port, delay = HUB_LONG_RESET_TIME; } - hub->children[port] = NULL; hub_port_disable(hub, port); done: up(&usb_address0_sem); -- cgit v1.2.3 From 95cc041850e4b5ffbff4800f77c1af2e0dd768a0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 9 Dec 2003 22:39:48 -0800 Subject: [PATCH] USB: fix bug for multiple opens on ttyUSB devices. This patch fixes the bug where running ppp over a ttyUSB device would fail. --- drivers/usb/serial/usb-serial.c | 48 +++++++++++------------------------------ 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index ec610ee4aa1c..c7a96102a73e 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -493,12 +493,15 @@ bailout: return retval; } -static void __serial_close(struct usb_serial_port *port, struct file *filp) +static void serial_close(struct tty_struct *tty, struct file * filp) { - if (!port->open_count) { - dbg ("%s - port not opened", __FUNCTION__); + struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; + struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); + + if (!serial) return; - } + + dbg("%s - port %d", __FUNCTION__, port->number); --port->open_count; if (port->open_count <= 0) { @@ -506,30 +509,18 @@ static void __serial_close(struct usb_serial_port *port, struct file *filp) * port is being closed by the last owner */ port->serial->type->close(port, filp); port->open_count = 0; + + if (port->tty) { + if (port->tty->driver_data) + port->tty->driver_data = NULL; + port->tty = NULL; + } } module_put(port->serial->type->owner); kobject_put(&port->serial->kobj); } -static void serial_close(struct tty_struct *tty, struct file * filp) -{ - struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; - struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); - - if (!serial) - return; - - dbg("%s - port %d", __FUNCTION__, port->number); - - /* if disconnect beat us to the punch here, there's nothing to do */ - if (tty && tty->driver_data) { - __serial_close(port, filp); - tty->driver_data = NULL; - } - port->tty = NULL; -} - static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { struct usb_serial_port *port = (struct usb_serial_port *) tty->driver_data; @@ -848,19 +839,6 @@ static void destroy_serial (struct kobject *kobj) dbg ("%s - %s", __FUNCTION__, kobj->name); serial = to_usb_serial(kobj); - - /* fail all future close/read/write/ioctl/etc calls */ - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - if (port->tty != NULL) { - port->tty->driver_data = NULL; - while (port->open_count > 0) { - __serial_close(port, NULL); - } - port->tty = NULL; - } - } - serial_shutdown (serial); /* return the minor range that this device had */ -- cgit v1.2.3 From 0d55831736fddd104c0716e3832f53355723787c Mon Sep 17 00:00:00 2001 From: Andrey Borzenkov Date: Wed, 10 Dec 2003 00:00:53 -0800 Subject: [PATCH] USB: prevent catch-all USB aliases in modules.alias visor.c defines one empty slot in USB ids table that can be filled in at runtime using module parameters. file2alias generates catch-all alias for it: alias usb:v*p*dl*dh*dc*dsc*dp*ic*isc*ip* visor patch adds the same sanity check as in depmod to scripts/file2alias. --- scripts/file2alias.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/file2alias.c b/scripts/file2alias.c index 8c707215b834..1528dddebe7e 100644 --- a/scripts/file2alias.c +++ b/scripts/file2alias.c @@ -52,6 +52,13 @@ static int do_usb_entry(const char *filename, id->bcdDevice_lo = TO_NATIVE(id->bcdDevice_lo); id->bcdDevice_hi = TO_NATIVE(id->bcdDevice_hi); + /* + * Some modules (visor) have empty slots as placeholder for + * run-time specification that results in catch-all alias + */ + if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass)) + return 1; + strcpy(alias, "usb:"); ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR, id->idVendor); -- cgit v1.2.3 From 10921a8f1305b8ec97794941db78b825db5839bc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 10 Dec 2003 17:49:24 -0800 Subject: kobject: fix bug where a parent could be deleted before a child device. --- lib/kobject.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/kobject.c b/lib/kobject.c index ff65c0f2c98f..51787be15552 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -236,8 +236,6 @@ static void unlink(struct kobject * kobj) list_del_init(&kobj->entry); up_write(&kobj->kset->subsys->rwsem); } - if (kobj->parent) - kobject_put(kobj->parent); kobject_put(kobj); } @@ -274,9 +272,11 @@ int kobject_add(struct kobject * kobj) kobj->parent = parent; error = create_dir(kobj); - if (error) + if (error) { unlink(kobj); - else { + if (parent) + kobject_put(parent); + } else { /* If this kobj does not belong to a kset, try to find a parent that does. */ top_kobj = kobj; @@ -452,6 +452,7 @@ void kobject_cleanup(struct kobject * kobj) { struct kobj_type * t = get_ktype(kobj); struct kset * s = kobj->kset; + struct kobject * parent = kobj->parent; pr_debug("kobject %s: cleaning up\n",kobject_name(kobj)); if (kobj->k_name != kobj->name) @@ -461,6 +462,8 @@ void kobject_cleanup(struct kobject * kobj) t->release(kobj); if (s) kset_put(s); + if (parent) + kobject_put(parent); } /** -- cgit v1.2.3 From e1f936a94c1b6e519bdffc1ce02bfb8a81035e06 Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Mon, 15 Dec 2003 00:35:56 -0800 Subject: [PATCH] Fix possible bio corruption with RAID5 1/ make sure raid5 doesn't try to handle multiple overlaping requests at the same time as this would confuse things badly. Currently it justs BUGs if this is attempted. 2/ Fix a possible data-loss-on-write problem. If two or more bio's that write to the same page are processed at the same time, only the first was actually commited to storage. 3/ Fix a use-after-free bug. raid5 keeps the bio's it is given in linked lists when more than one bio touch a single page. In some cases the tail of this list can be freed, and the current test for 'are we at the end' isn't reliable. This patch strengths the test to make it reliable. --- drivers/md/raid5.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 66ded6db1209..8ea6bf99dc29 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -40,6 +40,16 @@ #define stripe_hash(conf, sect) ((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]) +/* bio's attached to a stripe+device for I/O are linked together in bi_sector + * order without overlap. There may be several bio's per stripe+device, and + * a bio could span several devices. + * When walking this list for a particular stripe+device, we must never proceed + * beyond a bio that extends past this device, as the next bio might no longer + * be valid. + * This macro is used to determine the 'next' bio in the list, given the sector + * of the current stripe+device + */ +#define r5_next_bio(bio, sect) ( ( bio->bi_sector + (bio->bi_size>>9) < sect + STRIPE_SECTORS) ? bio->bi_next : NULL) /* * The following can be used to debug the driver */ @@ -613,7 +623,7 @@ static void copy_data(int frombio, struct bio *bio, int i; for (;bio && bio->bi_sector < sector+STRIPE_SECTORS; - bio = bio->bi_next) { + bio = r5_next_bio(bio, sector) ) { int page_offset; if (bio->bi_sector >= sector) page_offset = (signed)(bio->bi_sector - sector) * 512; @@ -738,7 +748,11 @@ static void compute_parity(struct stripe_head *sh, int method) for (i = disks; i--;) if (sh->dev[i].written) { sector_t sector = sh->dev[i].sector; - copy_data(1, sh->dev[i].written, sh->dev[i].page, sector); + struct bio *wbi = sh->dev[i].written; + while (wbi && wbi->bi_sector < sector + STRIPE_SECTORS) { + copy_data(1, wbi, sh->dev[i].page, sector); + wbi = r5_next_bio(wbi, sector); + } set_bit(R5_LOCKED, &sh->dev[i].flags); set_bit(R5_UPTODATE, &sh->dev[i].flags); @@ -791,8 +805,10 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, bip = &sh->dev[dd_idx].towrite; else bip = &sh->dev[dd_idx].toread; - while (*bip && (*bip)->bi_sector < bi->bi_sector) + while (*bip && (*bip)->bi_sector < bi->bi_sector) { + BUG_ON((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector); bip = & (*bip)->bi_next; + } /* FIXME do I need to worry about overlapping bion */ if (*bip && bi->bi_next && (*bip) != bi->bi_next) BUG(); @@ -813,7 +829,7 @@ static void add_stripe_bio (struct stripe_head *sh, struct bio *bi, int dd_idx, for (bi=sh->dev[dd_idx].towrite; sector < sh->dev[dd_idx].sector + STRIPE_SECTORS && bi && bi->bi_sector <= sector; - bi = bi->bi_next) { + bi = r5_next_bio(bi, sh->dev[dd_idx].sector)) { if (bi->bi_sector + (bi->bi_size>>9) >= sector) sector = bi->bi_sector + (bi->bi_size>>9); } @@ -883,7 +899,7 @@ static void handle_stripe(struct stripe_head *sh) spin_unlock_irq(&conf->device_lock); while (rbi && rbi->bi_sector < dev->sector + STRIPE_SECTORS) { copy_data(0, rbi, dev->page, dev->sector); - rbi2 = rbi->bi_next; + rbi2 = r5_next_bio(rbi, dev->sector); spin_lock_irq(&conf->device_lock); if (--rbi->bi_phys_segments == 0) { rbi->bi_next = return_bi; @@ -928,7 +944,7 @@ static void handle_stripe(struct stripe_head *sh) if (bi) to_write--; while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){ - struct bio *nextbi = bi->bi_next; + struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); clear_bit(BIO_UPTODATE, &bi->bi_flags); if (--bi->bi_phys_segments == 0) { md_write_end(conf->mddev); @@ -941,7 +957,7 @@ static void handle_stripe(struct stripe_head *sh) bi = sh->dev[i].written; sh->dev[i].written = NULL; while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) { - struct bio *bi2 = bi->bi_next; + struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector); clear_bit(BIO_UPTODATE, &bi->bi_flags); if (--bi->bi_phys_segments == 0) { md_write_end(conf->mddev); @@ -957,7 +973,7 @@ static void handle_stripe(struct stripe_head *sh) sh->dev[i].toread = NULL; if (bi) to_read--; while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS){ - struct bio *nextbi = bi->bi_next; + struct bio *nextbi = r5_next_bio(bi, sh->dev[i].sector); clear_bit(BIO_UPTODATE, &bi->bi_flags); if (--bi->bi_phys_segments == 0) { bi->bi_next = return_bi; @@ -1000,7 +1016,7 @@ static void handle_stripe(struct stripe_head *sh) wbi = dev->written; dev->written = NULL; while (wbi && wbi->bi_sector < dev->sector + STRIPE_SECTORS) { - wbi2 = wbi->bi_next; + wbi2 = r5_next_bio(wbi, dev->sector); if (--wbi->bi_phys_segments == 0) { md_write_end(conf->mddev); wbi->bi_next = return_bi; -- cgit v1.2.3 From 314dc1544cc8f810bbe7afe5fcc61260d5ae46cb Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 15 Dec 2003 15:51:55 -0800 Subject: [PATCH] Fix IDE bus reset and DMA disable when reading blank DVD-R From Jon Burgess: There is a problems with blank DVD media using the ide-cd driver. When we attempt to read the blank disk, the drive responds to the read request by returning a "blank media" error. The kernel doesn't have any special case handling for this sense value and retries the request a couple of times, then gives up and does a bus reset and disables DMA to the device. Which obviously doesn't help the situation. The sense key value of 8 isn't listed in ide-cd.h, but it is listed in scsi.h as a "BLANK_CHECK" error. This trivial patch treats this error condition as a reason to abort the request. This behaviour is the same as what we do with a blank CD-R. It looks like the same fix might be desired for 2.4 as well, although is perhaps not so important since scsi-ide is normally used instead. --- drivers/ide/ide-cd.c | 4 ++++ drivers/ide/ide-cd.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index dfc01ebe4678..c332518996ef 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -799,6 +799,10 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) * sector... If we got here the error is not correctable */ ide_dump_status (drive, "media error (bad sector)", stat); do_end_request = 1; + } else if (sense_key == BLANK_CHECK) { + /* Disk appears blank ?? */ + ide_dump_status (drive, "media error (blank)", stat); + do_end_request = 1; } else if ((err & ~ABRT_ERR) != 0) { /* Go to the default handler for other errors. */ diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index 5b25f2e37ac1..030b39ea13e4 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h @@ -501,6 +501,7 @@ struct cdrom_info { #define ILLEGAL_REQUEST 0x05 #define UNIT_ATTENTION 0x06 #define DATA_PROTECT 0x07 +#define BLANK_CHECK 0x08 #define ABORTED_COMMAND 0x0b #define MISCOMPARE 0x0e @@ -578,7 +579,7 @@ const char * const sense_key_texts[16] = { "Illegal request", "Unit attention", "Data protect", - "(reserved)", + "Blank check", "(reserved)", "(reserved)", "Aborted command", -- cgit v1.2.3 From f75da5af1c0b41783c8bb078d0ce7a03cc9be826 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 16 Dec 2003 16:12:29 -0800 Subject: [PATCH] CDROM_SEND_PACKET bug I just found Yet Another Bug in scsi_ioctl - CDROM_SEND_PACKET puts a kernel pointer in hdr->cmdp, where sg_io() expects to find user address. This worked up until recently because of the memcpy bug, but now it doesn't because we do the proper copy_from_user(). This fix undoes the user copy code from sg_io, and instead makes the SG_IO ioctl copy it locally. This makes SG_IO and CDROM_SEND_PACKET agree on the calling convention, and everybody is happy. I've tested that both cdrecord -dev=/dev/hdc -inq and cdrecord -dev=ATAPI:/dev/hdc -inq works now. The former will use SG_IO, the latter CDROM_SEND_PACKET (and incidentally would work in both 2.4 and 2.6, if it wasn't for CDROM_SEND_PACKET sucking badly in 2.4). --- drivers/block/scsi_ioctl.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/block/scsi_ioctl.c b/drivers/block/scsi_ioctl.c index 098425adddf0..0c02c5ab3eeb 100644 --- a/drivers/block/scsi_ioctl.c +++ b/drivers/block/scsi_ioctl.c @@ -150,7 +150,6 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, struct request *rq; struct bio *bio; char sense[SCSI_SENSE_BUFFERSIZE]; - unsigned char cdb[BLK_MAX_CDB]; void *buffer; if (hdr->interface_id != 'S') @@ -167,9 +166,6 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, if (hdr->dxfer_len > (q->max_sectors << 9)) return -EIO; - if (copy_from_user(cdb, hdr->cmdp, hdr->cmd_len)) - return -EFAULT; - reading = writing = 0; buffer = NULL; bio = NULL; @@ -220,7 +216,7 @@ static int sg_io(request_queue_t *q, struct block_device *bdev, * fill in request structure */ rq->cmd_len = hdr->cmd_len; - memcpy(rq->cmd, cdb, hdr->cmd_len); + memcpy(rq->cmd, hdr->cmdp, hdr->cmd_len); if (sizeof(rq->cmd) != hdr->cmd_len) memset(rq->cmd + hdr->cmd_len, 0, sizeof(rq->cmd) - hdr->cmd_len); @@ -436,12 +432,23 @@ int scsi_cmd_ioctl(struct block_device *bdev, unsigned int cmd, unsigned long ar break; case SG_IO: { struct sg_io_hdr hdr; + unsigned char cdb[BLK_MAX_CDB], *old_cdb; - if (copy_from_user(&hdr, (struct sg_io_hdr *) arg, sizeof(hdr))) { - err = -EFAULT; + err = -EFAULT; + if (copy_from_user(&hdr, (struct sg_io_hdr *) arg, sizeof(hdr))) break; - } + err = -EINVAL; + if (hdr.cmd_len > sizeof(rq->cmd)) + break; + err = -EFAULT; + if (copy_from_user(cdb, hdr.cmdp, hdr.cmd_len)) + break; + + old_cdb = hdr.cmdp; + hdr.cmdp = cdb; err = sg_io(q, bdev, &hdr); + + hdr.cmdp = old_cdb; if (copy_to_user((struct sg_io_hdr *) arg, &hdr, sizeof(hdr))) err = -EFAULT; break; -- cgit v1.2.3 From 0e70f996f011c870970eee3f584a2f9b8295cf34 Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 16 Dec 2003 16:26:43 -0800 Subject: [PATCH] qla1280 crash fix in error handling This fixes a bug in the qla1280 driver where it would leave a pointer to an on the stack completion event in a command structure if qla1280_mailbox_command fails. The result is that the interrupt handler later tries to complete() garbage on the stack. The mailbox command can fail if a device on the bus decides to lock up etc. --- drivers/scsi/qla1280.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index a995b9599e23..db6fea56aae8 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -16,9 +16,13 @@ * General Public License for more details. * ******************************************************************************/ -#define QLA1280_VERSION "3.23.37" +#define QLA1280_VERSION "3.23.37.1" /***************************************************************************** Revision History: + Rev 3.23.37.1 December 17, 2003, Jes Sorensen + - Delete completion queue from srb if mailbox command failed to + to avoid qla1280_done completeting qla1280_error_action's + obsolete context Rev 3.23.37 October 1, 2003, Jes Sorensen - Make MMIO depend on CONFIG_X86_VISWS instead of yet another random CONFIG option @@ -1464,8 +1468,15 @@ qla1280_error_action(Scsi_Cmnd * cmd, enum action action) /* If we didn't manage to issue the action, or we have no * command to wait for, exit here */ if (result == FAILED || handle == NULL || - handle == (unsigned char *)INVALID_HANDLE) + handle == (unsigned char *)INVALID_HANDLE) { + /* + * Clear completion queue to avoid qla1280_done() trying + * to complete the command at a later stage after we + * have exited the current context + */ + sp->wait = NULL; goto leave; + } /* set up a timer just in case we're really jammed */ init_timer(&timer); -- cgit v1.2.3 From 67e9bb60cdf60c3ead23020c96090e722895f47a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 17 Dec 2003 02:56:13 -0800 Subject: Linux 2.6.0 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f86eecacdb5e..acc02ef87101 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 0 -EXTRAVERSION = -test11 +EXTRAVERSION = # *DOCUMENTATION* # To see a list of typical targets execute "make help" -- cgit v1.2.3