Commit c36d31cb authored by Rui Miguel Silva's avatar Rui Miguel Silva Committed by Greg Kroah-Hartman

greybus: sdio: rework of event handler

Between the time connection with module is up and the host is added,
we can receive events (card inserted/removed, write protection
switch), so until the setup is complete we queue the events received
and handle them after.
Signed-off-by: default avatarRui Miguel Silva <rui.silva@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent ef0cc0ec
...@@ -28,6 +28,7 @@ struct gb_sdio_host { ...@@ -28,6 +28,7 @@ struct gb_sdio_host {
spinlock_t xfer; /* lock to cancel ongoing transfer */ spinlock_t xfer; /* lock to cancel ongoing transfer */
bool xfer_stop; bool xfer_stop;
struct work_struct mrqwork; struct work_struct mrqwork;
u8 queued_events;
bool removed; bool removed;
bool card_present; bool card_present;
bool read_only; bool read_only;
...@@ -121,54 +122,40 @@ static int gb_sdio_get_caps(struct gb_sdio_host *host) ...@@ -121,54 +122,40 @@ static int gb_sdio_get_caps(struct gb_sdio_host *host)
return 0; return 0;
} }
static int gb_sdio_event_recv(u8 type, struct gb_operation *op) static void _gb_queue_event(struct gb_sdio_host *host, u8 event)
{ {
struct gb_connection *connection = op->connection; if (event & GB_SDIO_CARD_INSERTED)
struct gb_sdio_host *host = connection->private; host->queued_events &= ~GB_SDIO_CARD_REMOVED;
struct gb_message *request; else if (event & GB_SDIO_CARD_REMOVED)
struct gb_sdio_event_request *payload; host->queued_events &= ~GB_SDIO_CARD_INSERTED;
u8 state_changed = 0;
u8 event;
if (type != GB_SDIO_TYPE_EVENT) {
dev_err(&connection->dev,
"unsupported unsolicited event: %u\n", type);
return -EINVAL;
}
request = op->request;
if (request->payload_size != sizeof(*payload)) { host->queued_events |= event;
dev_err(mmc_dev(host->mmc), "wrong event size received\n"); }
return -EINVAL;
}
payload = request->payload; static int _gb_sdio_process_events(struct gb_sdio_host *host, u8 event)
event = payload->event; {
u8 state_changed = 0;
switch (event) { if (event & GB_SDIO_CARD_INSERTED) {
case GB_SDIO_CARD_INSERTED:
if (!mmc_card_is_removable(host->mmc)) if (!mmc_card_is_removable(host->mmc))
return 0; return 0;
if (host->card_present) if (host->card_present)
return 0; return 0;
host->card_present = true; host->card_present = true;
state_changed = 1; state_changed = 1;
break; }
case GB_SDIO_CARD_REMOVED:
if (event & GB_SDIO_CARD_REMOVED) {
if (!mmc_card_is_removable(host->mmc)) if (!mmc_card_is_removable(host->mmc))
return 0; return 0;
if (!(host->card_present)) if (!(host->card_present))
return 0; return 0;
host->card_present = false; host->card_present = false;
state_changed = 1; state_changed = 1;
break; }
case GB_SDIO_WP:
if (event & GB_SDIO_WP) {
host->read_only = true; host->read_only = true;
break;
default:
dev_err(mmc_dev(host->mmc), "wrong event received %d\n", event);
return -EINVAL;
} }
if (state_changed) { if (state_changed) {
...@@ -180,6 +167,39 @@ static int gb_sdio_event_recv(u8 type, struct gb_operation *op) ...@@ -180,6 +167,39 @@ static int gb_sdio_event_recv(u8 type, struct gb_operation *op)
return 0; return 0;
} }
static int gb_sdio_event_recv(u8 type, struct gb_operation *op)
{
struct gb_connection *connection = op->connection;
struct gb_sdio_host *host = connection->private;
struct gb_message *request;
struct gb_sdio_event_request *payload;
int ret = 0;
u8 event;
if (type != GB_SDIO_TYPE_EVENT) {
dev_err(&connection->dev,
"unsupported unsolicited event: %u\n", type);
return -EINVAL;
}
request = op->request;
if (request->payload_size != sizeof(*payload)) {
dev_err(mmc_dev(host->mmc), "wrong event size received\n");
return -EINVAL;
}
payload = request->payload;
event = payload->event;
if (host->removed)
_gb_queue_event(host, event);
else
ret = _gb_sdio_process_events(host, event);
return ret;
}
static int gb_sdio_set_ios(struct gb_sdio_host *host, static int gb_sdio_set_ios(struct gb_sdio_host *host,
struct gb_sdio_set_ios_request *request) struct gb_sdio_set_ios_request *request)
{ {
...@@ -649,6 +669,7 @@ static int gb_sdio_connection_init(struct gb_connection *connection) ...@@ -649,6 +669,7 @@ static int gb_sdio_connection_init(struct gb_connection *connection)
host = mmc_priv(mmc); host = mmc_priv(mmc);
host->mmc = mmc; host->mmc = mmc;
host->removed = true;
host->connection = connection; host->connection = connection;
connection->private = host; connection->private = host;
...@@ -683,6 +704,9 @@ static int gb_sdio_connection_init(struct gb_connection *connection) ...@@ -683,6 +704,9 @@ static int gb_sdio_connection_init(struct gb_connection *connection)
ret = mmc_add_host(mmc); ret = mmc_add_host(mmc);
if (ret < 0) if (ret < 0)
goto free_work; goto free_work;
host->removed = false;
ret = _gb_sdio_process_events(host, host->queued_events);
host->queued_events = 0;
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment