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: (22 commits) USB: gadget: f_mass_storage: stale common->fsg value bug fix USB: gadget: f_mass_storage: fixed fs descriptors not being updated USB: musb: Enable the maximum supported burst mode for DMA USB: musb: fix Blackfin ulpi stubs USB: MUSB: make non-OMAP platforms build with CONFIG_PM=y USB: musb_core: make disconnect and suspend interrupts work again USB: obey the sysfs power/wakeup setting USB: gadget eth: Fix calculate CRC32 in EEM USB: qcserial: fix a memory leak in qcprobe error path USB: gadget/printer, fix sleep inside atomic USB: isp1362-hcd, fix double lock USB: serial: ftdi: correct merge conflict with CONTEC id USB: fix oops in usb_sg_init() USB: s3c2410: deactivate endpoints before gadget unbinding USB: ehci-mxc: bail out on transceiver problems USB: otg/ulpi: bail out on read errors usb: musb: Fix a bug by making suspend interrupt available in device mode USB: r8a66597: Fix failure in change of status USB: xHCI: Fix bug in link TRB activation change. USB: gadget: g_fs: possible invalid pointer reference bug fixed ...
This commit is contained in:
commit
9f2952dbcb
|
@ -1272,8 +1272,7 @@ static int usb_resume_both(struct usb_device *udev, pm_message_t msg)
|
||||||
|
|
||||||
static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
|
static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
|
||||||
{
|
{
|
||||||
int w, i;
|
int w;
|
||||||
struct usb_interface *intf;
|
|
||||||
|
|
||||||
/* Remote wakeup is needed only when we actually go to sleep.
|
/* Remote wakeup is needed only when we actually go to sleep.
|
||||||
* For things like FREEZE and QUIESCE, if the device is already
|
* For things like FREEZE and QUIESCE, if the device is already
|
||||||
|
@ -1285,16 +1284,10 @@ static void choose_wakeup(struct usb_device *udev, pm_message_t msg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If remote wakeup is permitted, see whether any interface drivers
|
/* Enable remote wakeup if it is allowed, even if no interface drivers
|
||||||
* actually want it.
|
* actually want it.
|
||||||
*/
|
*/
|
||||||
w = 0;
|
w = device_may_wakeup(&udev->dev);
|
||||||
if (device_may_wakeup(&udev->dev) && udev->actconfig) {
|
|
||||||
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
|
|
||||||
intf = udev->actconfig->interface[i];
|
|
||||||
w |= intf->needs_remote_wakeup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the device is autosuspended with the wrong wakeup setting,
|
/* If the device is autosuspended with the wrong wakeup setting,
|
||||||
* autoresume now so the setting can be changed.
|
* autoresume now so the setting can be changed.
|
||||||
|
|
|
@ -416,8 +416,11 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
|
||||||
/* A length of zero means transfer the whole sg list */
|
/* A length of zero means transfer the whole sg list */
|
||||||
len = length;
|
len = length;
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
for_each_sg(sg, sg, nents, i)
|
struct scatterlist *sg2;
|
||||||
len += sg->length;
|
int j;
|
||||||
|
|
||||||
|
for_each_sg(sg, sg2, nents, j)
|
||||||
|
len += sg2->length;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -469,8 +469,7 @@ static int eem_unwrap(struct gether *port,
|
||||||
crc = get_unaligned_le32(skb->data + len
|
crc = get_unaligned_le32(skb->data + len
|
||||||
- ETH_FCS_LEN);
|
- ETH_FCS_LEN);
|
||||||
crc2 = ~crc32_le(~0,
|
crc2 = ~crc32_le(~0,
|
||||||
skb->data,
|
skb->data, len - ETH_FCS_LEN);
|
||||||
skb->len - ETH_FCS_LEN);
|
|
||||||
} else {
|
} else {
|
||||||
crc = get_unaligned_be32(skb->data + len
|
crc = get_unaligned_be32(skb->data + len
|
||||||
- ETH_FCS_LEN);
|
- ETH_FCS_LEN);
|
||||||
|
|
|
@ -321,8 +321,8 @@ struct fsg_dev;
|
||||||
/* Data shared by all the FSG instances. */
|
/* Data shared by all the FSG instances. */
|
||||||
struct fsg_common {
|
struct fsg_common {
|
||||||
struct usb_gadget *gadget;
|
struct usb_gadget *gadget;
|
||||||
struct fsg_dev *fsg;
|
struct fsg_dev *fsg, *new_fsg;
|
||||||
struct fsg_dev *prev_fsg;
|
wait_queue_head_t fsg_wait;
|
||||||
|
|
||||||
/* filesem protects: backing files in use */
|
/* filesem protects: backing files in use */
|
||||||
struct rw_semaphore filesem;
|
struct rw_semaphore filesem;
|
||||||
|
@ -351,7 +351,6 @@ struct fsg_common {
|
||||||
enum fsg_state state; /* For exception handling */
|
enum fsg_state state; /* For exception handling */
|
||||||
unsigned int exception_req_tag;
|
unsigned int exception_req_tag;
|
||||||
|
|
||||||
u8 config, new_config;
|
|
||||||
enum data_direction data_dir;
|
enum data_direction data_dir;
|
||||||
u32 data_size;
|
u32 data_size;
|
||||||
u32 data_size_from_cmnd;
|
u32 data_size_from_cmnd;
|
||||||
|
@ -595,7 +594,7 @@ static int fsg_setup(struct usb_function *f,
|
||||||
u16 w_value = le16_to_cpu(ctrl->wValue);
|
u16 w_value = le16_to_cpu(ctrl->wValue);
|
||||||
u16 w_length = le16_to_cpu(ctrl->wLength);
|
u16 w_length = le16_to_cpu(ctrl->wLength);
|
||||||
|
|
||||||
if (!fsg->common->config)
|
if (!fsg_is_set(fsg->common))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
switch (ctrl->bRequest) {
|
switch (ctrl->bRequest) {
|
||||||
|
@ -2303,24 +2302,20 @@ static int alloc_request(struct fsg_common *common, struct usb_ep *ep,
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Reset interface setting and re-init endpoint state (toggle etc). */
|
||||||
* Reset interface setting and re-init endpoint state (toggle etc).
|
static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg)
|
||||||
* Call with altsetting < 0 to disable the interface. The only other
|
|
||||||
* available altsetting is 0, which enables the interface.
|
|
||||||
*/
|
|
||||||
static int do_set_interface(struct fsg_common *common, int altsetting)
|
|
||||||
{
|
{
|
||||||
int rc = 0;
|
const struct usb_endpoint_descriptor *d;
|
||||||
int i;
|
struct fsg_dev *fsg;
|
||||||
const struct usb_endpoint_descriptor *d;
|
int i, rc = 0;
|
||||||
|
|
||||||
if (common->running)
|
if (common->running)
|
||||||
DBG(common, "reset interface\n");
|
DBG(common, "reset interface\n");
|
||||||
|
|
||||||
reset:
|
reset:
|
||||||
/* Deallocate the requests */
|
/* Deallocate the requests */
|
||||||
if (common->prev_fsg) {
|
if (common->fsg) {
|
||||||
struct fsg_dev *fsg = common->prev_fsg;
|
fsg = common->fsg;
|
||||||
|
|
||||||
for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
|
for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
|
||||||
struct fsg_buffhd *bh = &common->buffhds[i];
|
struct fsg_buffhd *bh = &common->buffhds[i];
|
||||||
|
@ -2345,88 +2340,53 @@ reset:
|
||||||
fsg->bulk_out_enabled = 0;
|
fsg->bulk_out_enabled = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
common->prev_fsg = 0;
|
common->fsg = NULL;
|
||||||
|
wake_up(&common->fsg_wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
common->running = 0;
|
common->running = 0;
|
||||||
if (altsetting < 0 || rc != 0)
|
if (!new_fsg || rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
DBG(common, "set interface %d\n", altsetting);
|
common->fsg = new_fsg;
|
||||||
|
fsg = common->fsg;
|
||||||
|
|
||||||
if (fsg_is_set(common)) {
|
/* Enable the endpoints */
|
||||||
struct fsg_dev *fsg = common->fsg;
|
d = fsg_ep_desc(common->gadget,
|
||||||
common->prev_fsg = common->fsg;
|
&fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
|
||||||
|
rc = enable_endpoint(common, fsg->bulk_in, d);
|
||||||
|
if (rc)
|
||||||
|
goto reset;
|
||||||
|
fsg->bulk_in_enabled = 1;
|
||||||
|
|
||||||
/* Enable the endpoints */
|
d = fsg_ep_desc(common->gadget,
|
||||||
d = fsg_ep_desc(common->gadget,
|
&fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
|
||||||
&fsg_fs_bulk_in_desc, &fsg_hs_bulk_in_desc);
|
rc = enable_endpoint(common, fsg->bulk_out, d);
|
||||||
rc = enable_endpoint(common, fsg->bulk_in, d);
|
if (rc)
|
||||||
|
goto reset;
|
||||||
|
fsg->bulk_out_enabled = 1;
|
||||||
|
common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
|
||||||
|
clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
|
||||||
|
|
||||||
|
/* Allocate the requests */
|
||||||
|
for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
|
||||||
|
struct fsg_buffhd *bh = &common->buffhds[i];
|
||||||
|
|
||||||
|
rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto reset;
|
goto reset;
|
||||||
fsg->bulk_in_enabled = 1;
|
rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
|
||||||
|
|
||||||
d = fsg_ep_desc(common->gadget,
|
|
||||||
&fsg_fs_bulk_out_desc, &fsg_hs_bulk_out_desc);
|
|
||||||
rc = enable_endpoint(common, fsg->bulk_out, d);
|
|
||||||
if (rc)
|
if (rc)
|
||||||
goto reset;
|
goto reset;
|
||||||
fsg->bulk_out_enabled = 1;
|
bh->inreq->buf = bh->outreq->buf = bh->buf;
|
||||||
common->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize);
|
bh->inreq->context = bh->outreq->context = bh;
|
||||||
clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
|
bh->inreq->complete = bulk_in_complete;
|
||||||
|
bh->outreq->complete = bulk_out_complete;
|
||||||
/* Allocate the requests */
|
|
||||||
for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
|
|
||||||
struct fsg_buffhd *bh = &common->buffhds[i];
|
|
||||||
|
|
||||||
rc = alloc_request(common, fsg->bulk_in, &bh->inreq);
|
|
||||||
if (rc)
|
|
||||||
goto reset;
|
|
||||||
rc = alloc_request(common, fsg->bulk_out, &bh->outreq);
|
|
||||||
if (rc)
|
|
||||||
goto reset;
|
|
||||||
bh->inreq->buf = bh->outreq->buf = bh->buf;
|
|
||||||
bh->inreq->context = bh->outreq->context = bh;
|
|
||||||
bh->inreq->complete = bulk_in_complete;
|
|
||||||
bh->outreq->complete = bulk_out_complete;
|
|
||||||
}
|
|
||||||
|
|
||||||
common->running = 1;
|
|
||||||
for (i = 0; i < common->nluns; ++i)
|
|
||||||
common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
|
|
||||||
return rc;
|
|
||||||
} else {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Change our operational configuration. This code must agree with the code
|
|
||||||
* that returns config descriptors, and with interface altsetting code.
|
|
||||||
*
|
|
||||||
* It's also responsible for power management interactions. Some
|
|
||||||
* configurations might not work with our current power sources.
|
|
||||||
* For now we just assume the gadget is always self-powered.
|
|
||||||
*/
|
|
||||||
static int do_set_config(struct fsg_common *common, u8 new_config)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
/* Disable the single interface */
|
|
||||||
if (common->config != 0) {
|
|
||||||
DBG(common, "reset config\n");
|
|
||||||
common->config = 0;
|
|
||||||
rc = do_set_interface(common, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable the interface */
|
common->running = 1;
|
||||||
if (new_config != 0) {
|
for (i = 0; i < common->nluns; ++i)
|
||||||
common->config = new_config;
|
common->luns[i].unit_attention_data = SS_RESET_OCCURRED;
|
||||||
rc = do_set_interface(common, 0);
|
|
||||||
if (rc != 0)
|
|
||||||
common->config = 0; /* Reset on errors */
|
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2437,9 +2397,7 @@ static int do_set_config(struct fsg_common *common, u8 new_config)
|
||||||
static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
||||||
{
|
{
|
||||||
struct fsg_dev *fsg = fsg_from_func(f);
|
struct fsg_dev *fsg = fsg_from_func(f);
|
||||||
fsg->common->prev_fsg = fsg->common->fsg;
|
fsg->common->new_fsg = fsg;
|
||||||
fsg->common->fsg = fsg;
|
|
||||||
fsg->common->new_config = 1;
|
|
||||||
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
|
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2447,9 +2405,7 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
|
||||||
static void fsg_disable(struct usb_function *f)
|
static void fsg_disable(struct usb_function *f)
|
||||||
{
|
{
|
||||||
struct fsg_dev *fsg = fsg_from_func(f);
|
struct fsg_dev *fsg = fsg_from_func(f);
|
||||||
fsg->common->prev_fsg = fsg->common->fsg;
|
fsg->common->new_fsg = NULL;
|
||||||
fsg->common->fsg = fsg;
|
|
||||||
fsg->common->new_config = 0;
|
|
||||||
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
|
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2459,19 +2415,17 @@ static void fsg_disable(struct usb_function *f)
|
||||||
static void handle_exception(struct fsg_common *common)
|
static void handle_exception(struct fsg_common *common)
|
||||||
{
|
{
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
int sig;
|
|
||||||
int i;
|
int i;
|
||||||
struct fsg_buffhd *bh;
|
struct fsg_buffhd *bh;
|
||||||
enum fsg_state old_state;
|
enum fsg_state old_state;
|
||||||
u8 new_config;
|
|
||||||
struct fsg_lun *curlun;
|
struct fsg_lun *curlun;
|
||||||
unsigned int exception_req_tag;
|
unsigned int exception_req_tag;
|
||||||
int rc;
|
|
||||||
|
|
||||||
/* Clear the existing signals. Anything but SIGUSR1 is converted
|
/* Clear the existing signals. Anything but SIGUSR1 is converted
|
||||||
* into a high-priority EXIT exception. */
|
* into a high-priority EXIT exception. */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
sig = dequeue_signal_lock(current, ¤t->blocked, &info);
|
int sig =
|
||||||
|
dequeue_signal_lock(current, ¤t->blocked, &info);
|
||||||
if (!sig)
|
if (!sig)
|
||||||
break;
|
break;
|
||||||
if (sig != SIGUSR1) {
|
if (sig != SIGUSR1) {
|
||||||
|
@ -2482,7 +2436,7 @@ static void handle_exception(struct fsg_common *common)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cancel all the pending transfers */
|
/* Cancel all the pending transfers */
|
||||||
if (fsg_is_set(common)) {
|
if (likely(common->fsg)) {
|
||||||
for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
|
for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
|
||||||
bh = &common->buffhds[i];
|
bh = &common->buffhds[i];
|
||||||
if (bh->inreq_busy)
|
if (bh->inreq_busy)
|
||||||
|
@ -2523,7 +2477,6 @@ static void handle_exception(struct fsg_common *common)
|
||||||
common->next_buffhd_to_fill = &common->buffhds[0];
|
common->next_buffhd_to_fill = &common->buffhds[0];
|
||||||
common->next_buffhd_to_drain = &common->buffhds[0];
|
common->next_buffhd_to_drain = &common->buffhds[0];
|
||||||
exception_req_tag = common->exception_req_tag;
|
exception_req_tag = common->exception_req_tag;
|
||||||
new_config = common->new_config;
|
|
||||||
old_state = common->state;
|
old_state = common->state;
|
||||||
|
|
||||||
if (old_state == FSG_STATE_ABORT_BULK_OUT)
|
if (old_state == FSG_STATE_ABORT_BULK_OUT)
|
||||||
|
@ -2573,12 +2526,12 @@ static void handle_exception(struct fsg_common *common)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FSG_STATE_CONFIG_CHANGE:
|
case FSG_STATE_CONFIG_CHANGE:
|
||||||
rc = do_set_config(common, new_config);
|
do_set_interface(common, common->new_fsg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FSG_STATE_EXIT:
|
case FSG_STATE_EXIT:
|
||||||
case FSG_STATE_TERMINATED:
|
case FSG_STATE_TERMINATED:
|
||||||
do_set_config(common, 0); /* Free resources */
|
do_set_interface(common, NULL); /* Free resources */
|
||||||
spin_lock_irq(&common->lock);
|
spin_lock_irq(&common->lock);
|
||||||
common->state = FSG_STATE_TERMINATED; /* Stop the thread */
|
common->state = FSG_STATE_TERMINATED; /* Stop the thread */
|
||||||
spin_unlock_irq(&common->lock);
|
spin_unlock_irq(&common->lock);
|
||||||
|
@ -2863,6 +2816,7 @@ buffhds_first_it:
|
||||||
goto error_release;
|
goto error_release;
|
||||||
}
|
}
|
||||||
init_completion(&common->thread_notifier);
|
init_completion(&common->thread_notifier);
|
||||||
|
init_waitqueue_head(&common->fsg_wait);
|
||||||
#undef OR
|
#undef OR
|
||||||
|
|
||||||
|
|
||||||
|
@ -2957,9 +2911,17 @@ static void fsg_common_release(struct kref *ref)
|
||||||
static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
|
static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
|
||||||
{
|
{
|
||||||
struct fsg_dev *fsg = fsg_from_func(f);
|
struct fsg_dev *fsg = fsg_from_func(f);
|
||||||
|
struct fsg_common *common = fsg->common;
|
||||||
|
|
||||||
DBG(fsg, "unbind\n");
|
DBG(fsg, "unbind\n");
|
||||||
fsg_common_put(fsg->common);
|
if (fsg->common->fsg == fsg) {
|
||||||
|
fsg->common->new_fsg = NULL;
|
||||||
|
raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
|
||||||
|
/* FIXME: make interruptible or killable somehow? */
|
||||||
|
wait_event(common->fsg_wait, common->fsg != fsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
fsg_common_put(common);
|
||||||
usb_free_descriptors(fsg->function.descriptors);
|
usb_free_descriptors(fsg->function.descriptors);
|
||||||
usb_free_descriptors(fsg->function.hs_descriptors);
|
usb_free_descriptors(fsg->function.hs_descriptors);
|
||||||
kfree(fsg);
|
kfree(fsg);
|
||||||
|
@ -2970,7 +2932,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
{
|
{
|
||||||
struct fsg_dev *fsg = fsg_from_func(f);
|
struct fsg_dev *fsg = fsg_from_func(f);
|
||||||
struct usb_gadget *gadget = c->cdev->gadget;
|
struct usb_gadget *gadget = c->cdev->gadget;
|
||||||
int rc;
|
|
||||||
int i;
|
int i;
|
||||||
struct usb_ep *ep;
|
struct usb_ep *ep;
|
||||||
|
|
||||||
|
@ -2996,6 +2957,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
ep->driver_data = fsg->common; /* claim the endpoint */
|
ep->driver_data = fsg->common; /* claim the endpoint */
|
||||||
fsg->bulk_out = ep;
|
fsg->bulk_out = ep;
|
||||||
|
|
||||||
|
/* Copy descriptors */
|
||||||
|
f->descriptors = usb_copy_descriptors(fsg_fs_function);
|
||||||
|
if (unlikely(!f->descriptors))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
if (gadget_is_dualspeed(gadget)) {
|
if (gadget_is_dualspeed(gadget)) {
|
||||||
/* Assume endpoint addresses are the same for both speeds */
|
/* Assume endpoint addresses are the same for both speeds */
|
||||||
fsg_hs_bulk_in_desc.bEndpointAddress =
|
fsg_hs_bulk_in_desc.bEndpointAddress =
|
||||||
|
@ -3003,16 +2969,17 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
|
||||||
fsg_hs_bulk_out_desc.bEndpointAddress =
|
fsg_hs_bulk_out_desc.bEndpointAddress =
|
||||||
fsg_fs_bulk_out_desc.bEndpointAddress;
|
fsg_fs_bulk_out_desc.bEndpointAddress;
|
||||||
f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
|
f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
|
||||||
if (unlikely(!f->hs_descriptors))
|
if (unlikely(!f->hs_descriptors)) {
|
||||||
|
usb_free_descriptors(f->descriptors);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
autoconf_fail:
|
autoconf_fail:
|
||||||
ERROR(fsg, "unable to autoconfigure all endpoints\n");
|
ERROR(fsg, "unable to autoconfigure all endpoints\n");
|
||||||
rc = -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3036,11 +3003,6 @@ static int fsg_add(struct usb_composite_dev *cdev,
|
||||||
|
|
||||||
fsg->function.name = FSG_DRIVER_DESC;
|
fsg->function.name = FSG_DRIVER_DESC;
|
||||||
fsg->function.strings = fsg_strings_array;
|
fsg->function.strings = fsg_strings_array;
|
||||||
fsg->function.descriptors = usb_copy_descriptors(fsg_fs_function);
|
|
||||||
if (unlikely(!fsg->function.descriptors)) {
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto error_free_fsg;
|
|
||||||
}
|
|
||||||
fsg->function.bind = fsg_bind;
|
fsg->function.bind = fsg_bind;
|
||||||
fsg->function.unbind = fsg_unbind;
|
fsg->function.unbind = fsg_unbind;
|
||||||
fsg->function.setup = fsg_setup;
|
fsg->function.setup = fsg_setup;
|
||||||
|
@ -3056,19 +3018,9 @@ static int fsg_add(struct usb_composite_dev *cdev,
|
||||||
|
|
||||||
rc = usb_add_function(c, &fsg->function);
|
rc = usb_add_function(c, &fsg->function);
|
||||||
if (unlikely(rc))
|
if (unlikely(rc))
|
||||||
goto error_free_all;
|
kfree(fsg);
|
||||||
|
else
|
||||||
fsg_common_get(fsg->common);
|
fsg_common_get(fsg->common);
|
||||||
return 0;
|
|
||||||
|
|
||||||
error_free_all:
|
|
||||||
usb_free_descriptors(fsg->function.descriptors);
|
|
||||||
/* fsg_bind() might have copied those; or maybe not? who cares
|
|
||||||
* -- free it just in case. */
|
|
||||||
usb_free_descriptors(fsg->function.hs_descriptors);
|
|
||||||
error_free_fsg:
|
|
||||||
kfree(fsg);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -392,6 +392,17 @@ static int __gfs_do_config(struct usb_configuration *c,
|
||||||
if (unlikely(ret < 0))
|
if (unlikely(ret < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* After previous do_configs there may be some invalid
|
||||||
|
* pointers in c->interface array. This happens every time
|
||||||
|
* a user space function with fewer interfaces than a user
|
||||||
|
* space function that was run before the new one is run. The
|
||||||
|
* compasit's set_config() assumes that if there is no more
|
||||||
|
* then MAX_CONFIG_INTERFACES interfaces in a configuration
|
||||||
|
* then there is a NULL pointer after the last interface in
|
||||||
|
* c->interface array. We need to make sure this is true. */
|
||||||
|
if (c->next_interface_id < ARRAY_SIZE(c->interface))
|
||||||
|
c->interface[c->next_interface_id] = NULL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ static struct class *usb_gadget_class;
|
||||||
struct printer_dev {
|
struct printer_dev {
|
||||||
spinlock_t lock; /* lock this structure */
|
spinlock_t lock; /* lock this structure */
|
||||||
/* lock buffer lists during read/write calls */
|
/* lock buffer lists during read/write calls */
|
||||||
spinlock_t lock_printer_io;
|
struct mutex lock_printer_io;
|
||||||
struct usb_gadget *gadget;
|
struct usb_gadget *gadget;
|
||||||
struct usb_request *req; /* for control responses */
|
struct usb_request *req; /* for control responses */
|
||||||
u8 config;
|
u8 config;
|
||||||
|
@ -567,7 +567,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
|
||||||
|
|
||||||
DBG(dev, "printer_read trying to read %d bytes\n", (int)len);
|
DBG(dev, "printer_read trying to read %d bytes\n", (int)len);
|
||||||
|
|
||||||
spin_lock(&dev->lock_printer_io);
|
mutex_lock(&dev->lock_printer_io);
|
||||||
spin_lock_irqsave(&dev->lock, flags);
|
spin_lock_irqsave(&dev->lock, flags);
|
||||||
|
|
||||||
/* We will use this flag later to check if a printer reset happened
|
/* We will use this flag later to check if a printer reset happened
|
||||||
|
@ -601,7 +601,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
|
||||||
* call or not.
|
* call or not.
|
||||||
*/
|
*/
|
||||||
if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
|
if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
|
||||||
spin_unlock(&dev->lock_printer_io);
|
mutex_unlock(&dev->lock_printer_io);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -648,7 +648,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
|
||||||
if (dev->reset_printer) {
|
if (dev->reset_printer) {
|
||||||
list_add(¤t_rx_req->list, &dev->rx_reqs);
|
list_add(¤t_rx_req->list, &dev->rx_reqs);
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
spin_unlock(&dev->lock_printer_io);
|
mutex_unlock(&dev->lock_printer_io);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -673,7 +673,7 @@ printer_read(struct file *fd, char __user *buf, size_t len, loff_t *ptr)
|
||||||
dev->current_rx_buf = current_rx_buf;
|
dev->current_rx_buf = current_rx_buf;
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
spin_unlock(&dev->lock_printer_io);
|
mutex_unlock(&dev->lock_printer_io);
|
||||||
|
|
||||||
DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);
|
DBG(dev, "printer_read returned %d bytes\n", (int)bytes_copied);
|
||||||
|
|
||||||
|
@ -697,7 +697,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
||||||
if (len == 0)
|
if (len == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
spin_lock(&dev->lock_printer_io);
|
mutex_lock(&dev->lock_printer_io);
|
||||||
spin_lock_irqsave(&dev->lock, flags);
|
spin_lock_irqsave(&dev->lock, flags);
|
||||||
|
|
||||||
/* Check if a printer reset happens while we have interrupts on */
|
/* Check if a printer reset happens while we have interrupts on */
|
||||||
|
@ -713,7 +713,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
||||||
* a NON-Blocking call or not.
|
* a NON-Blocking call or not.
|
||||||
*/
|
*/
|
||||||
if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
|
if (fd->f_flags & (O_NONBLOCK|O_NDELAY)) {
|
||||||
spin_unlock(&dev->lock_printer_io);
|
mutex_unlock(&dev->lock_printer_io);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -752,7 +752,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
||||||
|
|
||||||
if (copy_from_user(req->buf, buf, size)) {
|
if (copy_from_user(req->buf, buf, size)) {
|
||||||
list_add(&req->list, &dev->tx_reqs);
|
list_add(&req->list, &dev->tx_reqs);
|
||||||
spin_unlock(&dev->lock_printer_io);
|
mutex_unlock(&dev->lock_printer_io);
|
||||||
return bytes_copied;
|
return bytes_copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -766,14 +766,14 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
||||||
if (dev->reset_printer) {
|
if (dev->reset_printer) {
|
||||||
list_add(&req->list, &dev->tx_reqs);
|
list_add(&req->list, &dev->tx_reqs);
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
spin_unlock(&dev->lock_printer_io);
|
mutex_unlock(&dev->lock_printer_io);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
|
if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) {
|
||||||
list_add(&req->list, &dev->tx_reqs);
|
list_add(&req->list, &dev->tx_reqs);
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
spin_unlock(&dev->lock_printer_io);
|
mutex_unlock(&dev->lock_printer_io);
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -782,7 +782,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
spin_unlock(&dev->lock_printer_io);
|
mutex_unlock(&dev->lock_printer_io);
|
||||||
|
|
||||||
DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);
|
DBG(dev, "printer_write sent %d bytes\n", (int)bytes_copied);
|
||||||
|
|
||||||
|
@ -820,11 +820,11 @@ printer_poll(struct file *fd, poll_table *wait)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
spin_lock(&dev->lock_printer_io);
|
mutex_lock(&dev->lock_printer_io);
|
||||||
spin_lock_irqsave(&dev->lock, flags);
|
spin_lock_irqsave(&dev->lock, flags);
|
||||||
setup_rx_reqs(dev);
|
setup_rx_reqs(dev);
|
||||||
spin_unlock_irqrestore(&dev->lock, flags);
|
spin_unlock_irqrestore(&dev->lock, flags);
|
||||||
spin_unlock(&dev->lock_printer_io);
|
mutex_unlock(&dev->lock_printer_io);
|
||||||
|
|
||||||
poll_wait(fd, &dev->rx_wait, wait);
|
poll_wait(fd, &dev->rx_wait, wait);
|
||||||
poll_wait(fd, &dev->tx_wait, wait);
|
poll_wait(fd, &dev->tx_wait, wait);
|
||||||
|
@ -1461,7 +1461,7 @@ autoconf_fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_init(&dev->lock);
|
spin_lock_init(&dev->lock);
|
||||||
spin_lock_init(&dev->lock_printer_io);
|
mutex_init(&dev->lock_printer_io);
|
||||||
INIT_LIST_HEAD(&dev->tx_reqs);
|
INIT_LIST_HEAD(&dev->tx_reqs);
|
||||||
INIT_LIST_HEAD(&dev->tx_reqs_active);
|
INIT_LIST_HEAD(&dev->tx_reqs_active);
|
||||||
INIT_LIST_HEAD(&dev->rx_reqs);
|
INIT_LIST_HEAD(&dev->rx_reqs);
|
||||||
|
@ -1594,7 +1594,7 @@ cleanup(void)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
spin_lock(&usb_printer_gadget.lock_printer_io);
|
mutex_lock(&usb_printer_gadget.lock_printer_io);
|
||||||
class_destroy(usb_gadget_class);
|
class_destroy(usb_gadget_class);
|
||||||
unregister_chrdev_region(g_printer_devno, 2);
|
unregister_chrdev_region(g_printer_devno, 2);
|
||||||
|
|
||||||
|
@ -1602,6 +1602,6 @@ cleanup(void)
|
||||||
if (status)
|
if (status)
|
||||||
ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
|
ERROR(dev, "usb_gadget_unregister_driver %x\n", status);
|
||||||
|
|
||||||
spin_unlock(&usb_printer_gadget.lock_printer_io);
|
mutex_unlock(&usb_printer_gadget.lock_printer_io);
|
||||||
}
|
}
|
||||||
module_exit(cleanup);
|
module_exit(cleanup);
|
||||||
|
|
|
@ -1700,9 +1700,13 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
|
||||||
if (!driver || driver != udc->driver || !driver->unbind)
|
if (!driver || driver != udc->driver || !driver->unbind)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n",
|
dprintk(DEBUG_NORMAL, "usb_gadget_unregister_driver() '%s'\n",
|
||||||
driver->driver.name);
|
driver->driver.name);
|
||||||
|
|
||||||
|
/* report disconnect */
|
||||||
|
if (driver->disconnect)
|
||||||
|
driver->disconnect(&udc->gadget);
|
||||||
|
|
||||||
driver->unbind(&udc->gadget);
|
driver->unbind(&udc->gadget);
|
||||||
|
|
||||||
device_del(&udc->gadget.dev);
|
device_del(&udc->gadget.dev);
|
||||||
|
|
|
@ -536,17 +536,11 @@ recycle:
|
||||||
list_move(&req->list, &port->read_pool);
|
list_move(&req->list, &port->read_pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Push from tty to ldisc; this is immediate with low_latency, and
|
/* Push from tty to ldisc; without low_latency set this is handled by
|
||||||
* may trigger callbacks to this driver ... so drop the spinlock.
|
* a workqueue, so we won't get callbacks and can hold port_lock
|
||||||
*/
|
*/
|
||||||
if (tty && do_push) {
|
if (tty && do_push) {
|
||||||
spin_unlock_irq(&port->port_lock);
|
|
||||||
tty_flip_buffer_push(tty);
|
tty_flip_buffer_push(tty);
|
||||||
wake_up_interruptible(&tty->read_wait);
|
|
||||||
spin_lock_irq(&port->port_lock);
|
|
||||||
|
|
||||||
/* tty may have been closed */
|
|
||||||
tty = port->port_tty;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -784,11 +778,6 @@ static int gs_open(struct tty_struct *tty, struct file *file)
|
||||||
port->open_count = 1;
|
port->open_count = 1;
|
||||||
port->openclose = false;
|
port->openclose = false;
|
||||||
|
|
||||||
/* low_latency means ldiscs work in tasklet context, without
|
|
||||||
* needing a workqueue schedule ... easier to keep up.
|
|
||||||
*/
|
|
||||||
tty->low_latency = 1;
|
|
||||||
|
|
||||||
/* if connected, start the I/O stream */
|
/* if connected, start the I/O stream */
|
||||||
if (port->port_usb) {
|
if (port->port_usb) {
|
||||||
struct gserial *gser = port->port_usb;
|
struct gserial *gser = port->port_usb;
|
||||||
|
@ -1195,6 +1184,7 @@ void gserial_cleanup(void)
|
||||||
n_ports = 0;
|
n_ports = 0;
|
||||||
|
|
||||||
tty_unregister_driver(gs_tty_driver);
|
tty_unregister_driver(gs_tty_driver);
|
||||||
|
put_tty_driver(gs_tty_driver);
|
||||||
gs_tty_driver = NULL;
|
gs_tty_driver = NULL;
|
||||||
|
|
||||||
pr_debug("%s: cleaned up ttyGS* support\n", __func__);
|
pr_debug("%s: cleaned up ttyGS* support\n", __func__);
|
||||||
|
|
|
@ -207,10 +207,17 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
|
||||||
/* Initialize the transceiver */
|
/* Initialize the transceiver */
|
||||||
if (pdata->otg) {
|
if (pdata->otg) {
|
||||||
pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
|
pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET;
|
||||||
if (otg_init(pdata->otg) != 0)
|
ret = otg_init(pdata->otg);
|
||||||
dev_err(dev, "unable to init transceiver\n");
|
if (ret) {
|
||||||
else if (otg_set_vbus(pdata->otg, 1) != 0)
|
dev_err(dev, "unable to init transceiver, probably missing\n");
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto err_add;
|
||||||
|
}
|
||||||
|
ret = otg_set_vbus(pdata->otg, 1);
|
||||||
|
if (ret) {
|
||||||
dev_err(dev, "unable to enable vbus on transceiver\n");
|
dev_err(dev, "unable to enable vbus on transceiver\n");
|
||||||
|
goto err_add;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->hcd = hcd;
|
priv->hcd = hcd;
|
||||||
|
|
|
@ -2224,12 +2224,9 @@ static void remove_debug_file(struct isp1362_hcd *isp1362_hcd)
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
|
static void __isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
|
||||||
{
|
{
|
||||||
int tmp = 20;
|
int tmp = 20;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&isp1362_hcd->lock, flags);
|
|
||||||
|
|
||||||
isp1362_write_reg16(isp1362_hcd, HCSWRES, HCSWRES_MAGIC);
|
isp1362_write_reg16(isp1362_hcd, HCSWRES, HCSWRES_MAGIC);
|
||||||
isp1362_write_reg32(isp1362_hcd, HCCMDSTAT, OHCI_HCR);
|
isp1362_write_reg32(isp1362_hcd, HCCMDSTAT, OHCI_HCR);
|
||||||
|
@ -2240,6 +2237,14 @@ static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
|
||||||
}
|
}
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
pr_err("Software reset timeout\n");
|
pr_err("Software reset timeout\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&isp1362_hcd->lock, flags);
|
||||||
|
__isp1362_sw_reset(isp1362_hcd);
|
||||||
spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
|
spin_unlock_irqrestore(&isp1362_hcd->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2418,7 +2423,7 @@ static void isp1362_hc_stop(struct usb_hcd *hcd)
|
||||||
if (isp1362_hcd->board && isp1362_hcd->board->reset)
|
if (isp1362_hcd->board && isp1362_hcd->board->reset)
|
||||||
isp1362_hcd->board->reset(hcd->self.controller, 1);
|
isp1362_hcd->board->reset(hcd->self.controller, 1);
|
||||||
else
|
else
|
||||||
isp1362_sw_reset(isp1362_hcd);
|
__isp1362_sw_reset(isp1362_hcd);
|
||||||
|
|
||||||
if (isp1362_hcd->board && isp1362_hcd->board->clock)
|
if (isp1362_hcd->board && isp1362_hcd->board->clock)
|
||||||
isp1362_hcd->board->clock(hcd->self.controller, 0);
|
isp1362_hcd->board->clock(hcd->self.controller, 0);
|
||||||
|
|
|
@ -1065,7 +1065,7 @@ static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port)
|
||||||
else if (speed == LSMODE)
|
else if (speed == LSMODE)
|
||||||
rh->port |= USB_PORT_STAT_LOW_SPEED;
|
rh->port |= USB_PORT_STAT_LOW_SPEED;
|
||||||
|
|
||||||
rh->port &= USB_PORT_STAT_RESET;
|
rh->port &= ~USB_PORT_STAT_RESET;
|
||||||
rh->port |= USB_PORT_STAT_ENABLE;
|
rh->port |= USB_PORT_STAT_ENABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -182,8 +182,12 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
|
||||||
* set, but other sections talk about dealing with the chain bit set. This was
|
* set, but other sections talk about dealing with the chain bit set. This was
|
||||||
* fixed in the 0.96 specification errata, but we have to assume that all 0.95
|
* fixed in the 0.96 specification errata, but we have to assume that all 0.95
|
||||||
* xHCI hardware can't handle the chain bit being cleared on a link TRB.
|
* xHCI hardware can't handle the chain bit being cleared on a link TRB.
|
||||||
|
*
|
||||||
|
* @more_trbs_coming: Will you enqueue more TRBs before calling
|
||||||
|
* prepare_transfer()?
|
||||||
*/
|
*/
|
||||||
static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer)
|
static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
|
||||||
|
bool consumer, bool more_trbs_coming)
|
||||||
{
|
{
|
||||||
u32 chain;
|
u32 chain;
|
||||||
union xhci_trb *next;
|
union xhci_trb *next;
|
||||||
|
@ -199,15 +203,28 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
|
||||||
while (last_trb(xhci, ring, ring->enq_seg, next)) {
|
while (last_trb(xhci, ring, ring->enq_seg, next)) {
|
||||||
if (!consumer) {
|
if (!consumer) {
|
||||||
if (ring != xhci->event_ring) {
|
if (ring != xhci->event_ring) {
|
||||||
if (chain) {
|
/*
|
||||||
next->link.control |= TRB_CHAIN;
|
* If the caller doesn't plan on enqueueing more
|
||||||
|
* TDs before ringing the doorbell, then we
|
||||||
/* Give this link TRB to the hardware */
|
* don't want to give the link TRB to the
|
||||||
wmb();
|
* hardware just yet. We'll give the link TRB
|
||||||
next->link.control ^= TRB_CYCLE;
|
* back in prepare_ring() just before we enqueue
|
||||||
} else {
|
* the TD at the top of the ring.
|
||||||
|
*/
|
||||||
|
if (!chain && !more_trbs_coming)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* If we're not dealing with 0.95 hardware,
|
||||||
|
* carry over the chain bit of the previous TRB
|
||||||
|
* (which may mean the chain bit is cleared).
|
||||||
|
*/
|
||||||
|
if (!xhci_link_trb_quirk(xhci)) {
|
||||||
|
next->link.control &= ~TRB_CHAIN;
|
||||||
|
next->link.control |= chain;
|
||||||
}
|
}
|
||||||
|
/* Give this link TRB to the hardware */
|
||||||
|
wmb();
|
||||||
|
next->link.control ^= TRB_CYCLE;
|
||||||
}
|
}
|
||||||
/* Toggle the cycle bit after the last ring segment. */
|
/* Toggle the cycle bit after the last ring segment. */
|
||||||
if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
|
if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
|
||||||
|
@ -1707,9 +1724,12 @@ void xhci_handle_event(struct xhci_hcd *xhci)
|
||||||
/*
|
/*
|
||||||
* Generic function for queueing a TRB on a ring.
|
* Generic function for queueing a TRB on a ring.
|
||||||
* The caller must have checked to make sure there's room on the ring.
|
* The caller must have checked to make sure there's room on the ring.
|
||||||
|
*
|
||||||
|
* @more_trbs_coming: Will you enqueue more TRBs before calling
|
||||||
|
* prepare_transfer()?
|
||||||
*/
|
*/
|
||||||
static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
|
static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
|
||||||
bool consumer,
|
bool consumer, bool more_trbs_coming,
|
||||||
u32 field1, u32 field2, u32 field3, u32 field4)
|
u32 field1, u32 field2, u32 field3, u32 field4)
|
||||||
{
|
{
|
||||||
struct xhci_generic_trb *trb;
|
struct xhci_generic_trb *trb;
|
||||||
|
@ -1719,7 +1739,7 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
|
||||||
trb->field[1] = field2;
|
trb->field[1] = field2;
|
||||||
trb->field[2] = field3;
|
trb->field[2] = field3;
|
||||||
trb->field[3] = field4;
|
trb->field[3] = field4;
|
||||||
inc_enq(xhci, ring, consumer);
|
inc_enq(xhci, ring, consumer, more_trbs_coming);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1988,6 +2008,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||||
int trb_buff_len, this_sg_len, running_total;
|
int trb_buff_len, this_sg_len, running_total;
|
||||||
bool first_trb;
|
bool first_trb;
|
||||||
u64 addr;
|
u64 addr;
|
||||||
|
bool more_trbs_coming;
|
||||||
|
|
||||||
struct xhci_generic_trb *start_trb;
|
struct xhci_generic_trb *start_trb;
|
||||||
int start_cycle;
|
int start_cycle;
|
||||||
|
@ -2073,7 +2094,11 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||||
length_field = TRB_LEN(trb_buff_len) |
|
length_field = TRB_LEN(trb_buff_len) |
|
||||||
remainder |
|
remainder |
|
||||||
TRB_INTR_TARGET(0);
|
TRB_INTR_TARGET(0);
|
||||||
queue_trb(xhci, ep_ring, false,
|
if (num_trbs > 1)
|
||||||
|
more_trbs_coming = true;
|
||||||
|
else
|
||||||
|
more_trbs_coming = false;
|
||||||
|
queue_trb(xhci, ep_ring, false, more_trbs_coming,
|
||||||
lower_32_bits(addr),
|
lower_32_bits(addr),
|
||||||
upper_32_bits(addr),
|
upper_32_bits(addr),
|
||||||
length_field,
|
length_field,
|
||||||
|
@ -2124,6 +2149,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||||
int num_trbs;
|
int num_trbs;
|
||||||
struct xhci_generic_trb *start_trb;
|
struct xhci_generic_trb *start_trb;
|
||||||
bool first_trb;
|
bool first_trb;
|
||||||
|
bool more_trbs_coming;
|
||||||
int start_cycle;
|
int start_cycle;
|
||||||
u32 field, length_field;
|
u32 field, length_field;
|
||||||
|
|
||||||
|
@ -2212,7 +2238,11 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||||
length_field = TRB_LEN(trb_buff_len) |
|
length_field = TRB_LEN(trb_buff_len) |
|
||||||
remainder |
|
remainder |
|
||||||
TRB_INTR_TARGET(0);
|
TRB_INTR_TARGET(0);
|
||||||
queue_trb(xhci, ep_ring, false,
|
if (num_trbs > 1)
|
||||||
|
more_trbs_coming = true;
|
||||||
|
else
|
||||||
|
more_trbs_coming = false;
|
||||||
|
queue_trb(xhci, ep_ring, false, more_trbs_coming,
|
||||||
lower_32_bits(addr),
|
lower_32_bits(addr),
|
||||||
upper_32_bits(addr),
|
upper_32_bits(addr),
|
||||||
length_field,
|
length_field,
|
||||||
|
@ -2291,7 +2321,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||||
/* Queue setup TRB - see section 6.4.1.2.1 */
|
/* Queue setup TRB - see section 6.4.1.2.1 */
|
||||||
/* FIXME better way to translate setup_packet into two u32 fields? */
|
/* FIXME better way to translate setup_packet into two u32 fields? */
|
||||||
setup = (struct usb_ctrlrequest *) urb->setup_packet;
|
setup = (struct usb_ctrlrequest *) urb->setup_packet;
|
||||||
queue_trb(xhci, ep_ring, false,
|
queue_trb(xhci, ep_ring, false, true,
|
||||||
/* FIXME endianness is probably going to bite my ass here. */
|
/* FIXME endianness is probably going to bite my ass here. */
|
||||||
setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16,
|
setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16,
|
||||||
setup->wIndex | setup->wLength << 16,
|
setup->wIndex | setup->wLength << 16,
|
||||||
|
@ -2307,7 +2337,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||||
if (urb->transfer_buffer_length > 0) {
|
if (urb->transfer_buffer_length > 0) {
|
||||||
if (setup->bRequestType & USB_DIR_IN)
|
if (setup->bRequestType & USB_DIR_IN)
|
||||||
field |= TRB_DIR_IN;
|
field |= TRB_DIR_IN;
|
||||||
queue_trb(xhci, ep_ring, false,
|
queue_trb(xhci, ep_ring, false, true,
|
||||||
lower_32_bits(urb->transfer_dma),
|
lower_32_bits(urb->transfer_dma),
|
||||||
upper_32_bits(urb->transfer_dma),
|
upper_32_bits(urb->transfer_dma),
|
||||||
length_field,
|
length_field,
|
||||||
|
@ -2324,7 +2354,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
|
||||||
field = 0;
|
field = 0;
|
||||||
else
|
else
|
||||||
field = TRB_DIR_IN;
|
field = TRB_DIR_IN;
|
||||||
queue_trb(xhci, ep_ring, false,
|
queue_trb(xhci, ep_ring, false, false,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
TRB_INTR_TARGET(0),
|
TRB_INTR_TARGET(0),
|
||||||
|
@ -2361,7 +2391,7 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2,
|
||||||
"unfailable commands failed.\n");
|
"unfailable commands failed.\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3,
|
queue_trb(xhci, xhci->cmd_ring, false, false, field1, field2, field3,
|
||||||
field4 | xhci->cmd_ring->cycle_state);
|
field4 | xhci->cmd_ring->cycle_state);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,8 +219,8 @@ static int musb_ulpi_write(struct otg_transceiver *otg,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define musb_ulpi_read(a, b) NULL
|
#define musb_ulpi_read NULL
|
||||||
#define musb_ulpi_write(a, b, c) NULL
|
#define musb_ulpi_write NULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct otg_io_access_ops musb_ulpi_access = {
|
static struct otg_io_access_ops musb_ulpi_access = {
|
||||||
|
@ -451,10 +451,6 @@ void musb_hnp_stop(struct musb *musb)
|
||||||
* @param power
|
* @param power
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define STAGE0_MASK (MUSB_INTR_RESUME | MUSB_INTR_SESSREQ \
|
|
||||||
| MUSB_INTR_VBUSERROR | MUSB_INTR_CONNECT \
|
|
||||||
| MUSB_INTR_RESET)
|
|
||||||
|
|
||||||
static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
|
static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
|
||||||
u8 devctl, u8 power)
|
u8 devctl, u8 power)
|
||||||
{
|
{
|
||||||
|
@ -642,7 +638,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
|
||||||
handled = IRQ_HANDLED;
|
handled = IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
if (int_usb & MUSB_INTR_SUSPEND) {
|
if (int_usb & MUSB_INTR_SUSPEND) {
|
||||||
DBG(1, "SUSPEND (%s) devctl %02x power %02x\n",
|
DBG(1, "SUSPEND (%s) devctl %02x power %02x\n",
|
||||||
otg_state_string(musb), devctl, power);
|
otg_state_string(musb), devctl, power);
|
||||||
|
@ -705,6 +701,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_USB_MUSB_HDRC_HCD
|
||||||
if (int_usb & MUSB_INTR_CONNECT) {
|
if (int_usb & MUSB_INTR_CONNECT) {
|
||||||
struct usb_hcd *hcd = musb_to_hcd(musb);
|
struct usb_hcd *hcd = musb_to_hcd(musb);
|
||||||
void __iomem *mbase = musb->mregs;
|
void __iomem *mbase = musb->mregs;
|
||||||
|
@ -1597,7 +1594,7 @@ irqreturn_t musb_interrupt(struct musb *musb)
|
||||||
/* the core can interrupt us for multiple reasons; docs have
|
/* the core can interrupt us for multiple reasons; docs have
|
||||||
* a generic interrupt flowchart to follow
|
* a generic interrupt flowchart to follow
|
||||||
*/
|
*/
|
||||||
if (musb->int_usb & STAGE0_MASK)
|
if (musb->int_usb)
|
||||||
retval |= musb_stage0_irq(musb, musb->int_usb,
|
retval |= musb_stage0_irq(musb, musb->int_usb,
|
||||||
devctl, power);
|
devctl, power);
|
||||||
|
|
||||||
|
|
|
@ -470,7 +470,8 @@ struct musb_csr_regs {
|
||||||
|
|
||||||
struct musb_context_registers {
|
struct musb_context_registers {
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
|
||||||
|
defined(CONFIG_ARCH_OMAP4)
|
||||||
u32 otg_sysconfig, otg_forcestandby;
|
u32 otg_sysconfig, otg_forcestandby;
|
||||||
#endif
|
#endif
|
||||||
u8 power;
|
u8 power;
|
||||||
|
@ -484,7 +485,8 @@ struct musb_context_registers {
|
||||||
struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
|
struct musb_csr_regs index_regs[MUSB_C_NUM_EPS];
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
|
||||||
|
defined(CONFIG_ARCH_OMAP4)
|
||||||
extern void musb_platform_save_context(struct musb *musb,
|
extern void musb_platform_save_context(struct musb *musb,
|
||||||
struct musb_context_registers *musb_context);
|
struct musb_context_registers *musb_context);
|
||||||
extern void musb_platform_restore_context(struct musb *musb,
|
extern void musb_platform_restore_context(struct musb *musb,
|
||||||
|
|
|
@ -132,18 +132,9 @@ static void configure_channel(struct dma_channel *channel,
|
||||||
if (mode) {
|
if (mode) {
|
||||||
csr |= 1 << MUSB_HSDMA_MODE1_SHIFT;
|
csr |= 1 << MUSB_HSDMA_MODE1_SHIFT;
|
||||||
BUG_ON(len < packet_sz);
|
BUG_ON(len < packet_sz);
|
||||||
|
|
||||||
if (packet_sz >= 64) {
|
|
||||||
csr |= MUSB_HSDMA_BURSTMODE_INCR16
|
|
||||||
<< MUSB_HSDMA_BURSTMODE_SHIFT;
|
|
||||||
} else if (packet_sz >= 32) {
|
|
||||||
csr |= MUSB_HSDMA_BURSTMODE_INCR8
|
|
||||||
<< MUSB_HSDMA_BURSTMODE_SHIFT;
|
|
||||||
} else if (packet_sz >= 16) {
|
|
||||||
csr |= MUSB_HSDMA_BURSTMODE_INCR4
|
|
||||||
<< MUSB_HSDMA_BURSTMODE_SHIFT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
csr |= MUSB_HSDMA_BURSTMODE_INCR16
|
||||||
|
<< MUSB_HSDMA_BURSTMODE_SHIFT;
|
||||||
|
|
||||||
csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
|
csr |= (musb_channel->epnum << MUSB_HSDMA_ENDPOINT_SHIFT)
|
||||||
| (1 << MUSB_HSDMA_ENABLE_SHIFT)
|
| (1 << MUSB_HSDMA_ENABLE_SHIFT)
|
||||||
|
|
|
@ -59,12 +59,17 @@ static int ulpi_set_flags(struct otg_transceiver *otg)
|
||||||
|
|
||||||
static int ulpi_init(struct otg_transceiver *otg)
|
static int ulpi_init(struct otg_transceiver *otg)
|
||||||
{
|
{
|
||||||
int i, vid, pid;
|
int i, vid, pid, ret;
|
||||||
|
u32 ulpi_id = 0;
|
||||||
|
|
||||||
vid = (otg_io_read(otg, ULPI_VENDOR_ID_HIGH) << 8) |
|
for (i = 0; i < 4; i++) {
|
||||||
otg_io_read(otg, ULPI_VENDOR_ID_LOW);
|
ret = otg_io_read(otg, ULPI_PRODUCT_ID_HIGH - i);
|
||||||
pid = (otg_io_read(otg, ULPI_PRODUCT_ID_HIGH) << 8) |
|
if (ret < 0)
|
||||||
otg_io_read(otg, ULPI_PRODUCT_ID_LOW);
|
return ret;
|
||||||
|
ulpi_id = (ulpi_id << 8) | ret;
|
||||||
|
}
|
||||||
|
vid = ulpi_id & 0xffff;
|
||||||
|
pid = ulpi_id >> 16;
|
||||||
|
|
||||||
pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
|
pr_info("ULPI transceiver vendor/product ID 0x%04x/0x%04x\n", vid, pid);
|
||||||
|
|
||||||
|
|
|
@ -653,7 +653,6 @@ static struct usb_device_id id_table_combined [] = {
|
||||||
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
|
{ USB_DEVICE(EVOLUTION_VID, EVOLUTION_ER1_PID) },
|
||||||
{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },
|
{ USB_DEVICE(EVOLUTION_VID, EVO_HYBRID_PID) },
|
||||||
{ USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) },
|
{ USB_DEVICE(EVOLUTION_VID, EVO_RCM4_PID) },
|
||||||
{ USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
|
|
||||||
{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
|
{ USB_DEVICE(FTDI_VID, FTDI_ARTEMIS_PID) },
|
||||||
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
|
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16_PID) },
|
||||||
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
|
{ USB_DEVICE(FTDI_VID, FTDI_ATIK_ATK16C_PID) },
|
||||||
|
|
|
@ -500,13 +500,6 @@
|
||||||
#define CONTEC_VID 0x06CE /* Vendor ID */
|
#define CONTEC_VID 0x06CE /* Vendor ID */
|
||||||
#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
|
#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
|
||||||
|
|
||||||
/*
|
|
||||||
* Contec products (http://www.contec.com)
|
|
||||||
* Submitted by Daniel Sangorrin
|
|
||||||
*/
|
|
||||||
#define CONTEC_VID 0x06CE /* Vendor ID */
|
|
||||||
#define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Definitions for B&B Electronics products.
|
* Definitions for B&B Electronics products.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -139,6 +139,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
|
||||||
"Could not set interface, error %d\n",
|
"Could not set interface, error %d\n",
|
||||||
retval);
|
retval);
|
||||||
retval = -ENODEV;
|
retval = -ENODEV;
|
||||||
|
kfree(data);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -155,6 +156,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
|
||||||
"Could not set interface, error %d\n",
|
"Could not set interface, error %d\n",
|
||||||
retval);
|
retval);
|
||||||
retval = -ENODEV;
|
retval = -ENODEV;
|
||||||
|
kfree(data);
|
||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -163,6 +165,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
|
||||||
default:
|
default:
|
||||||
dev_err(&serial->dev->dev,
|
dev_err(&serial->dev->dev,
|
||||||
"unknown number of interfaces: %d\n", nintf);
|
"unknown number of interfaces: %d\n", nintf);
|
||||||
|
kfree(data);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue