summaryrefslogtreecommitdiffstats
path: root/drivers/vme
diff options
context:
space:
mode:
authorDmitry Kalinkin <dmitry.kalinkin@gmail.com>2015-09-17 19:01:43 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-10-04 14:50:57 -0400
commit472f16f33c7d53515af83c805d4babd8a6c24a19 (patch)
treee92c06ce93ab7fb8c0c85b4e25bb1eb49734e249 /drivers/vme
parente2c6393fda98dde5534dd6f83bd15f76abed6555 (diff)
vme: include address space in error filtering
Also changes vme_bus_error_handler to take generic address modifier code instead of raw contents of a device-specific attribute register. 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')
-rw-r--r--drivers/vme/bridges/vme_tsi148.c4
-rw-r--r--drivers/vme/vme.c61
-rw-r--r--drivers/vme/vme_bridge.h4
3 files changed, 46 insertions, 23 deletions
diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c
index 60c4933ca0c8..4520d985379f 100644
--- a/drivers/vme/bridges/vme_tsi148.c
+++ b/drivers/vme/bridges/vme_tsi148.c
@@ -169,6 +169,7 @@ static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge)
169 unsigned int error_addr_high, error_addr_low; 169 unsigned int error_addr_high, error_addr_low;
170 unsigned long long error_addr; 170 unsigned long long error_addr;
171 u32 error_attrib; 171 u32 error_attrib;
172 int error_am;
172 struct tsi148_driver *bridge; 173 struct tsi148_driver *bridge;
173 174
174 bridge = tsi148_bridge->driver_priv; 175 bridge = tsi148_bridge->driver_priv;
@@ -176,6 +177,7 @@ static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge)
176 error_addr_high = ioread32be(bridge->base + TSI148_LCSR_VEAU); 177 error_addr_high = ioread32be(bridge->base + TSI148_LCSR_VEAU);
177 error_addr_low = ioread32be(bridge->base + TSI148_LCSR_VEAL); 178 error_addr_low = ioread32be(bridge->base + TSI148_LCSR_VEAL);
178 error_attrib = ioread32be(bridge->base + TSI148_LCSR_VEAT); 179 error_attrib = ioread32be(bridge->base + TSI148_LCSR_VEAT);
180 error_am = (error_attrib & TSI148_LCSR_VEAT_AM_M) >> 8;
179 181
180 reg_join(error_addr_high, error_addr_low, &error_addr); 182 reg_join(error_addr_high, error_addr_low, &error_addr);
181 183
@@ -186,7 +188,7 @@ static u32 tsi148_VERR_irqhandler(struct vme_bridge *tsi148_bridge)
186 } 188 }
187 189
188 if (err_chk) 190 if (err_chk)
189 vme_bus_error_handler(tsi148_bridge, error_addr, error_attrib); 191 vme_bus_error_handler(tsi148_bridge, error_addr, error_am);
190 else 192 else
191 dev_err(tsi148_bridge->parent, 193 dev_err(tsi148_bridge->parent,
192 "VME Bus Error at address: 0x%llx, attributes: %08x\n", 194 "VME Bus Error at address: 0x%llx, attributes: %08x\n",
diff --git a/drivers/vme/vme.c b/drivers/vme/vme.c
index 6803744978b2..2b79cd2715da 100644
--- a/drivers/vme/vme.c
+++ b/drivers/vme/vme.c
@@ -223,6 +223,39 @@ int vme_check_window(u32 aspace, unsigned long long vme_base,
223} 223}
224EXPORT_SYMBOL(vme_check_window); 224EXPORT_SYMBOL(vme_check_window);
225 225
226static u32 vme_get_aspace(int am)
227{
228 switch (am) {
229 case 0x29:
230 case 0x2D:
231 return VME_A16;
232 case 0x38:
233 case 0x39:
234 case 0x3A:
235 case 0x3B:
236 case 0x3C:
237 case 0x3D:
238 case 0x3E:
239 case 0x3F:
240 return VME_A24;
241 case 0x8:
242 case 0x9:
243 case 0xA:
244 case 0xB:
245 case 0xC:
246 case 0xD:
247 case 0xE:
248 case 0xF:
249 return VME_A32;
250 case 0x0:
251 case 0x1:
252 case 0x3:
253 return VME_A64;
254 }
255
256 return 0;
257}
258
226/* 259/*
227 * Request a slave image with specific attributes, return some unique 260 * Request a slave image with specific attributes, return some unique
228 * identifier. 261 * identifier.
@@ -991,14 +1024,14 @@ int vme_dma_free(struct vme_resource *resource)
991EXPORT_SYMBOL(vme_dma_free); 1024EXPORT_SYMBOL(vme_dma_free);
992 1025
993void vme_bus_error_handler(struct vme_bridge *bridge, 1026void vme_bus_error_handler(struct vme_bridge *bridge,
994 unsigned long long address, u32 attributes) 1027 unsigned long long address, int am)
995{ 1028{
996 struct vme_bus_error *error; 1029 struct vme_bus_error *error;
997 1030
998 error = kmalloc(sizeof(struct vme_bus_error), GFP_ATOMIC); 1031 error = kmalloc(sizeof(struct vme_bus_error), GFP_ATOMIC);
999 if (error) { 1032 if (error) {
1033 error->aspace = vme_get_aspace(am);
1000 error->address = address; 1034 error->address = address;
1001 error->attributes = attributes;
1002 list_add_tail(&error->list, &bridge->vme_errors); 1035 list_add_tail(&error->list, &bridge->vme_errors);
1003 } else { 1036 } else {
1004 dev_err(bridge->parent, 1037 dev_err(bridge->parent,
@@ -1019,19 +1052,13 @@ struct vme_bus_error *vme_find_error(struct vme_bridge *bridge, u32 aspace,
1019 1052
1020 bound = address + count; 1053 bound = address + count;
1021 1054
1022 /*
1023 * XXX We are currently not looking at the address space when parsing
1024 * for errors. This is because parsing the Address Modifier Codes
1025 * is going to be quite resource intensive to do properly. We
1026 * should be OK just looking at the addresses and this is certainly
1027 * much better than what we had before.
1028 */
1029 err_pos = NULL; 1055 err_pos = NULL;
1030 /* Iterate through errors */ 1056 /* Iterate through errors */
1031 list_for_each(err_pos, &bridge->vme_errors) { 1057 list_for_each(err_pos, &bridge->vme_errors) {
1032 vme_err = list_entry(err_pos, struct vme_bus_error, list); 1058 vme_err = list_entry(err_pos, struct vme_bus_error, list);
1033 if ((vme_err->address >= address) && 1059 if ((vme_err->aspace == aspace) &&
1034 (vme_err->address < bound)) { 1060 (vme_err->address >= address) &&
1061 (vme_err->address < bound)) {
1035 1062
1036 valid = vme_err; 1063 valid = vme_err;
1037 break; 1064 break;
@@ -1054,20 +1081,14 @@ void vme_clear_errors(struct vme_bridge *bridge, u32 aspace,
1054 1081
1055 bound = address + count; 1082 bound = address + count;
1056 1083
1057 /*
1058 * XXX We are currently not looking at the address space when parsing
1059 * for errors. This is because parsing the Address Modifier Codes
1060 * is going to be quite resource intensive to do properly. We
1061 * should be OK just looking at the addresses and this is certainly
1062 * much better than what we had before.
1063 */
1064 err_pos = NULL; 1084 err_pos = NULL;
1065 /* Iterate through errors */ 1085 /* Iterate through errors */
1066 list_for_each_safe(err_pos, temp, &bridge->vme_errors) { 1086 list_for_each_safe(err_pos, temp, &bridge->vme_errors) {
1067 vme_err = list_entry(err_pos, struct vme_bus_error, list); 1087 vme_err = list_entry(err_pos, struct vme_bus_error, list);
1068 1088
1069 if ((vme_err->address >= address) && 1089 if ((vme_err->aspace == aspace) &&
1070 (vme_err->address < bound)) { 1090 (vme_err->address >= address) &&
1091 (vme_err->address < bound)) {
1071 1092
1072 list_del(err_pos); 1093 list_del(err_pos);
1073 kfree(vme_err); 1094 kfree(vme_err);
diff --git a/drivers/vme/vme_bridge.h b/drivers/vme/vme_bridge.h
index d8d6b144003b..92fbe18cbc42 100644
--- a/drivers/vme/vme_bridge.h
+++ b/drivers/vme/vme_bridge.h
@@ -77,8 +77,8 @@ struct vme_lm_resource {
77 77
78struct vme_bus_error { 78struct vme_bus_error {
79 struct list_head list; 79 struct list_head list;
80 u32 aspace;
80 unsigned long long address; 81 unsigned long long address;
81 u32 attributes;
82}; 82};
83 83
84struct vme_callback { 84struct vme_callback {
@@ -167,7 +167,7 @@ struct vme_bridge {
167}; 167};
168 168
169void vme_bus_error_handler(struct vme_bridge *bridge, 169void vme_bus_error_handler(struct vme_bridge *bridge,
170 unsigned long long address, u32 attributes); 170 unsigned long long address, int am);
171struct vme_bus_error *vme_find_error(struct vme_bridge *bridge, u32 aspace, 171struct vme_bus_error *vme_find_error(struct vme_bridge *bridge, u32 aspace,
172 unsigned long long address, size_t count); 172 unsigned long long address, size_t count);
173void vme_clear_errors(struct vme_bridge *bridge, u32 aspace, 173void vme_clear_errors(struct vme_bridge *bridge, u32 aspace,