From 4552f0cbd45225f2c1cbadc224505f14f8749569 Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Thu, 12 Apr 2007 16:59:12 +1000 Subject: tifm: hide details of interrupt processing from socket drivers Instead of passing transformed value of adapter interrupt status to socket drivers, implement two separate callbacks - one for card events and another for dma events. Signed-off-by: Alex Dubov Signed-off-by: Pierre Ossman --- drivers/misc/tifm_7xx1.c | 22 ++++++++++++++-------- drivers/misc/tifm_core.c | 11 ++++++----- 2 files changed, 20 insertions(+), 13 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index bc60e2f..d6652b3 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -14,7 +14,13 @@ #include #define DRIVER_NAME "tifm_7xx1" -#define DRIVER_VERSION "0.7" +#define DRIVER_VERSION "0.8" + +#define TIFM_IRQ_ENABLE 0x80000000 +#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 static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) { @@ -31,7 +37,7 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) struct tifm_adapter *fm = dev_id; struct tifm_dev *sock; unsigned int irq_status; - unsigned int sock_irq_status, cnt; + unsigned int cnt; spin_lock(&fm->lock); irq_status = readl(fm->addr + FM_INTERRUPT_STATUS); @@ -45,12 +51,12 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) for (cnt = 0; cnt < fm->num_sockets; cnt++) { sock = fm->sockets[cnt]; - sock_irq_status = (irq_status >> cnt) - & (TIFM_IRQ_FIFOMASK(1) - | TIFM_IRQ_CARDMASK(1)); - - if (sock && sock_irq_status) - sock->signal_irq(sock, sock_irq_status); + if (sock) { + if ((irq_status >> cnt) & TIFM_IRQ_FIFOMASK(1)) + sock->data_event(sock); + if ((irq_status >> cnt) & TIFM_IRQ_CARDMASK(1)) + sock->card_event(sock); + } } fm->socket_change_set |= irq_status diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index 6b10ebe..6799b9c 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -14,7 +14,7 @@ #include #define DRIVER_NAME "tifm_core" -#define DRIVER_VERSION "0.7" +#define DRIVER_VERSION "0.8" static DEFINE_IDR(tifm_adapter_idr); static DEFINE_SPINLOCK(tifm_adapter_lock); @@ -175,8 +175,7 @@ void tifm_free_device(struct device *dev) } EXPORT_SYMBOL(tifm_free_device); -static void tifm_dummy_signal_irq(struct tifm_dev *sock, - unsigned int sock_irq_status) +static void tifm_dummy_event(struct tifm_dev *sock) { return; } @@ -191,7 +190,8 @@ struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm) dev->dev.parent = fm->dev; dev->dev.bus = &tifm_bus_type; dev->dev.release = tifm_free_device; - dev->signal_irq = tifm_dummy_signal_irq; + dev->card_event = tifm_dummy_event; + dev->data_event = tifm_dummy_event; } return dev; } @@ -249,7 +249,8 @@ static int tifm_device_remove(struct device *dev) struct tifm_driver *drv = fm_dev->drv; if (drv) { - fm_dev->signal_irq = tifm_dummy_signal_irq; + fm_dev->card_event = tifm_dummy_event; + fm_dev->data_event = tifm_dummy_event; if (drv->remove) drv->remove(fm_dev); fm_dev->drv = NULL; -- cgit v1.1 From 8dc4a61eca31dd45a9d45f9bc9c67d959f0f6cbd Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Thu, 12 Apr 2007 16:59:13 +1000 Subject: tifm: use bus methods to handle probe/remove instead of driver ones. Signed-off-by: Alex Dubov Signed-off-by: Pierre Ossman --- drivers/misc/tifm_core.c | 102 ++++++++++++++++++++++------------------------- 1 file changed, 47 insertions(+), 55 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index 6799b9c..dcff45a 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -60,14 +60,54 @@ static int tifm_uevent(struct device *dev, char **envp, int num_envp, return 0; } +static int tifm_device_probe(struct device *dev) +{ + struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); + struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver, + driver); + int rc = -ENODEV; + + get_device(dev); + if (dev->driver && drv->probe) { + rc = drv->probe(sock); + if (!rc) + return 0; + } + put_device(dev); + return rc; +} + +static void tifm_dummy_event(struct tifm_dev *sock) +{ + return; +} + +static int tifm_device_remove(struct device *dev) +{ + struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); + struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver, + driver); + + if (dev->driver && drv->remove) { + sock->card_event = tifm_dummy_event; + sock->data_event = tifm_dummy_event; + drv->remove(sock); + sock->dev.driver = NULL; + } + + put_device(dev); + return 0; +} + #ifdef CONFIG_PM static int tifm_device_suspend(struct device *dev, pm_message_t state) { struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); - struct tifm_driver *drv = fm_dev->drv; + struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver, + driver); - if (drv && drv->suspend) + if (dev->driver && drv->suspend) return drv->suspend(fm_dev, state); return 0; } @@ -75,9 +115,10 @@ static int tifm_device_suspend(struct device *dev, pm_message_t state) static int tifm_device_resume(struct device *dev) { struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); - struct tifm_driver *drv = fm_dev->drv; + struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver, + driver); - if (drv && drv->resume) + if (dev->driver && drv->resume) return drv->resume(fm_dev); return 0; } @@ -93,6 +134,8 @@ static struct bus_type tifm_bus_type = { .name = "tifm", .match = tifm_match, .uevent = tifm_uevent, + .probe = tifm_device_probe, + .remove = tifm_device_remove, .suspend = tifm_device_suspend, .resume = tifm_device_resume }; @@ -175,11 +218,6 @@ void tifm_free_device(struct device *dev) } EXPORT_SYMBOL(tifm_free_device); -static void tifm_dummy_event(struct tifm_dev *sock) -{ - return; -} - struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm) { struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL); @@ -218,55 +256,9 @@ void tifm_unmap_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents, } EXPORT_SYMBOL(tifm_unmap_sg); -static int tifm_device_probe(struct device *dev) -{ - struct tifm_driver *drv; - struct tifm_dev *fm_dev; - int rc = 0; - const tifm_media_id *id; - - drv = container_of(dev->driver, struct tifm_driver, driver); - fm_dev = container_of(dev, struct tifm_dev, dev); - get_device(dev); - if (!fm_dev->drv && drv->probe && drv->id_table) { - rc = -ENODEV; - id = tifm_device_match(drv->id_table, fm_dev); - if (id) - rc = drv->probe(fm_dev); - if (rc >= 0) { - rc = 0; - fm_dev->drv = drv; - } - } - if (rc) - put_device(dev); - return rc; -} - -static int tifm_device_remove(struct device *dev) -{ - struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); - struct tifm_driver *drv = fm_dev->drv; - - if (drv) { - fm_dev->card_event = tifm_dummy_event; - fm_dev->data_event = tifm_dummy_event; - if (drv->remove) - drv->remove(fm_dev); - fm_dev->drv = NULL; - } - - put_device(dev); - return 0; -} - int tifm_register_driver(struct tifm_driver *drv) { drv->driver.bus = &tifm_bus_type; - drv->driver.probe = tifm_device_probe; - drv->driver.remove = tifm_device_remove; - drv->driver.suspend = tifm_device_suspend; - drv->driver.resume = tifm_device_resume; return driver_register(&drv->driver); } -- cgit v1.1 From e23f2b8a1a52c00f0150659eb0bfde3a73976ffe Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Thu, 12 Apr 2007 16:59:14 +1000 Subject: tifm: simplify bus match and uevent handlers Remove code duplicating the kernel functionality and clean up data structures involved in driver matching. Signed-off-by: Alex Dubov Signed-off-by: Pierre Ossman --- drivers/misc/tifm_7xx1.c | 14 ++++++------ drivers/misc/tifm_core.c | 57 +++++++++++++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 30 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index d6652b3..fd7b8da 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -73,7 +73,7 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, +static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, int is_x2) { unsigned int s_state; @@ -90,7 +90,7 @@ static tifm_media_id tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, s_state = readl(sock_addr + SOCK_PRESENT_STATE); if (!(TIFM_SOCK_STATE_OCCUPIED & s_state)) - return FM_NULL; + return 0; if (is_x2) { writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL); @@ -129,7 +129,7 @@ static int tifm_7xx1_switch_media(void *data) { struct tifm_adapter *fm = data; unsigned long flags; - tifm_media_id media_id; + unsigned char media_id; char *card_name = "xx"; int cnt, rc; struct tifm_dev *sock; @@ -184,7 +184,7 @@ static int tifm_7xx1_switch_media(void *data) if (sock) { sock->addr = tifm_7xx1_sock_addr(fm->addr, cnt); - sock->media_id = media_id; + sock->type = media_id; sock->socket_id = cnt; switch (media_id) { case 1: @@ -266,7 +266,7 @@ static int tifm_7xx1_resume(struct pci_dev *dev) struct tifm_adapter *fm = pci_get_drvdata(dev); int cnt, rc; unsigned long flags; - tifm_media_id new_ids[fm->num_sockets]; + unsigned char new_ids[fm->num_sockets]; pci_set_power_state(dev, PCI_D0); pci_restore_state(dev); @@ -285,10 +285,10 @@ static int tifm_7xx1_resume(struct pci_dev *dev) fm->socket_change_set = 0; for (cnt = 0; cnt < fm->num_sockets; cnt++) { if (fm->sockets[cnt]) { - if (fm->sockets[cnt]->media_id == new_ids[cnt]) + if (fm->sockets[cnt]->type == new_ids[cnt]) fm->socket_change_set |= 1 << cnt; - fm->sockets[cnt]->media_id = new_ids[cnt]; + fm->sockets[cnt]->type = new_ids[cnt]; } } diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index dcff45a..6b2c447 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -19,42 +19,53 @@ static DEFINE_IDR(tifm_adapter_idr); static DEFINE_SPINLOCK(tifm_adapter_lock); -static tifm_media_id *tifm_device_match(tifm_media_id *ids, - struct tifm_dev *dev) +static const char *tifm_media_type_name(unsigned char type, unsigned char nt) { - while (*ids) { - if (dev->media_id == *ids) - return ids; - ids++; - } - return NULL; + const char *card_type_name[3][3] = { + { "SmartMedia/xD", "MemoryStick", "MMC/SD" }, + { "XD", "MS", "SD"}, + { "xd", "ms", "sd"} + }; + + if (nt > 2 || type < 1 || type > 3) + return NULL; + return card_type_name[nt][type - 1]; } -static int tifm_match(struct device *dev, struct device_driver *drv) +static int tifm_dev_match(struct tifm_dev *sock, struct tifm_device_id *id) { - struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); - struct tifm_driver *fm_drv; - - fm_drv = container_of(drv, struct tifm_driver, driver); - if (!fm_drv->id_table) - return -EINVAL; - if (tifm_device_match(fm_drv->id_table, fm_dev)) + if (sock->type == id->type) return 1; - return -ENODEV; + return 0; +} + +static int tifm_bus_match(struct device *dev, struct device_driver *drv) +{ + struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); + struct tifm_driver *fm_drv = container_of(drv, struct tifm_driver, + driver); + struct tifm_device_id *ids = fm_drv->id_table; + + if (ids) { + while (ids->type) { + if (tifm_dev_match(sock, ids)) + return 1; + ++ids; + } + } + return 0; } static int tifm_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size) { - struct tifm_dev *fm_dev; + struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); int i = 0; int length = 0; - const char *card_type_name[] = {"INV", "SM", "MS", "SD"}; - if (!dev || !(fm_dev = container_of(dev, struct tifm_dev, dev))) - return -ENODEV; if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &length, - "TIFM_CARD_TYPE=%s", card_type_name[fm_dev->media_id])) + "TIFM_CARD_TYPE=%s", + tifm_media_type_name(sock->type, 1))) return -ENOMEM; return 0; @@ -132,7 +143,7 @@ static int tifm_device_resume(struct device *dev) static struct bus_type tifm_bus_type = { .name = "tifm", - .match = tifm_match, + .match = tifm_bus_match, .uevent = tifm_uevent, .probe = tifm_device_probe, .remove = tifm_device_remove, -- cgit v1.1 From 3540af8ffddcdbc7573451ac0b5cd57a2eaf8af5 Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Thu, 12 Apr 2007 16:59:15 +1000 Subject: tifm: replace per-adapter kthread with freezeable workqueue Freezeable workqueue makes sure that adapter work items (device insertions and removals) would be handled after the system is fully resumed. Previously this was achieved by explicit freezing of the kthread. Signed-off-by: Alex Dubov Signed-off-by: Pierre Ossman --- drivers/misc/tifm_7xx1.c | 89 ++++++++++++++++++------------------------------ drivers/misc/tifm_core.c | 51 ++++++++++++++++++--------- 2 files changed, 68 insertions(+), 72 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index fd7b8da..e5655fe 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -28,7 +28,7 @@ static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) spin_lock_irqsave(&fm->lock, flags); fm->socket_change_set |= 1 << sock->socket_id; - wake_up_all(&fm->change_set_notify); + tifm_queue_work(&fm->media_switcher); spin_unlock_irqrestore(&fm->lock, flags); } @@ -64,10 +64,12 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) } writel(irq_status, fm->addr + FM_INTERRUPT_STATUS); - if (!fm->socket_change_set) + if (fm->finish_me) + complete_all(fm->finish_me); + else if (!fm->socket_change_set) writel(TIFM_IRQ_ENABLE, fm->addr + FM_SET_INTERRUPT_ENABLE); else - wake_up_all(&fm->change_set_notify); + tifm_queue_work(&fm->media_switcher); spin_unlock(&fm->lock); return IRQ_HANDLED; @@ -125,37 +127,29 @@ tifm_7xx1_sock_addr(char __iomem *base_addr, unsigned int sock_num) return base_addr + ((sock_num + 1) << 10); } -static int tifm_7xx1_switch_media(void *data) +static void tifm_7xx1_switch_media(struct work_struct *work) { - struct tifm_adapter *fm = data; + struct tifm_adapter *fm = container_of(work, struct tifm_adapter, + media_switcher); unsigned long flags; unsigned char media_id; char *card_name = "xx"; - int cnt, rc; + int cnt; struct tifm_dev *sock; unsigned int socket_change_set; - while (1) { - rc = wait_event_interruptible(fm->change_set_notify, - fm->socket_change_set); - if (rc == -ERESTARTSYS) - try_to_freeze(); - - spin_lock_irqsave(&fm->lock, flags); - socket_change_set = fm->socket_change_set; - fm->socket_change_set = 0; + 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); + dev_dbg(fm->dev, "checking media set %x\n", + socket_change_set); - if (kthread_should_stop()) - socket_change_set = (1 << fm->num_sockets) - 1; + if (!socket_change_set) { spin_unlock_irqrestore(&fm->lock, flags); + return; + } - if (!socket_change_set) - continue; - - spin_lock_irqsave(&fm->lock, flags); for (cnt = 0; cnt < fm->num_sockets; cnt++) { if (!(socket_change_set & (1 << cnt))) continue; @@ -172,8 +166,6 @@ static int tifm_7xx1_switch_media(void *data) tifm_7xx1_sock_addr(fm->addr, cnt) + SOCK_CONTROL); } - if (kthread_should_stop()) - continue; spin_unlock_irqrestore(&fm->lock, flags); media_id = tifm_7xx1_toggle_sock_power( @@ -222,30 +214,16 @@ static int tifm_7xx1_switch_media(void *data) } } - if (!kthread_should_stop()) { - 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); - } 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); - return 0; - } else { - spin_unlock_irqrestore(&fm->lock, flags); - } - } - } - return 0; + 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); } #ifdef CONFIG_PM @@ -267,6 +245,7 @@ static int tifm_7xx1_resume(struct pci_dev *dev) int cnt, rc; unsigned long flags; unsigned char new_ids[fm->num_sockets]; + DECLARE_COMPLETION_ONSTACK(finish_resume); pci_set_power_state(dev, PCI_D0); pci_restore_state(dev); @@ -299,12 +278,14 @@ static int tifm_7xx1_resume(struct pci_dev *dev) return 0; } else { fm->socket_change_set = 0; + fm->finish_me = &finish_resume; spin_unlock_irqrestore(&fm->lock, flags); } - wait_event_timeout(fm->change_set_notify, fm->socket_change_set, HZ); + wait_for_completion_timeout(&finish_resume, HZ); 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); @@ -365,6 +346,7 @@ static int tifm_7xx1_probe(struct pci_dev *dev, if (!fm->sockets) goto err_out_free; + INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media); fm->eject = tifm_7xx1_eject; pci_set_drvdata(dev, fm); @@ -377,15 +359,14 @@ static int tifm_7xx1_probe(struct pci_dev *dev, if (rc) goto err_out_unmap; - init_waitqueue_head(&fm->change_set_notify); - rc = tifm_add_adapter(fm, tifm_7xx1_switch_media); + rc = tifm_add_adapter(fm); if (rc) goto err_out_irq; writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), fm->addr + FM_SET_INTERRUPT_ENABLE); - wake_up_process(fm->media_switcher); + return 0; err_out_irq: @@ -417,8 +398,6 @@ static void tifm_7xx1_remove(struct pci_dev *dev) fm->socket_change_set = (1 << fm->num_sockets) - 1; spin_unlock_irqrestore(&fm->lock, flags); - kthread_stop(fm->media_switcher); - tifm_remove_adapter(fm); pci_set_drvdata(dev, NULL); diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index 6b2c447..ef8a97b8 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -16,6 +16,7 @@ #define DRIVER_NAME "tifm_core" #define DRIVER_VERSION "0.8" +static struct workqueue_struct *workqueue; static DEFINE_IDR(tifm_adapter_idr); static DEFINE_SPINLOCK(tifm_adapter_lock); @@ -184,8 +185,7 @@ void tifm_free_adapter(struct tifm_adapter *fm) } EXPORT_SYMBOL(tifm_free_adapter); -int tifm_add_adapter(struct tifm_adapter *fm, - int (*mediathreadfn)(void *data)) +int tifm_add_adapter(struct tifm_adapter *fm) { int rc; @@ -197,16 +197,13 @@ int tifm_add_adapter(struct tifm_adapter *fm, spin_unlock(&tifm_adapter_lock); if (!rc) { snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id); - fm->media_switcher = kthread_create(mediathreadfn, - fm, "tifm/%u", fm->id); + rc = class_device_add(&fm->cdev); - if (!IS_ERR(fm->media_switcher)) - return class_device_add(&fm->cdev); - - spin_lock(&tifm_adapter_lock); - idr_remove(&tifm_adapter_idr, fm->id); - spin_unlock(&tifm_adapter_lock); - rc = -ENOMEM; + if (rc) { + spin_lock(&tifm_adapter_lock); + idr_remove(&tifm_adapter_idr, fm->id); + spin_unlock(&tifm_adapter_lock); + } } return rc; } @@ -214,6 +211,7 @@ EXPORT_SYMBOL(tifm_add_adapter); void tifm_remove_adapter(struct tifm_adapter *fm) { + flush_workqueue(workqueue); class_device_del(&fm->cdev); spin_lock(&tifm_adapter_lock); @@ -267,6 +265,12 @@ void tifm_unmap_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents, } EXPORT_SYMBOL(tifm_unmap_sg); +void tifm_queue_work(struct work_struct *work) +{ + queue_work(workqueue, work); +} +EXPORT_SYMBOL(tifm_queue_work); + int tifm_register_driver(struct tifm_driver *drv) { drv->driver.bus = &tifm_bus_type; @@ -283,13 +287,25 @@ EXPORT_SYMBOL(tifm_unregister_driver); static int __init tifm_init(void) { - int rc = bus_register(&tifm_bus_type); + int rc; - if (!rc) { - rc = class_register(&tifm_adapter_class); - if (rc) - bus_unregister(&tifm_bus_type); - } + workqueue = create_freezeable_workqueue("tifm"); + if (!workqueue) + return -ENOMEM; + + rc = bus_register(&tifm_bus_type); + + if (rc) + goto err_out_wq; + + rc = class_register(&tifm_adapter_class); + if (!rc) + return 0; + + bus_unregister(&tifm_bus_type); + +err_out_wq: + destroy_workqueue(workqueue); return rc; } @@ -298,6 +314,7 @@ static void __exit tifm_exit(void) { class_unregister(&tifm_adapter_class); bus_unregister(&tifm_bus_type); + destroy_workqueue(workqueue); } subsys_initcall(tifm_init); -- cgit v1.1 From 342c0ec4859446140c0dc5d7d903bb3b3f0577cd Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Thu, 12 Apr 2007 16:59:16 +1000 Subject: tifm_7xx1: improve card detection routine Remove unneeded conditions and change a sleeping regime a little in the card type detection routine. Signed-off-by: Alex Dubov Signed-off-by: Pierre Ossman --- drivers/misc/tifm_7xx1.c | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index e5655fe..3474679 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -75,48 +75,46 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr, - int is_x2) +static unsigned char tifm_7xx1_toggle_sock_power(char __iomem *sock_addr) { unsigned int s_state; int cnt; writel(0x0e00, sock_addr + SOCK_CONTROL); - for (cnt = 0; cnt < 100; cnt++) { + for (cnt = 16; cnt <= 256; cnt <<= 1) { if (!(TIFM_SOCK_STATE_POWERED & readl(sock_addr + SOCK_PRESENT_STATE))) break; - msleep(10); + + msleep(cnt); } s_state = readl(sock_addr + SOCK_PRESENT_STATE); if (!(TIFM_SOCK_STATE_OCCUPIED & s_state)) return 0; - if (is_x2) { - writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL); - } else { - // SmartMedia cards need extra 40 msec - if (((readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7) == 1) - msleep(40); - writel(readl(sock_addr + SOCK_CONTROL) | TIFM_CTRL_LED, - sock_addr + SOCK_CONTROL); - msleep(10); - writel((s_state & 0x7) | 0x0c00 | TIFM_CTRL_LED, - sock_addr + SOCK_CONTROL); - } + writel(readl(sock_addr + SOCK_CONTROL) | TIFM_CTRL_LED, + sock_addr + SOCK_CONTROL); - for (cnt = 0; cnt < 100; cnt++) { + /* xd needs some extra time before power on */ + if (((readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7) + == TIFM_TYPE_XD) + msleep(40); + + writel((s_state & 7) | 0x0c00, sock_addr + SOCK_CONTROL); + /* wait for power to stabilize */ + msleep(20); + for (cnt = 16; cnt <= 256; cnt <<= 1) { if ((TIFM_SOCK_STATE_POWERED & readl(sock_addr + SOCK_PRESENT_STATE))) break; - msleep(10); + + msleep(cnt); } - if (!is_x2) - writel(readl(sock_addr + SOCK_CONTROL) & (~TIFM_CTRL_LED), - sock_addr + SOCK_CONTROL); + writel(readl(sock_addr + SOCK_CONTROL) & (~TIFM_CTRL_LED), + sock_addr + SOCK_CONTROL); return (readl(sock_addr + SOCK_PRESENT_STATE) >> 4) & 7; } @@ -169,8 +167,7 @@ static void tifm_7xx1_switch_media(struct work_struct *work) spin_unlock_irqrestore(&fm->lock, flags); media_id = tifm_7xx1_toggle_sock_power( - tifm_7xx1_sock_addr(fm->addr, cnt), - fm->num_sockets == 2); + tifm_7xx1_sock_addr(fm->addr, cnt)); if (media_id) { sock = tifm_alloc_device(fm); if (sock) { @@ -258,8 +255,7 @@ static int tifm_7xx1_resume(struct pci_dev *dev) for (cnt = 0; cnt < fm->num_sockets; cnt++) new_ids[cnt] = tifm_7xx1_toggle_sock_power( - tifm_7xx1_sock_addr(fm->addr, cnt), - fm->num_sockets == 2); + tifm_7xx1_sock_addr(fm->addr, cnt)); spin_lock_irqsave(&fm->lock, flags); fm->socket_change_set = 0; for (cnt = 0; cnt < fm->num_sockets; cnt++) { -- cgit v1.1 From 6113ed73e61a13db9da48831e1b35788b7f837cc Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Thu, 12 Apr 2007 16:59:17 +1000 Subject: tifm: move common adapter management tasks from tifm_7xx1 to tifm_core Some details of the adapter management (create, add, remove) are really belong to the tifm_core, as they are not hardware specific. Signed-off-by: Alex Dubov Signed-off-by: Pierre Ossman --- drivers/misc/tifm_7xx1.c | 28 ++++++++++---------------- drivers/misc/tifm_core.c | 52 +++++++++++++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 39 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index 3474679..e051f9d 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -22,6 +22,11 @@ #define TIFM_IRQ_FIFOMASK(x) ((x) << 16) #define TIFM_IRQ_SETALL 0xffffffff +static void tifm_7xx1_dummy_eject(struct tifm_adapter *fm, + struct tifm_dev *sock) +{ +} + static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) { unsigned long flags; @@ -140,7 +145,7 @@ static void tifm_7xx1_switch_media(struct work_struct *work) socket_change_set = fm->socket_change_set; fm->socket_change_set = 0; - dev_dbg(fm->dev, "checking media set %x\n", + dev_dbg(fm->cdev.dev, "checking media set %x\n", socket_change_set); if (!socket_change_set) { @@ -328,20 +333,13 @@ static int tifm_7xx1_probe(struct pci_dev *dev, pci_intx(dev, 1); - fm = tifm_alloc_adapter(); + fm = tifm_alloc_adapter(dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM + ? 4 : 2, &dev->dev); if (!fm) { rc = -ENOMEM; goto err_out_int; } - fm->dev = &dev->dev; - fm->num_sockets = (dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM) - ? 4 : 2; - fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->num_sockets, - GFP_KERNEL); - if (!fm->sockets) - goto err_out_free; - INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media); fm->eject = tifm_7xx1_eject; pci_set_drvdata(dev, fm); @@ -351,7 +349,7 @@ static int tifm_7xx1_probe(struct pci_dev *dev, if (!fm->addr) goto err_out_free; - rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm); + rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm); if (rc) goto err_out_unmap; @@ -359,10 +357,8 @@ static int tifm_7xx1_probe(struct pci_dev *dev, if (rc) goto err_out_irq; - writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), fm->addr + FM_SET_INTERRUPT_ENABLE); - return 0; err_out_irq: @@ -384,16 +380,12 @@ err_out: static void tifm_7xx1_remove(struct pci_dev *dev) { struct tifm_adapter *fm = pci_get_drvdata(dev); - unsigned long flags; + fm->eject = tifm_7xx1_dummy_eject; writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); mmiowb(); free_irq(dev->irq, fm); - spin_lock_irqsave(&fm->lock, flags); - fm->socket_change_set = (1 << fm->num_sockets) - 1; - spin_unlock_irqrestore(&fm->lock, flags); - tifm_remove_adapter(fm); pci_set_drvdata(dev, NULL); diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index ef8a97b8..f0cce2a 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -156,7 +156,6 @@ static void tifm_free(struct class_device *cdev) { struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev); - kfree(fm->sockets); kfree(fm); } @@ -165,26 +164,24 @@ static struct class tifm_adapter_class = { .release = tifm_free }; -struct tifm_adapter *tifm_alloc_adapter(void) +struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets, + struct device *dev) { struct tifm_adapter *fm; - fm = kzalloc(sizeof(struct tifm_adapter), GFP_KERNEL); + fm = kzalloc(sizeof(struct tifm_adapter) + + sizeof(struct tifm_dev*) * num_sockets, GFP_KERNEL); if (fm) { fm->cdev.class = &tifm_adapter_class; - spin_lock_init(&fm->lock); + fm->cdev.dev = dev; class_device_initialize(&fm->cdev); + spin_lock_init(&fm->lock); + fm->num_sockets = num_sockets; } return fm; } EXPORT_SYMBOL(tifm_alloc_adapter); -void tifm_free_adapter(struct tifm_adapter *fm) -{ - class_device_put(&fm->cdev); -} -EXPORT_SYMBOL(tifm_free_adapter); - int tifm_add_adapter(struct tifm_adapter *fm) { int rc; @@ -195,31 +192,44 @@ int tifm_add_adapter(struct tifm_adapter *fm) spin_lock(&tifm_adapter_lock); rc = idr_get_new(&tifm_adapter_idr, fm, &fm->id); spin_unlock(&tifm_adapter_lock); - if (!rc) { - snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id); - rc = class_device_add(&fm->cdev); - - if (rc) { - spin_lock(&tifm_adapter_lock); - idr_remove(&tifm_adapter_idr, fm->id); - spin_unlock(&tifm_adapter_lock); - } + if (rc) + return rc; + + snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id); + rc = class_device_add(&fm->cdev); + if (rc) { + spin_lock(&tifm_adapter_lock); + idr_remove(&tifm_adapter_idr, fm->id); + spin_unlock(&tifm_adapter_lock); } + return rc; } EXPORT_SYMBOL(tifm_add_adapter); void tifm_remove_adapter(struct tifm_adapter *fm) { + unsigned int cnt; + flush_workqueue(workqueue); - class_device_del(&fm->cdev); + for (cnt = 0; cnt < fm->num_sockets; ++cnt) { + if (fm->sockets[cnt]) + device_unregister(&fm->sockets[cnt]->dev); + } spin_lock(&tifm_adapter_lock); idr_remove(&tifm_adapter_idr, fm->id); spin_unlock(&tifm_adapter_lock); + class_device_del(&fm->cdev); } EXPORT_SYMBOL(tifm_remove_adapter); +void tifm_free_adapter(struct tifm_adapter *fm) +{ + class_device_put(&fm->cdev); +} +EXPORT_SYMBOL(tifm_free_adapter); + void tifm_free_device(struct device *dev) { struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); @@ -234,7 +244,7 @@ struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm) if (dev) { spin_lock_init(&dev->lock); - dev->dev.parent = fm->dev; + dev->dev.parent = fm->cdev.dev; dev->dev.bus = &tifm_bus_type; dev->dev.release = tifm_free_device; dev->card_event = tifm_dummy_event; -- cgit v1.1 From 2428a8fe2261e901e058d9ea8b6ed7e1b4268b79 Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Thu, 12 Apr 2007 16:59:18 +1000 Subject: tifm: move common device management tasks from tifm_7xx1 to tifm_core Some details of the device management (create, add, remove) are really belong to the tifm_core, as they are not hardware specific. Signed-off-by: Alex Dubov Signed-off-by: Pierre Ossman --- drivers/misc/tifm_7xx1.c | 94 ++++++++++++++++++------------------------------ drivers/misc/tifm_core.c | 39 +++++++++++++------- 2 files changed, 62 insertions(+), 71 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index e051f9d..3563869 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -136,7 +136,6 @@ static void tifm_7xx1_switch_media(struct work_struct *work) media_switcher); unsigned long flags; unsigned char media_id; - char *card_name = "xx"; int cnt; struct tifm_dev *sock; unsigned int socket_change_set; @@ -153,68 +152,45 @@ static void tifm_7xx1_switch_media(struct work_struct *work) return; } - 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 - ": 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); - writel(0x0e00, - tifm_7xx1_sock_addr(fm->addr, cnt) - + SOCK_CONTROL); - } - + for (cnt = 0; cnt < fm->num_sockets; cnt++) { + if (!(socket_change_set & (1 << cnt))) + continue; + sock = fm->sockets[cnt]; + if (sock) { + printk(KERN_INFO + "%s : demand removing card from socket %u:%u\n", + fm->cdev.class_id, fm->id, cnt); + fm->sockets[cnt] = NULL; spin_unlock_irqrestore(&fm->lock, flags); - media_id = tifm_7xx1_toggle_sock_power( - tifm_7xx1_sock_addr(fm->addr, cnt)); - if (media_id) { - sock = tifm_alloc_device(fm); - if (sock) { - sock->addr = tifm_7xx1_sock_addr(fm->addr, - cnt); - sock->type = 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); - } + device_unregister(&sock->dev); + spin_lock_irqsave(&fm->lock, flags); + writel(0x0e00, tifm_7xx1_sock_addr(fm->addr, cnt) + + SOCK_CONTROL); + } + + spin_unlock_irqrestore(&fm->lock, flags); + + media_id = tifm_7xx1_toggle_sock_power( + tifm_7xx1_sock_addr(fm->addr, cnt)); + + // tifm_alloc_device will check if media_id is valid + sock = tifm_alloc_device(fm, cnt, media_id); + if (sock) { + sock->addr = tifm_7xx1_sock_addr(fm->addr, 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); + } writel(TIFM_IRQ_FIFOMASK(socket_change_set) | TIFM_IRQ_CARDMASK(socket_change_set), diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index f0cce2a..1e59198 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -232,25 +232,40 @@ EXPORT_SYMBOL(tifm_free_adapter); void tifm_free_device(struct device *dev) { - struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); - kfree(fm_dev); + struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); + kfree(sock); } EXPORT_SYMBOL(tifm_free_device); -struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm) +struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm, unsigned int id, + unsigned char type) { - struct tifm_dev *dev = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL); + struct tifm_dev *sock = NULL; + + if (!tifm_media_type_name(type, 0)) + return sock; - if (dev) { - spin_lock_init(&dev->lock); + sock = kzalloc(sizeof(struct tifm_dev), GFP_KERNEL); + if (sock) { + spin_lock_init(&sock->lock); + sock->type = type; + sock->socket_id = id; + sock->card_event = tifm_dummy_event; + sock->data_event = tifm_dummy_event; - dev->dev.parent = fm->cdev.dev; - dev->dev.bus = &tifm_bus_type; - dev->dev.release = tifm_free_device; - dev->card_event = tifm_dummy_event; - dev->data_event = tifm_dummy_event; + sock->dev.parent = fm->cdev.dev; + sock->dev.bus = &tifm_bus_type; + sock->dev.dma_mask = fm->cdev.dev->dma_mask; + sock->dev.release = tifm_free_device; + + snprintf(sock->dev.bus_id, BUS_ID_SIZE, + "tifm_%s%u:%u", tifm_media_type_name(type, 2), + fm->id, id); + printk(KERN_INFO DRIVER_NAME + ": %s card detected in socket %u:%u\n", + tifm_media_type_name(type, 0), fm->id, id); } - return dev; + return sock; } EXPORT_SYMBOL(tifm_alloc_device); -- cgit v1.1 From 88de1b2fed2bbe9eb1b7310195be84cf143efb4f Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Thu, 12 Apr 2007 16:59:19 +1000 Subject: 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 Signed-off-by: Pierre Ossman --- drivers/misc/tifm_7xx1.c | 58 ++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 27 deletions(-) (limited to 'drivers/misc') 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; } -- cgit v1.1 From 4e64f223857b138e3474bedc967d51db25c414b3 Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Thu, 12 Apr 2007 16:59:20 +1000 Subject: tifm: add sysfs attribute for tifm devices A sysfs attribute reflecting current media type is added. Signed-off-by: Alex Dubov Signed-off-by: Pierre Ossman --- drivers/misc/tifm_core.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index 1e59198..70220be 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -142,14 +142,27 @@ static int tifm_device_resume(struct device *dev) #endif /* CONFIG_PM */ +static ssize_t type_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); + return sprintf(buf, "%x", sock->type); +} + +static struct device_attribute tifm_dev_attrs[] = { + __ATTR(type, S_IRUGO, type_show, NULL), + __ATTR_NULL +}; + static struct bus_type tifm_bus_type = { - .name = "tifm", - .match = tifm_bus_match, - .uevent = tifm_uevent, - .probe = tifm_device_probe, - .remove = tifm_device_remove, - .suspend = tifm_device_suspend, - .resume = tifm_device_resume + .name = "tifm", + .dev_attrs = tifm_dev_attrs, + .match = tifm_bus_match, + .uevent = tifm_uevent, + .probe = tifm_device_probe, + .remove = tifm_device_remove, + .suspend = tifm_device_suspend, + .resume = tifm_device_resume }; static void tifm_free(struct class_device *cdev) -- cgit v1.1 From 91f8d0118a0e1f25f809f3fde5a7616a1eaabc2b Mon Sep 17 00:00:00 2001 From: Alex Dubov Date: Thu, 12 Apr 2007 17:05:26 +1000 Subject: tifm: layout fixes, small changes to comments and printfs Cosmetic changes to the code. Signed-off-by: Alex Dubov Signed-off-by: Pierre Ossman --- drivers/misc/tifm_7xx1.c | 10 +++------- drivers/misc/tifm_core.c | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 19 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index eafa557..9dcff14 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -10,8 +10,6 @@ */ #include -#include -#include #define DRIVER_NAME "tifm_7xx1" #define DRIVER_VERSION "0.8" @@ -41,8 +39,7 @@ static irqreturn_t tifm_7xx1_isr(int irq, void *dev_id) { struct tifm_adapter *fm = dev_id; struct tifm_dev *sock; - unsigned int irq_status; - unsigned int cnt; + unsigned int irq_status, cnt; spin_lock(&fm->lock); irq_status = readl(fm->addr + FM_INTERRUPT_STATUS); @@ -134,11 +131,10 @@ static void tifm_7xx1_switch_media(struct work_struct *work) { struct tifm_adapter *fm = container_of(work, struct tifm_adapter, media_switcher); + struct tifm_dev *sock; unsigned long flags; unsigned char media_id; - int cnt; - struct tifm_dev *sock; - unsigned int socket_change_set; + unsigned int socket_change_set, cnt; spin_lock_irqsave(&fm->lock, flags); socket_change_set = fm->socket_change_set; diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index 70220be..d195fb0 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -115,23 +115,23 @@ static int tifm_device_remove(struct device *dev) static int tifm_device_suspend(struct device *dev, pm_message_t state) { - struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); + struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver, driver); if (dev->driver && drv->suspend) - return drv->suspend(fm_dev, state); + return drv->suspend(sock, state); return 0; } static int tifm_device_resume(struct device *dev) { - struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); + struct tifm_dev *sock = container_of(dev, struct tifm_dev, dev); struct tifm_driver *drv = container_of(dev->driver, struct tifm_driver, driver); if (dev->driver && drv->resume) - return drv->resume(fm_dev); + return drv->resume(sock); return 0; } @@ -155,14 +155,14 @@ static struct device_attribute tifm_dev_attrs[] = { }; static struct bus_type tifm_bus_type = { - .name = "tifm", - .dev_attrs = tifm_dev_attrs, - .match = tifm_bus_match, - .uevent = tifm_uevent, - .probe = tifm_device_probe, - .remove = tifm_device_remove, - .suspend = tifm_device_suspend, - .resume = tifm_device_resume + .name = "tifm", + .dev_attrs = tifm_dev_attrs, + .match = tifm_bus_match, + .uevent = tifm_uevent, + .probe = tifm_device_probe, + .remove = tifm_device_remove, + .suspend = tifm_device_suspend, + .resume = tifm_device_resume }; static void tifm_free(struct class_device *cdev) -- cgit v1.1 From c4030698029bb30d220fb0342a34280c629cee01 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 28 Apr 2007 14:21:10 +0200 Subject: tifm: add missing include for DMA_32BIT_MASK sparc64: drivers/misc/tifm_7xx1.c: In function `tifm_7xx1_probe': drivers/misc/tifm_7xx1.c:294: error: `DMA_32BIT_MASK' undeclared Signed-off-by: Andrew Morton Signed-off-by: Pierre Ossman --- drivers/misc/tifm_7xx1.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/misc') diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index 9dcff14..1ba6c08 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -10,6 +10,7 @@ */ #include +#include #define DRIVER_NAME "tifm_7xx1" #define DRIVER_VERSION "0.8" -- cgit v1.1