usb: chipidea: udc: refine isr_tr_complete_handler
authorPeter Chen <peter.chen@freescale.com>
Tue, 11 Mar 2014 05:47:37 +0000 (13:47 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 12 Mar 2014 19:32:21 +0000 (12:32 -0700)
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>
drivers/usb/chipidea/udc.c

index 0dc56aebb807b4c86ac031c2f16aece3f9fa45fc..7739c64ef2590a1dbdd0daf8e631b90cf99af628 100644 (file)
@@ -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);
        }
 }