diff options
author | Dmitry Kalinkin <dmitry.kalinkin@gmail.com> | 2015-09-18 02:01:42 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-10-04 19:50:57 +0100 |
commit | e2c6393fda98dde5534dd6f83bd15f76abed6555 (patch) | |
tree | 73f94bb441c10040c6527b07c86e74d4a2eb1b37 /drivers/vme/bridges/vme_tsi148.c | |
parent | da5ae8a991d35d73b3875de0298afaf033d85363 (diff) | |
download | lwn-e2c6393fda98dde5534dd6f83bd15f76abed6555.tar.gz lwn-e2c6393fda98dde5534dd6f83bd15f76abed6555.zip |
vme: move tsi148 error handling into VME subsystem
Error handling code found in tsi148 is not device specific. In fact it
already relies on shared vme_bus_error struct and vme_bridge.vme_errors
field. The other bridge driver could reuse this code if it is shared.
This introduces a slight behavior change: vme error message won't be
triggered in a rare case when err_chk=1 and kmalloc fails.
Signed-off-by: Dmitry Kalinkin <dmitry.kalinkin@gmail.com>
Cc: Igor Alekseev <igor.alekseev@itep.ru>
Acked-by: Martyn Welch <martyn@welchs.me.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/vme/bridges/vme_tsi148.c')
-rw-r--r-- | drivers/vme/bridges/vme_tsi148.c | 93 |
1 files changed, 7 insertions, 86 deletions
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 6c40f282c267..60c4933ca0c8 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -169,7 +169,6 @@ static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge) unsigned int error_addr_high, error_addr_low; unsigned long long error_addr; u32 error_attrib; - struct vme_bus_error *error = NULL; struct tsi148_driver *bridge; bridge = tsi148_bridge->driver_priv; @@ -186,23 +185,12 @@ static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge) "Occurred\n"); } - if (err_chk) { - error = kmalloc(sizeof(struct vme_bus_error), GFP_ATOMIC); - if (error) { - error->address = error_addr; - error->attributes = error_attrib; - list_add_tail(&error->list, &tsi148_bridge->vme_errors); - } else { - dev_err(tsi148_bridge->parent, - "Unable to alloc memory for VMEbus Error reporting\n"); - } - } - - if (!error) { + if (err_chk) + vme_bus_error_handler(tsi148_bridge, error_addr, error_attrib); + else dev_err(tsi148_bridge->parent, "VME Bus Error at address: 0x%llx, attributes: %08x\n", error_addr, error_attrib); - } /* Clear Status */ iowrite32be(TSI148_LCSR_VEAT_VESCL, bridge->base + TSI148_LCSR_VEAT); @@ -483,73 +471,6 @@ static int tsi148_irq_generate(struct vme_bridge *tsi148_bridge, int level, } /* - * Find the first error in this address range - */ -static struct vme_bus_error *tsi148_find_error(struct vme_bridge *tsi148_bridge, - u32 aspace, unsigned long long address, size_t count) -{ - struct list_head *err_pos; - struct vme_bus_error *vme_err, *valid = NULL; - unsigned long long bound; - - bound = address + count; - - /* - * XXX We are currently not looking at the address space when parsing - * for errors. This is because parsing the Address Modifier Codes - * is going to be quite resource intensive to do properly. We - * should be OK just looking at the addresses and this is certainly - * much better than what we had before. - */ - err_pos = NULL; - /* Iterate through errors */ - list_for_each(err_pos, &tsi148_bridge->vme_errors) { - vme_err = list_entry(err_pos, struct vme_bus_error, list); - if ((vme_err->address >= address) && - (vme_err->address < bound)) { - - valid = vme_err; - break; - } - } - - return valid; -} - -/* - * Clear errors in the provided address range. - */ -static void tsi148_clear_errors(struct vme_bridge *tsi148_bridge, - u32 aspace, unsigned long long address, size_t count) -{ - struct list_head *err_pos, *temp; - struct vme_bus_error *vme_err; - unsigned long long bound; - - bound = address + count; - - /* - * XXX We are currently not looking at the address space when parsing - * for errors. This is because parsing the Address Modifier Codes - * is going to be quite resource intensive to do properly. We - * should be OK just looking at the addresses and this is certainly - * much better than what we had before. - */ - err_pos = NULL; - /* Iterate through errors */ - list_for_each_safe(err_pos, temp, &tsi148_bridge->vme_errors) { - vme_err = list_entry(err_pos, struct vme_bus_error, list); - - if ((vme_err->address >= address) && - (vme_err->address < bound)) { - - list_del(err_pos); - kfree(vme_err); - } - } -} - -/* * Initialize a slave window with the requested attributes. */ static int tsi148_slave_set(struct vme_slave_resource *image, int enabled, @@ -1323,14 +1244,14 @@ out: __tsi148_master_get(image, &enabled, &vme_base, &size, &aspace, &cycle, &dwidth); - vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset, + vme_err = vme_find_error(tsi148_bridge, aspace, vme_base + offset, count); if (vme_err != NULL) { dev_err(image->parent->parent, "First VME read error detected " "an at address 0x%llx\n", vme_err->address); retval = vme_err->address - (vme_base + offset); /* Clear down save errors in this address range */ - tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset, + vme_clear_errors(tsi148_bridge, aspace, vme_base + offset, count); } @@ -1422,14 +1343,14 @@ out: ioread16(bridge->flush_image->kern_base + 0x7F000); - vme_err = tsi148_find_error(tsi148_bridge, aspace, vme_base + offset, + vme_err = vme_find_error(tsi148_bridge, aspace, vme_base + offset, count); if (vme_err != NULL) { dev_warn(tsi148_bridge->parent, "First VME write error detected" " an at address 0x%llx\n", vme_err->address); retval = vme_err->address - (vme_base + offset); /* Clear down save errors in this address range */ - tsi148_clear_errors(tsi148_bridge, aspace, vme_base + offset, + vme_clear_errors(tsi148_bridge, aspace, vme_base + offset, count); } |