/*------------------------------------------------------------------------------ * This is called when the USB service is stopped or paused for a PD. * Context: softirq or process */ void oz_usb_stop(struct oz_pd *pd, int pause) { struct oz_usb_ctx *usb_ctx; if (pause) { oz_trace("USB service paused.\n"); return; } spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]); usb_ctx = (struct oz_usb_ctx *)pd->app_ctx[OZ_APPID_USB-1]; pd->app_ctx[OZ_APPID_USB-1] = NULL; spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]); if (usb_ctx) { unsigned long tout = jiffies + HZ; oz_trace("USB service stopping...\n"); usb_ctx->stopped = 1; /* At this point the reference count on the usb context should * be 2 - one from when we created it and one from the hcd * which claims a reference. Since stopped = 1 no one else * should get in but someone may already be in. So wait * until they leave but timeout after 1 second. */ while ((atomic_read(&usb_ctx->ref_count) > 2) && time_before(jiffies, tout)) ; oz_trace("USB service stopped.\n"); oz_hcd_pd_departed(usb_ctx->hport); /* Release the reference taken in oz_usb_start. */ oz_usb_put(usb_ctx); } }
/* * This is called when the USB service is stopped or paused for a PD. * Context: softirq or process */ void oz_usb_stop(struct oz_pd *pd, int pause) { struct oz_usb_ctx *usb_ctx; if (pause) { oz_dbg(ON, "USB service paused\n"); return; } spin_lock_bh(&pd->app_lock[OZ_APPID_USB-1]); usb_ctx = (struct oz_usb_ctx *)pd->app_ctx[OZ_APPID_USB-1]; pd->app_ctx[OZ_APPID_USB-1] = NULL; spin_unlock_bh(&pd->app_lock[OZ_APPID_USB-1]); if (usb_ctx) { struct timespec ts, now; getnstimeofday(&ts); oz_dbg(ON, "USB service stopping...\n"); usb_ctx->stopped = 1; /* At this point the reference count on the usb context should * be 2 - one from when we created it and one from the hcd * which claims a reference. Since stopped = 1 no one else * should get in but someone may already be in. So wait * until they leave but timeout after 1 second. */ while ((atomic_read(&usb_ctx->ref_count) > 2)) { getnstimeofday(&now); /*Approx 1 Sec. this is not perfect calculation*/ if (now.tv_sec != ts.tv_sec) break; } oz_dbg(ON, "USB service stopped\n"); oz_hcd_pd_departed(usb_ctx->hport); /* Release the reference taken in oz_usb_start. */ oz_usb_put(usb_ctx); } }