From: Rui Miguel Silva Date: Thu, 2 Jul 2015 18:11:31 +0000 (+0100) Subject: greybus: sdio: rework of event handler X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=c36d31cbc57635f7e66176d84d7b8688796a01d3;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git 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: Rui Miguel Silva Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/greybus/sdio.c b/drivers/staging/greybus/sdio.c index e842cae7a5bd..53cb46f6f7c8 100644 --- a/drivers/staging/greybus/sdio.c +++ b/drivers/staging/greybus/sdio.c @@ -28,6 +28,7 @@ struct gb_sdio_host { spinlock_t xfer; /* lock to cancel ongoing transfer */ bool xfer_stop; struct work_struct mrqwork; + u8 queued_events; bool removed; bool card_present; bool read_only; @@ -121,54 +122,40 @@ static int gb_sdio_get_caps(struct gb_sdio_host *host) 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; - struct gb_sdio_host *host = connection->private; - struct gb_message *request; - struct gb_sdio_event_request *payload; - 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 (event & GB_SDIO_CARD_INSERTED) + host->queued_events &= ~GB_SDIO_CARD_REMOVED; + else if (event & GB_SDIO_CARD_REMOVED) + host->queued_events &= ~GB_SDIO_CARD_INSERTED; - if (request->payload_size != sizeof(*payload)) { - dev_err(mmc_dev(host->mmc), "wrong event size received\n"); - return -EINVAL; - } + host->queued_events |= event; +} - payload = request->payload; - event = payload->event; +static int _gb_sdio_process_events(struct gb_sdio_host *host, u8 event) +{ + u8 state_changed = 0; - switch (event) { - case GB_SDIO_CARD_INSERTED: + if (event & GB_SDIO_CARD_INSERTED) { if (!mmc_card_is_removable(host->mmc)) return 0; if (host->card_present) return 0; host->card_present = true; state_changed = 1; - break; - case GB_SDIO_CARD_REMOVED: + } + + if (event & GB_SDIO_CARD_REMOVED) { if (!mmc_card_is_removable(host->mmc)) return 0; if (!(host->card_present)) return 0; host->card_present = false; state_changed = 1; - break; - case GB_SDIO_WP: + } + + if (event & GB_SDIO_WP) { host->read_only = true; - break; - default: - dev_err(mmc_dev(host->mmc), "wrong event received %d\n", event); - return -EINVAL; } if (state_changed) { @@ -180,6 +167,39 @@ static int gb_sdio_event_recv(u8 type, struct gb_operation *op) 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, struct gb_sdio_set_ios_request *request) { @@ -649,6 +669,7 @@ static int gb_sdio_connection_init(struct gb_connection *connection) host = mmc_priv(mmc); host->mmc = mmc; + host->removed = true; host->connection = connection; connection->private = host; @@ -683,6 +704,9 @@ static int gb_sdio_connection_init(struct gb_connection *connection) ret = mmc_add_host(mmc); if (ret < 0) goto free_work; + host->removed = false; + ret = _gb_sdio_process_events(host, host->queued_events); + host->queued_events = 0; return ret;