usb: chipidea: udc: refine isr_tr_complete_handler
Matthieu CASTET and Michael Grzeschik mentioned isr_tr_complete_handler is a bit messy at below: http://marc.info/?l=linux-usb&m=139047775001152&w=2 This commit creates a new function isr_setup_packet_handler to handle setup packet, it makes isr_tr_complete_handler easy to read. This is no functional change at this commit, tested with g_mass_storage and g_ether. Cc: Michael Grzeschik <mgr@pengutronix.de> Cc: Matthieu CASTET <matthieu.castet@parrot.com> Signed-off-by: Peter Chen <peter.chen@freescale.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
192c028b6a
commit
d7b00e310b
|
@ -948,6 +948,156 @@ __acquires(hwep->lock)
|
|||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* isr_setup_packet_handler: setup packet handler
|
||||
* @ci: UDC descriptor
|
||||
*
|
||||
* This function handles setup packet
|
||||
*/
|
||||
static void isr_setup_packet_handler(struct ci_hdrc *ci)
|
||||
__releases(ci->lock)
|
||||
__acquires(ci->lock)
|
||||
{
|
||||
struct ci_hw_ep *hwep = &ci->ci_hw_ep[0];
|
||||
struct usb_ctrlrequest req;
|
||||
int type, num, dir, err = -EINVAL;
|
||||
u8 tmode = 0;
|
||||
|
||||
/*
|
||||
* Flush data and handshake transactions of previous
|
||||
* setup packet.
|
||||
*/
|
||||
_ep_nuke(ci->ep0out);
|
||||
_ep_nuke(ci->ep0in);
|
||||
|
||||
/* read_setup_packet */
|
||||
do {
|
||||
hw_test_and_set_setup_guard(ci);
|
||||
memcpy(&req, &hwep->qh.ptr->setup, sizeof(req));
|
||||
} while (!hw_test_and_clear_setup_guard(ci));
|
||||
|
||||
type = req.bRequestType;
|
||||
|
||||
ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
|
||||
|
||||
switch (req.bRequest) {
|
||||
case USB_REQ_CLEAR_FEATURE:
|
||||
if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
|
||||
le16_to_cpu(req.wValue) ==
|
||||
USB_ENDPOINT_HALT) {
|
||||
if (req.wLength != 0)
|
||||
break;
|
||||
num = le16_to_cpu(req.wIndex);
|
||||
dir = num & USB_ENDPOINT_DIR_MASK;
|
||||
num &= USB_ENDPOINT_NUMBER_MASK;
|
||||
if (dir) /* TX */
|
||||
num += ci->hw_ep_max / 2;
|
||||
if (!ci->ci_hw_ep[num].wedge) {
|
||||
spin_unlock(&ci->lock);
|
||||
err = usb_ep_clear_halt(
|
||||
&ci->ci_hw_ep[num].ep);
|
||||
spin_lock(&ci->lock);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
err = isr_setup_status_phase(ci);
|
||||
} else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
|
||||
le16_to_cpu(req.wValue) ==
|
||||
USB_DEVICE_REMOTE_WAKEUP) {
|
||||
if (req.wLength != 0)
|
||||
break;
|
||||
ci->remote_wakeup = 0;
|
||||
err = isr_setup_status_phase(ci);
|
||||
} else {
|
||||
goto delegate;
|
||||
}
|
||||
break;
|
||||
case USB_REQ_GET_STATUS:
|
||||
if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
|
||||
type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
|
||||
type != (USB_DIR_IN|USB_RECIP_INTERFACE))
|
||||
goto delegate;
|
||||
if (le16_to_cpu(req.wLength) != 2 ||
|
||||
le16_to_cpu(req.wValue) != 0)
|
||||
break;
|
||||
err = isr_get_status_response(ci, &req);
|
||||
break;
|
||||
case USB_REQ_SET_ADDRESS:
|
||||
if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
|
||||
goto delegate;
|
||||
if (le16_to_cpu(req.wLength) != 0 ||
|
||||
le16_to_cpu(req.wIndex) != 0)
|
||||
break;
|
||||
ci->address = (u8)le16_to_cpu(req.wValue);
|
||||
ci->setaddr = true;
|
||||
err = isr_setup_status_phase(ci);
|
||||
break;
|
||||
case USB_REQ_SET_FEATURE:
|
||||
if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
|
||||
le16_to_cpu(req.wValue) ==
|
||||
USB_ENDPOINT_HALT) {
|
||||
if (req.wLength != 0)
|
||||
break;
|
||||
num = le16_to_cpu(req.wIndex);
|
||||
dir = num & USB_ENDPOINT_DIR_MASK;
|
||||
num &= USB_ENDPOINT_NUMBER_MASK;
|
||||
if (dir) /* TX */
|
||||
num += ci->hw_ep_max / 2;
|
||||
|
||||
spin_unlock(&ci->lock);
|
||||
err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep);
|
||||
spin_lock(&ci->lock);
|
||||
if (!err)
|
||||
isr_setup_status_phase(ci);
|
||||
} else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
|
||||
if (req.wLength != 0)
|
||||
break;
|
||||
switch (le16_to_cpu(req.wValue)) {
|
||||
case USB_DEVICE_REMOTE_WAKEUP:
|
||||
ci->remote_wakeup = 1;
|
||||
err = isr_setup_status_phase(ci);
|
||||
break;
|
||||
case USB_DEVICE_TEST_MODE:
|
||||
tmode = le16_to_cpu(req.wIndex) >> 8;
|
||||
switch (tmode) {
|
||||
case TEST_J:
|
||||
case TEST_K:
|
||||
case TEST_SE0_NAK:
|
||||
case TEST_PACKET:
|
||||
case TEST_FORCE_EN:
|
||||
ci->test_mode = tmode;
|
||||
err = isr_setup_status_phase(
|
||||
ci);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto delegate;
|
||||
}
|
||||
} else {
|
||||
goto delegate;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
delegate:
|
||||
if (req.wLength == 0) /* no data phase */
|
||||
ci->ep0_dir = TX;
|
||||
|
||||
spin_unlock(&ci->lock);
|
||||
err = ci->driver->setup(&ci->gadget, &req);
|
||||
spin_lock(&ci->lock);
|
||||
break;
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
spin_unlock(&ci->lock);
|
||||
if (usb_ep_set_halt(&hwep->ep))
|
||||
dev_err(ci->dev, "error: ep_set_halt\n");
|
||||
spin_lock(&ci->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* isr_tr_complete_handler: transaction complete interrupt handler
|
||||
* @ci: UDC descriptor
|
||||
|
@ -959,12 +1109,10 @@ __releases(ci->lock)
|
|||
__acquires(ci->lock)
|
||||
{
|
||||
unsigned i;
|
||||
u8 tmode = 0;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < ci->hw_ep_max; i++) {
|
||||
struct ci_hw_ep *hwep = &ci->ci_hw_ep[i];
|
||||
int type, num, dir, err = -EINVAL;
|
||||
struct usb_ctrlrequest req;
|
||||
|
||||
if (hwep->ep.desc == NULL)
|
||||
continue; /* not configured */
|
||||
|
@ -985,143 +1133,9 @@ __acquires(ci->lock)
|
|||
}
|
||||
|
||||
/* Only handle setup packet below */
|
||||
if (i != 0 ||
|
||||
!hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(0)))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Flush data and handshake transactions of previous
|
||||
* setup packet.
|
||||
*/
|
||||
_ep_nuke(ci->ep0out);
|
||||
_ep_nuke(ci->ep0in);
|
||||
|
||||
/* read_setup_packet */
|
||||
do {
|
||||
hw_test_and_set_setup_guard(ci);
|
||||
memcpy(&req, &hwep->qh.ptr->setup, sizeof(req));
|
||||
} while (!hw_test_and_clear_setup_guard(ci));
|
||||
|
||||
type = req.bRequestType;
|
||||
|
||||
ci->ep0_dir = (type & USB_DIR_IN) ? TX : RX;
|
||||
|
||||
switch (req.bRequest) {
|
||||
case USB_REQ_CLEAR_FEATURE:
|
||||
if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
|
||||
le16_to_cpu(req.wValue) ==
|
||||
USB_ENDPOINT_HALT) {
|
||||
if (req.wLength != 0)
|
||||
break;
|
||||
num = le16_to_cpu(req.wIndex);
|
||||
dir = num & USB_ENDPOINT_DIR_MASK;
|
||||
num &= USB_ENDPOINT_NUMBER_MASK;
|
||||
if (dir) /* TX */
|
||||
num += ci->hw_ep_max/2;
|
||||
if (!ci->ci_hw_ep[num].wedge) {
|
||||
spin_unlock(&ci->lock);
|
||||
err = usb_ep_clear_halt(
|
||||
&ci->ci_hw_ep[num].ep);
|
||||
spin_lock(&ci->lock);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
err = isr_setup_status_phase(ci);
|
||||
} else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE) &&
|
||||
le16_to_cpu(req.wValue) ==
|
||||
USB_DEVICE_REMOTE_WAKEUP) {
|
||||
if (req.wLength != 0)
|
||||
break;
|
||||
ci->remote_wakeup = 0;
|
||||
err = isr_setup_status_phase(ci);
|
||||
} else {
|
||||
goto delegate;
|
||||
}
|
||||
break;
|
||||
case USB_REQ_GET_STATUS:
|
||||
if (type != (USB_DIR_IN|USB_RECIP_DEVICE) &&
|
||||
type != (USB_DIR_IN|USB_RECIP_ENDPOINT) &&
|
||||
type != (USB_DIR_IN|USB_RECIP_INTERFACE))
|
||||
goto delegate;
|
||||
if (le16_to_cpu(req.wLength) != 2 ||
|
||||
le16_to_cpu(req.wValue) != 0)
|
||||
break;
|
||||
err = isr_get_status_response(ci, &req);
|
||||
break;
|
||||
case USB_REQ_SET_ADDRESS:
|
||||
if (type != (USB_DIR_OUT|USB_RECIP_DEVICE))
|
||||
goto delegate;
|
||||
if (le16_to_cpu(req.wLength) != 0 ||
|
||||
le16_to_cpu(req.wIndex) != 0)
|
||||
break;
|
||||
ci->address = (u8)le16_to_cpu(req.wValue);
|
||||
ci->setaddr = true;
|
||||
err = isr_setup_status_phase(ci);
|
||||
break;
|
||||
case USB_REQ_SET_FEATURE:
|
||||
if (type == (USB_DIR_OUT|USB_RECIP_ENDPOINT) &&
|
||||
le16_to_cpu(req.wValue) ==
|
||||
USB_ENDPOINT_HALT) {
|
||||
if (req.wLength != 0)
|
||||
break;
|
||||
num = le16_to_cpu(req.wIndex);
|
||||
dir = num & USB_ENDPOINT_DIR_MASK;
|
||||
num &= USB_ENDPOINT_NUMBER_MASK;
|
||||
if (dir) /* TX */
|
||||
num += ci->hw_ep_max/2;
|
||||
|
||||
spin_unlock(&ci->lock);
|
||||
err = usb_ep_set_halt(&ci->ci_hw_ep[num].ep);
|
||||
spin_lock(&ci->lock);
|
||||
if (!err)
|
||||
isr_setup_status_phase(ci);
|
||||
} else if (type == (USB_DIR_OUT|USB_RECIP_DEVICE)) {
|
||||
if (req.wLength != 0)
|
||||
break;
|
||||
switch (le16_to_cpu(req.wValue)) {
|
||||
case USB_DEVICE_REMOTE_WAKEUP:
|
||||
ci->remote_wakeup = 1;
|
||||
err = isr_setup_status_phase(ci);
|
||||
break;
|
||||
case USB_DEVICE_TEST_MODE:
|
||||
tmode = le16_to_cpu(req.wIndex) >> 8;
|
||||
switch (tmode) {
|
||||
case TEST_J:
|
||||
case TEST_K:
|
||||
case TEST_SE0_NAK:
|
||||
case TEST_PACKET:
|
||||
case TEST_FORCE_EN:
|
||||
ci->test_mode = tmode;
|
||||
err = isr_setup_status_phase(
|
||||
ci);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto delegate;
|
||||
}
|
||||
} else {
|
||||
goto delegate;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
delegate:
|
||||
if (req.wLength == 0) /* no data phase */
|
||||
ci->ep0_dir = TX;
|
||||
|
||||
spin_unlock(&ci->lock);
|
||||
err = ci->driver->setup(&ci->gadget, &req);
|
||||
spin_lock(&ci->lock);
|
||||
break;
|
||||
}
|
||||
|
||||
if (err < 0) {
|
||||
spin_unlock(&ci->lock);
|
||||
if (usb_ep_set_halt(&hwep->ep))
|
||||
dev_err(ci->dev, "error: ep_set_halt\n");
|
||||
spin_lock(&ci->lock);
|
||||
}
|
||||
if (i == 0 &&
|
||||
hw_test_and_clear(ci, OP_ENDPTSETUPSTAT, BIT(0)))
|
||||
isr_setup_packet_handler(ci);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue