linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Mauro Carvalho Chehab <mchehab@redhat.com>
To: Stefan Bauer <stefan.bauer@cs.tu-chemnitz.de>
Cc: linux-media@vger.kernel.org, Matthias Schwarzott <zzam@gentoo.org>
Subject: Re: [RFC] b2c2_flexcop_pci: Add suspend/resume support
Date: Thu, 19 Apr 2012 14:51:17 -0300	[thread overview]
Message-ID: <4F905095.5020604@redhat.com> (raw)
In-Reply-To: <201204151618.07719.stefan.bauer@cs.tu-chemnitz.de>

Hi Stefan,

Em 15-04-2012 11:18, Stefan Bauer escreveu:
> Dear linux-dvb developers, dear Matthias,
> 
> 
> proper suspend and resume support for the b2c2_flexcop_pci driver is still missing as pointed out by these two bug reports:
> 
> https://bugs.gentoo.org/show_bug.cgi?id=288267
> https://bugzilla.kernel.org/show_bug.cgi?id=14394
> 
> The first report contains a proposed patch to add suspend/resume support written by Matthias Schwarzott <zzam@gentoo.org>. I and some others (see first bug report) confirm that it's actually working.
> 
> Behaviour without the patch: b2c2_flexcop_pci must be unloaded before suspending (means TV applications must be closed), and reloaded after resuming.
> Behaviour with the patch: No module unloading/reloading necessary any more.
> Known issues: TV application still needs to be closed before suspend. Otherwise the device is not functional (kaffeine shows only black screen) after resume. Reloading the module revives the device in that case.
> 
> I'd kindly ask you to review the attached patch by Matthias and consider its upstream inclusion after the issues are sorted out. I'm more than willing to assist and test as I can.

I don't have any b2c2 device, so I can't actually test it. on a quick lock,
it seems sane on my eyes. In order for us to merge, we need the patch author's
Signed-off-by.

Regards,
Mauro

> 
> 
> Kind regards,
> Stefan Bauer
> ---8<---
> diff --git a/drivers/media/dvb/b2c2/flexcop-common.h b/drivers/media/dvb/b2c2/flexcop-common.h
> index 437912e..c5f11a6 100644
> --- a/drivers/media/dvb/b2c2/flexcop-common.h
> +++ b/drivers/media/dvb/b2c2/flexcop-common.h
> @@ -117,6 +117,9 @@ int flexcop_device_initialize(struct flexcop_device *);
>  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);
> diff --git a/drivers/media/dvb/b2c2/flexcop-pci.c b/drivers/media/dvb/b2c2/flexcop-pci.c
> index 44f8fb5..1ef4b82 100644
> --- a/drivers/media/dvb/b2c2/flexcop-pci.c
> +++ b/drivers/media/dvb/b2c2/flexcop-pci.c
> @@ -293,8 +293,6 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
>  
>  	info("card revision %x", fc_pci->pdev->revision);
>  
> -	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)
> @@ -308,7 +306,6 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
>  		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)
> @@ -319,7 +316,6 @@ static int flexcop_pci_init(struct flexcop_pci *fc_pci)
>  
>  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:
> @@ -332,9 +328,7 @@ static void flexcop_pci_exit(struct flexcop_pci *fc_pci)
>  	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;
>  }
> @@ -373,6 +367,11 @@ static int flexcop_pci_probe(struct pci_dev *pdev,
>  
>  	/* 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;
>  
> @@ -398,6 +397,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;
>  }
> @@ -415,9 +415,74 @@ static void flexcop_pci_remove(struct pci_dev *pdev)
>  	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)
> +{
> +	int ret;
> +	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);
> +
> +	ret = pci_enable_device(pdev);
> +	if (ret < 0) {
> +		err("unable to enable device in resume\n");
> +		return ret;
> +	}
> +
> +	/* from flexcop_pci_probe */
> +	ret = flexcop_pci_init(fc_pci);
> +	if (ret < 0) {
> +		err("could not allocate pci resources in resume\n");
> +		return ret;
> +	}
> +
> +	/* 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) },
>  	{ },
> @@ -430,6 +495,10 @@ static struct pci_driver flexcop_pci_driver = {
>  	.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)
> diff --git a/drivers/media/dvb/b2c2/flexcop.c b/drivers/media/dvb/b2c2/flexcop.c
> index b1e8c99..cb961c8 100644
> --- a/drivers/media/dvb/b2c2/flexcop.c
> +++ b/drivers/media/dvb/b2c2/flexcop.c
> @@ -305,6 +305,75 @@ void flexcop_device_exit(struct flexcop_device *fc)
>  }
>  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 */
> +#if 1
> +	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);
> +#endif
> +
> +#if 1
> +	/* make sure streaming is really off */
> +	if (fc->stream_control)
> +		fc->stream_control(fc, 0);
> +#endif
> +#if 0
> +	fc->feedcount = 0;
> +	fc->extra_feedcount = 0;
> +	flexcop_reset_block_300(fc);
> +	flexcop_hw_filter_init(fc);
> +#endif
> +}
> +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");
> +#if 0
> +	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);
> +#endif
> +
> +	flexcop_device_name(fc, "resume of", "complete");
> +}
> +EXPORT_SYMBOL(flexcop_device_resume);
> +
>  static int flexcop_module_init(void)
>  {
>  	info(DRIVER_NAME " loaded successfully");
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


  reply	other threads:[~2012-04-19 17:51 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-04-15 14:18 [RFC] b2c2_flexcop_pci: Add suspend/resume support Stefan Bauer
2012-04-19 17:51 ` Mauro Carvalho Chehab [this message]
2012-04-27  8:49   ` Matthias Schwarzott

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4F905095.5020604@redhat.com \
    --to=mchehab@redhat.com \
    --cc=linux-media@vger.kernel.org \
    --cc=stefan.bauer@cs.tu-chemnitz.de \
    --cc=zzam@gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).