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

Commit 8e9e793d authored by Dominik Brodowski's avatar Dominik Brodowski
Browse files

[PATCH] pcmcia: merge suspend into device model



Merge the suspend and resume methods for 16-bit PCMCIA cards into the
device model -- for both runtime power management and suspend to ram/disk.

Bugfix in ds.c by Richard Purdie
Signed-Off-By: default avatarRichard Purdie <rpurdie@rpsys.net>

Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
parent 98e4c28b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ int dpm_runtime_suspend(struct device * dev, pm_message_t state)
	up(&dpm_sem);
	return error;
}
EXPORT_SYMBOL(dpm_runtime_suspend);


#if 0
+13 −1
Original line number Diff line number Diff line
@@ -780,8 +780,13 @@ int pccard_reset_card(struct pcmcia_socket *skt)
		ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);
		if (ret == 0) {
			send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);
			if (socket_reset(skt) == CS_SUCCESS)
			if (skt->callback)
				skt->callback->suspend(skt);
			if (socket_reset(skt) == CS_SUCCESS) {
				send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);
				if (skt->callback)
					skt->callback->resume(skt);
			}
		}

		ret = CS_SUCCESS;
@@ -812,6 +817,11 @@ int pcmcia_suspend_card(struct pcmcia_socket *skt)
			ret = CS_UNSUPPORTED_FUNCTION;
			break;
		}
		if (skt->callback) {
			ret = skt->callback->suspend(skt);
			if (ret)
				break;
		}
		ret = socket_suspend(skt);
	} while (0);
	up(&skt->skt_sem);
@@ -838,6 +848,8 @@ int pcmcia_resume_card(struct pcmcia_socket *skt)
			break;
		}
		ret = socket_resume(skt);
		if (!ret && skt->callback)
			skt->callback->resume(skt);
	} while (0);
	up(&skt->skt_sem);

+2 −0
Original line number Diff line number Diff line
@@ -143,6 +143,8 @@ struct pcmcia_callback{
	struct module	*owner;
	int		(*event) (struct pcmcia_socket *s, event_t event, int priority);
	void		(*requery) (struct pcmcia_socket *s);
	int		(*suspend) (struct pcmcia_socket *s);
	int		(*resume) (struct pcmcia_socket *s);
};

int pccard_register_pcmcia(struct pcmcia_socket *s, struct pcmcia_callback *c);
+84 −10
Original line number Diff line number Diff line
@@ -920,6 +920,78 @@ static struct device_attribute pcmcia_dev_attrs[] = {
	__ATTR_NULL,
};

/* PM support, also needed for reset */

static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
{
	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
	struct pcmcia_driver *p_drv = NULL;

	if (dev->driver)
		p_drv = to_pcmcia_drv(dev->driver);

	if (p_drv && p_drv->suspend)
		return p_drv->suspend(p_dev);

	return 0;
}


static int pcmcia_dev_resume(struct device * dev)
{
	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
        struct pcmcia_driver *p_drv = NULL;

	if (dev->driver)
		p_drv = to_pcmcia_drv(dev->driver);

	if (p_drv && p_drv->resume)
		return p_drv->resume(p_dev);

	return 0;
}


static int pcmcia_bus_suspend_callback(struct device *dev, void * _data)
{
	struct pcmcia_socket *skt = _data;
	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);

	if (p_dev->socket != skt)
		return 0;

	return dpm_runtime_suspend(dev, PMSG_SUSPEND);
}

static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
{
	struct pcmcia_socket *skt = _data;
	struct pcmcia_device *p_dev = to_pcmcia_dev(dev);

	if (p_dev->socket != skt)
		return 0;

	dpm_runtime_resume(dev);

	return 0;
}

static int pcmcia_bus_resume(struct pcmcia_socket *skt)
{
	bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback);
	return 0;
}

static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
{
	if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt,
			     pcmcia_bus_suspend_callback)) {
		pcmcia_bus_resume(skt);
		return -EIO;
	}
	return 0;
}


/*======================================================================

@@ -951,16 +1023,6 @@ static int send_event_callback(struct device *dev, void * _data)
	if (p_dev->state & (CLIENT_UNBOUND|CLIENT_STALE))
		return 0;

	if ((data->event == CS_EVENT_PM_SUSPEND) ||
	    (data->event == CS_EVENT_RESET_PHYSICAL)) {
		if (p_drv->suspend)
			return p_drv->suspend(p_dev);
	} else if ((data->event == CS_EVENT_PM_RESUME) ||
		   (data->event == CS_EVENT_CARD_RESET)) {
		if (p_drv->resume)
			return p_drv->resume(p_dev);
	}

	if (p_drv->event)
		return p_drv->event(data->event, data->priority,
				    &p_dev->event_callback_args);
@@ -1012,6 +1074,13 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority)
		ret = send_event(skt, event, priority);
		break;

	case CS_EVENT_PM_SUSPEND:
	case CS_EVENT_PM_RESUME:
	case CS_EVENT_RESET_PHYSICAL:
	case CS_EVENT_CARD_RESET:
		handle_event(skt, event);
		break;

	default:
		handle_event(skt, event);
		send_event(skt, event, priority);
@@ -1166,10 +1235,13 @@ int pcmcia_deregister_client(struct pcmcia_device *p_dev)
} /* deregister_client */
EXPORT_SYMBOL(pcmcia_deregister_client);


static struct pcmcia_callback pcmcia_bus_callback = {
	.owner = THIS_MODULE,
	.event = ds_event,
	.requery = pcmcia_bus_rescan,
	.suspend = pcmcia_bus_suspend,
	.resume = pcmcia_bus_resume,
};

static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
@@ -1238,6 +1310,8 @@ struct bus_type pcmcia_bus_type = {
	.uevent = pcmcia_bus_uevent,
	.match = pcmcia_bus_match,
	.dev_attrs = pcmcia_dev_attrs,
	.suspend = pcmcia_dev_suspend,
	.resume = pcmcia_dev_resume,
};