|
@@ -521,6 +521,7 @@ static void u132_hcd_giveback_urb(struct u132 *u132, struct u132_endp *endp,
|
|
|
urb->status = status;
|
|
|
urb->hcpriv = NULL;
|
|
|
spin_lock_irqsave(&endp->queue_lock.slock, irqs);
|
|
|
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
|
|
|
endp->queue_next += 1;
|
|
|
if (ENDP_QUEUE_SIZE > --endp->queue_size) {
|
|
|
endp->active = 0;
|
|
@@ -561,6 +562,7 @@ static void u132_hcd_abandon_urb(struct u132 *u132, struct u132_endp *endp,
|
|
|
urb->status = status;
|
|
|
urb->hcpriv = NULL;
|
|
|
spin_lock_irqsave(&endp->queue_lock.slock, irqs);
|
|
|
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
|
|
|
endp->queue_next += 1;
|
|
|
if (ENDP_QUEUE_SIZE > --endp->queue_size) {
|
|
|
endp->active = 0;
|
|
@@ -1876,20 +1878,32 @@ static int u132_hcd_reset(struct usb_hcd *hcd)
|
|
|
}
|
|
|
|
|
|
static int create_endpoint_and_queue_int(struct u132 *u132,
|
|
|
- struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb,
|
|
|
+ struct u132_udev *udev, struct urb *urb,
|
|
|
struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
|
|
|
gfp_t mem_flags)
|
|
|
{
|
|
|
struct u132_ring *ring;
|
|
|
unsigned long irqs;
|
|
|
- u8 endp_number = ++u132->num_endpoints;
|
|
|
- struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
|
|
|
- kmalloc(sizeof(struct u132_endp), mem_flags);
|
|
|
+ int rc;
|
|
|
+ u8 endp_number;
|
|
|
+ struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
|
|
|
+
|
|
|
if (!endp) {
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
+
|
|
|
+ spin_lock_init(&endp->queue_lock.slock);
|
|
|
+ spin_lock_irqsave(&endp->queue_lock.slock, irqs);
|
|
|
+ rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb);
|
|
|
+ if (rc) {
|
|
|
+ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
|
|
|
+ kfree(endp);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ endp_number = ++u132->num_endpoints;
|
|
|
+ urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
|
|
|
INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
|
|
|
- spin_lock_init(&endp->queue_lock.slock);
|
|
|
INIT_LIST_HEAD(&endp->urb_more);
|
|
|
ring = endp->ring = &u132->ring[0];
|
|
|
if (ring->curr_endp) {
|
|
@@ -1905,7 +1919,7 @@ static int create_endpoint_and_queue_int(struct u132 *u132,
|
|
|
endp->delayed = 0;
|
|
|
endp->endp_number = endp_number;
|
|
|
endp->u132 = u132;
|
|
|
- endp->hep = hep;
|
|
|
+ endp->hep = urb->ep;
|
|
|
endp->pipetype = usb_pipetype(urb->pipe);
|
|
|
u132_endp_init_kref(u132, endp);
|
|
|
if (usb_pipein(urb->pipe)) {
|
|
@@ -1924,7 +1938,6 @@ static int create_endpoint_and_queue_int(struct u132 *u132,
|
|
|
u132_udev_get_kref(u132, udev);
|
|
|
}
|
|
|
urb->hcpriv = u132;
|
|
|
- spin_lock_irqsave(&endp->queue_lock.slock, irqs);
|
|
|
endp->delayed = 1;
|
|
|
endp->jiffies = jiffies + msecs_to_jiffies(urb->interval);
|
|
|
endp->udev_number = address;
|
|
@@ -1939,8 +1952,8 @@ static int create_endpoint_and_queue_int(struct u132 *u132,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int queue_int_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
|
|
|
- struct usb_host_endpoint *hep, struct urb *urb,
|
|
|
+static int queue_int_on_old_endpoint(struct u132 *u132,
|
|
|
+ struct u132_udev *udev, struct urb *urb,
|
|
|
struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
|
|
|
u8 usb_endp, u8 address)
|
|
|
{
|
|
@@ -1964,21 +1977,33 @@ static int queue_int_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
|
|
|
}
|
|
|
|
|
|
static int create_endpoint_and_queue_bulk(struct u132 *u132,
|
|
|
- struct u132_udev *udev, struct usb_host_endpoint *hep, struct urb *urb,
|
|
|
+ struct u132_udev *udev, struct urb *urb,
|
|
|
struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp, u8 address,
|
|
|
gfp_t mem_flags)
|
|
|
{
|
|
|
int ring_number;
|
|
|
struct u132_ring *ring;
|
|
|
unsigned long irqs;
|
|
|
- u8 endp_number = ++u132->num_endpoints;
|
|
|
- struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
|
|
|
- kmalloc(sizeof(struct u132_endp), mem_flags);
|
|
|
+ int rc;
|
|
|
+ u8 endp_number;
|
|
|
+ struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
|
|
|
+
|
|
|
if (!endp) {
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
+
|
|
|
+ spin_lock_init(&endp->queue_lock.slock);
|
|
|
+ spin_lock_irqsave(&endp->queue_lock.slock, irqs);
|
|
|
+ rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb);
|
|
|
+ if (rc) {
|
|
|
+ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
|
|
|
+ kfree(endp);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ endp_number = ++u132->num_endpoints;
|
|
|
+ urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
|
|
|
INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
|
|
|
- spin_lock_init(&endp->queue_lock.slock);
|
|
|
INIT_LIST_HEAD(&endp->urb_more);
|
|
|
endp->dequeueing = 0;
|
|
|
endp->edset_flush = 0;
|
|
@@ -1986,7 +2011,7 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132,
|
|
|
endp->delayed = 0;
|
|
|
endp->endp_number = endp_number;
|
|
|
endp->u132 = u132;
|
|
|
- endp->hep = hep;
|
|
|
+ endp->hep = urb->ep;
|
|
|
endp->pipetype = usb_pipetype(urb->pipe);
|
|
|
u132_endp_init_kref(u132, endp);
|
|
|
if (usb_pipein(urb->pipe)) {
|
|
@@ -2015,7 +2040,6 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132,
|
|
|
}
|
|
|
ring->length += 1;
|
|
|
urb->hcpriv = u132;
|
|
|
- spin_lock_irqsave(&endp->queue_lock.slock, irqs);
|
|
|
endp->udev_number = address;
|
|
|
endp->usb_addr = usb_addr;
|
|
|
endp->usb_endp = usb_endp;
|
|
@@ -2029,7 +2053,7 @@ static int create_endpoint_and_queue_bulk(struct u132 *u132,
|
|
|
}
|
|
|
|
|
|
static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
|
|
|
- struct usb_host_endpoint *hep, struct urb *urb,
|
|
|
+ struct urb *urb,
|
|
|
struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
|
|
|
u8 usb_endp, u8 address)
|
|
|
{
|
|
@@ -2051,19 +2075,32 @@ static int queue_bulk_on_old_endpoint(struct u132 *u132, struct u132_udev *udev,
|
|
|
}
|
|
|
|
|
|
static int create_endpoint_and_queue_control(struct u132 *u132,
|
|
|
- struct usb_host_endpoint *hep, struct urb *urb,
|
|
|
+ struct urb *urb,
|
|
|
struct usb_device *usb_dev, u8 usb_addr, u8 usb_endp,
|
|
|
gfp_t mem_flags)
|
|
|
{
|
|
|
struct u132_ring *ring;
|
|
|
- u8 endp_number = ++u132->num_endpoints;
|
|
|
- struct u132_endp *endp = hep->hcpriv = u132->endp[endp_number - 1] =
|
|
|
- kmalloc(sizeof(struct u132_endp), mem_flags);
|
|
|
+ unsigned long irqs;
|
|
|
+ int rc;
|
|
|
+ u8 endp_number;
|
|
|
+ struct u132_endp *endp = kmalloc(sizeof(struct u132_endp), mem_flags);
|
|
|
+
|
|
|
if (!endp) {
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
+
|
|
|
+ spin_lock_init(&endp->queue_lock.slock);
|
|
|
+ spin_lock_irqsave(&endp->queue_lock.slock, irqs);
|
|
|
+ rc = usb_hcd_link_urb_to_ep(u132_to_hcd(u132), urb);
|
|
|
+ if (rc) {
|
|
|
+ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
|
|
|
+ kfree(endp);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
+
|
|
|
+ endp_number = ++u132->num_endpoints;
|
|
|
+ urb->ep->hcpriv = u132->endp[endp_number - 1] = endp;
|
|
|
INIT_DELAYED_WORK(&endp->scheduler, u132_hcd_endp_work_scheduler);
|
|
|
- spin_lock_init(&endp->queue_lock.slock);
|
|
|
INIT_LIST_HEAD(&endp->urb_more);
|
|
|
ring = endp->ring = &u132->ring[0];
|
|
|
if (ring->curr_endp) {
|
|
@@ -2079,11 +2116,10 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
|
|
|
endp->delayed = 0;
|
|
|
endp->endp_number = endp_number;
|
|
|
endp->u132 = u132;
|
|
|
- endp->hep = hep;
|
|
|
+ endp->hep = urb->ep;
|
|
|
u132_endp_init_kref(u132, endp);
|
|
|
u132_endp_get_kref(u132, endp);
|
|
|
if (usb_addr == 0) {
|
|
|
- unsigned long irqs;
|
|
|
u8 address = u132->addr[usb_addr].address;
|
|
|
struct u132_udev *udev = &u132->udev[address];
|
|
|
endp->udev_number = address;
|
|
@@ -2097,7 +2133,6 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
|
|
|
udev->endp_number_in[usb_endp] = endp_number;
|
|
|
udev->endp_number_out[usb_endp] = endp_number;
|
|
|
urb->hcpriv = u132;
|
|
|
- spin_lock_irqsave(&endp->queue_lock.slock, irqs);
|
|
|
endp->queue_size = 1;
|
|
|
endp->queue_last = 0;
|
|
|
endp->queue_next = 0;
|
|
@@ -2106,7 +2141,6 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
|
|
|
u132_endp_queue_work(u132, endp, 0);
|
|
|
return 0;
|
|
|
} else { /*(usb_addr > 0) */
|
|
|
- unsigned long irqs;
|
|
|
u8 address = u132->addr[usb_addr].address;
|
|
|
struct u132_udev *udev = &u132->udev[address];
|
|
|
endp->udev_number = address;
|
|
@@ -2120,7 +2154,6 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
|
|
|
udev->endp_number_in[usb_endp] = endp_number;
|
|
|
udev->endp_number_out[usb_endp] = endp_number;
|
|
|
urb->hcpriv = u132;
|
|
|
- spin_lock_irqsave(&endp->queue_lock.slock, irqs);
|
|
|
endp->queue_size = 1;
|
|
|
endp->queue_last = 0;
|
|
|
endp->queue_next = 0;
|
|
@@ -2132,7 +2165,7 @@ static int create_endpoint_and_queue_control(struct u132 *u132,
|
|
|
}
|
|
|
|
|
|
static int queue_control_on_old_endpoint(struct u132 *u132,
|
|
|
- struct usb_host_endpoint *hep, struct urb *urb,
|
|
|
+ struct urb *urb,
|
|
|
struct usb_device *usb_dev, struct u132_endp *endp, u8 usb_addr,
|
|
|
u8 usb_endp)
|
|
|
{
|
|
@@ -2232,8 +2265,8 @@ static int queue_control_on_old_endpoint(struct u132 *u132,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
|
|
|
- struct urb *urb, gfp_t mem_flags)
|
|
|
+static int u132_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
|
|
|
+ gfp_t mem_flags)
|
|
|
{
|
|
|
struct u132 *u132 = hcd_to_u132(hcd);
|
|
|
if (irqs_disabled()) {
|
|
@@ -2258,16 +2291,24 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
|
|
|
if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) {
|
|
|
u8 address = u132->addr[usb_addr].address;
|
|
|
struct u132_udev *udev = &u132->udev[address];
|
|
|
- struct u132_endp *endp = hep->hcpriv;
|
|
|
+ struct u132_endp *endp = urb->ep->hcpriv;
|
|
|
urb->actual_length = 0;
|
|
|
if (endp) {
|
|
|
unsigned long irqs;
|
|
|
int retval;
|
|
|
spin_lock_irqsave(&endp->queue_lock.slock,
|
|
|
irqs);
|
|
|
- retval = queue_int_on_old_endpoint(u132, udev,
|
|
|
- hep, urb, usb_dev, endp, usb_addr,
|
|
|
- usb_endp, address);
|
|
|
+ retval = usb_hcd_link_urb_to_ep(hcd, urb);
|
|
|
+ if (retval == 0) {
|
|
|
+ retval = queue_int_on_old_endpoint(
|
|
|
+ u132, udev, urb,
|
|
|
+ usb_dev, endp,
|
|
|
+ usb_addr, usb_endp,
|
|
|
+ address);
|
|
|
+ if (retval)
|
|
|
+ usb_hcd_unlink_urb_from_ep(
|
|
|
+ hcd, urb);
|
|
|
+ }
|
|
|
spin_unlock_irqrestore(&endp->queue_lock.slock,
|
|
|
irqs);
|
|
|
if (retval) {
|
|
@@ -2282,8 +2323,8 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
|
|
|
return -EINVAL;
|
|
|
} else { /*(endp == NULL) */
|
|
|
return create_endpoint_and_queue_int(u132, udev,
|
|
|
- hep, urb, usb_dev, usb_addr, usb_endp,
|
|
|
- address, mem_flags);
|
|
|
+ urb, usb_dev, usb_addr,
|
|
|
+ usb_endp, address, mem_flags);
|
|
|
}
|
|
|
} else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
|
|
|
dev_err(&u132->platform_dev->dev, "the hardware does no"
|
|
@@ -2292,16 +2333,24 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
|
|
|
} else if (usb_pipetype(urb->pipe) == PIPE_BULK) {
|
|
|
u8 address = u132->addr[usb_addr].address;
|
|
|
struct u132_udev *udev = &u132->udev[address];
|
|
|
- struct u132_endp *endp = hep->hcpriv;
|
|
|
+ struct u132_endp *endp = urb->ep->hcpriv;
|
|
|
urb->actual_length = 0;
|
|
|
if (endp) {
|
|
|
unsigned long irqs;
|
|
|
int retval;
|
|
|
spin_lock_irqsave(&endp->queue_lock.slock,
|
|
|
irqs);
|
|
|
- retval = queue_bulk_on_old_endpoint(u132, udev,
|
|
|
- hep, urb, usb_dev, endp, usb_addr,
|
|
|
- usb_endp, address);
|
|
|
+ retval = usb_hcd_link_urb_to_ep(hcd, urb);
|
|
|
+ if (retval == 0) {
|
|
|
+ retval = queue_bulk_on_old_endpoint(
|
|
|
+ u132, udev, urb,
|
|
|
+ usb_dev, endp,
|
|
|
+ usb_addr, usb_endp,
|
|
|
+ address);
|
|
|
+ if (retval)
|
|
|
+ usb_hcd_unlink_urb_from_ep(
|
|
|
+ hcd, urb);
|
|
|
+ }
|
|
|
spin_unlock_irqrestore(&endp->queue_lock.slock,
|
|
|
irqs);
|
|
|
if (retval) {
|
|
@@ -2314,10 +2363,10 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
|
|
|
return -EINVAL;
|
|
|
} else
|
|
|
return create_endpoint_and_queue_bulk(u132,
|
|
|
- udev, hep, urb, usb_dev, usb_addr,
|
|
|
+ udev, urb, usb_dev, usb_addr,
|
|
|
usb_endp, address, mem_flags);
|
|
|
} else {
|
|
|
- struct u132_endp *endp = hep->hcpriv;
|
|
|
+ struct u132_endp *endp = urb->ep->hcpriv;
|
|
|
u16 urb_size = 8;
|
|
|
u8 *b = urb->setup_packet;
|
|
|
int i = 0;
|
|
@@ -2340,9 +2389,16 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
|
|
|
int retval;
|
|
|
spin_lock_irqsave(&endp->queue_lock.slock,
|
|
|
irqs);
|
|
|
- retval = queue_control_on_old_endpoint(u132,
|
|
|
- hep, urb, usb_dev, endp, usb_addr,
|
|
|
- usb_endp);
|
|
|
+ retval = usb_hcd_link_urb_to_ep(hcd, urb);
|
|
|
+ if (retval == 0) {
|
|
|
+ retval = queue_control_on_old_endpoint(
|
|
|
+ u132, urb, usb_dev,
|
|
|
+ endp, usb_addr,
|
|
|
+ usb_endp);
|
|
|
+ if (retval)
|
|
|
+ usb_hcd_unlink_urb_from_ep(
|
|
|
+ hcd, urb);
|
|
|
+ }
|
|
|
spin_unlock_irqrestore(&endp->queue_lock.slock,
|
|
|
irqs);
|
|
|
if (retval) {
|
|
@@ -2355,7 +2411,7 @@ static int u132_urb_enqueue(struct usb_hcd *hcd, struct usb_host_endpoint *hep,
|
|
|
return -EINVAL;
|
|
|
} else
|
|
|
return create_endpoint_and_queue_control(u132,
|
|
|
- hep, urb, usb_dev, usb_addr, usb_endp,
|
|
|
+ urb, usb_dev, usb_addr, usb_endp,
|
|
|
mem_flags);
|
|
|
}
|
|
|
}
|
|
@@ -2390,10 +2446,17 @@ static int dequeue_from_overflow_chain(struct u132 *u132,
|
|
|
}
|
|
|
|
|
|
static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
|
|
|
- struct urb *urb)
|
|
|
+ struct urb *urb, int status)
|
|
|
{
|
|
|
unsigned long irqs;
|
|
|
+ int rc;
|
|
|
+
|
|
|
spin_lock_irqsave(&endp->queue_lock.slock, irqs);
|
|
|
+ rc = usb_hcd_check_unlink_urb(u132_to_hcd(u132), urb, status);
|
|
|
+ if (rc) {
|
|
|
+ spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
|
|
|
+ return rc;
|
|
|
+ }
|
|
|
if (endp->queue_size == 0) {
|
|
|
dev_err(&u132->platform_dev->dev, "urb=%p not found in endp[%d]"
|
|
|
"=%p ring[%d] %c%c usb_endp=%d usb_addr=%d\n", urb,
|
|
@@ -2438,6 +2501,8 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
|
|
|
}
|
|
|
if (urb_slot) {
|
|
|
struct usb_hcd *hcd = u132_to_hcd(u132);
|
|
|
+
|
|
|
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
|
|
|
endp->queue_size -= 1;
|
|
|
if (list_empty(&endp->urb_more)) {
|
|
|
spin_unlock_irqrestore(&endp->queue_lock.slock,
|
|
@@ -2467,7 +2532,10 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
|
|
|
spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
|
|
|
return -EINVAL;
|
|
|
} else {
|
|
|
- int retval = dequeue_from_overflow_chain(u132, endp,
|
|
|
+ int retval;
|
|
|
+
|
|
|
+ usb_hcd_unlink_urb_from_ep(u132_to_hcd(u132), urb);
|
|
|
+ retval = dequeue_from_overflow_chain(u132, endp,
|
|
|
urb);
|
|
|
spin_unlock_irqrestore(&endp->queue_lock.slock, irqs);
|
|
|
return retval;
|
|
@@ -2475,7 +2543,7 @@ static int u132_endp_urb_dequeue(struct u132 *u132, struct u132_endp *endp,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
|
|
|
+static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
|
|
{
|
|
|
struct u132 *u132 = hcd_to_u132(hcd);
|
|
|
if (u132->going > 2) {
|
|
@@ -2490,11 +2558,11 @@ static int u132_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
|
|
|
if (usb_pipein(urb->pipe)) {
|
|
|
u8 endp_number = udev->endp_number_in[usb_endp];
|
|
|
struct u132_endp *endp = u132->endp[endp_number - 1];
|
|
|
- return u132_endp_urb_dequeue(u132, endp, urb);
|
|
|
+ return u132_endp_urb_dequeue(u132, endp, urb, status);
|
|
|
} else {
|
|
|
u8 endp_number = udev->endp_number_out[usb_endp];
|
|
|
struct u132_endp *endp = u132->endp[endp_number - 1];
|
|
|
- return u132_endp_urb_dequeue(u132, endp, urb);
|
|
|
+ return u132_endp_urb_dequeue(u132, endp, urb, status);
|
|
|
}
|
|
|
}
|
|
|
}
|