diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-18 13:06:00 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-18 13:06:00 -0500 |
commit | 7b077868cb8bc31aa5a0dad961ecc9f157bff744 (patch) | |
tree | 02edce8760040ab5c15c242eb648fb3a342c58d7 /arch | |
parent | 16e024f30ce96ef5fa651e2914e19d175a924cab (diff) | |
parent | 1f1c96102ff848778cd596e81bdbd45f81a40119 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 update #2 from Martin Schwidefsky:
"The main patch is the function measurement blocks extension for PCI to
do performance statistics and help with debugging. The other patch is
a small cleanup in ccwdev.h."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
s390/ccwdev: Include asm/schid.h.
s390/pci: performance statistics and debug infrastructure
Diffstat (limited to 'arch')
-rw-r--r-- | arch/s390/include/asm/ccwdev.h | 4 | ||||
-rw-r--r-- | arch/s390/include/asm/pci.h | 39 | ||||
-rw-r--r-- | arch/s390/include/asm/pci_debug.h | 36 | ||||
-rw-r--r-- | arch/s390/pci/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/pci/pci.c | 73 | ||||
-rw-r--r-- | arch/s390/pci/pci_clp.c | 1 | ||||
-rw-r--r-- | arch/s390/pci/pci_debug.c | 193 | ||||
-rw-r--r-- | arch/s390/pci/pci_dma.c | 8 | ||||
-rw-r--r-- | arch/s390/pci/pci_event.c | 2 |
9 files changed, 350 insertions, 8 deletions
diff --git a/arch/s390/include/asm/ccwdev.h b/arch/s390/include/asm/ccwdev.h index 6d1f3573f0df..e6061617a50b 100644 --- a/arch/s390/include/asm/ccwdev.h +++ b/arch/s390/include/asm/ccwdev.h | |||
@@ -12,15 +12,13 @@ | |||
12 | #include <linux/mod_devicetable.h> | 12 | #include <linux/mod_devicetable.h> |
13 | #include <asm/fcx.h> | 13 | #include <asm/fcx.h> |
14 | #include <asm/irq.h> | 14 | #include <asm/irq.h> |
15 | #include <asm/schid.h> | ||
15 | 16 | ||
16 | /* structs from asm/cio.h */ | 17 | /* structs from asm/cio.h */ |
17 | struct irb; | 18 | struct irb; |
18 | struct ccw1; | 19 | struct ccw1; |
19 | struct ccw_dev_id; | 20 | struct ccw_dev_id; |
20 | 21 | ||
21 | /* from asm/schid.h */ | ||
22 | struct subchannel_id; | ||
23 | |||
24 | /* simplified initializers for struct ccw_device: | 22 | /* simplified initializers for struct ccw_device: |
25 | * CCW_DEVICE and CCW_DEVICE_DEVTYPE initialize one | 23 | * CCW_DEVICE and CCW_DEVICE_DEVTYPE initialize one |
26 | * entry in your MODULE_DEVICE_TABLE and set the match_flag correctly */ | 24 | * entry in your MODULE_DEVICE_TABLE and set the match_flag correctly */ |
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index a6175ad0c42f..b1fa93c606ad 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <asm-generic/pci.h> | 9 | #include <asm-generic/pci.h> |
10 | #include <asm-generic/pci-dma-compat.h> | 10 | #include <asm-generic/pci-dma-compat.h> |
11 | #include <asm/pci_clp.h> | 11 | #include <asm/pci_clp.h> |
12 | #include <asm/pci_debug.h> | ||
12 | 13 | ||
13 | #define PCIBIOS_MIN_IO 0x1000 | 14 | #define PCIBIOS_MIN_IO 0x1000 |
14 | #define PCIBIOS_MIN_MEM 0x10000000 | 15 | #define PCIBIOS_MIN_MEM 0x10000000 |
@@ -33,6 +34,25 @@ int pci_proc_domain(struct pci_bus *); | |||
33 | #define ZPCI_FC_BLOCKED 0x20 | 34 | #define ZPCI_FC_BLOCKED 0x20 |
34 | #define ZPCI_FC_DMA_ENABLED 0x10 | 35 | #define ZPCI_FC_DMA_ENABLED 0x10 |
35 | 36 | ||
37 | struct zpci_fmb { | ||
38 | u32 format : 8; | ||
39 | u32 dma_valid : 1; | ||
40 | u32 : 23; | ||
41 | u32 samples; | ||
42 | u64 last_update; | ||
43 | /* hardware counters */ | ||
44 | u64 ld_ops; | ||
45 | u64 st_ops; | ||
46 | u64 stb_ops; | ||
47 | u64 rpcit_ops; | ||
48 | u64 dma_rbytes; | ||
49 | u64 dma_wbytes; | ||
50 | /* software counters */ | ||
51 | atomic64_t allocated_pages; | ||
52 | atomic64_t mapped_pages; | ||
53 | atomic64_t unmapped_pages; | ||
54 | } __packed __aligned(16); | ||
55 | |||
36 | struct msi_map { | 56 | struct msi_map { |
37 | unsigned long irq; | 57 | unsigned long irq; |
38 | struct msi_desc *msi; | 58 | struct msi_desc *msi; |
@@ -92,7 +112,15 @@ struct zpci_dev { | |||
92 | u64 end_dma; /* End of available DMA addresses */ | 112 | u64 end_dma; /* End of available DMA addresses */ |
93 | u64 dma_mask; /* DMA address space mask */ | 113 | u64 dma_mask; /* DMA address space mask */ |
94 | 114 | ||
115 | /* Function measurement block */ | ||
116 | struct zpci_fmb *fmb; | ||
117 | u16 fmb_update; /* update interval */ | ||
118 | |||
95 | enum pci_bus_speed max_bus_speed; | 119 | enum pci_bus_speed max_bus_speed; |
120 | |||
121 | struct dentry *debugfs_dev; | ||
122 | struct dentry *debugfs_perf; | ||
123 | struct dentry *debugfs_debug; | ||
96 | }; | 124 | }; |
97 | 125 | ||
98 | struct pci_hp_callback_ops { | 126 | struct pci_hp_callback_ops { |
@@ -155,4 +183,15 @@ extern struct list_head zpci_list; | |||
155 | extern struct pci_hp_callback_ops hotplug_ops; | 183 | extern struct pci_hp_callback_ops hotplug_ops; |
156 | extern unsigned int pci_probe; | 184 | extern unsigned int pci_probe; |
157 | 185 | ||
186 | /* FMB */ | ||
187 | int zpci_fmb_enable_device(struct zpci_dev *); | ||
188 | int zpci_fmb_disable_device(struct zpci_dev *); | ||
189 | |||
190 | /* Debug */ | ||
191 | int zpci_debug_init(void); | ||
192 | void zpci_debug_exit(void); | ||
193 | void zpci_debug_init_device(struct zpci_dev *); | ||
194 | void zpci_debug_exit_device(struct zpci_dev *); | ||
195 | void zpci_debug_info(struct zpci_dev *, struct seq_file *); | ||
196 | |||
158 | #endif | 197 | #endif |
diff --git a/arch/s390/include/asm/pci_debug.h b/arch/s390/include/asm/pci_debug.h new file mode 100644 index 000000000000..6bbec4265b6e --- /dev/null +++ b/arch/s390/include/asm/pci_debug.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef _S390_ASM_PCI_DEBUG_H | ||
2 | #define _S390_ASM_PCI_DEBUG_H | ||
3 | |||
4 | #include <asm/debug.h> | ||
5 | |||
6 | extern debug_info_t *pci_debug_msg_id; | ||
7 | extern debug_info_t *pci_debug_err_id; | ||
8 | |||
9 | #ifdef CONFIG_PCI_DEBUG | ||
10 | #define zpci_dbg(fmt, args...) \ | ||
11 | do { \ | ||
12 | if (pci_debug_msg_id->level >= 2) \ | ||
13 | debug_sprintf_event(pci_debug_msg_id, 2, fmt , ## args);\ | ||
14 | } while (0) | ||
15 | |||
16 | #else /* !CONFIG_PCI_DEBUG */ | ||
17 | #define zpci_dbg(fmt, args...) do { } while (0) | ||
18 | #endif | ||
19 | |||
20 | #define zpci_err(text...) \ | ||
21 | do { \ | ||
22 | char debug_buffer[16]; \ | ||
23 | snprintf(debug_buffer, 16, text); \ | ||
24 | debug_text_event(pci_debug_err_id, 0, debug_buffer); \ | ||
25 | } while (0) | ||
26 | |||
27 | static inline void zpci_err_hex(void *addr, int len) | ||
28 | { | ||
29 | while (len > 0) { | ||
30 | debug_event(pci_debug_err_id, 0, (void *) addr, len); | ||
31 | len -= pci_debug_err_id->buf_size; | ||
32 | addr += pci_debug_err_id->buf_size; | ||
33 | } | ||
34 | } | ||
35 | |||
36 | #endif | ||
diff --git a/arch/s390/pci/Makefile b/arch/s390/pci/Makefile index ab0827b6bc4b..f0f426a113ce 100644 --- a/arch/s390/pci/Makefile +++ b/arch/s390/pci/Makefile | |||
@@ -3,4 +3,4 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_PCI) += pci.o pci_dma.o pci_clp.o pci_msi.o \ | 5 | obj-$(CONFIG_PCI) += pci.o pci_dma.o pci_clp.o pci_msi.o \ |
6 | pci_sysfs.o pci_event.o | 6 | pci_sysfs.o pci_event.o pci_debug.o |
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 7ed38e5e3028..8fa416b8775f 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c | |||
@@ -98,6 +98,10 @@ EXPORT_SYMBOL_GPL(zpci_iomap_start); | |||
98 | static int __read_mostly aisb_max; | 98 | static int __read_mostly aisb_max; |
99 | 99 | ||
100 | static struct kmem_cache *zdev_irq_cache; | 100 | static struct kmem_cache *zdev_irq_cache; |
101 | static struct kmem_cache *zdev_fmb_cache; | ||
102 | |||
103 | debug_info_t *pci_debug_msg_id; | ||
104 | debug_info_t *pci_debug_err_id; | ||
101 | 105 | ||
102 | static inline int irq_to_msi_nr(unsigned int irq) | 106 | static inline int irq_to_msi_nr(unsigned int irq) |
103 | { | 107 | { |
@@ -216,6 +220,7 @@ struct mod_pci_args { | |||
216 | u64 base; | 220 | u64 base; |
217 | u64 limit; | 221 | u64 limit; |
218 | u64 iota; | 222 | u64 iota; |
223 | u64 fmb_addr; | ||
219 | }; | 224 | }; |
220 | 225 | ||
221 | static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args *args) | 226 | static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args *args) |
@@ -232,6 +237,7 @@ static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args | |||
232 | fib->pba = args->base; | 237 | fib->pba = args->base; |
233 | fib->pal = args->limit; | 238 | fib->pal = args->limit; |
234 | fib->iota = args->iota; | 239 | fib->iota = args->iota; |
240 | fib->fmb_addr = args->fmb_addr; | ||
235 | 241 | ||
236 | rc = mpcifc_instr(req, fib); | 242 | rc = mpcifc_instr(req, fib); |
237 | free_page((unsigned long) fib); | 243 | free_page((unsigned long) fib); |
@@ -242,7 +248,7 @@ static int mod_pci(struct zpci_dev *zdev, int fn, u8 dmaas, struct mod_pci_args | |||
242 | int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas, | 248 | int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas, |
243 | u64 base, u64 limit, u64 iota) | 249 | u64 base, u64 limit, u64 iota) |
244 | { | 250 | { |
245 | struct mod_pci_args args = { base, limit, iota }; | 251 | struct mod_pci_args args = { base, limit, iota, 0 }; |
246 | 252 | ||
247 | WARN_ON_ONCE(iota & 0x3fff); | 253 | WARN_ON_ONCE(iota & 0x3fff); |
248 | args.iota |= ZPCI_IOTA_RTTO_FLAG; | 254 | args.iota |= ZPCI_IOTA_RTTO_FLAG; |
@@ -252,7 +258,7 @@ int zpci_register_ioat(struct zpci_dev *zdev, u8 dmaas, | |||
252 | /* Modify PCI: Unregister I/O address translation parameters */ | 258 | /* Modify PCI: Unregister I/O address translation parameters */ |
253 | int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas) | 259 | int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas) |
254 | { | 260 | { |
255 | struct mod_pci_args args = { 0, 0, 0 }; | 261 | struct mod_pci_args args = { 0, 0, 0, 0 }; |
256 | 262 | ||
257 | return mod_pci(zdev, ZPCI_MOD_FC_DEREG_IOAT, dmaas, &args); | 263 | return mod_pci(zdev, ZPCI_MOD_FC_DEREG_IOAT, dmaas, &args); |
258 | } | 264 | } |
@@ -260,11 +266,46 @@ int zpci_unregister_ioat(struct zpci_dev *zdev, u8 dmaas) | |||
260 | /* Modify PCI: Unregister adapter interruptions */ | 266 | /* Modify PCI: Unregister adapter interruptions */ |
261 | static int zpci_unregister_airq(struct zpci_dev *zdev) | 267 | static int zpci_unregister_airq(struct zpci_dev *zdev) |
262 | { | 268 | { |
263 | struct mod_pci_args args = { 0, 0, 0 }; | 269 | struct mod_pci_args args = { 0, 0, 0, 0 }; |
264 | 270 | ||
265 | return mod_pci(zdev, ZPCI_MOD_FC_DEREG_INT, 0, &args); | 271 | return mod_pci(zdev, ZPCI_MOD_FC_DEREG_INT, 0, &args); |
266 | } | 272 | } |
267 | 273 | ||
274 | /* Modify PCI: Set PCI function measurement parameters */ | ||
275 | int zpci_fmb_enable_device(struct zpci_dev *zdev) | ||
276 | { | ||
277 | struct mod_pci_args args = { 0, 0, 0, 0 }; | ||
278 | |||
279 | if (zdev->fmb) | ||
280 | return -EINVAL; | ||
281 | |||
282 | zdev->fmb = kmem_cache_alloc(zdev_fmb_cache, GFP_KERNEL); | ||
283 | if (!zdev->fmb) | ||
284 | return -ENOMEM; | ||
285 | memset(zdev->fmb, 0, sizeof(*zdev->fmb)); | ||
286 | WARN_ON((u64) zdev->fmb & 0xf); | ||
287 | |||
288 | args.fmb_addr = virt_to_phys(zdev->fmb); | ||
289 | return mod_pci(zdev, ZPCI_MOD_FC_SET_MEASURE, 0, &args); | ||
290 | } | ||
291 | |||
292 | /* Modify PCI: Disable PCI function measurement */ | ||
293 | int zpci_fmb_disable_device(struct zpci_dev *zdev) | ||
294 | { | ||
295 | struct mod_pci_args args = { 0, 0, 0, 0 }; | ||
296 | int rc; | ||
297 | |||
298 | if (!zdev->fmb) | ||
299 | return -EINVAL; | ||
300 | |||
301 | /* Function measurement is disabled if fmb address is zero */ | ||
302 | rc = mod_pci(zdev, ZPCI_MOD_FC_SET_MEASURE, 0, &args); | ||
303 | |||
304 | kmem_cache_free(zdev_fmb_cache, zdev->fmb); | ||
305 | zdev->fmb = NULL; | ||
306 | return rc; | ||
307 | } | ||
308 | |||
268 | #define ZPCI_PCIAS_CFGSPC 15 | 309 | #define ZPCI_PCIAS_CFGSPC 15 |
269 | 310 | ||
270 | static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len) | 311 | static int zpci_cfg_load(struct zpci_dev *zdev, int offset, u32 *val, u8 len) |
@@ -633,6 +674,7 @@ static void zpci_remove_device(struct pci_dev *pdev) | |||
633 | dev_info(&pdev->dev, "Removing device %u\n", zdev->domain); | 674 | dev_info(&pdev->dev, "Removing device %u\n", zdev->domain); |
634 | zdev->state = ZPCI_FN_STATE_CONFIGURED; | 675 | zdev->state = ZPCI_FN_STATE_CONFIGURED; |
635 | zpci_dma_exit_device(zdev); | 676 | zpci_dma_exit_device(zdev); |
677 | zpci_fmb_disable_device(zdev); | ||
636 | zpci_sysfs_remove_device(&pdev->dev); | 678 | zpci_sysfs_remove_device(&pdev->dev); |
637 | zpci_unmap_resources(pdev); | 679 | zpci_unmap_resources(pdev); |
638 | list_del(&zdev->entry); /* can be called from init */ | 680 | list_del(&zdev->entry); /* can be called from init */ |
@@ -799,6 +841,16 @@ static void zpci_irq_exit(void) | |||
799 | kfree(bucket); | 841 | kfree(bucket); |
800 | } | 842 | } |
801 | 843 | ||
844 | void zpci_debug_info(struct zpci_dev *zdev, struct seq_file *m) | ||
845 | { | ||
846 | if (!zdev) | ||
847 | return; | ||
848 | |||
849 | seq_printf(m, "global irq retries: %u\n", atomic_read(&irq_retries)); | ||
850 | seq_printf(m, "aibv[0]:%016lx aibv[1]:%016lx aisb:%016lx\n", | ||
851 | get_imap(0)->aibv, get_imap(1)->aibv, *bucket->aisb); | ||
852 | } | ||
853 | |||
802 | static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size, | 854 | static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size, |
803 | unsigned long flags, int domain) | 855 | unsigned long flags, int domain) |
804 | { | 856 | { |
@@ -994,6 +1046,8 @@ int zpci_scan_device(struct zpci_dev *zdev) | |||
994 | goto out; | 1046 | goto out; |
995 | } | 1047 | } |
996 | 1048 | ||
1049 | zpci_debug_init_device(zdev); | ||
1050 | zpci_fmb_enable_device(zdev); | ||
997 | zpci_map_resources(zdev); | 1051 | zpci_map_resources(zdev); |
998 | pci_bus_add_devices(zdev->bus); | 1052 | pci_bus_add_devices(zdev->bus); |
999 | 1053 | ||
@@ -1020,6 +1074,11 @@ static int zpci_mem_init(void) | |||
1020 | if (!zdev_irq_cache) | 1074 | if (!zdev_irq_cache) |
1021 | goto error_zdev; | 1075 | goto error_zdev; |
1022 | 1076 | ||
1077 | zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb), | ||
1078 | 16, 0, NULL); | ||
1079 | if (!zdev_fmb_cache) | ||
1080 | goto error_fmb; | ||
1081 | |||
1023 | /* TODO: use realloc */ | 1082 | /* TODO: use realloc */ |
1024 | zpci_iomap_start = kzalloc(ZPCI_IOMAP_MAX_ENTRIES * sizeof(*zpci_iomap_start), | 1083 | zpci_iomap_start = kzalloc(ZPCI_IOMAP_MAX_ENTRIES * sizeof(*zpci_iomap_start), |
1025 | GFP_KERNEL); | 1084 | GFP_KERNEL); |
@@ -1028,6 +1087,8 @@ static int zpci_mem_init(void) | |||
1028 | return 0; | 1087 | return 0; |
1029 | 1088 | ||
1030 | error_iomap: | 1089 | error_iomap: |
1090 | kmem_cache_destroy(zdev_fmb_cache); | ||
1091 | error_fmb: | ||
1031 | kmem_cache_destroy(zdev_irq_cache); | 1092 | kmem_cache_destroy(zdev_irq_cache); |
1032 | error_zdev: | 1093 | error_zdev: |
1033 | return -ENOMEM; | 1094 | return -ENOMEM; |
@@ -1037,6 +1098,7 @@ static void zpci_mem_exit(void) | |||
1037 | { | 1098 | { |
1038 | kfree(zpci_iomap_start); | 1099 | kfree(zpci_iomap_start); |
1039 | kmem_cache_destroy(zdev_irq_cache); | 1100 | kmem_cache_destroy(zdev_irq_cache); |
1101 | kmem_cache_destroy(zdev_fmb_cache); | ||
1040 | } | 1102 | } |
1041 | 1103 | ||
1042 | unsigned int pci_probe = 1; | 1104 | unsigned int pci_probe = 1; |
@@ -1066,6 +1128,10 @@ static int __init pci_base_init(void) | |||
1066 | test_facility(69), test_facility(70), | 1128 | test_facility(69), test_facility(70), |
1067 | test_facility(71)); | 1129 | test_facility(71)); |
1068 | 1130 | ||
1131 | rc = zpci_debug_init(); | ||
1132 | if (rc) | ||
1133 | return rc; | ||
1134 | |||
1069 | rc = zpci_mem_init(); | 1135 | rc = zpci_mem_init(); |
1070 | if (rc) | 1136 | if (rc) |
1071 | goto out_mem; | 1137 | goto out_mem; |
@@ -1098,6 +1164,7 @@ out_irq: | |||
1098 | out_hash: | 1164 | out_hash: |
1099 | zpci_mem_exit(); | 1165 | zpci_mem_exit(); |
1100 | out_mem: | 1166 | out_mem: |
1167 | zpci_debug_exit(); | ||
1101 | return rc; | 1168 | return rc; |
1102 | } | 1169 | } |
1103 | subsys_initcall(pci_base_init); | 1170 | subsys_initcall(pci_base_init); |
diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c index 7f4ce8d874a4..2c847143cbd1 100644 --- a/arch/s390/pci/pci_clp.c +++ b/arch/s390/pci/pci_clp.c | |||
@@ -51,6 +51,7 @@ static void clp_store_query_pci_fngrp(struct zpci_dev *zdev, | |||
51 | zdev->tlb_refresh = response->refresh; | 51 | zdev->tlb_refresh = response->refresh; |
52 | zdev->dma_mask = response->dasm; | 52 | zdev->dma_mask = response->dasm; |
53 | zdev->msi_addr = response->msia; | 53 | zdev->msi_addr = response->msia; |
54 | zdev->fmb_update = response->mui; | ||
54 | 55 | ||
55 | pr_debug("Supported number of MSI vectors: %u\n", response->noi); | 56 | pr_debug("Supported number of MSI vectors: %u\n", response->noi); |
56 | switch (response->version) { | 57 | switch (response->version) { |
diff --git a/arch/s390/pci/pci_debug.c b/arch/s390/pci/pci_debug.c new file mode 100644 index 000000000000..a303c95346cb --- /dev/null +++ b/arch/s390/pci/pci_debug.c | |||
@@ -0,0 +1,193 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corp. 2012 | ||
3 | * | ||
4 | * Author(s): | ||
5 | * Jan Glauber <jang@linux.vnet.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #define COMPONENT "zPCI" | ||
9 | #define pr_fmt(fmt) COMPONENT ": " fmt | ||
10 | |||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/seq_file.h> | ||
13 | #include <linux/debugfs.h> | ||
14 | #include <linux/pci.h> | ||
15 | #include <asm/debug.h> | ||
16 | |||
17 | #include <asm/pci_dma.h> | ||
18 | |||
19 | static struct dentry *debugfs_root; | ||
20 | |||
21 | static char *pci_perf_names[] = { | ||
22 | /* hardware counters */ | ||
23 | "Load operations", | ||
24 | "Store operations", | ||
25 | "Store block operations", | ||
26 | "Refresh operations", | ||
27 | "DMA read bytes", | ||
28 | "DMA write bytes", | ||
29 | /* software counters */ | ||
30 | "Allocated pages", | ||
31 | "Mapped pages", | ||
32 | "Unmapped pages", | ||
33 | }; | ||
34 | |||
35 | static int pci_perf_show(struct seq_file *m, void *v) | ||
36 | { | ||
37 | struct zpci_dev *zdev = m->private; | ||
38 | u64 *stat; | ||
39 | int i; | ||
40 | |||
41 | if (!zdev) | ||
42 | return 0; | ||
43 | if (!zdev->fmb) | ||
44 | return seq_printf(m, "FMB statistics disabled\n"); | ||
45 | |||
46 | /* header */ | ||
47 | seq_printf(m, "FMB @ %p\n", zdev->fmb); | ||
48 | seq_printf(m, "Update interval: %u ms\n", zdev->fmb_update); | ||
49 | seq_printf(m, "Samples: %u\n", zdev->fmb->samples); | ||
50 | seq_printf(m, "Last update TOD: %Lx\n", zdev->fmb->last_update); | ||
51 | |||
52 | /* hardware counters */ | ||
53 | stat = (u64 *) &zdev->fmb->ld_ops; | ||
54 | for (i = 0; i < 4; i++) | ||
55 | seq_printf(m, "%26s:\t%llu\n", | ||
56 | pci_perf_names[i], *(stat + i)); | ||
57 | if (zdev->fmb->dma_valid) | ||
58 | for (i = 4; i < 6; i++) | ||
59 | seq_printf(m, "%26s:\t%llu\n", | ||
60 | pci_perf_names[i], *(stat + i)); | ||
61 | /* software counters */ | ||
62 | for (i = 6; i < ARRAY_SIZE(pci_perf_names); i++) | ||
63 | seq_printf(m, "%26s:\t%llu\n", | ||
64 | pci_perf_names[i], | ||
65 | atomic64_read((atomic64_t *) (stat + i))); | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static ssize_t pci_perf_seq_write(struct file *file, const char __user *ubuf, | ||
71 | size_t count, loff_t *off) | ||
72 | { | ||
73 | struct zpci_dev *zdev = ((struct seq_file *) file->private_data)->private; | ||
74 | unsigned long val; | ||
75 | int rc; | ||
76 | |||
77 | if (!zdev) | ||
78 | return 0; | ||
79 | |||
80 | rc = kstrtoul_from_user(ubuf, count, 10, &val); | ||
81 | if (rc) | ||
82 | return rc; | ||
83 | |||
84 | switch (val) { | ||
85 | case 0: | ||
86 | rc = zpci_fmb_disable_device(zdev); | ||
87 | if (rc) | ||
88 | return rc; | ||
89 | break; | ||
90 | case 1: | ||
91 | rc = zpci_fmb_enable_device(zdev); | ||
92 | if (rc) | ||
93 | return rc; | ||
94 | break; | ||
95 | } | ||
96 | return count; | ||
97 | } | ||
98 | |||
99 | static int pci_perf_seq_open(struct inode *inode, struct file *filp) | ||
100 | { | ||
101 | return single_open(filp, pci_perf_show, | ||
102 | filp->f_path.dentry->d_inode->i_private); | ||
103 | } | ||
104 | |||
105 | static const struct file_operations debugfs_pci_perf_fops = { | ||
106 | .open = pci_perf_seq_open, | ||
107 | .read = seq_read, | ||
108 | .write = pci_perf_seq_write, | ||
109 | .llseek = seq_lseek, | ||
110 | .release = single_release, | ||
111 | }; | ||
112 | |||
113 | static int pci_debug_show(struct seq_file *m, void *v) | ||
114 | { | ||
115 | struct zpci_dev *zdev = m->private; | ||
116 | |||
117 | zpci_debug_info(zdev, m); | ||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static int pci_debug_seq_open(struct inode *inode, struct file *filp) | ||
122 | { | ||
123 | return single_open(filp, pci_debug_show, | ||
124 | filp->f_path.dentry->d_inode->i_private); | ||
125 | } | ||
126 | |||
127 | static const struct file_operations debugfs_pci_debug_fops = { | ||
128 | .open = pci_debug_seq_open, | ||
129 | .read = seq_read, | ||
130 | .llseek = seq_lseek, | ||
131 | .release = single_release, | ||
132 | }; | ||
133 | |||
134 | void zpci_debug_init_device(struct zpci_dev *zdev) | ||
135 | { | ||
136 | zdev->debugfs_dev = debugfs_create_dir(dev_name(&zdev->pdev->dev), | ||
137 | debugfs_root); | ||
138 | if (IS_ERR(zdev->debugfs_dev)) | ||
139 | zdev->debugfs_dev = NULL; | ||
140 | |||
141 | zdev->debugfs_perf = debugfs_create_file("statistics", | ||
142 | S_IFREG | S_IRUGO | S_IWUSR, | ||
143 | zdev->debugfs_dev, zdev, | ||
144 | &debugfs_pci_perf_fops); | ||
145 | if (IS_ERR(zdev->debugfs_perf)) | ||
146 | zdev->debugfs_perf = NULL; | ||
147 | |||
148 | zdev->debugfs_debug = debugfs_create_file("debug", | ||
149 | S_IFREG | S_IRUGO | S_IWUSR, | ||
150 | zdev->debugfs_dev, zdev, | ||
151 | &debugfs_pci_debug_fops); | ||
152 | if (IS_ERR(zdev->debugfs_debug)) | ||
153 | zdev->debugfs_debug = NULL; | ||
154 | } | ||
155 | |||
156 | void zpci_debug_exit_device(struct zpci_dev *zdev) | ||
157 | { | ||
158 | debugfs_remove(zdev->debugfs_perf); | ||
159 | debugfs_remove(zdev->debugfs_debug); | ||
160 | debugfs_remove(zdev->debugfs_dev); | ||
161 | } | ||
162 | |||
163 | int __init zpci_debug_init(void) | ||
164 | { | ||
165 | /* event trace buffer */ | ||
166 | pci_debug_msg_id = debug_register("pci_msg", 16, 1, 16 * sizeof(long)); | ||
167 | if (!pci_debug_msg_id) | ||
168 | return -EINVAL; | ||
169 | debug_register_view(pci_debug_msg_id, &debug_sprintf_view); | ||
170 | debug_set_level(pci_debug_msg_id, 3); | ||
171 | zpci_dbg("Debug view initialized\n"); | ||
172 | |||
173 | /* error log */ | ||
174 | pci_debug_err_id = debug_register("pci_error", 2, 1, 16); | ||
175 | if (!pci_debug_err_id) | ||
176 | return -EINVAL; | ||
177 | debug_register_view(pci_debug_err_id, &debug_hex_ascii_view); | ||
178 | debug_set_level(pci_debug_err_id, 6); | ||
179 | zpci_err("Debug view initialized\n"); | ||
180 | |||
181 | debugfs_root = debugfs_create_dir("pci", NULL); | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | void zpci_debug_exit(void) | ||
186 | { | ||
187 | if (pci_debug_msg_id) | ||
188 | debug_unregister(pci_debug_msg_id); | ||
189 | if (pci_debug_err_id) | ||
190 | debug_unregister(pci_debug_err_id); | ||
191 | |||
192 | debugfs_remove(debugfs_root); | ||
193 | } | ||
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c index c64b4b294b0a..6138468b420f 100644 --- a/arch/s390/pci/pci_dma.c +++ b/arch/s390/pci/pci_dma.c | |||
@@ -291,8 +291,10 @@ static dma_addr_t s390_dma_map_pages(struct device *dev, struct page *page, | |||
291 | if (direction == DMA_NONE || direction == DMA_TO_DEVICE) | 291 | if (direction == DMA_NONE || direction == DMA_TO_DEVICE) |
292 | flags |= ZPCI_TABLE_PROTECTED; | 292 | flags |= ZPCI_TABLE_PROTECTED; |
293 | 293 | ||
294 | if (!dma_update_trans(zdev, pa, dma_addr, size, flags)) | 294 | if (!dma_update_trans(zdev, pa, dma_addr, size, flags)) { |
295 | atomic64_add(nr_pages, (atomic64_t *) &zdev->fmb->mapped_pages); | ||
295 | return dma_addr + offset; | 296 | return dma_addr + offset; |
297 | } | ||
296 | 298 | ||
297 | out_free: | 299 | out_free: |
298 | dma_free_iommu(zdev, iommu_page_index, nr_pages); | 300 | dma_free_iommu(zdev, iommu_page_index, nr_pages); |
@@ -315,6 +317,7 @@ static void s390_dma_unmap_pages(struct device *dev, dma_addr_t dma_addr, | |||
315 | ZPCI_TABLE_PROTECTED | ZPCI_PTE_INVALID)) | 317 | ZPCI_TABLE_PROTECTED | ZPCI_PTE_INVALID)) |
316 | dev_err(dev, "Failed to unmap addr: %Lx\n", dma_addr); | 318 | dev_err(dev, "Failed to unmap addr: %Lx\n", dma_addr); |
317 | 319 | ||
320 | atomic64_add(npages, (atomic64_t *) &zdev->fmb->unmapped_pages); | ||
318 | iommu_page_index = (dma_addr - zdev->start_dma) >> PAGE_SHIFT; | 321 | iommu_page_index = (dma_addr - zdev->start_dma) >> PAGE_SHIFT; |
319 | dma_free_iommu(zdev, iommu_page_index, npages); | 322 | dma_free_iommu(zdev, iommu_page_index, npages); |
320 | } | 323 | } |
@@ -323,6 +326,7 @@ static void *s390_dma_alloc(struct device *dev, size_t size, | |||
323 | dma_addr_t *dma_handle, gfp_t flag, | 326 | dma_addr_t *dma_handle, gfp_t flag, |
324 | struct dma_attrs *attrs) | 327 | struct dma_attrs *attrs) |
325 | { | 328 | { |
329 | struct zpci_dev *zdev = get_zdev(container_of(dev, struct pci_dev, dev)); | ||
326 | struct page *page; | 330 | struct page *page; |
327 | unsigned long pa; | 331 | unsigned long pa; |
328 | dma_addr_t map; | 332 | dma_addr_t map; |
@@ -331,6 +335,8 @@ static void *s390_dma_alloc(struct device *dev, size_t size, | |||
331 | page = alloc_pages(flag, get_order(size)); | 335 | page = alloc_pages(flag, get_order(size)); |
332 | if (!page) | 336 | if (!page) |
333 | return NULL; | 337 | return NULL; |
338 | |||
339 | atomic64_add(size / PAGE_SIZE, (atomic64_t *) &zdev->fmb->allocated_pages); | ||
334 | pa = page_to_phys(page); | 340 | pa = page_to_phys(page); |
335 | memset((void *) pa, 0, size); | 341 | memset((void *) pa, 0, size); |
336 | 342 | ||
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c index dbed8cd3370c..ec62e3a0dc09 100644 --- a/arch/s390/pci/pci_event.c +++ b/arch/s390/pci/pci_event.c | |||
@@ -45,6 +45,8 @@ static void zpci_event_log_err(struct zpci_ccdf_err *ccdf) | |||
45 | { | 45 | { |
46 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); | 46 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); |
47 | 47 | ||
48 | zpci_err("SEI error CCD:\n"); | ||
49 | zpci_err_hex(ccdf, sizeof(*ccdf)); | ||
48 | dev_err(&zdev->pdev->dev, "event code: 0x%x\n", ccdf->pec); | 50 | dev_err(&zdev->pdev->dev, "event code: 0x%x\n", ccdf->pec); |
49 | } | 51 | } |
50 | 52 | ||