s390/pci: improve error handling during interrupt deregistration
When we ask a function to stop creating interrupts this may fail due to the function being already gone (e.g. after hot-unplug). Consequently we don't free associated resources like summary bits and bit vectors used for irq processing. This could lead to situations where we ran out of these resources and fail to setup new interrupts. The fix is to just ignore the errors in cases where we can be sure no new interrupts are generated. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Reviewed-by: Gerald Schaefer <gerald.schaefer@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Esse commit está contido em:

commit de
Martin Schwidefsky

pai
795818e8bf
commit
4dfbd3efe3
@@ -108,6 +108,7 @@ static int zpci_set_airq(struct zpci_dev *zdev)
|
||||
{
|
||||
u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_REG_INT);
|
||||
struct zpci_fib fib = {0};
|
||||
u8 status;
|
||||
|
||||
fib.isc = PCI_ISC;
|
||||
fib.sum = 1; /* enable summary notifications */
|
||||
@@ -117,7 +118,22 @@ static int zpci_set_airq(struct zpci_dev *zdev)
|
||||
fib.aisb = (unsigned long) zpci_aisb_iv->vector + (zdev->aisb/64)*8;
|
||||
fib.aisbo = zdev->aisb & 63;
|
||||
|
||||
return zpci_mod_fc(req, &fib);
|
||||
return zpci_mod_fc(req, &fib, &status) ? -EIO : 0;
|
||||
}
|
||||
|
||||
/* Modify PCI: Unregister adapter interruptions */
|
||||
static int zpci_clear_airq(struct zpci_dev *zdev)
|
||||
{
|
||||
u64 req = ZPCI_CREATE_REQ(zdev->fh, 0, ZPCI_MOD_FC_DEREG_INT);
|
||||
struct zpci_fib fib = {0};
|
||||
u8 cc, status;
|
||||
|
||||
cc = zpci_mod_fc(req, &fib, &status);
|
||||
if (cc == 3 || (cc == 1 && status == 24))
|
||||
/* Function already gone or IRQs already deregistered. */
|
||||
cc = 0;
|
||||
|
||||
return cc ? -EIO : 0;
|
||||
}
|
||||
|
||||
struct mod_pci_args {
|
||||
@@ -131,13 +147,14 @@ static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args
|
||||
{
|
||||
u64 req = ZPCI_CREATE_REQ(zdev->fh, dmaas, fn);
|
||||
struct zpci_fib fib = {0};
|
||||
u8 status;
|
||||
|
||||
fib.pba = args->base;
|
||||
fib.pal = args->limit;
|
||||
fib.iota = args->iota;
|
||||
fib.fmb_addr = args->fmb_addr;
|
||||
|
||||
return zpci_mod_fc(req, &fib);
|
||||
return zpci_mod_fc(req, &fib, &status) ? -EIO : 0;
|
||||
}
|
||||
|
||||
/* Modify PCI: Register I/O address translation parameters */
|
||||
@@ -159,14 +176,6 @@ int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas)
|
||||
return mod_pci(zdev, ZPCI_MOD_FC_DEREG_IOAT, dmaas, &args);
|
||||
}
|
||||
|
||||
/* Modify PCI: Unregister adapter interruptions */
|
||||
static int zpci_clear_airq(struct zpci_dev *zdev)
|
||||
{
|
||||
struct mod_pci_args args = { 0, 0, 0, 0 };
|
||||
|
||||
return mod_pci(zdev, ZPCI_MOD_FC_DEREG_INT, 0, &args);
|
||||
}
|
||||
|
||||
/* Modify PCI: Set PCI function measurement parameters */
|
||||
int zpci_fmb_enable_device(struct zpci_dev *zdev)
|
||||
{
|
||||
|
@@ -40,20 +40,20 @@ static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status)
|
||||
return cc;
|
||||
}
|
||||
|
||||
int zpci_mod_fc(u64 req, struct zpci_fib *fib)
|
||||
u8 zpci_mod_fc(u64 req, struct zpci_fib *fib, u8 *status)
|
||||
{
|
||||
u8 cc, status;
|
||||
u8 cc;
|
||||
|
||||
do {
|
||||
cc = __mpcifc(req, fib, &status);
|
||||
cc = __mpcifc(req, fib, status);
|
||||
if (cc == 2)
|
||||
msleep(ZPCI_INSN_BUSY_DELAY);
|
||||
} while (cc == 2);
|
||||
|
||||
if (cc)
|
||||
zpci_err_insn(cc, status, req, 0);
|
||||
zpci_err_insn(cc, *status, req, 0);
|
||||
|
||||
return (cc) ? -EIO : 0;
|
||||
return cc;
|
||||
}
|
||||
|
||||
/* Refresh PCI Translations */
|
||||
|
Referência em uma nova issue
Block a user