| From 78cbccd3bd683c295a44af8050797dc4a41376ff Mon Sep 17 00:00:00 2001 |
| From: Raghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com> |
| Date: Mon, 25 Apr 2016 23:32:37 -0700 |
| Subject: aacraid: Fix for KDUMP driver hang |
| |
| From: Raghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com> |
| |
| commit 78cbccd3bd683c295a44af8050797dc4a41376ff upstream. |
| |
| When KDUMP is triggered the driver first talks to the firmware in INTX |
| mode, but the adapter firmware is still in MSIX mode. Therefore the first |
| driver command hangs since the driver is waiting for an INTX response and |
| firmware gives a MSIX response. If when the OS is installed on a RAID |
| drive created by the adapter KDUMP will hang since the driver does not |
| receive a response in sync mode. |
| |
| Fixed by: Change the firmware to INTX mode if it is in MSIX mode before |
| sending the first sync command. |
| |
| Signed-off-by: Raghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com> |
| Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de> |
| Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/scsi/aacraid/aacraid.h | 1 + |
| drivers/scsi/aacraid/comminit.c | 24 ++++++++++++++++++++++++ |
| 2 files changed, 25 insertions(+) |
| |
| --- a/drivers/scsi/aacraid/aacraid.h |
| +++ b/drivers/scsi/aacraid/aacraid.h |
| @@ -29,6 +29,7 @@ enum { |
| #define AAC_INT_MODE_MSI (1<<1) |
| #define AAC_INT_MODE_AIF (1<<2) |
| #define AAC_INT_MODE_SYNC (1<<3) |
| +#define AAC_INT_MODE_MSIX (1<<16) |
| |
| #define AAC_INT_ENABLE_TYPE1_INTX 0xfffffffb |
| #define AAC_INT_ENABLE_TYPE1_MSIX 0xfffffffa |
| --- a/drivers/scsi/aacraid/comminit.c |
| +++ b/drivers/scsi/aacraid/comminit.c |
| @@ -37,6 +37,7 @@ |
| #include <linux/spinlock.h> |
| #include <linux/slab.h> |
| #include <linux/blkdev.h> |
| +#include <linux/delay.h> |
| #include <linux/completion.h> |
| #include <linux/mm.h> |
| #include <scsi/scsi_host.h> |
| @@ -47,6 +48,20 @@ struct aac_common aac_config = { |
| .irq_mod = 1 |
| }; |
| |
| +static inline int aac_is_msix_mode(struct aac_dev *dev) |
| +{ |
| + u32 status; |
| + |
| + status = src_readl(dev, MUnit.OMR); |
| + return (status & AAC_INT_MODE_MSIX); |
| +} |
| + |
| +static inline void aac_change_to_intx(struct aac_dev *dev) |
| +{ |
| + aac_src_access_devreg(dev, AAC_DISABLE_MSIX); |
| + aac_src_access_devreg(dev, AAC_ENABLE_INTX); |
| +} |
| + |
| static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign) |
| { |
| unsigned char *base; |
| @@ -427,6 +442,15 @@ struct aac_dev *aac_init_adapter(struct |
| dev->comm_interface = AAC_COMM_PRODUCER; |
| dev->raw_io_interface = dev->raw_io_64 = 0; |
| |
| + |
| + /* |
| + * Enable INTX mode, if not done already Enabled |
| + */ |
| + if (aac_is_msix_mode(dev)) { |
| + aac_change_to_intx(dev); |
| + dev_info(&dev->pdev->dev, "Changed firmware to INTX mode"); |
| + } |
| + |
| if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, |
| 0, 0, 0, 0, 0, 0, |
| status+0, status+1, status+2, status+3, NULL)) && |