All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] flexcop-pci: add suspend/resume support
@ 2009-05-26 19:09 Matthias Schwarzott
  2009-06-10 14:26 ` Mauro Carvalho Chehab
  2009-06-11  8:13 ` Patrick Boettcher
  0 siblings, 2 replies; 3+ messages in thread
From: Matthias Schwarzott @ 2009-05-26 19:09 UTC (permalink / raw)
  To: linux-media, Patrick Boettcher; +Cc: Uwe Bugla

[-- Attachment #1: Type: text/plain, Size: 632 bytes --]

Hi Patrick! Hi list!

This patch adds suspend/resume support to flexcop-pci driver.

I could only test this patch with the bare card, but without having a DVB-S 
signal. I checked it with and without running szap (obviously getting no 
lock).
It works fine here with suspend-to-disk on a tuxonice kernel.

Setting of hw-filter in resume is done the same way as the watchdog does it: 
Just looping over fc->demux.feed_list and running flexcop_pid_feed_control.
Where I am unsure is the order at resume. For now hw filters get started 
first, then dma is re-started.

Do I need to give special care to irq handling?

Regards
Matthias

[-- Attachment #2: flexcop-suspend.diff --]
[-- Type: text/x-diff, Size: 6449 bytes --]

Index: v4l-dvb/linux/drivers/media/dvb/b2c2/flexcop-common.h
===================================================================
--- v4l-dvb.orig/linux/drivers/media/dvb/b2c2/flexcop-common.h
+++ v4l-dvb/linux/drivers/media/dvb/b2c2/flexcop-common.h
@@ -117,6 +117,9 @@ int flexcop_device_initialize(struct fle
 void flexcop_device_exit(struct flexcop_device *fc);
 void flexcop_reset_block_300(struct flexcop_device *fc);
 
+void flexcop_device_suspend(struct flexcop_device *fc);
+void flexcop_device_resume(struct flexcop_device *fc);
+
 /* from flexcop-dma.c */
 int flexcop_dma_allocate(struct pci_dev *pdev,
 		struct flexcop_dma *dma, u32 size);
Index: v4l-dvb/linux/drivers/media/dvb/b2c2/flexcop.c
===================================================================
--- v4l-dvb.orig/linux/drivers/media/dvb/b2c2/flexcop.c
+++ v4l-dvb/linux/drivers/media/dvb/b2c2/flexcop.c
@@ -292,6 +292,59 @@ void flexcop_device_exit(struct flexcop_
 }
 EXPORT_SYMBOL(flexcop_device_exit);
 
+void flexcop_device_suspend(struct flexcop_device *fc)
+{
+	/* flexcop_device_exit does only unregister objects
+	 * so just stop streaming here */
+	struct dvb_demux_feed *feed;
+
+	/* copied from flexcop_pci_irq_check_work */
+	info("stopping pid feeds");
+	spin_lock_irq(&fc->demux.lock);
+	list_for_each_entry(feed, &fc->demux.feed_list,
+			list_head) {
+		flexcop_pid_feed_control(fc, feed, 0);
+	}
+	spin_unlock_irq(&fc->demux.lock);
+}
+EXPORT_SYMBOL(flexcop_device_suspend);
+
+void flexcop_device_resume(struct flexcop_device *fc)
+{
+	/* copied from flexcop_device_initialize */
+	struct dvb_demux_feed *feed;
+	flexcop_reset(fc);
+
+	flexcop_sram_init(fc);
+	flexcop_hw_filter_init(fc);
+	flexcop_smc_ctrl(fc, 0);
+
+	/* do the MAC address reading after initializing the dvb_adapter */
+	/* TODO: need not reread MAC address, but status was not saved */
+	if (fc->get_mac_addr(fc, 0) == 0) {
+		u8 *b = fc->dvb_adapter.proposed_mac;
+		info("MAC address = %pM", b);
+		flexcop_set_mac_filter(fc, b);
+		flexcop_mac_filter_ctrl(fc, 1);
+	} else
+		warn("reading of MAC address failed.\n");
+
+	/* TODO: Is it fine to start streaming here,
+	 * before DMA is re-initialized */
+
+	/* copied from flexcop_pci_irq_check_work */
+	info("restarting pid feeds");
+	spin_lock_irq(&fc->demux.lock);
+	list_for_each_entry(feed, &fc->demux.feed_list,
+			list_head) {
+		flexcop_pid_feed_control(fc, feed, 1);
+	}
+	spin_unlock_irq(&fc->demux.lock);
+
+	flexcop_device_name(fc, "resume of", "complete");
+}
+EXPORT_SYMBOL(flexcop_device_resume);
+
 static int flexcop_module_init(void)
 {
 	info(DRIVER_NAME " loaded successfully");
Index: v4l-dvb/linux/drivers/media/dvb/b2c2/flexcop-pci.c
===================================================================
--- v4l-dvb.orig/linux/drivers/media/dvb/b2c2/flexcop-pci.c
+++ v4l-dvb/linux/drivers/media/dvb/b2c2/flexcop-pci.c
@@ -319,8 +319,6 @@ static int flexcop_pci_init(struct flexc
 	pci_read_config_byte(fc_pci->pdev, PCI_CLASS_REVISION, &card_rev);
 	info("card revision %x", card_rev);
 
-	if ((ret = pci_enable_device(fc_pci->pdev)) != 0)
-		return ret;
 	pci_set_master(fc_pci->pdev);
 
 	if ((ret = pci_request_regions(fc_pci->pdev, DRIVER_NAME)) != 0)
@@ -334,7 +332,6 @@ static int flexcop_pci_init(struct flexc
 		goto err_pci_release_regions;
 	}
 
-	pci_set_drvdata(fc_pci->pdev, fc_pci);
 	spin_lock_init(&fc_pci->irq_lock);
 	if ((ret = request_irq(fc_pci->pdev->irq, flexcop_pci_isr,
 					IRQF_SHARED, DRIVER_NAME, fc_pci)) != 0)
@@ -345,7 +342,6 @@ static int flexcop_pci_init(struct flexc
 
 err_pci_iounmap:
 	pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
-	pci_set_drvdata(fc_pci->pdev, NULL);
 err_pci_release_regions:
 	pci_release_regions(fc_pci->pdev);
 err_pci_disable_device:
@@ -358,9 +354,7 @@ static void flexcop_pci_exit(struct flex
 	if (fc_pci->init_state & FC_PCI_INIT) {
 		free_irq(fc_pci->pdev->irq, fc_pci);
 		pci_iounmap(fc_pci->pdev, fc_pci->io_mem);
-		pci_set_drvdata(fc_pci->pdev, NULL);
 		pci_release_regions(fc_pci->pdev);
-		pci_disable_device(fc_pci->pdev);
 	}
 	fc_pci->init_state &= ~FC_PCI_INIT;
 }
@@ -399,6 +393,11 @@ static int flexcop_pci_probe(struct pci_
 
 	/* bus specific part */
 	fc_pci->pdev = pdev;
+	ret = pci_enable_device(pdev);
+	if (ret != 0)
+		goto err_kfree;
+
+	pci_set_drvdata(pdev, fc_pci);
 	if ((ret = flexcop_pci_init(fc_pci)) != 0)
 		goto err_kfree;
 
@@ -428,6 +427,7 @@ err_fc_exit:
 err_pci_exit:
 	flexcop_pci_exit(fc_pci);
 err_kfree:
+	pci_set_drvdata(pdev, NULL);
 	flexcop_device_kfree(fc);
 	return ret;
 }
@@ -445,9 +445,65 @@ static void flexcop_pci_remove(struct pc
 	flexcop_pci_dma_exit(fc_pci);
 	flexcop_device_exit(fc_pci->fc_dev);
 	flexcop_pci_exit(fc_pci);
+	pci_set_drvdata(pdev, NULL);
+	pci_disable_device(pdev);
 	flexcop_device_kfree(fc_pci->fc_dev);
 }
 
+#ifdef CONFIG_PM
+static int flexcop_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
+{
+	struct flexcop_pci *fc_pci = pci_get_drvdata(pdev);
+	struct flexcop_device *fc = fc_pci->fc_dev;
+
+	/* most parts are from flexcop_pci_remove */
+
+	if (irq_chk_intv > 0)
+		cancel_delayed_work(&fc_pci->irq_check_work);
+
+	flexcop_pci_dma_exit(fc_pci);
+	flexcop_device_suspend(fc);
+	flexcop_pci_exit(fc_pci);
+
+	pci_save_state(pdev);
+
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, pci_choose_state(pdev, mesg));
+
+	return 0;
+}
+
+static int flexcop_pci_resume(struct pci_dev *pdev)
+{
+	struct flexcop_pci *fc_pci = pci_get_drvdata(pdev);
+	struct flexcop_device *fc = fc_pci->fc_dev;
+
+	/* restore power state 0 */
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+
+	pci_enable_device(pdev);
+
+	/* from flexcop_pci_probe */
+	flexcop_pci_init(fc_pci);
+
+	/* init flexcop */
+	flexcop_device_resume(fc); /* instead of flexcop_device_initialize */
+
+	/* init dma */
+	flexcop_pci_dma_init(fc_pci);
+
+	/* last step: restart watchdog */
+	if (irq_chk_intv > 0)
+		schedule_delayed_work(&fc_pci->irq_check_work,
+				msecs_to_jiffies(irq_chk_intv < 100 ?
+					100 :
+					irq_chk_intv));
+
+	return 0;
+}
+#endif
+
 static struct pci_device_id flexcop_pci_tbl[] = {
 	{ PCI_DEVICE(0x13d0, 0x2103) },
 	{ },
@@ -460,6 +516,10 @@ static struct pci_driver flexcop_pci_dri
 	.id_table = flexcop_pci_tbl,
 	.probe    = flexcop_pci_probe,
 	.remove   = flexcop_pci_remove,
+#ifdef CONFIG_PM
+	.suspend  = flexcop_pci_suspend,
+	.resume   = flexcop_pci_resume,
+#endif
 };
 
 static int __init flexcop_pci_module_init(void)

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] flexcop-pci: add suspend/resume support
  2009-05-26 19:09 [PATCH] flexcop-pci: add suspend/resume support Matthias Schwarzott
@ 2009-06-10 14:26 ` Mauro Carvalho Chehab
  2009-06-11  8:13 ` Patrick Boettcher
  1 sibling, 0 replies; 3+ messages in thread
From: Mauro Carvalho Chehab @ 2009-06-10 14:26 UTC (permalink / raw)
  To: Matthias Schwarzott; +Cc: linux-media, Patrick Boettcher, Uwe Bugla

Em Tue, 26 May 2009 21:09:28 +0200
Matthias Schwarzott <zzam@gentoo.org> escreveu:

> Hi Patrick! Hi list!
> 
> This patch adds suspend/resume support to flexcop-pci driver.
> 
> I could only test this patch with the bare card, but without having a DVB-S 
> signal. I checked it with and without running szap (obviously getting no 
> lock).
> It works fine here with suspend-to-disk on a tuxonice kernel.
> 
> Setting of hw-filter in resume is done the same way as the watchdog does it: 
> Just looping over fc->demux.feed_list and running flexcop_pid_feed_control.
> Where I am unsure is the order at resume. For now hw filters get started 
> first, then dma is re-started.
> 
> Do I need to give special care to irq handling?

It would be important to have a test with real signals to see if the patch is
really working, and see if it will still work if you suspend while streaming.

Also, you missed your SOB.



Cheers,
Mauro

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] flexcop-pci: add suspend/resume support
  2009-05-26 19:09 [PATCH] flexcop-pci: add suspend/resume support Matthias Schwarzott
  2009-06-10 14:26 ` Mauro Carvalho Chehab
@ 2009-06-11  8:13 ` Patrick Boettcher
  1 sibling, 0 replies; 3+ messages in thread
From: Patrick Boettcher @ 2009-06-11  8:13 UTC (permalink / raw)
  To: Matthias Schwarzott; +Cc: linux-media, Uwe Bugla

Hi Matthias,

On Tue, 26 May 2009, Matthias Schwarzott wrote:
> This patch adds suspend/resume support to flexcop-pci driver.
>
> I could only test this patch with the bare card, but without having a DVB-S
> signal. I checked it with and without running szap (obviously getting no
> lock).
> It works fine here with suspend-to-disk on a tuxonice kernel.

As I'm notoriously out of time I haven't yet checked the functionality 
with suspend though I'm looking forward to do so, because it would 
extremely nice to use suspend2disk for shutting down rather than shutdown.

> Setting of hw-filter in resume is done the same way as the watchdog does it:
> Just looping over fc->demux.feed_list and running flexcop_pid_feed_control.
> Where I am unsure is the order at resume. For now hw filters get started
> first, then dma is re-started.
>
> Do I need to give special care to irq handling?

Good question. I think starting the streaming the same way as it is done 
in normal operation would do the trick, but I'm not sure whether this is 
possible for suspend/resume. I need to try.

Thanks a lot for the patch, I will try to adapt it also for dvb-usb. Like 
that all dvb-usb-based device will become resumable in one shot :). But 
time will tell when. :/

Patrick.

--
   Mail: patrick.boettcher@desy.de
   WWW:  http://www.wi-bw.tfh-wildau.de/~pboettch/

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2009-06-11  8:13 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-26 19:09 [PATCH] flexcop-pci: add suspend/resume support Matthias Schwarzott
2009-06-10 14:26 ` Mauro Carvalho Chehab
2009-06-11  8:13 ` Patrick Boettcher

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.