Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=6412d927313f08808d61b7efba8da43717d4e8d2
Commit:     6412d927313f08808d61b7efba8da43717d4e8d2
Parent:     1499ead31ede528a657c50761c4780c40f929d6d
Author:     Alex Dubov <[EMAIL PROTECTED]>
AuthorDate: Mon Dec 11 01:55:33 2006 +1100
Committer:  Pierre Ossman <[EMAIL PROTECTED]>
CommitDate: Sun Feb 4 20:54:09 2007 +0100

    tifm_7xx1: Merge media insert and media remove functions
    
    Hardware does not say whether card was inserted or removed when reporting
    socket events. Moreover, during suspend, media can be removed or switched
    to some other card type without notification. Therefore, for each socket
    in the change set the following is performed:
    1. If there's active device in the socket it's unregistered
    2. Media detection is performed
    3. If detection recognizes supportable media, new device is registered
    
    This patch also alters some macros and variable names to enhance clarity.
    
    Signed-off-by: Alex Dubov <[EMAIL PROTECTED]>
    Signed-off-by: Pierre Ossman <[EMAIL PROTECTED]>
---
 drivers/misc/tifm_7xx1.c |  254 +++++++++++++++++++++++-----------------------
 include/linux/tifm.h     |   19 ++--
 2 files changed, 134 insertions(+), 139 deletions(-)

diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c
index 24b20a4..5ab81dd 100644
--- a/drivers/misc/tifm_7xx1.c
+++ b/drivers/misc/tifm_7xx1.c
@@ -21,47 +21,12 @@ static void tifm_7xx1_eject(struct tifm_adapter *fm, struct 
tifm_dev *sock)
 
        spin_lock_irqsave(&fm->lock, flags);
        if (!fm->inhibit_new_cards) {
-               fm->remove_mask |= 1 << sock->socket_id;
-               queue_work(fm->wq, &fm->media_remover);
+               fm->socket_change_set |= 1 << sock->socket_id;
+               queue_work(fm->wq, &fm->media_switcher);
        }
        spin_unlock_irqrestore(&fm->lock, flags);
 }
 
-static void tifm_7xx1_remove_media(struct work_struct *work)
-{
-       struct tifm_adapter *fm =
-               container_of(work, struct tifm_adapter, media_remover);
-       unsigned long flags;
-       int cnt;
-       struct tifm_dev *sock;
-
-       if (!class_device_get(&fm->cdev))
-               return;
-       spin_lock_irqsave(&fm->lock, flags);
-       for (cnt = 0; cnt < fm->max_sockets; cnt++) {
-               if (fm->sockets[cnt] && (fm->remove_mask & (1 << cnt))) {
-                       printk(KERN_INFO DRIVER_NAME
-                              ": demand removing card from socket %d\n", cnt);
-                       sock = fm->sockets[cnt];
-                       fm->sockets[cnt] = NULL;
-                       fm->remove_mask &= ~(1 << cnt);
-
-                       writel(0x0e00, sock->addr + SOCK_CONTROL);
-
-                       writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
-                               fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-                       writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
-                               fm->addr + FM_SET_INTERRUPT_ENABLE);
-
-                       spin_unlock_irqrestore(&fm->lock, flags);
-                       device_unregister(&sock->dev);
-                       spin_lock_irqsave(&fm->lock, flags);
-               }
-       }
-       spin_unlock_irqrestore(&fm->lock, flags);
-       class_device_put(&fm->cdev);
-}
-
 static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
 {
        struct tifm_adapter *fm = dev_id;
@@ -79,32 +44,27 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id)
        if (irq_status & TIFM_IRQ_ENABLE) {
                writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
 
-               for (cnt = 0; cnt <  fm->max_sockets; cnt++) {
+               for (cnt = 0; cnt <  fm->num_sockets; cnt++) {
                        sock = fm->sockets[cnt];
-                       sock_irq_status = (irq_status >> cnt) &
-                                       (TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK);
-
-                       if (sock) {
-                               if (sock_irq_status)
-                                       sock->signal_irq(sock, sock_irq_status);
+                       sock_irq_status = (irq_status >> cnt)
+                                         & (TIFM_IRQ_FIFOMASK(1)
+                                            | TIFM_IRQ_CARDMASK(1));
 
-                               if (irq_status & (1 << cnt))
-                                       fm->remove_mask |= 1 << cnt;
-                       } else {
-                               if (irq_status & (1 << cnt))
-                                       fm->insert_mask |= 1 << cnt;
-                       }
+                       if (sock && sock_irq_status)
+                               sock->signal_irq(sock, sock_irq_status);
                }
+
+                fm->socket_change_set |= irq_status
+                                         & ((1 << fm->num_sockets) - 1);
        }
        writel(irq_status, fm->addr + FM_INTERRUPT_STATUS);
 
        if (!fm->inhibit_new_cards) {
-               if (!fm->remove_mask && !fm->insert_mask) {
+               if (!fm->socket_change_set) {
                        writel(TIFM_IRQ_ENABLE,
                                fm->addr + FM_SET_INTERRUPT_ENABLE);
                } else {
-                       queue_work(fm->wq, &fm->media_remover);
-                       queue_work(fm->wq, &fm->media_inserter);
+                       queue_work(fm->wq, &fm->media_switcher);
                }
        }
 
@@ -163,84 +123,125 @@ tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned 
int sock_num)
        return base_addr + ((sock_num + 1) << 10);
 }
 
-static void tifm_7xx1_insert_media(struct work_struct *work)
+static void tifm_7xx1_switch_media(struct work_struct *work)
 {
        struct tifm_adapter *fm =
-               container_of(work, struct tifm_adapter, media_inserter);
+               container_of(work, struct tifm_adapter, media_switcher);
        unsigned long flags;
        tifm_media_id media_id;
        char *card_name = "xx";
-       int cnt, ok_to_register;
-       unsigned int insert_mask;
-       struct tifm_dev *new_sock = NULL;
+       int cnt;
+       struct tifm_dev *sock;
+       unsigned int socket_change_set;
 
        if (!class_device_get(&fm->cdev))
                return;
-       spin_lock_irqsave(&fm->lock, flags);
-       insert_mask = fm->insert_mask;
-       fm->insert_mask = 0;
-       if (fm->inhibit_new_cards) {
+
+       while (1) {
+               spin_lock_irqsave(&fm->lock, flags);
+               socket_change_set = fm->socket_change_set;
+               fm->socket_change_set = 0;
+
+               dev_dbg(fm->dev, "checking media set %x\n",
+                       socket_change_set);
+
+               if (fm->inhibit_new_cards)
+                       socket_change_set = (1 << fm->num_sockets) - 1;
                spin_unlock_irqrestore(&fm->lock, flags);
-               class_device_put(&fm->cdev);
-               return;
-       }
-       spin_unlock_irqrestore(&fm->lock, flags);
 
-       for (cnt = 0; cnt < fm->max_sockets; cnt++) {
-               if (!(insert_mask & (1 << cnt)))
-                       continue;
-
-               media_id = 
tifm_7xx1_toggle_sock_power(tifm_7xx1_sock_addr(fm->addr, cnt),
-                                                      fm->max_sockets == 2);
-               if (media_id) {
-                       ok_to_register = 0;
-                       new_sock = tifm_alloc_device(fm);
-                       if (new_sock) {
-                               new_sock->addr = tifm_7xx1_sock_addr(fm->addr,
-                                                                       cnt);
-                               new_sock->media_id = media_id;
-                               new_sock->socket_id = cnt;
-                               switch (media_id) {
-                               case 1:
-                                       card_name = "xd";
-                                       break;
-                               case 2:
-                                       card_name = "ms";
-                                       break;
-                               case 3:
-                                       card_name = "sd";
-                                       break;
-                               default:
-                                       break;
-                               }
-                               snprintf(new_sock->dev.bus_id, BUS_ID_SIZE,
-                                       "tifm_%s%u:%u", card_name, fm->id, cnt);
+               if (!socket_change_set)
+                       break;
+
+               spin_lock_irqsave(&fm->lock, flags);
+               for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+                       if (!(socket_change_set & (1 << cnt)))
+                               continue;
+                       sock = fm->sockets[cnt];
+                       if (sock) {
                                printk(KERN_INFO DRIVER_NAME
-                                       ": %s card detected in socket %d\n",
-                                       card_name, cnt);
+                                      ": demand removing card from socket 
%d\n",
+                                      cnt);
+                               fm->sockets[cnt] = NULL;
+                               spin_unlock_irqrestore(&fm->lock, flags);
+                               device_unregister(&sock->dev);
                                spin_lock_irqsave(&fm->lock, flags);
-                               if (!fm->sockets[cnt]) {
-                                       fm->sockets[cnt] = new_sock;
-                                       ok_to_register = 1;
+                               writel(0x0e00,
+                                      tifm_7xx1_sock_addr(fm->addr, cnt)
+                                      + SOCK_CONTROL);
+                       }
+                       if (fm->inhibit_new_cards)
+                               continue;
+
+                       spin_unlock_irqrestore(&fm->lock, flags);
+                       media_id = tifm_7xx1_toggle_sock_power(
+                                       tifm_7xx1_sock_addr(fm->addr, cnt),
+                                       fm->num_sockets == 2);
+                       if (media_id) {
+                               sock = tifm_alloc_device(fm);
+                               if (sock) {
+                                       sock->addr = 
tifm_7xx1_sock_addr(fm->addr,
+                                                                       cnt);
+                                       sock->media_id = media_id;
+                                       sock->socket_id = cnt;
+                                       switch (media_id) {
+                                       case 1:
+                                               card_name = "xd";
+                                               break;
+                                       case 2:
+                                               card_name = "ms";
+                                               break;
+                                       case 3:
+                                               card_name = "sd";
+                                               break;
+                                       default:
+                                               tifm_free_device(&sock->dev);
+                                               spin_lock_irqsave(&fm->lock, 
flags);
+                                               continue;
+                                       }
+                                       snprintf(sock->dev.bus_id, BUS_ID_SIZE,
+                                               "tifm_%s%u:%u", card_name, 
fm->id, cnt);
+                                       printk(KERN_INFO DRIVER_NAME
+                                               ": %s card detected in socket 
%d\n",
+                                               card_name, cnt);
+                                       if (!device_register(&sock->dev)) {
+                                               spin_lock_irqsave(&fm->lock, 
flags);
+                                               if (!fm->sockets[cnt]) {
+                                                       fm->sockets[cnt] = sock;
+                                                       sock = NULL;
+                                               }
+                                               
spin_unlock_irqrestore(&fm->lock, flags);
+                                       }
+                                       if (sock)
+                                               tifm_free_device(&sock->dev);
                                }
+                               spin_lock_irqsave(&fm->lock, flags);
+                       }
+               }
+
+               if (!fm->inhibit_new_cards) {
+                       writel(TIFM_IRQ_FIFOMASK(socket_change_set)
+                              | TIFM_IRQ_CARDMASK(socket_change_set),
+                              fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
+                       writel(TIFM_IRQ_FIFOMASK(socket_change_set)
+                              | TIFM_IRQ_CARDMASK(socket_change_set),
+                              fm->addr + FM_SET_INTERRUPT_ENABLE);
+                       writel(TIFM_IRQ_ENABLE,
+                              fm->addr + FM_SET_INTERRUPT_ENABLE);
+                       spin_unlock_irqrestore(&fm->lock, flags);
+                       break;
+               } else {
+                       for (cnt = 0; cnt < fm->num_sockets; cnt++) {
+                               if (fm->sockets[cnt])
+                                       fm->socket_change_set |= 1 << cnt;
+                       }
+                       if (!fm->socket_change_set) {
+                               spin_unlock_irqrestore(&fm->lock, flags);
+                               break;
+                       } else {
                                spin_unlock_irqrestore(&fm->lock, flags);
-                               if (!ok_to_register ||
-                                           device_register(&new_sock->dev)) {
-                                       spin_lock_irqsave(&fm->lock, flags);
-                                       fm->sockets[cnt] = NULL;
-                                       spin_unlock_irqrestore(&fm->lock,
-                                                               flags);
-                                       tifm_free_device(&new_sock->dev);
-                               }
                        }
                }
-               writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
-                      fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-               writel((TIFM_IRQ_FIFOMASK | TIFM_IRQ_CARDMASK) << cnt,
-                      fm->addr + FM_SET_INTERRUPT_ENABLE);
        }
-
-       writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE);
        class_device_put(&fm->cdev);
 }
 
@@ -251,13 +252,12 @@ static int tifm_7xx1_suspend(struct pci_dev *dev, 
pm_message_t state)
 
        spin_lock_irqsave(&fm->lock, flags);
        fm->inhibit_new_cards = 1;
-       fm->remove_mask = 0xf;
-       fm->insert_mask = 0;
+       fm->socket_change_set = 0xf;
        writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
        spin_unlock_irqrestore(&fm->lock, flags);
        flush_workqueue(fm->wq);
 
-       tifm_7xx1_remove_media(&fm->media_remover);
+       tifm_7xx1_switch_media(&fm->media_switcher);
 
        pci_set_power_state(dev, PCI_D3hot);
         pci_disable_device(dev);
@@ -279,9 +279,9 @@ static int tifm_7xx1_resume(struct pci_dev *dev)
        fm->inhibit_new_cards = 0;
        writel(TIFM_IRQ_SETALL, fm->addr + FM_INTERRUPT_STATUS);
        writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-       writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK,
+       writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
                fm->addr + FM_SET_INTERRUPT_ENABLE);
-       fm->insert_mask = 0xf;
+       fm->socket_change_set = 0xf;
        spin_unlock_irqrestore(&fm->lock, flags);
        return 0;
 }
@@ -318,14 +318,13 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
        }
 
        fm->dev = &dev->dev;
-       fm->max_sockets = (dev->device == 0x803B) ? 2 : 4;
-       fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->max_sockets,
+       fm->num_sockets = (dev->device == 0x803B) ? 2 : 4;
+       fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->num_sockets,
                                GFP_KERNEL);
        if (!fm->sockets)
                goto err_out_free;
 
-       INIT_WORK(&fm->media_inserter, tifm_7xx1_insert_media);
-       INIT_WORK(&fm->media_remover, tifm_7xx1_remove_media);
+       INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media);
        fm->eject = tifm_7xx1_eject;
        pci_set_drvdata(dev, fm);
 
@@ -343,10 +342,10 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
                goto err_out_irq;
 
        writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
-       writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SETALLSOCK,
+       writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
                fm->addr + FM_SET_INTERRUPT_ENABLE);
 
-       fm->insert_mask = 0xf;
+       fm->socket_change_set = 0xf;
 
        return 0;
 
@@ -373,14 +372,13 @@ static void tifm_7xx1_remove(struct pci_dev *dev)
 
        spin_lock_irqsave(&fm->lock, flags);
        fm->inhibit_new_cards = 1;
-       fm->remove_mask = 0xf;
-       fm->insert_mask = 0;
+       fm->socket_change_set = 0xf;
        writel(TIFM_IRQ_ENABLE, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
        spin_unlock_irqrestore(&fm->lock, flags);
 
        flush_workqueue(fm->wq);
 
-       tifm_7xx1_remove_media(&fm->media_remover);
+       tifm_7xx1_switch_media(&fm->media_switcher);
 
        writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
        free_irq(dev->irq, fm);
diff --git a/include/linux/tifm.h b/include/linux/tifm.h
index 5b0baef..eaf9e1f 100644
--- a/include/linux/tifm.h
+++ b/include/linux/tifm.h
@@ -62,11 +62,10 @@ enum {
 
 
 #define TIFM_IRQ_ENABLE           0x80000000
-#define TIFM_IRQ_SOCKMASK         0x00000001
-#define TIFM_IRQ_CARDMASK         0x00000100
-#define TIFM_IRQ_FIFOMASK         0x00010000
+#define TIFM_IRQ_SOCKMASK(x)      (x)
+#define TIFM_IRQ_CARDMASK(x)      ((x) << 8)
+#define TIFM_IRQ_FIFOMASK(x)      ((x) << 16)
 #define TIFM_IRQ_SETALL           0xffffffff
-#define TIFM_IRQ_SETALLSOCK       0x0000000f
 
 #define TIFM_CTRL_LED             0x00000040
 #define TIFM_CTRL_FAST_CLK        0x00000100
@@ -108,18 +107,16 @@ struct tifm_driver {
 
 struct tifm_adapter {
        char __iomem            *addr;
-       unsigned int            irq_status;
-       unsigned int            insert_mask;
-       unsigned int            remove_mask;
        spinlock_t              lock;
+       unsigned int            irq_status;
+       unsigned int            socket_change_set;
        unsigned int            id;
-       unsigned int            max_sockets;
+       unsigned int            num_sockets;
+       struct tifm_dev         **sockets;
        char                    wq_name[KOBJ_NAME_LEN];
        unsigned int            inhibit_new_cards;
        struct workqueue_struct *wq;
-       struct work_struct      media_inserter;
-       struct work_struct      media_remover;
-       struct tifm_dev         **sockets;
+       struct work_struct      media_switcher;
        struct class_device     cdev;
        struct device           *dev;
 
-
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