diff options
author | Dmitry Kalinkin <dmitry.kalinkin@gmail.com> | 2015-09-17 19:01:43 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-10-04 14:50:57 -0400 |
commit | 472f16f33c7d53515af83c805d4babd8a6c24a19 (patch) | |
tree | e92c06ce93ab7fb8c0c85b4e25bb1eb49734e249 /drivers/vme | |
parent | e2c6393fda98dde5534dd6f83bd15f76abed6555 (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.c | 4 | ||||
-rw-r--r-- | drivers/vme/vme.c | 61 | ||||
-rw-r--r-- | drivers/vme/vme_bridge.h | 4 |
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 | } |
224 | EXPORT_SYMBOL(vme_check_window); | 224 | EXPORT_SYMBOL(vme_check_window); |
225 | 225 | ||
226 | static 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) | |||
991 | EXPORT_SYMBOL(vme_dma_free); | 1024 | EXPORT_SYMBOL(vme_dma_free); |
992 | 1025 | ||
993 | void vme_bus_error_handler(struct vme_bridge *bridge, | 1026 | void 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 | ||
78 | struct vme_bus_error { | 78 | struct 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 | ||
84 | struct vme_callback { | 84 | struct vme_callback { |
@@ -167,7 +167,7 @@ struct vme_bridge { | |||
167 | }; | 167 | }; |
168 | 168 | ||
169 | void vme_bus_error_handler(struct vme_bridge *bridge, | 169 | void vme_bus_error_handler(struct vme_bridge *bridge, |
170 | unsigned long long address, u32 attributes); | 170 | unsigned long long address, int am); |
171 | struct vme_bus_error *vme_find_error(struct vme_bridge *bridge, u32 aspace, | 171 | struct 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); |
173 | void vme_clear_errors(struct vme_bridge *bridge, u32 aspace, | 173 | void vme_clear_errors(struct vme_bridge *bridge, u32 aspace, |