diff options
-rw-r--r-- | arch/s390/boot/Makefile | 4 | ||||
-rw-r--r-- | arch/s390/include/asm/ctl_reg.h | 2 | ||||
-rw-r--r-- | arch/s390/include/asm/eadm.h | 13 | ||||
-rw-r--r-- | arch/s390/include/asm/pci.h | 6 | ||||
-rw-r--r-- | arch/s390/include/asm/sclp.h | 3 | ||||
-rw-r--r-- | arch/s390/include/asm/setup.h | 3 | ||||
-rw-r--r-- | arch/s390/kernel/crash_dump.c | 22 | ||||
-rw-r--r-- | arch/s390/kernel/early.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/setup.c | 7 | ||||
-rw-r--r-- | arch/s390/pci/pci.c | 202 | ||||
-rw-r--r-- | arch/s390/pci/pci_clp.c | 8 | ||||
-rw-r--r-- | arch/s390/pci/pci_event.c | 79 | ||||
-rw-r--r-- | drivers/s390/block/scm_blk.c | 24 | ||||
-rw-r--r-- | drivers/s390/block/scm_blk_cluster.c | 2 | ||||
-rw-r--r-- | drivers/s390/char/Makefile | 3 | ||||
-rw-r--r-- | drivers/s390/char/fs3270.c | 1 | ||||
-rw-r--r-- | drivers/s390/char/sclp.h | 5 | ||||
-rw-r--r-- | drivers/s390/char/sclp_cmd.c | 180 | ||||
-rw-r--r-- | drivers/s390/char/sclp_early.c | 264 | ||||
-rw-r--r-- | drivers/s390/char/sclp_sdias.c | 78 | ||||
-rw-r--r-- | drivers/s390/char/sclp_sdias.h | 46 | ||||
-rw-r--r-- | drivers/s390/char/zcore.c | 22 | ||||
-rw-r--r-- | drivers/s390/cio/eadm_sch.c | 10 | ||||
-rw-r--r-- | drivers/s390/cio/scm.c | 45 |
24 files changed, 562 insertions, 469 deletions
diff --git a/arch/s390/boot/Makefile b/arch/s390/boot/Makefile index f2737a005afc..9a42ecec5647 100644 --- a/arch/s390/boot/Makefile +++ b/arch/s390/boot/Makefile | |||
@@ -21,6 +21,6 @@ $(obj)/bzImage: $(obj)/compressed/vmlinux FORCE | |||
21 | $(obj)/compressed/vmlinux: FORCE | 21 | $(obj)/compressed/vmlinux: FORCE |
22 | $(Q)$(MAKE) $(build)=$(obj)/compressed $@ | 22 | $(Q)$(MAKE) $(build)=$(obj)/compressed $@ |
23 | 23 | ||
24 | install: $(CONFIGURE) $(obj)/image | 24 | install: $(CONFIGURE) $(obj)/bzImage |
25 | sh -x $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/image \ | 25 | sh -x $(srctree)/$(obj)/install.sh $(KERNELRELEASE) $(obj)/bzImage \ |
26 | System.map "$(INSTALL_PATH)" | 26 | System.map "$(INSTALL_PATH)" |
diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h index 9b69c0befdca..4e63f1a13600 100644 --- a/arch/s390/include/asm/ctl_reg.h +++ b/arch/s390/include/asm/ctl_reg.h | |||
@@ -7,6 +7,8 @@ | |||
7 | #ifndef __ASM_CTL_REG_H | 7 | #ifndef __ASM_CTL_REG_H |
8 | #define __ASM_CTL_REG_H | 8 | #define __ASM_CTL_REG_H |
9 | 9 | ||
10 | #include <linux/bug.h> | ||
11 | |||
10 | #ifdef CONFIG_64BIT | 12 | #ifdef CONFIG_64BIT |
11 | # define __CTL_LOAD "lctlg" | 13 | # define __CTL_LOAD "lctlg" |
12 | # define __CTL_STORE "stctg" | 14 | # define __CTL_STORE "stctg" |
diff --git a/arch/s390/include/asm/eadm.h b/arch/s390/include/asm/eadm.h index dc9200ca32ed..67026300c88e 100644 --- a/arch/s390/include/asm/eadm.h +++ b/arch/s390/include/asm/eadm.h | |||
@@ -111,18 +111,7 @@ struct scm_driver { | |||
111 | int scm_driver_register(struct scm_driver *scmdrv); | 111 | int scm_driver_register(struct scm_driver *scmdrv); |
112 | void scm_driver_unregister(struct scm_driver *scmdrv); | 112 | void scm_driver_unregister(struct scm_driver *scmdrv); |
113 | 113 | ||
114 | int scm_start_aob(struct aob *aob); | 114 | int eadm_start_aob(struct aob *aob); |
115 | void scm_irq_handler(struct aob *aob, int error); | 115 | void scm_irq_handler(struct aob *aob, int error); |
116 | 116 | ||
117 | struct eadm_ops { | ||
118 | int (*eadm_start) (struct aob *aob); | ||
119 | struct module *owner; | ||
120 | }; | ||
121 | |||
122 | int scm_get_ref(void); | ||
123 | void scm_put_ref(void); | ||
124 | |||
125 | void register_eadm_ops(struct eadm_ops *ops); | ||
126 | void unregister_eadm_ops(struct eadm_ops *ops); | ||
127 | |||
128 | #endif /* _ASM_S390_EADM_H */ | 117 | #endif /* _ASM_S390_EADM_H */ |
diff --git a/arch/s390/include/asm/pci.h b/arch/s390/include/asm/pci.h index 1cc185da9d38..c129ab2ac731 100644 --- a/arch/s390/include/asm/pci.h +++ b/arch/s390/include/asm/pci.h | |||
@@ -63,9 +63,10 @@ enum zpci_state { | |||
63 | }; | 63 | }; |
64 | 64 | ||
65 | struct zpci_bar_struct { | 65 | struct zpci_bar_struct { |
66 | struct resource *res; /* bus resource */ | ||
66 | u32 val; /* bar start & 3 flag bits */ | 67 | u32 val; /* bar start & 3 flag bits */ |
67 | u8 size; /* order 2 exponent */ | ||
68 | u16 map_idx; /* index into bar mapping array */ | 68 | u16 map_idx; /* index into bar mapping array */ |
69 | u8 size; /* order 2 exponent */ | ||
69 | }; | 70 | }; |
70 | 71 | ||
71 | /* Private data per function */ | 72 | /* Private data per function */ |
@@ -97,6 +98,7 @@ struct zpci_dev { | |||
97 | unsigned long iommu_pages; | 98 | unsigned long iommu_pages; |
98 | unsigned int next_bit; | 99 | unsigned int next_bit; |
99 | 100 | ||
101 | char res_name[16]; | ||
100 | struct zpci_bar_struct bars[PCI_BAR_COUNT]; | 102 | struct zpci_bar_struct bars[PCI_BAR_COUNT]; |
101 | 103 | ||
102 | u64 start_dma; /* Start of available DMA addresses */ | 104 | u64 start_dma; /* Start of available DMA addresses */ |
@@ -122,12 +124,10 @@ static inline bool zdev_enabled(struct zpci_dev *zdev) | |||
122 | Prototypes | 124 | Prototypes |
123 | ----------------------------------------------------------------------------- */ | 125 | ----------------------------------------------------------------------------- */ |
124 | /* Base stuff */ | 126 | /* Base stuff */ |
125 | struct zpci_dev *zpci_alloc_device(void); | ||
126 | int zpci_create_device(struct zpci_dev *); | 127 | int zpci_create_device(struct zpci_dev *); |
127 | int zpci_enable_device(struct zpci_dev *); | 128 | int zpci_enable_device(struct zpci_dev *); |
128 | int zpci_disable_device(struct zpci_dev *); | 129 | int zpci_disable_device(struct zpci_dev *); |
129 | void zpci_stop_device(struct zpci_dev *); | 130 | void zpci_stop_device(struct zpci_dev *); |
130 | void zpci_free_device(struct zpci_dev *); | ||
131 | int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64); | 131 | int zpci_register_ioat(struct zpci_dev *, u8, u64, u64, u64); |
132 | int zpci_unregister_ioat(struct zpci_dev *, u8); | 132 | int zpci_unregister_ioat(struct zpci_dev *, u8); |
133 | 133 | ||
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h index 7dc7f9c63b65..30ef748bc161 100644 --- a/arch/s390/include/asm/sclp.h +++ b/arch/s390/include/asm/sclp.h | |||
@@ -43,7 +43,6 @@ struct sclp_cpu_info { | |||
43 | int sclp_get_cpu_info(struct sclp_cpu_info *info); | 43 | int sclp_get_cpu_info(struct sclp_cpu_info *info); |
44 | int sclp_cpu_configure(u8 cpu); | 44 | int sclp_cpu_configure(u8 cpu); |
45 | int sclp_cpu_deconfigure(u8 cpu); | 45 | int sclp_cpu_deconfigure(u8 cpu); |
46 | void sclp_facilities_detect(void); | ||
47 | unsigned long long sclp_get_rnmax(void); | 46 | unsigned long long sclp_get_rnmax(void); |
48 | unsigned long long sclp_get_rzm(void); | 47 | unsigned long long sclp_get_rzm(void); |
49 | int sclp_sdias_blk_count(void); | 48 | int sclp_sdias_blk_count(void); |
@@ -57,5 +56,7 @@ bool sclp_has_vt220(void); | |||
57 | int sclp_pci_configure(u32 fid); | 56 | int sclp_pci_configure(u32 fid); |
58 | int sclp_pci_deconfigure(u32 fid); | 57 | int sclp_pci_deconfigure(u32 fid); |
59 | int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode); | 58 | int memcpy_hsa(void *dest, unsigned long src, size_t count, int mode); |
59 | unsigned long sclp_get_hsa_size(void); | ||
60 | void sclp_early_detect(void); | ||
60 | 61 | ||
61 | #endif /* _ASM_S390_SCLP_H */ | 62 | #endif /* _ASM_S390_SCLP_H */ |
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h index df802ee14af6..94cfbe442f12 100644 --- a/arch/s390/include/asm/setup.h +++ b/arch/s390/include/asm/setup.h | |||
@@ -107,9 +107,6 @@ void create_mem_hole(struct mem_chunk mem_chunk[], unsigned long addr, | |||
107 | #define MACHINE_HAS_RRBM (S390_lowcore.machine_flags & MACHINE_FLAG_RRBM) | 107 | #define MACHINE_HAS_RRBM (S390_lowcore.machine_flags & MACHINE_FLAG_RRBM) |
108 | #endif /* CONFIG_64BIT */ | 108 | #endif /* CONFIG_64BIT */ |
109 | 109 | ||
110 | #define ZFCPDUMP_HSA_SIZE (32UL<<20) | ||
111 | #define ZFCPDUMP_HSA_SIZE_MAX (64UL<<20) | ||
112 | |||
113 | /* | 110 | /* |
114 | * Console mode. Override with conmode= | 111 | * Console mode. Override with conmode= |
115 | */ | 112 | */ |
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index f45b2ab0cb81..d7658c4b2ed5 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c | |||
@@ -95,7 +95,7 @@ static void *elfcorehdr_newmem; | |||
95 | /* | 95 | /* |
96 | * Copy one page from zfcpdump "oldmem" | 96 | * Copy one page from zfcpdump "oldmem" |
97 | * | 97 | * |
98 | * For pages below ZFCPDUMP_HSA_SIZE memory from the HSA is copied. Otherwise | 98 | * For pages below HSA size memory from the HSA is copied. Otherwise |
99 | * real memory copy is used. | 99 | * real memory copy is used. |
100 | */ | 100 | */ |
101 | static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize, | 101 | static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize, |
@@ -103,7 +103,7 @@ static ssize_t copy_oldmem_page_zfcpdump(char *buf, size_t csize, | |||
103 | { | 103 | { |
104 | int rc; | 104 | int rc; |
105 | 105 | ||
106 | if (src < ZFCPDUMP_HSA_SIZE) { | 106 | if (src < sclp_get_hsa_size()) { |
107 | rc = memcpy_hsa(buf, src, csize, userbuf); | 107 | rc = memcpy_hsa(buf, src, csize, userbuf); |
108 | } else { | 108 | } else { |
109 | if (userbuf) | 109 | if (userbuf) |
@@ -188,18 +188,19 @@ static int remap_oldmem_pfn_range_kdump(struct vm_area_struct *vma, | |||
188 | /* | 188 | /* |
189 | * Remap "oldmem" for zfcpdump | 189 | * Remap "oldmem" for zfcpdump |
190 | * | 190 | * |
191 | * We only map available memory above ZFCPDUMP_HSA_SIZE. Memory below | 191 | * We only map available memory above HSA size. Memory below HSA size |
192 | * ZFCPDUMP_HSA_SIZE is read on demand using the copy_oldmem_page() function. | 192 | * is read on demand using the copy_oldmem_page() function. |
193 | */ | 193 | */ |
194 | static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma, | 194 | static int remap_oldmem_pfn_range_zfcpdump(struct vm_area_struct *vma, |
195 | unsigned long from, | 195 | unsigned long from, |
196 | unsigned long pfn, | 196 | unsigned long pfn, |
197 | unsigned long size, pgprot_t prot) | 197 | unsigned long size, pgprot_t prot) |
198 | { | 198 | { |
199 | unsigned long hsa_end = sclp_get_hsa_size(); | ||
199 | unsigned long size_hsa; | 200 | unsigned long size_hsa; |
200 | 201 | ||
201 | if (pfn < ZFCPDUMP_HSA_SIZE >> PAGE_SHIFT) { | 202 | if (pfn < hsa_end >> PAGE_SHIFT) { |
202 | size_hsa = min(size, ZFCPDUMP_HSA_SIZE - (pfn << PAGE_SHIFT)); | 203 | size_hsa = min(size, hsa_end - (pfn << PAGE_SHIFT)); |
203 | if (size == size_hsa) | 204 | if (size == size_hsa) |
204 | return 0; | 205 | return 0; |
205 | size -= size_hsa; | 206 | size -= size_hsa; |
@@ -238,9 +239,9 @@ int copy_from_oldmem(void *dest, void *src, size_t count) | |||
238 | return rc; | 239 | return rc; |
239 | } | 240 | } |
240 | } else { | 241 | } else { |
241 | if ((unsigned long) src < ZFCPDUMP_HSA_SIZE) { | 242 | unsigned long hsa_end = sclp_get_hsa_size(); |
242 | copied = min(count, | 243 | if ((unsigned long) src < hsa_end) { |
243 | ZFCPDUMP_HSA_SIZE - (unsigned long) src); | 244 | copied = min(count, hsa_end - (unsigned long) src); |
244 | rc = memcpy_hsa(dest, (unsigned long) src, copied, 0); | 245 | rc = memcpy_hsa(dest, (unsigned long) src, copied, 0); |
245 | if (rc) | 246 | if (rc) |
246 | return rc; | 247 | return rc; |
@@ -580,6 +581,9 @@ int elfcorehdr_alloc(unsigned long long *addr, unsigned long long *size) | |||
580 | /* If elfcorehdr= has been passed via cmdline, we use that one */ | 581 | /* If elfcorehdr= has been passed via cmdline, we use that one */ |
581 | if (elfcorehdr_addr != ELFCORE_ADDR_MAX) | 582 | if (elfcorehdr_addr != ELFCORE_ADDR_MAX) |
582 | return 0; | 583 | return 0; |
584 | /* If we cannot get HSA size for zfcpdump return error */ | ||
585 | if (ipl_info.type == IPL_TYPE_FCP_DUMP && !sclp_get_hsa_size()) | ||
586 | return -ENODEV; | ||
583 | mem_chunk_cnt = get_mem_chunk_cnt(); | 587 | mem_chunk_cnt = get_mem_chunk_cnt(); |
584 | 588 | ||
585 | alloc_size = 0x1000 + get_cpu_cnt() * 0x300 + | 589 | alloc_size = 0x1000 + get_cpu_cnt() * 0x300 + |
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 96543ac400a7..fca20b5fe79e 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -483,7 +483,7 @@ void __init startup_init(void) | |||
483 | detect_diag44(); | 483 | detect_diag44(); |
484 | detect_machine_facilities(); | 484 | detect_machine_facilities(); |
485 | setup_topology(); | 485 | setup_topology(); |
486 | sclp_facilities_detect(); | 486 | sclp_early_detect(); |
487 | #ifdef CONFIG_DYNAMIC_FTRACE | 487 | #ifdef CONFIG_DYNAMIC_FTRACE |
488 | S390_lowcore.ftrace_func = (unsigned long)ftrace_caller; | 488 | S390_lowcore.ftrace_func = (unsigned long)ftrace_caller; |
489 | #endif | 489 | #endif |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index ffe1c53264a7..4444875266ee 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -471,8 +471,9 @@ static void __init setup_memory_end(void) | |||
471 | 471 | ||
472 | 472 | ||
473 | #ifdef CONFIG_ZFCPDUMP | 473 | #ifdef CONFIG_ZFCPDUMP |
474 | if (ipl_info.type == IPL_TYPE_FCP_DUMP && !OLDMEM_BASE) { | 474 | if (ipl_info.type == IPL_TYPE_FCP_DUMP && |
475 | memory_end = ZFCPDUMP_HSA_SIZE; | 475 | !OLDMEM_BASE && sclp_get_hsa_size()) { |
476 | memory_end = sclp_get_hsa_size(); | ||
476 | memory_end_set = 1; | 477 | memory_end_set = 1; |
477 | } | 478 | } |
478 | #endif | 479 | #endif |
@@ -586,7 +587,7 @@ static unsigned long __init find_crash_base(unsigned long crash_size, | |||
586 | crash_base = (chunk->addr + chunk->size) - crash_size; | 587 | crash_base = (chunk->addr + chunk->size) - crash_size; |
587 | if (crash_base < crash_size) | 588 | if (crash_base < crash_size) |
588 | continue; | 589 | continue; |
589 | if (crash_base < ZFCPDUMP_HSA_SIZE_MAX) | 590 | if (crash_base < sclp_get_hsa_size()) |
590 | continue; | 591 | continue; |
591 | if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE) | 592 | if (crash_base < (unsigned long) INITRD_START + INITRD_SIZE) |
592 | continue; | 593 | continue; |
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index 0c9a17780e4b..bf7c73d71eef 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c | |||
@@ -530,20 +530,6 @@ static void zpci_unmap_resources(struct zpci_dev *zdev) | |||
530 | } | 530 | } |
531 | } | 531 | } |
532 | 532 | ||
533 | struct zpci_dev *zpci_alloc_device(void) | ||
534 | { | ||
535 | struct zpci_dev *zdev; | ||
536 | |||
537 | /* Alloc memory for our private pci device data */ | ||
538 | zdev = kzalloc(sizeof(*zdev), GFP_KERNEL); | ||
539 | return zdev ? : ERR_PTR(-ENOMEM); | ||
540 | } | ||
541 | |||
542 | void zpci_free_device(struct zpci_dev *zdev) | ||
543 | { | ||
544 | kfree(zdev); | ||
545 | } | ||
546 | |||
547 | int pcibios_add_platform_entries(struct pci_dev *pdev) | 533 | int pcibios_add_platform_entries(struct pci_dev *pdev) |
548 | { | 534 | { |
549 | return zpci_sysfs_add_device(&pdev->dev); | 535 | return zpci_sysfs_add_device(&pdev->dev); |
@@ -579,37 +565,6 @@ static void zpci_irq_exit(void) | |||
579 | unregister_adapter_interrupt(&zpci_airq); | 565 | unregister_adapter_interrupt(&zpci_airq); |
580 | } | 566 | } |
581 | 567 | ||
582 | static struct resource *zpci_alloc_bus_resource(unsigned long start, unsigned long size, | ||
583 | unsigned long flags, int domain) | ||
584 | { | ||
585 | struct resource *r; | ||
586 | char *name; | ||
587 | int rc; | ||
588 | |||
589 | r = kzalloc(sizeof(*r), GFP_KERNEL); | ||
590 | if (!r) | ||
591 | return ERR_PTR(-ENOMEM); | ||
592 | r->start = start; | ||
593 | r->end = r->start + size - 1; | ||
594 | r->flags = flags; | ||
595 | r->parent = &iomem_resource; | ||
596 | name = kmalloc(18, GFP_KERNEL); | ||
597 | if (!name) { | ||
598 | kfree(r); | ||
599 | return ERR_PTR(-ENOMEM); | ||
600 | } | ||
601 | sprintf(name, "PCI Bus: %04x:%02x", domain, ZPCI_BUS_NR); | ||
602 | r->name = name; | ||
603 | |||
604 | rc = request_resource(&iomem_resource, r); | ||
605 | if (rc) { | ||
606 | kfree(r->name); | ||
607 | kfree(r); | ||
608 | return ERR_PTR(-ENOMEM); | ||
609 | } | ||
610 | return r; | ||
611 | } | ||
612 | |||
613 | static int zpci_alloc_iomap(struct zpci_dev *zdev) | 568 | static int zpci_alloc_iomap(struct zpci_dev *zdev) |
614 | { | 569 | { |
615 | int entry; | 570 | int entry; |
@@ -633,6 +588,82 @@ static void zpci_free_iomap(struct zpci_dev *zdev, int entry) | |||
633 | spin_unlock(&zpci_iomap_lock); | 588 | spin_unlock(&zpci_iomap_lock); |
634 | } | 589 | } |
635 | 590 | ||
591 | static struct resource *__alloc_res(struct zpci_dev *zdev, unsigned long start, | ||
592 | unsigned long size, unsigned long flags) | ||
593 | { | ||
594 | struct resource *r; | ||
595 | |||
596 | r = kzalloc(sizeof(*r), GFP_KERNEL); | ||
597 | if (!r) | ||
598 | return NULL; | ||
599 | |||
600 | r->start = start; | ||
601 | r->end = r->start + size - 1; | ||
602 | r->flags = flags; | ||
603 | r->name = zdev->res_name; | ||
604 | |||
605 | if (request_resource(&iomem_resource, r)) { | ||
606 | kfree(r); | ||
607 | return NULL; | ||
608 | } | ||
609 | return r; | ||
610 | } | ||
611 | |||
612 | static int zpci_setup_bus_resources(struct zpci_dev *zdev, | ||
613 | struct list_head *resources) | ||
614 | { | ||
615 | unsigned long addr, size, flags; | ||
616 | struct resource *res; | ||
617 | int i, entry; | ||
618 | |||
619 | snprintf(zdev->res_name, sizeof(zdev->res_name), | ||
620 | "PCI Bus %04x:%02x", zdev->domain, ZPCI_BUS_NR); | ||
621 | |||
622 | for (i = 0; i < PCI_BAR_COUNT; i++) { | ||
623 | if (!zdev->bars[i].size) | ||
624 | continue; | ||
625 | entry = zpci_alloc_iomap(zdev); | ||
626 | if (entry < 0) | ||
627 | return entry; | ||
628 | zdev->bars[i].map_idx = entry; | ||
629 | |||
630 | /* only MMIO is supported */ | ||
631 | flags = IORESOURCE_MEM; | ||
632 | if (zdev->bars[i].val & 8) | ||
633 | flags |= IORESOURCE_PREFETCH; | ||
634 | if (zdev->bars[i].val & 4) | ||
635 | flags |= IORESOURCE_MEM_64; | ||
636 | |||
637 | addr = ZPCI_IOMAP_ADDR_BASE + ((u64) entry << 48); | ||
638 | |||
639 | size = 1UL << zdev->bars[i].size; | ||
640 | |||
641 | res = __alloc_res(zdev, addr, size, flags); | ||
642 | if (!res) { | ||
643 | zpci_free_iomap(zdev, entry); | ||
644 | return -ENOMEM; | ||
645 | } | ||
646 | zdev->bars[i].res = res; | ||
647 | pci_add_resource(resources, res); | ||
648 | } | ||
649 | |||
650 | return 0; | ||
651 | } | ||
652 | |||
653 | static void zpci_cleanup_bus_resources(struct zpci_dev *zdev) | ||
654 | { | ||
655 | int i; | ||
656 | |||
657 | for (i = 0; i < PCI_BAR_COUNT; i++) { | ||
658 | if (!zdev->bars[i].size) | ||
659 | continue; | ||
660 | |||
661 | zpci_free_iomap(zdev, zdev->bars[i].map_idx); | ||
662 | release_resource(zdev->bars[i].res); | ||
663 | kfree(zdev->bars[i].res); | ||
664 | } | ||
665 | } | ||
666 | |||
636 | int pcibios_add_device(struct pci_dev *pdev) | 667 | int pcibios_add_device(struct pci_dev *pdev) |
637 | { | 668 | { |
638 | struct zpci_dev *zdev = get_zdev(pdev); | 669 | struct zpci_dev *zdev = get_zdev(pdev); |
@@ -729,52 +760,6 @@ struct dev_pm_ops pcibios_pm_ops = { | |||
729 | }; | 760 | }; |
730 | #endif /* CONFIG_HIBERNATE_CALLBACKS */ | 761 | #endif /* CONFIG_HIBERNATE_CALLBACKS */ |
731 | 762 | ||
732 | static int zpci_scan_bus(struct zpci_dev *zdev) | ||
733 | { | ||
734 | struct resource *res; | ||
735 | LIST_HEAD(resources); | ||
736 | int i; | ||
737 | |||
738 | /* allocate mapping entry for each used bar */ | ||
739 | for (i = 0; i < PCI_BAR_COUNT; i++) { | ||
740 | unsigned long addr, size, flags; | ||
741 | int entry; | ||
742 | |||
743 | if (!zdev->bars[i].size) | ||
744 | continue; | ||
745 | entry = zpci_alloc_iomap(zdev); | ||
746 | if (entry < 0) | ||
747 | return entry; | ||
748 | zdev->bars[i].map_idx = entry; | ||
749 | |||
750 | /* only MMIO is supported */ | ||
751 | flags = IORESOURCE_MEM; | ||
752 | if (zdev->bars[i].val & 8) | ||
753 | flags |= IORESOURCE_PREFETCH; | ||
754 | if (zdev->bars[i].val & 4) | ||
755 | flags |= IORESOURCE_MEM_64; | ||
756 | |||
757 | addr = ZPCI_IOMAP_ADDR_BASE + ((u64) entry << 48); | ||
758 | |||
759 | size = 1UL << zdev->bars[i].size; | ||
760 | |||
761 | res = zpci_alloc_bus_resource(addr, size, flags, zdev->domain); | ||
762 | if (IS_ERR(res)) { | ||
763 | zpci_free_iomap(zdev, entry); | ||
764 | return PTR_ERR(res); | ||
765 | } | ||
766 | pci_add_resource(&resources, res); | ||
767 | } | ||
768 | |||
769 | zdev->bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops, | ||
770 | zdev, &resources); | ||
771 | if (!zdev->bus) | ||
772 | return -EIO; | ||
773 | |||
774 | zdev->bus->max_bus_speed = zdev->max_bus_speed; | ||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | static int zpci_alloc_domain(struct zpci_dev *zdev) | 763 | static int zpci_alloc_domain(struct zpci_dev *zdev) |
779 | { | 764 | { |
780 | spin_lock(&zpci_domain_lock); | 765 | spin_lock(&zpci_domain_lock); |
@@ -795,6 +780,41 @@ static void zpci_free_domain(struct zpci_dev *zdev) | |||
795 | spin_unlock(&zpci_domain_lock); | 780 | spin_unlock(&zpci_domain_lock); |
796 | } | 781 | } |
797 | 782 | ||
783 | void pcibios_remove_bus(struct pci_bus *bus) | ||
784 | { | ||
785 | struct zpci_dev *zdev = get_zdev_by_bus(bus); | ||
786 | |||
787 | zpci_exit_slot(zdev); | ||
788 | zpci_cleanup_bus_resources(zdev); | ||
789 | zpci_free_domain(zdev); | ||
790 | |||
791 | spin_lock(&zpci_list_lock); | ||
792 | list_del(&zdev->entry); | ||
793 | spin_unlock(&zpci_list_lock); | ||
794 | |||
795 | kfree(zdev); | ||
796 | } | ||
797 | |||
798 | static int zpci_scan_bus(struct zpci_dev *zdev) | ||
799 | { | ||
800 | LIST_HEAD(resources); | ||
801 | int ret; | ||
802 | |||
803 | ret = zpci_setup_bus_resources(zdev, &resources); | ||
804 | if (ret) | ||
805 | return ret; | ||
806 | |||
807 | zdev->bus = pci_scan_root_bus(NULL, ZPCI_BUS_NR, &pci_root_ops, | ||
808 | zdev, &resources); | ||
809 | if (!zdev->bus) { | ||
810 | zpci_cleanup_bus_resources(zdev); | ||
811 | return -EIO; | ||
812 | } | ||
813 | |||
814 | zdev->bus->max_bus_speed = zdev->max_bus_speed; | ||
815 | return 0; | ||
816 | } | ||
817 | |||
798 | int zpci_enable_device(struct zpci_dev *zdev) | 818 | int zpci_enable_device(struct zpci_dev *zdev) |
799 | { | 819 | { |
800 | int rc; | 820 | int rc; |
diff --git a/arch/s390/pci/pci_clp.c b/arch/s390/pci/pci_clp.c index 84147984224a..c747394029ee 100644 --- a/arch/s390/pci/pci_clp.c +++ b/arch/s390/pci/pci_clp.c | |||
@@ -155,9 +155,9 @@ int clp_add_pci_device(u32 fid, u32 fh, int configured) | |||
155 | int rc; | 155 | int rc; |
156 | 156 | ||
157 | zpci_dbg(3, "add fid:%x, fh:%x, c:%d\n", fid, fh, configured); | 157 | zpci_dbg(3, "add fid:%x, fh:%x, c:%d\n", fid, fh, configured); |
158 | zdev = zpci_alloc_device(); | 158 | zdev = kzalloc(sizeof(*zdev), GFP_KERNEL); |
159 | if (IS_ERR(zdev)) | 159 | if (!zdev) |
160 | return PTR_ERR(zdev); | 160 | return -ENOMEM; |
161 | 161 | ||
162 | zdev->fh = fh; | 162 | zdev->fh = fh; |
163 | zdev->fid = fid; | 163 | zdev->fid = fid; |
@@ -178,7 +178,7 @@ int clp_add_pci_device(u32 fid, u32 fh, int configured) | |||
178 | return 0; | 178 | return 0; |
179 | 179 | ||
180 | error: | 180 | error: |
181 | zpci_free_device(zdev); | 181 | kfree(zdev); |
182 | return rc; | 182 | return rc; |
183 | } | 183 | } |
184 | 184 | ||
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c index 278e671ec9ac..800f064b0da7 100644 --- a/arch/s390/pci/pci_event.c +++ b/arch/s390/pci/pci_event.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/pci.h> | 12 | #include <linux/pci.h> |
13 | #include <asm/pci_debug.h> | 13 | #include <asm/pci_debug.h> |
14 | #include <asm/sclp.h> | ||
14 | 15 | ||
15 | /* Content Code Description for PCI Function Error */ | 16 | /* Content Code Description for PCI Function Error */ |
16 | struct zpci_ccdf_err { | 17 | struct zpci_ccdf_err { |
@@ -42,10 +43,27 @@ struct zpci_ccdf_avail { | |||
42 | u16 pec; /* PCI event code */ | 43 | u16 pec; /* PCI event code */ |
43 | } __packed; | 44 | } __packed; |
44 | 45 | ||
45 | static void zpci_event_log_avail(struct zpci_ccdf_avail *ccdf) | 46 | void zpci_event_error(void *data) |
46 | { | 47 | { |
48 | struct zpci_ccdf_err *ccdf = data; | ||
49 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); | ||
50 | |||
51 | zpci_err("error CCDF:\n"); | ||
52 | zpci_err_hex(ccdf, sizeof(*ccdf)); | ||
53 | |||
54 | if (!zdev) | ||
55 | return; | ||
56 | |||
57 | pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n", | ||
58 | pci_name(zdev->pdev), ccdf->pec, ccdf->fid); | ||
59 | } | ||
60 | |||
61 | void zpci_event_availability(void *data) | ||
62 | { | ||
63 | struct zpci_ccdf_avail *ccdf = data; | ||
47 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); | 64 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); |
48 | struct pci_dev *pdev = zdev ? zdev->pdev : NULL; | 65 | struct pci_dev *pdev = zdev ? zdev->pdev : NULL; |
66 | int ret; | ||
49 | 67 | ||
50 | pr_info("%s: Event 0x%x reconfigured PCI function 0x%x\n", | 68 | pr_info("%s: Event 0x%x reconfigured PCI function 0x%x\n", |
51 | pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid); | 69 | pdev ? pci_name(pdev) : "n/a", ccdf->pec, ccdf->fid); |
@@ -53,36 +71,47 @@ static void zpci_event_log_avail(struct zpci_ccdf_avail *ccdf) | |||
53 | zpci_err_hex(ccdf, sizeof(*ccdf)); | 71 | zpci_err_hex(ccdf, sizeof(*ccdf)); |
54 | 72 | ||
55 | switch (ccdf->pec) { | 73 | switch (ccdf->pec) { |
56 | case 0x0301: | 74 | case 0x0301: /* Standby -> Configured */ |
57 | zpci_enable_device(zdev); | 75 | if (!zdev || zdev->state == ZPCI_FN_STATE_CONFIGURED) |
76 | break; | ||
77 | zdev->state = ZPCI_FN_STATE_CONFIGURED; | ||
78 | ret = zpci_enable_device(zdev); | ||
79 | if (ret) | ||
80 | break; | ||
81 | pci_rescan_bus(zdev->bus); | ||
58 | break; | 82 | break; |
59 | case 0x0302: | 83 | case 0x0302: /* Reserved -> Standby */ |
60 | clp_add_pci_device(ccdf->fid, ccdf->fh, 0); | 84 | clp_add_pci_device(ccdf->fid, ccdf->fh, 0); |
61 | break; | 85 | break; |
62 | case 0x0306: | 86 | case 0x0303: /* Deconfiguration requested */ |
87 | if (pdev) | ||
88 | pci_stop_and_remove_bus_device(pdev); | ||
89 | |||
90 | ret = zpci_disable_device(zdev); | ||
91 | if (ret) | ||
92 | break; | ||
93 | |||
94 | ret = sclp_pci_deconfigure(zdev->fid); | ||
95 | zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret); | ||
96 | if (!ret) | ||
97 | zdev->state = ZPCI_FN_STATE_STANDBY; | ||
98 | |||
99 | break; | ||
100 | case 0x0304: /* Configured -> Standby */ | ||
101 | if (pdev) | ||
102 | pci_stop_and_remove_bus_device(pdev); | ||
103 | |||
104 | zpci_disable_device(zdev); | ||
105 | zdev->state = ZPCI_FN_STATE_STANDBY; | ||
106 | break; | ||
107 | case 0x0306: /* 0x308 or 0x302 for multiple devices */ | ||
63 | clp_rescan_pci_devices(); | 108 | clp_rescan_pci_devices(); |
64 | break; | 109 | break; |
110 | case 0x0308: /* Standby -> Reserved */ | ||
111 | pci_stop_root_bus(zdev->bus); | ||
112 | pci_remove_root_bus(zdev->bus); | ||
113 | break; | ||
65 | default: | 114 | default: |
66 | break; | 115 | break; |
67 | } | 116 | } |
68 | } | 117 | } |
69 | |||
70 | void zpci_event_error(void *data) | ||
71 | { | ||
72 | struct zpci_ccdf_err *ccdf = data; | ||
73 | struct zpci_dev *zdev = get_zdev_by_fid(ccdf->fid); | ||
74 | |||
75 | zpci_err("error CCDF:\n"); | ||
76 | zpci_err_hex(ccdf, sizeof(*ccdf)); | ||
77 | |||
78 | if (!zdev) | ||
79 | return; | ||
80 | |||
81 | pr_err("%s: Event 0x%x reports an error for PCI function 0x%x\n", | ||
82 | pci_name(zdev->pdev), ccdf->pec, ccdf->fid); | ||
83 | } | ||
84 | |||
85 | void zpci_event_availability(void *data) | ||
86 | { | ||
87 | zpci_event_log_avail(data); | ||
88 | } | ||
diff --git a/drivers/s390/block/scm_blk.c b/drivers/s390/block/scm_blk.c index 548209a9c43c..d0ab5019d885 100644 --- a/drivers/s390/block/scm_blk.c +++ b/drivers/s390/block/scm_blk.c | |||
@@ -118,22 +118,6 @@ static void scm_request_done(struct scm_request *scmrq) | |||
118 | spin_unlock_irqrestore(&list_lock, flags); | 118 | spin_unlock_irqrestore(&list_lock, flags); |
119 | } | 119 | } |
120 | 120 | ||
121 | static int scm_open(struct block_device *blkdev, fmode_t mode) | ||
122 | { | ||
123 | return scm_get_ref(); | ||
124 | } | ||
125 | |||
126 | static void scm_release(struct gendisk *gendisk, fmode_t mode) | ||
127 | { | ||
128 | scm_put_ref(); | ||
129 | } | ||
130 | |||
131 | static const struct block_device_operations scm_blk_devops = { | ||
132 | .owner = THIS_MODULE, | ||
133 | .open = scm_open, | ||
134 | .release = scm_release, | ||
135 | }; | ||
136 | |||
137 | static bool scm_permit_request(struct scm_blk_dev *bdev, struct request *req) | 121 | static bool scm_permit_request(struct scm_blk_dev *bdev, struct request *req) |
138 | { | 122 | { |
139 | return rq_data_dir(req) != WRITE || bdev->state != SCM_WR_PROHIBIT; | 123 | return rq_data_dir(req) != WRITE || bdev->state != SCM_WR_PROHIBIT; |
@@ -256,7 +240,7 @@ static void scm_blk_request(struct request_queue *rq) | |||
256 | atomic_inc(&bdev->queued_reqs); | 240 | atomic_inc(&bdev->queued_reqs); |
257 | blk_start_request(req); | 241 | blk_start_request(req); |
258 | 242 | ||
259 | ret = scm_start_aob(scmrq->aob); | 243 | ret = eadm_start_aob(scmrq->aob); |
260 | if (ret) { | 244 | if (ret) { |
261 | SCM_LOG(5, "no subchannel"); | 245 | SCM_LOG(5, "no subchannel"); |
262 | scm_request_requeue(scmrq); | 246 | scm_request_requeue(scmrq); |
@@ -320,7 +304,7 @@ static void scm_blk_handle_error(struct scm_request *scmrq) | |||
320 | } | 304 | } |
321 | 305 | ||
322 | restart: | 306 | restart: |
323 | if (!scm_start_aob(scmrq->aob)) | 307 | if (!eadm_start_aob(scmrq->aob)) |
324 | return; | 308 | return; |
325 | 309 | ||
326 | requeue: | 310 | requeue: |
@@ -363,6 +347,10 @@ static void scm_blk_tasklet(struct scm_blk_dev *bdev) | |||
363 | blk_run_queue(bdev->rq); | 347 | blk_run_queue(bdev->rq); |
364 | } | 348 | } |
365 | 349 | ||
350 | static const struct block_device_operations scm_blk_devops = { | ||
351 | .owner = THIS_MODULE, | ||
352 | }; | ||
353 | |||
366 | int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev) | 354 | int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev) |
367 | { | 355 | { |
368 | struct request_queue *rq; | 356 | struct request_queue *rq; |
diff --git a/drivers/s390/block/scm_blk_cluster.c b/drivers/s390/block/scm_blk_cluster.c index c0d102e3a48b..27f930cd657f 100644 --- a/drivers/s390/block/scm_blk_cluster.c +++ b/drivers/s390/block/scm_blk_cluster.c | |||
@@ -187,7 +187,7 @@ bool scm_need_cluster_request(struct scm_request *scmrq) | |||
187 | void scm_initiate_cluster_request(struct scm_request *scmrq) | 187 | void scm_initiate_cluster_request(struct scm_request *scmrq) |
188 | { | 188 | { |
189 | scm_prepare_cluster_request(scmrq); | 189 | scm_prepare_cluster_request(scmrq); |
190 | if (scm_start_aob(scmrq->aob)) | 190 | if (eadm_start_aob(scmrq->aob)) |
191 | scm_request_requeue(scmrq); | 191 | scm_request_requeue(scmrq); |
192 | } | 192 | } |
193 | 193 | ||
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index 17821a026c9c..b69ab17f13fa 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile | |||
@@ -3,7 +3,8 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ | 5 | obj-y += ctrlchar.o keyboard.o defkeymap.o sclp.o sclp_rw.o sclp_quiesce.o \ |
6 | sclp_cmd.o sclp_config.o sclp_cpi_sys.o sclp_ocf.o sclp_ctl.o | 6 | sclp_cmd.o sclp_config.o sclp_cpi_sys.o sclp_ocf.o sclp_ctl.o \ |
7 | sclp_early.o | ||
7 | 8 | ||
8 | obj-$(CONFIG_TN3270) += raw3270.o | 9 | obj-$(CONFIG_TN3270) += raw3270.o |
9 | obj-$(CONFIG_TN3270_CONSOLE) += con3270.o | 10 | obj-$(CONFIG_TN3270_CONSOLE) += con3270.o |
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index f93cc32eb818..71e974738014 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c | |||
@@ -564,6 +564,7 @@ static void __exit | |||
564 | fs3270_exit(void) | 564 | fs3270_exit(void) |
565 | { | 565 | { |
566 | raw3270_unregister_notifier(&fs3270_notifier); | 566 | raw3270_unregister_notifier(&fs3270_notifier); |
567 | device_destroy(class3270, MKDEV(IBM_FS3270_MAJOR, 0)); | ||
567 | __unregister_chrdev(IBM_FS3270_MAJOR, 0, 1, "fs3270"); | 568 | __unregister_chrdev(IBM_FS3270_MAJOR, 0, 1, "fs3270"); |
568 | } | 569 | } |
569 | 570 | ||
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 40d1406289ed..6fbe09686d18 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h | |||
@@ -99,6 +99,7 @@ struct init_sccb { | |||
99 | } __attribute__((packed)); | 99 | } __attribute__((packed)); |
100 | 100 | ||
101 | extern u64 sclp_facilities; | 101 | extern u64 sclp_facilities; |
102 | |||
102 | #define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL) | 103 | #define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL) |
103 | #define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL) | 104 | #define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL) |
104 | #define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL) | 105 | #define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL) |
@@ -179,6 +180,10 @@ void sclp_sdias_exit(void); | |||
179 | extern int sclp_console_pages; | 180 | extern int sclp_console_pages; |
180 | extern int sclp_console_drop; | 181 | extern int sclp_console_drop; |
181 | extern unsigned long sclp_console_full; | 182 | extern unsigned long sclp_console_full; |
183 | extern u8 sclp_fac84; | ||
184 | extern unsigned long long sclp_rzm; | ||
185 | extern unsigned long long sclp_rnmax; | ||
186 | extern __initdata int sclp_early_read_info_sccb_valid; | ||
182 | 187 | ||
183 | /* useful inlines */ | 188 | /* useful inlines */ |
184 | 189 | ||
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 77df9cb00688..eaa21d542c5c 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c | |||
@@ -28,168 +28,6 @@ | |||
28 | 28 | ||
29 | #include "sclp.h" | 29 | #include "sclp.h" |
30 | 30 | ||
31 | #define SCLP_CMDW_READ_SCP_INFO 0x00020001 | ||
32 | #define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 | ||
33 | |||
34 | struct read_info_sccb { | ||
35 | struct sccb_header header; /* 0-7 */ | ||
36 | u16 rnmax; /* 8-9 */ | ||
37 | u8 rnsize; /* 10 */ | ||
38 | u8 _reserved0[24 - 11]; /* 11-15 */ | ||
39 | u8 loadparm[8]; /* 24-31 */ | ||
40 | u8 _reserved1[48 - 32]; /* 32-47 */ | ||
41 | u64 facilities; /* 48-55 */ | ||
42 | u8 _reserved2[84 - 56]; /* 56-83 */ | ||
43 | u8 fac84; /* 84 */ | ||
44 | u8 fac85; /* 85 */ | ||
45 | u8 _reserved3[91 - 86]; /* 86-90 */ | ||
46 | u8 flags; /* 91 */ | ||
47 | u8 _reserved4[100 - 92]; /* 92-99 */ | ||
48 | u32 rnsize2; /* 100-103 */ | ||
49 | u64 rnmax2; /* 104-111 */ | ||
50 | u8 _reserved5[4096 - 112]; /* 112-4095 */ | ||
51 | } __attribute__((packed, aligned(PAGE_SIZE))); | ||
52 | |||
53 | static struct init_sccb __initdata early_event_mask_sccb __aligned(PAGE_SIZE); | ||
54 | static struct read_info_sccb __initdata early_read_info_sccb; | ||
55 | static int __initdata early_read_info_sccb_valid; | ||
56 | |||
57 | u64 sclp_facilities; | ||
58 | static u8 sclp_fac84; | ||
59 | static unsigned long long rzm; | ||
60 | static unsigned long long rnmax; | ||
61 | |||
62 | static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) | ||
63 | { | ||
64 | int rc; | ||
65 | |||
66 | __ctl_set_bit(0, 9); | ||
67 | rc = sclp_service_call(cmd, sccb); | ||
68 | if (rc) | ||
69 | goto out; | ||
70 | __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | | ||
71 | PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT); | ||
72 | local_irq_disable(); | ||
73 | out: | ||
74 | /* Contents of the sccb might have changed. */ | ||
75 | barrier(); | ||
76 | __ctl_clear_bit(0, 9); | ||
77 | return rc; | ||
78 | } | ||
79 | |||
80 | static void __init sclp_read_info_early(void) | ||
81 | { | ||
82 | int rc; | ||
83 | int i; | ||
84 | struct read_info_sccb *sccb; | ||
85 | sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, | ||
86 | SCLP_CMDW_READ_SCP_INFO}; | ||
87 | |||
88 | sccb = &early_read_info_sccb; | ||
89 | for (i = 0; i < ARRAY_SIZE(commands); i++) { | ||
90 | do { | ||
91 | memset(sccb, 0, sizeof(*sccb)); | ||
92 | sccb->header.length = sizeof(*sccb); | ||
93 | sccb->header.function_code = 0x80; | ||
94 | sccb->header.control_mask[2] = 0x80; | ||
95 | rc = sclp_cmd_sync_early(commands[i], sccb); | ||
96 | } while (rc == -EBUSY); | ||
97 | |||
98 | if (rc) | ||
99 | break; | ||
100 | if (sccb->header.response_code == 0x10) { | ||
101 | early_read_info_sccb_valid = 1; | ||
102 | break; | ||
103 | } | ||
104 | if (sccb->header.response_code != 0x1f0) | ||
105 | break; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static void __init sclp_event_mask_early(void) | ||
110 | { | ||
111 | struct init_sccb *sccb = &early_event_mask_sccb; | ||
112 | int rc; | ||
113 | |||
114 | do { | ||
115 | memset(sccb, 0, sizeof(*sccb)); | ||
116 | sccb->header.length = sizeof(*sccb); | ||
117 | sccb->mask_length = sizeof(sccb_mask_t); | ||
118 | rc = sclp_cmd_sync_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); | ||
119 | } while (rc == -EBUSY); | ||
120 | } | ||
121 | |||
122 | void __init sclp_facilities_detect(void) | ||
123 | { | ||
124 | struct read_info_sccb *sccb; | ||
125 | |||
126 | sclp_read_info_early(); | ||
127 | if (!early_read_info_sccb_valid) | ||
128 | return; | ||
129 | |||
130 | sccb = &early_read_info_sccb; | ||
131 | sclp_facilities = sccb->facilities; | ||
132 | sclp_fac84 = sccb->fac84; | ||
133 | if (sccb->fac85 & 0x02) | ||
134 | S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; | ||
135 | rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; | ||
136 | rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; | ||
137 | rzm <<= 20; | ||
138 | |||
139 | sclp_event_mask_early(); | ||
140 | } | ||
141 | |||
142 | bool __init sclp_has_linemode(void) | ||
143 | { | ||
144 | struct init_sccb *sccb = &early_event_mask_sccb; | ||
145 | |||
146 | if (sccb->header.response_code != 0x20) | ||
147 | return 0; | ||
148 | if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK))) | ||
149 | return 0; | ||
150 | if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) | ||
151 | return 0; | ||
152 | return 1; | ||
153 | } | ||
154 | |||
155 | bool __init sclp_has_vt220(void) | ||
156 | { | ||
157 | struct init_sccb *sccb = &early_event_mask_sccb; | ||
158 | |||
159 | if (sccb->header.response_code != 0x20) | ||
160 | return 0; | ||
161 | if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) | ||
162 | return 1; | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | unsigned long long sclp_get_rnmax(void) | ||
167 | { | ||
168 | return rnmax; | ||
169 | } | ||
170 | |||
171 | unsigned long long sclp_get_rzm(void) | ||
172 | { | ||
173 | return rzm; | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * This function will be called after sclp_facilities_detect(), which gets | ||
178 | * called from early.c code. Therefore the sccb should have valid contents. | ||
179 | */ | ||
180 | void __init sclp_get_ipl_info(struct sclp_ipl_info *info) | ||
181 | { | ||
182 | struct read_info_sccb *sccb; | ||
183 | |||
184 | if (!early_read_info_sccb_valid) | ||
185 | return; | ||
186 | sccb = &early_read_info_sccb; | ||
187 | info->is_valid = 1; | ||
188 | if (sccb->flags & 0x2) | ||
189 | info->has_dump = 1; | ||
190 | memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN); | ||
191 | } | ||
192 | |||
193 | static void sclp_sync_callback(struct sclp_req *req, void *data) | 31 | static void sclp_sync_callback(struct sclp_req *req, void *data) |
194 | { | 32 | { |
195 | struct completion *completion = data; | 33 | struct completion *completion = data; |
@@ -356,14 +194,14 @@ struct assign_storage_sccb { | |||
356 | 194 | ||
357 | int arch_get_memory_phys_device(unsigned long start_pfn) | 195 | int arch_get_memory_phys_device(unsigned long start_pfn) |
358 | { | 196 | { |
359 | if (!rzm) | 197 | if (!sclp_rzm) |
360 | return 0; | 198 | return 0; |
361 | return PFN_PHYS(start_pfn) >> ilog2(rzm); | 199 | return PFN_PHYS(start_pfn) >> ilog2(sclp_rzm); |
362 | } | 200 | } |
363 | 201 | ||
364 | static unsigned long long rn2addr(u16 rn) | 202 | static unsigned long long rn2addr(u16 rn) |
365 | { | 203 | { |
366 | return (unsigned long long) (rn - 1) * rzm; | 204 | return (unsigned long long) (rn - 1) * sclp_rzm; |
367 | } | 205 | } |
368 | 206 | ||
369 | static int do_assign_storage(sclp_cmdw_t cmd, u16 rn) | 207 | static int do_assign_storage(sclp_cmdw_t cmd, u16 rn) |
@@ -404,7 +242,7 @@ static int sclp_assign_storage(u16 rn) | |||
404 | if (rc) | 242 | if (rc) |
405 | return rc; | 243 | return rc; |
406 | start = rn2addr(rn); | 244 | start = rn2addr(rn); |
407 | storage_key_init_range(start, start + rzm); | 245 | storage_key_init_range(start, start + sclp_rzm); |
408 | return 0; | 246 | return 0; |
409 | } | 247 | } |
410 | 248 | ||
@@ -462,7 +300,7 @@ static int sclp_mem_change_state(unsigned long start, unsigned long size, | |||
462 | istart = rn2addr(incr->rn); | 300 | istart = rn2addr(incr->rn); |
463 | if (start + size - 1 < istart) | 301 | if (start + size - 1 < istart) |
464 | break; | 302 | break; |
465 | if (start > istart + rzm - 1) | 303 | if (start > istart + sclp_rzm - 1) |
466 | continue; | 304 | continue; |
467 | if (online) | 305 | if (online) |
468 | rc |= sclp_assign_storage(incr->rn); | 306 | rc |= sclp_assign_storage(incr->rn); |
@@ -526,7 +364,7 @@ static void __init add_memory_merged(u16 rn) | |||
526 | if (!first_rn) | 364 | if (!first_rn) |
527 | goto skip_add; | 365 | goto skip_add; |
528 | start = rn2addr(first_rn); | 366 | start = rn2addr(first_rn); |
529 | size = (unsigned long long ) num * rzm; | 367 | size = (unsigned long long) num * sclp_rzm; |
530 | if (start >= VMEM_MAX_PHYS) | 368 | if (start >= VMEM_MAX_PHYS) |
531 | goto skip_add; | 369 | goto skip_add; |
532 | if (start + size > VMEM_MAX_PHYS) | 370 | if (start + size > VMEM_MAX_PHYS) |
@@ -574,7 +412,7 @@ static void __init insert_increment(u16 rn, int standby, int assigned) | |||
574 | } | 412 | } |
575 | if (!assigned) | 413 | if (!assigned) |
576 | new_incr->rn = last_rn + 1; | 414 | new_incr->rn = last_rn + 1; |
577 | if (new_incr->rn > rnmax) { | 415 | if (new_incr->rn > sclp_rnmax) { |
578 | kfree(new_incr); | 416 | kfree(new_incr); |
579 | return; | 417 | return; |
580 | } | 418 | } |
@@ -617,7 +455,7 @@ static int __init sclp_detect_standby_memory(void) | |||
617 | 455 | ||
618 | if (OLDMEM_BASE) /* No standby memory in kdump mode */ | 456 | if (OLDMEM_BASE) /* No standby memory in kdump mode */ |
619 | return 0; | 457 | return 0; |
620 | if (!early_read_info_sccb_valid) | 458 | if (!sclp_early_read_info_sccb_valid) |
621 | return 0; | 459 | return 0; |
622 | if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL) | 460 | if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL) |
623 | return 0; | 461 | return 0; |
@@ -661,7 +499,7 @@ static int __init sclp_detect_standby_memory(void) | |||
661 | } | 499 | } |
662 | if (rc || list_empty(&sclp_mem_list)) | 500 | if (rc || list_empty(&sclp_mem_list)) |
663 | goto out; | 501 | goto out; |
664 | for (i = 1; i <= rnmax - assigned; i++) | 502 | for (i = 1; i <= sclp_rnmax - assigned; i++) |
665 | insert_increment(0, 1, 0); | 503 | insert_increment(0, 1, 0); |
666 | rc = register_memory_notifier(&sclp_mem_nb); | 504 | rc = register_memory_notifier(&sclp_mem_nb); |
667 | if (rc) | 505 | if (rc) |
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c new file mode 100644 index 000000000000..f7aa080e9b28 --- /dev/null +++ b/drivers/s390/char/sclp_early.c | |||
@@ -0,0 +1,264 @@ | |||
1 | /* | ||
2 | * SCLP early driver | ||
3 | * | ||
4 | * Copyright IBM Corp. 2013 | ||
5 | */ | ||
6 | |||
7 | #define KMSG_COMPONENT "sclp_early" | ||
8 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
9 | |||
10 | #include <asm/ctl_reg.h> | ||
11 | #include <asm/sclp.h> | ||
12 | #include <asm/ipl.h> | ||
13 | #include "sclp_sdias.h" | ||
14 | #include "sclp.h" | ||
15 | |||
16 | #define SCLP_CMDW_READ_SCP_INFO 0x00020001 | ||
17 | #define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 | ||
18 | |||
19 | struct read_info_sccb { | ||
20 | struct sccb_header header; /* 0-7 */ | ||
21 | u16 rnmax; /* 8-9 */ | ||
22 | u8 rnsize; /* 10 */ | ||
23 | u8 _reserved0[24 - 11]; /* 11-15 */ | ||
24 | u8 loadparm[8]; /* 24-31 */ | ||
25 | u8 _reserved1[48 - 32]; /* 32-47 */ | ||
26 | u64 facilities; /* 48-55 */ | ||
27 | u8 _reserved2[84 - 56]; /* 56-83 */ | ||
28 | u8 fac84; /* 84 */ | ||
29 | u8 fac85; /* 85 */ | ||
30 | u8 _reserved3[91 - 86]; /* 86-90 */ | ||
31 | u8 flags; /* 91 */ | ||
32 | u8 _reserved4[100 - 92]; /* 92-99 */ | ||
33 | u32 rnsize2; /* 100-103 */ | ||
34 | u64 rnmax2; /* 104-111 */ | ||
35 | u8 _reserved5[4096 - 112]; /* 112-4095 */ | ||
36 | } __packed __aligned(PAGE_SIZE); | ||
37 | |||
38 | static __initdata struct init_sccb early_event_mask_sccb __aligned(PAGE_SIZE); | ||
39 | static __initdata struct read_info_sccb early_read_info_sccb; | ||
40 | static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE); | ||
41 | static unsigned long sclp_hsa_size; | ||
42 | |||
43 | __initdata int sclp_early_read_info_sccb_valid; | ||
44 | u64 sclp_facilities; | ||
45 | u8 sclp_fac84; | ||
46 | unsigned long long sclp_rzm; | ||
47 | unsigned long long sclp_rnmax; | ||
48 | |||
49 | static int __init sclp_cmd_sync_early(sclp_cmdw_t cmd, void *sccb) | ||
50 | { | ||
51 | int rc; | ||
52 | |||
53 | __ctl_set_bit(0, 9); | ||
54 | rc = sclp_service_call(cmd, sccb); | ||
55 | if (rc) | ||
56 | goto out; | ||
57 | __load_psw_mask(PSW_DEFAULT_KEY | PSW_MASK_BASE | PSW_MASK_EA | | ||
58 | PSW_MASK_BA | PSW_MASK_EXT | PSW_MASK_WAIT); | ||
59 | local_irq_disable(); | ||
60 | out: | ||
61 | /* Contents of the sccb might have changed. */ | ||
62 | barrier(); | ||
63 | __ctl_clear_bit(0, 9); | ||
64 | return rc; | ||
65 | } | ||
66 | |||
67 | static void __init sclp_read_info_early(void) | ||
68 | { | ||
69 | int rc; | ||
70 | int i; | ||
71 | struct read_info_sccb *sccb; | ||
72 | sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, | ||
73 | SCLP_CMDW_READ_SCP_INFO}; | ||
74 | |||
75 | sccb = &early_read_info_sccb; | ||
76 | for (i = 0; i < ARRAY_SIZE(commands); i++) { | ||
77 | do { | ||
78 | memset(sccb, 0, sizeof(*sccb)); | ||
79 | sccb->header.length = sizeof(*sccb); | ||
80 | sccb->header.function_code = 0x80; | ||
81 | sccb->header.control_mask[2] = 0x80; | ||
82 | rc = sclp_cmd_sync_early(commands[i], sccb); | ||
83 | } while (rc == -EBUSY); | ||
84 | |||
85 | if (rc) | ||
86 | break; | ||
87 | if (sccb->header.response_code == 0x10) { | ||
88 | sclp_early_read_info_sccb_valid = 1; | ||
89 | break; | ||
90 | } | ||
91 | if (sccb->header.response_code != 0x1f0) | ||
92 | break; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | static void __init sclp_facilities_detect(void) | ||
97 | { | ||
98 | struct read_info_sccb *sccb; | ||
99 | |||
100 | sclp_read_info_early(); | ||
101 | if (!sclp_early_read_info_sccb_valid) | ||
102 | return; | ||
103 | |||
104 | sccb = &early_read_info_sccb; | ||
105 | sclp_facilities = sccb->facilities; | ||
106 | sclp_fac84 = sccb->fac84; | ||
107 | if (sccb->fac85 & 0x02) | ||
108 | S390_lowcore.machine_flags |= MACHINE_FLAG_ESOP; | ||
109 | sclp_rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; | ||
110 | sclp_rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; | ||
111 | sclp_rzm <<= 20; | ||
112 | } | ||
113 | |||
114 | bool __init sclp_has_linemode(void) | ||
115 | { | ||
116 | struct init_sccb *sccb = &early_event_mask_sccb; | ||
117 | |||
118 | if (sccb->header.response_code != 0x20) | ||
119 | return 0; | ||
120 | if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK))) | ||
121 | return 0; | ||
122 | if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) | ||
123 | return 0; | ||
124 | return 1; | ||
125 | } | ||
126 | |||
127 | bool __init sclp_has_vt220(void) | ||
128 | { | ||
129 | struct init_sccb *sccb = &early_event_mask_sccb; | ||
130 | |||
131 | if (sccb->header.response_code != 0x20) | ||
132 | return 0; | ||
133 | if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) | ||
134 | return 1; | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | unsigned long long sclp_get_rnmax(void) | ||
139 | { | ||
140 | return sclp_rnmax; | ||
141 | } | ||
142 | |||
143 | unsigned long long sclp_get_rzm(void) | ||
144 | { | ||
145 | return sclp_rzm; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * This function will be called after sclp_facilities_detect(), which gets | ||
150 | * called from early.c code. Therefore the sccb should have valid contents. | ||
151 | */ | ||
152 | void __init sclp_get_ipl_info(struct sclp_ipl_info *info) | ||
153 | { | ||
154 | struct read_info_sccb *sccb; | ||
155 | |||
156 | if (!sclp_early_read_info_sccb_valid) | ||
157 | return; | ||
158 | sccb = &early_read_info_sccb; | ||
159 | info->is_valid = 1; | ||
160 | if (sccb->flags & 0x2) | ||
161 | info->has_dump = 1; | ||
162 | memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN); | ||
163 | } | ||
164 | |||
165 | static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb) | ||
166 | { | ||
167 | int rc; | ||
168 | |||
169 | do { | ||
170 | rc = sclp_cmd_sync_early(cmd, sccb); | ||
171 | } while (rc == -EBUSY); | ||
172 | |||
173 | if (rc) | ||
174 | return -EIO; | ||
175 | if (((struct sccb_header *) sccb)->response_code != 0x0020) | ||
176 | return -EIO; | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static void __init sccb_init_eq_size(struct sdias_sccb *sccb) | ||
181 | { | ||
182 | memset(sccb, 0, sizeof(*sccb)); | ||
183 | |||
184 | sccb->hdr.length = sizeof(*sccb); | ||
185 | sccb->evbuf.hdr.length = sizeof(struct sdias_evbuf); | ||
186 | sccb->evbuf.hdr.type = EVTYP_SDIAS; | ||
187 | sccb->evbuf.event_qual = SDIAS_EQ_SIZE; | ||
188 | sccb->evbuf.data_id = SDIAS_DI_FCP_DUMP; | ||
189 | sccb->evbuf.event_id = 4712; | ||
190 | sccb->evbuf.dbs = 1; | ||
191 | } | ||
192 | |||
193 | static int __init sclp_set_event_mask(unsigned long receive_mask, | ||
194 | unsigned long send_mask) | ||
195 | { | ||
196 | struct init_sccb *sccb = (void *) &sccb_early; | ||
197 | |||
198 | memset(sccb, 0, sizeof(*sccb)); | ||
199 | sccb->header.length = sizeof(*sccb); | ||
200 | sccb->mask_length = sizeof(sccb_mask_t); | ||
201 | sccb->receive_mask = receive_mask; | ||
202 | sccb->send_mask = send_mask; | ||
203 | return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); | ||
204 | } | ||
205 | |||
206 | static long __init sclp_hsa_size_init(void) | ||
207 | { | ||
208 | struct sdias_sccb *sccb = (void *) &sccb_early; | ||
209 | |||
210 | sccb_init_eq_size(sccb); | ||
211 | if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb)) | ||
212 | return -EIO; | ||
213 | if (sccb->evbuf.blk_cnt != 0) | ||
214 | return (sccb->evbuf.blk_cnt - 1) * PAGE_SIZE; | ||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static long __init sclp_hsa_copy_wait(void) | ||
219 | { | ||
220 | struct sccb_header *sccb = (void *) &sccb_early; | ||
221 | |||
222 | memset(sccb, 0, PAGE_SIZE); | ||
223 | sccb->length = PAGE_SIZE; | ||
224 | if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb)) | ||
225 | return -EIO; | ||
226 | return (((struct sdias_sccb *) sccb)->evbuf.blk_cnt - 1) * PAGE_SIZE; | ||
227 | } | ||
228 | |||
229 | unsigned long sclp_get_hsa_size(void) | ||
230 | { | ||
231 | return sclp_hsa_size; | ||
232 | } | ||
233 | |||
234 | static void __init sclp_hsa_size_detect(void) | ||
235 | { | ||
236 | long size; | ||
237 | |||
238 | /* First try synchronous interface (LPAR) */ | ||
239 | if (sclp_set_event_mask(0, 0x40000010)) | ||
240 | return; | ||
241 | size = sclp_hsa_size_init(); | ||
242 | if (size < 0) | ||
243 | return; | ||
244 | if (size != 0) | ||
245 | goto out; | ||
246 | /* Then try asynchronous interface (z/VM) */ | ||
247 | if (sclp_set_event_mask(0x00000010, 0x40000010)) | ||
248 | return; | ||
249 | size = sclp_hsa_size_init(); | ||
250 | if (size < 0) | ||
251 | return; | ||
252 | size = sclp_hsa_copy_wait(); | ||
253 | if (size < 0) | ||
254 | return; | ||
255 | out: | ||
256 | sclp_hsa_size = size; | ||
257 | } | ||
258 | |||
259 | void __init sclp_early_detect(void) | ||
260 | { | ||
261 | sclp_facilities_detect(); | ||
262 | sclp_hsa_size_detect(); | ||
263 | sclp_set_event_mask(0, 0); | ||
264 | } | ||
diff --git a/drivers/s390/char/sclp_sdias.c b/drivers/s390/char/sclp_sdias.c index b1032931a1c4..561a0414b352 100644 --- a/drivers/s390/char/sclp_sdias.c +++ b/drivers/s390/char/sclp_sdias.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Sclp "store data in absolut storage" | 2 | * SCLP "store data in absolute storage" |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2003, 2007 | 4 | * Copyright IBM Corp. 2003, 2013 |
5 | * Author(s): Michael Holzheu | 5 | * Author(s): Michael Holzheu |
6 | */ | 6 | */ |
7 | 7 | ||
@@ -14,6 +14,7 @@ | |||
14 | #include <asm/debug.h> | 14 | #include <asm/debug.h> |
15 | #include <asm/ipl.h> | 15 | #include <asm/ipl.h> |
16 | 16 | ||
17 | #include "sclp_sdias.h" | ||
17 | #include "sclp.h" | 18 | #include "sclp.h" |
18 | #include "sclp_rw.h" | 19 | #include "sclp_rw.h" |
19 | 20 | ||
@@ -22,46 +23,12 @@ | |||
22 | #define SDIAS_RETRIES 300 | 23 | #define SDIAS_RETRIES 300 |
23 | #define SDIAS_SLEEP_TICKS 50 | 24 | #define SDIAS_SLEEP_TICKS 50 |
24 | 25 | ||
25 | #define EQ_STORE_DATA 0x0 | ||
26 | #define EQ_SIZE 0x1 | ||
27 | #define DI_FCP_DUMP 0x0 | ||
28 | #define ASA_SIZE_32 0x0 | ||
29 | #define ASA_SIZE_64 0x1 | ||
30 | #define EVSTATE_ALL_STORED 0x0 | ||
31 | #define EVSTATE_NO_DATA 0x3 | ||
32 | #define EVSTATE_PART_STORED 0x10 | ||
33 | |||
34 | static struct debug_info *sdias_dbf; | 26 | static struct debug_info *sdias_dbf; |
35 | 27 | ||
36 | static struct sclp_register sclp_sdias_register = { | 28 | static struct sclp_register sclp_sdias_register = { |
37 | .send_mask = EVTYP_SDIAS_MASK, | 29 | .send_mask = EVTYP_SDIAS_MASK, |
38 | }; | 30 | }; |
39 | 31 | ||
40 | struct sdias_evbuf { | ||
41 | struct evbuf_header hdr; | ||
42 | u8 event_qual; | ||
43 | u8 data_id; | ||
44 | u64 reserved2; | ||
45 | u32 event_id; | ||
46 | u16 reserved3; | ||
47 | u8 asa_size; | ||
48 | u8 event_status; | ||
49 | u32 reserved4; | ||
50 | u32 blk_cnt; | ||
51 | u64 asa; | ||
52 | u32 reserved5; | ||
53 | u32 fbn; | ||
54 | u32 reserved6; | ||
55 | u32 lbn; | ||
56 | u16 reserved7; | ||
57 | u16 dbs; | ||
58 | } __attribute__((packed)); | ||
59 | |||
60 | struct sdias_sccb { | ||
61 | struct sccb_header hdr; | ||
62 | struct sdias_evbuf evbuf; | ||
63 | } __attribute__((packed)); | ||
64 | |||
65 | static struct sdias_sccb sccb __attribute__((aligned(4096))); | 32 | static struct sdias_sccb sccb __attribute__((aligned(4096))); |
66 | static struct sdias_evbuf sdias_evbuf; | 33 | static struct sdias_evbuf sdias_evbuf; |
67 | 34 | ||
@@ -148,8 +115,8 @@ int sclp_sdias_blk_count(void) | |||
148 | sccb.hdr.length = sizeof(sccb); | 115 | sccb.hdr.length = sizeof(sccb); |
149 | sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf); | 116 | sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf); |
150 | sccb.evbuf.hdr.type = EVTYP_SDIAS; | 117 | sccb.evbuf.hdr.type = EVTYP_SDIAS; |
151 | sccb.evbuf.event_qual = EQ_SIZE; | 118 | sccb.evbuf.event_qual = SDIAS_EQ_SIZE; |
152 | sccb.evbuf.data_id = DI_FCP_DUMP; | 119 | sccb.evbuf.data_id = SDIAS_DI_FCP_DUMP; |
153 | sccb.evbuf.event_id = 4712; | 120 | sccb.evbuf.event_id = 4712; |
154 | sccb.evbuf.dbs = 1; | 121 | sccb.evbuf.dbs = 1; |
155 | 122 | ||
@@ -208,13 +175,13 @@ int sclp_sdias_copy(void *dest, int start_blk, int nr_blks) | |||
208 | sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf); | 175 | sccb.evbuf.hdr.length = sizeof(struct sdias_evbuf); |
209 | sccb.evbuf.hdr.type = EVTYP_SDIAS; | 176 | sccb.evbuf.hdr.type = EVTYP_SDIAS; |
210 | sccb.evbuf.hdr.flags = 0; | 177 | sccb.evbuf.hdr.flags = 0; |
211 | sccb.evbuf.event_qual = EQ_STORE_DATA; | 178 | sccb.evbuf.event_qual = SDIAS_EQ_STORE_DATA; |
212 | sccb.evbuf.data_id = DI_FCP_DUMP; | 179 | sccb.evbuf.data_id = SDIAS_DI_FCP_DUMP; |
213 | sccb.evbuf.event_id = 4712; | 180 | sccb.evbuf.event_id = 4712; |
214 | #ifdef CONFIG_64BIT | 181 | #ifdef CONFIG_64BIT |
215 | sccb.evbuf.asa_size = ASA_SIZE_64; | 182 | sccb.evbuf.asa_size = SDIAS_ASA_SIZE_64; |
216 | #else | 183 | #else |
217 | sccb.evbuf.asa_size = ASA_SIZE_32; | 184 | sccb.evbuf.asa_size = SDIAS_ASA_SIZE_32; |
218 | #endif | 185 | #endif |
219 | sccb.evbuf.event_status = 0; | 186 | sccb.evbuf.event_status = 0; |
220 | sccb.evbuf.blk_cnt = nr_blks; | 187 | sccb.evbuf.blk_cnt = nr_blks; |
@@ -240,20 +207,19 @@ int sclp_sdias_copy(void *dest, int start_blk, int nr_blks) | |||
240 | } | 207 | } |
241 | 208 | ||
242 | switch (sdias_evbuf.event_status) { | 209 | switch (sdias_evbuf.event_status) { |
243 | case EVSTATE_ALL_STORED: | 210 | case SDIAS_EVSTATE_ALL_STORED: |
244 | TRACE("all stored\n"); | 211 | TRACE("all stored\n"); |
245 | break; | 212 | break; |
246 | case EVSTATE_PART_STORED: | 213 | case SDIAS_EVSTATE_PART_STORED: |
247 | TRACE("part stored: %i\n", sdias_evbuf.blk_cnt); | 214 | TRACE("part stored: %i\n", sdias_evbuf.blk_cnt); |
248 | break; | 215 | break; |
249 | case EVSTATE_NO_DATA: | 216 | case SDIAS_EVSTATE_NO_DATA: |
250 | TRACE("no data\n"); | 217 | TRACE("no data\n"); |
251 | /* fall through */ | 218 | /* fall through */ |
252 | default: | 219 | default: |
253 | pr_err("Error from SCLP while copying hsa. " | 220 | pr_err("Error from SCLP while copying hsa. Event status = %x\n", |
254 | "Event status = %x\n", | 221 | sdias_evbuf.event_status); |
255 | sdias_evbuf.event_status); | 222 | rc = -EIO; |
256 | rc = -EIO; | ||
257 | } | 223 | } |
258 | out: | 224 | out: |
259 | mutex_unlock(&sdias_mutex); | 225 | mutex_unlock(&sdias_mutex); |
diff --git a/drivers/s390/char/sclp_sdias.h b/drivers/s390/char/sclp_sdias.h new file mode 100644 index 000000000000..f2431c414150 --- /dev/null +++ b/drivers/s390/char/sclp_sdias.h | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * SCLP "store data in absolute storage" | ||
3 | * | ||
4 | * Copyright IBM Corp. 2003, 2013 | ||
5 | */ | ||
6 | |||
7 | #ifndef SCLP_SDIAS_H | ||
8 | #define SCLP_SDIAS_H | ||
9 | |||
10 | #include "sclp.h" | ||
11 | |||
12 | #define SDIAS_EQ_STORE_DATA 0x0 | ||
13 | #define SDIAS_EQ_SIZE 0x1 | ||
14 | #define SDIAS_DI_FCP_DUMP 0x0 | ||
15 | #define SDIAS_ASA_SIZE_32 0x0 | ||
16 | #define SDIAS_ASA_SIZE_64 0x1 | ||
17 | #define SDIAS_EVSTATE_ALL_STORED 0x0 | ||
18 | #define SDIAS_EVSTATE_NO_DATA 0x3 | ||
19 | #define SDIAS_EVSTATE_PART_STORED 0x10 | ||
20 | |||
21 | struct sdias_evbuf { | ||
22 | struct evbuf_header hdr; | ||
23 | u8 event_qual; | ||
24 | u8 data_id; | ||
25 | u64 reserved2; | ||
26 | u32 event_id; | ||
27 | u16 reserved3; | ||
28 | u8 asa_size; | ||
29 | u8 event_status; | ||
30 | u32 reserved4; | ||
31 | u32 blk_cnt; | ||
32 | u64 asa; | ||
33 | u32 reserved5; | ||
34 | u32 fbn; | ||
35 | u32 reserved6; | ||
36 | u32 lbn; | ||
37 | u16 reserved7; | ||
38 | u16 dbs; | ||
39 | } __packed; | ||
40 | |||
41 | struct sdias_sccb { | ||
42 | struct sccb_header hdr; | ||
43 | struct sdias_evbuf evbuf; | ||
44 | } __packed; | ||
45 | |||
46 | #endif /* SCLP_SDIAS_H */ | ||
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index ffb1fcf0bf5b..3d8e4d63f514 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -328,9 +328,9 @@ static ssize_t zcore_read(struct file *file, char __user *buf, size_t count, | |||
328 | mem_offs = 0; | 328 | mem_offs = 0; |
329 | 329 | ||
330 | /* Copy from HSA data */ | 330 | /* Copy from HSA data */ |
331 | if (*ppos < (ZFCPDUMP_HSA_SIZE + HEADER_SIZE)) { | 331 | if (*ppos < sclp_get_hsa_size() + HEADER_SIZE) { |
332 | size = min((count - hdr_count), (size_t) (ZFCPDUMP_HSA_SIZE | 332 | size = min((count - hdr_count), |
333 | - mem_start)); | 333 | (size_t) (sclp_get_hsa_size() - mem_start)); |
334 | rc = memcpy_hsa_user(buf + hdr_count, mem_start, size); | 334 | rc = memcpy_hsa_user(buf + hdr_count, mem_start, size); |
335 | if (rc) | 335 | if (rc) |
336 | goto fail; | 336 | goto fail; |
@@ -490,7 +490,7 @@ static ssize_t zcore_hsa_read(struct file *filp, char __user *buf, | |||
490 | static char str[18]; | 490 | static char str[18]; |
491 | 491 | ||
492 | if (hsa_available) | 492 | if (hsa_available) |
493 | snprintf(str, sizeof(str), "%lx\n", ZFCPDUMP_HSA_SIZE); | 493 | snprintf(str, sizeof(str), "%lx\n", sclp_get_hsa_size()); |
494 | else | 494 | else |
495 | snprintf(str, sizeof(str), "0\n"); | 495 | snprintf(str, sizeof(str), "0\n"); |
496 | return simple_read_from_buffer(buf, count, ppos, str, strlen(str)); | 496 | return simple_read_from_buffer(buf, count, ppos, str, strlen(str)); |
@@ -584,17 +584,9 @@ static int __init sys_info_init(enum arch_id arch, unsigned long mem_end) | |||
584 | 584 | ||
585 | static int __init check_sdias(void) | 585 | static int __init check_sdias(void) |
586 | { | 586 | { |
587 | int rc, act_hsa_size; | 587 | if (!sclp_get_hsa_size()) { |
588 | |||
589 | rc = sclp_sdias_blk_count(); | ||
590 | if (rc < 0) { | ||
591 | TRACE("Could not determine HSA size\n"); | 588 | TRACE("Could not determine HSA size\n"); |
592 | return rc; | 589 | return -ENODEV; |
593 | } | ||
594 | act_hsa_size = (rc - 1) * PAGE_SIZE; | ||
595 | if (act_hsa_size < ZFCPDUMP_HSA_SIZE) { | ||
596 | TRACE("HSA size too small: %i\n", act_hsa_size); | ||
597 | return -EINVAL; | ||
598 | } | 590 | } |
599 | return 0; | 591 | return 0; |
600 | } | 592 | } |
@@ -662,7 +654,7 @@ static int __init zcore_reipl_init(void) | |||
662 | ipl_block = (void *) __get_free_page(GFP_KERNEL); | 654 | ipl_block = (void *) __get_free_page(GFP_KERNEL); |
663 | if (!ipl_block) | 655 | if (!ipl_block) |
664 | return -ENOMEM; | 656 | return -ENOMEM; |
665 | if (ipib_info.ipib < ZFCPDUMP_HSA_SIZE) | 657 | if (ipib_info.ipib < sclp_get_hsa_size()) |
666 | rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); | 658 | rc = memcpy_hsa_kernel(ipl_block, ipib_info.ipib, PAGE_SIZE); |
667 | else | 659 | else |
668 | rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE); | 660 | rc = memcpy_real(ipl_block, (void *) ipib_info.ipib, PAGE_SIZE); |
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c index aca7bfc113aa..3a2ee4a740b4 100644 --- a/drivers/s390/cio/eadm_sch.c +++ b/drivers/s390/cio/eadm_sch.c | |||
@@ -190,7 +190,7 @@ static struct subchannel *eadm_get_idle_sch(void) | |||
190 | return NULL; | 190 | return NULL; |
191 | } | 191 | } |
192 | 192 | ||
193 | static int eadm_start_aob(struct aob *aob) | 193 | int eadm_start_aob(struct aob *aob) |
194 | { | 194 | { |
195 | struct eadm_private *private; | 195 | struct eadm_private *private; |
196 | struct subchannel *sch; | 196 | struct subchannel *sch; |
@@ -218,6 +218,7 @@ out_unlock: | |||
218 | 218 | ||
219 | return ret; | 219 | return ret; |
220 | } | 220 | } |
221 | EXPORT_SYMBOL_GPL(eadm_start_aob); | ||
221 | 222 | ||
222 | static int eadm_subchannel_probe(struct subchannel *sch) | 223 | static int eadm_subchannel_probe(struct subchannel *sch) |
223 | { | 224 | { |
@@ -380,11 +381,6 @@ static struct css_driver eadm_subchannel_driver = { | |||
380 | .restore = eadm_subchannel_restore, | 381 | .restore = eadm_subchannel_restore, |
381 | }; | 382 | }; |
382 | 383 | ||
383 | static struct eadm_ops eadm_ops = { | ||
384 | .eadm_start = eadm_start_aob, | ||
385 | .owner = THIS_MODULE, | ||
386 | }; | ||
387 | |||
388 | static int __init eadm_sch_init(void) | 384 | static int __init eadm_sch_init(void) |
389 | { | 385 | { |
390 | int ret; | 386 | int ret; |
@@ -404,7 +400,6 @@ static int __init eadm_sch_init(void) | |||
404 | if (ret) | 400 | if (ret) |
405 | goto cleanup; | 401 | goto cleanup; |
406 | 402 | ||
407 | register_eadm_ops(&eadm_ops); | ||
408 | return ret; | 403 | return ret; |
409 | 404 | ||
410 | cleanup: | 405 | cleanup: |
@@ -415,7 +410,6 @@ cleanup: | |||
415 | 410 | ||
416 | static void __exit eadm_sch_exit(void) | 411 | static void __exit eadm_sch_exit(void) |
417 | { | 412 | { |
418 | unregister_eadm_ops(&eadm_ops); | ||
419 | css_driver_unregister(&eadm_subchannel_driver); | 413 | css_driver_unregister(&eadm_subchannel_driver); |
420 | isc_unregister(EADM_SCH_ISC); | 414 | isc_unregister(EADM_SCH_ISC); |
421 | debug_unregister(eadm_debug); | 415 | debug_unregister(eadm_debug); |
diff --git a/drivers/s390/cio/scm.c b/drivers/s390/cio/scm.c index 46ec25632e8b..15268edc54ae 100644 --- a/drivers/s390/cio/scm.c +++ b/drivers/s390/cio/scm.c | |||
@@ -15,8 +15,6 @@ | |||
15 | #include "chsc.h" | 15 | #include "chsc.h" |
16 | 16 | ||
17 | static struct device *scm_root; | 17 | static struct device *scm_root; |
18 | static struct eadm_ops *eadm_ops; | ||
19 | static DEFINE_MUTEX(eadm_ops_mutex); | ||
20 | 18 | ||
21 | #define to_scm_dev(n) container_of(n, struct scm_device, dev) | 19 | #define to_scm_dev(n) container_of(n, struct scm_device, dev) |
22 | #define to_scm_drv(d) container_of(d, struct scm_driver, drv) | 20 | #define to_scm_drv(d) container_of(d, struct scm_driver, drv) |
@@ -73,49 +71,6 @@ void scm_driver_unregister(struct scm_driver *scmdrv) | |||
73 | } | 71 | } |
74 | EXPORT_SYMBOL_GPL(scm_driver_unregister); | 72 | EXPORT_SYMBOL_GPL(scm_driver_unregister); |
75 | 73 | ||
76 | int scm_get_ref(void) | ||
77 | { | ||
78 | int ret = 0; | ||
79 | |||
80 | mutex_lock(&eadm_ops_mutex); | ||
81 | if (!eadm_ops || !try_module_get(eadm_ops->owner)) | ||
82 | ret = -ENOENT; | ||
83 | mutex_unlock(&eadm_ops_mutex); | ||
84 | |||
85 | return ret; | ||
86 | } | ||
87 | EXPORT_SYMBOL_GPL(scm_get_ref); | ||
88 | |||
89 | void scm_put_ref(void) | ||
90 | { | ||
91 | mutex_lock(&eadm_ops_mutex); | ||
92 | module_put(eadm_ops->owner); | ||
93 | mutex_unlock(&eadm_ops_mutex); | ||
94 | } | ||
95 | EXPORT_SYMBOL_GPL(scm_put_ref); | ||
96 | |||
97 | void register_eadm_ops(struct eadm_ops *ops) | ||
98 | { | ||
99 | mutex_lock(&eadm_ops_mutex); | ||
100 | eadm_ops = ops; | ||
101 | mutex_unlock(&eadm_ops_mutex); | ||
102 | } | ||
103 | EXPORT_SYMBOL_GPL(register_eadm_ops); | ||
104 | |||
105 | void unregister_eadm_ops(struct eadm_ops *ops) | ||
106 | { | ||
107 | mutex_lock(&eadm_ops_mutex); | ||
108 | eadm_ops = NULL; | ||
109 | mutex_unlock(&eadm_ops_mutex); | ||
110 | } | ||
111 | EXPORT_SYMBOL_GPL(unregister_eadm_ops); | ||
112 | |||
113 | int scm_start_aob(struct aob *aob) | ||
114 | { | ||
115 | return eadm_ops->eadm_start(aob); | ||
116 | } | ||
117 | EXPORT_SYMBOL_GPL(scm_start_aob); | ||
118 | |||
119 | void scm_irq_handler(struct aob *aob, int error) | 74 | void scm_irq_handler(struct aob *aob, int error) |
120 | { | 75 | { |
121 | struct aob_rq_header *aobrq = (void *) aob->request.data; | 76 | struct aob_rq_header *aobrq = (void *) aob->request.data; |