diff options
Diffstat (limited to 'arch/s390/pci/pci.c')
-rw-r--r-- | arch/s390/pci/pci.c | 73 |
1 files changed, 70 insertions, 3 deletions
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); |