diff options
Diffstat (limited to 'drivers/crypto')
-rw-r--r-- | drivers/crypto/hifn_795x.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c index 391c20a3dff8..7b7c85439c33 100644 --- a/drivers/crypto/hifn_795x.c +++ b/drivers/crypto/hifn_795x.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/highmem.h> | 28 | #include <linux/highmem.h> |
29 | #include <linux/interrupt.h> | ||
29 | #include <linux/crypto.h> | 30 | #include <linux/crypto.h> |
30 | 31 | ||
31 | #include <crypto/algapi.h> | 32 | #include <crypto/algapi.h> |
@@ -426,6 +427,8 @@ struct hifn_device | |||
426 | 427 | ||
427 | u8 snum; | 428 | u8 snum; |
428 | 429 | ||
430 | struct tasklet_struct tasklet; | ||
431 | |||
429 | struct crypto_queue queue; | 432 | struct crypto_queue queue; |
430 | struct list_head alg_list; | 433 | struct list_head alg_list; |
431 | }; | 434 | }; |
@@ -1879,7 +1882,7 @@ static irqreturn_t hifn_interrupt(int irq, void *data) | |||
1879 | hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg); | 1882 | hifn_write_1(dev, HIFN_1_DMA_IER, dev->dmareg); |
1880 | } | 1883 | } |
1881 | 1884 | ||
1882 | hifn_check_for_completion(dev, 0); | 1885 | tasklet_schedule(&dev->tasklet); |
1883 | hifn_clear_rings(dev); | 1886 | hifn_clear_rings(dev); |
1884 | 1887 | ||
1885 | return IRQ_HANDLED; | 1888 | return IRQ_HANDLED; |
@@ -2408,6 +2411,19 @@ err_out_exit: | |||
2408 | return err; | 2411 | return err; |
2409 | } | 2412 | } |
2410 | 2413 | ||
2414 | static void hifn_tasklet_callback(unsigned long data) | ||
2415 | { | ||
2416 | struct hifn_device *dev = (struct hifn_device *)data; | ||
2417 | |||
2418 | /* | ||
2419 | * This is ok to call this without lock being held, | ||
2420 | * althogh it modifies some parameters used in parallel, | ||
2421 | * (like dev->success), but they are used in process | ||
2422 | * context or update is atomic (like setting dev->sa[i] to NULL). | ||
2423 | */ | ||
2424 | hifn_check_for_completion(dev, 0); | ||
2425 | } | ||
2426 | |||
2411 | static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 2427 | static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
2412 | { | 2428 | { |
2413 | int err, i; | 2429 | int err, i; |
@@ -2489,6 +2505,8 @@ static int hifn_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2489 | 2505 | ||
2490 | pci_set_drvdata(pdev, dev); | 2506 | pci_set_drvdata(pdev, dev); |
2491 | 2507 | ||
2508 | tasklet_init(&dev->tasklet, hifn_tasklet_callback, (unsigned long)dev); | ||
2509 | |||
2492 | crypto_init_queue(&dev->queue, 1); | 2510 | crypto_init_queue(&dev->queue, 1); |
2493 | 2511 | ||
2494 | err = request_irq(dev->irq, hifn_interrupt, IRQF_SHARED, dev->name, dev); | 2512 | err = request_irq(dev->irq, hifn_interrupt, IRQF_SHARED, dev->name, dev); |
@@ -2524,6 +2542,7 @@ err_out_stop_device: | |||
2524 | hifn_stop_device(dev); | 2542 | hifn_stop_device(dev); |
2525 | err_out_free_irq: | 2543 | err_out_free_irq: |
2526 | free_irq(dev->irq, dev->name); | 2544 | free_irq(dev->irq, dev->name); |
2545 | tasklet_kill(&dev->tasklet); | ||
2527 | err_out_free_desc: | 2546 | err_out_free_desc: |
2528 | pci_free_consistent(pdev, sizeof(struct hifn_dma), | 2547 | pci_free_consistent(pdev, sizeof(struct hifn_dma), |
2529 | dev->desc_virt, dev->desc_dma); | 2548 | dev->desc_virt, dev->desc_dma); |
@@ -2563,6 +2582,7 @@ static void hifn_remove(struct pci_dev *pdev) | |||
2563 | hifn_stop_device(dev); | 2582 | hifn_stop_device(dev); |
2564 | 2583 | ||
2565 | free_irq(dev->irq, dev->name); | 2584 | free_irq(dev->irq, dev->name); |
2585 | tasklet_kill(&dev->tasklet); | ||
2566 | 2586 | ||
2567 | hifn_flush(dev); | 2587 | hifn_flush(dev); |
2568 | 2588 | ||