diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-09 17:34:20 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-03-09 17:34:20 -0800 |
commit | 98a563c02de8d4199da0ed1b422d2b5ac93040af (patch) | |
tree | 35752a234ce6561e8cf7b7e6a2e5a2f7ac8c809f /usb | |
parent | e777bbc09f0785f314aae0367fdc8f9e3e1f28a7 (diff) | |
download | patches-98a563c02de8d4199da0ed1b422d2b5ac93040af.tar.gz |
more usb patches
Diffstat (limited to 'usb')
-rw-r--r-- | usb/always-announce-new-usb-devices.patch | 6 | ||||
-rw-r--r-- | usb/usb-ub-01-remove-first_open.patch | 71 | ||||
-rw-r--r-- | usb/usb-ub-02-remove-diag.patch | 395 | ||||
-rw-r--r-- | usb/usb-ub-03-drop-stall-clearing.patch | 45 | ||||
-rw-r--r-- | usb/usb-usbcore-don-t-assume-a-usb-configuration-includes-any-interfaces.patch | 66 | ||||
-rw-r--r-- | usb/usb-usbcore-usb_set_configuration-oops.patch | 43 |
6 files changed, 623 insertions, 3 deletions
diff --git a/usb/always-announce-new-usb-devices.patch b/usb/always-announce-new-usb-devices.patch index 87fc956b748fa6..d3e74cc6260fff 100644 --- a/usb/always-announce-new-usb-devices.patch +++ b/usb/always-announce-new-usb-devices.patch @@ -14,7 +14,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- gregkh-2.6.orig/drivers/usb/core/hub.c +++ gregkh-2.6/drivers/usb/core/hub.c -@@ -1257,7 +1257,6 @@ static int choose_configuration(struct u +@@ -1261,7 +1261,6 @@ static int choose_configuration(struct u return i; } @@ -22,7 +22,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> static void show_string(struct usb_device *udev, char *id, char *string) { if (!string) -@@ -1265,10 +1264,6 @@ static void show_string(struct usb_devic +@@ -1269,10 +1268,6 @@ static void show_string(struct usb_devic dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, string); } @@ -33,7 +33,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> #ifdef CONFIG_USB_OTG -@@ -1313,7 +1308,10 @@ int usb_new_device(struct usb_device *ud +@@ -1317,7 +1312,10 @@ int usb_new_device(struct usb_device *ud udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); /* Tell the world! */ diff --git a/usb/usb-ub-01-remove-first_open.patch b/usb/usb-ub-01-remove-first_open.patch new file mode 100644 index 00000000000000..494b3f51bba3b0 --- /dev/null +++ b/usb/usb-ub-01-remove-first_open.patch @@ -0,0 +1,71 @@ +From zaitcev@redhat.com Thu Mar 2 16:36:30 2006 +Date: Thu, 2 Mar 2006 16:36:09 -0800 +From: Pete Zaitcev <zaitcev@redhat.com> +To: greg@kroah.com +Cc: zaitcev@redhat.com, linux-usb-devel@lists.sourceforge.net +Subject: USB: ub 01 remove first_open +Message-Id: <20060302163609.21b4236a.zaitcev@redhat.com> + +The first_open was long overdue for removal, but I wanted to keep this +separate for other changes in case of regressions. + +Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/block/ub.c | 23 ----------------------- + 1 file changed, 23 deletions(-) + +--- gregkh-2.6.orig/drivers/block/ub.c ++++ gregkh-2.6/drivers/block/ub.c +@@ -8,7 +8,6 @@ + * and is not licensed separately. See file COPYING for details. + * + * TODO (sorted by decreasing priority) +- * -- Kill first_open (Al Viro fixed the block layer now) + * -- set readonly flag for CDs, set removable flag for CF readers + * -- do inquiry and verify we got a disk and not a tape (for LUN mismatch) + * -- special case some senses, e.g. 3a/0 -> no media present, reduce retries +@@ -334,7 +333,6 @@ struct ub_lun { + int changed; /* Media was changed */ + int removable; + int readonly; +- int first_open; /* Kludge. See ub_bd_open. */ + + struct ub_request urq; + +@@ -1849,26 +1847,6 @@ static int ub_bd_open(struct inode *inod + sc->openc++; + spin_unlock_irqrestore(&ub_lock, flags); + +- /* +- * This is a workaround for a specific problem in our block layer. +- * In 2.6.9, register_disk duplicates the code from rescan_partitions. +- * However, if we do add_disk with a device which persistently reports +- * a changed media, add_disk calls register_disk, which does do_open, +- * which will call rescan_paritions for changed media. After that, +- * register_disk attempts to do it all again and causes double kobject +- * registration and a eventually an oops on module removal. +- * +- * The bottom line is, Al Viro says that we should not allow +- * bdev->bd_invalidated to be set when doing add_disk no matter what. +- */ +- if (lun->first_open) { +- lun->first_open = 0; +- if (lun->changed) { +- rc = -ENOMEDIUM; +- goto err_open; +- } +- } +- + if (lun->removable || lun->readonly) + check_disk_change(inode->i_bdev); + +@@ -2537,7 +2515,6 @@ static int ub_probe_lun(struct ub_dev *s + + lun->removable = 1; /* XXX Query this from the device */ + lun->changed = 1; /* ub_revalidate clears only */ +- lun->first_open = 1; + ub_revalidate(sc, lun); + + rc = -ENOMEM; diff --git a/usb/usb-ub-02-remove-diag.patch b/usb/usb-ub-02-remove-diag.patch new file mode 100644 index 00000000000000..85b976ec588306 --- /dev/null +++ b/usb/usb-ub-02-remove-diag.patch @@ -0,0 +1,395 @@ +From zaitcev@redhat.com Thu Mar 2 16:43:23 2006 +Date: Thu, 2 Mar 2006 16:42:59 -0800 +From: Pete Zaitcev <zaitcev@redhat.com> +To: greg@kroah.com +Cc: zaitcev@redhat.com, linux-usb-devel@lists.sourceforge.net, viro@www.linux.org.uk +Subject: USB: ub 02 remove diag +Message-Id: <20060302164259.095ab85b.zaitcev@redhat.com> + +Remove the "diag" file from the sysfs. The usbmon is good enough these days +so I do not need this feature anymore. Also, sysfs is a pain. Al Viro caught +a race in this, which I thought too bothersome to fix. + +Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/block/ub.c | 197 +---------------------------------------------------- + 1 file changed, 4 insertions(+), 193 deletions(-) + +--- gregkh-2.6.orig/drivers/block/ub.c ++++ gregkh-2.6/drivers/block/ub.c +@@ -180,6 +180,7 @@ struct ub_dev; + #define UB_DIR_ILLEGAL2 2 + #define UB_DIR_WRITE 3 + ++/* P3 */ + #define UB_DIR_CHAR(c) (((c)==UB_DIR_WRITE)? 'w': \ + (((c)==UB_DIR_READ)? 'r': 'n')) + +@@ -195,24 +196,11 @@ enum ub_scsi_cmd_state { + UB_CMDST_DONE /* Final state */ + }; + +-static char *ub_scsi_cmd_stname[] = { +- ". ", +- "Cmd", +- "dat", +- "c2s", +- "sts", +- "clr", +- "crs", +- "Sen", +- "fin" +-}; +- + struct ub_scsi_cmd { + unsigned char cdb[UB_MAX_CDB_SIZE]; + unsigned char cdb_len; + + unsigned char dir; /* 0 - none, 1 - read, 3 - write. */ +- unsigned char trace_index; + enum ub_scsi_cmd_state state; + unsigned int tag; + struct ub_scsi_cmd *next; +@@ -249,28 +237,6 @@ struct ub_capacity { + }; + + /* +- * The SCSI command tracing structure. +- */ +- +-#define SCMD_ST_HIST_SZ 8 +-#define SCMD_TRACE_SZ 63 /* Less than 4KB of 61-byte lines */ +- +-struct ub_scsi_cmd_trace { +- int hcur; +- unsigned int tag; +- unsigned int req_size, act_size; +- unsigned char op; +- unsigned char dir; +- unsigned char key, asc, ascq; +- char st_hst[SCMD_ST_HIST_SZ]; +-}; +- +-struct ub_scsi_trace { +- int cur; +- struct ub_scsi_cmd_trace vec[SCMD_TRACE_SZ]; +-}; +- +-/* + * This is a direct take-off from linux/include/completion.h + * The difference is that I do not wait on this thing, just poll. + * When I want to wait (ub_probe), I just use the stock completion. +@@ -388,7 +354,6 @@ struct ub_dev { + wait_queue_head_t reset_wait; + + int sg_stat[6]; +- struct ub_scsi_trace tr; + }; + + /* +@@ -458,137 +423,6 @@ static int ub_qlock_next = 0; + static DEFINE_SPINLOCK(ub_lock); /* Locks globals and ->openc */ + + /* +- * The SCSI command tracing procedures. +- */ +- +-static void ub_cmdtr_new(struct ub_dev *sc, struct ub_scsi_cmd *cmd) +-{ +- int n; +- struct ub_scsi_cmd_trace *t; +- +- if ((n = sc->tr.cur + 1) == SCMD_TRACE_SZ) n = 0; +- t = &sc->tr.vec[n]; +- +- memset(t, 0, sizeof(struct ub_scsi_cmd_trace)); +- t->tag = cmd->tag; +- t->op = cmd->cdb[0]; +- t->dir = cmd->dir; +- t->req_size = cmd->len; +- t->st_hst[0] = cmd->state; +- +- sc->tr.cur = n; +- cmd->trace_index = n; +-} +- +-static void ub_cmdtr_state(struct ub_dev *sc, struct ub_scsi_cmd *cmd) +-{ +- int n; +- struct ub_scsi_cmd_trace *t; +- +- t = &sc->tr.vec[cmd->trace_index]; +- if (t->tag == cmd->tag) { +- if ((n = t->hcur + 1) == SCMD_ST_HIST_SZ) n = 0; +- t->st_hst[n] = cmd->state; +- t->hcur = n; +- } +-} +- +-static void ub_cmdtr_act_len(struct ub_dev *sc, struct ub_scsi_cmd *cmd) +-{ +- struct ub_scsi_cmd_trace *t; +- +- t = &sc->tr.vec[cmd->trace_index]; +- if (t->tag == cmd->tag) +- t->act_size = cmd->act_len; +-} +- +-static void ub_cmdtr_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd, +- unsigned char *sense) +-{ +- struct ub_scsi_cmd_trace *t; +- +- t = &sc->tr.vec[cmd->trace_index]; +- if (t->tag == cmd->tag) { +- t->key = sense[2] & 0x0F; +- t->asc = sense[12]; +- t->ascq = sense[13]; +- } +-} +- +-static ssize_t ub_diag_show(struct device *dev, struct device_attribute *attr, +- char *page) +-{ +- struct usb_interface *intf; +- struct ub_dev *sc; +- struct list_head *p; +- struct ub_lun *lun; +- int cnt; +- unsigned long flags; +- int nc, nh; +- int i, j; +- struct ub_scsi_cmd_trace *t; +- +- intf = to_usb_interface(dev); +- sc = usb_get_intfdata(intf); +- if (sc == NULL) +- return 0; +- +- cnt = 0; +- spin_lock_irqsave(sc->lock, flags); +- +- cnt += sprintf(page + cnt, +- "poison %d reset %d\n", +- atomic_read(&sc->poison), sc->reset); +- cnt += sprintf(page + cnt, +- "qlen %d qmax %d\n", +- sc->cmd_queue.qlen, sc->cmd_queue.qmax); +- cnt += sprintf(page + cnt, +- "sg %d %d %d %d %d .. %d\n", +- sc->sg_stat[0], +- sc->sg_stat[1], +- sc->sg_stat[2], +- sc->sg_stat[3], +- sc->sg_stat[4], +- sc->sg_stat[5]); +- +- list_for_each (p, &sc->luns) { +- lun = list_entry(p, struct ub_lun, link); +- cnt += sprintf(page + cnt, +- "lun %u changed %d removable %d readonly %d\n", +- lun->num, lun->changed, lun->removable, lun->readonly); +- } +- +- if ((nc = sc->tr.cur + 1) == SCMD_TRACE_SZ) nc = 0; +- for (j = 0; j < SCMD_TRACE_SZ; j++) { +- t = &sc->tr.vec[nc]; +- +- cnt += sprintf(page + cnt, "%08x %02x", t->tag, t->op); +- if (t->op == REQUEST_SENSE) { +- cnt += sprintf(page + cnt, " [sense %x %02x %02x]", +- t->key, t->asc, t->ascq); +- } else { +- cnt += sprintf(page + cnt, " %c", UB_DIR_CHAR(t->dir)); +- cnt += sprintf(page + cnt, " [%5d %5d]", +- t->req_size, t->act_size); +- } +- if ((nh = t->hcur + 1) == SCMD_ST_HIST_SZ) nh = 0; +- for (i = 0; i < SCMD_ST_HIST_SZ; i++) { +- cnt += sprintf(page + cnt, " %s", +- ub_scsi_cmd_stname[(int)t->st_hst[nh]]); +- if (++nh == SCMD_ST_HIST_SZ) nh = 0; +- } +- cnt += sprintf(page + cnt, "\n"); +- +- if (++nc == SCMD_TRACE_SZ) nc = 0; +- } +- +- spin_unlock_irqrestore(sc->lock, flags); +- return cnt; +-} +- +-static DEVICE_ATTR(diag, S_IRUGO, ub_diag_show, NULL); /* N.B. World readable */ +- +-/* + * The id allocator. + * + * This also stores the host for indexing by minor, which is somewhat dirty. +@@ -1090,7 +924,6 @@ static int ub_scsi_cmd_start(struct ub_d + add_timer(&sc->work_timer); + + cmd->state = UB_CMDST_CMD; +- ub_cmdtr_state(sc, cmd); + return 0; + } + +@@ -1143,12 +976,10 @@ static void ub_scsi_dispatch(struct ub_d + ub_cmdq_pop(sc); + (*cmd->done)(sc, cmd); + } else if (cmd->state == UB_CMDST_INIT) { +- ub_cmdtr_new(sc, cmd); + if ((rc = ub_scsi_cmd_start(sc, cmd)) == 0) + break; + cmd->error = rc; + cmd->state = UB_CMDST_DONE; +- ub_cmdtr_state(sc, cmd); + } else { + if (!ub_is_completed(&sc->work_done)) + break; +@@ -1245,7 +1076,6 @@ static void ub_scsi_urb_compl(struct ub_ + return; + } + cmd->state = UB_CMDST_CLEAR; +- ub_cmdtr_state(sc, cmd); + return; + case -ESHUTDOWN: /* unplug */ + case -EILSEQ: /* unplug timeout on uhci */ +@@ -1277,7 +1107,6 @@ static void ub_scsi_urb_compl(struct ub_ + return; + } + cmd->state = UB_CMDST_CLR2STS; +- ub_cmdtr_state(sc, cmd); + return; + } + if (urb->status == -EOVERFLOW) { +@@ -1302,7 +1131,6 @@ static void ub_scsi_urb_compl(struct ub_ + if (urb->status != 0 || + len != cmd->sgv[cmd->current_sg].length) { + cmd->act_len += len; +- ub_cmdtr_act_len(sc, cmd); + + cmd->error = -EIO; + ub_state_stat(sc, cmd); +@@ -1329,7 +1157,6 @@ static void ub_scsi_urb_compl(struct ub_ + } + + cmd->act_len += urb->actual_length; +- ub_cmdtr_act_len(sc, cmd); + + if (++cmd->current_sg < cmd->nsg) { + ub_data_start(sc, cmd); +@@ -1355,7 +1182,6 @@ static void ub_scsi_urb_compl(struct ub_ + cmd->error = -EIO; /* A cheap trick... */ + + cmd->state = UB_CMDST_CLRRS; +- ub_cmdtr_state(sc, cmd); + return; + } + +@@ -1439,7 +1265,6 @@ static void ub_scsi_urb_compl(struct ub_ + return; + } + cmd->state = UB_CMDST_DONE; +- ub_cmdtr_state(sc, cmd); + ub_cmdq_pop(sc); + (*cmd->done)(sc, cmd); + +@@ -1494,7 +1319,6 @@ static void ub_data_start(struct ub_dev + add_timer(&sc->work_timer); + + cmd->state = UB_CMDST_DATA; +- ub_cmdtr_state(sc, cmd); + } + + /* +@@ -1506,7 +1330,6 @@ static void ub_state_done(struct ub_dev + + cmd->error = rc; + cmd->state = UB_CMDST_DONE; +- ub_cmdtr_state(sc, cmd); + ub_cmdq_pop(sc); + (*cmd->done)(sc, cmd); + } +@@ -1552,7 +1375,6 @@ static void ub_state_stat(struct ub_dev + + cmd->stat_count = 0; + cmd->state = UB_CMDST_STAT; +- ub_cmdtr_state(sc, cmd); + } + + /* +@@ -1571,7 +1393,6 @@ static void ub_state_stat_counted(struct + return; + + cmd->state = UB_CMDST_STAT; +- ub_cmdtr_state(sc, cmd); + } + + /* +@@ -1609,7 +1430,6 @@ static void ub_state_sense(struct ub_dev + scmd->tag = sc->tagcnt++; + + cmd->state = UB_CMDST_SENSE; +- ub_cmdtr_state(sc, cmd); + + ub_cmdq_insert(sc, scmd); + return; +@@ -1666,11 +1486,6 @@ static void ub_top_sense_done(struct ub_ + struct ub_scsi_cmd *cmd; + + /* +- * Ignoring scmd->act_len, because the buffer was pre-zeroed. +- */ +- ub_cmdtr_sense(sc, scmd, sense); +- +- /* + * Find the command which triggered the unit attention or a check, + * save the sense into it, and advance its state machine. + */ +@@ -1691,6 +1506,9 @@ static void ub_top_sense_done(struct ub_ + return; + } + ++ /* ++ * Ignoring scmd->act_len, because the buffer was pre-zeroed. ++ */ + cmd->key = sense[2] & 0x0F; + cmd->asc = sense[12]; + cmd->ascq = sense[13]; +@@ -2413,9 +2231,6 @@ static int ub_probe(struct usb_interface + if (ub_get_pipes(sc, sc->dev, intf) != 0) + goto err_dev_desc; + +- if (device_create_file(&sc->intf->dev, &dev_attr_diag) != 0) +- goto err_diag; +- + /* + * At this point, all USB initialization is done, do upper layer. + * We really hate halfway initialized structures, so from the +@@ -2480,8 +2295,6 @@ static int ub_probe(struct usb_interface + } + return 0; + +- /* device_remove_file(&sc->intf->dev, &dev_attr_diag); */ +-err_diag: + err_dev_desc: + usb_set_intfdata(intf, NULL); + // usb_put_intf(sc->intf); +@@ -2609,7 +2422,6 @@ static void ub_disconnect(struct usb_int + while ((cmd = ub_cmdq_peek(sc)) != NULL) { + cmd->error = -ENOTCONN; + cmd->state = UB_CMDST_DONE; +- ub_cmdtr_state(sc, cmd); + ub_cmdq_pop(sc); + (*cmd->done)(sc, cmd); + cnt++; +@@ -2660,7 +2472,6 @@ static void ub_disconnect(struct usb_int + * and no URBs left in transit. + */ + +- device_remove_file(&sc->intf->dev, &dev_attr_diag); + usb_set_intfdata(intf, NULL); + // usb_put_intf(sc->intf); + sc->intf = NULL; diff --git a/usb/usb-ub-03-drop-stall-clearing.patch b/usb/usb-ub-03-drop-stall-clearing.patch new file mode 100644 index 00000000000000..8f98647bb621b7 --- /dev/null +++ b/usb/usb-ub-03-drop-stall-clearing.patch @@ -0,0 +1,45 @@ +From zaitcev@redhat.com Thu Mar 2 16:53:17 2006 +Date: Thu, 2 Mar 2006 16:53:00 -0800 +From: Pete Zaitcev <zaitcev@redhat.com> +To: greg@kroah.com +Cc: zaitcev@redhat.com, linux-usb-devel@lists.sourceforge.net +Subject: USB: ub 03 drop stall clearing +Message-Id: <20060302165300.211eb11c.zaitcev@redhat.com> + +Matt mentioned that a very old ZIP-100 actually does need this, but I am +yet to see anyone who actually has one still working and uses ub with it. +He/she must be a retrocomputing geek, who can easily bias it to usb-storage +with libusual, if needed. Meanwhile, common folks have trouble with poorly +designed USB keys and some el-cheapo European music players. I think we +better drop this for now. + +Signed-off-by: Pete Zaitcev <zaitcev@redhat.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/block/ub.c | 13 +------------ + 1 file changed, 1 insertion(+), 12 deletions(-) + +--- gregkh-2.6.orig/drivers/block/ub.c ++++ gregkh-2.6/drivers/block/ub.c +@@ -2270,19 +2270,8 @@ static int ub_probe(struct usb_interface + + nluns = 1; + for (i = 0; i < 3; i++) { +- if ((rc = ub_sync_getmaxlun(sc)) < 0) { +- /* +- * This segment is taken from usb-storage. They say +- * that ZIP-100 needs this, but my own ZIP-100 works +- * fine without this. +- * Still, it does not seem to hurt anything. +- */ +- if (rc == -EPIPE) { +- ub_probe_clear_stall(sc, sc->recv_bulk_pipe); +- ub_probe_clear_stall(sc, sc->send_bulk_pipe); +- } ++ if ((rc = ub_sync_getmaxlun(sc)) < 0) + break; +- } + if (rc != 0) { + nluns = rc; + break; diff --git a/usb/usb-usbcore-don-t-assume-a-usb-configuration-includes-any-interfaces.patch b/usb/usb-usbcore-don-t-assume-a-usb-configuration-includes-any-interfaces.patch new file mode 100644 index 00000000000000..87289923538524 --- /dev/null +++ b/usb/usb-usbcore-don-t-assume-a-usb-configuration-includes-any-interfaces.patch @@ -0,0 +1,66 @@ +From stern@rowland.harvard.edu Wed Mar 8 12:14:14 2006 +Date: Wed, 8 Mar 2006 15:14:09 -0500 (EST) +From: Alan Stern <stern@rowland.harvard.edu> +To: David Brownell <david-b@pacbell.net> +cc: Greg KH <greg@kroah.com>, Andrew Morton <akpm@osdl.org>, Linus Torvalds <torvalds@osdl.org>, <mingo@elte.hu> +Subject: USB: usbcore: Don't assume a USB configuration includes any interfaces +Message-ID: <Pine.LNX.4.44L0.0603081509100.5360-100000@iolanthe.rowland.org> + +In a couple of places, usbcore assumes that a USB device configuration +will have a nonzero number of interfaces. Having no interfaces may or +may not be allowed by the USB spec; in any event we shouldn't die if we +encounter such a thing. This patch (as662) removes the assumptions. + +Signed-off-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/hub.c | 16 ++++++++++------ + 1 file changed, 10 insertions(+), 6 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/core/hub.c ++++ gregkh-2.6/drivers/usb/core/hub.c +@@ -1179,8 +1179,11 @@ static int choose_configuration(struct u + c = udev->config; + num_configs = udev->descriptor.bNumConfigurations; + for (i = 0; i < num_configs; (i++, c++)) { +- struct usb_interface_descriptor *desc = +- &c->intf_cache[0]->altsetting->desc; ++ struct usb_interface_descriptor *desc = NULL; ++ ++ /* It's possible that a config has no interfaces! */ ++ if (c->desc.bNumInterfaces > 0) ++ desc = &c->intf_cache[0]->altsetting->desc; + + /* + * HP's USB bus-powered keyboard has only one configuration +@@ -1215,7 +1218,8 @@ static int choose_configuration(struct u + /* If the first config's first interface is COMM/2/0xff + * (MSFT RNDIS), rule it out unless Linux has host-side + * RNDIS support. */ +- if (i == 0 && desc->bInterfaceClass == USB_CLASS_COMM ++ if (i == 0 && desc ++ && desc->bInterfaceClass == USB_CLASS_COMM + && desc->bInterfaceSubClass == 2 + && desc->bInterfaceProtocol == 0xff) { + #ifndef CONFIG_USB_NET_RNDIS +@@ -1231,8 +1235,8 @@ static int choose_configuration(struct u + * than a vendor-specific driver. */ + else if (udev->descriptor.bDeviceClass != + USB_CLASS_VENDOR_SPEC && +- desc->bInterfaceClass != +- USB_CLASS_VENDOR_SPEC) { ++ (!desc || desc->bInterfaceClass != ++ USB_CLASS_VENDOR_SPEC)) { + best = c; + break; + } +@@ -3024,7 +3028,7 @@ int usb_reset_device(struct usb_device * + parent_hub = hdev_to_hub(parent_hdev); + + /* If we're resetting an active hub, take some special actions */ +- if (udev->actconfig && ++ if (udev->actconfig && udev->actconfig->desc.bNumInterfaces > 0 && + udev->actconfig->interface[0]->dev.driver == + &hub_driver.driver && + (hub = hdev_to_hub(udev)) != NULL) { diff --git a/usb/usb-usbcore-usb_set_configuration-oops.patch b/usb/usb-usbcore-usb_set_configuration-oops.patch new file mode 100644 index 00000000000000..057dfe1016baaa --- /dev/null +++ b/usb/usb-usbcore-usb_set_configuration-oops.patch @@ -0,0 +1,43 @@ +From horst@schirmeier.com Thu Mar 9 05:10:56 2006 +Date: Thu, 9 Mar 2006 14:10:49 +0100 +From: Horst Schirmeier <horst@schirmeier.com> +To: Alan Stern <stern@rowland.harvard.edu> +Cc: Greg KH <greg@kroah.com> +Subject: USB: usbcore: usb_set_configuration oops (NULL ptr dereference) +Message-ID: <20060309131048.GL22994@quickstop.soohrt.org> +Content-Disposition: inline + +When trying to deconfigure a device via usb_set_configuration(dev, 0), +2.6.16-rc kernels after 55c527187c9d78f840b284d596a0b298bc1493af oops +with "Unable to handle NULL pointer dereference at...". This is due to +an unchecked dereference of cp in the power budget part. + +Signed-off-by: Horst Schirmeier <horst@schirmeier.com> +Acked-by: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/message.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- gregkh-2.6.orig/drivers/usb/core/message.c ++++ gregkh-2.6/drivers/usb/core/message.c +@@ -1388,11 +1388,13 @@ free_interfaces: + if (dev->state != USB_STATE_ADDRESS) + usb_disable_device (dev, 1); // Skip ep0 + +- i = dev->bus_mA - cp->desc.bMaxPower * 2; +- if (i < 0) +- dev_warn(&dev->dev, "new config #%d exceeds power " +- "limit by %dmA\n", +- configuration, -i); ++ if (cp) { ++ i = dev->bus_mA - cp->desc.bMaxPower * 2; ++ if (i < 0) ++ dev_warn(&dev->dev, "new config #%d exceeds power " ++ "limit by %dmA\n", ++ configuration, -i); ++ } + + if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_CONFIGURATION, 0, configuration, 0, |