]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
staging: ozwpan: set port changed flag at disconnect
authorVinayak Pane <vpane@nvidia.com>
Fri, 27 Jun 2014 02:38:03 +0000 (19:38 -0700)
committerEric Chuang <echuang@nvidia.com>
Sun, 29 Jun 2014 23:12:04 +0000 (16:12 -0700)
Set port changed flag at every hub disconnect control message.
USB hub status should know correct port status always.

Also contains ugly WAR to recover from network failure cases.
After 3 port reset retries reset the net interface.

Bug 1522708

Change-Id: I1aa5baa837f60668cfb4a23dd7fa820be27151e7
Signed-off-by: Vinayak Pane <vpane@nvidia.com>
Reviewed-on: http://git-master/r/431926
GVS: Gerrit_Virtual_Submit
Reviewed-by: Peter Zu <pzu@nvidia.com>
Reviewed-by: Kevin Bruckert <kbruckert@nvidia.com>
Tested-by: Kevin Bruckert <kbruckert@nvidia.com>
Reviewed-by: Mitch Luban <mluban@nvidia.com>
drivers/staging/ozwpan/ozhcd.c
drivers/staging/ozwpan/ozpd.c
drivers/staging/ozwpan/ozpd.h

index 42c8a088074086f133d177f80461d2e38b805031..f43d50f060b263fa903f4d83e07a4e19d8bac27a 100644 (file)
@@ -34,6 +34,9 @@
 #include "oztrace.h"
 #include "ozurbparanoia.h"
 #include "ozhcd.h"
+#include "ozpd.h"
+#include "ozproto.h"
+#include "ozusbsvc.h"
 
 #define OZ_HUB_DEBOUNCE_TIMEOUT        1500
 
@@ -756,6 +759,7 @@ void oz_hcd_pd_departed(void *hport)
        struct oz_port *port = (struct oz_port *)hport;
        struct oz_hcd *ozhcd;
        void *hpd;
+       struct usb_hcd *hcd;
        struct oz_endpoint *ep = NULL;
 
        oz_trace("%s:\n", __func__);
@@ -798,6 +802,8 @@ void oz_hcd_pd_departed(void *hport)
        spin_unlock_bh(&port->port_lock);
        if (ep)
                oz_ep_free(port, ep);
+       hcd = ozhcd->hcd;
+       clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
        oz_trace_msg(H, "usb_hcd_poll_rh_status()\n");
        usb_hcd_poll_rh_status(ozhcd->hcd);
        oz_usb_put(hpd);
@@ -1995,6 +2001,29 @@ static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
                ozhcd->ports[port_id-1].bus_addr = 0;
                hpd = oz_claim_hpd(&ozhcd->ports[port_id-1]);
                if (hpd != NULL) {
+                       struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
+                       struct oz_pd *pd = (struct oz_pd *)usb_ctx->pd;
+
+                       /* FIXME: Hack to reset network interface
+                        * Unrecoverable situation occured.
+                        */
+                       if (pd && ((++pd->reset_retry > 2) ||
+                               (!(pd->state & OZ_PD_S_CONNECTED)))) {
+                               char *_net_dev = "";
+
+                               pr_info("OZ: tear down network interface\n");
+                               spin_lock_bh(&port->port_lock);
+                               port->flags |= OZ_PORT_F_CHANGED;
+                               spin_unlock_bh(&port->port_lock);
+                               oz_usb_put(hpd);
+
+                               oz_pd_stop(pd);
+                               msleep(10);
+                               oz_protocol_term();
+                               msleep(100);
+                               oz_protocol_init(_net_dev);
+                               break;
+                       }
                        oz_usb_reset_device(hpd);
                        oz_usb_put(hpd);
                }
@@ -2083,6 +2112,10 @@ static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
        case USB_PORT_FEAT_C_CONNECTION:
                oz_trace("USB_PORT_FEAT_C_CONNECTION\n");
                clear_bits = (USB_PORT_STAT_C_CONNECTION << 16);
+               spin_lock_bh(&port->port_lock);
+               port->flags |= OZ_PORT_F_CHANGED;
+               spin_unlock_bh(&port->port_lock);
+
                break;
        case USB_PORT_FEAT_C_ENABLE:
                oz_trace("USB_PORT_FEAT_C_ENABLE\n");
index bc488433856d8b3c87ed8029bdce39544d454496..24db6ded553c91f51cfb0ca36089becf08d1749b 100644 (file)
@@ -202,6 +202,7 @@ struct oz_pd *oz_pd_alloc(const u8 *mac_addr)
                hrtimer_init(&pd->timeout, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
                pd->heartbeat.function = oz_pd_heartbeat_event;
                pd->timeout.function = oz_pd_timeout_event;
+               pd->reset_retry = 0;
                atomic_set(&pd->pd_destroy_scheduled, 0);
                memset(&pd->workitem, 0, sizeof(pd->workitem));
                INIT_WORK(&pd->workitem, oz_pd_free);
index f21c830db56464dff628b9e57e3fbecb97df4460..a19ad5712626131a14a578e40100764253876f25 100644 (file)
@@ -111,6 +111,7 @@ struct oz_pd {
        struct work_struct workitem;
        struct work_struct uevent_workitem;
        atomic_t        pd_destroy_scheduled;
+       unsigned int reset_retry;
        u8      up_audio_buf;
 };