Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=88de1b2fed2bbe9eb1b7310195be84cf143efb4f
Commit:     88de1b2fed2bbe9eb1b7310195be84cf143efb4f
Parent:     2428a8fe2261e901e058d9ea8b6ed7e1b4268b79
Author:     Alex Dubov <[EMAIL PROTECTED]>
AuthorDate: Thu Apr 12 16:59:19 2007 +1000
Committer:  Pierre Ossman <[EMAIL PROTECTED]>
CommitDate: Tue May 1 13:04:13 2007 +0200

    tifm_7xx1: fix adapter resume function
    
    Fixes to the adapter resume function to correctly handle all possible cases:
    1. Card is removed during suspend
    2. Card is inserted during suspend into previously empty socket
    3. Card is replaced during suspend by same or different media type card.
    
    Signed-off-by: Alex Dubov <[EMAIL PROTECTED]>
    Signed-off-by: Pierre Ossman <[EMAIL PROTECTED]>
---
 drivers/misc/tifm_7xx1.c |   58 ++++++++++++++++++++++++---------------------
 1 files changed, 31 insertions(+), 27 deletions(-)

diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index 3563869..eafa557 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -220,7 +220,8 @@ static int tifm_7xx1_suspend(struct pci_dev *dev, 
pm_message_t state)
 static int tifm_7xx1_resume(struct pci_dev *dev)
 {
        struct tifm_adapter *fm = pci_get_drvdata(dev);
-       int cnt, rc;
+       int rc;
+       unsigned int good_sockets = 0, bad_sockets = 0;
        unsigned long flags;
        unsigned char new_ids[fm->num_sockets];
        DECLARE_COMPLETION_ONSTACK(finish_resume);
@@ -234,46 +235,49 @@ static int tifm_7xx1_resume(struct pci_dev *dev)
 
        dev_dbg(&dev->dev, "resuming host\n");
 
-       for (cnt = 0; cnt < fm->num_sockets; cnt++)
-               new_ids[cnt] = tifm_7xx1_toggle_sock_power(
-                                       tifm_7xx1_sock_addr(fm->addr, cnt));
+       for (rc = 0; rc < fm->num_sockets; rc++)
+               new_ids[rc] = tifm_7xx1_toggle_sock_power(
+                                       tifm_7xx1_sock_addr(fm->addr, rc));
        spin_lock_irqsave(&fm->lock, flags);
-       fm->socket_change_set = 0;
-       for (cnt = 0; cnt < fm->num_sockets; cnt++) {
-               if (fm->sockets[cnt]) {
-                       if (fm->sockets[cnt]->type == new_ids[cnt])
-                               fm->socket_change_set |= 1 << cnt;
-
-                       fm->sockets[cnt]->type = new_ids[cnt];
+       for (rc = 0; rc < fm->num_sockets; rc++) {
+               if (fm->sockets[rc]) {
+                       if (fm->sockets[rc]->type == new_ids[rc])
+                               good_sockets |= 1 << rc;
+                       else
+                               bad_sockets |= 1 << rc;
                }
        }
 
        writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
               fm->addr + FM_SET_INTERRUPT_ENABLE);
-       if (!fm->socket_change_set) {
-               spin_unlock_irqrestore(&fm->lock, flags);
-               return 0;
-       } else {
-               fm->socket_change_set = 0;
+       dev_dbg(&dev->dev, "change sets on resume: good %x, bad %x\n",
+               good_sockets, bad_sockets);
+
+       fm->socket_change_set = 0;
+       if (good_sockets) {
                fm->finish_me = &finish_resume;
                spin_unlock_irqrestore(&fm->lock, flags);
+               rc = wait_for_completion_timeout(&finish_resume, HZ);
+               dev_dbg(&dev->dev, "wait returned %d\n", rc);
+               writel(TIFM_IRQ_FIFOMASK(good_sockets)
+                      | TIFM_IRQ_CARDMASK(good_sockets),
+                      fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+               writel(TIFM_IRQ_FIFOMASK(good_sockets)
+                      | TIFM_IRQ_CARDMASK(good_sockets),
+                      fm->addr + FM_SET_INTERRUPT_ENABLE);
+               spin_lock_irqsave(&fm->lock, flags);
+               fm->finish_me = NULL;
+               fm->socket_change_set ^= good_sockets & fm->socket_change_set;
        }
 
-       wait_for_completion_timeout(&finish_resume, HZ);
+       fm->socket_change_set |= bad_sockets;
+       if (fm->socket_change_set)
+               tifm_queue_work(&fm->media_switcher);
 
-       spin_lock_irqsave(&fm->lock, flags);
-       fm->finish_me = NULL;
-       writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
-              | TIFM_IRQ_CARDMASK(fm->socket_change_set),
-              fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-       writel(TIFM_IRQ_FIFOMASK(fm->socket_change_set)
-              | TIFM_IRQ_CARDMASK(fm->socket_change_set),
-              fm->addr + FM_SET_INTERRUPT_ENABLE);
+       spin_unlock_irqrestore(&fm->lock, flags);
        writel(TIFM_IRQ_ENABLE,
               fm->addr + FM_SET_INTERRUPT_ENABLE);
-       fm->socket_change_set = 0;
 
-       spin_unlock_irqrestore(&fm->lock, flags);
        return 0;
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to