diff options
Diffstat (limited to 'drivers/net/wireless/marvell/libertas/if_sdio.c')
| -rw-r--r-- | drivers/net/wireless/marvell/libertas/if_sdio.c | 93 |
1 files changed, 48 insertions, 45 deletions
diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c index 8d98e7fdd27c..fc5318035822 100644 --- a/drivers/net/wireless/marvell/libertas/if_sdio.c +++ b/drivers/net/wireless/marvell/libertas/if_sdio.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * linux/drivers/net/wireless/libertas/if_sdio.c * @@ -5,11 +6,6 @@ * * Inspired by if_cs.c, Copyright 2007 Holger Schurig * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * * This hardware has more or less no CMD53 support, so all registers * must be accessed using sdio_readb()/sdio_writeb(). * @@ -69,7 +65,7 @@ static const struct sdio_device_id if_sdio_ids[] = { { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, - SDIO_DEVICE_ID_MARVELL_8688WLAN) }, + SDIO_DEVICE_ID_MARVELL_8688_WLAN) }, { /* end: all zeroes */ }, }; @@ -105,9 +101,9 @@ MODULE_FIRMWARE("sd8688_helper.bin"); MODULE_FIRMWARE("sd8688.bin"); struct if_sdio_packet { - struct if_sdio_packet *next; + struct list_head list; u16 nb; - u8 buffer[0] __attribute__((aligned(4))); + u8 buffer[] __aligned(4); }; struct if_sdio_card { @@ -123,10 +119,11 @@ struct if_sdio_card { u8 buffer[65536] __attribute__((aligned(4))); spinlock_t lock; - struct if_sdio_packet *packets; + struct list_head packets; struct workqueue_struct *workqueue; struct work_struct packet_worker; + struct work_struct reset_worker; u8 rx_unit; }; @@ -408,9 +405,10 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) while (1) { spin_lock_irqsave(&card->lock, flags); - packet = card->packets; + packet = list_first_entry_or_null(&card->packets, + struct if_sdio_packet, list); if (packet) - card->packets = packet->next; + list_del(&packet->list); spin_unlock_irqrestore(&card->lock, flags); if (!packet) @@ -913,7 +911,7 @@ static int if_sdio_host_to_card(struct lbs_private *priv, { int ret; struct if_sdio_card *card; - struct if_sdio_packet *packet, *cur; + struct if_sdio_packet *packet; u16 size; unsigned long flags; @@ -938,7 +936,6 @@ static int if_sdio_host_to_card(struct lbs_private *priv, goto out; } - packet->next = NULL; packet->nb = size; /* @@ -953,14 +950,7 @@ static int if_sdio_host_to_card(struct lbs_private *priv, spin_lock_irqsave(&card->lock, flags); - if (!card->packets) - card->packets = packet; - else { - cur = card->packets; - while (cur->next) - cur = cur->next; - cur->next = packet; - } + list_add_tail(&packet->list, &card->packets); switch (type) { case MVMS_CMD: @@ -985,7 +975,7 @@ out: static int if_sdio_enter_deep_sleep(struct lbs_private *priv) { - int ret = -1; + int ret; struct cmd_header cmd; memset(&cmd, 0, sizeof(cmd)); @@ -1033,10 +1023,19 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv) } -static struct mmc_host *reset_host; - static void if_sdio_reset_card_worker(struct work_struct *work) { + int ret; + const char *name; + struct device *dev; + struct if_sdio_card *card; + struct mmc_host *reset_host; + + card = container_of(work, struct if_sdio_card, reset_worker); + reset_host = card->func->card->host; + name = card->priv->dev->name; + dev = &card->func->dev; + /* * The actual reset operation must be run outside of lbs_thread. This * is because mmc_remove_host() will cause the device to be instantly @@ -1047,21 +1046,19 @@ static void if_sdio_reset_card_worker(struct work_struct *work) * instance for that reason. */ - pr_info("Resetting card..."); + dev_info(dev, "resetting card %s...", name); mmc_remove_host(reset_host); - mmc_add_host(reset_host); + ret = mmc_add_host(reset_host); + if (ret) + dev_err(dev, "%s: can't add mmc host, error %d\n", name, ret); } -static DECLARE_WORK(card_reset_work, if_sdio_reset_card_worker); static void if_sdio_reset_card(struct lbs_private *priv) { struct if_sdio_card *card = priv->card; - if (work_pending(&card_reset_work)) - return; - - reset_host = card->func->card->host; - schedule_work(&card_reset_work); + if (!work_pending(&card->reset_worker)) + schedule_work(&card->reset_worker); } static int if_sdio_power_save(struct lbs_private *priv) @@ -1141,7 +1138,7 @@ static int if_sdio_probe(struct sdio_func *func, struct lbs_private *priv; int ret, i; unsigned int model; - struct if_sdio_packet *packet; + struct if_sdio_packet *packet, *tmp; for (i = 0;i < func->card->num_info;i++) { if (sscanf(func->card->info[i], @@ -1182,7 +1179,16 @@ static int if_sdio_probe(struct sdio_func *func, } spin_lock_init(&card->lock); - card->workqueue = alloc_workqueue("libertas_sdio", WQ_MEM_RECLAIM, 0); + INIT_LIST_HEAD(&card->packets); + + card->workqueue = alloc_workqueue("libertas_sdio", + WQ_MEM_RECLAIM | WQ_UNBOUND, 0); + if (unlikely(!card->workqueue)) { + ret = -ENOMEM; + goto err_queue; + } + + INIT_WORK(&card->reset_worker, if_sdio_reset_card_worker); INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); init_waitqueue_head(&card->pwron_waitq); @@ -1233,12 +1239,12 @@ err_activate_card: flush_workqueue(card->workqueue); lbs_remove_card(priv); free: + cancel_work_sync(&card->packet_worker); + cancel_work_sync(&card->reset_worker); destroy_workqueue(card->workqueue); - while (card->packets) { - packet = card->packets; - card->packets = card->packets->next; +err_queue: + list_for_each_entry_safe(packet, tmp, &card->packets, list) kfree(packet); - } kfree(card); @@ -1248,7 +1254,7 @@ free: static void if_sdio_remove(struct sdio_func *func) { struct if_sdio_card *card; - struct if_sdio_packet *packet; + struct if_sdio_packet *packet, *tmp; card = sdio_get_drvdata(func); @@ -1276,13 +1282,12 @@ static void if_sdio_remove(struct sdio_func *func) lbs_stop_card(card->priv); lbs_remove_card(card->priv); + cancel_work_sync(&card->packet_worker); + cancel_work_sync(&card->reset_worker); destroy_workqueue(card->workqueue); - while (card->packets) { - packet = card->packets; - card->packets = card->packets->next; + list_for_each_entry_safe(packet, tmp, &card->packets, list) kfree(packet); - } kfree(card); } @@ -1402,8 +1407,6 @@ static void __exit if_sdio_exit_module(void) /* Set the flag as user is removing this module. */ user_rmmod = 1; - cancel_work_sync(&card_reset_work); - sdio_unregister_driver(&if_sdio_driver); } |
