diff options
author | Stephan Gatzka <stephan@gatzka.org> | 2011-07-25 16:16:24 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2011-09-16 16:30:28 -0400 |
commit | 2d7a36e23300d268599f6eae4093643d22fbb356 (patch) | |
tree | 8ab2e18f979af804a4f069ac77cbbd34801c5e88 /drivers/firewire/ohci.c | |
parent | 32ce38f40337cf4a805552e494354d961587c838 (diff) |
firewire: ohci: Move code from the bus reset tasklet into a workqueue
Code inside bus_reset_work may now sleep. This is a prerequisite to
support a phy from Texas Instruments cleanly. The patch to support this
phy will be submitted later.
Signed-off-by: Stephan Gatzka <stephan@gatzka.org>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/ohci.c')
-rw-r--r-- | drivers/firewire/ohci.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index fd7170a9ad2c..c026f46fc157 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/string.h> | 42 | #include <linux/string.h> |
43 | #include <linux/time.h> | 43 | #include <linux/time.h> |
44 | #include <linux/vmalloc.h> | 44 | #include <linux/vmalloc.h> |
45 | #include <linux/workqueue.h> | ||
45 | 46 | ||
46 | #include <asm/byteorder.h> | 47 | #include <asm/byteorder.h> |
47 | #include <asm/page.h> | 48 | #include <asm/page.h> |
@@ -226,7 +227,7 @@ struct fw_ohci { | |||
226 | 227 | ||
227 | __le32 *self_id_cpu; | 228 | __le32 *self_id_cpu; |
228 | dma_addr_t self_id_bus; | 229 | dma_addr_t self_id_bus; |
229 | struct tasklet_struct bus_reset_tasklet; | 230 | struct work_struct bus_reset_work; |
230 | 231 | ||
231 | u32 self_id_buffer[512]; | 232 | u32 self_id_buffer[512]; |
232 | }; | 233 | }; |
@@ -859,7 +860,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) | |||
859 | * | 860 | * |
860 | * Alas some chips sometimes emit bus reset packets with a | 861 | * Alas some chips sometimes emit bus reset packets with a |
861 | * wrong generation. We set the correct generation for these | 862 | * wrong generation. We set the correct generation for these |
862 | * at a slightly incorrect time (in bus_reset_tasklet). | 863 | * at a slightly incorrect time (in bus_reset_work). |
863 | */ | 864 | */ |
864 | if (evt == OHCI1394_evt_bus_reset) { | 865 | if (evt == OHCI1394_evt_bus_reset) { |
865 | if (!(ohci->quirks & QUIRK_RESET_PACKET)) | 866 | if (!(ohci->quirks & QUIRK_RESET_PACKET)) |
@@ -1713,9 +1714,10 @@ static u32 update_bus_time(struct fw_ohci *ohci) | |||
1713 | return ohci->bus_time | cycle_time_seconds; | 1714 | return ohci->bus_time | cycle_time_seconds; |
1714 | } | 1715 | } |
1715 | 1716 | ||
1716 | static void bus_reset_tasklet(unsigned long data) | 1717 | static void bus_reset_work(struct work_struct *work) |
1717 | { | 1718 | { |
1718 | struct fw_ohci *ohci = (struct fw_ohci *)data; | 1719 | struct fw_ohci *ohci = |
1720 | container_of(work, struct fw_ohci, bus_reset_work); | ||
1719 | int self_id_count, i, j, reg; | 1721 | int self_id_count, i, j, reg; |
1720 | int generation, new_generation; | 1722 | int generation, new_generation; |
1721 | unsigned long flags; | 1723 | unsigned long flags; |
@@ -1887,7 +1889,7 @@ static irqreturn_t irq_handler(int irq, void *data) | |||
1887 | log_irqs(event); | 1889 | log_irqs(event); |
1888 | 1890 | ||
1889 | if (event & OHCI1394_selfIDComplete) | 1891 | if (event & OHCI1394_selfIDComplete) |
1890 | tasklet_schedule(&ohci->bus_reset_tasklet); | 1892 | queue_work(fw_workqueue, &ohci->bus_reset_work); |
1891 | 1893 | ||
1892 | if (event & OHCI1394_RQPkt) | 1894 | if (event & OHCI1394_RQPkt) |
1893 | tasklet_schedule(&ohci->ar_request_ctx.tasklet); | 1895 | tasklet_schedule(&ohci->ar_request_ctx.tasklet); |
@@ -2260,7 +2262,7 @@ static int ohci_set_config_rom(struct fw_card *card, | |||
2260 | * then set up the real values for the two registers. | 2262 | * then set up the real values for the two registers. |
2261 | * | 2263 | * |
2262 | * We use ohci->lock to avoid racing with the code that sets | 2264 | * We use ohci->lock to avoid racing with the code that sets |
2263 | * ohci->next_config_rom to NULL (see bus_reset_tasklet). | 2265 | * ohci->next_config_rom to NULL (see bus_reset_work). |
2264 | */ | 2266 | */ |
2265 | 2267 | ||
2266 | next_config_rom = | 2268 | next_config_rom = |
@@ -3239,8 +3241,7 @@ static int __devinit pci_probe(struct pci_dev *dev, | |||
3239 | spin_lock_init(&ohci->lock); | 3241 | spin_lock_init(&ohci->lock); |
3240 | mutex_init(&ohci->phy_reg_mutex); | 3242 | mutex_init(&ohci->phy_reg_mutex); |
3241 | 3243 | ||
3242 | tasklet_init(&ohci->bus_reset_tasklet, | 3244 | INIT_WORK(&ohci->bus_reset_work, bus_reset_work); |
3243 | bus_reset_tasklet, (unsigned long)ohci); | ||
3244 | 3245 | ||
3245 | err = pci_request_region(dev, 0, ohci_driver_name); | 3246 | err = pci_request_region(dev, 0, ohci_driver_name); |
3246 | if (err) { | 3247 | if (err) { |
@@ -3382,6 +3383,7 @@ static void pci_remove(struct pci_dev *dev) | |||
3382 | ohci = pci_get_drvdata(dev); | 3383 | ohci = pci_get_drvdata(dev); |
3383 | reg_write(ohci, OHCI1394_IntMaskClear, ~0); | 3384 | reg_write(ohci, OHCI1394_IntMaskClear, ~0); |
3384 | flush_writes(ohci); | 3385 | flush_writes(ohci); |
3386 | cancel_work_sync(&ohci->bus_reset_work); | ||
3385 | fw_core_remove_card(&ohci->card); | 3387 | fw_core_remove_card(&ohci->card); |
3386 | 3388 | ||
3387 | /* | 3389 | /* |