This patch (as1598) adds support for the new "reset" callback to the
g_file_storage driver.  Resets are handled slightly differently from
disconnects, in that the driver doesn't sync the backing storage file
during a reset but does during a disconnect.

The problem is that a file sync can take a long time if there are many
dirty pages, which can cause the driver's main thread to miss other
USB events if they arrive too quickly.  After a disconnect we
generally don't expect to see other events in the near future, whereas
after a reset we do.

Unfortunately the driver already contains an FSG_STATE_RESET symbol.
The patch renames it to FSG_STATE_CLASS_RESET, because it refers to a
class-specific reset event rather than a general USB port reset, and
uses FSG_STATE_RESET for port resets.  The g_mass_storage driver
shares a source file with g_file_storage; therefore it had to be
modified accordingly.

Signed-off-by: Alan Stern <[email protected]>
Reported-by: Chen Peter-B29397 <[email protected]>

---

 drivers/usb/gadget/f_mass_storage.c |    5 +++--
 drivers/usb/gadget/file_storage.c   |   20 ++++++++++++++++----
 drivers/usb/gadget/storage_common.c |    3 ++-
 3 files changed, 21 insertions(+), 7 deletions(-)

Index: usb-3.5/drivers/usb/gadget/storage_common.c
===================================================================
--- usb-3.5.orig/drivers/usb/gadget/storage_common.c
+++ usb-3.5/drivers/usb/gadget/storage_common.c
@@ -279,9 +279,10 @@ enum fsg_state {
 
        FSG_STATE_IDLE = 0,
        FSG_STATE_ABORT_BULK_OUT,
-       FSG_STATE_RESET,
+       FSG_STATE_CLASS_RESET,
        FSG_STATE_INTERFACE_CHANGE,
        FSG_STATE_CONFIG_CHANGE,
+       FSG_STATE_RESET,
        FSG_STATE_DISCONNECT,
        FSG_STATE_EXIT,
        FSG_STATE_TERMINATED
Index: usb-3.5/drivers/usb/gadget/file_storage.c
===================================================================
--- usb-3.5.orig/drivers/usb/gadget/file_storage.c
+++ usb-3.5/drivers/usb/gadget/file_storage.c
@@ -676,10 +676,18 @@ static void fsg_disconnect(struct usb_ga
 {
        struct fsg_dev          *fsg = get_gadget_data(gadget);
 
-       DBG(fsg, "disconnect or port reset\n");
+       DBG(fsg, "disconnect\n");
        raise_exception(fsg, FSG_STATE_DISCONNECT);
 }
 
+static void fsg_reset(struct usb_gadget *gadget)
+{
+       struct fsg_dev          *fsg = get_gadget_data(gadget);
+
+       DBG(fsg, "port reset\n");
+       raise_exception(fsg, FSG_STATE_RESET);
+}
+
 
 static int ep0_queue(struct fsg_dev *fsg)
 {
@@ -816,7 +824,7 @@ static void received_cbi_adsc(struct fsg
                /* Raise an exception to stop the current operation
                 * and reinitialize our state. */
                DBG(fsg, "cbi reset request\n");
-               raise_exception(fsg, FSG_STATE_RESET);
+               raise_exception(fsg, FSG_STATE_CLASS_RESET);
                return;
        }
 
@@ -867,7 +875,7 @@ static int class_setup_req(struct fsg_de
                        /* Raise an exception to stop the current operation
                         * and reinitialize our state. */
                        DBG(fsg, "bulk reset request\n");
-                       raise_exception(fsg, FSG_STATE_RESET);
+                       raise_exception(fsg, FSG_STATE_CLASS_RESET);
                        value = DELAYED_STATUS;
                        break;
 
@@ -3006,7 +3014,7 @@ static void handle_exception(struct fsg_
                spin_unlock_irq(&fsg->lock);
                break;
 
-       case FSG_STATE_RESET:
+       case FSG_STATE_CLASS_RESET:
                /* In case we were forced against our will to halt a
                 * bulk endpoint, clear the halt now.  (The SuperH UDC
                 * requires this.) */
@@ -3050,6 +3058,9 @@ static void handle_exception(struct fsg_
        case FSG_STATE_DISCONNECT:
                for (i = 0; i < fsg->nluns; ++i)
                        fsg_lun_fsync_sub(fsg->luns + i);
+               /* FALL THROUGH */
+
+       case FSG_STATE_RESET:
                do_set_config(fsg, 0);          // Unconfigured state
                break;
 
@@ -3608,6 +3619,7 @@ static struct usb_gadget_driver           fsg_dri
        .function       = (char *) fsg_string_product,
        .unbind         = fsg_unbind,
        .disconnect     = fsg_disconnect,
+       .reset          = fsg_reset,
        .setup          = fsg_setup,
        .suspend        = fsg_suspend,
        .resume         = fsg_resume,
Index: usb-3.5/drivers/usb/gadget/f_mass_storage.c
===================================================================
--- usb-3.5.orig/drivers/usb/gadget/f_mass_storage.c
+++ usb-3.5/drivers/usb/gadget/f_mass_storage.c
@@ -554,7 +554,7 @@ static int fsg_setup(struct usb_function
                 * and reinitialize our state.
                 */
                DBG(fsg, "bulk reset request\n");
-               raise_exception(fsg->common, FSG_STATE_RESET);
+               raise_exception(fsg->common, FSG_STATE_CLASS_RESET);
                return DELAYED_STATUS;
 
        case US_BULK_GET_MAX_LUN:
@@ -2470,7 +2470,7 @@ static void handle_exception(struct fsg_
                spin_unlock_irq(&common->lock);
                break;
 
-       case FSG_STATE_RESET:
+       case FSG_STATE_CLASS_RESET:
                /*
                 * In case we were forced against our will to halt a
                 * bulk endpoint, clear the halt now.  (The SuperH UDC
@@ -2511,6 +2511,7 @@ static void handle_exception(struct fsg_
 
        case FSG_STATE_INTERFACE_CHANGE:
        case FSG_STATE_DISCONNECT:
+       case FSG_STATE_RESET:
        case FSG_STATE_COMMAND_PHASE:
        case FSG_STATE_DATA_PHASE:
        case FSG_STATE_STATUS_PHASE:

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to