|
@@ -1290,15 +1290,23 @@ static void if_sdio_remove(struct sdio_func *func)
|
|
|
static int if_sdio_suspend(struct device *dev)
|
|
|
{
|
|
|
struct sdio_func *func = dev_to_sdio_func(dev);
|
|
|
- int ret;
|
|
|
struct if_sdio_card *card = sdio_get_drvdata(func);
|
|
|
+ struct lbs_private *priv = card->priv;
|
|
|
+ int ret;
|
|
|
|
|
|
mmc_pm_flag_t flags = sdio_get_host_pm_caps(func);
|
|
|
+ priv->power_up_on_resume = false;
|
|
|
|
|
|
/* If we're powered off anyway, just let the mmc layer remove the
|
|
|
* card. */
|
|
|
- if (!lbs_iface_active(card->priv))
|
|
|
- return -ENOSYS;
|
|
|
+ if (!lbs_iface_active(priv)) {
|
|
|
+ if (priv->fw_ready) {
|
|
|
+ priv->power_up_on_resume = true;
|
|
|
+ if_sdio_power_off(card);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
|
|
|
dev_info(dev, "%s: suspend: PM flags = 0x%x\n",
|
|
|
sdio_func_id(func), flags);
|
|
@@ -1306,9 +1314,14 @@ static int if_sdio_suspend(struct device *dev)
|
|
|
/* If we aren't being asked to wake on anything, we should bail out
|
|
|
* and let the SD stack power down the card.
|
|
|
*/
|
|
|
- if (card->priv->wol_criteria == EHS_REMOVE_WAKEUP) {
|
|
|
+ if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
|
|
|
dev_info(dev, "Suspend without wake params -- powering down card\n");
|
|
|
- return -ENOSYS;
|
|
|
+ if (priv->fw_ready) {
|
|
|
+ priv->power_up_on_resume = true;
|
|
|
+ if_sdio_power_off(card);
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
if (!(flags & MMC_PM_KEEP_POWER)) {
|
|
@@ -1321,7 +1334,7 @@ static int if_sdio_suspend(struct device *dev)
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- ret = lbs_suspend(card->priv);
|
|
|
+ ret = lbs_suspend(priv);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
@@ -1336,6 +1349,11 @@ static int if_sdio_resume(struct device *dev)
|
|
|
|
|
|
dev_info(dev, "%s: resume: we're back\n", sdio_func_id(func));
|
|
|
|
|
|
+ if (card->priv->power_up_on_resume) {
|
|
|
+ if_sdio_power_on(card);
|
|
|
+ wait_event(card->pwron_waitq, card->priv->fw_ready);
|
|
|
+ }
|
|
|
+
|
|
|
ret = lbs_resume(card->priv);
|
|
|
|
|
|
return ret;
|