Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6:
  USB: gadget: Fix EEM driver comments and VID/PID
  usb-storage: Workaround devices with bogus sense size
  USB: ehci: Fix IST boundary checking interval math.
  USB: option: Support for AIRPLUS MCD650 Datacard
  USB: whci-hcd: always do an update after processing a halted qTD
  USB: whci-hcd: handle early deletion of endpoints
  USB: wusb: don't use the stack to read security descriptor
  USB: rename Documentation/ABI/.../sysfs-class-usb_host
This commit is contained in:
Linus Torvalds 2009-10-15 15:05:33 -07:00
commit 59c0b586ae
8 changed files with 82 additions and 52 deletions

View file

@ -1,4 +1,4 @@
What: /sys/class/usb_host/usb_hostN/wusb_chid
What: /sys/class/uwb_rc/uwbN/wusbhc/wusb_chid
Date: July 2008
KernelVersion: 2.6.27
Contact: David Vrabel <david.vrabel@csr.com>
@ -9,7 +9,7 @@ Description:
Set an all zero CHID to stop the host controller.
What: /sys/class/usb_host/usb_hostN/wusb_trust_timeout
What: /sys/class/uwb_rc/uwbN/wusbhc/wusb_trust_timeout
Date: July 2008
KernelVersion: 2.6.27
Contact: David Vrabel <david.vrabel@csr.com>

View file

@ -61,11 +61,6 @@
* simpler, Microsoft pushes their own approach: RNDIS. The published
* RNDIS specs are ambiguous and appear to be incomplete, and are also
* needlessly complex. They borrow more from CDC ACM than CDC ECM.
*
* While CDC ECM, CDC Subset, and RNDIS are designed to extend the ethernet
* interface to the target, CDC EEM was designed to use ethernet over the USB
* link between the host and target. CDC EEM is implemented as an alternative
* to those other protocols when that communication model is more appropriate
*/
#define DRIVER_DESC "Ethernet Gadget"
@ -157,8 +152,8 @@ static inline bool has_rndis(void)
#define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */
/* For EEM gadgets */
#define EEM_VENDOR_NUM 0x0525 /* INVALID - NEEDS TO BE ALLOCATED */
#define EEM_PRODUCT_NUM 0xa4a1 /* INVALID - NEEDS TO BE ALLOCATED */
#define EEM_VENDOR_NUM 0x1d6b /* Linux Foundation */
#define EEM_PRODUCT_NUM 0x0102 /* EEM Gadget */
/*-------------------------------------------------------------------------*/

View file

@ -1400,6 +1400,10 @@ iso_stream_schedule (
goto fail;
}
period = urb->interval;
if (!stream->highspeed)
period <<= 3;
now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
/* when's the last uframe this urb could start? */
@ -1417,8 +1421,8 @@ iso_stream_schedule (
/* Fell behind (by up to twice the slop amount)? */
if (start >= max - 2 * 8 * SCHEDULE_SLOP)
start += stream->interval * DIV_ROUND_UP(
max - start, stream->interval) - mod;
start += period * DIV_ROUND_UP(
max - start, period) - mod;
/* Tried to schedule too far into the future? */
if (unlikely((start + sched->span) >= max)) {
@ -1441,10 +1445,6 @@ iso_stream_schedule (
/* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */
period = urb->interval;
if (!stream->highspeed)
period <<= 3;
/* find a uframe slot with enough bandwidth */
for (; start < (stream->next_uframe + period); start++) {
int enough_space;

View file

@ -115,6 +115,10 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset)
if (status & QTD_STS_HALTED) {
/* Ug, an error. */
process_halted_qtd(whc, qset, td);
/* A halted qTD always triggers an update
because the qset was either removed or
reactivated. */
update |= WHC_UPDATE_UPDATED;
goto done;
}
@ -305,6 +309,7 @@ int asl_urb_dequeue(struct whc *whc, struct urb *urb, int status)
struct whc_urb *wurb = urb->hcpriv;
struct whc_qset *qset = wurb->qset;
struct whc_std *std, *t;
bool has_qtd = false;
int ret;
unsigned long flags;
@ -315,17 +320,21 @@ int asl_urb_dequeue(struct whc *whc, struct urb *urb, int status)
goto out;
list_for_each_entry_safe(std, t, &qset->stds, list_node) {
if (std->urb == urb)
if (std->urb == urb) {
if (std->qtd)
has_qtd = true;
qset_free_std(whc, std);
else
} else
std->qtd = NULL; /* so this std is re-added when the qset is */
}
asl_qset_remove(whc, qset);
wurb->status = status;
wurb->is_async = true;
queue_work(whc->workqueue, &wurb->dequeue_work);
if (has_qtd) {
asl_qset_remove(whc, qset);
wurb->status = status;
wurb->is_async = true;
queue_work(whc->workqueue, &wurb->dequeue_work);
} else
qset_remove_urb(whc, qset, urb, status);
out:
spin_unlock_irqrestore(&whc->lock, flags);

View file

@ -121,6 +121,10 @@ static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset)
if (status & QTD_STS_HALTED) {
/* Ug, an error. */
process_halted_qtd(whc, qset, td);
/* A halted qTD always triggers an update
because the qset was either removed or
reactivated. */
update |= WHC_UPDATE_UPDATED;
goto done;
}
@ -333,6 +337,7 @@ int pzl_urb_dequeue(struct whc *whc, struct urb *urb, int status)
struct whc_urb *wurb = urb->hcpriv;
struct whc_qset *qset = wurb->qset;
struct whc_std *std, *t;
bool has_qtd = false;
int ret;
unsigned long flags;
@ -343,17 +348,22 @@ int pzl_urb_dequeue(struct whc *whc, struct urb *urb, int status)
goto out;
list_for_each_entry_safe(std, t, &qset->stds, list_node) {
if (std->urb == urb)
if (std->urb == urb) {
if (std->qtd)
has_qtd = true;
qset_free_std(whc, std);
else
} else
std->qtd = NULL; /* so this std is re-added when the qset is */
}
pzl_qset_remove(whc, qset);
wurb->status = status;
wurb->is_async = false;
queue_work(whc->workqueue, &wurb->dequeue_work);
if (has_qtd) {
pzl_qset_remove(whc, qset);
update_pzl_hw_view(whc);
wurb->status = status;
wurb->is_async = false;
queue_work(whc->workqueue, &wurb->dequeue_work);
} else
qset_remove_urb(whc, qset, urb, status);
out:
spin_unlock_irqrestore(&whc->lock, flags);

View file

@ -328,6 +328,9 @@ static int option_resume(struct usb_serial *serial);
#define ALCATEL_VENDOR_ID 0x1bbb
#define ALCATEL_PRODUCT_X060S 0x0000
/* Airplus products */
#define AIRPLUS_VENDOR_ID 0x1011
#define AIRPLUS_PRODUCT_MCD650 0x3198
static struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
@ -589,6 +592,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);

View file

@ -696,7 +696,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
/* device supports and needs bigger sense buffer */
if (us->fflags & US_FL_SANE_SENSE)
sense_size = ~0;
Retry_Sense:
US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size);
@ -720,6 +720,21 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
srb->result = DID_ABORT << 16;
goto Handle_Errors;
}
/* Some devices claim to support larger sense but fail when
* trying to request it. When a transport failure happens
* using US_FS_SANE_SENSE, we always retry with a standard
* (small) sense request. This fixes some USB GSM modems
*/
if (temp_result == USB_STOR_TRANSPORT_FAILED &&
(us->fflags & US_FL_SANE_SENSE) &&
sense_size != US_SENSE_SIZE) {
US_DEBUGP("-- auto-sense failure, retry small sense\n");
sense_size = US_SENSE_SIZE;
goto Retry_Sense;
}
/* Other failures */
if (temp_result != USB_STOR_TRANSPORT_GOOD) {
US_DEBUGP("-- auto-sense failure\n");

View file

@ -200,35 +200,40 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc,
{
int result, bytes, secd_size;
struct device *dev = &usb_dev->dev;
struct usb_security_descriptor secd;
struct usb_security_descriptor *secd;
const struct usb_encryption_descriptor *etd, *ccm1_etd = NULL;
void *secd_buf;
const void *itr, *top;
char buf[64];
secd = kmalloc(sizeof(struct usb_security_descriptor), GFP_KERNEL);
if (secd == NULL) {
result = -ENOMEM;
goto out;
}
result = usb_get_descriptor(usb_dev, USB_DT_SECURITY,
0, &secd, sizeof(secd));
0, secd, sizeof(struct usb_security_descriptor));
if (result < sizeof(secd)) {
dev_err(dev, "Can't read security descriptor or "
"not enough data: %d\n", result);
goto error_secd;
goto out;
}
secd_size = le16_to_cpu(secd.wTotalLength);
secd_buf = kmalloc(secd_size, GFP_KERNEL);
if (secd_buf == NULL) {
secd_size = le16_to_cpu(secd->wTotalLength);
secd = krealloc(secd, secd_size, GFP_KERNEL);
if (secd == NULL) {
dev_err(dev, "Can't allocate space for security descriptors\n");
goto error_secd_alloc;
goto out;
}
result = usb_get_descriptor(usb_dev, USB_DT_SECURITY,
0, secd_buf, secd_size);
0, secd, secd_size);
if (result < secd_size) {
dev_err(dev, "Can't read security descriptor or "
"not enough data: %d\n", result);
goto error_secd_all;
goto out;
}
bytes = 0;
itr = secd_buf + sizeof(secd);
top = secd_buf + result;
itr = &secd[1];
top = (void *)secd + result;
while (itr < top) {
etd = itr;
if (top - itr < sizeof(*etd)) {
@ -259,24 +264,16 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc,
dev_err(dev, "WUSB device doesn't support CCM1 encryption, "
"can't use!\n");
result = -EINVAL;
goto error_no_ccm1;
goto out;
}
wusb_dev->ccm1_etd = *ccm1_etd;
dev_dbg(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n",
buf, wusb_et_name(ccm1_etd->bEncryptionType),
ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex);
result = 0;
kfree(secd_buf);
out:
kfree(secd);
return result;
error_no_ccm1:
error_secd_all:
kfree(secd_buf);
error_secd_alloc:
error_secd:
goto out;
}
void wusb_dev_sec_rm(struct wusb_dev *wusb_dev)