Skip to content

Commit

Permalink
aacraid: Fix for KDUMP driver hang
Browse files Browse the repository at this point in the history
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.

Cc: stable@vger.kernel.org
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>
  • Loading branch information
Raghava Aditya Renukunta authored and martinkpetersen committed Apr 29, 2016
1 parent eef76f1 commit 78cbccd
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/scsi/aacraid/aacraid.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions drivers/scsi/aacraid/comminit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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;
Expand Down Expand Up @@ -414,6 +429,15 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
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)) &&
Expand Down

0 comments on commit 78cbccd

Please sign in to comment.