From patchwork Fri Jan 21 20:44:50 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vasily Khoruzhick X-Patchwork-Id: 496571 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p0LKlWRw014452 for ; Fri, 21 Jan 2011 20:47:33 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753751Ab1AUUr2 (ORCPT ); Fri, 21 Jan 2011 15:47:28 -0500 Received: from mail-ew0-f46.google.com ([209.85.215.46]:46839 "EHLO mail-ew0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753766Ab1AUUr0 (ORCPT ); Fri, 21 Jan 2011 15:47:26 -0500 Received: by mail-ew0-f46.google.com with SMTP id 5so1170225ewy.19 for ; Fri, 21 Jan 2011 12:47:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:subject:date:message-id:x-mailer :in-reply-to:references; bh=fzc+fbphut9uZefEehPylnO6IAhfZBBO2Vpb+Okp0ls=; b=bdp9eOWDm55UIkNumEbHLhc7qA+sPp9k+HGsYJ8LCNNiZICG8Yd7JBIvTHBjlNxtTL bZbq/7XLNOH2wFQSTpfR+T52D/0s4wE6V7vMrTXKVB2e+wnRTHsJYJACdnfoymYSAYTk xOO4JUMxkRrwMI7TLsdH2qeedOxW98duhdTSM= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:subject:date:message-id:x-mailer:in-reply-to:references; b=Aro8k2gasVMj66GDbIxDusgLK9yTLJCyit//KfEk94f8P/MazChaBIMzvI+50rrRr/ opsBun5/CY4g6LpB604tzGEt6NZWW8ravt36oD+ow+z5G6HS6x4ytSq/TIQ0kFx9SHOC 07XJq4p9bsKjvTolFtk3KYnn0VRDgiFKD2+sU= Received: by 10.213.36.2 with SMTP id r2mr1583750ebd.51.1295642845407; Fri, 21 Jan 2011 12:47:25 -0800 (PST) Received: from localhost.localdomain ([80.249.94.18]) by mx.google.com with ESMTPS id x54sm7794339eeh.5.2011.01.21.12.47.22 (version=TLSv1/SSLv3 cipher=RC4-MD5); Fri, 21 Jan 2011 12:47:24 -0800 (PST) From: Vasily Khoruzhick To: libertas-dev@lists.infradead.org, linux-wireless@vger.kernel.org, Andrey Yurovsky , Colin McCabe , Marek Vasut , anarsoul@gmail.com Subject: [PATCH 3/3] libertas_spi: Add support for suspend/resume Date: Fri, 21 Jan 2011 22:44:50 +0200 Message-Id: <1295642690-16646-4-git-send-email-anarsoul@gmail.com> X-Mailer: git-send-email 1.7.4.rc1 In-Reply-To: <1295642690-16646-1-git-send-email-anarsoul@gmail.com> References: <1295642690-16646-1-git-send-email-anarsoul@gmail.com> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 21 Jan 2011 20:47:33 +0000 (UTC) diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index f6c2cd6..772da3a 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c @@ -57,6 +57,7 @@ struct if_spi_card { /* Handles all SPI communication (except for FW load) */ struct workqueue_struct *workqueue; struct work_struct packet_work; + struct work_struct resume_work; u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; @@ -1057,6 +1058,24 @@ out: return err; } +static void if_spi_resume_worker(struct work_struct *work) +{ + struct if_spi_card *card; + + card = container_of(work, struct if_spi_card, resume_work); + + if (card->pdata->setup) + card->pdata->setup(card->spi); + + /* Init card ... */ + if_spi_init_card(card); + + enable_irq(card->spi->irq); + + /* And resume it ... */ + lbs_resume(card->priv); +} + static int __devinit if_spi_probe(struct spi_device *spi) { struct if_spi_card *card; @@ -1107,6 +1126,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) goto free_card; } card->priv = priv; + priv->setup_fw_on_resume = 1; priv->card = card; priv->hw_host_to_card = if_spi_host_to_card; priv->enter_deep_sleep = NULL; @@ -1117,6 +1137,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) /* Initialize interrupt handling stuff. */ card->workqueue = create_workqueue("libertas_spi"); INIT_WORK(&card->packet_work, if_spi_host_to_card_worker); + INIT_WORK(&card->resume_work, if_spi_resume_worker); err = request_irq(spi->irq, if_spi_host_interrupt, IRQF_TRIGGER_FALLING, "libertas_spi", card); @@ -1161,6 +1182,8 @@ static int __devexit libertas_spi_remove(struct spi_device *spi) lbs_deb_spi("libertas_spi_remove\n"); lbs_deb_enter(LBS_DEB_SPI); + cancel_work_sync(&card->resume_work); + lbs_stop_card(priv); lbs_remove_card(priv); /* will call free_netdev */ @@ -1174,6 +1197,37 @@ static int __devexit libertas_spi_remove(struct spi_device *spi) return 0; } +static int if_spi_suspend(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + struct if_spi_card *card = spi_get_drvdata(spi); + + lbs_suspend(card->priv); + flush_workqueue(card->workqueue); + disable_irq(spi->irq); + + if (card->pdata->teardown) + card->pdata->teardown(spi); + + return 0; +} + +static int if_spi_resume(struct device *dev) +{ + struct spi_device *spi = to_spi_device(dev); + struct if_spi_card *card = spi_get_drvdata(spi); + + /* Schedule delayed work */ + schedule_work(&card->resume_work); + + return 0; +} + +static const struct dev_pm_ops if_spi_pm_ops = { + .suspend = if_spi_suspend, + .resume = if_spi_resume, +}; + static struct spi_driver libertas_spi_driver = { .probe = if_spi_probe, .remove = __devexit_p(libertas_spi_remove), @@ -1181,6 +1235,7 @@ static struct spi_driver libertas_spi_driver = { .name = "libertas_spi", .bus = &spi_bus_type, .owner = THIS_MODULE, + .pm = &if_spi_pm_ops, }, };