summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVinayak Pane <vpane@nvidia.com>2014-06-26 19:38:03 -0700
committerMandar Padmawar <mpadmawar@nvidia.com>2014-07-10 02:05:19 -0700
commit630e52e4a8c9cfece1acf289b5d02f4ede7dc358 (patch)
treea482d8ddcef007c00af93cb38ab3c5a1143b135f
parent108d084bf6c4d25ee076f5b48fcac5f3a3e26d03 (diff)
staging: ozwpan: set port changed flag at disconnect
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 (cherry picked from commit bf3790755af42b0d6d2497061b7880078829e9c7) Reviewed-on: http://git-master/r/435721 GVS: Gerrit_Virtual_Submit Reviewed-by: Anshul Jain (SW) <anshulj@nvidia.com> Tested-by: Anshul Jain (SW) <anshulj@nvidia.com>
-rw-r--r--drivers/staging/ozwpan/ozhcd.c33
-rw-r--r--drivers/staging/ozwpan/ozpd.c1
-rw-r--r--drivers/staging/ozwpan/ozpd.h1
3 files changed, 35 insertions, 0 deletions
diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c
index 42c8a0880740..f43d50f060b2 100644
--- a/drivers/staging/ozwpan/ozhcd.c
+++ b/drivers/staging/ozwpan/ozhcd.c
@@ -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");
diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c
index bc488433856d..24db6ded553c 100644
--- a/drivers/staging/ozwpan/ozpd.c
+++ b/drivers/staging/ozwpan/ozpd.c
@@ -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);
diff --git a/drivers/staging/ozwpan/ozpd.h b/drivers/staging/ozwpan/ozpd.h
index f21c830db564..a19ad5712626 100644
--- a/drivers/staging/ozwpan/ozpd.h
+++ b/drivers/staging/ozwpan/ozpd.h
@@ -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;
};