Commit 911e572e authored by Guilherme G. Piccoli's avatar Guilherme G. Piccoli Committed by Martin K. Petersen

scsi: aacraid: fix PCI error recovery path

During a PCI error recovery, if aac_check_health() is not aware that a
PCI error happened and we have an offline PCI channel, it might trigger
some errors (like NULL pointer dereference) and inhibit the error
recovery process to complete.

This patch makes the health check procedure aware of PCI channel issues,
and in case of error recovery process, the function
aac_adapter_check_health() returns -1 and let the recovery process to
complete successfully. This patch was tested on upstream kernel
v4.11-rc5 in PowerPC ppc64le architecture with adapter 9005:028d
(VID:DID) - the error recovery procedure was able to recover fine.

Fixes: 5c63f7f7 ("aacraid: Added EEH support")
Cc: stable@vger.kernel.org # v4.6+
Signed-off-by: default avatarGuilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>
Reviewed-by: default avatarDave Carroll <david.carroll@microsemi.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 7c856152
...@@ -1690,9 +1690,6 @@ struct aac_dev ...@@ -1690,9 +1690,6 @@ struct aac_dev
#define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \ #define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
(dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) (dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)
#define aac_adapter_check_health(dev) \
(dev)->a_ops.adapter_check_health(dev)
#define aac_adapter_restart(dev, bled, reset_type) \ #define aac_adapter_restart(dev, bled, reset_type) \
((dev)->a_ops.adapter_restart(dev, bled, reset_type)) ((dev)->a_ops.adapter_restart(dev, bled, reset_type))
...@@ -2615,6 +2612,14 @@ static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor) ...@@ -2615,6 +2612,14 @@ static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor)
return capacity; return capacity;
} }
static inline int aac_adapter_check_health(struct aac_dev *dev)
{
if (unlikely(pci_channel_offline(dev->pdev)))
return -1;
return (dev)->a_ops.adapter_check_health(dev);
}
/* SCp.phase values */ /* SCp.phase values */
#define AAC_OWNER_MIDLEVEL 0x101 #define AAC_OWNER_MIDLEVEL 0x101
#define AAC_OWNER_LOWLEVEL 0x102 #define AAC_OWNER_LOWLEVEL 0x102
......
...@@ -1873,7 +1873,8 @@ int aac_check_health(struct aac_dev * aac) ...@@ -1873,7 +1873,8 @@ int aac_check_health(struct aac_dev * aac)
spin_unlock_irqrestore(&aac->fib_lock, flagv); spin_unlock_irqrestore(&aac->fib_lock, flagv);
if (BlinkLED < 0) { if (BlinkLED < 0) {
printk(KERN_ERR "%s: Host adapter dead %d\n", aac->name, BlinkLED); printk(KERN_ERR "%s: Host adapter is dead (or got a PCI error) %d\n",
aac->name, BlinkLED);
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment