summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/marvell/libertas/if_sdio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/marvell/libertas/if_sdio.c')
-rw-r--r--drivers/net/wireless/marvell/libertas/if_sdio.c73
1 files changed, 37 insertions, 36 deletions
diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c
index a63c5e622ee3..524034699972 100644
--- a/drivers/net/wireless/marvell/libertas/if_sdio.c
+++ b/drivers/net/wireless/marvell/libertas/if_sdio.c
@@ -101,7 +101,7 @@ 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[] __aligned(4);
};
@@ -119,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;
};
@@ -404,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)
@@ -909,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;
@@ -934,7 +936,6 @@ static int if_sdio_host_to_card(struct lbs_private *priv,
goto out;
}
- packet->next = NULL;
packet->nb = size;
/*
@@ -949,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:
@@ -1029,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
@@ -1043,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)
@@ -1137,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],
@@ -1178,11 +1179,15 @@ static int if_sdio_probe(struct sdio_func *func,
}
spin_lock_init(&card->lock);
+ INIT_LIST_HEAD(&card->packets);
+
card->workqueue = alloc_workqueue("libertas_sdio", WQ_MEM_RECLAIM, 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,13 +1238,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);
err_queue:
- 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);
@@ -1249,7 +1253,7 @@ err_queue:
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);
@@ -1277,13 +1281,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);
}
@@ -1403,8 +1406,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);
}