Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f063aea authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6:
  pcmcia: use dev_pm_ops for class pcmcia_socket_class
  power: support _noirq actions on device types and classes
  pcmcia: allow for four multifunction subdevices (again)
  pcmcia: do not use ioports < 0x100 on x86
  pd6729: Coding Style fixes
parents f3845f3f d7646f76
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -439,8 +439,23 @@ static int device_resume_noirq(struct device *dev, pm_message_t state)
	if (dev->bus && dev->bus->pm) {
		pm_dev_dbg(dev, state, "EARLY ");
		error = pm_noirq_op(dev, dev->bus->pm, state);
		if (error)
			goto End;
	}

	if (dev->type && dev->type->pm) {
		pm_dev_dbg(dev, state, "EARLY type ");
		error = pm_noirq_op(dev, dev->type->pm, state);
		if (error)
			goto End;
	}

	if (dev->class && dev->class->pm) {
		pm_dev_dbg(dev, state, "EARLY class ");
		error = pm_noirq_op(dev, dev->class->pm, state);
	}

End:
	TRACE_RESUME(error);
	return error;
}
@@ -735,10 +750,26 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state)
{
	int error = 0;

	if (dev->class && dev->class->pm) {
		pm_dev_dbg(dev, state, "LATE class ");
		error = pm_noirq_op(dev, dev->class->pm, state);
		if (error)
			goto End;
	}

	if (dev->type && dev->type->pm) {
		pm_dev_dbg(dev, state, "LATE type ");
		error = pm_noirq_op(dev, dev->type->pm, state);
		if (error)
			goto End;
	}

	if (dev->bus && dev->bus->pm) {
		pm_dev_dbg(dev, state, "LATE ");
		error = pm_noirq_op(dev, dev->bus->pm, state);
	}

End:
	return error;
}

+0 −2
Original line number Diff line number Diff line
@@ -361,7 +361,6 @@ static int at91_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
	struct at91_cf_socket	*cf = platform_get_drvdata(pdev);
	struct at91_cf_data	*board = cf->board;

	pcmcia_socket_dev_suspend(&pdev->dev);
	if (device_may_wakeup(&pdev->dev)) {
		enable_irq_wake(board->det_pin);
		if (board->irq_pin)
@@ -381,7 +380,6 @@ static int at91_cf_resume(struct platform_device *pdev)
			disable_irq_wake(board->irq_pin);
	}

	pcmcia_socket_dev_resume(&pdev->dev);
	return 0;
}

+0 −13
Original line number Diff line number Diff line
@@ -510,17 +510,6 @@ static int au1x00_drv_pcmcia_probe(struct platform_device *dev)
	return ret;
}

static int au1x00_drv_pcmcia_suspend(struct platform_device *dev,
				     pm_message_t state)
{
	return pcmcia_socket_dev_suspend(&dev->dev);
}

static int au1x00_drv_pcmcia_resume(struct platform_device *dev)
{
	return pcmcia_socket_dev_resume(&dev->dev);
}

static struct platform_driver au1x00_pcmcia_driver = {
	.driver = {
		.name		= "au1x00-pcmcia",
@@ -528,8 +517,6 @@ static struct platform_driver au1x00_pcmcia_driver = {
	},
	.probe		= au1x00_drv_pcmcia_probe,
	.remove		= au1x00_drv_pcmcia_remove,
	.suspend 	= au1x00_drv_pcmcia_suspend,
	.resume 	= au1x00_drv_pcmcia_resume,
};


+0 −12
Original line number Diff line number Diff line
@@ -300,16 +300,6 @@ static int __devexit bfin_cf_remove(struct platform_device *pdev)
	return 0;
}

static int bfin_cf_suspend(struct platform_device *pdev, pm_message_t mesg)
{
	return pcmcia_socket_dev_suspend(&pdev->dev);
}

static int bfin_cf_resume(struct platform_device *pdev)
{
	return pcmcia_socket_dev_resume(&pdev->dev);
}

static struct platform_driver bfin_cf_driver = {
	.driver = {
		   .name = (char *)driver_name,
@@ -317,8 +307,6 @@ static struct platform_driver bfin_cf_driver = {
		   },
	.probe = bfin_cf_probe,
	.remove = __devexit_p(bfin_cf_remove),
	.suspend = bfin_cf_suspend,
	.resume = bfin_cf_resume,
};

static int __init bfin_cf_init(void)
+63 −61
Original line number Diff line number Diff line
@@ -76,65 +76,6 @@ DECLARE_RWSEM(pcmcia_socket_list_rwsem);
EXPORT_SYMBOL(pcmcia_socket_list_rwsem);


/*
 * Low-level PCMCIA socket drivers need to register with the PCCard
 * core using pcmcia_register_socket.
 *
 * socket drivers are expected to use the following callbacks in their
 * .drv struct:
 *  - pcmcia_socket_dev_suspend
 *  - pcmcia_socket_dev_resume
 * These functions check for the appropriate struct pcmcia_soket arrays,
 * and pass them to the low-level functions pcmcia_{suspend,resume}_socket
 */
static int socket_early_resume(struct pcmcia_socket *skt);
static int socket_late_resume(struct pcmcia_socket *skt);
static int socket_resume(struct pcmcia_socket *skt);
static int socket_suspend(struct pcmcia_socket *skt);

static void pcmcia_socket_dev_run(struct device *dev,
				  int (*cb)(struct pcmcia_socket *))
{
	struct pcmcia_socket *socket;

	down_read(&pcmcia_socket_list_rwsem);
	list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
		if (socket->dev.parent != dev)
			continue;
		mutex_lock(&socket->skt_mutex);
		cb(socket);
		mutex_unlock(&socket->skt_mutex);
	}
	up_read(&pcmcia_socket_list_rwsem);
}

int pcmcia_socket_dev_suspend(struct device *dev)
{
	pcmcia_socket_dev_run(dev, socket_suspend);
	return 0;
}
EXPORT_SYMBOL(pcmcia_socket_dev_suspend);

void pcmcia_socket_dev_early_resume(struct device *dev)
{
	pcmcia_socket_dev_run(dev, socket_early_resume);
}
EXPORT_SYMBOL(pcmcia_socket_dev_early_resume);

void pcmcia_socket_dev_late_resume(struct device *dev)
{
	pcmcia_socket_dev_run(dev, socket_late_resume);
}
EXPORT_SYMBOL(pcmcia_socket_dev_late_resume);

int pcmcia_socket_dev_resume(struct device *dev)
{
	pcmcia_socket_dev_run(dev, socket_resume);
	return 0;
}
EXPORT_SYMBOL(pcmcia_socket_dev_resume);


struct pcmcia_socket *pcmcia_get_socket(struct pcmcia_socket *skt)
{
	struct device *dev = get_device(&skt->dev);
@@ -578,12 +519,18 @@ static int socket_early_resume(struct pcmcia_socket *skt)

static int socket_late_resume(struct pcmcia_socket *skt)
{
	int ret;

	mutex_lock(&skt->ops_mutex);
	skt->state &= ~SOCKET_SUSPEND;
	mutex_unlock(&skt->ops_mutex);

	if (!(skt->state & SOCKET_PRESENT))
		return socket_insert(skt);
	if (!(skt->state & SOCKET_PRESENT)) {
		ret = socket_insert(skt);
		if (ret == -ENODEV)
			ret = 0;
		return ret;
	}

	if (skt->resume_status) {
		socket_shutdown(skt);
@@ -919,11 +866,66 @@ static void pcmcia_release_socket_class(struct class *data)
}


#ifdef CONFIG_PM

static int __pcmcia_pm_op(struct device *dev,
			  int (*callback) (struct pcmcia_socket *skt))
{
	struct pcmcia_socket *s = container_of(dev, struct pcmcia_socket, dev);
	int ret;

	mutex_lock(&s->skt_mutex);
	ret = callback(s);
	mutex_unlock(&s->skt_mutex);

	return ret;
}

static int pcmcia_socket_dev_suspend_noirq(struct device *dev)
{
	return __pcmcia_pm_op(dev, socket_suspend);
}

static int pcmcia_socket_dev_resume_noirq(struct device *dev)
{
	return __pcmcia_pm_op(dev, socket_early_resume);
}

static int pcmcia_socket_dev_resume(struct device *dev)
{
	return __pcmcia_pm_op(dev, socket_late_resume);
}

static const struct dev_pm_ops pcmcia_socket_pm_ops = {
	/* dev_resume may be called with IRQs enabled */
	SET_SYSTEM_SLEEP_PM_OPS(NULL,
				pcmcia_socket_dev_resume)

	/* late suspend must be called with IRQs disabled */
	.suspend_noirq = pcmcia_socket_dev_suspend_noirq,
	.freeze_noirq = pcmcia_socket_dev_suspend_noirq,
	.poweroff_noirq = pcmcia_socket_dev_suspend_noirq,

	/* early resume must be called with IRQs disabled */
	.resume_noirq = pcmcia_socket_dev_resume_noirq,
	.thaw_noirq = pcmcia_socket_dev_resume_noirq,
	.restore_noirq = pcmcia_socket_dev_resume_noirq,
};

#define PCMCIA_SOCKET_CLASS_PM_OPS (&pcmcia_socket_pm_ops)

#else /* CONFIG_PM */

#define PCMCIA_SOCKET_CLASS_PM_OPS NULL

#endif /* CONFIG_PM */

struct class pcmcia_socket_class = {
	.name = "pcmcia_socket",
	.dev_uevent = pcmcia_socket_uevent,
	.dev_release = pcmcia_release_socket,
	.class_release = pcmcia_release_socket_class,
	.pm = PCMCIA_SOCKET_CLASS_PM_OPS,
};
EXPORT_SYMBOL(pcmcia_socket_class);

Loading