diff options
author | Alexander Gordeev <agordeev@redhat.com> | 2014-02-19 03:58:19 -0500 |
---|---|---|
committer | Jens Axboe <axboe@fb.com> | 2014-02-21 18:45:26 -0500 |
commit | 46817769edb239b511a63345ba2f3c87803f1c14 (patch) | |
tree | ad5b8a6bae5bd08677e4a0ee65f7013831936565 | |
parent | c5e3035c88cbefe60ec155b3f9999413da1ee694 (diff) |
skd: Fix incomplete cleanup of MSI-X interrupt
When enabling MSI-X interrupts fails due to lack of memory
the call to pci_disable_msix() is missed and the device is
left with MSI-X interrupts enabled while the driver assumes
otherwise. This update fixes the described misbehaviour and
cleans up the code of skd_release_msix() function.
Signed-off-by: Alexander Gordeev <agordeev@redhat.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Cc: Kyungmin Park <kyungmin.park@samsung.com>
Cc: linux-pci@vger.kernel.org
Signed-off-by: Jens Axboe <axboe@fb.com>
-rw-r--r-- | drivers/block/skd_main.c | 50 |
1 files changed, 26 insertions, 24 deletions
diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c index 3fa0918ddaf8..d0550ba948fa 100644 --- a/drivers/block/skd_main.c +++ b/drivers/block/skd_main.c | |||
@@ -3910,43 +3910,44 @@ static void skd_release_msix(struct skd_device *skdev) | |||
3910 | struct skd_msix_entry *qentry; | 3910 | struct skd_msix_entry *qentry; |
3911 | int i; | 3911 | int i; |
3912 | 3912 | ||
3913 | if (skdev->msix_entries == NULL) | 3913 | if (skdev->msix_entries) { |
3914 | return; | 3914 | for (i = 0; i < skdev->msix_count; i++) { |
3915 | for (i = 0; i < skdev->msix_count; i++) { | 3915 | qentry = &skdev->msix_entries[i]; |
3916 | qentry = &skdev->msix_entries[i]; | 3916 | skdev = qentry->rsp; |
3917 | skdev = qentry->rsp; | 3917 | |
3918 | if (qentry->have_irq) | ||
3919 | devm_free_irq(&skdev->pdev->dev, | ||
3920 | qentry->vector, qentry->rsp); | ||
3921 | } | ||
3918 | 3922 | ||
3919 | if (qentry->have_irq) | 3923 | kfree(skdev->msix_entries); |
3920 | devm_free_irq(&skdev->pdev->dev, | ||
3921 | qentry->vector, qentry->rsp); | ||
3922 | } | 3924 | } |
3923 | pci_disable_msix(skdev->pdev); | 3925 | |
3924 | kfree(skdev->msix_entries); | 3926 | if (skdev->msix_count) |
3927 | pci_disable_msix(skdev->pdev); | ||
3928 | |||
3925 | skdev->msix_count = 0; | 3929 | skdev->msix_count = 0; |
3926 | skdev->msix_entries = NULL; | 3930 | skdev->msix_entries = NULL; |
3927 | } | 3931 | } |
3928 | 3932 | ||
3929 | static int skd_acquire_msix(struct skd_device *skdev) | 3933 | static int skd_acquire_msix(struct skd_device *skdev) |
3930 | { | 3934 | { |
3931 | int i, rc; | 3935 | int i, rc, msix_count = SKD_MAX_MSIX_COUNT; |
3932 | struct pci_dev *pdev; | 3936 | struct pci_dev *pdev = skdev->pdev; |
3933 | struct msix_entry *entries = NULL; | 3937 | struct msix_entry *entries; |
3934 | struct skd_msix_entry *qentry; | 3938 | struct skd_msix_entry *qentry; |
3935 | 3939 | ||
3936 | pdev = skdev->pdev; | 3940 | entries = kzalloc(sizeof(struct msix_entry) * msix_count, GFP_KERNEL); |
3937 | skdev->msix_count = SKD_MAX_MSIX_COUNT; | ||
3938 | entries = kzalloc(sizeof(struct msix_entry) * SKD_MAX_MSIX_COUNT, | ||
3939 | GFP_KERNEL); | ||
3940 | if (!entries) | 3941 | if (!entries) |
3941 | return -ENOMEM; | 3942 | return -ENOMEM; |
3942 | 3943 | ||
3943 | for (i = 0; i < SKD_MAX_MSIX_COUNT; i++) | 3944 | for (i = 0; i < msix_count; i++) |
3944 | entries[i].entry = i; | 3945 | entries[i].entry = i; |
3945 | 3946 | ||
3946 | rc = pci_enable_msix(pdev, entries, SKD_MAX_MSIX_COUNT); | 3947 | rc = pci_enable_msix(pdev, entries, msix_count); |
3947 | if (rc < 0) | 3948 | if (rc < 0) |
3948 | goto msix_out; | 3949 | goto msix_out; |
3949 | if (rc) { | 3950 | else if (rc) { |
3950 | if (rc < SKD_MIN_MSIX_COUNT) { | 3951 | if (rc < SKD_MIN_MSIX_COUNT) { |
3951 | pr_err("(%s): failed to enable MSI-X %d\n", | 3952 | pr_err("(%s): failed to enable MSI-X %d\n", |
3952 | skd_name(skdev), rc); | 3953 | skd_name(skdev), rc); |
@@ -3956,20 +3957,21 @@ static int skd_acquire_msix(struct skd_device *skdev) | |||
3956 | skdev->name, __func__, __LINE__, | 3957 | skdev->name, __func__, __LINE__, |
3957 | pci_name(pdev), skdev->name, rc); | 3958 | pci_name(pdev), skdev->name, rc); |
3958 | 3959 | ||
3959 | skdev->msix_count = rc; | 3960 | msix_count = rc; |
3960 | rc = pci_enable_msix(pdev, entries, skdev->msix_count); | 3961 | rc = pci_enable_msix(pdev, entries, msix_count); |
3961 | if (rc) { | 3962 | if (rc) { |
3962 | pr_err("(%s): failed to enable MSI-X " | 3963 | pr_err("(%s): failed to enable MSI-X " |
3963 | "support (%d) %d\n", | 3964 | "support (%d) %d\n", |
3964 | skd_name(skdev), skdev->msix_count, rc); | 3965 | skd_name(skdev), msix_count, rc); |
3965 | goto msix_out; | 3966 | goto msix_out; |
3966 | } | 3967 | } |
3967 | } | 3968 | } |
3969 | |||
3970 | skdev->msix_count = msix_count; | ||
3968 | skdev->msix_entries = kzalloc(sizeof(struct skd_msix_entry) * | 3971 | skdev->msix_entries = kzalloc(sizeof(struct skd_msix_entry) * |
3969 | skdev->msix_count, GFP_KERNEL); | 3972 | skdev->msix_count, GFP_KERNEL); |
3970 | if (!skdev->msix_entries) { | 3973 | if (!skdev->msix_entries) { |
3971 | rc = -ENOMEM; | 3974 | rc = -ENOMEM; |
3972 | skdev->msix_count = 0; | ||
3973 | pr_err("(%s): msix table allocation error\n", | 3975 | pr_err("(%s): msix table allocation error\n", |
3974 | skd_name(skdev)); | 3976 | skd_name(skdev)); |
3975 | goto msix_out; | 3977 | goto msix_out; |