mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 22:51:42 +00:00
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:
commit
59c0b586ae
@ -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
|
Date: July 2008
|
||||||
KernelVersion: 2.6.27
|
KernelVersion: 2.6.27
|
||||||
Contact: David Vrabel <david.vrabel@csr.com>
|
Contact: David Vrabel <david.vrabel@csr.com>
|
||||||
@ -9,7 +9,7 @@ Description:
|
|||||||
|
|
||||||
Set an all zero CHID to stop the host controller.
|
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
|
Date: July 2008
|
||||||
KernelVersion: 2.6.27
|
KernelVersion: 2.6.27
|
||||||
Contact: David Vrabel <david.vrabel@csr.com>
|
Contact: David Vrabel <david.vrabel@csr.com>
|
@ -61,11 +61,6 @@
|
|||||||
* simpler, Microsoft pushes their own approach: RNDIS. The published
|
* simpler, Microsoft pushes their own approach: RNDIS. The published
|
||||||
* RNDIS specs are ambiguous and appear to be incomplete, and are also
|
* RNDIS specs are ambiguous and appear to be incomplete, and are also
|
||||||
* needlessly complex. They borrow more from CDC ACM than CDC ECM.
|
* 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"
|
#define DRIVER_DESC "Ethernet Gadget"
|
||||||
@ -157,8 +152,8 @@ static inline bool has_rndis(void)
|
|||||||
#define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */
|
#define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */
|
||||||
|
|
||||||
/* For EEM gadgets */
|
/* For EEM gadgets */
|
||||||
#define EEM_VENDOR_NUM 0x0525 /* INVALID - NEEDS TO BE ALLOCATED */
|
#define EEM_VENDOR_NUM 0x1d6b /* Linux Foundation */
|
||||||
#define EEM_PRODUCT_NUM 0xa4a1 /* INVALID - NEEDS TO BE ALLOCATED */
|
#define EEM_PRODUCT_NUM 0x0102 /* EEM Gadget */
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -1400,6 +1400,10 @@ iso_stream_schedule (
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
period = urb->interval;
|
||||||
|
if (!stream->highspeed)
|
||||||
|
period <<= 3;
|
||||||
|
|
||||||
now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
|
now = ehci_readl(ehci, &ehci->regs->frame_index) % mod;
|
||||||
|
|
||||||
/* when's the last uframe this urb could start? */
|
/* 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)? */
|
/* Fell behind (by up to twice the slop amount)? */
|
||||||
if (start >= max - 2 * 8 * SCHEDULE_SLOP)
|
if (start >= max - 2 * 8 * SCHEDULE_SLOP)
|
||||||
start += stream->interval * DIV_ROUND_UP(
|
start += period * DIV_ROUND_UP(
|
||||||
max - start, stream->interval) - mod;
|
max - start, period) - mod;
|
||||||
|
|
||||||
/* Tried to schedule too far into the future? */
|
/* Tried to schedule too far into the future? */
|
||||||
if (unlikely((start + sched->span) >= max)) {
|
if (unlikely((start + sched->span) >= max)) {
|
||||||
@ -1441,10 +1445,6 @@ iso_stream_schedule (
|
|||||||
|
|
||||||
/* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */
|
/* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */
|
||||||
|
|
||||||
period = urb->interval;
|
|
||||||
if (!stream->highspeed)
|
|
||||||
period <<= 3;
|
|
||||||
|
|
||||||
/* find a uframe slot with enough bandwidth */
|
/* find a uframe slot with enough bandwidth */
|
||||||
for (; start < (stream->next_uframe + period); start++) {
|
for (; start < (stream->next_uframe + period); start++) {
|
||||||
int enough_space;
|
int enough_space;
|
||||||
|
@ -115,6 +115,10 @@ static uint32_t process_qset(struct whc *whc, struct whc_qset *qset)
|
|||||||
if (status & QTD_STS_HALTED) {
|
if (status & QTD_STS_HALTED) {
|
||||||
/* Ug, an error. */
|
/* Ug, an error. */
|
||||||
process_halted_qtd(whc, qset, td);
|
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;
|
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_urb *wurb = urb->hcpriv;
|
||||||
struct whc_qset *qset = wurb->qset;
|
struct whc_qset *qset = wurb->qset;
|
||||||
struct whc_std *std, *t;
|
struct whc_std *std, *t;
|
||||||
|
bool has_qtd = false;
|
||||||
int ret;
|
int ret;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
@ -315,17 +320,21 @@ int asl_urb_dequeue(struct whc *whc, struct urb *urb, int status)
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
list_for_each_entry_safe(std, t, &qset->stds, list_node) {
|
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);
|
qset_free_std(whc, std);
|
||||||
else
|
} else
|
||||||
std->qtd = NULL; /* so this std is re-added when the qset is */
|
std->qtd = NULL; /* so this std is re-added when the qset is */
|
||||||
}
|
}
|
||||||
|
|
||||||
asl_qset_remove(whc, qset);
|
if (has_qtd) {
|
||||||
wurb->status = status;
|
asl_qset_remove(whc, qset);
|
||||||
wurb->is_async = true;
|
wurb->status = status;
|
||||||
queue_work(whc->workqueue, &wurb->dequeue_work);
|
wurb->is_async = true;
|
||||||
|
queue_work(whc->workqueue, &wurb->dequeue_work);
|
||||||
|
} else
|
||||||
|
qset_remove_urb(whc, qset, urb, status);
|
||||||
out:
|
out:
|
||||||
spin_unlock_irqrestore(&whc->lock, flags);
|
spin_unlock_irqrestore(&whc->lock, flags);
|
||||||
|
|
||||||
|
@ -121,6 +121,10 @@ static enum whc_update pzl_process_qset(struct whc *whc, struct whc_qset *qset)
|
|||||||
if (status & QTD_STS_HALTED) {
|
if (status & QTD_STS_HALTED) {
|
||||||
/* Ug, an error. */
|
/* Ug, an error. */
|
||||||
process_halted_qtd(whc, qset, td);
|
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;
|
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_urb *wurb = urb->hcpriv;
|
||||||
struct whc_qset *qset = wurb->qset;
|
struct whc_qset *qset = wurb->qset;
|
||||||
struct whc_std *std, *t;
|
struct whc_std *std, *t;
|
||||||
|
bool has_qtd = false;
|
||||||
int ret;
|
int ret;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
@ -343,17 +348,22 @@ int pzl_urb_dequeue(struct whc *whc, struct urb *urb, int status)
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
list_for_each_entry_safe(std, t, &qset->stds, list_node) {
|
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);
|
qset_free_std(whc, std);
|
||||||
else
|
} else
|
||||||
std->qtd = NULL; /* so this std is re-added when the qset is */
|
std->qtd = NULL; /* so this std is re-added when the qset is */
|
||||||
}
|
}
|
||||||
|
|
||||||
pzl_qset_remove(whc, qset);
|
if (has_qtd) {
|
||||||
wurb->status = status;
|
pzl_qset_remove(whc, qset);
|
||||||
wurb->is_async = false;
|
update_pzl_hw_view(whc);
|
||||||
queue_work(whc->workqueue, &wurb->dequeue_work);
|
wurb->status = status;
|
||||||
|
wurb->is_async = false;
|
||||||
|
queue_work(whc->workqueue, &wurb->dequeue_work);
|
||||||
|
} else
|
||||||
|
qset_remove_urb(whc, qset, urb, status);
|
||||||
out:
|
out:
|
||||||
spin_unlock_irqrestore(&whc->lock, flags);
|
spin_unlock_irqrestore(&whc->lock, flags);
|
||||||
|
|
||||||
|
@ -328,6 +328,9 @@ static int option_resume(struct usb_serial *serial);
|
|||||||
#define ALCATEL_VENDOR_ID 0x1bbb
|
#define ALCATEL_VENDOR_ID 0x1bbb
|
||||||
#define ALCATEL_PRODUCT_X060S 0x0000
|
#define ALCATEL_PRODUCT_X060S 0x0000
|
||||||
|
|
||||||
|
/* Airplus products */
|
||||||
|
#define AIRPLUS_VENDOR_ID 0x1011
|
||||||
|
#define AIRPLUS_PRODUCT_MCD650 0x3198
|
||||||
|
|
||||||
static struct usb_device_id option_ids[] = {
|
static struct usb_device_id option_ids[] = {
|
||||||
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
|
{ 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(ALINK_VENDOR_ID, 0x9000) },
|
||||||
{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
|
||||||
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
|
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
|
||||||
|
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(usb, option_ids);
|
MODULE_DEVICE_TABLE(usb, option_ids);
|
||||||
|
@ -696,7 +696,7 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us)
|
|||||||
/* device supports and needs bigger sense buffer */
|
/* device supports and needs bigger sense buffer */
|
||||||
if (us->fflags & US_FL_SANE_SENSE)
|
if (us->fflags & US_FL_SANE_SENSE)
|
||||||
sense_size = ~0;
|
sense_size = ~0;
|
||||||
|
Retry_Sense:
|
||||||
US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
|
US_DEBUGP("Issuing auto-REQUEST_SENSE\n");
|
||||||
|
|
||||||
scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sense_size);
|
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;
|
srb->result = DID_ABORT << 16;
|
||||||
goto Handle_Errors;
|
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) {
|
if (temp_result != USB_STOR_TRANSPORT_GOOD) {
|
||||||
US_DEBUGP("-- auto-sense failure\n");
|
US_DEBUGP("-- auto-sense failure\n");
|
||||||
|
|
||||||
|
@ -200,35 +200,40 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc,
|
|||||||
{
|
{
|
||||||
int result, bytes, secd_size;
|
int result, bytes, secd_size;
|
||||||
struct device *dev = &usb_dev->dev;
|
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;
|
const struct usb_encryption_descriptor *etd, *ccm1_etd = NULL;
|
||||||
void *secd_buf;
|
|
||||||
const void *itr, *top;
|
const void *itr, *top;
|
||||||
char buf[64];
|
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,
|
result = usb_get_descriptor(usb_dev, USB_DT_SECURITY,
|
||||||
0, &secd, sizeof(secd));
|
0, secd, sizeof(struct usb_security_descriptor));
|
||||||
if (result < sizeof(secd)) {
|
if (result < sizeof(secd)) {
|
||||||
dev_err(dev, "Can't read security descriptor or "
|
dev_err(dev, "Can't read security descriptor or "
|
||||||
"not enough data: %d\n", result);
|
"not enough data: %d\n", result);
|
||||||
goto error_secd;
|
goto out;
|
||||||
}
|
}
|
||||||
secd_size = le16_to_cpu(secd.wTotalLength);
|
secd_size = le16_to_cpu(secd->wTotalLength);
|
||||||
secd_buf = kmalloc(secd_size, GFP_KERNEL);
|
secd = krealloc(secd, secd_size, GFP_KERNEL);
|
||||||
if (secd_buf == NULL) {
|
if (secd == NULL) {
|
||||||
dev_err(dev, "Can't allocate space for security descriptors\n");
|
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,
|
result = usb_get_descriptor(usb_dev, USB_DT_SECURITY,
|
||||||
0, secd_buf, secd_size);
|
0, secd, secd_size);
|
||||||
if (result < secd_size) {
|
if (result < secd_size) {
|
||||||
dev_err(dev, "Can't read security descriptor or "
|
dev_err(dev, "Can't read security descriptor or "
|
||||||
"not enough data: %d\n", result);
|
"not enough data: %d\n", result);
|
||||||
goto error_secd_all;
|
goto out;
|
||||||
}
|
}
|
||||||
bytes = 0;
|
bytes = 0;
|
||||||
itr = secd_buf + sizeof(secd);
|
itr = &secd[1];
|
||||||
top = secd_buf + result;
|
top = (void *)secd + result;
|
||||||
while (itr < top) {
|
while (itr < top) {
|
||||||
etd = itr;
|
etd = itr;
|
||||||
if (top - itr < sizeof(*etd)) {
|
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, "
|
dev_err(dev, "WUSB device doesn't support CCM1 encryption, "
|
||||||
"can't use!\n");
|
"can't use!\n");
|
||||||
result = -EINVAL;
|
result = -EINVAL;
|
||||||
goto error_no_ccm1;
|
goto out;
|
||||||
}
|
}
|
||||||
wusb_dev->ccm1_etd = *ccm1_etd;
|
wusb_dev->ccm1_etd = *ccm1_etd;
|
||||||
dev_dbg(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n",
|
dev_dbg(dev, "supported encryption: %s; using %s (0x%02x/%02x)\n",
|
||||||
buf, wusb_et_name(ccm1_etd->bEncryptionType),
|
buf, wusb_et_name(ccm1_etd->bEncryptionType),
|
||||||
ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex);
|
ccm1_etd->bEncryptionValue, ccm1_etd->bAuthKeyIndex);
|
||||||
result = 0;
|
result = 0;
|
||||||
kfree(secd_buf);
|
|
||||||
out:
|
out:
|
||||||
|
kfree(secd);
|
||||||
return result;
|
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)
|
void wusb_dev_sec_rm(struct wusb_dev *wusb_dev)
|
||||||
|
Loading…
Reference in New Issue
Block a user