diff options
48 files changed, 1458 insertions, 989 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 0d189c93eeaf..25f8d20dac53 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -1689,9 +1689,14 @@ running once the system is up. | |||
1689 | decrease the size and leave more room for directly | 1689 | decrease the size and leave more room for directly |
1690 | mapped kernel RAM. | 1690 | mapped kernel RAM. |
1691 | 1691 | ||
1692 | vmhalt= [KNL,S390] | 1692 | vmhalt= [KNL,S390] Perform z/VM CP command after system halt. |
1693 | Format: <command> | ||
1693 | 1694 | ||
1694 | vmpoff= [KNL,S390] | 1695 | vmpanic= [KNL,S390] Perform z/VM CP command after kernel panic. |
1696 | Format: <command> | ||
1697 | |||
1698 | vmpoff= [KNL,S390] Perform z/VM CP command after power off. | ||
1699 | Format: <command> | ||
1695 | 1700 | ||
1696 | waveartist= [HW,OSS] | 1701 | waveartist= [HW,OSS] |
1697 | Format: <io>,<irq>,<dma>,<dma2> | 1702 | Format: <io>,<irq>,<dma>,<dma2> |
diff --git a/arch/s390/appldata/appldata.h b/arch/s390/appldata/appldata.h index e806a8922bbb..71d65eb30650 100644 --- a/arch/s390/appldata/appldata.h +++ b/arch/s390/appldata/appldata.h | |||
@@ -3,9 +3,9 @@ | |||
3 | * | 3 | * |
4 | * Definitions and interface for Linux - z/VM Monitor Stream. | 4 | * Definitions and interface for Linux - z/VM Monitor Stream. |
5 | * | 5 | * |
6 | * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. | 6 | * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH. |
7 | * | 7 | * |
8 | * Author: Gerald Schaefer <geraldsc@de.ibm.com> | 8 | * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | //#define APPLDATA_DEBUG /* Debug messages on/off */ | 11 | //#define APPLDATA_DEBUG /* Debug messages on/off */ |
@@ -29,6 +29,22 @@ | |||
29 | #define CTL_APPLDATA_NET_SUM 2125 | 29 | #define CTL_APPLDATA_NET_SUM 2125 |
30 | #define CTL_APPLDATA_PROC 2126 | 30 | #define CTL_APPLDATA_PROC 2126 |
31 | 31 | ||
32 | #ifndef CONFIG_64BIT | ||
33 | |||
34 | #define APPLDATA_START_INTERVAL_REC 0x00 /* Function codes for */ | ||
35 | #define APPLDATA_STOP_REC 0x01 /* DIAG 0xDC */ | ||
36 | #define APPLDATA_GEN_EVENT_RECORD 0x02 | ||
37 | #define APPLDATA_START_CONFIG_REC 0x03 | ||
38 | |||
39 | #else | ||
40 | |||
41 | #define APPLDATA_START_INTERVAL_REC 0x80 | ||
42 | #define APPLDATA_STOP_REC 0x81 | ||
43 | #define APPLDATA_GEN_EVENT_RECORD 0x82 | ||
44 | #define APPLDATA_START_CONFIG_REC 0x83 | ||
45 | |||
46 | #endif /* CONFIG_64BIT */ | ||
47 | |||
32 | #define P_INFO(x...) printk(KERN_INFO MY_PRINT_NAME " info: " x) | 48 | #define P_INFO(x...) printk(KERN_INFO MY_PRINT_NAME " info: " x) |
33 | #define P_ERROR(x...) printk(KERN_ERR MY_PRINT_NAME " error: " x) | 49 | #define P_ERROR(x...) printk(KERN_ERR MY_PRINT_NAME " error: " x) |
34 | #define P_WARNING(x...) printk(KERN_WARNING MY_PRINT_NAME " status: " x) | 50 | #define P_WARNING(x...) printk(KERN_WARNING MY_PRINT_NAME " status: " x) |
@@ -53,7 +69,11 @@ struct appldata_ops { | |||
53 | void *data; /* record data */ | 69 | void *data; /* record data */ |
54 | unsigned int size; /* size of record */ | 70 | unsigned int size; /* size of record */ |
55 | struct module *owner; /* THIS_MODULE */ | 71 | struct module *owner; /* THIS_MODULE */ |
72 | char mod_lvl[2]; /* modification level, EBCDIC */ | ||
56 | }; | 73 | }; |
57 | 74 | ||
58 | extern int appldata_register_ops(struct appldata_ops *ops); | 75 | extern int appldata_register_ops(struct appldata_ops *ops); |
59 | extern void appldata_unregister_ops(struct appldata_ops *ops); | 76 | extern void appldata_unregister_ops(struct appldata_ops *ops); |
77 | extern int appldata_diag(char record_nr, u16 function, unsigned long buffer, | ||
78 | u16 length, char *mod_lvl); | ||
79 | |||
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index 54d35c130907..61bc44626c04 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c | |||
@@ -5,9 +5,9 @@ | |||
5 | * Exports appldata_register_ops() and appldata_unregister_ops() for the | 5 | * Exports appldata_register_ops() and appldata_unregister_ops() for the |
6 | * data gathering modules. | 6 | * data gathering modules. |
7 | * | 7 | * |
8 | * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. | 8 | * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH. |
9 | * | 9 | * |
10 | * Author: Gerald Schaefer <geraldsc@de.ibm.com> | 10 | * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com> |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/config.h> | 13 | #include <linux/config.h> |
@@ -40,22 +40,6 @@ | |||
40 | 40 | ||
41 | #define TOD_MICRO 0x01000 /* nr. of TOD clock units | 41 | #define TOD_MICRO 0x01000 /* nr. of TOD clock units |
42 | for 1 microsecond */ | 42 | for 1 microsecond */ |
43 | #ifndef CONFIG_64BIT | ||
44 | |||
45 | #define APPLDATA_START_INTERVAL_REC 0x00 /* Function codes for */ | ||
46 | #define APPLDATA_STOP_REC 0x01 /* DIAG 0xDC */ | ||
47 | #define APPLDATA_GEN_EVENT_RECORD 0x02 | ||
48 | #define APPLDATA_START_CONFIG_REC 0x03 | ||
49 | |||
50 | #else | ||
51 | |||
52 | #define APPLDATA_START_INTERVAL_REC 0x80 | ||
53 | #define APPLDATA_STOP_REC 0x81 | ||
54 | #define APPLDATA_GEN_EVENT_RECORD 0x82 | ||
55 | #define APPLDATA_START_CONFIG_REC 0x83 | ||
56 | |||
57 | #endif /* CONFIG_64BIT */ | ||
58 | |||
59 | 43 | ||
60 | /* | 44 | /* |
61 | * Parameter list for DIAGNOSE X'DC' | 45 | * Parameter list for DIAGNOSE X'DC' |
@@ -195,8 +179,8 @@ static void appldata_work_fn(void *data) | |||
195 | * | 179 | * |
196 | * prepare parameter list, issue DIAG 0xDC | 180 | * prepare parameter list, issue DIAG 0xDC |
197 | */ | 181 | */ |
198 | static int appldata_diag(char record_nr, u16 function, unsigned long buffer, | 182 | int appldata_diag(char record_nr, u16 function, unsigned long buffer, |
199 | u16 length) | 183 | u16 length, char *mod_lvl) |
200 | { | 184 | { |
201 | unsigned long ry; | 185 | unsigned long ry; |
202 | struct appldata_product_id { | 186 | struct appldata_product_id { |
@@ -214,7 +198,7 @@ static int appldata_diag(char record_nr, u16 function, unsigned long buffer, | |||
214 | .record_nr = record_nr, | 198 | .record_nr = record_nr, |
215 | .version_nr = {0xF2, 0xF6}, /* "26" */ | 199 | .version_nr = {0xF2, 0xF6}, /* "26" */ |
216 | .release_nr = {0xF0, 0xF1}, /* "01" */ | 200 | .release_nr = {0xF0, 0xF1}, /* "01" */ |
217 | .mod_lvl = {0xF0, 0xF0}, /* "00" */ | 201 | .mod_lvl = {mod_lvl[0], mod_lvl[1]}, |
218 | }; | 202 | }; |
219 | struct appldata_parameter_list appldata_parameter_list = { | 203 | struct appldata_parameter_list appldata_parameter_list = { |
220 | .diag = 0xDC, | 204 | .diag = 0xDC, |
@@ -467,24 +451,25 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp, | |||
467 | module_put(ops->owner); | 451 | module_put(ops->owner); |
468 | return -ENODEV; | 452 | return -ENODEV; |
469 | } | 453 | } |
470 | ops->active = 1; | ||
471 | ops->callback(ops->data); // init record | 454 | ops->callback(ops->data); // init record |
472 | rc = appldata_diag(ops->record_nr, | 455 | rc = appldata_diag(ops->record_nr, |
473 | APPLDATA_START_INTERVAL_REC, | 456 | APPLDATA_START_INTERVAL_REC, |
474 | (unsigned long) ops->data, ops->size); | 457 | (unsigned long) ops->data, ops->size, |
458 | ops->mod_lvl); | ||
475 | if (rc != 0) { | 459 | if (rc != 0) { |
476 | P_ERROR("START DIAG 0xDC for %s failed, " | 460 | P_ERROR("START DIAG 0xDC for %s failed, " |
477 | "return code: %d\n", ops->name, rc); | 461 | "return code: %d\n", ops->name, rc); |
478 | module_put(ops->owner); | 462 | module_put(ops->owner); |
479 | ops->active = 0; | ||
480 | } else { | 463 | } else { |
481 | P_INFO("Monitoring %s data enabled, " | 464 | P_INFO("Monitoring %s data enabled, " |
482 | "DIAG 0xDC started.\n", ops->name); | 465 | "DIAG 0xDC started.\n", ops->name); |
466 | ops->active = 1; | ||
483 | } | 467 | } |
484 | } else if ((buf[0] == '0') && (ops->active == 1)) { | 468 | } else if ((buf[0] == '0') && (ops->active == 1)) { |
485 | ops->active = 0; | 469 | ops->active = 0; |
486 | rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, | 470 | rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, |
487 | (unsigned long) ops->data, ops->size); | 471 | (unsigned long) ops->data, ops->size, |
472 | ops->mod_lvl); | ||
488 | if (rc != 0) { | 473 | if (rc != 0) { |
489 | P_ERROR("STOP DIAG 0xDC for %s failed, " | 474 | P_ERROR("STOP DIAG 0xDC for %s failed, " |
490 | "return code: %d\n", ops->name, rc); | 475 | "return code: %d\n", ops->name, rc); |
@@ -633,7 +618,7 @@ appldata_offline_cpu(int cpu) | |||
633 | spin_unlock(&appldata_timer_lock); | 618 | spin_unlock(&appldata_timer_lock); |
634 | } | 619 | } |
635 | 620 | ||
636 | static int | 621 | static int __cpuinit |
637 | appldata_cpu_notify(struct notifier_block *self, | 622 | appldata_cpu_notify(struct notifier_block *self, |
638 | unsigned long action, void *hcpu) | 623 | unsigned long action, void *hcpu) |
639 | { | 624 | { |
@@ -710,7 +695,8 @@ static void __exit appldata_exit(void) | |||
710 | list_for_each(lh, &appldata_ops_list) { | 695 | list_for_each(lh, &appldata_ops_list) { |
711 | ops = list_entry(lh, struct appldata_ops, list); | 696 | ops = list_entry(lh, struct appldata_ops, list); |
712 | rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, | 697 | rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC, |
713 | (unsigned long) ops->data, ops->size); | 698 | (unsigned long) ops->data, ops->size, |
699 | ops->mod_lvl); | ||
714 | if (rc != 0) { | 700 | if (rc != 0) { |
715 | P_ERROR("STOP DIAG 0xDC for %s failed, " | 701 | P_ERROR("STOP DIAG 0xDC for %s failed, " |
716 | "return code: %d\n", ops->name, rc); | 702 | "return code: %d\n", ops->name, rc); |
@@ -739,6 +725,7 @@ MODULE_DESCRIPTION("Linux-VM Monitor Stream, base infrastructure"); | |||
739 | 725 | ||
740 | EXPORT_SYMBOL_GPL(appldata_register_ops); | 726 | EXPORT_SYMBOL_GPL(appldata_register_ops); |
741 | EXPORT_SYMBOL_GPL(appldata_unregister_ops); | 727 | EXPORT_SYMBOL_GPL(appldata_unregister_ops); |
728 | EXPORT_SYMBOL_GPL(appldata_diag); | ||
742 | 729 | ||
743 | #ifdef MODULE | 730 | #ifdef MODULE |
744 | /* | 731 | /* |
@@ -779,7 +766,6 @@ unsigned long nr_iowait(void) | |||
779 | #endif /* MODULE */ | 766 | #endif /* MODULE */ |
780 | EXPORT_SYMBOL_GPL(si_swapinfo); | 767 | EXPORT_SYMBOL_GPL(si_swapinfo); |
781 | EXPORT_SYMBOL_GPL(nr_threads); | 768 | EXPORT_SYMBOL_GPL(nr_threads); |
782 | EXPORT_SYMBOL_GPL(avenrun); | ||
783 | EXPORT_SYMBOL_GPL(get_full_page_state); | 769 | EXPORT_SYMBOL_GPL(get_full_page_state); |
784 | EXPORT_SYMBOL_GPL(nr_running); | 770 | EXPORT_SYMBOL_GPL(nr_running); |
785 | EXPORT_SYMBOL_GPL(nr_iowait); | 771 | EXPORT_SYMBOL_GPL(nr_iowait); |
diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c index f0e2fbed3d4c..7915a197d96d 100644 --- a/arch/s390/appldata/appldata_mem.c +++ b/arch/s390/appldata/appldata_mem.c | |||
@@ -4,9 +4,9 @@ | |||
4 | * Data gathering module for Linux-VM Monitor Stream, Stage 1. | 4 | * Data gathering module for Linux-VM Monitor Stream, Stage 1. |
5 | * Collects data related to memory management. | 5 | * Collects data related to memory management. |
6 | * | 6 | * |
7 | * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. | 7 | * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH. |
8 | * | 8 | * |
9 | * Author: Gerald Schaefer <geraldsc@de.ibm.com> | 9 | * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com> |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/config.h> | 12 | #include <linux/config.h> |
@@ -152,6 +152,7 @@ static struct appldata_ops ops = { | |||
152 | .callback = &appldata_get_mem_data, | 152 | .callback = &appldata_get_mem_data, |
153 | .data = &appldata_mem_data, | 153 | .data = &appldata_mem_data, |
154 | .owner = THIS_MODULE, | 154 | .owner = THIS_MODULE, |
155 | .mod_lvl = {0xF0, 0xF0}, /* EBCDIC "00" */ | ||
155 | }; | 156 | }; |
156 | 157 | ||
157 | 158 | ||
diff --git a/arch/s390/appldata/appldata_net_sum.c b/arch/s390/appldata/appldata_net_sum.c index 2a4c7432db4a..39b7bdecbf05 100644 --- a/arch/s390/appldata/appldata_net_sum.c +++ b/arch/s390/appldata/appldata_net_sum.c | |||
@@ -5,9 +5,9 @@ | |||
5 | * Collects accumulated network statistics (Packets received/transmitted, | 5 | * Collects accumulated network statistics (Packets received/transmitted, |
6 | * dropped, errors, ...). | 6 | * dropped, errors, ...). |
7 | * | 7 | * |
8 | * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. | 8 | * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH. |
9 | * | 9 | * |
10 | * Author: Gerald Schaefer <geraldsc@de.ibm.com> | 10 | * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com> |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/config.h> | 13 | #include <linux/config.h> |
@@ -152,6 +152,7 @@ static struct appldata_ops ops = { | |||
152 | .callback = &appldata_get_net_sum_data, | 152 | .callback = &appldata_get_net_sum_data, |
153 | .data = &appldata_net_sum_data, | 153 | .data = &appldata_net_sum_data, |
154 | .owner = THIS_MODULE, | 154 | .owner = THIS_MODULE, |
155 | .mod_lvl = {0xF0, 0xF0}, /* EBCDIC "00" */ | ||
155 | }; | 156 | }; |
156 | 157 | ||
157 | 158 | ||
diff --git a/arch/s390/appldata/appldata_os.c b/arch/s390/appldata/appldata_os.c index 99ddd3bf2fba..f2b44a2f1dec 100644 --- a/arch/s390/appldata/appldata_os.c +++ b/arch/s390/appldata/appldata_os.c | |||
@@ -4,9 +4,9 @@ | |||
4 | * Data gathering module for Linux-VM Monitor Stream, Stage 1. | 4 | * Data gathering module for Linux-VM Monitor Stream, Stage 1. |
5 | * Collects misc. OS related data (CPU utilization, running processes). | 5 | * Collects misc. OS related data (CPU utilization, running processes). |
6 | * | 6 | * |
7 | * Copyright (C) 2003 IBM Corporation, IBM Deutschland Entwicklung GmbH. | 7 | * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH. |
8 | * | 8 | * |
9 | * Author: Gerald Schaefer <geraldsc@de.ibm.com> | 9 | * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com> |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/config.h> | 12 | #include <linux/config.h> |
@@ -44,11 +44,14 @@ struct appldata_os_per_cpu { | |||
44 | u32 per_cpu_system; /* ... spent in kernel mode */ | 44 | u32 per_cpu_system; /* ... spent in kernel mode */ |
45 | u32 per_cpu_idle; /* ... spent in idle mode */ | 45 | u32 per_cpu_idle; /* ... spent in idle mode */ |
46 | 46 | ||
47 | // New in 2.6 --> | 47 | /* New in 2.6 */ |
48 | u32 per_cpu_irq; /* ... spent in interrupts */ | 48 | u32 per_cpu_irq; /* ... spent in interrupts */ |
49 | u32 per_cpu_softirq; /* ... spent in softirqs */ | 49 | u32 per_cpu_softirq; /* ... spent in softirqs */ |
50 | u32 per_cpu_iowait; /* ... spent while waiting for I/O */ | 50 | u32 per_cpu_iowait; /* ... spent while waiting for I/O */ |
51 | // <-- New in 2.6 | 51 | |
52 | /* New in modification level 01 */ | ||
53 | u32 per_cpu_steal; /* ... stolen by hypervisor */ | ||
54 | u32 cpu_id; /* number of this CPU */ | ||
52 | } __attribute__((packed)); | 55 | } __attribute__((packed)); |
53 | 56 | ||
54 | struct appldata_os_data { | 57 | struct appldata_os_data { |
@@ -68,10 +71,9 @@ struct appldata_os_data { | |||
68 | u32 avenrun[3]; /* average nr. of running processes during */ | 71 | u32 avenrun[3]; /* average nr. of running processes during */ |
69 | /* the last 1, 5 and 15 minutes */ | 72 | /* the last 1, 5 and 15 minutes */ |
70 | 73 | ||
71 | // New in 2.6 --> | 74 | /* New in 2.6 */ |
72 | u32 nr_iowait; /* number of blocked threads | 75 | u32 nr_iowait; /* number of blocked threads |
73 | (waiting for I/O) */ | 76 | (waiting for I/O) */ |
74 | // <-- New in 2.6 | ||
75 | 77 | ||
76 | /* per cpu data */ | 78 | /* per cpu data */ |
77 | struct appldata_os_per_cpu os_cpu[0]; | 79 | struct appldata_os_per_cpu os_cpu[0]; |
@@ -79,6 +81,14 @@ struct appldata_os_data { | |||
79 | 81 | ||
80 | static struct appldata_os_data *appldata_os_data; | 82 | static struct appldata_os_data *appldata_os_data; |
81 | 83 | ||
84 | static struct appldata_ops ops = { | ||
85 | .ctl_nr = CTL_APPLDATA_OS, | ||
86 | .name = "os", | ||
87 | .record_nr = APPLDATA_RECORD_OS_ID, | ||
88 | .owner = THIS_MODULE, | ||
89 | .mod_lvl = {0xF0, 0xF1}, /* EBCDIC "01" */ | ||
90 | }; | ||
91 | |||
82 | 92 | ||
83 | static inline void appldata_print_debug(struct appldata_os_data *os_data) | 93 | static inline void appldata_print_debug(struct appldata_os_data *os_data) |
84 | { | 94 | { |
@@ -100,15 +110,17 @@ static inline void appldata_print_debug(struct appldata_os_data *os_data) | |||
100 | P_DEBUG("nr_cpus = %u\n", os_data->nr_cpus); | 110 | P_DEBUG("nr_cpus = %u\n", os_data->nr_cpus); |
101 | for (i = 0; i < os_data->nr_cpus; i++) { | 111 | for (i = 0; i < os_data->nr_cpus; i++) { |
102 | P_DEBUG("cpu%u : user = %u, nice = %u, system = %u, " | 112 | P_DEBUG("cpu%u : user = %u, nice = %u, system = %u, " |
103 | "idle = %u, irq = %u, softirq = %u, iowait = %u\n", | 113 | "idle = %u, irq = %u, softirq = %u, iowait = %u, " |
104 | i, | 114 | "steal = %u\n", |
115 | os_data->os_cpu[i].cpu_id, | ||
105 | os_data->os_cpu[i].per_cpu_user, | 116 | os_data->os_cpu[i].per_cpu_user, |
106 | os_data->os_cpu[i].per_cpu_nice, | 117 | os_data->os_cpu[i].per_cpu_nice, |
107 | os_data->os_cpu[i].per_cpu_system, | 118 | os_data->os_cpu[i].per_cpu_system, |
108 | os_data->os_cpu[i].per_cpu_idle, | 119 | os_data->os_cpu[i].per_cpu_idle, |
109 | os_data->os_cpu[i].per_cpu_irq, | 120 | os_data->os_cpu[i].per_cpu_irq, |
110 | os_data->os_cpu[i].per_cpu_softirq, | 121 | os_data->os_cpu[i].per_cpu_softirq, |
111 | os_data->os_cpu[i].per_cpu_iowait); | 122 | os_data->os_cpu[i].per_cpu_iowait, |
123 | os_data->os_cpu[i].per_cpu_steal); | ||
112 | } | 124 | } |
113 | 125 | ||
114 | P_DEBUG("sync_count_1 = %u\n", os_data->sync_count_1); | 126 | P_DEBUG("sync_count_1 = %u\n", os_data->sync_count_1); |
@@ -123,14 +135,13 @@ static inline void appldata_print_debug(struct appldata_os_data *os_data) | |||
123 | */ | 135 | */ |
124 | static void appldata_get_os_data(void *data) | 136 | static void appldata_get_os_data(void *data) |
125 | { | 137 | { |
126 | int i, j; | 138 | int i, j, rc; |
127 | struct appldata_os_data *os_data; | 139 | struct appldata_os_data *os_data; |
140 | unsigned int new_size; | ||
128 | 141 | ||
129 | os_data = data; | 142 | os_data = data; |
130 | os_data->sync_count_1++; | 143 | os_data->sync_count_1++; |
131 | 144 | ||
132 | os_data->nr_cpus = num_online_cpus(); | ||
133 | |||
134 | os_data->nr_threads = nr_threads; | 145 | os_data->nr_threads = nr_threads; |
135 | os_data->nr_running = nr_running(); | 146 | os_data->nr_running = nr_running(); |
136 | os_data->nr_iowait = nr_iowait(); | 147 | os_data->nr_iowait = nr_iowait(); |
@@ -154,9 +165,44 @@ static void appldata_get_os_data(void *data) | |||
154 | cputime_to_jiffies(kstat_cpu(i).cpustat.softirq); | 165 | cputime_to_jiffies(kstat_cpu(i).cpustat.softirq); |
155 | os_data->os_cpu[j].per_cpu_iowait = | 166 | os_data->os_cpu[j].per_cpu_iowait = |
156 | cputime_to_jiffies(kstat_cpu(i).cpustat.iowait); | 167 | cputime_to_jiffies(kstat_cpu(i).cpustat.iowait); |
168 | os_data->os_cpu[j].per_cpu_steal = | ||
169 | cputime_to_jiffies(kstat_cpu(i).cpustat.steal); | ||
170 | os_data->os_cpu[j].cpu_id = i; | ||
157 | j++; | 171 | j++; |
158 | } | 172 | } |
159 | 173 | ||
174 | os_data->nr_cpus = j; | ||
175 | |||
176 | new_size = sizeof(struct appldata_os_data) + | ||
177 | (os_data->nr_cpus * sizeof(struct appldata_os_per_cpu)); | ||
178 | if (ops.size != new_size) { | ||
179 | if (ops.active) { | ||
180 | rc = appldata_diag(APPLDATA_RECORD_OS_ID, | ||
181 | APPLDATA_START_INTERVAL_REC, | ||
182 | (unsigned long) ops.data, new_size, | ||
183 | ops.mod_lvl); | ||
184 | if (rc != 0) { | ||
185 | P_ERROR("os: START NEW DIAG 0xDC failed, " | ||
186 | "return code: %d, new size = %i\n", rc, | ||
187 | new_size); | ||
188 | P_INFO("os: stopping old record now\n"); | ||
189 | } else | ||
190 | P_INFO("os: new record size = %i\n", new_size); | ||
191 | |||
192 | rc = appldata_diag(APPLDATA_RECORD_OS_ID, | ||
193 | APPLDATA_STOP_REC, | ||
194 | (unsigned long) ops.data, ops.size, | ||
195 | ops.mod_lvl); | ||
196 | if (rc != 0) | ||
197 | P_ERROR("os: STOP OLD DIAG 0xDC failed, " | ||
198 | "return code: %d, old size = %i\n", rc, | ||
199 | ops.size); | ||
200 | else | ||
201 | P_INFO("os: old record size = %i stopped\n", | ||
202 | ops.size); | ||
203 | } | ||
204 | ops.size = new_size; | ||
205 | } | ||
160 | os_data->timestamp = get_clock(); | 206 | os_data->timestamp = get_clock(); |
161 | os_data->sync_count_2++; | 207 | os_data->sync_count_2++; |
162 | #ifdef APPLDATA_DEBUG | 208 | #ifdef APPLDATA_DEBUG |
@@ -165,15 +211,6 @@ static void appldata_get_os_data(void *data) | |||
165 | } | 211 | } |
166 | 212 | ||
167 | 213 | ||
168 | static struct appldata_ops ops = { | ||
169 | .ctl_nr = CTL_APPLDATA_OS, | ||
170 | .name = "os", | ||
171 | .record_nr = APPLDATA_RECORD_OS_ID, | ||
172 | .callback = &appldata_get_os_data, | ||
173 | .owner = THIS_MODULE, | ||
174 | }; | ||
175 | |||
176 | |||
177 | /* | 214 | /* |
178 | * appldata_os_init() | 215 | * appldata_os_init() |
179 | * | 216 | * |
@@ -181,26 +218,25 @@ static struct appldata_ops ops = { | |||
181 | */ | 218 | */ |
182 | static int __init appldata_os_init(void) | 219 | static int __init appldata_os_init(void) |
183 | { | 220 | { |
184 | int rc, size; | 221 | int rc, max_size; |
185 | 222 | ||
186 | size = sizeof(struct appldata_os_data) + | 223 | max_size = sizeof(struct appldata_os_data) + |
187 | (NR_CPUS * sizeof(struct appldata_os_per_cpu)); | 224 | (NR_CPUS * sizeof(struct appldata_os_per_cpu)); |
188 | if (size > APPLDATA_MAX_REC_SIZE) { | 225 | if (max_size > APPLDATA_MAX_REC_SIZE) { |
189 | P_ERROR("Size of record = %i, bigger than maximum (%i)!\n", | 226 | P_ERROR("Max. size of OS record = %i, bigger than maximum " |
190 | size, APPLDATA_MAX_REC_SIZE); | 227 | "record size (%i)\n", max_size, APPLDATA_MAX_REC_SIZE); |
191 | rc = -ENOMEM; | 228 | rc = -ENOMEM; |
192 | goto out; | 229 | goto out; |
193 | } | 230 | } |
194 | P_DEBUG("sizeof(os) = %i, sizeof(os_cpu) = %lu\n", size, | 231 | P_DEBUG("max. sizeof(os) = %i, sizeof(os_cpu) = %lu\n", max_size, |
195 | sizeof(struct appldata_os_per_cpu)); | 232 | sizeof(struct appldata_os_per_cpu)); |
196 | 233 | ||
197 | appldata_os_data = kmalloc(size, GFP_DMA); | 234 | appldata_os_data = kzalloc(max_size, GFP_DMA); |
198 | if (appldata_os_data == NULL) { | 235 | if (appldata_os_data == NULL) { |
199 | P_ERROR("No memory for %s!\n", ops.name); | 236 | P_ERROR("No memory for %s!\n", ops.name); |
200 | rc = -ENOMEM; | 237 | rc = -ENOMEM; |
201 | goto out; | 238 | goto out; |
202 | } | 239 | } |
203 | memset(appldata_os_data, 0, size); | ||
204 | 240 | ||
205 | appldata_os_data->per_cpu_size = sizeof(struct appldata_os_per_cpu); | 241 | appldata_os_data->per_cpu_size = sizeof(struct appldata_os_per_cpu); |
206 | appldata_os_data->cpu_offset = offsetof(struct appldata_os_data, | 242 | appldata_os_data->cpu_offset = offsetof(struct appldata_os_data, |
@@ -208,7 +244,7 @@ static int __init appldata_os_init(void) | |||
208 | P_DEBUG("cpu offset = %u\n", appldata_os_data->cpu_offset); | 244 | P_DEBUG("cpu offset = %u\n", appldata_os_data->cpu_offset); |
209 | 245 | ||
210 | ops.data = appldata_os_data; | 246 | ops.data = appldata_os_data; |
211 | ops.size = size; | 247 | ops.callback = &appldata_get_os_data; |
212 | rc = appldata_register_ops(&ops); | 248 | rc = appldata_register_ops(&ops); |
213 | if (rc != 0) { | 249 | if (rc != 0) { |
214 | P_ERROR("Error registering ops, rc = %i\n", rc); | 250 | P_ERROR("Error registering ops, rc = %i\n", rc); |
diff --git a/arch/s390/kernel/binfmt_elf32.c b/arch/s390/kernel/binfmt_elf32.c index 1f451c2cb071..12a6311e9838 100644 --- a/arch/s390/kernel/binfmt_elf32.c +++ b/arch/s390/kernel/binfmt_elf32.c | |||
@@ -177,11 +177,6 @@ struct elf_prpsinfo32 | |||
177 | 177 | ||
178 | #include <linux/highuid.h> | 178 | #include <linux/highuid.h> |
179 | 179 | ||
180 | #undef NEW_TO_OLD_UID | ||
181 | #undef NEW_TO_OLD_GID | ||
182 | #define NEW_TO_OLD_UID(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid) | ||
183 | #define NEW_TO_OLD_GID(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid) | ||
184 | |||
185 | #define elf_addr_t u32 | 180 | #define elf_addr_t u32 |
186 | /* | 181 | /* |
187 | #define init_elf_binfmt init_elf32_binfmt | 182 | #define init_elf_binfmt init_elf32_binfmt |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index b2448487854c..aa8b52c2140f 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -93,13 +93,22 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
93 | l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 | 93 | l %r13,__LC_SVC_NEW_PSW+4 # load &system_call to %r13 |
94 | .endm | 94 | .endm |
95 | 95 | ||
96 | .macro SAVE_ALL psworg,savearea,sync | 96 | .macro SAVE_ALL_SYNC psworg,savearea |
97 | la %r12,\psworg | 97 | la %r12,\psworg |
98 | .if \sync | ||
99 | tm \psworg+1,0x01 # test problem state bit | 98 | tm \psworg+1,0x01 # test problem state bit |
100 | bz BASED(2f) # skip stack setup save | 99 | bz BASED(2f) # skip stack setup save |
101 | l %r15,__LC_KERNEL_STACK # problem state -> load ksp | 100 | l %r15,__LC_KERNEL_STACK # problem state -> load ksp |
102 | .else | 101 | #ifdef CONFIG_CHECK_STACK |
102 | b BASED(3f) | ||
103 | 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD | ||
104 | bz BASED(stack_overflow) | ||
105 | 3: | ||
106 | #endif | ||
107 | 2: | ||
108 | .endm | ||
109 | |||
110 | .macro SAVE_ALL_ASYNC psworg,savearea | ||
111 | la %r12,\psworg | ||
103 | tm \psworg+1,0x01 # test problem state bit | 112 | tm \psworg+1,0x01 # test problem state bit |
104 | bnz BASED(1f) # from user -> load async stack | 113 | bnz BASED(1f) # from user -> load async stack |
105 | clc \psworg+4(4),BASED(.Lcritical_end) | 114 | clc \psworg+4(4),BASED(.Lcritical_end) |
@@ -115,7 +124,6 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
115 | sra %r14,STACK_SHIFT | 124 | sra %r14,STACK_SHIFT |
116 | be BASED(2f) | 125 | be BASED(2f) |
117 | 1: l %r15,__LC_ASYNC_STACK | 126 | 1: l %r15,__LC_ASYNC_STACK |
118 | .endif | ||
119 | #ifdef CONFIG_CHECK_STACK | 127 | #ifdef CONFIG_CHECK_STACK |
120 | b BASED(3f) | 128 | b BASED(3f) |
121 | 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD | 129 | 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD |
@@ -196,7 +204,7 @@ system_call: | |||
196 | STORE_TIMER __LC_SYNC_ENTER_TIMER | 204 | STORE_TIMER __LC_SYNC_ENTER_TIMER |
197 | sysc_saveall: | 205 | sysc_saveall: |
198 | SAVE_ALL_BASE __LC_SAVE_AREA | 206 | SAVE_ALL_BASE __LC_SAVE_AREA |
199 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 207 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
200 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 208 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
201 | lh %r7,0x8a # get svc number from lowcore | 209 | lh %r7,0x8a # get svc number from lowcore |
202 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 210 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
@@ -425,7 +433,7 @@ pgm_check_handler: | |||
425 | SAVE_ALL_BASE __LC_SAVE_AREA | 433 | SAVE_ALL_BASE __LC_SAVE_AREA |
426 | tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception | 434 | tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception |
427 | bnz BASED(pgm_per) # got per exception -> special case | 435 | bnz BASED(pgm_per) # got per exception -> special case |
428 | SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 | 436 | SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA |
429 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA | 437 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA |
430 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 438 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
431 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 439 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
@@ -464,7 +472,7 @@ pgm_per: | |||
464 | # Normal per exception | 472 | # Normal per exception |
465 | # | 473 | # |
466 | pgm_per_std: | 474 | pgm_per_std: |
467 | SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 | 475 | SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA |
468 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA | 476 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA |
469 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 477 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
470 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 478 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
@@ -490,7 +498,7 @@ pgm_no_vtime2: | |||
490 | # it was a single stepped SVC that is causing all the trouble | 498 | # it was a single stepped SVC that is causing all the trouble |
491 | # | 499 | # |
492 | pgm_svcper: | 500 | pgm_svcper: |
493 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 501 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
494 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 502 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
495 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 503 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
496 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 504 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
@@ -519,7 +527,7 @@ io_int_handler: | |||
519 | STORE_TIMER __LC_ASYNC_ENTER_TIMER | 527 | STORE_TIMER __LC_ASYNC_ENTER_TIMER |
520 | stck __LC_INT_CLOCK | 528 | stck __LC_INT_CLOCK |
521 | SAVE_ALL_BASE __LC_SAVE_AREA+16 | 529 | SAVE_ALL_BASE __LC_SAVE_AREA+16 |
522 | SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+16,0 | 530 | SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 |
523 | CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 | 531 | CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 |
524 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 532 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
525 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 533 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
@@ -631,7 +639,7 @@ ext_int_handler: | |||
631 | STORE_TIMER __LC_ASYNC_ENTER_TIMER | 639 | STORE_TIMER __LC_ASYNC_ENTER_TIMER |
632 | stck __LC_INT_CLOCK | 640 | stck __LC_INT_CLOCK |
633 | SAVE_ALL_BASE __LC_SAVE_AREA+16 | 641 | SAVE_ALL_BASE __LC_SAVE_AREA+16 |
634 | SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16,0 | 642 | SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 |
635 | CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 | 643 | CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 |
636 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 644 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
637 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 645 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
@@ -657,21 +665,31 @@ __critical_end: | |||
657 | .globl mcck_int_handler | 665 | .globl mcck_int_handler |
658 | mcck_int_handler: | 666 | mcck_int_handler: |
659 | spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer | 667 | spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer |
660 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA | ||
661 | lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs | 668 | lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs |
662 | SAVE_ALL_BASE __LC_SAVE_AREA+32 | 669 | SAVE_ALL_BASE __LC_SAVE_AREA+32 |
663 | la %r12,__LC_MCK_OLD_PSW | 670 | la %r12,__LC_MCK_OLD_PSW |
664 | tm __LC_MCCK_CODE,0x80 # system damage? | 671 | tm __LC_MCCK_CODE,0x80 # system damage? |
665 | bo BASED(mcck_int_main) # yes -> rest of mcck code invalid | 672 | bo BASED(mcck_int_main) # yes -> rest of mcck code invalid |
666 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? | ||
667 | bo BASED(0f) | ||
668 | spt __LC_LAST_UPDATE_TIMER # revalidate cpu timer | ||
669 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 673 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
670 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER | 674 | mvc __LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER |
671 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER | 675 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA |
672 | mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER | 676 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? |
677 | bo BASED(1f) | ||
678 | la %r14,__LC_SYNC_ENTER_TIMER | ||
679 | clc 0(8,%r14),__LC_ASYNC_ENTER_TIMER | ||
680 | bl BASED(0f) | ||
681 | la %r14,__LC_ASYNC_ENTER_TIMER | ||
682 | 0: clc 0(8,%r14),__LC_EXIT_TIMER | ||
683 | bl BASED(0f) | ||
684 | la %r14,__LC_EXIT_TIMER | ||
685 | 0: clc 0(8,%r14),__LC_LAST_UPDATE_TIMER | ||
686 | bl BASED(0f) | ||
687 | la %r14,__LC_LAST_UPDATE_TIMER | ||
688 | 0: spt 0(%r14) | ||
689 | mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) | ||
690 | 1: | ||
673 | #endif | 691 | #endif |
674 | 0: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | 692 | tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? |
675 | bno BASED(mcck_int_main) # no -> skip cleanup critical | 693 | bno BASED(mcck_int_main) # no -> skip cleanup critical |
676 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit | 694 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit |
677 | bnz BASED(mcck_int_main) # from user -> load async stack | 695 | bnz BASED(mcck_int_main) # from user -> load async stack |
@@ -691,7 +709,7 @@ mcck_int_main: | |||
691 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 709 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
692 | tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | 710 | tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? |
693 | bno BASED(mcck_no_vtime) # no -> skip cleanup critical | 711 | bno BASED(mcck_no_vtime) # no -> skip cleanup critical |
694 | tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? | 712 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
695 | bz BASED(mcck_no_vtime) | 713 | bz BASED(mcck_no_vtime) |
696 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | 714 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER |
697 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 715 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
@@ -715,6 +733,20 @@ mcck_no_vtime: | |||
715 | l %r1,BASED(.Ls390_handle_mcck) | 733 | l %r1,BASED(.Ls390_handle_mcck) |
716 | basr %r14,%r1 # call machine check handler | 734 | basr %r14,%r1 # call machine check handler |
717 | mcck_return: | 735 | mcck_return: |
736 | mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW | ||
737 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit | ||
738 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
739 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+52 | ||
740 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? | ||
741 | bno BASED(0f) | ||
742 | lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 | ||
743 | stpt __LC_EXIT_TIMER | ||
744 | lpsw __LC_RETURN_MCCK_PSW # back to caller | ||
745 | 0: | ||
746 | #endif | ||
747 | lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 | ||
748 | lpsw __LC_RETURN_MCCK_PSW # back to caller | ||
749 | |||
718 | RESTORE_ALL __LC_RETURN_MCCK_PSW,0 | 750 | RESTORE_ALL __LC_RETURN_MCCK_PSW,0 |
719 | 751 | ||
720 | #ifdef CONFIG_SMP | 752 | #ifdef CONFIG_SMP |
@@ -781,6 +813,8 @@ cleanup_table_sysc_leave: | |||
781 | .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000 | 813 | .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000 |
782 | cleanup_table_sysc_work_loop: | 814 | cleanup_table_sysc_work_loop: |
783 | .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000 | 815 | .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000 |
816 | cleanup_table_io_return: | ||
817 | .long io_return + 0x80000000, io_leave + 0x80000000 | ||
784 | cleanup_table_io_leave: | 818 | cleanup_table_io_leave: |
785 | .long io_leave + 0x80000000, io_done + 0x80000000 | 819 | .long io_leave + 0x80000000, io_done + 0x80000000 |
786 | cleanup_table_io_work_loop: | 820 | cleanup_table_io_work_loop: |
@@ -807,6 +841,11 @@ cleanup_critical: | |||
807 | clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) | 841 | clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) |
808 | bl BASED(cleanup_sysc_return) | 842 | bl BASED(cleanup_sysc_return) |
809 | 0: | 843 | 0: |
844 | clc 4(4,%r12),BASED(cleanup_table_io_return) | ||
845 | bl BASED(0f) | ||
846 | clc 4(4,%r12),BASED(cleanup_table_io_return+4) | ||
847 | bl BASED(cleanup_io_return) | ||
848 | 0: | ||
810 | clc 4(4,%r12),BASED(cleanup_table_io_leave) | 849 | clc 4(4,%r12),BASED(cleanup_table_io_leave) |
811 | bl BASED(0f) | 850 | bl BASED(0f) |
812 | clc 4(4,%r12),BASED(cleanup_table_io_leave+4) | 851 | clc 4(4,%r12),BASED(cleanup_table_io_leave+4) |
@@ -839,7 +878,7 @@ cleanup_system_call: | |||
839 | mvc __LC_SAVE_AREA(16),0(%r12) | 878 | mvc __LC_SAVE_AREA(16),0(%r12) |
840 | 0: st %r13,4(%r12) | 879 | 0: st %r13,4(%r12) |
841 | st %r12,__LC_SAVE_AREA+48 # argh | 880 | st %r12,__LC_SAVE_AREA+48 # argh |
842 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 881 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
843 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 882 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
844 | l %r12,__LC_SAVE_AREA+48 # argh | 883 | l %r12,__LC_SAVE_AREA+48 # argh |
845 | st %r15,12(%r12) | 884 | st %r15,12(%r12) |
@@ -980,7 +1019,6 @@ cleanup_io_leave_insn: | |||
980 | .long cleanup_critical | 1019 | .long cleanup_critical |
981 | 1020 | ||
982 | #define SYSCALL(esa,esame,emu) .long esa | 1021 | #define SYSCALL(esa,esame,emu) .long esa |
983 | .globl sys_call_table | ||
984 | sys_call_table: | 1022 | sys_call_table: |
985 | #include "syscalls.S" | 1023 | #include "syscalls.S" |
986 | #undef SYSCALL | 1024 | #undef SYSCALL |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 2ac095bc0e25..f3222a1b2861 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -87,13 +87,22 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ | |||
87 | larl %r13,system_call | 87 | larl %r13,system_call |
88 | .endm | 88 | .endm |
89 | 89 | ||
90 | .macro SAVE_ALL psworg,savearea,sync | 90 | .macro SAVE_ALL_SYNC psworg,savearea |
91 | la %r12,\psworg | 91 | la %r12,\psworg |
92 | .if \sync | ||
93 | tm \psworg+1,0x01 # test problem state bit | 92 | tm \psworg+1,0x01 # test problem state bit |
94 | jz 2f # skip stack setup save | 93 | jz 2f # skip stack setup save |
95 | lg %r15,__LC_KERNEL_STACK # problem state -> load ksp | 94 | lg %r15,__LC_KERNEL_STACK # problem state -> load ksp |
96 | .else | 95 | #ifdef CONFIG_CHECK_STACK |
96 | j 3f | ||
97 | 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD | ||
98 | jz stack_overflow | ||
99 | 3: | ||
100 | #endif | ||
101 | 2: | ||
102 | .endm | ||
103 | |||
104 | .macro SAVE_ALL_ASYNC psworg,savearea | ||
105 | la %r12,\psworg | ||
97 | tm \psworg+1,0x01 # test problem state bit | 106 | tm \psworg+1,0x01 # test problem state bit |
98 | jnz 1f # from user -> load kernel stack | 107 | jnz 1f # from user -> load kernel stack |
99 | clc \psworg+8(8),BASED(.Lcritical_end) | 108 | clc \psworg+8(8),BASED(.Lcritical_end) |
@@ -108,7 +117,6 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ | |||
108 | srag %r14,%r14,STACK_SHIFT | 117 | srag %r14,%r14,STACK_SHIFT |
109 | jz 2f | 118 | jz 2f |
110 | 1: lg %r15,__LC_ASYNC_STACK # load async stack | 119 | 1: lg %r15,__LC_ASYNC_STACK # load async stack |
111 | .endif | ||
112 | #ifdef CONFIG_CHECK_STACK | 120 | #ifdef CONFIG_CHECK_STACK |
113 | j 3f | 121 | j 3f |
114 | 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD | 122 | 2: tml %r15,STACK_SIZE - CONFIG_STACK_GUARD |
@@ -187,7 +195,7 @@ system_call: | |||
187 | STORE_TIMER __LC_SYNC_ENTER_TIMER | 195 | STORE_TIMER __LC_SYNC_ENTER_TIMER |
188 | sysc_saveall: | 196 | sysc_saveall: |
189 | SAVE_ALL_BASE __LC_SAVE_AREA | 197 | SAVE_ALL_BASE __LC_SAVE_AREA |
190 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 198 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
191 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 199 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
192 | llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore | 200 | llgh %r7,__LC_SVC_INT_CODE # get svc number from lowcore |
193 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 201 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
@@ -446,7 +454,7 @@ pgm_check_handler: | |||
446 | SAVE_ALL_BASE __LC_SAVE_AREA | 454 | SAVE_ALL_BASE __LC_SAVE_AREA |
447 | tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception | 455 | tm __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception |
448 | jnz pgm_per # got per exception -> special case | 456 | jnz pgm_per # got per exception -> special case |
449 | SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 | 457 | SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA |
450 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA | 458 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA |
451 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 459 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
452 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 460 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
@@ -485,7 +493,7 @@ pgm_per: | |||
485 | # Normal per exception | 493 | # Normal per exception |
486 | # | 494 | # |
487 | pgm_per_std: | 495 | pgm_per_std: |
488 | SAVE_ALL __LC_PGM_OLD_PSW,__LC_SAVE_AREA,1 | 496 | SAVE_ALL_SYNC __LC_PGM_OLD_PSW,__LC_SAVE_AREA |
489 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA | 497 | CREATE_STACK_FRAME __LC_PGM_OLD_PSW,__LC_SAVE_AREA |
490 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 498 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
491 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 499 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
@@ -511,7 +519,7 @@ pgm_no_vtime2: | |||
511 | # it was a single stepped SVC that is causing all the trouble | 519 | # it was a single stepped SVC that is causing all the trouble |
512 | # | 520 | # |
513 | pgm_svcper: | 521 | pgm_svcper: |
514 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 522 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
515 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 523 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
516 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 524 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
517 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 525 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
@@ -539,7 +547,7 @@ io_int_handler: | |||
539 | STORE_TIMER __LC_ASYNC_ENTER_TIMER | 547 | STORE_TIMER __LC_ASYNC_ENTER_TIMER |
540 | stck __LC_INT_CLOCK | 548 | stck __LC_INT_CLOCK |
541 | SAVE_ALL_BASE __LC_SAVE_AREA+32 | 549 | SAVE_ALL_BASE __LC_SAVE_AREA+32 |
542 | SAVE_ALL __LC_IO_OLD_PSW,__LC_SAVE_AREA+32,0 | 550 | SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 |
543 | CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 | 551 | CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 |
544 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 552 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
545 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 553 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
@@ -647,7 +655,7 @@ ext_int_handler: | |||
647 | STORE_TIMER __LC_ASYNC_ENTER_TIMER | 655 | STORE_TIMER __LC_ASYNC_ENTER_TIMER |
648 | stck __LC_INT_CLOCK | 656 | stck __LC_INT_CLOCK |
649 | SAVE_ALL_BASE __LC_SAVE_AREA+32 | 657 | SAVE_ALL_BASE __LC_SAVE_AREA+32 |
650 | SAVE_ALL __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32,0 | 658 | SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 |
651 | CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 | 659 | CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 |
652 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 660 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
653 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 661 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
@@ -672,21 +680,32 @@ __critical_end: | |||
672 | mcck_int_handler: | 680 | mcck_int_handler: |
673 | la %r1,4095 # revalidate r1 | 681 | la %r1,4095 # revalidate r1 |
674 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer | 682 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer |
675 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r1) | ||
676 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs | 683 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs |
677 | SAVE_ALL_BASE __LC_SAVE_AREA+64 | 684 | SAVE_ALL_BASE __LC_SAVE_AREA+64 |
678 | la %r12,__LC_MCK_OLD_PSW | 685 | la %r12,__LC_MCK_OLD_PSW |
679 | tm __LC_MCCK_CODE,0x80 # system damage? | 686 | tm __LC_MCCK_CODE,0x80 # system damage? |
680 | jo mcck_int_main # yes -> rest of mcck code invalid | 687 | jo mcck_int_main # yes -> rest of mcck code invalid |
681 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? | ||
682 | jo 0f | ||
683 | spt __LC_LAST_UPDATE_TIMER | ||
684 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 688 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
685 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER | 689 | la %r14,4095 |
686 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER | 690 | mvc __LC_SAVE_AREA+104(8),__LC_ASYNC_ENTER_TIMER |
687 | mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER | 691 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r14) |
692 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? | ||
693 | jo 1f | ||
694 | la %r14,__LC_SYNC_ENTER_TIMER | ||
695 | clc 0(8,%r14),__LC_ASYNC_ENTER_TIMER | ||
696 | jl 0f | ||
697 | la %r14,__LC_ASYNC_ENTER_TIMER | ||
698 | 0: clc 0(8,%r14),__LC_EXIT_TIMER | ||
699 | jl 0f | ||
700 | la %r14,__LC_EXIT_TIMER | ||
701 | 0: clc 0(8,%r14),__LC_LAST_UPDATE_TIMER | ||
702 | jl 0f | ||
703 | la %r14,__LC_LAST_UPDATE_TIMER | ||
704 | 0: spt 0(%r14) | ||
705 | mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) | ||
706 | 1: | ||
688 | #endif | 707 | #endif |
689 | 0: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | 708 | tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? |
690 | jno mcck_int_main # no -> skip cleanup critical | 709 | jno mcck_int_main # no -> skip cleanup critical |
691 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit | 710 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit |
692 | jnz mcck_int_main # from user -> load kernel stack | 711 | jnz mcck_int_main # from user -> load kernel stack |
@@ -705,7 +724,7 @@ mcck_int_main: | |||
705 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 724 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
706 | tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | 725 | tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? |
707 | jno mcck_no_vtime # no -> no timer update | 726 | jno mcck_no_vtime # no -> no timer update |
708 | tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? | 727 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
709 | jz mcck_no_vtime | 728 | jz mcck_no_vtime |
710 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | 729 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER |
711 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 730 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
@@ -727,7 +746,17 @@ mcck_no_vtime: | |||
727 | jno mcck_return | 746 | jno mcck_return |
728 | brasl %r14,s390_handle_mcck | 747 | brasl %r14,s390_handle_mcck |
729 | mcck_return: | 748 | mcck_return: |
730 | RESTORE_ALL __LC_RETURN_MCCK_PSW,0 | 749 | mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW |
750 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit | ||
751 | lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 | ||
752 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
753 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+104 | ||
754 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? | ||
755 | jno 0f | ||
756 | stpt __LC_EXIT_TIMER | ||
757 | 0: | ||
758 | #endif | ||
759 | lpswe __LC_RETURN_MCCK_PSW # back to caller | ||
731 | 760 | ||
732 | #ifdef CONFIG_SMP | 761 | #ifdef CONFIG_SMP |
733 | /* | 762 | /* |
@@ -789,6 +818,8 @@ cleanup_table_sysc_leave: | |||
789 | .quad sysc_leave, sysc_work_loop | 818 | .quad sysc_leave, sysc_work_loop |
790 | cleanup_table_sysc_work_loop: | 819 | cleanup_table_sysc_work_loop: |
791 | .quad sysc_work_loop, sysc_reschedule | 820 | .quad sysc_work_loop, sysc_reschedule |
821 | cleanup_table_io_return: | ||
822 | .quad io_return, io_leave | ||
792 | cleanup_table_io_leave: | 823 | cleanup_table_io_leave: |
793 | .quad io_leave, io_done | 824 | .quad io_leave, io_done |
794 | cleanup_table_io_work_loop: | 825 | cleanup_table_io_work_loop: |
@@ -815,6 +846,11 @@ cleanup_critical: | |||
815 | clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) | 846 | clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) |
816 | jl cleanup_sysc_return | 847 | jl cleanup_sysc_return |
817 | 0: | 848 | 0: |
849 | clc 8(8,%r12),BASED(cleanup_table_io_return) | ||
850 | jl 0f | ||
851 | clc 8(8,%r12),BASED(cleanup_table_io_return+8) | ||
852 | jl cleanup_io_return | ||
853 | 0: | ||
818 | clc 8(8,%r12),BASED(cleanup_table_io_leave) | 854 | clc 8(8,%r12),BASED(cleanup_table_io_leave) |
819 | jl 0f | 855 | jl 0f |
820 | clc 8(8,%r12),BASED(cleanup_table_io_leave+8) | 856 | clc 8(8,%r12),BASED(cleanup_table_io_leave+8) |
@@ -847,7 +883,7 @@ cleanup_system_call: | |||
847 | mvc __LC_SAVE_AREA(32),0(%r12) | 883 | mvc __LC_SAVE_AREA(32),0(%r12) |
848 | 0: stg %r13,8(%r12) | 884 | 0: stg %r13,8(%r12) |
849 | stg %r12,__LC_SAVE_AREA+96 # argh | 885 | stg %r12,__LC_SAVE_AREA+96 # argh |
850 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 886 | SAVE_ALL_SYNC __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
851 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 887 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
852 | lg %r12,__LC_SAVE_AREA+96 # argh | 888 | lg %r12,__LC_SAVE_AREA+96 # argh |
853 | stg %r15,24(%r12) | 889 | stg %r15,24(%r12) |
@@ -957,7 +993,6 @@ cleanup_io_leave_insn: | |||
957 | .quad __critical_end | 993 | .quad __critical_end |
958 | 994 | ||
959 | #define SYSCALL(esa,esame,emu) .long esame | 995 | #define SYSCALL(esa,esame,emu) .long esame |
960 | .globl sys_call_table | ||
961 | sys_call_table: | 996 | sys_call_table: |
962 | #include "syscalls.S" | 997 | #include "syscalls.S" |
963 | #undef SYSCALL | 998 | #undef SYSCALL |
@@ -965,7 +1000,6 @@ sys_call_table: | |||
965 | #ifdef CONFIG_COMPAT | 1000 | #ifdef CONFIG_COMPAT |
966 | 1001 | ||
967 | #define SYSCALL(esa,esame,emu) .long emu | 1002 | #define SYSCALL(esa,esame,emu) .long emu |
968 | .globl sys_call_table_emu | ||
969 | sys_call_table_emu: | 1003 | sys_call_table_emu: |
970 | #include "syscalls.S" | 1004 | #include "syscalls.S" |
971 | #undef SYSCALL | 1005 | #undef SYSCALL |
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S index ea88d066bf04..538c82da49b1 100644 --- a/arch/s390/kernel/head.S +++ b/arch/s390/kernel/head.S | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/s390/kernel/head.S | 2 | * arch/s390/kernel/head.S |
3 | * | 3 | * |
4 | * (C) Copyright IBM Corp. 1999, 2005 | 4 | * Copyright (C) IBM Corp. 1999,2006 |
5 | * | 5 | * |
6 | * Author(s): Hartmut Penner <hp@de.ibm.com> | 6 | * Author(s): Hartmut Penner <hp@de.ibm.com> |
7 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 7 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
@@ -482,24 +482,23 @@ start: | |||
482 | 482 | ||
483 | .macro GET_IPL_DEVICE | 483 | .macro GET_IPL_DEVICE |
484 | .Lget_ipl_device: | 484 | .Lget_ipl_device: |
485 | basr %r12,0 | 485 | l %r1,0xb8 # get sid |
486 | .LGID: l %r1,0xb8 # get sid | ||
487 | sll %r1,15 # test if subchannel is enabled | 486 | sll %r1,15 # test if subchannel is enabled |
488 | srl %r1,31 | 487 | srl %r1,31 |
489 | ltr %r1,%r1 | 488 | ltr %r1,%r1 |
490 | bz 0(%r14) # subchannel disabled | 489 | bz 2f-.LPG1(%r13) # subchannel disabled |
491 | l %r1,0xb8 | 490 | l %r1,0xb8 |
492 | la %r5,.Lipl_schib-.LGID(%r12) | 491 | la %r5,.Lipl_schib-.LPG1(%r13) |
493 | stsch 0(%r5) # get schib of subchannel | 492 | stsch 0(%r5) # get schib of subchannel |
494 | bnz 0(%r14) # schib not available | 493 | bnz 2f-.LPG1(%r13) # schib not available |
495 | tm 5(%r5),0x01 # devno valid? | 494 | tm 5(%r5),0x01 # devno valid? |
496 | bno 0(%r14) | 495 | bno 2f-.LPG1(%r13) |
497 | la %r6,ipl_parameter_flags-.LGID(%r12) | 496 | la %r6,ipl_parameter_flags-.LPG1(%r13) |
498 | oi 3(%r6),0x01 # set flag | 497 | oi 3(%r6),0x01 # set flag |
499 | la %r2,ipl_devno-.LGID(%r12) | 498 | la %r2,ipl_devno-.LPG1(%r13) |
500 | mvc 0(2,%r2),6(%r5) # store devno | 499 | mvc 0(2,%r2),6(%r5) # store devno |
501 | tm 4(%r5),0x80 # qdio capable device? | 500 | tm 4(%r5),0x80 # qdio capable device? |
502 | bno 0(%r14) | 501 | bno 2f-.LPG1(%r13) |
503 | oi 3(%r6),0x02 # set flag | 502 | oi 3(%r6),0x02 # set flag |
504 | 503 | ||
505 | # copy ipl parameters | 504 | # copy ipl parameters |
@@ -523,7 +522,7 @@ start: | |||
523 | ar %r2,%r1 | 522 | ar %r2,%r1 |
524 | sr %r0,%r4 | 523 | sr %r0,%r4 |
525 | jne 1b | 524 | jne 1b |
526 | b 0(%r14) | 525 | b 2f-.LPG1(%r13) |
527 | 526 | ||
528 | .align 4 | 527 | .align 4 |
529 | .Lipl_schib: | 528 | .Lipl_schib: |
@@ -537,6 +536,7 @@ ipl_parameter_flags: | |||
537 | .globl ipl_devno | 536 | .globl ipl_devno |
538 | ipl_devno: | 537 | ipl_devno: |
539 | .word 0 | 538 | .word 0 |
539 | 2: | ||
540 | .endm | 540 | .endm |
541 | 541 | ||
542 | #ifdef CONFIG_64BIT | 542 | #ifdef CONFIG_64BIT |
diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index 2d3b089bfb83..d00de17b3778 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/s390/kernel/head31.S | 2 | * arch/s390/kernel/head31.S |
3 | * | 3 | * |
4 | * (C) Copyright IBM Corp. 2005 | 4 | * Copyright (C) IBM Corp. 2005,2006 |
5 | * | 5 | * |
6 | * Author(s): Hartmut Penner <hp@de.ibm.com> | 6 | * Author(s): Hartmut Penner <hp@de.ibm.com> |
7 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 7 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
@@ -16,12 +16,31 @@ | |||
16 | # or linload or SALIPL | 16 | # or linload or SALIPL |
17 | # | 17 | # |
18 | .org 0x10000 | 18 | .org 0x10000 |
19 | startup:basr %r13,0 # get base | 19 | startup:basr %r13,0 # get base |
20 | .LPG1: l %r1, .Lget_ipl_device_addr-.LPG1(%r13) | 20 | .LPG0: l %r13,0f-.LPG0(%r13) |
21 | basr %r14, %r1 | 21 | b 0(%r13) |
22 | 0: .long startup_continue | ||
23 | |||
24 | # | ||
25 | # params at 10400 (setup.h) | ||
26 | # | ||
27 | .org PARMAREA | ||
28 | .long 0,0 # IPL_DEVICE | ||
29 | .long 0,RAMDISK_ORIGIN # INITRD_START | ||
30 | .long 0,RAMDISK_SIZE # INITRD_SIZE | ||
31 | |||
32 | .org COMMAND_LINE | ||
33 | .byte "root=/dev/ram0 ro" | ||
34 | .byte 0 | ||
35 | |||
36 | .org 0x11000 | ||
37 | |||
38 | startup_continue: | ||
39 | basr %r13,0 # get base | ||
40 | .LPG1: GET_IPL_DEVICE | ||
22 | lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers | 41 | lctl %c0,%c15,.Lctl-.LPG1(%r13) # load control registers |
23 | la %r12,_pstart-.LPG1(%r13) # pointer to parameter area | 42 | l %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area |
24 | # move IPL device to lowcore | 43 | # move IPL device to lowcore |
25 | mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12) | 44 | mvc __LC_IPLDEV(4),IPL_DEVICE-PARMAREA(%r12) |
26 | 45 | ||
27 | # | 46 | # |
@@ -51,8 +70,8 @@ startup:basr %r13,0 # get base | |||
51 | a %r1,__LC_EXT_NEW_PSW+4 # set handler | 70 | a %r1,__LC_EXT_NEW_PSW+4 # set handler |
52 | st %r1,__LC_EXT_NEW_PSW+4 | 71 | st %r1,__LC_EXT_NEW_PSW+4 |
53 | 72 | ||
54 | la %r4,_pstart-.LPG1(%r13) # %r4 is our index for sccb stuff | 73 | l %r4,.Lsccbaddr-.LPG1(%r13) # %r4 is our index for sccb stuff |
55 | la %r1, .Lsccb-PARMAREA(%r4) # our sccb | 74 | lr %r1,%r4 # our sccb |
56 | .insn rre,0xb2200000,%r2,%r1 # service call | 75 | .insn rre,0xb2200000,%r2,%r1 # service call |
57 | ipm %r1 | 76 | ipm %r1 |
58 | srl %r1,28 # get cc code | 77 | srl %r1,28 # get cc code |
@@ -63,7 +82,7 @@ startup:basr %r13,0 # get base | |||
63 | be .Lservicecall-.LPG1(%r13) | 82 | be .Lservicecall-.LPG1(%r13) |
64 | lpsw .Lwaitsclp-.LPG1(%r13) | 83 | lpsw .Lwaitsclp-.LPG1(%r13) |
65 | .Lsclph: | 84 | .Lsclph: |
66 | lh %r1,.Lsccbr-PARMAREA(%r4) | 85 | lh %r1,.Lsccbr-.Lsccb(%r4) |
67 | chi %r1,0x10 # 0x0010 is the sucess code | 86 | chi %r1,0x10 # 0x0010 is the sucess code |
68 | je .Lprocsccb # let's process the sccb | 87 | je .Lprocsccb # let's process the sccb |
69 | chi %r1,0x1f0 | 88 | chi %r1,0x1f0 |
@@ -74,7 +93,7 @@ startup:basr %r13,0 # get base | |||
74 | b .Lservicecall-.LPG1(%r13) | 93 | b .Lservicecall-.LPG1(%r13) |
75 | .Lprocsccb: | 94 | .Lprocsccb: |
76 | lhi %r1,0 | 95 | lhi %r1,0 |
77 | icm %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0 | 96 | icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0 |
78 | jnz .Lscnd | 97 | jnz .Lscnd |
79 | lhi %r1,0x800 # otherwise report 2GB | 98 | lhi %r1,0x800 # otherwise report 2GB |
80 | .Lscnd: | 99 | .Lscnd: |
@@ -84,10 +103,10 @@ startup:basr %r13,0 # get base | |||
84 | lr %r1,%r3 | 103 | lr %r1,%r3 |
85 | .Lno2gb: | 104 | .Lno2gb: |
86 | xr %r3,%r3 # same logic | 105 | xr %r3,%r3 # same logic |
87 | ic %r3,.Lscpa1-PARMAREA(%r4) | 106 | ic %r3,.Lscpa1-.Lsccb(%r4) |
88 | chi %r3,0x00 | 107 | chi %r3,0x00 |
89 | jne .Lcompmem | 108 | jne .Lcompmem |
90 | l %r3,.Lscpa2-PARMAREA(%r13) | 109 | l %r3,.Lscpa2-.Lsccb(%r4) |
91 | .Lcompmem: | 110 | .Lcompmem: |
92 | mr %r2,%r1 # mem in MB on 128-bit | 111 | mr %r2,%r1 # mem in MB on 128-bit |
93 | l %r1,.Lonemb-.LPG1(%r13) | 112 | l %r1,.Lonemb-.LPG1(%r13) |
@@ -95,8 +114,6 @@ startup:basr %r13,0 # get base | |||
95 | b .Lfchunk-.LPG1(%r13) | 114 | b .Lfchunk-.LPG1(%r13) |
96 | 115 | ||
97 | .align 4 | 116 | .align 4 |
98 | .Lget_ipl_device_addr: | ||
99 | .long .Lget_ipl_device | ||
100 | .Lpmask: | 117 | .Lpmask: |
101 | .byte 0 | 118 | .byte 0 |
102 | .align 8 | 119 | .align 8 |
@@ -242,6 +259,8 @@ startup:basr %r13,0 # get base | |||
242 | .long 0 # cr13: home space segment table | 259 | .long 0 # cr13: home space segment table |
243 | .long 0xc0000000 # cr14: machine check handling off | 260 | .long 0xc0000000 # cr14: machine check handling off |
244 | .long 0 # cr15: linkage stack operations | 261 | .long 0 # cr15: linkage stack operations |
262 | .Lduct: .long 0,0,0,0,0,0,0,0 | ||
263 | .long 0,0,0,0,0,0,0,0 | ||
245 | .Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem | 264 | .Lpcmem:.long 0x00080000,0x80000000 + .Lchkmem |
246 | .Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu | 265 | .Lpcfpu:.long 0x00080000,0x80000000 + .Lchkfpu |
247 | .Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp | 266 | .Lpccsp:.long 0x00080000,0x80000000 + .Lchkcsp |
@@ -252,25 +271,9 @@ startup:basr %r13,0 # get base | |||
252 | .Lmflags:.long machine_flags | 271 | .Lmflags:.long machine_flags |
253 | .Lbss_bgn: .long __bss_start | 272 | .Lbss_bgn: .long __bss_start |
254 | .Lbss_end: .long _end | 273 | .Lbss_end: .long _end |
255 | 274 | .Lparmaddr: .long PARMAREA | |
256 | .org PARMAREA-64 | 275 | .Lsccbaddr: .long .Lsccb |
257 | .Lduct: .long 0,0,0,0,0,0,0,0 | 276 | .align 4096 |
258 | .long 0,0,0,0,0,0,0,0 | ||
259 | |||
260 | # | ||
261 | # params at 10400 (setup.h) | ||
262 | # | ||
263 | .org PARMAREA | ||
264 | .global _pstart | ||
265 | _pstart: | ||
266 | .long 0,0 # IPL_DEVICE | ||
267 | .long 0,RAMDISK_ORIGIN # INITRD_START | ||
268 | .long 0,RAMDISK_SIZE # INITRD_SIZE | ||
269 | |||
270 | .org COMMAND_LINE | ||
271 | .byte "root=/dev/ram0 ro" | ||
272 | .byte 0 | ||
273 | .org 0x11000 | ||
274 | .Lsccb: | 277 | .Lsccb: |
275 | .hword 0x1000 # length, one page | 278 | .hword 0x1000 # length, one page |
276 | .byte 0x00,0x00,0x00 | 279 | .byte 0x00,0x00,0x00 |
@@ -287,18 +290,14 @@ _pstart: | |||
287 | .Lscpincr2: | 290 | .Lscpincr2: |
288 | .quad 0x00 | 291 | .quad 0x00 |
289 | .fill 3984,1,0 | 292 | .fill 3984,1,0 |
290 | .org 0x12000 | 293 | .align 4096 |
291 | .global _pend | ||
292 | _pend: | ||
293 | |||
294 | GET_IPL_DEVICE | ||
295 | 294 | ||
296 | #ifdef CONFIG_SHARED_KERNEL | 295 | #ifdef CONFIG_SHARED_KERNEL |
297 | .org 0x100000 | 296 | .org 0x100000 |
298 | #endif | 297 | #endif |
299 | 298 | ||
300 | # | 299 | # |
301 | # startup-code, running in virtual mode | 300 | # startup-code, running in absolute addressing mode |
302 | # | 301 | # |
303 | .globl _stext | 302 | .globl _stext |
304 | _stext: basr %r13,0 # get base | 303 | _stext: basr %r13,0 # get base |
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index f08c06f45d5c..47744fcca930 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/s390/kernel/head64.S | 2 | * arch/s390/kernel/head64.S |
3 | * | 3 | * |
4 | * (C) Copyright IBM Corp. 1999,2005 | 4 | * Copyright (C) IBM Corp. 1999,2006 |
5 | * | 5 | * |
6 | * Author(s): Hartmut Penner <hp@de.ibm.com> | 6 | * Author(s): Hartmut Penner <hp@de.ibm.com> |
7 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 7 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
@@ -15,18 +15,37 @@ | |||
15 | # this is called either by the ipl loader or directly by PSW restart | 15 | # this is called either by the ipl loader or directly by PSW restart |
16 | # or linload or SALIPL | 16 | # or linload or SALIPL |
17 | # | 17 | # |
18 | .org 0x10000 | 18 | .org 0x10000 |
19 | startup:basr %r13,0 # get base | 19 | startup:basr %r13,0 # get base |
20 | .LPG0: l %r13,0f-.LPG0(%r13) | ||
21 | b 0(%r13) | ||
22 | 0: .long startup_continue | ||
23 | |||
24 | # | ||
25 | # params at 10400 (setup.h) | ||
26 | # | ||
27 | .org PARMAREA | ||
28 | .quad 0 # IPL_DEVICE | ||
29 | .quad RAMDISK_ORIGIN # INITRD_START | ||
30 | .quad RAMDISK_SIZE # INITRD_SIZE | ||
31 | |||
32 | .org COMMAND_LINE | ||
33 | .byte "root=/dev/ram0 ro" | ||
34 | .byte 0 | ||
35 | |||
36 | .org 0x11000 | ||
37 | |||
38 | startup_continue: | ||
39 | basr %r13,0 # get base | ||
20 | .LPG1: sll %r13,1 # remove high order bit | 40 | .LPG1: sll %r13,1 # remove high order bit |
21 | srl %r13,1 | 41 | srl %r13,1 |
22 | l %r1,.Lget_ipl_device_addr-.LPG1(%r13) | 42 | GET_IPL_DEVICE |
23 | basr %r14,%r1 | ||
24 | lhi %r1,1 # mode 1 = esame | 43 | lhi %r1,1 # mode 1 = esame |
25 | slr %r0,%r0 # set cpuid to zero | 44 | slr %r0,%r0 # set cpuid to zero |
26 | sigp %r1,%r0,0x12 # switch to esame mode | 45 | sigp %r1,%r0,0x12 # switch to esame mode |
27 | sam64 # switch to 64 bit mode | 46 | sam64 # switch to 64 bit mode |
28 | lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers | 47 | lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers |
29 | larl %r12,_pstart # pointer to parameter area | 48 | lg %r12,.Lparmaddr-.LPG1(%r13)# pointer to parameter area |
30 | # move IPL device to lowcore | 49 | # move IPL device to lowcore |
31 | mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12) | 50 | mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12) |
32 | 51 | ||
@@ -55,8 +74,8 @@ startup:basr %r13,0 # get base | |||
55 | larl %r1,.Lsclph | 74 | larl %r1,.Lsclph |
56 | stg %r1,__LC_EXT_NEW_PSW+8 # set handler | 75 | stg %r1,__LC_EXT_NEW_PSW+8 # set handler |
57 | 76 | ||
58 | larl %r4,_pstart # %r4 is our index for sccb stuff | 77 | larl %r4,.Lsccb # %r4 is our index for sccb stuff |
59 | la %r1,.Lsccb-PARMAREA(%r4) # our sccb | 78 | lgr %r1,%r4 # our sccb |
60 | .insn rre,0xb2200000,%r2,%r1 # service call | 79 | .insn rre,0xb2200000,%r2,%r1 # service call |
61 | ipm %r1 | 80 | ipm %r1 |
62 | srl %r1,28 # get cc code | 81 | srl %r1,28 # get cc code |
@@ -67,7 +86,7 @@ startup:basr %r13,0 # get base | |||
67 | be .Lservicecall-.LPG1(%r13) | 86 | be .Lservicecall-.LPG1(%r13) |
68 | lpswe .Lwaitsclp-.LPG1(%r13) | 87 | lpswe .Lwaitsclp-.LPG1(%r13) |
69 | .Lsclph: | 88 | .Lsclph: |
70 | lh %r1,.Lsccbr-PARMAREA(%r4) | 89 | lh %r1,.Lsccbr-.Lsccb(%r4) |
71 | chi %r1,0x10 # 0x0010 is the sucess code | 90 | chi %r1,0x10 # 0x0010 is the sucess code |
72 | je .Lprocsccb # let's process the sccb | 91 | je .Lprocsccb # let's process the sccb |
73 | chi %r1,0x1f0 | 92 | chi %r1,0x1f0 |
@@ -78,15 +97,15 @@ startup:basr %r13,0 # get base | |||
78 | b .Lservicecall-.LPG1(%r13) | 97 | b .Lservicecall-.LPG1(%r13) |
79 | .Lprocsccb: | 98 | .Lprocsccb: |
80 | lghi %r1,0 | 99 | lghi %r1,0 |
81 | icm %r1,3,.Lscpincr1-PARMAREA(%r4) # use this one if != 0 | 100 | icm %r1,3,.Lscpincr1-.Lsccb(%r4) # use this one if != 0 |
82 | jnz .Lscnd | 101 | jnz .Lscnd |
83 | lg %r1,.Lscpincr2-PARMAREA(%r4) # otherwise use this one | 102 | lg %r1,.Lscpincr2-.Lsccb(%r4) # otherwise use this one |
84 | .Lscnd: | 103 | .Lscnd: |
85 | xr %r3,%r3 # same logic | 104 | xr %r3,%r3 # same logic |
86 | ic %r3,.Lscpa1-PARMAREA(%r4) | 105 | ic %r3,.Lscpa1-.Lsccb(%r4) |
87 | chi %r3,0x00 | 106 | chi %r3,0x00 |
88 | jne .Lcompmem | 107 | jne .Lcompmem |
89 | l %r3,.Lscpa2-PARMAREA(%r13) | 108 | l %r3,.Lscpa2-.Lsccb(%r4) |
90 | .Lcompmem: | 109 | .Lcompmem: |
91 | mlgr %r2,%r1 # mem in MB on 128-bit | 110 | mlgr %r2,%r1 # mem in MB on 128-bit |
92 | l %r1,.Lonemb-.LPG1(%r13) | 111 | l %r1,.Lonemb-.LPG1(%r13) |
@@ -94,8 +113,6 @@ startup:basr %r13,0 # get base | |||
94 | b .Lfchunk-.LPG1(%r13) | 113 | b .Lfchunk-.LPG1(%r13) |
95 | 114 | ||
96 | .align 4 | 115 | .align 4 |
97 | .Lget_ipl_device_addr: | ||
98 | .long .Lget_ipl_device | ||
99 | .Lpmask: | 116 | .Lpmask: |
100 | .byte 0 | 117 | .byte 0 |
101 | .align 8 | 118 | .align 8 |
@@ -242,29 +259,16 @@ startup:basr %r13,0 # get base | |||
242 | .quad 0 # cr13: home space segment table | 259 | .quad 0 # cr13: home space segment table |
243 | .quad 0xc0000000 # cr14: machine check handling off | 260 | .quad 0xc0000000 # cr14: machine check handling off |
244 | .quad 0 # cr15: linkage stack operations | 261 | .quad 0 # cr15: linkage stack operations |
262 | .Lduct: .long 0,0,0,0,0,0,0,0 | ||
263 | .long 0,0,0,0,0,0,0,0 | ||
245 | .Lpcmsk:.quad 0x0000000180000000 | 264 | .Lpcmsk:.quad 0x0000000180000000 |
246 | .L4malign:.quad 0xffffffffffc00000 | 265 | .L4malign:.quad 0xffffffffffc00000 |
247 | .Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 | 266 | .Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8 |
248 | .Lnop: .long 0x07000700 | 267 | .Lnop: .long 0x07000700 |
268 | .Lparmaddr: | ||
269 | .quad PARMAREA | ||
249 | 270 | ||
250 | .org PARMAREA-64 | 271 | .align 4096 |
251 | .Lduct: .long 0,0,0,0,0,0,0,0 | ||
252 | .long 0,0,0,0,0,0,0,0 | ||
253 | |||
254 | # | ||
255 | # params at 10400 (setup.h) | ||
256 | # | ||
257 | .org PARMAREA | ||
258 | .global _pstart | ||
259 | _pstart: | ||
260 | .quad 0 # IPL_DEVICE | ||
261 | .quad RAMDISK_ORIGIN # INITRD_START | ||
262 | .quad RAMDISK_SIZE # INITRD_SIZE | ||
263 | |||
264 | .org COMMAND_LINE | ||
265 | .byte "root=/dev/ram0 ro" | ||
266 | .byte 0 | ||
267 | .org 0x11000 | ||
268 | .Lsccb: | 272 | .Lsccb: |
269 | .hword 0x1000 # length, one page | 273 | .hword 0x1000 # length, one page |
270 | .byte 0x00,0x00,0x00 | 274 | .byte 0x00,0x00,0x00 |
@@ -281,18 +285,14 @@ _pstart: | |||
281 | .Lscpincr2: | 285 | .Lscpincr2: |
282 | .quad 0x00 | 286 | .quad 0x00 |
283 | .fill 3984,1,0 | 287 | .fill 3984,1,0 |
284 | .org 0x12000 | 288 | .align 4096 |
285 | .global _pend | ||
286 | _pend: | ||
287 | |||
288 | GET_IPL_DEVICE | ||
289 | 289 | ||
290 | #ifdef CONFIG_SHARED_KERNEL | 290 | #ifdef CONFIG_SHARED_KERNEL |
291 | .org 0x100000 | 291 | .org 0x100000 |
292 | #endif | 292 | #endif |
293 | 293 | ||
294 | # | 294 | # |
295 | # startup-code, running in virtual mode | 295 | # startup-code, running in absolute addressing mode |
296 | # | 296 | # |
297 | .globl _stext | 297 | .globl _stext |
298 | _stext: basr %r13,0 # get base | 298 | _stext: basr %r13,0 # get base |
@@ -326,4 +326,3 @@ _stext: basr %r13,0 # get base | |||
326 | .align 8 | 326 | .align 8 |
327 | .Ldw: .quad 0x0002000180000000,0x0000000000000000 | 327 | .Ldw: .quad 0x0002000180000000,0x0000000000000000 |
328 | .Laregs: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 | 328 | .Laregs: .long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 |
329 | |||
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 4176c77670c4..0886e739d122 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c | |||
@@ -46,8 +46,6 @@ EXPORT_SYMBOL(__down_interruptible); | |||
46 | */ | 46 | */ |
47 | extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs); | 47 | extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs); |
48 | EXPORT_SYMBOL(dump_fpu); | 48 | EXPORT_SYMBOL(dump_fpu); |
49 | EXPORT_SYMBOL(overflowuid); | ||
50 | EXPORT_SYMBOL(overflowgid); | ||
51 | EXPORT_SYMBOL(empty_zero_page); | 49 | EXPORT_SYMBOL(empty_zero_page); |
52 | 50 | ||
53 | /* | 51 | /* |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index b282034452a4..2b2551e3510b 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/seq_file.h> | 37 | #include <linux/seq_file.h> |
38 | #include <linux/kernel_stat.h> | 38 | #include <linux/kernel_stat.h> |
39 | #include <linux/device.h> | 39 | #include <linux/device.h> |
40 | #include <linux/notifier.h> | ||
40 | 41 | ||
41 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
42 | #include <asm/system.h> | 43 | #include <asm/system.h> |
@@ -115,6 +116,7 @@ void __devinit cpu_init (void) | |||
115 | */ | 116 | */ |
116 | char vmhalt_cmd[128] = ""; | 117 | char vmhalt_cmd[128] = ""; |
117 | char vmpoff_cmd[128] = ""; | 118 | char vmpoff_cmd[128] = ""; |
119 | char vmpanic_cmd[128] = ""; | ||
118 | 120 | ||
119 | static inline void strncpy_skip_quote(char *dst, char *src, int n) | 121 | static inline void strncpy_skip_quote(char *dst, char *src, int n) |
120 | { | 122 | { |
@@ -146,6 +148,38 @@ static int __init vmpoff_setup(char *str) | |||
146 | 148 | ||
147 | __setup("vmpoff=", vmpoff_setup); | 149 | __setup("vmpoff=", vmpoff_setup); |
148 | 150 | ||
151 | static int vmpanic_notify(struct notifier_block *self, unsigned long event, | ||
152 | void *data) | ||
153 | { | ||
154 | if (MACHINE_IS_VM && strlen(vmpanic_cmd) > 0) | ||
155 | cpcmd(vmpanic_cmd, NULL, 0, NULL); | ||
156 | |||
157 | return NOTIFY_OK; | ||
158 | } | ||
159 | |||
160 | #define PANIC_PRI_VMPANIC 0 | ||
161 | |||
162 | static struct notifier_block vmpanic_nb = { | ||
163 | .notifier_call = vmpanic_notify, | ||
164 | .priority = PANIC_PRI_VMPANIC | ||
165 | }; | ||
166 | |||
167 | static int __init vmpanic_setup(char *str) | ||
168 | { | ||
169 | static int register_done __initdata = 0; | ||
170 | |||
171 | strncpy_skip_quote(vmpanic_cmd, str, 127); | ||
172 | vmpanic_cmd[127] = 0; | ||
173 | if (!register_done) { | ||
174 | register_done = 1; | ||
175 | atomic_notifier_chain_register(&panic_notifier_list, | ||
176 | &vmpanic_nb); | ||
177 | } | ||
178 | return 1; | ||
179 | } | ||
180 | |||
181 | __setup("vmpanic=", vmpanic_setup); | ||
182 | |||
149 | /* | 183 | /* |
150 | * condev= and conmode= setup parameter. | 184 | * condev= and conmode= setup parameter. |
151 | */ | 185 | */ |
@@ -289,19 +323,34 @@ void (*_machine_power_off)(void) = do_machine_power_off_nonsmp; | |||
289 | 323 | ||
290 | void machine_restart(char *command) | 324 | void machine_restart(char *command) |
291 | { | 325 | { |
292 | console_unblank(); | 326 | if (!in_interrupt() || oops_in_progress) |
327 | /* | ||
328 | * Only unblank the console if we are called in enabled | ||
329 | * context or a bust_spinlocks cleared the way for us. | ||
330 | */ | ||
331 | console_unblank(); | ||
293 | _machine_restart(command); | 332 | _machine_restart(command); |
294 | } | 333 | } |
295 | 334 | ||
296 | void machine_halt(void) | 335 | void machine_halt(void) |
297 | { | 336 | { |
298 | console_unblank(); | 337 | if (!in_interrupt() || oops_in_progress) |
338 | /* | ||
339 | * Only unblank the console if we are called in enabled | ||
340 | * context or a bust_spinlocks cleared the way for us. | ||
341 | */ | ||
342 | console_unblank(); | ||
299 | _machine_halt(); | 343 | _machine_halt(); |
300 | } | 344 | } |
301 | 345 | ||
302 | void machine_power_off(void) | 346 | void machine_power_off(void) |
303 | { | 347 | { |
304 | console_unblank(); | 348 | if (!in_interrupt() || oops_in_progress) |
349 | /* | ||
350 | * Only unblank the console if we are called in enabled | ||
351 | * context or a bust_spinlocks cleared the way for us. | ||
352 | */ | ||
353 | console_unblank(); | ||
305 | _machine_power_off(); | 354 | _machine_power_off(); |
306 | } | 355 | } |
307 | 356 | ||
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index a46793beeddd..b7630436f693 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -150,13 +150,11 @@ void show_stack(struct task_struct *task, unsigned long *sp) | |||
150 | unsigned long *stack; | 150 | unsigned long *stack; |
151 | int i; | 151 | int i; |
152 | 152 | ||
153 | // debugging aid: "show_stack(NULL);" prints the | ||
154 | // back trace for this cpu. | ||
155 | |||
156 | if (!sp) | 153 | if (!sp) |
157 | sp = task ? (unsigned long *) task->thread.ksp : __r15; | 154 | stack = task ? (unsigned long *) task->thread.ksp : __r15; |
155 | else | ||
156 | stack = sp; | ||
158 | 157 | ||
159 | stack = sp; | ||
160 | for (i = 0; i < kstack_depth_to_print; i++) { | 158 | for (i = 0; i < kstack_depth_to_print; i++) { |
161 | if (((addr_t) stack & (THREAD_SIZE-1)) == 0) | 159 | if (((addr_t) stack & (THREAD_SIZE-1)) == 0) |
162 | break; | 160 | break; |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index cfb1fff3787c..bafcd2f20ae2 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -95,7 +95,7 @@ dasd_alloc_device(void) | |||
95 | spin_lock_init(&device->mem_lock); | 95 | spin_lock_init(&device->mem_lock); |
96 | spin_lock_init(&device->request_queue_lock); | 96 | spin_lock_init(&device->request_queue_lock); |
97 | atomic_set (&device->tasklet_scheduled, 0); | 97 | atomic_set (&device->tasklet_scheduled, 0); |
98 | tasklet_init(&device->tasklet, | 98 | tasklet_init(&device->tasklet, |
99 | (void (*)(unsigned long)) dasd_tasklet, | 99 | (void (*)(unsigned long)) dasd_tasklet, |
100 | (unsigned long) device); | 100 | (unsigned long) device); |
101 | INIT_LIST_HEAD(&device->ccw_queue); | 101 | INIT_LIST_HEAD(&device->ccw_queue); |
@@ -128,7 +128,7 @@ dasd_state_new_to_known(struct dasd_device *device) | |||
128 | int rc; | 128 | int rc; |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * As long as the device is not in state DASD_STATE_NEW we want to | 131 | * As long as the device is not in state DASD_STATE_NEW we want to |
132 | * keep the reference count > 0. | 132 | * keep the reference count > 0. |
133 | */ | 133 | */ |
134 | dasd_get_device(device); | 134 | dasd_get_device(device); |
@@ -336,7 +336,7 @@ dasd_decrease_state(struct dasd_device *device) | |||
336 | if (device->state == DASD_STATE_ONLINE && | 336 | if (device->state == DASD_STATE_ONLINE && |
337 | device->target <= DASD_STATE_READY) | 337 | device->target <= DASD_STATE_READY) |
338 | dasd_state_online_to_ready(device); | 338 | dasd_state_online_to_ready(device); |
339 | 339 | ||
340 | if (device->state == DASD_STATE_READY && | 340 | if (device->state == DASD_STATE_READY && |
341 | device->target <= DASD_STATE_BASIC) | 341 | device->target <= DASD_STATE_BASIC) |
342 | dasd_state_ready_to_basic(device); | 342 | dasd_state_ready_to_basic(device); |
@@ -348,7 +348,7 @@ dasd_decrease_state(struct dasd_device *device) | |||
348 | if (device->state == DASD_STATE_BASIC && | 348 | if (device->state == DASD_STATE_BASIC && |
349 | device->target <= DASD_STATE_KNOWN) | 349 | device->target <= DASD_STATE_KNOWN) |
350 | dasd_state_basic_to_known(device); | 350 | dasd_state_basic_to_known(device); |
351 | 351 | ||
352 | if (device->state == DASD_STATE_KNOWN && | 352 | if (device->state == DASD_STATE_KNOWN && |
353 | device->target <= DASD_STATE_NEW) | 353 | device->target <= DASD_STATE_NEW) |
354 | dasd_state_known_to_new(device); | 354 | dasd_state_known_to_new(device); |
@@ -994,7 +994,7 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
994 | ((irb->scsw.cstat << 8) | irb->scsw.dstat), cqr); | 994 | ((irb->scsw.cstat << 8) | irb->scsw.dstat), cqr); |
995 | 995 | ||
996 | /* Find out the appropriate era_action. */ | 996 | /* Find out the appropriate era_action. */ |
997 | if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) | 997 | if (irb->scsw.fctl & SCSW_FCTL_HALT_FUNC) |
998 | era = dasd_era_fatal; | 998 | era = dasd_era_fatal; |
999 | else if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) && | 999 | else if (irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END) && |
1000 | irb->scsw.cstat == 0 && | 1000 | irb->scsw.cstat == 0 && |
@@ -1004,7 +1004,7 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1004 | era = dasd_era_fatal; /* don't recover this request */ | 1004 | era = dasd_era_fatal; /* don't recover this request */ |
1005 | else if (irb->esw.esw0.erw.cons) | 1005 | else if (irb->esw.esw0.erw.cons) |
1006 | era = device->discipline->examine_error(cqr, irb); | 1006 | era = device->discipline->examine_error(cqr, irb); |
1007 | else | 1007 | else |
1008 | era = dasd_era_recover; | 1008 | era = dasd_era_recover; |
1009 | 1009 | ||
1010 | DBF_DEV_EVENT(DBF_DEBUG, device, "era_code %d", era); | 1010 | DBF_DEV_EVENT(DBF_DEBUG, device, "era_code %d", era); |
@@ -1287,7 +1287,7 @@ __dasd_start_head(struct dasd_device * device) | |||
1287 | } | 1287 | } |
1288 | 1288 | ||
1289 | /* | 1289 | /* |
1290 | * Remove requests from the ccw queue. | 1290 | * Remove requests from the ccw queue. |
1291 | */ | 1291 | */ |
1292 | static void | 1292 | static void |
1293 | dasd_flush_ccw_queue(struct dasd_device * device, int all) | 1293 | dasd_flush_ccw_queue(struct dasd_device * device, int all) |
@@ -1450,23 +1450,23 @@ dasd_sleep_on(struct dasd_ccw_req * cqr) | |||
1450 | wait_queue_head_t wait_q; | 1450 | wait_queue_head_t wait_q; |
1451 | struct dasd_device *device; | 1451 | struct dasd_device *device; |
1452 | int rc; | 1452 | int rc; |
1453 | 1453 | ||
1454 | device = cqr->device; | 1454 | device = cqr->device; |
1455 | spin_lock_irq(get_ccwdev_lock(device->cdev)); | 1455 | spin_lock_irq(get_ccwdev_lock(device->cdev)); |
1456 | 1456 | ||
1457 | init_waitqueue_head (&wait_q); | 1457 | init_waitqueue_head (&wait_q); |
1458 | cqr->callback = dasd_wakeup_cb; | 1458 | cqr->callback = dasd_wakeup_cb; |
1459 | cqr->callback_data = (void *) &wait_q; | 1459 | cqr->callback_data = (void *) &wait_q; |
1460 | cqr->status = DASD_CQR_QUEUED; | 1460 | cqr->status = DASD_CQR_QUEUED; |
1461 | list_add_tail(&cqr->list, &device->ccw_queue); | 1461 | list_add_tail(&cqr->list, &device->ccw_queue); |
1462 | 1462 | ||
1463 | /* let the bh start the request to keep them in order */ | 1463 | /* let the bh start the request to keep them in order */ |
1464 | dasd_schedule_bh(device); | 1464 | dasd_schedule_bh(device); |
1465 | 1465 | ||
1466 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); | 1466 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); |
1467 | 1467 | ||
1468 | wait_event(wait_q, _wait_for_wakeup(cqr)); | 1468 | wait_event(wait_q, _wait_for_wakeup(cqr)); |
1469 | 1469 | ||
1470 | /* Request status is either done or failed. */ | 1470 | /* Request status is either done or failed. */ |
1471 | rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; | 1471 | rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; |
1472 | return rc; | 1472 | return rc; |
@@ -1568,7 +1568,7 @@ dasd_sleep_on_immediatly(struct dasd_ccw_req * cqr) | |||
1568 | wait_queue_head_t wait_q; | 1568 | wait_queue_head_t wait_q; |
1569 | struct dasd_device *device; | 1569 | struct dasd_device *device; |
1570 | int rc; | 1570 | int rc; |
1571 | 1571 | ||
1572 | device = cqr->device; | 1572 | device = cqr->device; |
1573 | spin_lock_irq(get_ccwdev_lock(device->cdev)); | 1573 | spin_lock_irq(get_ccwdev_lock(device->cdev)); |
1574 | rc = _dasd_term_running_cqr(device); | 1574 | rc = _dasd_term_running_cqr(device); |
@@ -1576,20 +1576,20 @@ dasd_sleep_on_immediatly(struct dasd_ccw_req * cqr) | |||
1576 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); | 1576 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); |
1577 | return rc; | 1577 | return rc; |
1578 | } | 1578 | } |
1579 | 1579 | ||
1580 | init_waitqueue_head (&wait_q); | 1580 | init_waitqueue_head (&wait_q); |
1581 | cqr->callback = dasd_wakeup_cb; | 1581 | cqr->callback = dasd_wakeup_cb; |
1582 | cqr->callback_data = (void *) &wait_q; | 1582 | cqr->callback_data = (void *) &wait_q; |
1583 | cqr->status = DASD_CQR_QUEUED; | 1583 | cqr->status = DASD_CQR_QUEUED; |
1584 | list_add(&cqr->list, &device->ccw_queue); | 1584 | list_add(&cqr->list, &device->ccw_queue); |
1585 | 1585 | ||
1586 | /* let the bh start the request to keep them in order */ | 1586 | /* let the bh start the request to keep them in order */ |
1587 | dasd_schedule_bh(device); | 1587 | dasd_schedule_bh(device); |
1588 | 1588 | ||
1589 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); | 1589 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); |
1590 | 1590 | ||
1591 | wait_event(wait_q, _wait_for_wakeup(cqr)); | 1591 | wait_event(wait_q, _wait_for_wakeup(cqr)); |
1592 | 1592 | ||
1593 | /* Request status is either done or failed. */ | 1593 | /* Request status is either done or failed. */ |
1594 | rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; | 1594 | rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; |
1595 | return rc; | 1595 | return rc; |
@@ -1725,7 +1725,7 @@ dasd_flush_request_queue(struct dasd_device * device) | |||
1725 | 1725 | ||
1726 | if (!device->request_queue) | 1726 | if (!device->request_queue) |
1727 | return; | 1727 | return; |
1728 | 1728 | ||
1729 | spin_lock_irq(&device->request_queue_lock); | 1729 | spin_lock_irq(&device->request_queue_lock); |
1730 | while (!list_empty(&device->request_queue->queue_head)) { | 1730 | while (!list_empty(&device->request_queue->queue_head)) { |
1731 | req = elv_next_request(device->request_queue); | 1731 | req = elv_next_request(device->request_queue); |
@@ -1855,15 +1855,34 @@ dasd_generic_probe (struct ccw_device *cdev, | |||
1855 | { | 1855 | { |
1856 | int ret; | 1856 | int ret; |
1857 | 1857 | ||
1858 | ret = ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); | ||
1859 | if (ret) { | ||
1860 | printk(KERN_WARNING | ||
1861 | "dasd_generic_probe: could not set ccw-device options " | ||
1862 | "for %s\n", cdev->dev.bus_id); | ||
1863 | return ret; | ||
1864 | } | ||
1858 | ret = dasd_add_sysfs_files(cdev); | 1865 | ret = dasd_add_sysfs_files(cdev); |
1859 | if (ret) { | 1866 | if (ret) { |
1860 | printk(KERN_WARNING | 1867 | printk(KERN_WARNING |
1861 | "dasd_generic_probe: could not add sysfs entries " | 1868 | "dasd_generic_probe: could not add sysfs entries " |
1862 | "for %s\n", cdev->dev.bus_id); | 1869 | "for %s\n", cdev->dev.bus_id); |
1863 | } else { | 1870 | return ret; |
1864 | cdev->handler = &dasd_int_handler; | ||
1865 | } | 1871 | } |
1872 | cdev->handler = &dasd_int_handler; | ||
1866 | 1873 | ||
1874 | /* | ||
1875 | * Automatically online either all dasd devices (dasd_autodetect) | ||
1876 | * or all devices specified with dasd= parameters during | ||
1877 | * initial probe. | ||
1878 | */ | ||
1879 | if ((dasd_get_feature(cdev, DASD_FEATURE_INITIAL_ONLINE) > 0 ) || | ||
1880 | (dasd_autodetect && dasd_busid_known(cdev->dev.bus_id) != 0)) | ||
1881 | ret = ccw_device_set_online(cdev); | ||
1882 | if (ret) | ||
1883 | printk(KERN_WARNING | ||
1884 | "dasd_generic_probe: could not initially online " | ||
1885 | "ccw-device %s\n", cdev->dev.bus_id); | ||
1867 | return ret; | 1886 | return ret; |
1868 | } | 1887 | } |
1869 | 1888 | ||
@@ -1911,6 +1930,8 @@ dasd_generic_set_online (struct ccw_device *cdev, | |||
1911 | struct dasd_device *device; | 1930 | struct dasd_device *device; |
1912 | int rc; | 1931 | int rc; |
1913 | 1932 | ||
1933 | /* first online clears initial online feature flag */ | ||
1934 | dasd_set_feature(cdev, DASD_FEATURE_INITIAL_ONLINE, 0); | ||
1914 | device = dasd_create_device(cdev); | 1935 | device = dasd_create_device(cdev); |
1915 | if (IS_ERR(device)) | 1936 | if (IS_ERR(device)) |
1916 | return PTR_ERR(device); | 1937 | return PTR_ERR(device); |
@@ -2065,31 +2086,6 @@ dasd_generic_notify(struct ccw_device *cdev, int event) | |||
2065 | return ret; | 2086 | return ret; |
2066 | } | 2087 | } |
2067 | 2088 | ||
2068 | /* | ||
2069 | * Automatically online either all dasd devices (dasd_autodetect) or | ||
2070 | * all devices specified with dasd= parameters. | ||
2071 | */ | ||
2072 | static int | ||
2073 | __dasd_auto_online(struct device *dev, void *data) | ||
2074 | { | ||
2075 | struct ccw_device *cdev; | ||
2076 | |||
2077 | cdev = to_ccwdev(dev); | ||
2078 | if (dasd_autodetect || dasd_busid_known(cdev->dev.bus_id) == 0) | ||
2079 | ccw_device_set_online(cdev); | ||
2080 | return 0; | ||
2081 | } | ||
2082 | |||
2083 | void | ||
2084 | dasd_generic_auto_online (struct ccw_driver *dasd_discipline_driver) | ||
2085 | { | ||
2086 | struct device_driver *drv; | ||
2087 | |||
2088 | drv = get_driver(&dasd_discipline_driver->driver); | ||
2089 | driver_for_each_device(drv, NULL, NULL, __dasd_auto_online); | ||
2090 | put_driver(drv); | ||
2091 | } | ||
2092 | |||
2093 | 2089 | ||
2094 | static int __init | 2090 | static int __init |
2095 | dasd_init(void) | 2091 | dasd_init(void) |
@@ -2170,23 +2166,4 @@ EXPORT_SYMBOL_GPL(dasd_generic_remove); | |||
2170 | EXPORT_SYMBOL_GPL(dasd_generic_notify); | 2166 | EXPORT_SYMBOL_GPL(dasd_generic_notify); |
2171 | EXPORT_SYMBOL_GPL(dasd_generic_set_online); | 2167 | EXPORT_SYMBOL_GPL(dasd_generic_set_online); |
2172 | EXPORT_SYMBOL_GPL(dasd_generic_set_offline); | 2168 | EXPORT_SYMBOL_GPL(dasd_generic_set_offline); |
2173 | EXPORT_SYMBOL_GPL(dasd_generic_auto_online); | ||
2174 | 2169 | ||
2175 | /* | ||
2176 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
2177 | * Emacs will notice this stuff at the end of the file and automatically | ||
2178 | * adjust the settings for this buffer only. This must remain at the end | ||
2179 | * of the file. | ||
2180 | * --------------------------------------------------------------------------- | ||
2181 | * Local variables: | ||
2182 | * c-indent-level: 4 | ||
2183 | * c-brace-imaginary-offset: 0 | ||
2184 | * c-brace-offset: -4 | ||
2185 | * c-argdecl-indent: 4 | ||
2186 | * c-label-offset: -4 | ||
2187 | * c-continued-statement-offset: 4 | ||
2188 | * c-continued-brace-offset: 0 | ||
2189 | * indent-tabs-mode: 1 | ||
2190 | * tab-width: 8 | ||
2191 | * End: | ||
2192 | */ | ||
diff --git a/drivers/s390/block/dasd_3370_erp.c b/drivers/s390/block/dasd_3370_erp.c index 1d11c2a9525d..1ddab8991d92 100644 --- a/drivers/s390/block/dasd_3370_erp.c +++ b/drivers/s390/block/dasd_3370_erp.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/drivers/s390/block/dasd_3370_erp.c | 2 | * File...........: linux/drivers/s390/block/dasd_3370_erp.c |
3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
4 | * Bugreports.to..: <Linux390@de.ibm.com> | 4 | * Bugreports.to..: <Linux390@de.ibm.com> |
@@ -12,10 +12,10 @@ | |||
12 | 12 | ||
13 | 13 | ||
14 | /* | 14 | /* |
15 | * DASD_3370_ERP_EXAMINE | 15 | * DASD_3370_ERP_EXAMINE |
16 | * | 16 | * |
17 | * DESCRIPTION | 17 | * DESCRIPTION |
18 | * Checks only for fatal/no/recover error. | 18 | * Checks only for fatal/no/recover error. |
19 | * A detailed examination of the sense data is done later outside | 19 | * A detailed examination of the sense data is done later outside |
20 | * the interrupt handler. | 20 | * the interrupt handler. |
21 | * | 21 | * |
@@ -23,7 +23,7 @@ | |||
23 | * 'Chapter 7. 3370 Sense Data'. | 23 | * 'Chapter 7. 3370 Sense Data'. |
24 | * | 24 | * |
25 | * RETURN VALUES | 25 | * RETURN VALUES |
26 | * dasd_era_none no error | 26 | * dasd_era_none no error |
27 | * dasd_era_fatal for all fatal (unrecoverable errors) | 27 | * dasd_era_fatal for all fatal (unrecoverable errors) |
28 | * dasd_era_recover for all others. | 28 | * dasd_era_recover for all others. |
29 | */ | 29 | */ |
@@ -82,22 +82,3 @@ dasd_3370_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb) | |||
82 | return dasd_era_recover; | 82 | return dasd_era_recover; |
83 | 83 | ||
84 | } /* END dasd_3370_erp_examine */ | 84 | } /* END dasd_3370_erp_examine */ |
85 | |||
86 | /* | ||
87 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
88 | * Emacs will notice this stuff at the end of the file and automatically | ||
89 | * adjust the settings for this buffer only. This must remain at the end | ||
90 | * of the file. | ||
91 | * --------------------------------------------------------------------------- | ||
92 | * Local variables: | ||
93 | * c-indent-level: 4 | ||
94 | * c-brace-imaginary-offset: 0 | ||
95 | * c-brace-offset: -4 | ||
96 | * c-argdecl-indent: 4 | ||
97 | * c-label-offset: -4 | ||
98 | * c-continued-statement-offset: 4 | ||
99 | * c-continued-brace-offset: 0 | ||
100 | * indent-tabs-mode: 1 | ||
101 | * tab-width: 8 | ||
102 | * End: | ||
103 | */ | ||
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 2ed51562319e..669805d4402d 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/drivers/s390/block/dasd_3990_erp.c | 2 | * File...........: linux/drivers/s390/block/dasd_3990_erp.c |
3 | * Author(s)......: Horst Hummel <Horst.Hummel@de.ibm.com> | 3 | * Author(s)......: Horst Hummel <Horst.Hummel@de.ibm.com> |
4 | * Holger Smolinski <Holger.Smolinski@de.ibm.com> | 4 | * Holger Smolinski <Holger.Smolinski@de.ibm.com> |
5 | * Bugreports.to..: <Linux390@de.ibm.com> | 5 | * Bugreports.to..: <Linux390@de.ibm.com> |
6 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001 | 6 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001 |
@@ -25,23 +25,23 @@ struct DCTL_data { | |||
25 | } __attribute__ ((packed)); | 25 | } __attribute__ ((packed)); |
26 | 26 | ||
27 | /* | 27 | /* |
28 | ***************************************************************************** | 28 | ***************************************************************************** |
29 | * SECTION ERP EXAMINATION | 29 | * SECTION ERP EXAMINATION |
30 | ***************************************************************************** | 30 | ***************************************************************************** |
31 | */ | 31 | */ |
32 | 32 | ||
33 | /* | 33 | /* |
34 | * DASD_3990_ERP_EXAMINE_24 | 34 | * DASD_3990_ERP_EXAMINE_24 |
35 | * | 35 | * |
36 | * DESCRIPTION | 36 | * DESCRIPTION |
37 | * Checks only for fatal (unrecoverable) error. | 37 | * Checks only for fatal (unrecoverable) error. |
38 | * A detailed examination of the sense data is done later outside | 38 | * A detailed examination of the sense data is done later outside |
39 | * the interrupt handler. | 39 | * the interrupt handler. |
40 | * | 40 | * |
41 | * Each bit configuration leading to an action code 2 (Exit with | 41 | * Each bit configuration leading to an action code 2 (Exit with |
42 | * programming error or unusual condition indication) | 42 | * programming error or unusual condition indication) |
43 | * are handled as fatal error´s. | 43 | * are handled as fatal error´s. |
44 | * | 44 | * |
45 | * All other configurations are handled as recoverable errors. | 45 | * All other configurations are handled as recoverable errors. |
46 | * | 46 | * |
47 | * RETURN VALUES | 47 | * RETURN VALUES |
@@ -93,15 +93,15 @@ dasd_3990_erp_examine_24(struct dasd_ccw_req * cqr, char *sense) | |||
93 | } /* END dasd_3990_erp_examine_24 */ | 93 | } /* END dasd_3990_erp_examine_24 */ |
94 | 94 | ||
95 | /* | 95 | /* |
96 | * DASD_3990_ERP_EXAMINE_32 | 96 | * DASD_3990_ERP_EXAMINE_32 |
97 | * | 97 | * |
98 | * DESCRIPTION | 98 | * DESCRIPTION |
99 | * Checks only for fatal/no/recoverable error. | 99 | * Checks only for fatal/no/recoverable error. |
100 | * A detailed examination of the sense data is done later outside | 100 | * A detailed examination of the sense data is done later outside |
101 | * the interrupt handler. | 101 | * the interrupt handler. |
102 | * | 102 | * |
103 | * RETURN VALUES | 103 | * RETURN VALUES |
104 | * dasd_era_none no error | 104 | * dasd_era_none no error |
105 | * dasd_era_fatal for all fatal (unrecoverable errors) | 105 | * dasd_era_fatal for all fatal (unrecoverable errors) |
106 | * dasd_era_recover for recoverable others. | 106 | * dasd_era_recover for recoverable others. |
107 | */ | 107 | */ |
@@ -128,10 +128,10 @@ dasd_3990_erp_examine_32(struct dasd_ccw_req * cqr, char *sense) | |||
128 | } /* end dasd_3990_erp_examine_32 */ | 128 | } /* end dasd_3990_erp_examine_32 */ |
129 | 129 | ||
130 | /* | 130 | /* |
131 | * DASD_3990_ERP_EXAMINE | 131 | * DASD_3990_ERP_EXAMINE |
132 | * | 132 | * |
133 | * DESCRIPTION | 133 | * DESCRIPTION |
134 | * Checks only for fatal/no/recover error. | 134 | * Checks only for fatal/no/recover error. |
135 | * A detailed examination of the sense data is done later outside | 135 | * A detailed examination of the sense data is done later outside |
136 | * the interrupt handler. | 136 | * the interrupt handler. |
137 | * | 137 | * |
@@ -139,7 +139,7 @@ dasd_3990_erp_examine_32(struct dasd_ccw_req * cqr, char *sense) | |||
139 | * 'Chapter 7. Error Recovery Procedures'. | 139 | * 'Chapter 7. Error Recovery Procedures'. |
140 | * | 140 | * |
141 | * RETURN VALUES | 141 | * RETURN VALUES |
142 | * dasd_era_none no error | 142 | * dasd_era_none no error |
143 | * dasd_era_fatal for all fatal (unrecoverable errors) | 143 | * dasd_era_fatal for all fatal (unrecoverable errors) |
144 | * dasd_era_recover for all others. | 144 | * dasd_era_recover for all others. |
145 | */ | 145 | */ |
@@ -178,18 +178,18 @@ dasd_3990_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb) | |||
178 | } /* END dasd_3990_erp_examine */ | 178 | } /* END dasd_3990_erp_examine */ |
179 | 179 | ||
180 | /* | 180 | /* |
181 | ***************************************************************************** | 181 | ***************************************************************************** |
182 | * SECTION ERP HANDLING | 182 | * SECTION ERP HANDLING |
183 | ***************************************************************************** | 183 | ***************************************************************************** |
184 | */ | 184 | */ |
185 | /* | 185 | /* |
186 | ***************************************************************************** | 186 | ***************************************************************************** |
187 | * 24 and 32 byte sense ERP functions | 187 | * 24 and 32 byte sense ERP functions |
188 | ***************************************************************************** | 188 | ***************************************************************************** |
189 | */ | 189 | */ |
190 | 190 | ||
191 | /* | 191 | /* |
192 | * DASD_3990_ERP_CLEANUP | 192 | * DASD_3990_ERP_CLEANUP |
193 | * | 193 | * |
194 | * DESCRIPTION | 194 | * DESCRIPTION |
195 | * Removes the already build but not necessary ERP request and sets | 195 | * Removes the already build but not necessary ERP request and sets |
@@ -197,10 +197,10 @@ dasd_3990_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb) | |||
197 | * | 197 | * |
198 | * PARAMETER | 198 | * PARAMETER |
199 | * erp request to be blocked | 199 | * erp request to be blocked |
200 | * final_status either DASD_CQR_DONE or DASD_CQR_FAILED | 200 | * final_status either DASD_CQR_DONE or DASD_CQR_FAILED |
201 | * | 201 | * |
202 | * RETURN VALUES | 202 | * RETURN VALUES |
203 | * cqr original cqr | 203 | * cqr original cqr |
204 | */ | 204 | */ |
205 | static struct dasd_ccw_req * | 205 | static struct dasd_ccw_req * |
206 | dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status) | 206 | dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status) |
@@ -214,7 +214,7 @@ dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status) | |||
214 | } /* end dasd_3990_erp_cleanup */ | 214 | } /* end dasd_3990_erp_cleanup */ |
215 | 215 | ||
216 | /* | 216 | /* |
217 | * DASD_3990_ERP_BLOCK_QUEUE | 217 | * DASD_3990_ERP_BLOCK_QUEUE |
218 | * | 218 | * |
219 | * DESCRIPTION | 219 | * DESCRIPTION |
220 | * Block the given device request queue to prevent from further | 220 | * Block the given device request queue to prevent from further |
@@ -237,7 +237,7 @@ dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires) | |||
237 | } | 237 | } |
238 | 238 | ||
239 | /* | 239 | /* |
240 | * DASD_3990_ERP_INT_REQ | 240 | * DASD_3990_ERP_INT_REQ |
241 | * | 241 | * |
242 | * DESCRIPTION | 242 | * DESCRIPTION |
243 | * Handles 'Intervention Required' error. | 243 | * Handles 'Intervention Required' error. |
@@ -277,7 +277,7 @@ dasd_3990_erp_int_req(struct dasd_ccw_req * erp) | |||
277 | } /* end dasd_3990_erp_int_req */ | 277 | } /* end dasd_3990_erp_int_req */ |
278 | 278 | ||
279 | /* | 279 | /* |
280 | * DASD_3990_ERP_ALTERNATE_PATH | 280 | * DASD_3990_ERP_ALTERNATE_PATH |
281 | * | 281 | * |
282 | * DESCRIPTION | 282 | * DESCRIPTION |
283 | * Repeat the operation on a different channel path. | 283 | * Repeat the operation on a different channel path. |
@@ -330,15 +330,15 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) | |||
330 | * DASD_3990_ERP_DCTL | 330 | * DASD_3990_ERP_DCTL |
331 | * | 331 | * |
332 | * DESCRIPTION | 332 | * DESCRIPTION |
333 | * Setup cqr to do the Diagnostic Control (DCTL) command with an | 333 | * Setup cqr to do the Diagnostic Control (DCTL) command with an |
334 | * Inhibit Write subcommand (0x20) and the given modifier. | 334 | * Inhibit Write subcommand (0x20) and the given modifier. |
335 | * | 335 | * |
336 | * PARAMETER | 336 | * PARAMETER |
337 | * erp pointer to the current (failed) ERP | 337 | * erp pointer to the current (failed) ERP |
338 | * modifier subcommand modifier | 338 | * modifier subcommand modifier |
339 | * | 339 | * |
340 | * RETURN VALUES | 340 | * RETURN VALUES |
341 | * dctl_cqr pointer to NEW dctl_cqr | 341 | * dctl_cqr pointer to NEW dctl_cqr |
342 | * | 342 | * |
343 | */ | 343 | */ |
344 | static struct dasd_ccw_req * | 344 | static struct dasd_ccw_req * |
@@ -386,7 +386,7 @@ dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier) | |||
386 | } /* end dasd_3990_erp_DCTL */ | 386 | } /* end dasd_3990_erp_DCTL */ |
387 | 387 | ||
388 | /* | 388 | /* |
389 | * DASD_3990_ERP_ACTION_1 | 389 | * DASD_3990_ERP_ACTION_1 |
390 | * | 390 | * |
391 | * DESCRIPTION | 391 | * DESCRIPTION |
392 | * Setup ERP to do the ERP action 1 (see Reference manual). | 392 | * Setup ERP to do the ERP action 1 (see Reference manual). |
@@ -415,7 +415,7 @@ dasd_3990_erp_action_1(struct dasd_ccw_req * erp) | |||
415 | } /* end dasd_3990_erp_action_1 */ | 415 | } /* end dasd_3990_erp_action_1 */ |
416 | 416 | ||
417 | /* | 417 | /* |
418 | * DASD_3990_ERP_ACTION_4 | 418 | * DASD_3990_ERP_ACTION_4 |
419 | * | 419 | * |
420 | * DESCRIPTION | 420 | * DESCRIPTION |
421 | * Setup ERP to do the ERP action 4 (see Reference manual). | 421 | * Setup ERP to do the ERP action 4 (see Reference manual). |
@@ -453,11 +453,11 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) | |||
453 | 453 | ||
454 | if (sense[25] == 0x1D) { /* state change pending */ | 454 | if (sense[25] == 0x1D) { /* state change pending */ |
455 | 455 | ||
456 | DEV_MESSAGE(KERN_INFO, device, | 456 | DEV_MESSAGE(KERN_INFO, device, |
457 | "waiting for state change pending " | 457 | "waiting for state change pending " |
458 | "interrupt, %d retries left", | 458 | "interrupt, %d retries left", |
459 | erp->retries); | 459 | erp->retries); |
460 | 460 | ||
461 | dasd_3990_erp_block_queue(erp, 30*HZ); | 461 | dasd_3990_erp_block_queue(erp, 30*HZ); |
462 | 462 | ||
463 | } else if (sense[25] == 0x1E) { /* busy */ | 463 | } else if (sense[25] == 0x1E) { /* busy */ |
@@ -469,9 +469,9 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) | |||
469 | } else { | 469 | } else { |
470 | 470 | ||
471 | /* no state change pending - retry */ | 471 | /* no state change pending - retry */ |
472 | DEV_MESSAGE (KERN_INFO, device, | 472 | DEV_MESSAGE (KERN_INFO, device, |
473 | "redriving request immediately, " | 473 | "redriving request immediately, " |
474 | "%d retries left", | 474 | "%d retries left", |
475 | erp->retries); | 475 | erp->retries); |
476 | erp->status = DASD_CQR_QUEUED; | 476 | erp->status = DASD_CQR_QUEUED; |
477 | } | 477 | } |
@@ -482,13 +482,13 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) | |||
482 | } /* end dasd_3990_erp_action_4 */ | 482 | } /* end dasd_3990_erp_action_4 */ |
483 | 483 | ||
484 | /* | 484 | /* |
485 | ***************************************************************************** | 485 | ***************************************************************************** |
486 | * 24 byte sense ERP functions (only) | 486 | * 24 byte sense ERP functions (only) |
487 | ***************************************************************************** | 487 | ***************************************************************************** |
488 | */ | 488 | */ |
489 | 489 | ||
490 | /* | 490 | /* |
491 | * DASD_3990_ERP_ACTION_5 | 491 | * DASD_3990_ERP_ACTION_5 |
492 | * | 492 | * |
493 | * DESCRIPTION | 493 | * DESCRIPTION |
494 | * Setup ERP to do the ERP action 5 (see Reference manual). | 494 | * Setup ERP to do the ERP action 5 (see Reference manual). |
@@ -523,7 +523,7 @@ dasd_3990_erp_action_5(struct dasd_ccw_req * erp) | |||
523 | * | 523 | * |
524 | * PARAMETER | 524 | * PARAMETER |
525 | * sense current sense data | 525 | * sense current sense data |
526 | * | 526 | * |
527 | * RETURN VALUES | 527 | * RETURN VALUES |
528 | * void | 528 | * void |
529 | */ | 529 | */ |
@@ -1150,9 +1150,9 @@ dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) | |||
1150 | * PARAMETER | 1150 | * PARAMETER |
1151 | * erp current erp_head | 1151 | * erp current erp_head |
1152 | * sense current sense data | 1152 | * sense current sense data |
1153 | * | 1153 | * |
1154 | * RETURN VALUES | 1154 | * RETURN VALUES |
1155 | * erp 'new' erp_head - pointer to new ERP | 1155 | * erp 'new' erp_head - pointer to new ERP |
1156 | */ | 1156 | */ |
1157 | static struct dasd_ccw_req * | 1157 | static struct dasd_ccw_req * |
1158 | dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) | 1158 | dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) |
@@ -1185,7 +1185,7 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) | |||
1185 | } /* end dasd_3990_erp_com_rej */ | 1185 | } /* end dasd_3990_erp_com_rej */ |
1186 | 1186 | ||
1187 | /* | 1187 | /* |
1188 | * DASD_3990_ERP_BUS_OUT | 1188 | * DASD_3990_ERP_BUS_OUT |
1189 | * | 1189 | * |
1190 | * DESCRIPTION | 1190 | * DESCRIPTION |
1191 | * Handles 24 byte 'Bus Out Parity Check' error. | 1191 | * Handles 24 byte 'Bus Out Parity Check' error. |
@@ -1483,7 +1483,7 @@ dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense) | |||
1483 | * | 1483 | * |
1484 | * PARAMETER | 1484 | * PARAMETER |
1485 | * erp already added default ERP | 1485 | * erp already added default ERP |
1486 | * | 1486 | * |
1487 | * RETURN VALUES | 1487 | * RETURN VALUES |
1488 | * erp new erp_head - pointer to new ERP | 1488 | * erp new erp_head - pointer to new ERP |
1489 | */ | 1489 | */ |
@@ -1527,11 +1527,11 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp) | |||
1527 | } /* end dasd_3990_erp_file_prot */ | 1527 | } /* end dasd_3990_erp_file_prot */ |
1528 | 1528 | ||
1529 | /* | 1529 | /* |
1530 | * DASD_3990_ERP_INSPECT_24 | 1530 | * DASD_3990_ERP_INSPECT_24 |
1531 | * | 1531 | * |
1532 | * DESCRIPTION | 1532 | * DESCRIPTION |
1533 | * Does a detailed inspection of the 24 byte sense data | 1533 | * Does a detailed inspection of the 24 byte sense data |
1534 | * and sets up a related error recovery action. | 1534 | * and sets up a related error recovery action. |
1535 | * | 1535 | * |
1536 | * PARAMETER | 1536 | * PARAMETER |
1537 | * sense sense data of the actual error | 1537 | * sense sense data of the actual error |
@@ -1602,13 +1602,13 @@ dasd_3990_erp_inspect_24(struct dasd_ccw_req * erp, char *sense) | |||
1602 | } /* END dasd_3990_erp_inspect_24 */ | 1602 | } /* END dasd_3990_erp_inspect_24 */ |
1603 | 1603 | ||
1604 | /* | 1604 | /* |
1605 | ***************************************************************************** | 1605 | ***************************************************************************** |
1606 | * 32 byte sense ERP functions (only) | 1606 | * 32 byte sense ERP functions (only) |
1607 | ***************************************************************************** | 1607 | ***************************************************************************** |
1608 | */ | 1608 | */ |
1609 | 1609 | ||
1610 | /* | 1610 | /* |
1611 | * DASD_3990_ERPACTION_10_32 | 1611 | * DASD_3990_ERPACTION_10_32 |
1612 | * | 1612 | * |
1613 | * DESCRIPTION | 1613 | * DESCRIPTION |
1614 | * Handles 32 byte 'Action 10' of Single Program Action Codes. | 1614 | * Handles 32 byte 'Action 10' of Single Program Action Codes. |
@@ -1616,7 +1616,7 @@ dasd_3990_erp_inspect_24(struct dasd_ccw_req * erp, char *sense) | |||
1616 | * | 1616 | * |
1617 | * PARAMETER | 1617 | * PARAMETER |
1618 | * erp current erp_head | 1618 | * erp current erp_head |
1619 | * sense current sense data | 1619 | * sense current sense data |
1620 | * RETURN VALUES | 1620 | * RETURN VALUES |
1621 | * erp modified erp_head | 1621 | * erp modified erp_head |
1622 | */ | 1622 | */ |
@@ -1640,18 +1640,18 @@ dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense) | |||
1640 | * | 1640 | * |
1641 | * DESCRIPTION | 1641 | * DESCRIPTION |
1642 | * Handles 32 byte 'Action 1B' of Single Program Action Codes. | 1642 | * Handles 32 byte 'Action 1B' of Single Program Action Codes. |
1643 | * A write operation could not be finished because of an unexpected | 1643 | * A write operation could not be finished because of an unexpected |
1644 | * condition. | 1644 | * condition. |
1645 | * The already created 'default erp' is used to get the link to | 1645 | * The already created 'default erp' is used to get the link to |
1646 | * the erp chain, but it can not be used for this recovery | 1646 | * the erp chain, but it can not be used for this recovery |
1647 | * action because it contains no DE/LO data space. | 1647 | * action because it contains no DE/LO data space. |
1648 | * | 1648 | * |
1649 | * PARAMETER | 1649 | * PARAMETER |
1650 | * default_erp already added default erp. | 1650 | * default_erp already added default erp. |
1651 | * sense current sense data | 1651 | * sense current sense data |
1652 | * | 1652 | * |
1653 | * RETURN VALUES | 1653 | * RETURN VALUES |
1654 | * erp new erp or | 1654 | * erp new erp or |
1655 | * default_erp in case of imprecise ending or error | 1655 | * default_erp in case of imprecise ending or error |
1656 | */ | 1656 | */ |
1657 | static struct dasd_ccw_req * | 1657 | static struct dasd_ccw_req * |
@@ -1789,16 +1789,16 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | |||
1789 | * DASD_3990_UPDATE_1B | 1789 | * DASD_3990_UPDATE_1B |
1790 | * | 1790 | * |
1791 | * DESCRIPTION | 1791 | * DESCRIPTION |
1792 | * Handles the update to the 32 byte 'Action 1B' of Single Program | 1792 | * Handles the update to the 32 byte 'Action 1B' of Single Program |
1793 | * Action Codes in case the first action was not successful. | 1793 | * Action Codes in case the first action was not successful. |
1794 | * The already created 'previous_erp' is the currently not successful | 1794 | * The already created 'previous_erp' is the currently not successful |
1795 | * ERP. | 1795 | * ERP. |
1796 | * | 1796 | * |
1797 | * PARAMETER | 1797 | * PARAMETER |
1798 | * previous_erp already created previous erp. | 1798 | * previous_erp already created previous erp. |
1799 | * sense current sense data | 1799 | * sense current sense data |
1800 | * RETURN VALUES | 1800 | * RETURN VALUES |
1801 | * erp modified erp | 1801 | * erp modified erp |
1802 | */ | 1802 | */ |
1803 | static struct dasd_ccw_req * | 1803 | static struct dasd_ccw_req * |
1804 | dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) | 1804 | dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) |
@@ -1897,7 +1897,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) | |||
1897 | } /* end dasd_3990_update_1B */ | 1897 | } /* end dasd_3990_update_1B */ |
1898 | 1898 | ||
1899 | /* | 1899 | /* |
1900 | * DASD_3990_ERP_COMPOUND_RETRY | 1900 | * DASD_3990_ERP_COMPOUND_RETRY |
1901 | * | 1901 | * |
1902 | * DESCRIPTION | 1902 | * DESCRIPTION |
1903 | * Handles the compound ERP action retry code. | 1903 | * Handles the compound ERP action retry code. |
@@ -1943,7 +1943,7 @@ dasd_3990_erp_compound_retry(struct dasd_ccw_req * erp, char *sense) | |||
1943 | } /* end dasd_3990_erp_compound_retry */ | 1943 | } /* end dasd_3990_erp_compound_retry */ |
1944 | 1944 | ||
1945 | /* | 1945 | /* |
1946 | * DASD_3990_ERP_COMPOUND_PATH | 1946 | * DASD_3990_ERP_COMPOUND_PATH |
1947 | * | 1947 | * |
1948 | * DESCRIPTION | 1948 | * DESCRIPTION |
1949 | * Handles the compound ERP action for retry on alternate | 1949 | * Handles the compound ERP action for retry on alternate |
@@ -1965,7 +1965,7 @@ dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense) | |||
1965 | dasd_3990_erp_alternate_path(erp); | 1965 | dasd_3990_erp_alternate_path(erp); |
1966 | 1966 | ||
1967 | if (erp->status == DASD_CQR_FAILED) { | 1967 | if (erp->status == DASD_CQR_FAILED) { |
1968 | /* reset the lpm and the status to be able to | 1968 | /* reset the lpm and the status to be able to |
1969 | * try further actions. */ | 1969 | * try further actions. */ |
1970 | 1970 | ||
1971 | erp->lpm = 0; | 1971 | erp->lpm = 0; |
@@ -1980,7 +1980,7 @@ dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense) | |||
1980 | } /* end dasd_3990_erp_compound_path */ | 1980 | } /* end dasd_3990_erp_compound_path */ |
1981 | 1981 | ||
1982 | /* | 1982 | /* |
1983 | * DASD_3990_ERP_COMPOUND_CODE | 1983 | * DASD_3990_ERP_COMPOUND_CODE |
1984 | * | 1984 | * |
1985 | * DESCRIPTION | 1985 | * DESCRIPTION |
1986 | * Handles the compound ERP action for retry code. | 1986 | * Handles the compound ERP action for retry code. |
@@ -2001,18 +2001,18 @@ dasd_3990_erp_compound_code(struct dasd_ccw_req * erp, char *sense) | |||
2001 | 2001 | ||
2002 | switch (sense[28]) { | 2002 | switch (sense[28]) { |
2003 | case 0x17: | 2003 | case 0x17: |
2004 | /* issue a Diagnostic Control command with an | 2004 | /* issue a Diagnostic Control command with an |
2005 | * Inhibit Write subcommand and controler modifier */ | 2005 | * Inhibit Write subcommand and controler modifier */ |
2006 | erp = dasd_3990_erp_DCTL(erp, 0x20); | 2006 | erp = dasd_3990_erp_DCTL(erp, 0x20); |
2007 | break; | 2007 | break; |
2008 | 2008 | ||
2009 | case 0x25: | 2009 | case 0x25: |
2010 | /* wait for 5 seconds and retry again */ | 2010 | /* wait for 5 seconds and retry again */ |
2011 | erp->retries = 1; | 2011 | erp->retries = 1; |
2012 | 2012 | ||
2013 | dasd_3990_erp_block_queue (erp, 5*HZ); | 2013 | dasd_3990_erp_block_queue (erp, 5*HZ); |
2014 | break; | 2014 | break; |
2015 | 2015 | ||
2016 | default: | 2016 | default: |
2017 | /* should not happen - continue */ | 2017 | /* should not happen - continue */ |
2018 | break; | 2018 | break; |
@@ -2026,7 +2026,7 @@ dasd_3990_erp_compound_code(struct dasd_ccw_req * erp, char *sense) | |||
2026 | } /* end dasd_3990_erp_compound_code */ | 2026 | } /* end dasd_3990_erp_compound_code */ |
2027 | 2027 | ||
2028 | /* | 2028 | /* |
2029 | * DASD_3990_ERP_COMPOUND_CONFIG | 2029 | * DASD_3990_ERP_COMPOUND_CONFIG |
2030 | * | 2030 | * |
2031 | * DESCRIPTION | 2031 | * DESCRIPTION |
2032 | * Handles the compound ERP action for configruation | 2032 | * Handles the compound ERP action for configruation |
@@ -2063,10 +2063,10 @@ dasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense) | |||
2063 | } /* end dasd_3990_erp_compound_config */ | 2063 | } /* end dasd_3990_erp_compound_config */ |
2064 | 2064 | ||
2065 | /* | 2065 | /* |
2066 | * DASD_3990_ERP_COMPOUND | 2066 | * DASD_3990_ERP_COMPOUND |
2067 | * | 2067 | * |
2068 | * DESCRIPTION | 2068 | * DESCRIPTION |
2069 | * Does the further compound program action if | 2069 | * Does the further compound program action if |
2070 | * compound retry was not successful. | 2070 | * compound retry was not successful. |
2071 | * | 2071 | * |
2072 | * PARAMETER | 2072 | * PARAMETER |
@@ -2110,11 +2110,11 @@ dasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense) | |||
2110 | } /* end dasd_3990_erp_compound */ | 2110 | } /* end dasd_3990_erp_compound */ |
2111 | 2111 | ||
2112 | /* | 2112 | /* |
2113 | * DASD_3990_ERP_INSPECT_32 | 2113 | * DASD_3990_ERP_INSPECT_32 |
2114 | * | 2114 | * |
2115 | * DESCRIPTION | 2115 | * DESCRIPTION |
2116 | * Does a detailed inspection of the 32 byte sense data | 2116 | * Does a detailed inspection of the 32 byte sense data |
2117 | * and sets up a related error recovery action. | 2117 | * and sets up a related error recovery action. |
2118 | * | 2118 | * |
2119 | * PARAMETER | 2119 | * PARAMETER |
2120 | * sense sense data of the actual error | 2120 | * sense sense data of the actual error |
@@ -2228,9 +2228,9 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) | |||
2228 | } /* end dasd_3990_erp_inspect_32 */ | 2228 | } /* end dasd_3990_erp_inspect_32 */ |
2229 | 2229 | ||
2230 | /* | 2230 | /* |
2231 | ***************************************************************************** | 2231 | ***************************************************************************** |
2232 | * main ERP control fuctions (24 and 32 byte sense) | 2232 | * main ERP control fuctions (24 and 32 byte sense) |
2233 | ***************************************************************************** | 2233 | ***************************************************************************** |
2234 | */ | 2234 | */ |
2235 | 2235 | ||
2236 | /* | 2236 | /* |
@@ -2243,7 +2243,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) | |||
2243 | * PARAMETER | 2243 | * PARAMETER |
2244 | * erp pointer to the currently created default ERP | 2244 | * erp pointer to the currently created default ERP |
2245 | * RETURN VALUES | 2245 | * RETURN VALUES |
2246 | * erp_new contens was possibly modified | 2246 | * erp_new contens was possibly modified |
2247 | */ | 2247 | */ |
2248 | static struct dasd_ccw_req * | 2248 | static struct dasd_ccw_req * |
2249 | dasd_3990_erp_inspect(struct dasd_ccw_req * erp) | 2249 | dasd_3990_erp_inspect(struct dasd_ccw_req * erp) |
@@ -2272,14 +2272,14 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp) | |||
2272 | 2272 | ||
2273 | /* | 2273 | /* |
2274 | * DASD_3990_ERP_ADD_ERP | 2274 | * DASD_3990_ERP_ADD_ERP |
2275 | * | 2275 | * |
2276 | * DESCRIPTION | 2276 | * DESCRIPTION |
2277 | * This funtion adds an additional request block (ERP) to the head of | 2277 | * This funtion adds an additional request block (ERP) to the head of |
2278 | * the given cqr (or erp). | 2278 | * the given cqr (or erp). |
2279 | * This erp is initialized as an default erp (retry TIC) | 2279 | * This erp is initialized as an default erp (retry TIC) |
2280 | * | 2280 | * |
2281 | * PARAMETER | 2281 | * PARAMETER |
2282 | * cqr head of the current ERP-chain (or single cqr if | 2282 | * cqr head of the current ERP-chain (or single cqr if |
2283 | * first error) | 2283 | * first error) |
2284 | * RETURN VALUES | 2284 | * RETURN VALUES |
2285 | * erp pointer to new ERP-chain head | 2285 | * erp pointer to new ERP-chain head |
@@ -2332,15 +2332,15 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) | |||
2332 | } | 2332 | } |
2333 | 2333 | ||
2334 | /* | 2334 | /* |
2335 | * DASD_3990_ERP_ADDITIONAL_ERP | 2335 | * DASD_3990_ERP_ADDITIONAL_ERP |
2336 | * | 2336 | * |
2337 | * DESCRIPTION | 2337 | * DESCRIPTION |
2338 | * An additional ERP is needed to handle the current error. | 2338 | * An additional ERP is needed to handle the current error. |
2339 | * Add ERP to the head of the ERP-chain containing the ERP processing | 2339 | * Add ERP to the head of the ERP-chain containing the ERP processing |
2340 | * determined based on the sense data. | 2340 | * determined based on the sense data. |
2341 | * | 2341 | * |
2342 | * PARAMETER | 2342 | * PARAMETER |
2343 | * cqr head of the current ERP-chain (or single cqr if | 2343 | * cqr head of the current ERP-chain (or single cqr if |
2344 | * first error) | 2344 | * first error) |
2345 | * | 2345 | * |
2346 | * RETURN VALUES | 2346 | * RETURN VALUES |
@@ -2376,7 +2376,7 @@ dasd_3990_erp_additional_erp(struct dasd_ccw_req * cqr) | |||
2376 | * 24 byte sense byte 25 and 27 is set as well. | 2376 | * 24 byte sense byte 25 and 27 is set as well. |
2377 | * | 2377 | * |
2378 | * PARAMETER | 2378 | * PARAMETER |
2379 | * cqr1 first cqr, which will be compared with the | 2379 | * cqr1 first cqr, which will be compared with the |
2380 | * cqr2 second cqr. | 2380 | * cqr2 second cqr. |
2381 | * | 2381 | * |
2382 | * RETURN VALUES | 2382 | * RETURN VALUES |
@@ -2415,7 +2415,7 @@ dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1, struct dasd_ccw_req *cqr2) | |||
2415 | * cqr failed cqr (either original cqr or already an erp) | 2415 | * cqr failed cqr (either original cqr or already an erp) |
2416 | * | 2416 | * |
2417 | * RETURN VALUES | 2417 | * RETURN VALUES |
2418 | * erp erp-pointer to the already defined error | 2418 | * erp erp-pointer to the already defined error |
2419 | * recovery procedure OR | 2419 | * recovery procedure OR |
2420 | * NULL if a 'new' error occurred. | 2420 | * NULL if a 'new' error occurred. |
2421 | */ | 2421 | */ |
@@ -2451,10 +2451,10 @@ dasd_3990_erp_in_erp(struct dasd_ccw_req *cqr) | |||
2451 | * DASD_3990_ERP_FURTHER_ERP (24 & 32 byte sense) | 2451 | * DASD_3990_ERP_FURTHER_ERP (24 & 32 byte sense) |
2452 | * | 2452 | * |
2453 | * DESCRIPTION | 2453 | * DESCRIPTION |
2454 | * No retry is left for the current ERP. Check what has to be done | 2454 | * No retry is left for the current ERP. Check what has to be done |
2455 | * with the ERP. | 2455 | * with the ERP. |
2456 | * - do further defined ERP action or | 2456 | * - do further defined ERP action or |
2457 | * - wait for interrupt or | 2457 | * - wait for interrupt or |
2458 | * - exit with permanent error | 2458 | * - exit with permanent error |
2459 | * | 2459 | * |
2460 | * PARAMETER | 2460 | * PARAMETER |
@@ -2485,7 +2485,7 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) | |||
2485 | 2485 | ||
2486 | if (!(sense[2] & DASD_SENSE_BIT_0)) { | 2486 | if (!(sense[2] & DASD_SENSE_BIT_0)) { |
2487 | 2487 | ||
2488 | /* issue a Diagnostic Control command with an | 2488 | /* issue a Diagnostic Control command with an |
2489 | * Inhibit Write subcommand */ | 2489 | * Inhibit Write subcommand */ |
2490 | 2490 | ||
2491 | switch (sense[25]) { | 2491 | switch (sense[25]) { |
@@ -2535,14 +2535,14 @@ dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) | |||
2535 | } /* end dasd_3990_erp_further_erp */ | 2535 | } /* end dasd_3990_erp_further_erp */ |
2536 | 2536 | ||
2537 | /* | 2537 | /* |
2538 | * DASD_3990_ERP_HANDLE_MATCH_ERP | 2538 | * DASD_3990_ERP_HANDLE_MATCH_ERP |
2539 | * | 2539 | * |
2540 | * DESCRIPTION | 2540 | * DESCRIPTION |
2541 | * An error occurred again and an ERP has been detected which is already | 2541 | * An error occurred again and an ERP has been detected which is already |
2542 | * used to handle this error (e.g. retries). | 2542 | * used to handle this error (e.g. retries). |
2543 | * All prior ERP's are asumed to be successful and therefore removed | 2543 | * All prior ERP's are asumed to be successful and therefore removed |
2544 | * from queue. | 2544 | * from queue. |
2545 | * If retry counter of matching erp is already 0, it is checked if further | 2545 | * If retry counter of matching erp is already 0, it is checked if further |
2546 | * action is needed (besides retry) or if the ERP has failed. | 2546 | * action is needed (besides retry) or if the ERP has failed. |
2547 | * | 2547 | * |
2548 | * PARAMETER | 2548 | * PARAMETER |
@@ -2631,7 +2631,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head, | |||
2631 | * erp erp-pointer to the head of the ERP action chain. | 2631 | * erp erp-pointer to the head of the ERP action chain. |
2632 | * This means: | 2632 | * This means: |
2633 | * - either a ptr to an additional ERP cqr or | 2633 | * - either a ptr to an additional ERP cqr or |
2634 | * - the original given cqr (which's status might | 2634 | * - the original given cqr (which's status might |
2635 | * be modified) | 2635 | * be modified) |
2636 | */ | 2636 | */ |
2637 | struct dasd_ccw_req * | 2637 | struct dasd_ccw_req * |
@@ -2723,22 +2723,3 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) | |||
2723 | return erp; | 2723 | return erp; |
2724 | 2724 | ||
2725 | } /* end dasd_3990_erp_action */ | 2725 | } /* end dasd_3990_erp_action */ |
2726 | |||
2727 | /* | ||
2728 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
2729 | * Emacs will notice this stuff at the end of the file and automatically | ||
2730 | * adjust the settings for this buffer only. This must remain at the end | ||
2731 | * of the file. | ||
2732 | * --------------------------------------------------------------------------- | ||
2733 | * Local variables: | ||
2734 | * c-indent-level: 4 | ||
2735 | * c-brace-imaginary-offset: 0 | ||
2736 | * c-brace-offset: -4 | ||
2737 | * c-argdecl-indent: 4 | ||
2738 | * c-label-offset: -4 | ||
2739 | * c-continued-statement-offset: 4 | ||
2740 | * c-continued-brace-offset: 0 | ||
2741 | * indent-tabs-mode: 1 | ||
2742 | * tab-width: 8 | ||
2743 | * End: | ||
2744 | */ | ||
diff --git a/drivers/s390/block/dasd_9336_erp.c b/drivers/s390/block/dasd_9336_erp.c index dc861446d056..6e082688475a 100644 --- a/drivers/s390/block/dasd_9336_erp.c +++ b/drivers/s390/block/dasd_9336_erp.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/drivers/s390/block/dasd_9336_erp.c | 2 | * File...........: linux/drivers/s390/block/dasd_9336_erp.c |
3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
4 | * Bugreports.to..: <Linux390@de.ibm.com> | 4 | * Bugreports.to..: <Linux390@de.ibm.com> |
@@ -12,10 +12,10 @@ | |||
12 | 12 | ||
13 | 13 | ||
14 | /* | 14 | /* |
15 | * DASD_9336_ERP_EXAMINE | 15 | * DASD_9336_ERP_EXAMINE |
16 | * | 16 | * |
17 | * DESCRIPTION | 17 | * DESCRIPTION |
18 | * Checks only for fatal/no/recover error. | 18 | * Checks only for fatal/no/recover error. |
19 | * A detailed examination of the sense data is done later outside | 19 | * A detailed examination of the sense data is done later outside |
20 | * the interrupt handler. | 20 | * the interrupt handler. |
21 | * | 21 | * |
@@ -23,7 +23,7 @@ | |||
23 | * 'Chapter 7. 9336 Sense Data'. | 23 | * 'Chapter 7. 9336 Sense Data'. |
24 | * | 24 | * |
25 | * RETURN VALUES | 25 | * RETURN VALUES |
26 | * dasd_era_none no error | 26 | * dasd_era_none no error |
27 | * dasd_era_fatal for all fatal (unrecoverable errors) | 27 | * dasd_era_fatal for all fatal (unrecoverable errors) |
28 | * dasd_era_recover for all others. | 28 | * dasd_era_recover for all others. |
29 | */ | 29 | */ |
@@ -39,22 +39,3 @@ dasd_9336_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb) | |||
39 | return dasd_era_recover; | 39 | return dasd_era_recover; |
40 | 40 | ||
41 | } /* END dasd_9336_erp_examine */ | 41 | } /* END dasd_9336_erp_examine */ |
42 | |||
43 | /* | ||
44 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
45 | * Emacs will notice this stuff at the end of the file and automatically | ||
46 | * adjust the settings for this buffer only. This must remain at the end | ||
47 | * of the file. | ||
48 | * --------------------------------------------------------------------------- | ||
49 | * Local variables: | ||
50 | * c-indent-level: 4 | ||
51 | * c-brace-imaginary-offset: 0 | ||
52 | * c-brace-offset: -4 | ||
53 | * c-argdecl-indent: 4 | ||
54 | * c-label-offset: -4 | ||
55 | * c-continued-statement-offset: 4 | ||
56 | * c-continued-brace-offset: 0 | ||
57 | * indent-tabs-mode: 1 | ||
58 | * tab-width: 8 | ||
59 | * End: | ||
60 | */ | ||
diff --git a/drivers/s390/block/dasd_9343_erp.c b/drivers/s390/block/dasd_9343_erp.c index 4a5b79569aaa..ddecb9808ed4 100644 --- a/drivers/s390/block/dasd_9343_erp.c +++ b/drivers/s390/block/dasd_9343_erp.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/drivers/s390/block/dasd_9345_erp.c | 2 | * File...........: linux/drivers/s390/block/dasd_9345_erp.c |
3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
4 | * Bugreports.to..: <Linux390@de.ibm.com> | 4 | * Bugreports.to..: <Linux390@de.ibm.com> |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 216bc4fba199..9e9ae7179602 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include "dasd_int.h" | 27 | #include "dasd_int.h" |
28 | 28 | ||
29 | kmem_cache_t *dasd_page_cache; | 29 | kmem_cache_t *dasd_page_cache; |
30 | EXPORT_SYMBOL(dasd_page_cache); | 30 | EXPORT_SYMBOL_GPL(dasd_page_cache); |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * dasd_devmap_t is used to store the features and the relation | 33 | * dasd_devmap_t is used to store the features and the relation |
@@ -49,6 +49,20 @@ struct dasd_devmap { | |||
49 | }; | 49 | }; |
50 | 50 | ||
51 | /* | 51 | /* |
52 | * dasd_servermap is used to store the server_id of all storage servers | ||
53 | * accessed by DASD device driver. | ||
54 | */ | ||
55 | struct dasd_servermap { | ||
56 | struct list_head list; | ||
57 | struct server_id { | ||
58 | char vendor[4]; | ||
59 | char serial[15]; | ||
60 | } sid; | ||
61 | }; | ||
62 | |||
63 | static struct list_head dasd_serverlist; | ||
64 | |||
65 | /* | ||
52 | * Parameter parsing functions for dasd= parameter. The syntax is: | 66 | * Parameter parsing functions for dasd= parameter. The syntax is: |
53 | * <devno> : (0x)?[0-9a-fA-F]+ | 67 | * <devno> : (0x)?[0-9a-fA-F]+ |
54 | * <busid> : [0-0a-f]\.[0-9a-f]\.(0x)?[0-9a-fA-F]+ | 68 | * <busid> : [0-0a-f]\.[0-9a-f]\.(0x)?[0-9a-fA-F]+ |
@@ -64,6 +78,8 @@ struct dasd_devmap { | |||
64 | 78 | ||
65 | int dasd_probeonly = 0; /* is true, when probeonly mode is active */ | 79 | int dasd_probeonly = 0; /* is true, when probeonly mode is active */ |
66 | int dasd_autodetect = 0; /* is true, when autodetection is active */ | 80 | int dasd_autodetect = 0; /* is true, when autodetection is active */ |
81 | int dasd_nopav = 0; /* is true, when PAV is disabled */ | ||
82 | EXPORT_SYMBOL_GPL(dasd_nopav); | ||
67 | 83 | ||
68 | /* | 84 | /* |
69 | * char *dasd[] is intended to hold the ranges supplied by the dasd= statement | 85 | * char *dasd[] is intended to hold the ranges supplied by the dasd= statement |
@@ -123,7 +139,7 @@ static inline int | |||
123 | dasd_busid(char **str, int *id0, int *id1, int *devno) | 139 | dasd_busid(char **str, int *id0, int *id1, int *devno) |
124 | { | 140 | { |
125 | int val, old_style; | 141 | int val, old_style; |
126 | 142 | ||
127 | /* check for leading '0x' */ | 143 | /* check for leading '0x' */ |
128 | old_style = 0; | 144 | old_style = 0; |
129 | if ((*str)[0] == '0' && (*str)[1] == 'x') { | 145 | if ((*str)[0] == '0' && (*str)[1] == 'x') { |
@@ -179,7 +195,7 @@ dasd_feature_list(char *str, char **endp) | |||
179 | features = 0; | 195 | features = 0; |
180 | 196 | ||
181 | while (1) { | 197 | while (1) { |
182 | for (len = 0; | 198 | for (len = 0; |
183 | str[len] && str[len] != ':' && str[len] != ')'; len++); | 199 | str[len] && str[len] != ':' && str[len] != ')'; len++); |
184 | if (len == 2 && !strncmp(str, "ro", 2)) | 200 | if (len == 2 && !strncmp(str, "ro", 2)) |
185 | features |= DASD_FEATURE_READONLY; | 201 | features |= DASD_FEATURE_READONLY; |
@@ -228,19 +244,24 @@ dasd_parse_keyword( char *parsestring ) { | |||
228 | length = strlen(parsestring); | 244 | length = strlen(parsestring); |
229 | residual_str = parsestring + length; | 245 | residual_str = parsestring + length; |
230 | } | 246 | } |
231 | if (strncmp ("autodetect", parsestring, length) == 0) { | 247 | if (strncmp("autodetect", parsestring, length) == 0) { |
232 | dasd_autodetect = 1; | 248 | dasd_autodetect = 1; |
233 | MESSAGE (KERN_INFO, "%s", | 249 | MESSAGE (KERN_INFO, "%s", |
234 | "turning to autodetection mode"); | 250 | "turning to autodetection mode"); |
235 | return residual_str; | 251 | return residual_str; |
236 | } | 252 | } |
237 | if (strncmp ("probeonly", parsestring, length) == 0) { | 253 | if (strncmp("probeonly", parsestring, length) == 0) { |
238 | dasd_probeonly = 1; | 254 | dasd_probeonly = 1; |
239 | MESSAGE(KERN_INFO, "%s", | 255 | MESSAGE(KERN_INFO, "%s", |
240 | "turning to probeonly mode"); | 256 | "turning to probeonly mode"); |
241 | return residual_str; | 257 | return residual_str; |
242 | } | 258 | } |
243 | if (strncmp ("fixedbuffers", parsestring, length) == 0) { | 259 | if (strncmp("nopav", parsestring, length) == 0) { |
260 | dasd_nopav = 1; | ||
261 | MESSAGE(KERN_INFO, "%s", "disable PAV mode"); | ||
262 | return residual_str; | ||
263 | } | ||
264 | if (strncmp("fixedbuffers", parsestring, length) == 0) { | ||
244 | if (dasd_page_cache) | 265 | if (dasd_page_cache) |
245 | return residual_str; | 266 | return residual_str; |
246 | dasd_page_cache = | 267 | dasd_page_cache = |
@@ -294,6 +315,8 @@ dasd_parse_range( char *parsestring ) { | |||
294 | features = dasd_feature_list(str, &str); | 315 | features = dasd_feature_list(str, &str); |
295 | if (features < 0) | 316 | if (features < 0) |
296 | return ERR_PTR(-EINVAL); | 317 | return ERR_PTR(-EINVAL); |
318 | /* each device in dasd= parameter should be set initially online */ | ||
319 | features |= DASD_FEATURE_INITIAL_ONLINE; | ||
297 | while (from <= to) { | 320 | while (from <= to) { |
298 | sprintf(bus_id, "%01x.%01x.%04x", | 321 | sprintf(bus_id, "%01x.%01x.%04x", |
299 | from_id0, from_id1, from++); | 322 | from_id0, from_id1, from++); |
@@ -359,7 +382,7 @@ dasd_parse(void) | |||
359 | * Add a devmap for the device specified by busid. It is possible that | 382 | * Add a devmap for the device specified by busid. It is possible that |
360 | * the devmap already exists (dasd= parameter). The order of the devices | 383 | * the devmap already exists (dasd= parameter). The order of the devices |
361 | * added through this function will define the kdevs for the individual | 384 | * added through this function will define the kdevs for the individual |
362 | * devices. | 385 | * devices. |
363 | */ | 386 | */ |
364 | static struct dasd_devmap * | 387 | static struct dasd_devmap * |
365 | dasd_add_busid(char *bus_id, int features) | 388 | dasd_add_busid(char *bus_id, int features) |
@@ -368,7 +391,7 @@ dasd_add_busid(char *bus_id, int features) | |||
368 | int hash; | 391 | int hash; |
369 | 392 | ||
370 | new = (struct dasd_devmap *) | 393 | new = (struct dasd_devmap *) |
371 | kmalloc(sizeof(struct dasd_devmap), GFP_KERNEL); | 394 | kzalloc(sizeof(struct dasd_devmap), GFP_KERNEL); |
372 | if (!new) | 395 | if (!new) |
373 | return ERR_PTR(-ENOMEM); | 396 | return ERR_PTR(-ENOMEM); |
374 | spin_lock(&dasd_devmap_lock); | 397 | spin_lock(&dasd_devmap_lock); |
@@ -630,7 +653,8 @@ dasd_ro_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
630 | } | 653 | } |
631 | 654 | ||
632 | static ssize_t | 655 | static ssize_t |
633 | dasd_ro_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 656 | dasd_ro_store(struct device *dev, struct device_attribute *attr, |
657 | const char *buf, size_t count) | ||
634 | { | 658 | { |
635 | struct dasd_devmap *devmap; | 659 | struct dasd_devmap *devmap; |
636 | int ro_flag; | 660 | int ro_flag; |
@@ -658,7 +682,7 @@ static DEVICE_ATTR(readonly, 0644, dasd_ro_show, dasd_ro_store); | |||
658 | * use_diag controls whether the driver should use diag rather than ssch | 682 | * use_diag controls whether the driver should use diag rather than ssch |
659 | * to talk to the device | 683 | * to talk to the device |
660 | */ | 684 | */ |
661 | static ssize_t | 685 | static ssize_t |
662 | dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf) | 686 | dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf) |
663 | { | 687 | { |
664 | struct dasd_devmap *devmap; | 688 | struct dasd_devmap *devmap; |
@@ -673,7 +697,8 @@ dasd_use_diag_show(struct device *dev, struct device_attribute *attr, char *buf) | |||
673 | } | 697 | } |
674 | 698 | ||
675 | static ssize_t | 699 | static ssize_t |
676 | dasd_use_diag_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 700 | dasd_use_diag_store(struct device *dev, struct device_attribute *attr, |
701 | const char *buf, size_t count) | ||
677 | { | 702 | { |
678 | struct dasd_devmap *devmap; | 703 | struct dasd_devmap *devmap; |
679 | ssize_t rc; | 704 | ssize_t rc; |
@@ -697,11 +722,11 @@ dasd_use_diag_store(struct device *dev, struct device_attribute *attr, const cha | |||
697 | return rc; | 722 | return rc; |
698 | } | 723 | } |
699 | 724 | ||
700 | static | 725 | static DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store); |
701 | DEVICE_ATTR(use_diag, 0644, dasd_use_diag_show, dasd_use_diag_store); | ||
702 | 726 | ||
703 | static ssize_t | 727 | static ssize_t |
704 | dasd_discipline_show(struct device *dev, struct device_attribute *attr, char *buf) | 728 | dasd_discipline_show(struct device *dev, struct device_attribute *attr, |
729 | char *buf) | ||
705 | { | 730 | { |
706 | struct dasd_devmap *devmap; | 731 | struct dasd_devmap *devmap; |
707 | char *dname; | 732 | char *dname; |
@@ -834,6 +859,38 @@ static struct attribute_group dasd_attr_group = { | |||
834 | .attrs = dasd_attrs, | 859 | .attrs = dasd_attrs, |
835 | }; | 860 | }; |
836 | 861 | ||
862 | /* | ||
863 | * Check if the related storage server is already contained in the | ||
864 | * dasd_serverlist. If server is not contained, create new entry. | ||
865 | * Return 0 if server was already in serverlist, | ||
866 | * 1 if the server was added successfully | ||
867 | * <0 in case of error. | ||
868 | */ | ||
869 | static int | ||
870 | dasd_add_server(struct dasd_uid *uid) | ||
871 | { | ||
872 | struct dasd_servermap *new, *tmp; | ||
873 | |||
874 | /* check if server is already contained */ | ||
875 | list_for_each_entry(tmp, &dasd_serverlist, list) | ||
876 | // normale cmp? | ||
877 | if (strncmp(tmp->sid.vendor, uid->vendor, | ||
878 | sizeof(tmp->sid.vendor)) == 0 | ||
879 | && strncmp(tmp->sid.serial, uid->serial, | ||
880 | sizeof(tmp->sid.serial)) == 0) | ||
881 | return 0; | ||
882 | |||
883 | new = (struct dasd_servermap *) | ||
884 | kzalloc(sizeof(struct dasd_servermap), GFP_KERNEL); | ||
885 | if (!new) | ||
886 | return -ENOMEM; | ||
887 | |||
888 | strncpy(new->sid.vendor, uid->vendor, sizeof(new->sid.vendor)); | ||
889 | strncpy(new->sid.serial, uid->serial, sizeof(new->sid.serial)); | ||
890 | list_add(&new->list, &dasd_serverlist); | ||
891 | return 1; | ||
892 | } | ||
893 | |||
837 | 894 | ||
838 | /* | 895 | /* |
839 | * Return copy of the device unique identifier. | 896 | * Return copy of the device unique identifier. |
@@ -854,21 +911,26 @@ dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) | |||
854 | 911 | ||
855 | /* | 912 | /* |
856 | * Register the given device unique identifier into devmap struct. | 913 | * Register the given device unique identifier into devmap struct. |
914 | * Return 0 if server was already in serverlist, | ||
915 | * 1 if the server was added successful | ||
916 | * <0 in case of error. | ||
857 | */ | 917 | */ |
858 | int | 918 | int |
859 | dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) | 919 | dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) |
860 | { | 920 | { |
861 | struct dasd_devmap *devmap; | 921 | struct dasd_devmap *devmap; |
922 | int rc; | ||
862 | 923 | ||
863 | devmap = dasd_find_busid(cdev->dev.bus_id); | 924 | devmap = dasd_find_busid(cdev->dev.bus_id); |
864 | if (IS_ERR(devmap)) | 925 | if (IS_ERR(devmap)) |
865 | return PTR_ERR(devmap); | 926 | return PTR_ERR(devmap); |
866 | spin_lock(&dasd_devmap_lock); | 927 | spin_lock(&dasd_devmap_lock); |
867 | devmap->uid = *uid; | 928 | devmap->uid = *uid; |
929 | rc = dasd_add_server(uid); | ||
868 | spin_unlock(&dasd_devmap_lock); | 930 | spin_unlock(&dasd_devmap_lock); |
869 | return 0; | 931 | return rc; |
870 | } | 932 | } |
871 | EXPORT_SYMBOL(dasd_set_uid); | 933 | EXPORT_SYMBOL_GPL(dasd_set_uid); |
872 | 934 | ||
873 | /* | 935 | /* |
874 | * Return value of the specified feature. | 936 | * Return value of the specified feature. |
@@ -880,7 +942,7 @@ dasd_get_feature(struct ccw_device *cdev, int feature) | |||
880 | 942 | ||
881 | devmap = dasd_find_busid(cdev->dev.bus_id); | 943 | devmap = dasd_find_busid(cdev->dev.bus_id); |
882 | if (IS_ERR(devmap)) | 944 | if (IS_ERR(devmap)) |
883 | return (int) PTR_ERR(devmap); | 945 | return PTR_ERR(devmap); |
884 | 946 | ||
885 | return ((devmap->features & feature) != 0); | 947 | return ((devmap->features & feature) != 0); |
886 | } | 948 | } |
@@ -896,7 +958,7 @@ dasd_set_feature(struct ccw_device *cdev, int feature, int flag) | |||
896 | 958 | ||
897 | devmap = dasd_find_busid(cdev->dev.bus_id); | 959 | devmap = dasd_find_busid(cdev->dev.bus_id); |
898 | if (IS_ERR(devmap)) | 960 | if (IS_ERR(devmap)) |
899 | return (int) PTR_ERR(devmap); | 961 | return PTR_ERR(devmap); |
900 | 962 | ||
901 | spin_lock(&dasd_devmap_lock); | 963 | spin_lock(&dasd_devmap_lock); |
902 | if (flag) | 964 | if (flag) |
@@ -932,8 +994,10 @@ dasd_devmap_init(void) | |||
932 | dasd_max_devindex = 0; | 994 | dasd_max_devindex = 0; |
933 | for (i = 0; i < 256; i++) | 995 | for (i = 0; i < 256; i++) |
934 | INIT_LIST_HEAD(&dasd_hashlists[i]); | 996 | INIT_LIST_HEAD(&dasd_hashlists[i]); |
935 | return 0; | ||
936 | 997 | ||
998 | /* Initialize servermap structure. */ | ||
999 | INIT_LIST_HEAD(&dasd_serverlist); | ||
1000 | return 0; | ||
937 | } | 1001 | } |
938 | 1002 | ||
939 | void | 1003 | void |
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 3f9d704d2657..4002f6c1c1b3 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/drivers/s390/block/dasd_diag.c | 2 | * File...........: linux/drivers/s390/block/dasd_diag.c |
3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
4 | * Based on.......: linux/drivers/s390/block/mdisk.c | 4 | * Based on.......: linux/drivers/s390/block/mdisk.c |
@@ -336,7 +336,7 @@ dasd_diag_check_device(struct dasd_device *device) | |||
336 | 336 | ||
337 | private = (struct dasd_diag_private *) device->private; | 337 | private = (struct dasd_diag_private *) device->private; |
338 | if (private == NULL) { | 338 | if (private == NULL) { |
339 | private = kmalloc(sizeof(struct dasd_diag_private),GFP_KERNEL); | 339 | private = kzalloc(sizeof(struct dasd_diag_private),GFP_KERNEL); |
340 | if (private == NULL) { | 340 | if (private == NULL) { |
341 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 341 | DEV_MESSAGE(KERN_WARNING, device, "%s", |
342 | "memory allocation failed for private data"); | 342 | "memory allocation failed for private data"); |
@@ -527,7 +527,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req) | |||
527 | datasize, device); | 527 | datasize, device); |
528 | if (IS_ERR(cqr)) | 528 | if (IS_ERR(cqr)) |
529 | return cqr; | 529 | return cqr; |
530 | 530 | ||
531 | dreq = (struct dasd_diag_req *) cqr->data; | 531 | dreq = (struct dasd_diag_req *) cqr->data; |
532 | dreq->block_count = count; | 532 | dreq->block_count = count; |
533 | dbio = dreq->bio; | 533 | dbio = dreq->bio; |
diff --git a/drivers/s390/block/dasd_diag.h b/drivers/s390/block/dasd_diag.h index 38a4e55f8953..b8c78267ff3e 100644 --- a/drivers/s390/block/dasd_diag.h +++ b/drivers/s390/block/dasd_diag.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/drivers/s390/block/dasd_diag.h | 2 | * File...........: linux/drivers/s390/block/dasd_diag.h |
3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
4 | * Based on.......: linux/drivers/s390/block/mdisk.h | 4 | * Based on.......: linux/drivers/s390/block/mdisk.h |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 7d5a6cee4bd8..0dfab30e8089 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/drivers/s390/block/dasd_eckd.c | 2 | * File...........: linux/drivers/s390/block/dasd_eckd.c |
3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
4 | * Horst Hummel <Horst.Hummel@de.ibm.com> | 4 | * Horst Hummel <Horst.Hummel@de.ibm.com> |
5 | * Carsten Otte <Cotte@de.ibm.com> | 5 | * Carsten Otte <Cotte@de.ibm.com> |
6 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 6 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
7 | * Bugreports.to..: <Linux390@de.ibm.com> | 7 | * Bugreports.to..: <Linux390@de.ibm.com> |
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/io.h> | 24 | #include <asm/io.h> |
25 | #include <asm/todclk.h> | 25 | #include <asm/todclk.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | #include <asm/cio.h> | ||
27 | #include <asm/ccwdev.h> | 28 | #include <asm/ccwdev.h> |
28 | 29 | ||
29 | #include "dasd_int.h" | 30 | #include "dasd_int.h" |
@@ -89,17 +90,22 @@ dasd_eckd_probe (struct ccw_device *cdev) | |||
89 | { | 90 | { |
90 | int ret; | 91 | int ret; |
91 | 92 | ||
92 | ret = dasd_generic_probe (cdev, &dasd_eckd_discipline); | 93 | /* set ECKD specific ccw-device options */ |
93 | if (ret) | 94 | ret = ccw_device_set_options(cdev, CCWDEV_ALLOW_FORCE); |
95 | if (ret) { | ||
96 | printk(KERN_WARNING | ||
97 | "dasd_eckd_probe: could not set ccw-device options " | ||
98 | "for %s\n", cdev->dev.bus_id); | ||
94 | return ret; | 99 | return ret; |
95 | ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP | CCWDEV_ALLOW_FORCE); | 100 | } |
96 | return 0; | 101 | ret = dasd_generic_probe(cdev, &dasd_eckd_discipline); |
102 | return ret; | ||
97 | } | 103 | } |
98 | 104 | ||
99 | static int | 105 | static int |
100 | dasd_eckd_set_online(struct ccw_device *cdev) | 106 | dasd_eckd_set_online(struct ccw_device *cdev) |
101 | { | 107 | { |
102 | return dasd_generic_set_online (cdev, &dasd_eckd_discipline); | 108 | return dasd_generic_set_online(cdev, &dasd_eckd_discipline); |
103 | } | 109 | } |
104 | 110 | ||
105 | static struct ccw_driver dasd_eckd_driver = { | 111 | static struct ccw_driver dasd_eckd_driver = { |
@@ -210,14 +216,14 @@ check_XRC (struct ccw1 *de_ccw, | |||
210 | 216 | ||
211 | /* switch on System Time Stamp - needed for XRC Support */ | 217 | /* switch on System Time Stamp - needed for XRC Support */ |
212 | if (private->rdc_data.facilities.XRC_supported) { | 218 | if (private->rdc_data.facilities.XRC_supported) { |
213 | 219 | ||
214 | data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid' */ | 220 | data->ga_extended |= 0x08; /* switch on 'Time Stamp Valid' */ |
215 | data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */ | 221 | data->ga_extended |= 0x02; /* switch on 'Extended Parameter' */ |
216 | 222 | ||
217 | data->ep_sys_time = get_clock (); | 223 | data->ep_sys_time = get_clock (); |
218 | 224 | ||
219 | de_ccw->count = sizeof (struct DE_eckd_data); | 225 | de_ccw->count = sizeof (struct DE_eckd_data); |
220 | de_ccw->flags |= CCW_FLAG_SLI; | 226 | de_ccw->flags |= CCW_FLAG_SLI; |
221 | } | 227 | } |
222 | 228 | ||
223 | return; | 229 | return; |
@@ -296,8 +302,8 @@ define_extent(struct ccw1 * ccw, struct DE_eckd_data * data, int trk, | |||
296 | /* check for sequential prestage - enhance cylinder range */ | 302 | /* check for sequential prestage - enhance cylinder range */ |
297 | if (data->attributes.operation == DASD_SEQ_PRESTAGE || | 303 | if (data->attributes.operation == DASD_SEQ_PRESTAGE || |
298 | data->attributes.operation == DASD_SEQ_ACCESS) { | 304 | data->attributes.operation == DASD_SEQ_ACCESS) { |
299 | 305 | ||
300 | if (end.cyl + private->attrib.nr_cyl < geo.cyl) | 306 | if (end.cyl + private->attrib.nr_cyl < geo.cyl) |
301 | end.cyl += private->attrib.nr_cyl; | 307 | end.cyl += private->attrib.nr_cyl; |
302 | else | 308 | else |
303 | end.cyl = (geo.cyl - 1); | 309 | end.cyl = (geo.cyl - 1); |
@@ -317,7 +323,7 @@ locate_record(struct ccw1 *ccw, struct LO_eckd_data *data, int trk, | |||
317 | struct dasd_eckd_private *private; | 323 | struct dasd_eckd_private *private; |
318 | int sector; | 324 | int sector; |
319 | int dn, d; | 325 | int dn, d; |
320 | 326 | ||
321 | private = (struct dasd_eckd_private *) device->private; | 327 | private = (struct dasd_eckd_private *) device->private; |
322 | 328 | ||
323 | DBF_DEV_EVENT(DBF_INFO, device, | 329 | DBF_DEV_EVENT(DBF_INFO, device, |
@@ -541,6 +547,86 @@ dasd_eckd_read_conf(struct dasd_device *device) | |||
541 | } | 547 | } |
542 | 548 | ||
543 | /* | 549 | /* |
550 | * Build CP for Perform Subsystem Function - SSC. | ||
551 | */ | ||
552 | struct dasd_ccw_req * | ||
553 | dasd_eckd_build_psf_ssc(struct dasd_device *device) | ||
554 | { | ||
555 | struct dasd_ccw_req *cqr; | ||
556 | struct dasd_psf_ssc_data *psf_ssc_data; | ||
557 | struct ccw1 *ccw; | ||
558 | |||
559 | cqr = dasd_smalloc_request("ECKD", 1 /* PSF */ , | ||
560 | sizeof(struct dasd_psf_ssc_data), | ||
561 | device); | ||
562 | |||
563 | if (IS_ERR(cqr)) { | ||
564 | DEV_MESSAGE(KERN_WARNING, device, "%s", | ||
565 | "Could not allocate PSF-SSC request"); | ||
566 | return cqr; | ||
567 | } | ||
568 | psf_ssc_data = (struct dasd_psf_ssc_data *)cqr->data; | ||
569 | psf_ssc_data->order = PSF_ORDER_SSC; | ||
570 | psf_ssc_data->suborder = 0x08; | ||
571 | |||
572 | ccw = cqr->cpaddr; | ||
573 | ccw->cmd_code = DASD_ECKD_CCW_PSF; | ||
574 | ccw->cda = (__u32)(addr_t)psf_ssc_data; | ||
575 | ccw->count = 66; | ||
576 | |||
577 | cqr->device = device; | ||
578 | cqr->expires = 10*HZ; | ||
579 | cqr->buildclk = get_clock(); | ||
580 | cqr->status = DASD_CQR_FILLED; | ||
581 | return cqr; | ||
582 | } | ||
583 | |||
584 | /* | ||
585 | * Perform Subsystem Function. | ||
586 | * It is necessary to trigger CIO for channel revalidation since this | ||
587 | * call might change behaviour of DASD devices. | ||
588 | */ | ||
589 | static int | ||
590 | dasd_eckd_psf_ssc(struct dasd_device *device) | ||
591 | { | ||
592 | struct dasd_ccw_req *cqr; | ||
593 | int rc; | ||
594 | |||
595 | cqr = dasd_eckd_build_psf_ssc(device); | ||
596 | if (IS_ERR(cqr)) | ||
597 | return PTR_ERR(cqr); | ||
598 | |||
599 | rc = dasd_sleep_on(cqr); | ||
600 | if (!rc) | ||
601 | /* trigger CIO to reprobe devices */ | ||
602 | css_schedule_reprobe(); | ||
603 | dasd_sfree_request(cqr, cqr->device); | ||
604 | return rc; | ||
605 | } | ||
606 | |||
607 | /* | ||
608 | * Valide storage server of current device. | ||
609 | */ | ||
610 | static int | ||
611 | dasd_eckd_validate_server(struct dasd_device *device) | ||
612 | { | ||
613 | int rc; | ||
614 | |||
615 | /* Currently PAV is the only reason to 'validate' server on LPAR */ | ||
616 | if (dasd_nopav || MACHINE_IS_VM) | ||
617 | return 0; | ||
618 | |||
619 | rc = dasd_eckd_psf_ssc(device); | ||
620 | if (rc) | ||
621 | /* may be requested feature is not available on server, | ||
622 | * therefore just report error and go ahead */ | ||
623 | DEV_MESSAGE(KERN_INFO, device, | ||
624 | "Perform Subsystem Function returned rc=%d", rc); | ||
625 | /* RE-Read Configuration Data */ | ||
626 | return dasd_eckd_read_conf(device); | ||
627 | } | ||
628 | |||
629 | /* | ||
544 | * Check device characteristics. | 630 | * Check device characteristics. |
545 | * If the device is accessible using ECKD discipline, the device is enabled. | 631 | * If the device is accessible using ECKD discipline, the device is enabled. |
546 | */ | 632 | */ |
@@ -554,7 +640,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
554 | 640 | ||
555 | private = (struct dasd_eckd_private *) device->private; | 641 | private = (struct dasd_eckd_private *) device->private; |
556 | if (private == NULL) { | 642 | if (private == NULL) { |
557 | private = kmalloc(sizeof(struct dasd_eckd_private), | 643 | private = kzalloc(sizeof(struct dasd_eckd_private), |
558 | GFP_KERNEL | GFP_DMA); | 644 | GFP_KERNEL | GFP_DMA); |
559 | if (private == NULL) { | 645 | if (private == NULL) { |
560 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 646 | DEV_MESSAGE(KERN_WARNING, device, "%s", |
@@ -562,7 +648,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
562 | "data"); | 648 | "data"); |
563 | return -ENOMEM; | 649 | return -ENOMEM; |
564 | } | 650 | } |
565 | memset(private, 0, sizeof(struct dasd_eckd_private)); | ||
566 | device->private = (void *) private; | 651 | device->private = (void *) private; |
567 | } | 652 | } |
568 | /* Invalidate status of initial analysis. */ | 653 | /* Invalidate status of initial analysis. */ |
@@ -571,16 +656,29 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
571 | private->attrib.operation = DASD_NORMAL_CACHE; | 656 | private->attrib.operation = DASD_NORMAL_CACHE; |
572 | private->attrib.nr_cyl = 0; | 657 | private->attrib.nr_cyl = 0; |
573 | 658 | ||
659 | /* Read Configuration Data */ | ||
660 | rc = dasd_eckd_read_conf(device); | ||
661 | if (rc) | ||
662 | return rc; | ||
663 | |||
664 | /* Generate device unique id and register in devmap */ | ||
665 | rc = dasd_eckd_generate_uid(device, &uid); | ||
666 | if (rc) | ||
667 | return rc; | ||
668 | rc = dasd_set_uid(device->cdev, &uid); | ||
669 | if (rc == 1) /* new server found */ | ||
670 | rc = dasd_eckd_validate_server(device); | ||
671 | if (rc) | ||
672 | return rc; | ||
673 | |||
574 | /* Read Device Characteristics */ | 674 | /* Read Device Characteristics */ |
575 | rdc_data = (void *) &(private->rdc_data); | 675 | rdc_data = (void *) &(private->rdc_data); |
576 | memset(rdc_data, 0, sizeof(rdc_data)); | 676 | memset(rdc_data, 0, sizeof(rdc_data)); |
577 | rc = read_dev_chars(device->cdev, &rdc_data, 64); | 677 | rc = read_dev_chars(device->cdev, &rdc_data, 64); |
578 | if (rc) { | 678 | if (rc) |
579 | DEV_MESSAGE(KERN_WARNING, device, | 679 | DEV_MESSAGE(KERN_WARNING, device, |
580 | "Read device characteristics returned error %d", | 680 | "Read device characteristics returned " |
581 | rc); | 681 | "rc=%d", rc); |
582 | return rc; | ||
583 | } | ||
584 | 682 | ||
585 | DEV_MESSAGE(KERN_INFO, device, | 683 | DEV_MESSAGE(KERN_INFO, device, |
586 | "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d", | 684 | "%04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d", |
@@ -591,19 +689,6 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
591 | private->rdc_data.no_cyl, | 689 | private->rdc_data.no_cyl, |
592 | private->rdc_data.trk_per_cyl, | 690 | private->rdc_data.trk_per_cyl, |
593 | private->rdc_data.sec_per_trk); | 691 | private->rdc_data.sec_per_trk); |
594 | |||
595 | /* Read Configuration Data */ | ||
596 | rc = dasd_eckd_read_conf (device); | ||
597 | if (rc) | ||
598 | return rc; | ||
599 | |||
600 | /* Generate device unique id and register in devmap */ | ||
601 | rc = dasd_eckd_generate_uid(device, &uid); | ||
602 | if (rc) | ||
603 | return rc; | ||
604 | |||
605 | rc = dasd_set_uid(device->cdev, &uid); | ||
606 | |||
607 | return rc; | 692 | return rc; |
608 | } | 693 | } |
609 | 694 | ||
@@ -773,7 +858,7 @@ dasd_eckd_end_analysis(struct dasd_device *device) | |||
773 | ((private->rdc_data.no_cyl * | 858 | ((private->rdc_data.no_cyl * |
774 | private->rdc_data.trk_per_cyl * | 859 | private->rdc_data.trk_per_cyl * |
775 | blk_per_trk * (device->bp_block >> 9)) >> 1), | 860 | blk_per_trk * (device->bp_block >> 9)) >> 1), |
776 | ((blk_per_trk * device->bp_block) >> 10), | 861 | ((blk_per_trk * device->bp_block) >> 10), |
777 | private->uses_cdl ? | 862 | private->uses_cdl ? |
778 | "compatible disk layout" : "linux disk layout"); | 863 | "compatible disk layout" : "linux disk layout"); |
779 | 864 | ||
@@ -970,7 +1055,7 @@ dasd_eckd_format_device(struct dasd_device * device, | |||
970 | if (i < 3) { | 1055 | if (i < 3) { |
971 | ect->kl = 4; | 1056 | ect->kl = 4; |
972 | ect->dl = sizes_trk0[i] - 4; | 1057 | ect->dl = sizes_trk0[i] - 4; |
973 | } | 1058 | } |
974 | } | 1059 | } |
975 | if ((fdata->intensity & 0x08) && | 1060 | if ((fdata->intensity & 0x08) && |
976 | fdata->start_unit == 1) { | 1061 | fdata->start_unit == 1) { |
@@ -1270,7 +1355,7 @@ dasd_eckd_fill_info(struct dasd_device * device, | |||
1270 | 1355 | ||
1271 | /* | 1356 | /* |
1272 | * Release device ioctl. | 1357 | * Release device ioctl. |
1273 | * Buils a channel programm to releases a prior reserved | 1358 | * Buils a channel programm to releases a prior reserved |
1274 | * (see dasd_eckd_reserve) device. | 1359 | * (see dasd_eckd_reserve) device. |
1275 | */ | 1360 | */ |
1276 | static int | 1361 | static int |
@@ -1310,8 +1395,8 @@ dasd_eckd_release(struct dasd_device *device) | |||
1310 | /* | 1395 | /* |
1311 | * Reserve device ioctl. | 1396 | * Reserve device ioctl. |
1312 | * Options are set to 'synchronous wait for interrupt' and | 1397 | * Options are set to 'synchronous wait for interrupt' and |
1313 | * 'timeout the request'. This leads to a terminate IO if | 1398 | * 'timeout the request'. This leads to a terminate IO if |
1314 | * the interrupt is outstanding for a certain time. | 1399 | * the interrupt is outstanding for a certain time. |
1315 | */ | 1400 | */ |
1316 | static int | 1401 | static int |
1317 | dasd_eckd_reserve(struct dasd_device *device) | 1402 | dasd_eckd_reserve(struct dasd_device *device) |
@@ -1349,7 +1434,7 @@ dasd_eckd_reserve(struct dasd_device *device) | |||
1349 | 1434 | ||
1350 | /* | 1435 | /* |
1351 | * Steal lock ioctl - unconditional reserve device. | 1436 | * Steal lock ioctl - unconditional reserve device. |
1352 | * Buils a channel programm to break a device's reservation. | 1437 | * Buils a channel programm to break a device's reservation. |
1353 | * (unconditional reserve) | 1438 | * (unconditional reserve) |
1354 | */ | 1439 | */ |
1355 | static int | 1440 | static int |
@@ -1522,6 +1607,40 @@ dasd_eckd_ioctl(struct dasd_device *device, unsigned int cmd, void __user *argp) | |||
1522 | } | 1607 | } |
1523 | 1608 | ||
1524 | /* | 1609 | /* |
1610 | * Dump the range of CCWs into 'page' buffer | ||
1611 | * and return number of printed chars. | ||
1612 | */ | ||
1613 | static inline int | ||
1614 | dasd_eckd_dump_ccw_range(struct ccw1 *from, struct ccw1 *to, char *page) | ||
1615 | { | ||
1616 | int len, count; | ||
1617 | char *datap; | ||
1618 | |||
1619 | len = 0; | ||
1620 | while (from <= to) { | ||
1621 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
1622 | " CCW %p: %08X %08X DAT:", | ||
1623 | from, ((int *) from)[0], ((int *) from)[1]); | ||
1624 | |||
1625 | /* get pointer to data (consider IDALs) */ | ||
1626 | if (from->flags & CCW_FLAG_IDA) | ||
1627 | datap = (char *) *((addr_t *) (addr_t) from->cda); | ||
1628 | else | ||
1629 | datap = (char *) ((addr_t) from->cda); | ||
1630 | |||
1631 | /* dump data (max 32 bytes) */ | ||
1632 | for (count = 0; count < from->count && count < 32; count++) { | ||
1633 | if (count % 8 == 0) len += sprintf(page + len, " "); | ||
1634 | if (count % 4 == 0) len += sprintf(page + len, " "); | ||
1635 | len += sprintf(page + len, "%02x", datap[count]); | ||
1636 | } | ||
1637 | len += sprintf(page + len, "\n"); | ||
1638 | from++; | ||
1639 | } | ||
1640 | return len; | ||
1641 | } | ||
1642 | |||
1643 | /* | ||
1525 | * Print sense data and related channel program. | 1644 | * Print sense data and related channel program. |
1526 | * Parts are printed because printk buffer is only 1024 bytes. | 1645 | * Parts are printed because printk buffer is only 1024 bytes. |
1527 | */ | 1646 | */ |
@@ -1530,8 +1649,8 @@ dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, | |||
1530 | struct irb *irb) | 1649 | struct irb *irb) |
1531 | { | 1650 | { |
1532 | char *page; | 1651 | char *page; |
1533 | struct ccw1 *act, *end, *last; | 1652 | struct ccw1 *first, *last, *fail, *from, *to; |
1534 | int len, sl, sct, count; | 1653 | int len, sl, sct; |
1535 | 1654 | ||
1536 | page = (char *) get_zeroed_page(GFP_ATOMIC); | 1655 | page = (char *) get_zeroed_page(GFP_ATOMIC); |
1537 | if (page == NULL) { | 1656 | if (page == NULL) { |
@@ -1539,7 +1658,8 @@ dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, | |||
1539 | "No memory to dump sense data"); | 1658 | "No memory to dump sense data"); |
1540 | return; | 1659 | return; |
1541 | } | 1660 | } |
1542 | len = sprintf(page, KERN_ERR PRINTK_HEADER | 1661 | /* dump the sense data */ |
1662 | len = sprintf(page, KERN_ERR PRINTK_HEADER | ||
1543 | " I/O status report for device %s:\n", | 1663 | " I/O status report for device %s:\n", |
1544 | device->cdev->dev.bus_id); | 1664 | device->cdev->dev.bus_id); |
1545 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 1665 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
@@ -1564,87 +1684,55 @@ dasd_eckd_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, | |||
1564 | 1684 | ||
1565 | if (irb->ecw[27] & DASD_SENSE_BIT_0) { | 1685 | if (irb->ecw[27] & DASD_SENSE_BIT_0) { |
1566 | /* 24 Byte Sense Data */ | 1686 | /* 24 Byte Sense Data */ |
1567 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 1687 | sprintf(page + len, KERN_ERR PRINTK_HEADER |
1568 | " 24 Byte: %x MSG %x, " | 1688 | " 24 Byte: %x MSG %x, " |
1569 | "%s MSGb to SYSOP\n", | 1689 | "%s MSGb to SYSOP\n", |
1570 | irb->ecw[7] >> 4, irb->ecw[7] & 0x0f, | 1690 | irb->ecw[7] >> 4, irb->ecw[7] & 0x0f, |
1571 | irb->ecw[1] & 0x10 ? "" : "no"); | 1691 | irb->ecw[1] & 0x10 ? "" : "no"); |
1572 | } else { | 1692 | } else { |
1573 | /* 32 Byte Sense Data */ | 1693 | /* 32 Byte Sense Data */ |
1574 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 1694 | sprintf(page + len, KERN_ERR PRINTK_HEADER |
1575 | " 32 Byte: Format: %x " | 1695 | " 32 Byte: Format: %x " |
1576 | "Exception class %x\n", | 1696 | "Exception class %x\n", |
1577 | irb->ecw[6] & 0x0f, irb->ecw[22] >> 4); | 1697 | irb->ecw[6] & 0x0f, irb->ecw[22] >> 4); |
1578 | } | 1698 | } |
1579 | } else { | 1699 | } else { |
1580 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 1700 | sprintf(page + len, KERN_ERR PRINTK_HEADER |
1581 | " SORRY - NO VALID SENSE AVAILABLE\n"); | 1701 | " SORRY - NO VALID SENSE AVAILABLE\n"); |
1582 | } | 1702 | } |
1583 | MESSAGE_LOG(KERN_ERR, "%s", | 1703 | printk("%s", page); |
1584 | page + sizeof(KERN_ERR PRINTK_HEADER)); | 1704 | |
1585 | 1705 | /* dump the Channel Program (max 140 Bytes per line) */ | |
1586 | /* dump the Channel Program */ | 1706 | /* Count CCW and print first CCWs (maximum 1024 % 140 = 7) */ |
1587 | /* print first CCWs (maximum 8) */ | 1707 | first = req->cpaddr; |
1588 | act = req->cpaddr; | 1708 | for (last = first; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++); |
1589 | for (last = act; last->flags & (CCW_FLAG_CC | CCW_FLAG_DC); last++); | 1709 | to = min(first + 6, last); |
1590 | end = min(act + 8, last); | 1710 | len = sprintf(page, KERN_ERR PRINTK_HEADER |
1591 | len = sprintf(page, KERN_ERR PRINTK_HEADER | ||
1592 | " Related CP in req: %p\n", req); | 1711 | " Related CP in req: %p\n", req); |
1593 | while (act <= end) { | 1712 | dasd_eckd_dump_ccw_range(first, to, page + len); |
1594 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 1713 | printk("%s", page); |
1595 | " CCW %p: %08X %08X DAT:", | ||
1596 | act, ((int *) act)[0], ((int *) act)[1]); | ||
1597 | for (count = 0; count < 32 && count < act->count; | ||
1598 | count += sizeof(int)) | ||
1599 | len += sprintf(page + len, " %08X", | ||
1600 | ((int *) (addr_t) act->cda) | ||
1601 | [(count>>2)]); | ||
1602 | len += sprintf(page + len, "\n"); | ||
1603 | act++; | ||
1604 | } | ||
1605 | MESSAGE_LOG(KERN_ERR, "%s", | ||
1606 | page + sizeof(KERN_ERR PRINTK_HEADER)); | ||
1607 | 1714 | ||
1608 | /* print failing CCW area */ | 1715 | /* print failing CCW area (maximum 4) */ |
1716 | /* scsw->cda is either valid or zero */ | ||
1609 | len = 0; | 1717 | len = 0; |
1610 | if (act < ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2) { | 1718 | from = ++to; |
1611 | act = ((struct ccw1 *)(addr_t) irb->scsw.cpa) - 2; | 1719 | fail = (struct ccw1 *)(addr_t) irb->scsw.cpa; /* failing CCW */ |
1612 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n"); | 1720 | if (from < fail - 2) { |
1613 | } | 1721 | from = fail - 2; /* there is a gap - print header */ |
1614 | end = min((struct ccw1 *)(addr_t) irb->scsw.cpa + 2, last); | 1722 | len += sprintf(page, KERN_ERR PRINTK_HEADER "......\n"); |
1615 | while (act <= end) { | ||
1616 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
1617 | " CCW %p: %08X %08X DAT:", | ||
1618 | act, ((int *) act)[0], ((int *) act)[1]); | ||
1619 | for (count = 0; count < 32 && count < act->count; | ||
1620 | count += sizeof(int)) | ||
1621 | len += sprintf(page + len, " %08X", | ||
1622 | ((int *) (addr_t) act->cda) | ||
1623 | [(count>>2)]); | ||
1624 | len += sprintf(page + len, "\n"); | ||
1625 | act++; | ||
1626 | } | 1723 | } |
1724 | to = min(fail + 1, last); | ||
1725 | len += dasd_eckd_dump_ccw_range(from, to, page + len); | ||
1627 | 1726 | ||
1628 | /* print last CCWs */ | 1727 | /* print last CCWs (maximum 2) */ |
1629 | if (act < last - 2) { | 1728 | from = max(from, ++to); |
1630 | act = last - 2; | 1729 | if (from < last - 1) { |
1730 | from = last - 1; /* there is a gap - print header */ | ||
1631 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n"); | 1731 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER "......\n"); |
1632 | } | 1732 | } |
1633 | while (act <= last) { | 1733 | len += dasd_eckd_dump_ccw_range(from, last, page + len); |
1634 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | ||
1635 | " CCW %p: %08X %08X DAT:", | ||
1636 | act, ((int *) act)[0], ((int *) act)[1]); | ||
1637 | for (count = 0; count < 32 && count < act->count; | ||
1638 | count += sizeof(int)) | ||
1639 | len += sprintf(page + len, " %08X", | ||
1640 | ((int *) (addr_t) act->cda) | ||
1641 | [(count>>2)]); | ||
1642 | len += sprintf(page + len, "\n"); | ||
1643 | act++; | ||
1644 | } | ||
1645 | if (len > 0) | 1734 | if (len > 0) |
1646 | MESSAGE_LOG(KERN_ERR, "%s", | 1735 | printk("%s", page); |
1647 | page + sizeof(KERN_ERR PRINTK_HEADER)); | ||
1648 | free_page((unsigned long) page); | 1736 | free_page((unsigned long) page); |
1649 | } | 1737 | } |
1650 | 1738 | ||
@@ -1685,14 +1773,8 @@ static struct dasd_discipline dasd_eckd_discipline = { | |||
1685 | static int __init | 1773 | static int __init |
1686 | dasd_eckd_init(void) | 1774 | dasd_eckd_init(void) |
1687 | { | 1775 | { |
1688 | int ret; | ||
1689 | |||
1690 | ASCEBC(dasd_eckd_discipline.ebcname, 4); | 1776 | ASCEBC(dasd_eckd_discipline.ebcname, 4); |
1691 | 1777 | return ccw_driver_register(&dasd_eckd_driver); | |
1692 | ret = ccw_driver_register(&dasd_eckd_driver); | ||
1693 | if (!ret) | ||
1694 | dasd_generic_auto_online(&dasd_eckd_driver); | ||
1695 | return ret; | ||
1696 | } | 1778 | } |
1697 | 1779 | ||
1698 | static void __exit | 1780 | static void __exit |
@@ -1703,22 +1785,3 @@ dasd_eckd_cleanup(void) | |||
1703 | 1785 | ||
1704 | module_init(dasd_eckd_init); | 1786 | module_init(dasd_eckd_init); |
1705 | module_exit(dasd_eckd_cleanup); | 1787 | module_exit(dasd_eckd_cleanup); |
1706 | |||
1707 | /* | ||
1708 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
1709 | * Emacs will notice this stuff at the end of the file and automatically | ||
1710 | * adjust the settings for this buffer only. This must remain at the end | ||
1711 | * of the file. | ||
1712 | * --------------------------------------------------------------------------- | ||
1713 | * Local variables: | ||
1714 | * c-indent-level: 4 | ||
1715 | * c-brace-imaginary-offset: 0 | ||
1716 | * c-brace-offset: -4 | ||
1717 | * c-argdecl-indent: 4 | ||
1718 | * c-label-offset: -4 | ||
1719 | * c-continued-statement-offset: 4 | ||
1720 | * c-continued-brace-offset: 0 | ||
1721 | * indent-tabs-mode: 1 | ||
1722 | * tab-width: 8 | ||
1723 | * End: | ||
1724 | */ | ||
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index d5734e976e1c..712ff1650134 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/drivers/s390/block/dasd_eckd.h | 2 | * File...........: linux/drivers/s390/block/dasd_eckd.h |
3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
4 | * Horst Hummel <Horst.Hummel@de.ibm.com> | 4 | * Horst Hummel <Horst.Hummel@de.ibm.com> |
5 | * Bugreports.to..: <Linux390@de.ibm.com> | 5 | * Bugreports.to..: <Linux390@de.ibm.com> |
6 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 | 6 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 |
7 | * | 7 | * |
@@ -41,9 +41,10 @@ | |||
41 | #define DASD_ECKD_CCW_RESERVE 0xB4 | 41 | #define DASD_ECKD_CCW_RESERVE 0xB4 |
42 | 42 | ||
43 | /* | 43 | /* |
44 | *Perform Subsystem Function / Sub-Orders | 44 | * Perform Subsystem Function / Sub-Orders |
45 | */ | 45 | */ |
46 | #define PSF_ORDER_PRSSD 0x18 | 46 | #define PSF_ORDER_PRSSD 0x18 |
47 | #define PSF_ORDER_SSC 0x1D | ||
47 | 48 | ||
48 | /***************************************************************************** | 49 | /***************************************************************************** |
49 | * SECTION: Type Definitions | 50 | * SECTION: Type Definitions |
@@ -155,7 +156,7 @@ struct dasd_eckd_characteristics { | |||
155 | unsigned char reserved2:4; | 156 | unsigned char reserved2:4; |
156 | unsigned char reserved3:8; | 157 | unsigned char reserved3:8; |
157 | unsigned char defect_wr:1; | 158 | unsigned char defect_wr:1; |
158 | unsigned char XRC_supported:1; | 159 | unsigned char XRC_supported:1; |
159 | unsigned char reserved4:1; | 160 | unsigned char reserved4:1; |
160 | unsigned char striping:1; | 161 | unsigned char striping:1; |
161 | unsigned char reserved5:4; | 162 | unsigned char reserved5:4; |
@@ -343,7 +344,7 @@ struct dasd_eckd_path { | |||
343 | }; | 344 | }; |
344 | 345 | ||
345 | /* | 346 | /* |
346 | * Perform Subsystem Function - Prepare for Read Subsystem Data | 347 | * Perform Subsystem Function - Prepare for Read Subsystem Data |
347 | */ | 348 | */ |
348 | struct dasd_psf_prssd_data { | 349 | struct dasd_psf_prssd_data { |
349 | unsigned char order; | 350 | unsigned char order; |
@@ -353,4 +354,15 @@ struct dasd_psf_prssd_data { | |||
353 | unsigned char varies[9]; | 354 | unsigned char varies[9]; |
354 | } __attribute__ ((packed)); | 355 | } __attribute__ ((packed)); |
355 | 356 | ||
357 | /* | ||
358 | * Perform Subsystem Function - Set Subsystem Characteristics | ||
359 | */ | ||
360 | struct dasd_psf_ssc_data { | ||
361 | unsigned char order; | ||
362 | unsigned char flags; | ||
363 | unsigned char cu_type[4]; | ||
364 | unsigned char suborder; | ||
365 | unsigned char reserved[59]; | ||
366 | } __attribute__((packed)); | ||
367 | |||
356 | #endif /* DASD_ECKD_H */ | 368 | #endif /* DASD_ECKD_H */ |
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index 2d8af709947f..da65f1b032f5 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c | |||
@@ -276,7 +276,7 @@ struct dasd_eer_header { | |||
276 | __u64 tv_sec; | 276 | __u64 tv_sec; |
277 | __u64 tv_usec; | 277 | __u64 tv_usec; |
278 | char busid[DASD_EER_BUSID_SIZE]; | 278 | char busid[DASD_EER_BUSID_SIZE]; |
279 | }; | 279 | } __attribute__ ((packed)); |
280 | 280 | ||
281 | /* | 281 | /* |
282 | * The following function can be used for those triggers that have | 282 | * The following function can be used for those triggers that have |
@@ -521,6 +521,8 @@ static int dasd_eer_open(struct inode *inp, struct file *filp) | |||
521 | unsigned long flags; | 521 | unsigned long flags; |
522 | 522 | ||
523 | eerb = kzalloc(sizeof(struct eerbuffer), GFP_KERNEL); | 523 | eerb = kzalloc(sizeof(struct eerbuffer), GFP_KERNEL); |
524 | if (!eerb) | ||
525 | return -ENOMEM; | ||
524 | eerb->buffer_page_count = eer_pages; | 526 | eerb->buffer_page_count = eer_pages; |
525 | if (eerb->buffer_page_count < 1 || | 527 | if (eerb->buffer_page_count < 1 || |
526 | eerb->buffer_page_count > INT_MAX / PAGE_SIZE) { | 528 | eerb->buffer_page_count > INT_MAX / PAGE_SIZE) { |
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c index b842377cb0c6..4108d96f6a5a 100644 --- a/drivers/s390/block/dasd_erp.c +++ b/drivers/s390/block/dasd_erp.c | |||
@@ -90,7 +90,7 @@ dasd_default_erp_action(struct dasd_ccw_req * cqr) | |||
90 | 90 | ||
91 | /* just retry - there is nothing to save ... I got no sense data.... */ | 91 | /* just retry - there is nothing to save ... I got no sense data.... */ |
92 | if (cqr->retries > 0) { | 92 | if (cqr->retries > 0) { |
93 | DEV_MESSAGE (KERN_DEBUG, device, | 93 | DEV_MESSAGE (KERN_DEBUG, device, |
94 | "default ERP called (%i retries left)", | 94 | "default ERP called (%i retries left)", |
95 | cqr->retries); | 95 | cqr->retries); |
96 | cqr->lpm = LPM_ANYPATH; | 96 | cqr->lpm = LPM_ANYPATH; |
@@ -155,7 +155,7 @@ dasd_default_erp_postaction(struct dasd_ccw_req * cqr) | |||
155 | 155 | ||
156 | /* | 156 | /* |
157 | * Print the hex dump of the memory used by a request. This includes | 157 | * Print the hex dump of the memory used by a request. This includes |
158 | * all error recovery ccws that have been chained in from of the | 158 | * all error recovery ccws that have been chained in from of the |
159 | * real request. | 159 | * real request. |
160 | */ | 160 | */ |
161 | static inline void | 161 | static inline void |
@@ -227,12 +227,12 @@ dasd_log_ccw(struct dasd_ccw_req * cqr, int caller, __u32 cpa) | |||
227 | /* | 227 | /* |
228 | * Log bytes arround failed CCW but only if we did | 228 | * Log bytes arround failed CCW but only if we did |
229 | * not log the whole CP of the CCW is outside the | 229 | * not log the whole CP of the CCW is outside the |
230 | * logged CP. | 230 | * logged CP. |
231 | */ | 231 | */ |
232 | if (cplength > 40 || | 232 | if (cplength > 40 || |
233 | ((addr_t) cpa < (addr_t) lcqr->cpaddr && | 233 | ((addr_t) cpa < (addr_t) lcqr->cpaddr && |
234 | (addr_t) cpa > (addr_t) (lcqr->cpaddr + cplength + 4))) { | 234 | (addr_t) cpa > (addr_t) (lcqr->cpaddr + cplength + 4))) { |
235 | 235 | ||
236 | DEV_MESSAGE(KERN_ERR, device, | 236 | DEV_MESSAGE(KERN_ERR, device, |
237 | "Failed CCW (%p) (area):", | 237 | "Failed CCW (%p) (area):", |
238 | (void *) (long) cpa); | 238 | (void *) (long) cpa); |
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 91145698f8e9..bb7755b9b19d 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/drivers/s390/block/dasd_fba.c | 2 | * File...........: linux/drivers/s390/block/dasd_fba.c |
3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
4 | * Bugreports.to..: <Linux390@de.ibm.com> | 4 | * Bugreports.to..: <Linux390@de.ibm.com> |
@@ -56,19 +56,13 @@ static struct ccw_driver dasd_fba_driver; /* see below */ | |||
56 | static int | 56 | static int |
57 | dasd_fba_probe(struct ccw_device *cdev) | 57 | dasd_fba_probe(struct ccw_device *cdev) |
58 | { | 58 | { |
59 | int ret; | 59 | return dasd_generic_probe(cdev, &dasd_fba_discipline); |
60 | |||
61 | ret = dasd_generic_probe (cdev, &dasd_fba_discipline); | ||
62 | if (ret) | ||
63 | return ret; | ||
64 | ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP); | ||
65 | return 0; | ||
66 | } | 60 | } |
67 | 61 | ||
68 | static int | 62 | static int |
69 | dasd_fba_set_online(struct ccw_device *cdev) | 63 | dasd_fba_set_online(struct ccw_device *cdev) |
70 | { | 64 | { |
71 | return dasd_generic_set_online (cdev, &dasd_fba_discipline); | 65 | return dasd_generic_set_online(cdev, &dasd_fba_discipline); |
72 | } | 66 | } |
73 | 67 | ||
74 | static struct ccw_driver dasd_fba_driver = { | 68 | static struct ccw_driver dasd_fba_driver = { |
@@ -125,13 +119,13 @@ static int | |||
125 | dasd_fba_check_characteristics(struct dasd_device *device) | 119 | dasd_fba_check_characteristics(struct dasd_device *device) |
126 | { | 120 | { |
127 | struct dasd_fba_private *private; | 121 | struct dasd_fba_private *private; |
128 | struct ccw_device *cdev = device->cdev; | 122 | struct ccw_device *cdev = device->cdev; |
129 | void *rdc_data; | 123 | void *rdc_data; |
130 | int rc; | 124 | int rc; |
131 | 125 | ||
132 | private = (struct dasd_fba_private *) device->private; | 126 | private = (struct dasd_fba_private *) device->private; |
133 | if (private == NULL) { | 127 | if (private == NULL) { |
134 | private = kmalloc(sizeof(struct dasd_fba_private), GFP_KERNEL); | 128 | private = kzalloc(sizeof(struct dasd_fba_private), GFP_KERNEL); |
135 | if (private == NULL) { | 129 | if (private == NULL) { |
136 | DEV_MESSAGE(KERN_WARNING, device, "%s", | 130 | DEV_MESSAGE(KERN_WARNING, device, "%s", |
137 | "memory allocation failed for private " | 131 | "memory allocation failed for private " |
@@ -204,7 +198,7 @@ dasd_fba_examine_error(struct dasd_ccw_req * cqr, struct irb * irb) | |||
204 | if (irb->scsw.cstat == 0x00 && | 198 | if (irb->scsw.cstat == 0x00 && |
205 | irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END)) | 199 | irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END)) |
206 | return dasd_era_none; | 200 | return dasd_era_none; |
207 | 201 | ||
208 | cdev = device->cdev; | 202 | cdev = device->cdev; |
209 | switch (cdev->id.dev_type) { | 203 | switch (cdev->id.dev_type) { |
210 | case 0x3370: | 204 | case 0x3370: |
@@ -539,7 +533,7 @@ dasd_fba_dump_sense(struct dasd_device *device, struct dasd_ccw_req * req, | |||
539 | * 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has | 533 | * 8192 bytes (=2 pages). For 64 bit one dasd_mchunkt_t structure has |
540 | * 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use | 534 | * 24 bytes, the struct dasd_ccw_req has 136 bytes and each block can use |
541 | * up to 16 bytes (8 for the ccw and 8 for the idal pointer). In | 535 | * up to 16 bytes (8 for the ccw and 8 for the idal pointer). In |
542 | * addition we have one define extent ccw + 16 bytes of data and a | 536 | * addition we have one define extent ccw + 16 bytes of data and a |
543 | * locate record ccw for each block (stupid devices!) + 16 bytes of data. | 537 | * locate record ccw for each block (stupid devices!) + 16 bytes of data. |
544 | * That makes: | 538 | * That makes: |
545 | * (8192 - 24 - 136 - 8 - 16) / 40 = 200.2 blocks at maximum. | 539 | * (8192 - 24 - 136 - 8 - 16) / 40 = 200.2 blocks at maximum. |
@@ -569,16 +563,8 @@ static struct dasd_discipline dasd_fba_discipline = { | |||
569 | static int __init | 563 | static int __init |
570 | dasd_fba_init(void) | 564 | dasd_fba_init(void) |
571 | { | 565 | { |
572 | int ret; | ||
573 | |||
574 | ASCEBC(dasd_fba_discipline.ebcname, 4); | 566 | ASCEBC(dasd_fba_discipline.ebcname, 4); |
575 | 567 | return ccw_driver_register(&dasd_fba_driver); | |
576 | ret = ccw_driver_register(&dasd_fba_driver); | ||
577 | if (ret) | ||
578 | return ret; | ||
579 | |||
580 | dasd_generic_auto_online(&dasd_fba_driver); | ||
581 | return 0; | ||
582 | } | 568 | } |
583 | 569 | ||
584 | static void __exit | 570 | static void __exit |
@@ -589,22 +575,3 @@ dasd_fba_cleanup(void) | |||
589 | 575 | ||
590 | module_init(dasd_fba_init); | 576 | module_init(dasd_fba_init); |
591 | module_exit(dasd_fba_cleanup); | 577 | module_exit(dasd_fba_cleanup); |
592 | |||
593 | /* | ||
594 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
595 | * Emacs will notice this stuff at the end of the file and automatically | ||
596 | * adjust the settings for this buffer only. This must remain at the end | ||
597 | * of the file. | ||
598 | * --------------------------------------------------------------------------- | ||
599 | * Local variables: | ||
600 | * c-indent-level: 4 | ||
601 | * c-brace-imaginary-offset: 0 | ||
602 | * c-brace-offset: -4 | ||
603 | * c-argdecl-indent: 4 | ||
604 | * c-label-offset: -4 | ||
605 | * c-continued-statement-offset: 4 | ||
606 | * c-continued-brace-offset: 0 | ||
607 | * indent-tabs-mode: 1 | ||
608 | * tab-width: 8 | ||
609 | * End: | ||
610 | */ | ||
diff --git a/drivers/s390/block/dasd_fba.h b/drivers/s390/block/dasd_fba.h index da1fa91fc01d..14c910baa5fe 100644 --- a/drivers/s390/block/dasd_fba.h +++ b/drivers/s390/block/dasd_fba.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/drivers/s390/block/dasd_fba.h | 2 | * File...........: linux/drivers/s390/block/dasd_fba.h |
3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
4 | * Bugreports.to..: <Linux390@de.ibm.com> | 4 | * Bugreports.to..: <Linux390@de.ibm.com> |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index d4b13e300a76..03a83efc34c4 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * File...........: linux/drivers/s390/block/dasd_int.h | 2 | * File...........: linux/drivers/s390/block/dasd_int.h |
3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> | 3 | * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> |
4 | * Horst Hummel <Horst.Hummel@de.ibm.com> | 4 | * Horst Hummel <Horst.Hummel@de.ibm.com> |
5 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 5 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
6 | * Bugreports.to..: <Linux390@de.ibm.com> | 6 | * Bugreports.to..: <Linux390@de.ibm.com> |
7 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 | 7 | * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 |
@@ -186,7 +186,7 @@ struct dasd_ccw_req { | |||
186 | void *callback_data; | 186 | void *callback_data; |
187 | }; | 187 | }; |
188 | 188 | ||
189 | /* | 189 | /* |
190 | * dasd_ccw_req -> status can be: | 190 | * dasd_ccw_req -> status can be: |
191 | */ | 191 | */ |
192 | #define DASD_CQR_FILLED 0x00 /* request is ready to be processed */ | 192 | #define DASD_CQR_FILLED 0x00 /* request is ready to be processed */ |
@@ -248,7 +248,7 @@ struct dasd_discipline { | |||
248 | /* | 248 | /* |
249 | * Error recovery functions. examine_error() returns a value that | 249 | * Error recovery functions. examine_error() returns a value that |
250 | * indicates what to do for an error condition. If examine_error() | 250 | * indicates what to do for an error condition. If examine_error() |
251 | * returns 'dasd_era_recover' erp_action() is called to create a | 251 | * returns 'dasd_era_recover' erp_action() is called to create a |
252 | * special error recovery ccw. erp_postaction() is called after | 252 | * special error recovery ccw. erp_postaction() is called after |
253 | * an error recovery ccw has finished its execution. dump_sense | 253 | * an error recovery ccw has finished its execution. dump_sense |
254 | * is called for every error condition to print the sense data | 254 | * is called for every error condition to print the sense data |
@@ -302,11 +302,11 @@ struct dasd_device { | |||
302 | spinlock_t request_queue_lock; | 302 | spinlock_t request_queue_lock; |
303 | struct block_device *bdev; | 303 | struct block_device *bdev; |
304 | unsigned int devindex; | 304 | unsigned int devindex; |
305 | unsigned long blocks; /* size of volume in blocks */ | 305 | unsigned long blocks; /* size of volume in blocks */ |
306 | unsigned int bp_block; /* bytes per block */ | 306 | unsigned int bp_block; /* bytes per block */ |
307 | unsigned int s2b_shift; /* log2 (bp_block/512) */ | 307 | unsigned int s2b_shift; /* log2 (bp_block/512) */ |
308 | unsigned long flags; /* per device flags */ | 308 | unsigned long flags; /* per device flags */ |
309 | unsigned short features; /* copy of devmap-features (read-only!) */ | 309 | unsigned short features; /* copy of devmap-features (read-only!) */ |
310 | 310 | ||
311 | /* extended error reporting stuff (eer) */ | 311 | /* extended error reporting stuff (eer) */ |
312 | struct dasd_ccw_req *eer_cqr; | 312 | struct dasd_ccw_req *eer_cqr; |
@@ -513,12 +513,12 @@ void dasd_generic_remove (struct ccw_device *cdev); | |||
513 | int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *); | 513 | int dasd_generic_set_online(struct ccw_device *, struct dasd_discipline *); |
514 | int dasd_generic_set_offline (struct ccw_device *cdev); | 514 | int dasd_generic_set_offline (struct ccw_device *cdev); |
515 | int dasd_generic_notify(struct ccw_device *, int); | 515 | int dasd_generic_notify(struct ccw_device *, int); |
516 | void dasd_generic_auto_online (struct ccw_driver *); | ||
517 | 516 | ||
518 | /* externals in dasd_devmap.c */ | 517 | /* externals in dasd_devmap.c */ |
519 | extern int dasd_max_devindex; | 518 | extern int dasd_max_devindex; |
520 | extern int dasd_probeonly; | 519 | extern int dasd_probeonly; |
521 | extern int dasd_autodetect; | 520 | extern int dasd_autodetect; |
521 | extern int dasd_nopav; | ||
522 | 522 | ||
523 | int dasd_devmap_init(void); | 523 | int dasd_devmap_init(void); |
524 | void dasd_devmap_exit(void); | 524 | void dasd_devmap_exit(void); |
@@ -606,22 +606,3 @@ static inline int dasd_eer_enabled(struct dasd_device *device) | |||
606 | #endif /* __KERNEL__ */ | 606 | #endif /* __KERNEL__ */ |
607 | 607 | ||
608 | #endif /* DASD_H */ | 608 | #endif /* DASD_H */ |
609 | |||
610 | /* | ||
611 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
612 | * Emacs will notice this stuff at the end of the file and automatically | ||
613 | * adjust the settings for this buffer only. This must remain at the end | ||
614 | * of the file. | ||
615 | * --------------------------------------------------------------------------- | ||
616 | * Local variables: | ||
617 | * c-indent-level: 4 | ||
618 | * c-brace-imaginary-offset: 0 | ||
619 | * c-brace-offset: -4 | ||
620 | * c-argdecl-indent: 4 | ||
621 | * c-label-offset: -4 | ||
622 | * c-continued-statement-offset: 4 | ||
623 | * c-continued-brace-offset: 0 | ||
624 | * indent-tabs-mode: 1 | ||
625 | * tab-width: 8 | ||
626 | * End: | ||
627 | */ | ||
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index b8c80d28df41..302bcd0f28be 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c | |||
@@ -90,10 +90,10 @@ static int | |||
90 | dasd_ioctl_quiesce(struct dasd_device *device) | 90 | dasd_ioctl_quiesce(struct dasd_device *device) |
91 | { | 91 | { |
92 | unsigned long flags; | 92 | unsigned long flags; |
93 | 93 | ||
94 | if (!capable (CAP_SYS_ADMIN)) | 94 | if (!capable (CAP_SYS_ADMIN)) |
95 | return -EACCES; | 95 | return -EACCES; |
96 | 96 | ||
97 | DEV_MESSAGE (KERN_DEBUG, device, "%s", | 97 | DEV_MESSAGE (KERN_DEBUG, device, "%s", |
98 | "Quiesce IO on device"); | 98 | "Quiesce IO on device"); |
99 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | 99 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
@@ -110,13 +110,13 @@ static int | |||
110 | dasd_ioctl_resume(struct dasd_device *device) | 110 | dasd_ioctl_resume(struct dasd_device *device) |
111 | { | 111 | { |
112 | unsigned long flags; | 112 | unsigned long flags; |
113 | 113 | ||
114 | if (!capable (CAP_SYS_ADMIN)) | 114 | if (!capable (CAP_SYS_ADMIN)) |
115 | return -EACCES; | 115 | return -EACCES; |
116 | 116 | ||
117 | DEV_MESSAGE (KERN_DEBUG, device, "%s", | 117 | DEV_MESSAGE (KERN_DEBUG, device, "%s", |
118 | "resume IO on device"); | 118 | "resume IO on device"); |
119 | 119 | ||
120 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | 120 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
121 | device->stopped &= ~DASD_STOPPED_QUIESCE; | 121 | device->stopped &= ~DASD_STOPPED_QUIESCE; |
122 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | 122 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); |
@@ -287,7 +287,7 @@ dasd_ioctl_information(struct dasd_device *device, | |||
287 | dasd_info->open_count = atomic_read(&device->open_count); | 287 | dasd_info->open_count = atomic_read(&device->open_count); |
288 | if (!device->bdev) | 288 | if (!device->bdev) |
289 | dasd_info->open_count++; | 289 | dasd_info->open_count++; |
290 | 290 | ||
291 | /* | 291 | /* |
292 | * check if device is really formatted | 292 | * check if device is really formatted |
293 | * LDL / CDL was returned by 'fill_info' | 293 | * LDL / CDL was returned by 'fill_info' |
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index eecb2afad5c2..3c1314b7391b 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c | |||
@@ -50,6 +50,9 @@ struct raw3270 { | |||
50 | unsigned char *ascebc; /* ascii -> ebcdic table */ | 50 | unsigned char *ascebc; /* ascii -> ebcdic table */ |
51 | struct class_device *clttydev; /* 3270-class tty device ptr */ | 51 | struct class_device *clttydev; /* 3270-class tty device ptr */ |
52 | struct class_device *cltubdev; /* 3270-class tub device ptr */ | 52 | struct class_device *cltubdev; /* 3270-class tub device ptr */ |
53 | |||
54 | struct raw3270_request init_request; | ||
55 | unsigned char init_data[256]; | ||
53 | }; | 56 | }; |
54 | 57 | ||
55 | /* raw3270->flags */ | 58 | /* raw3270->flags */ |
@@ -484,8 +487,6 @@ struct raw3270_ua { /* Query Reply structure for Usable Area */ | |||
484 | } __attribute__ ((packed)) aua; | 487 | } __attribute__ ((packed)) aua; |
485 | } __attribute__ ((packed)); | 488 | } __attribute__ ((packed)); |
486 | 489 | ||
487 | static unsigned char raw3270_init_data[256]; | ||
488 | static struct raw3270_request raw3270_init_request; | ||
489 | static struct diag210 raw3270_init_diag210; | 490 | static struct diag210 raw3270_init_diag210; |
490 | static DECLARE_MUTEX(raw3270_init_sem); | 491 | static DECLARE_MUTEX(raw3270_init_sem); |
491 | 492 | ||
@@ -644,17 +645,17 @@ __raw3270_size_device(struct raw3270 *rp) | |||
644 | * required (3270 device switched to 'stand-by') and command | 645 | * required (3270 device switched to 'stand-by') and command |
645 | * rejects (old devices that can't do 'read partition'). | 646 | * rejects (old devices that can't do 'read partition'). |
646 | */ | 647 | */ |
647 | memset(&raw3270_init_request, 0, sizeof(raw3270_init_request)); | 648 | memset(&rp->init_request, 0, sizeof(rp->init_request)); |
648 | memset(raw3270_init_data, 0, sizeof(raw3270_init_data)); | 649 | memset(&rp->init_data, 0, 256); |
649 | /* Store 'read partition' data stream to raw3270_init_data */ | 650 | /* Store 'read partition' data stream to init_data */ |
650 | memcpy(raw3270_init_data, wbuf, sizeof(wbuf)); | 651 | memcpy(&rp->init_data, wbuf, sizeof(wbuf)); |
651 | INIT_LIST_HEAD(&raw3270_init_request.list); | 652 | INIT_LIST_HEAD(&rp->init_request.list); |
652 | raw3270_init_request.ccw.cmd_code = TC_WRITESF; | 653 | rp->init_request.ccw.cmd_code = TC_WRITESF; |
653 | raw3270_init_request.ccw.flags = CCW_FLAG_SLI; | 654 | rp->init_request.ccw.flags = CCW_FLAG_SLI; |
654 | raw3270_init_request.ccw.count = sizeof(wbuf); | 655 | rp->init_request.ccw.count = sizeof(wbuf); |
655 | raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data); | 656 | rp->init_request.ccw.cda = (__u32) __pa(&rp->init_data); |
656 | 657 | ||
657 | rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request); | 658 | rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request); |
658 | if (rc) | 659 | if (rc) |
659 | /* Check error cases: -ERESTARTSYS, -EIO and -EOPNOTSUPP */ | 660 | /* Check error cases: -ERESTARTSYS, -EIO and -EOPNOTSUPP */ |
660 | return rc; | 661 | return rc; |
@@ -679,18 +680,18 @@ __raw3270_size_device(struct raw3270 *rp) | |||
679 | * The device accepted the 'read partition' command. Now | 680 | * The device accepted the 'read partition' command. Now |
680 | * set up a read ccw and issue it. | 681 | * set up a read ccw and issue it. |
681 | */ | 682 | */ |
682 | raw3270_init_request.ccw.cmd_code = TC_READMOD; | 683 | rp->init_request.ccw.cmd_code = TC_READMOD; |
683 | raw3270_init_request.ccw.flags = CCW_FLAG_SLI; | 684 | rp->init_request.ccw.flags = CCW_FLAG_SLI; |
684 | raw3270_init_request.ccw.count = sizeof(raw3270_init_data); | 685 | rp->init_request.ccw.count = sizeof(rp->init_data); |
685 | raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data); | 686 | rp->init_request.ccw.cda = (__u32) __pa(rp->init_data); |
686 | rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request); | 687 | rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request); |
687 | if (rc) | 688 | if (rc) |
688 | return rc; | 689 | return rc; |
689 | /* Got a Query Reply */ | 690 | /* Got a Query Reply */ |
690 | count = sizeof(raw3270_init_data) - raw3270_init_request.rescnt; | 691 | count = sizeof(rp->init_data) - rp->init_request.rescnt; |
691 | uap = (struct raw3270_ua *) (raw3270_init_data + 1); | 692 | uap = (struct raw3270_ua *) (rp->init_data + 1); |
692 | /* Paranoia check. */ | 693 | /* Paranoia check. */ |
693 | if (raw3270_init_data[0] != 0x88 || uap->uab.qcode != 0x81) | 694 | if (rp->init_data[0] != 0x88 || uap->uab.qcode != 0x81) |
694 | return -EOPNOTSUPP; | 695 | return -EOPNOTSUPP; |
695 | /* Copy rows/columns of default Usable Area */ | 696 | /* Copy rows/columns of default Usable Area */ |
696 | rp->rows = uap->uab.h; | 697 | rp->rows = uap->uab.h; |
@@ -749,18 +750,18 @@ raw3270_reset_device(struct raw3270 *rp) | |||
749 | int rc; | 750 | int rc; |
750 | 751 | ||
751 | down(&raw3270_init_sem); | 752 | down(&raw3270_init_sem); |
752 | memset(&raw3270_init_request, 0, sizeof(raw3270_init_request)); | 753 | memset(&rp->init_request, 0, sizeof(rp->init_request)); |
753 | memset(raw3270_init_data, 0, sizeof(raw3270_init_data)); | 754 | memset(&rp->init_data, 0, sizeof(rp->init_data)); |
754 | /* Store reset data stream to raw3270_init_data/raw3270_init_request */ | 755 | /* Store reset data stream to init_data/init_request */ |
755 | raw3270_init_data[0] = TW_KR; | 756 | rp->init_data[0] = TW_KR; |
756 | INIT_LIST_HEAD(&raw3270_init_request.list); | 757 | INIT_LIST_HEAD(&rp->init_request.list); |
757 | raw3270_init_request.ccw.cmd_code = TC_EWRITEA; | 758 | rp->init_request.ccw.cmd_code = TC_EWRITEA; |
758 | raw3270_init_request.ccw.flags = CCW_FLAG_SLI; | 759 | rp->init_request.ccw.flags = CCW_FLAG_SLI; |
759 | raw3270_init_request.ccw.count = 1; | 760 | rp->init_request.ccw.count = 1; |
760 | raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data); | 761 | rp->init_request.ccw.cda = (__u32) __pa(rp->init_data); |
761 | rp->view = &raw3270_init_view; | 762 | rp->view = &raw3270_init_view; |
762 | raw3270_init_view.dev = rp; | 763 | raw3270_init_view.dev = rp; |
763 | rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request); | 764 | rc = raw3270_start_init(rp, &raw3270_init_view, &rp->init_request); |
764 | raw3270_init_view.dev = 0; | 765 | raw3270_init_view.dev = 0; |
765 | rp->view = 0; | 766 | rp->view = 0; |
766 | up(&raw3270_init_sem); | 767 | up(&raw3270_init_sem); |
@@ -854,7 +855,7 @@ raw3270_setup_console(struct ccw_device *cdev) | |||
854 | char *ascebc; | 855 | char *ascebc; |
855 | int rc; | 856 | int rc; |
856 | 857 | ||
857 | rp = (struct raw3270 *) alloc_bootmem(sizeof(struct raw3270)); | 858 | rp = (struct raw3270 *) alloc_bootmem_low(sizeof(struct raw3270)); |
858 | ascebc = (char *) alloc_bootmem(256); | 859 | ascebc = (char *) alloc_bootmem(256); |
859 | rc = raw3270_setup_device(cdev, rp, ascebc); | 860 | rc = raw3270_setup_device(cdev, rp, ascebc); |
860 | if (rc) | 861 | if (rc) |
@@ -895,7 +896,7 @@ raw3270_create_device(struct ccw_device *cdev) | |||
895 | char *ascebc; | 896 | char *ascebc; |
896 | int rc; | 897 | int rc; |
897 | 898 | ||
898 | rp = kmalloc(sizeof(struct raw3270), GFP_KERNEL); | 899 | rp = kmalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA); |
899 | if (!rp) | 900 | if (!rp) |
900 | return ERR_PTR(-ENOMEM); | 901 | return ERR_PTR(-ENOMEM); |
901 | ascebc = kmalloc(256, GFP_KERNEL); | 902 | ascebc = kmalloc(256, GFP_KERNEL); |
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index 0960bef7b199..15b895496a45 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c | |||
@@ -224,39 +224,6 @@ is_blacklisted (int ssid, int devno) | |||
224 | } | 224 | } |
225 | 225 | ||
226 | #ifdef CONFIG_PROC_FS | 226 | #ifdef CONFIG_PROC_FS |
227 | static int | ||
228 | __s390_redo_validation(struct subchannel_id schid, void *data) | ||
229 | { | ||
230 | int ret; | ||
231 | struct subchannel *sch; | ||
232 | |||
233 | sch = get_subchannel_by_schid(schid); | ||
234 | if (sch) { | ||
235 | /* Already known. */ | ||
236 | put_device(&sch->dev); | ||
237 | return 0; | ||
238 | } | ||
239 | ret = css_probe_device(schid); | ||
240 | if (ret == -ENXIO) | ||
241 | return ret; /* We're through. */ | ||
242 | if (ret == -ENOMEM) | ||
243 | /* Stop validation for now. Bad, but no need for a panic. */ | ||
244 | return ret; | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | /* | ||
249 | * Function: s390_redo_validation | ||
250 | * Look for no longer blacklisted devices | ||
251 | * FIXME: there must be a better way to do this */ | ||
252 | static inline void | ||
253 | s390_redo_validation (void) | ||
254 | { | ||
255 | CIO_TRACE_EVENT (0, "redoval"); | ||
256 | |||
257 | for_each_subchannel(__s390_redo_validation, NULL); | ||
258 | } | ||
259 | |||
260 | /* | 227 | /* |
261 | * Function: blacklist_parse_proc_parameters | 228 | * Function: blacklist_parse_proc_parameters |
262 | * parse the stuff which is piped to /proc/cio_ignore | 229 | * parse the stuff which is piped to /proc/cio_ignore |
@@ -281,7 +248,7 @@ blacklist_parse_proc_parameters (char *buf) | |||
281 | return; | 248 | return; |
282 | } | 249 | } |
283 | 250 | ||
284 | s390_redo_validation (); | 251 | css_schedule_reprobe(); |
285 | } | 252 | } |
286 | 253 | ||
287 | /* Iterator struct for all devices. */ | 254 | /* Iterator struct for all devices. */ |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index bdfee7fbaa2e..c7319a07ba35 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -404,21 +404,24 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver) | |||
404 | } | 404 | } |
405 | 405 | ||
406 | static int | 406 | static int |
407 | __ccwgroup_driver_unregister_device(struct device *dev, void *data) | 407 | __ccwgroup_match_all(struct device *dev, void *data) |
408 | { | 408 | { |
409 | __ccwgroup_remove_symlinks(to_ccwgroupdev(dev)); | 409 | return 1; |
410 | device_unregister(dev); | ||
411 | put_device(dev); | ||
412 | return 0; | ||
413 | } | 410 | } |
414 | 411 | ||
415 | void | 412 | void |
416 | ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) | 413 | ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) |
417 | { | 414 | { |
415 | struct device *dev; | ||
416 | |||
418 | /* We don't want ccwgroup devices to live longer than their driver. */ | 417 | /* We don't want ccwgroup devices to live longer than their driver. */ |
419 | get_driver(&cdriver->driver); | 418 | get_driver(&cdriver->driver); |
420 | driver_for_each_device(&cdriver->driver, NULL, NULL, | 419 | while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, |
421 | __ccwgroup_driver_unregister_device); | 420 | __ccwgroup_match_all))) { |
421 | __ccwgroup_remove_symlinks(to_ccwgroupdev(dev)); | ||
422 | device_unregister(dev); | ||
423 | put_device(dev); | ||
424 | } | ||
422 | put_driver(&cdriver->driver); | 425 | put_driver(&cdriver->driver); |
423 | driver_unregister(&cdriver->driver); | 426 | driver_unregister(&cdriver->driver); |
424 | } | 427 | } |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 72187e54dcac..b00f3ed051a0 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -244,8 +244,7 @@ s390_subchannel_remove_chpid(struct device *dev, void *data) | |||
244 | 244 | ||
245 | if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) && | 245 | if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) && |
246 | (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) && | 246 | (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) && |
247 | (sch->schib.pmcw.lpum == mask) && | 247 | (sch->schib.pmcw.lpum == mask)) { |
248 | (sch->vpm == 0)) { | ||
249 | int cc; | 248 | int cc; |
250 | 249 | ||
251 | cc = cio_clear(sch); | 250 | cc = cio_clear(sch); |
@@ -918,12 +917,13 @@ chp_measurement_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
918 | chp = to_channelpath(container_of(kobj, struct device, kobj)); | 917 | chp = to_channelpath(container_of(kobj, struct device, kobj)); |
919 | css = to_css(chp->dev.parent); | 918 | css = to_css(chp->dev.parent); |
920 | 919 | ||
921 | size = sizeof(struct cmg_chars); | 920 | size = sizeof(struct cmg_entry); |
922 | 921 | ||
923 | /* Only allow single reads. */ | 922 | /* Only allow single reads. */ |
924 | if (off || count < size) | 923 | if (off || count < size) |
925 | return 0; | 924 | return 0; |
926 | chp_measurement_copy_block((struct cmg_entry *)buf, css, chp->id); | 925 | chp_measurement_copy_block((struct cmg_entry *)buf, css, chp->id); |
926 | count = size; | ||
927 | return count; | 927 | return count; |
928 | } | 928 | } |
929 | 929 | ||
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 07ef3f640f4a..1c3e8e9012b0 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c | |||
@@ -3,9 +3,10 @@ | |||
3 | * | 3 | * |
4 | * Linux on zSeries Channel Measurement Facility support | 4 | * Linux on zSeries Channel Measurement Facility support |
5 | * | 5 | * |
6 | * Copyright 2000,2003 IBM Corporation | 6 | * Copyright 2000,2006 IBM Corporation |
7 | * | 7 | * |
8 | * Author: Arnd Bergmann <arndb@de.ibm.com> | 8 | * Authors: Arnd Bergmann <arndb@de.ibm.com> |
9 | * Cornelia Huck <cornelia.huck@de.ibm.com> | ||
9 | * | 10 | * |
10 | * original idea from Natarajan Krishnaswami <nkrishna@us.ibm.com> | 11 | * original idea from Natarajan Krishnaswami <nkrishna@us.ibm.com> |
11 | * | 12 | * |
@@ -96,9 +97,9 @@ module_param(format, bool, 0444); | |||
96 | /** | 97 | /** |
97 | * struct cmb_operations - functions to use depending on cmb_format | 98 | * struct cmb_operations - functions to use depending on cmb_format |
98 | * | 99 | * |
99 | * all these functions operate on a struct cmf_device. There is only | 100 | * Most of these functions operate on a struct ccw_device. There is only |
100 | * one instance of struct cmb_operations because all cmf_device | 101 | * one instance of struct cmb_operations because the format of the measurement |
101 | * objects are guaranteed to be of the same type. | 102 | * data is guaranteed to be the same for every ccw_device. |
102 | * | 103 | * |
103 | * @alloc: allocate memory for a channel measurement block, | 104 | * @alloc: allocate memory for a channel measurement block, |
104 | * either with the help of a special pool or with kmalloc | 105 | * either with the help of a special pool or with kmalloc |
@@ -107,6 +108,7 @@ module_param(format, bool, 0444); | |||
107 | * @readall: read a measurement block in a common format | 108 | * @readall: read a measurement block in a common format |
108 | * @reset: clear the data in the associated measurement block and | 109 | * @reset: clear the data in the associated measurement block and |
109 | * reset its time stamp | 110 | * reset its time stamp |
111 | * @align: align an allocated block so that the hardware can use it | ||
110 | */ | 112 | */ |
111 | struct cmb_operations { | 113 | struct cmb_operations { |
112 | int (*alloc) (struct ccw_device*); | 114 | int (*alloc) (struct ccw_device*); |
@@ -115,11 +117,19 @@ struct cmb_operations { | |||
115 | u64 (*read) (struct ccw_device*, int); | 117 | u64 (*read) (struct ccw_device*, int); |
116 | int (*readall)(struct ccw_device*, struct cmbdata *); | 118 | int (*readall)(struct ccw_device*, struct cmbdata *); |
117 | void (*reset) (struct ccw_device*); | 119 | void (*reset) (struct ccw_device*); |
120 | void * (*align) (void *); | ||
118 | 121 | ||
119 | struct attribute_group *attr_group; | 122 | struct attribute_group *attr_group; |
120 | }; | 123 | }; |
121 | static struct cmb_operations *cmbops; | 124 | static struct cmb_operations *cmbops; |
122 | 125 | ||
126 | struct cmb_data { | ||
127 | void *hw_block; /* Pointer to block updated by hardware */ | ||
128 | void *last_block; /* Last changed block copied from hardware block */ | ||
129 | int size; /* Size of hw_block and last_block */ | ||
130 | unsigned long long last_update; /* when last_block was updated */ | ||
131 | }; | ||
132 | |||
123 | /* our user interface is designed in terms of nanoseconds, | 133 | /* our user interface is designed in terms of nanoseconds, |
124 | * while the hardware measures total times in its own | 134 | * while the hardware measures total times in its own |
125 | * unit.*/ | 135 | * unit.*/ |
@@ -226,63 +236,229 @@ struct set_schib_struct { | |||
226 | unsigned long address; | 236 | unsigned long address; |
227 | wait_queue_head_t wait; | 237 | wait_queue_head_t wait; |
228 | int ret; | 238 | int ret; |
239 | struct kref kref; | ||
229 | }; | 240 | }; |
230 | 241 | ||
242 | static void cmf_set_schib_release(struct kref *kref) | ||
243 | { | ||
244 | struct set_schib_struct *set_data; | ||
245 | |||
246 | set_data = container_of(kref, struct set_schib_struct, kref); | ||
247 | kfree(set_data); | ||
248 | } | ||
249 | |||
250 | #define CMF_PENDING 1 | ||
251 | |||
231 | static int set_schib_wait(struct ccw_device *cdev, u32 mme, | 252 | static int set_schib_wait(struct ccw_device *cdev, u32 mme, |
232 | int mbfc, unsigned long address) | 253 | int mbfc, unsigned long address) |
233 | { | 254 | { |
234 | struct set_schib_struct s = { | 255 | struct set_schib_struct *set_data; |
235 | .mme = mme, | 256 | int ret; |
236 | .mbfc = mbfc, | ||
237 | .address = address, | ||
238 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s.wait), | ||
239 | }; | ||
240 | 257 | ||
241 | spin_lock_irq(cdev->ccwlock); | 258 | spin_lock_irq(cdev->ccwlock); |
242 | s.ret = set_schib(cdev, mme, mbfc, address); | 259 | if (!cdev->private->cmb) { |
243 | if (s.ret != -EBUSY) { | 260 | ret = -ENODEV; |
244 | goto out_nowait; | 261 | goto out; |
245 | } | 262 | } |
263 | set_data = kzalloc(sizeof(struct set_schib_struct), GFP_ATOMIC); | ||
264 | if (!set_data) { | ||
265 | ret = -ENOMEM; | ||
266 | goto out; | ||
267 | } | ||
268 | init_waitqueue_head(&set_data->wait); | ||
269 | kref_init(&set_data->kref); | ||
270 | set_data->mme = mme; | ||
271 | set_data->mbfc = mbfc; | ||
272 | set_data->address = address; | ||
273 | |||
274 | ret = set_schib(cdev, mme, mbfc, address); | ||
275 | if (ret != -EBUSY) | ||
276 | goto out_put; | ||
246 | 277 | ||
247 | if (cdev->private->state != DEV_STATE_ONLINE) { | 278 | if (cdev->private->state != DEV_STATE_ONLINE) { |
248 | s.ret = -EBUSY; | ||
249 | /* if the device is not online, don't even try again */ | 279 | /* if the device is not online, don't even try again */ |
250 | goto out_nowait; | 280 | ret = -EBUSY; |
281 | goto out_put; | ||
251 | } | 282 | } |
283 | |||
252 | cdev->private->state = DEV_STATE_CMFCHANGE; | 284 | cdev->private->state = DEV_STATE_CMFCHANGE; |
253 | cdev->private->cmb_wait = &s; | 285 | set_data->ret = CMF_PENDING; |
254 | s.ret = 1; | 286 | cdev->private->cmb_wait = set_data; |
255 | 287 | ||
256 | spin_unlock_irq(cdev->ccwlock); | 288 | spin_unlock_irq(cdev->ccwlock); |
257 | if (wait_event_interruptible(s.wait, s.ret != 1)) { | 289 | if (wait_event_interruptible(set_data->wait, |
290 | set_data->ret != CMF_PENDING)) { | ||
258 | spin_lock_irq(cdev->ccwlock); | 291 | spin_lock_irq(cdev->ccwlock); |
259 | if (s.ret == 1) { | 292 | if (set_data->ret == CMF_PENDING) { |
260 | s.ret = -ERESTARTSYS; | 293 | set_data->ret = -ERESTARTSYS; |
261 | cdev->private->cmb_wait = 0; | ||
262 | if (cdev->private->state == DEV_STATE_CMFCHANGE) | 294 | if (cdev->private->state == DEV_STATE_CMFCHANGE) |
263 | cdev->private->state = DEV_STATE_ONLINE; | 295 | cdev->private->state = DEV_STATE_ONLINE; |
264 | } | 296 | } |
265 | spin_unlock_irq(cdev->ccwlock); | 297 | spin_unlock_irq(cdev->ccwlock); |
266 | } | 298 | } |
267 | return s.ret; | 299 | spin_lock_irq(cdev->ccwlock); |
268 | 300 | cdev->private->cmb_wait = NULL; | |
269 | out_nowait: | 301 | ret = set_data->ret; |
302 | out_put: | ||
303 | kref_put(&set_data->kref, cmf_set_schib_release); | ||
304 | out: | ||
270 | spin_unlock_irq(cdev->ccwlock); | 305 | spin_unlock_irq(cdev->ccwlock); |
271 | return s.ret; | 306 | return ret; |
272 | } | 307 | } |
273 | 308 | ||
274 | void retry_set_schib(struct ccw_device *cdev) | 309 | void retry_set_schib(struct ccw_device *cdev) |
275 | { | 310 | { |
276 | struct set_schib_struct *s; | 311 | struct set_schib_struct *set_data; |
312 | |||
313 | set_data = cdev->private->cmb_wait; | ||
314 | if (!set_data) { | ||
315 | WARN_ON(1); | ||
316 | return; | ||
317 | } | ||
318 | kref_get(&set_data->kref); | ||
319 | set_data->ret = set_schib(cdev, set_data->mme, set_data->mbfc, | ||
320 | set_data->address); | ||
321 | wake_up(&set_data->wait); | ||
322 | kref_put(&set_data->kref, cmf_set_schib_release); | ||
323 | } | ||
324 | |||
325 | static int cmf_copy_block(struct ccw_device *cdev) | ||
326 | { | ||
327 | struct subchannel *sch; | ||
328 | void *reference_buf; | ||
329 | void *hw_block; | ||
330 | struct cmb_data *cmb_data; | ||
331 | |||
332 | sch = to_subchannel(cdev->dev.parent); | ||
333 | |||
334 | if (stsch(sch->schid, &sch->schib)) | ||
335 | return -ENODEV; | ||
336 | |||
337 | if (sch->schib.scsw.fctl & SCSW_FCTL_START_FUNC) { | ||
338 | /* Don't copy if a start function is in progress. */ | ||
339 | if ((!sch->schib.scsw.actl & SCSW_ACTL_SUSPENDED) && | ||
340 | (sch->schib.scsw.actl & | ||
341 | (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT)) && | ||
342 | (!sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) | ||
343 | return -EBUSY; | ||
344 | } | ||
345 | cmb_data = cdev->private->cmb; | ||
346 | hw_block = cmbops->align(cmb_data->hw_block); | ||
347 | if (!memcmp(cmb_data->last_block, hw_block, cmb_data->size)) | ||
348 | /* No need to copy. */ | ||
349 | return 0; | ||
350 | reference_buf = kzalloc(cmb_data->size, GFP_ATOMIC); | ||
351 | if (!reference_buf) | ||
352 | return -ENOMEM; | ||
353 | /* Ensure consistency of block copied from hardware. */ | ||
354 | do { | ||
355 | memcpy(cmb_data->last_block, hw_block, cmb_data->size); | ||
356 | memcpy(reference_buf, hw_block, cmb_data->size); | ||
357 | } while (memcmp(cmb_data->last_block, reference_buf, cmb_data->size)); | ||
358 | cmb_data->last_update = get_clock(); | ||
359 | kfree(reference_buf); | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | struct copy_block_struct { | ||
364 | wait_queue_head_t wait; | ||
365 | int ret; | ||
366 | struct kref kref; | ||
367 | }; | ||
368 | |||
369 | static void cmf_copy_block_release(struct kref *kref) | ||
370 | { | ||
371 | struct copy_block_struct *copy_block; | ||
372 | |||
373 | copy_block = container_of(kref, struct copy_block_struct, kref); | ||
374 | kfree(copy_block); | ||
375 | } | ||
376 | |||
377 | static int cmf_cmb_copy_wait(struct ccw_device *cdev) | ||
378 | { | ||
379 | struct copy_block_struct *copy_block; | ||
380 | int ret; | ||
381 | unsigned long flags; | ||
382 | |||
383 | spin_lock_irqsave(cdev->ccwlock, flags); | ||
384 | if (!cdev->private->cmb) { | ||
385 | ret = -ENODEV; | ||
386 | goto out; | ||
387 | } | ||
388 | copy_block = kzalloc(sizeof(struct copy_block_struct), GFP_ATOMIC); | ||
389 | if (!copy_block) { | ||
390 | ret = -ENOMEM; | ||
391 | goto out; | ||
392 | } | ||
393 | init_waitqueue_head(©_block->wait); | ||
394 | kref_init(©_block->kref); | ||
395 | |||
396 | ret = cmf_copy_block(cdev); | ||
397 | if (ret != -EBUSY) | ||
398 | goto out_put; | ||
399 | |||
400 | if (cdev->private->state != DEV_STATE_ONLINE) { | ||
401 | ret = -EBUSY; | ||
402 | goto out_put; | ||
403 | } | ||
404 | |||
405 | cdev->private->state = DEV_STATE_CMFUPDATE; | ||
406 | copy_block->ret = CMF_PENDING; | ||
407 | cdev->private->cmb_wait = copy_block; | ||
408 | |||
409 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
410 | if (wait_event_interruptible(copy_block->wait, | ||
411 | copy_block->ret != CMF_PENDING)) { | ||
412 | spin_lock_irqsave(cdev->ccwlock, flags); | ||
413 | if (copy_block->ret == CMF_PENDING) { | ||
414 | copy_block->ret = -ERESTARTSYS; | ||
415 | if (cdev->private->state == DEV_STATE_CMFUPDATE) | ||
416 | cdev->private->state = DEV_STATE_ONLINE; | ||
417 | } | ||
418 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
419 | } | ||
420 | spin_lock_irqsave(cdev->ccwlock, flags); | ||
421 | cdev->private->cmb_wait = NULL; | ||
422 | ret = copy_block->ret; | ||
423 | out_put: | ||
424 | kref_put(©_block->kref, cmf_copy_block_release); | ||
425 | out: | ||
426 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
427 | return ret; | ||
428 | } | ||
429 | |||
430 | void cmf_retry_copy_block(struct ccw_device *cdev) | ||
431 | { | ||
432 | struct copy_block_struct *copy_block; | ||
277 | 433 | ||
278 | s = cdev->private->cmb_wait; | 434 | copy_block = cdev->private->cmb_wait; |
279 | cdev->private->cmb_wait = 0; | 435 | if (!copy_block) { |
280 | if (!s) { | ||
281 | WARN_ON(1); | 436 | WARN_ON(1); |
282 | return; | 437 | return; |
283 | } | 438 | } |
284 | s->ret = set_schib(cdev, s->mme, s->mbfc, s->address); | 439 | kref_get(©_block->kref); |
285 | wake_up(&s->wait); | 440 | copy_block->ret = cmf_copy_block(cdev); |
441 | wake_up(©_block->wait); | ||
442 | kref_put(©_block->kref, cmf_copy_block_release); | ||
443 | } | ||
444 | |||
445 | static void cmf_generic_reset(struct ccw_device *cdev) | ||
446 | { | ||
447 | struct cmb_data *cmb_data; | ||
448 | |||
449 | spin_lock_irq(cdev->ccwlock); | ||
450 | cmb_data = cdev->private->cmb; | ||
451 | if (cmb_data) { | ||
452 | memset(cmb_data->last_block, 0, cmb_data->size); | ||
453 | /* | ||
454 | * Need to reset hw block as well to make the hardware start | ||
455 | * from 0 again. | ||
456 | */ | ||
457 | memset(cmbops->align(cmb_data->hw_block), 0, cmb_data->size); | ||
458 | cmb_data->last_update = 0; | ||
459 | } | ||
460 | cdev->private->cmb_start_time = get_clock(); | ||
461 | spin_unlock_irq(cdev->ccwlock); | ||
286 | } | 462 | } |
287 | 463 | ||
288 | /** | 464 | /** |
@@ -343,8 +519,8 @@ struct cmb { | |||
343 | /* insert a single device into the cmb_area list | 519 | /* insert a single device into the cmb_area list |
344 | * called with cmb_area.lock held from alloc_cmb | 520 | * called with cmb_area.lock held from alloc_cmb |
345 | */ | 521 | */ |
346 | static inline int | 522 | static inline int alloc_cmb_single (struct ccw_device *cdev, |
347 | alloc_cmb_single (struct ccw_device *cdev) | 523 | struct cmb_data *cmb_data) |
348 | { | 524 | { |
349 | struct cmb *cmb; | 525 | struct cmb *cmb; |
350 | struct ccw_device_private *node; | 526 | struct ccw_device_private *node; |
@@ -358,10 +534,12 @@ alloc_cmb_single (struct ccw_device *cdev) | |||
358 | 534 | ||
359 | /* find first unused cmb in cmb_area.mem. | 535 | /* find first unused cmb in cmb_area.mem. |
360 | * this is a little tricky: cmb_area.list | 536 | * this is a little tricky: cmb_area.list |
361 | * remains sorted by ->cmb pointers */ | 537 | * remains sorted by ->cmb->hw_data pointers */ |
362 | cmb = cmb_area.mem; | 538 | cmb = cmb_area.mem; |
363 | list_for_each_entry(node, &cmb_area.list, cmb_list) { | 539 | list_for_each_entry(node, &cmb_area.list, cmb_list) { |
364 | if ((struct cmb*)node->cmb > cmb) | 540 | struct cmb_data *data; |
541 | data = node->cmb; | ||
542 | if ((struct cmb*)data->hw_block > cmb) | ||
365 | break; | 543 | break; |
366 | cmb++; | 544 | cmb++; |
367 | } | 545 | } |
@@ -372,7 +550,8 @@ alloc_cmb_single (struct ccw_device *cdev) | |||
372 | 550 | ||
373 | /* insert new cmb */ | 551 | /* insert new cmb */ |
374 | list_add_tail(&cdev->private->cmb_list, &node->cmb_list); | 552 | list_add_tail(&cdev->private->cmb_list, &node->cmb_list); |
375 | cdev->private->cmb = cmb; | 553 | cmb_data->hw_block = cmb; |
554 | cdev->private->cmb = cmb_data; | ||
376 | ret = 0; | 555 | ret = 0; |
377 | out: | 556 | out: |
378 | spin_unlock_irq(cdev->ccwlock); | 557 | spin_unlock_irq(cdev->ccwlock); |
@@ -385,7 +564,19 @@ alloc_cmb (struct ccw_device *cdev) | |||
385 | int ret; | 564 | int ret; |
386 | struct cmb *mem; | 565 | struct cmb *mem; |
387 | ssize_t size; | 566 | ssize_t size; |
567 | struct cmb_data *cmb_data; | ||
568 | |||
569 | /* Allocate private cmb_data. */ | ||
570 | cmb_data = kzalloc(sizeof(struct cmb_data), GFP_KERNEL); | ||
571 | if (!cmb_data) | ||
572 | return -ENOMEM; | ||
388 | 573 | ||
574 | cmb_data->last_block = kzalloc(sizeof(struct cmb), GFP_KERNEL); | ||
575 | if (!cmb_data->last_block) { | ||
576 | kfree(cmb_data); | ||
577 | return -ENOMEM; | ||
578 | } | ||
579 | cmb_data->size = sizeof(struct cmb); | ||
389 | spin_lock(&cmb_area.lock); | 580 | spin_lock(&cmb_area.lock); |
390 | 581 | ||
391 | if (!cmb_area.mem) { | 582 | if (!cmb_area.mem) { |
@@ -414,29 +605,36 @@ alloc_cmb (struct ccw_device *cdev) | |||
414 | } | 605 | } |
415 | 606 | ||
416 | /* do the actual allocation */ | 607 | /* do the actual allocation */ |
417 | ret = alloc_cmb_single(cdev); | 608 | ret = alloc_cmb_single(cdev, cmb_data); |
418 | out: | 609 | out: |
419 | spin_unlock(&cmb_area.lock); | 610 | spin_unlock(&cmb_area.lock); |
420 | 611 | if (ret) { | |
612 | kfree(cmb_data->last_block); | ||
613 | kfree(cmb_data); | ||
614 | } | ||
421 | return ret; | 615 | return ret; |
422 | } | 616 | } |
423 | 617 | ||
424 | static void | 618 | static void free_cmb(struct ccw_device *cdev) |
425 | free_cmb(struct ccw_device *cdev) | ||
426 | { | 619 | { |
427 | struct ccw_device_private *priv; | 620 | struct ccw_device_private *priv; |
428 | 621 | struct cmb_data *cmb_data; | |
429 | priv = cdev->private; | ||
430 | 622 | ||
431 | spin_lock(&cmb_area.lock); | 623 | spin_lock(&cmb_area.lock); |
432 | spin_lock_irq(cdev->ccwlock); | 624 | spin_lock_irq(cdev->ccwlock); |
433 | 625 | ||
626 | priv = cdev->private; | ||
627 | |||
434 | if (list_empty(&priv->cmb_list)) { | 628 | if (list_empty(&priv->cmb_list)) { |
435 | /* already freed */ | 629 | /* already freed */ |
436 | goto out; | 630 | goto out; |
437 | } | 631 | } |
438 | 632 | ||
633 | cmb_data = priv->cmb; | ||
439 | priv->cmb = NULL; | 634 | priv->cmb = NULL; |
635 | if (cmb_data) | ||
636 | kfree(cmb_data->last_block); | ||
637 | kfree(cmb_data); | ||
440 | list_del_init(&priv->cmb_list); | 638 | list_del_init(&priv->cmb_list); |
441 | 639 | ||
442 | if (list_empty(&cmb_area.list)) { | 640 | if (list_empty(&cmb_area.list)) { |
@@ -451,83 +649,97 @@ out: | |||
451 | spin_unlock(&cmb_area.lock); | 649 | spin_unlock(&cmb_area.lock); |
452 | } | 650 | } |
453 | 651 | ||
454 | static int | 652 | static int set_cmb(struct ccw_device *cdev, u32 mme) |
455 | set_cmb(struct ccw_device *cdev, u32 mme) | ||
456 | { | 653 | { |
457 | u16 offset; | 654 | u16 offset; |
655 | struct cmb_data *cmb_data; | ||
656 | unsigned long flags; | ||
458 | 657 | ||
459 | if (!cdev->private->cmb) | 658 | spin_lock_irqsave(cdev->ccwlock, flags); |
659 | if (!cdev->private->cmb) { | ||
660 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
460 | return -EINVAL; | 661 | return -EINVAL; |
461 | 662 | } | |
462 | offset = mme ? (struct cmb *)cdev->private->cmb - cmb_area.mem : 0; | 663 | cmb_data = cdev->private->cmb; |
664 | offset = mme ? (struct cmb *)cmb_data->hw_block - cmb_area.mem : 0; | ||
665 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
463 | 666 | ||
464 | return set_schib_wait(cdev, mme, 0, offset); | 667 | return set_schib_wait(cdev, mme, 0, offset); |
465 | } | 668 | } |
466 | 669 | ||
467 | static u64 | 670 | static u64 read_cmb (struct ccw_device *cdev, int index) |
468 | read_cmb (struct ccw_device *cdev, int index) | ||
469 | { | 671 | { |
470 | /* yes, we have to put it on the stack | 672 | struct cmb *cmb; |
471 | * because the cmb must only be accessed | ||
472 | * atomically, e.g. with mvc */ | ||
473 | struct cmb cmb; | ||
474 | unsigned long flags; | ||
475 | u32 val; | 673 | u32 val; |
674 | int ret; | ||
675 | unsigned long flags; | ||
676 | |||
677 | ret = cmf_cmb_copy_wait(cdev); | ||
678 | if (ret < 0) | ||
679 | return 0; | ||
476 | 680 | ||
477 | spin_lock_irqsave(cdev->ccwlock, flags); | 681 | spin_lock_irqsave(cdev->ccwlock, flags); |
478 | if (!cdev->private->cmb) { | 682 | if (!cdev->private->cmb) { |
479 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 683 | ret = 0; |
480 | return 0; | 684 | goto out; |
481 | } | 685 | } |
482 | 686 | cmb = ((struct cmb_data *)cdev->private->cmb)->last_block; | |
483 | cmb = *(struct cmb*)cdev->private->cmb; | ||
484 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
485 | 687 | ||
486 | switch (index) { | 688 | switch (index) { |
487 | case cmb_ssch_rsch_count: | 689 | case cmb_ssch_rsch_count: |
488 | return cmb.ssch_rsch_count; | 690 | ret = cmb->ssch_rsch_count; |
691 | goto out; | ||
489 | case cmb_sample_count: | 692 | case cmb_sample_count: |
490 | return cmb.sample_count; | 693 | ret = cmb->sample_count; |
694 | goto out; | ||
491 | case cmb_device_connect_time: | 695 | case cmb_device_connect_time: |
492 | val = cmb.device_connect_time; | 696 | val = cmb->device_connect_time; |
493 | break; | 697 | break; |
494 | case cmb_function_pending_time: | 698 | case cmb_function_pending_time: |
495 | val = cmb.function_pending_time; | 699 | val = cmb->function_pending_time; |
496 | break; | 700 | break; |
497 | case cmb_device_disconnect_time: | 701 | case cmb_device_disconnect_time: |
498 | val = cmb.device_disconnect_time; | 702 | val = cmb->device_disconnect_time; |
499 | break; | 703 | break; |
500 | case cmb_control_unit_queuing_time: | 704 | case cmb_control_unit_queuing_time: |
501 | val = cmb.control_unit_queuing_time; | 705 | val = cmb->control_unit_queuing_time; |
502 | break; | 706 | break; |
503 | case cmb_device_active_only_time: | 707 | case cmb_device_active_only_time: |
504 | val = cmb.device_active_only_time; | 708 | val = cmb->device_active_only_time; |
505 | break; | 709 | break; |
506 | default: | 710 | default: |
507 | return 0; | 711 | ret = 0; |
712 | goto out; | ||
508 | } | 713 | } |
509 | return time_to_avg_nsec(val, cmb.sample_count); | 714 | ret = time_to_avg_nsec(val, cmb->sample_count); |
715 | out: | ||
716 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
717 | return ret; | ||
510 | } | 718 | } |
511 | 719 | ||
512 | static int | 720 | static int readall_cmb (struct ccw_device *cdev, struct cmbdata *data) |
513 | readall_cmb (struct ccw_device *cdev, struct cmbdata *data) | ||
514 | { | 721 | { |
515 | /* yes, we have to put it on the stack | 722 | struct cmb *cmb; |
516 | * because the cmb must only be accessed | 723 | struct cmb_data *cmb_data; |
517 | * atomically, e.g. with mvc */ | ||
518 | struct cmb cmb; | ||
519 | unsigned long flags; | ||
520 | u64 time; | 724 | u64 time; |
725 | unsigned long flags; | ||
726 | int ret; | ||
521 | 727 | ||
728 | ret = cmf_cmb_copy_wait(cdev); | ||
729 | if (ret < 0) | ||
730 | return ret; | ||
522 | spin_lock_irqsave(cdev->ccwlock, flags); | 731 | spin_lock_irqsave(cdev->ccwlock, flags); |
523 | if (!cdev->private->cmb) { | 732 | cmb_data = cdev->private->cmb; |
524 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 733 | if (!cmb_data) { |
525 | return -ENODEV; | 734 | ret = -ENODEV; |
735 | goto out; | ||
526 | } | 736 | } |
527 | 737 | if (cmb_data->last_update == 0) { | |
528 | cmb = *(struct cmb*)cdev->private->cmb; | 738 | ret = -EAGAIN; |
529 | time = get_clock() - cdev->private->cmb_start_time; | 739 | goto out; |
530 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 740 | } |
741 | cmb = cmb_data->last_block; | ||
742 | time = cmb_data->last_update - cdev->private->cmb_start_time; | ||
531 | 743 | ||
532 | memset(data, 0, sizeof(struct cmbdata)); | 744 | memset(data, 0, sizeof(struct cmbdata)); |
533 | 745 | ||
@@ -538,31 +750,32 @@ readall_cmb (struct ccw_device *cdev, struct cmbdata *data) | |||
538 | data->elapsed_time = (time * 1000) >> 12; | 750 | data->elapsed_time = (time * 1000) >> 12; |
539 | 751 | ||
540 | /* copy data to new structure */ | 752 | /* copy data to new structure */ |
541 | data->ssch_rsch_count = cmb.ssch_rsch_count; | 753 | data->ssch_rsch_count = cmb->ssch_rsch_count; |
542 | data->sample_count = cmb.sample_count; | 754 | data->sample_count = cmb->sample_count; |
543 | 755 | ||
544 | /* time fields are converted to nanoseconds while copying */ | 756 | /* time fields are converted to nanoseconds while copying */ |
545 | data->device_connect_time = time_to_nsec(cmb.device_connect_time); | 757 | data->device_connect_time = time_to_nsec(cmb->device_connect_time); |
546 | data->function_pending_time = time_to_nsec(cmb.function_pending_time); | 758 | data->function_pending_time = time_to_nsec(cmb->function_pending_time); |
547 | data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time); | 759 | data->device_disconnect_time = |
760 | time_to_nsec(cmb->device_disconnect_time); | ||
548 | data->control_unit_queuing_time | 761 | data->control_unit_queuing_time |
549 | = time_to_nsec(cmb.control_unit_queuing_time); | 762 | = time_to_nsec(cmb->control_unit_queuing_time); |
550 | data->device_active_only_time | 763 | data->device_active_only_time |
551 | = time_to_nsec(cmb.device_active_only_time); | 764 | = time_to_nsec(cmb->device_active_only_time); |
765 | ret = 0; | ||
766 | out: | ||
767 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
768 | return ret; | ||
769 | } | ||
552 | 770 | ||
553 | return 0; | 771 | static void reset_cmb(struct ccw_device *cdev) |
772 | { | ||
773 | cmf_generic_reset(cdev); | ||
554 | } | 774 | } |
555 | 775 | ||
556 | static void | 776 | static void * align_cmb(void *area) |
557 | reset_cmb(struct ccw_device *cdev) | ||
558 | { | 777 | { |
559 | struct cmb *cmb; | 778 | return area; |
560 | spin_lock_irq(cdev->ccwlock); | ||
561 | cmb = cdev->private->cmb; | ||
562 | if (cmb) | ||
563 | memset (cmb, 0, sizeof (*cmb)); | ||
564 | cdev->private->cmb_start_time = get_clock(); | ||
565 | spin_unlock_irq(cdev->ccwlock); | ||
566 | } | 779 | } |
567 | 780 | ||
568 | static struct attribute_group cmf_attr_group; | 781 | static struct attribute_group cmf_attr_group; |
@@ -574,6 +787,7 @@ static struct cmb_operations cmbops_basic = { | |||
574 | .read = read_cmb, | 787 | .read = read_cmb, |
575 | .readall = readall_cmb, | 788 | .readall = readall_cmb, |
576 | .reset = reset_cmb, | 789 | .reset = reset_cmb, |
790 | .align = align_cmb, | ||
577 | .attr_group = &cmf_attr_group, | 791 | .attr_group = &cmf_attr_group, |
578 | }; | 792 | }; |
579 | 793 | ||
@@ -610,22 +824,34 @@ static inline struct cmbe* cmbe_align(struct cmbe *c) | |||
610 | return (struct cmbe*)addr; | 824 | return (struct cmbe*)addr; |
611 | } | 825 | } |
612 | 826 | ||
613 | static int | 827 | static int alloc_cmbe (struct ccw_device *cdev) |
614 | alloc_cmbe (struct ccw_device *cdev) | ||
615 | { | 828 | { |
616 | struct cmbe *cmbe; | 829 | struct cmbe *cmbe; |
617 | cmbe = kmalloc (sizeof (*cmbe) * 2, GFP_KERNEL); | 830 | struct cmb_data *cmb_data; |
831 | int ret; | ||
832 | |||
833 | cmbe = kzalloc (sizeof (*cmbe) * 2, GFP_KERNEL); | ||
618 | if (!cmbe) | 834 | if (!cmbe) |
619 | return -ENOMEM; | 835 | return -ENOMEM; |
620 | 836 | cmb_data = kzalloc(sizeof(struct cmb_data), GFP_KERNEL); | |
837 | if (!cmb_data) { | ||
838 | ret = -ENOMEM; | ||
839 | goto out_free; | ||
840 | } | ||
841 | cmb_data->last_block = kzalloc(sizeof(struct cmbe), GFP_KERNEL); | ||
842 | if (!cmb_data->last_block) { | ||
843 | ret = -ENOMEM; | ||
844 | goto out_free; | ||
845 | } | ||
846 | cmb_data->size = sizeof(struct cmbe); | ||
621 | spin_lock_irq(cdev->ccwlock); | 847 | spin_lock_irq(cdev->ccwlock); |
622 | if (cdev->private->cmb) { | 848 | if (cdev->private->cmb) { |
623 | kfree(cmbe); | ||
624 | spin_unlock_irq(cdev->ccwlock); | 849 | spin_unlock_irq(cdev->ccwlock); |
625 | return -EBUSY; | 850 | ret = -EBUSY; |
851 | goto out_free; | ||
626 | } | 852 | } |
627 | 853 | cmb_data->hw_block = cmbe; | |
628 | cdev->private->cmb = cmbe; | 854 | cdev->private->cmb = cmb_data; |
629 | spin_unlock_irq(cdev->ccwlock); | 855 | spin_unlock_irq(cdev->ccwlock); |
630 | 856 | ||
631 | /* activate global measurement if this is the first channel */ | 857 | /* activate global measurement if this is the first channel */ |
@@ -636,14 +862,24 @@ alloc_cmbe (struct ccw_device *cdev) | |||
636 | spin_unlock(&cmb_area.lock); | 862 | spin_unlock(&cmb_area.lock); |
637 | 863 | ||
638 | return 0; | 864 | return 0; |
865 | out_free: | ||
866 | if (cmb_data) | ||
867 | kfree(cmb_data->last_block); | ||
868 | kfree(cmb_data); | ||
869 | kfree(cmbe); | ||
870 | return ret; | ||
639 | } | 871 | } |
640 | 872 | ||
641 | static void | 873 | static void free_cmbe (struct ccw_device *cdev) |
642 | free_cmbe (struct ccw_device *cdev) | ||
643 | { | 874 | { |
875 | struct cmb_data *cmb_data; | ||
876 | |||
644 | spin_lock_irq(cdev->ccwlock); | 877 | spin_lock_irq(cdev->ccwlock); |
645 | kfree(cdev->private->cmb); | 878 | cmb_data = cdev->private->cmb; |
646 | cdev->private->cmb = NULL; | 879 | cdev->private->cmb = NULL; |
880 | if (cmb_data) | ||
881 | kfree(cmb_data->last_block); | ||
882 | kfree(cmb_data); | ||
647 | spin_unlock_irq(cdev->ccwlock); | 883 | spin_unlock_irq(cdev->ccwlock); |
648 | 884 | ||
649 | /* deactivate global measurement if this is the last channel */ | 885 | /* deactivate global measurement if this is the last channel */ |
@@ -654,89 +890,105 @@ free_cmbe (struct ccw_device *cdev) | |||
654 | spin_unlock(&cmb_area.lock); | 890 | spin_unlock(&cmb_area.lock); |
655 | } | 891 | } |
656 | 892 | ||
657 | static int | 893 | static int set_cmbe(struct ccw_device *cdev, u32 mme) |
658 | set_cmbe(struct ccw_device *cdev, u32 mme) | ||
659 | { | 894 | { |
660 | unsigned long mba; | 895 | unsigned long mba; |
896 | struct cmb_data *cmb_data; | ||
897 | unsigned long flags; | ||
661 | 898 | ||
662 | if (!cdev->private->cmb) | 899 | spin_lock_irqsave(cdev->ccwlock, flags); |
900 | if (!cdev->private->cmb) { | ||
901 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
663 | return -EINVAL; | 902 | return -EINVAL; |
664 | mba = mme ? (unsigned long) cmbe_align(cdev->private->cmb) : 0; | 903 | } |
904 | cmb_data = cdev->private->cmb; | ||
905 | mba = mme ? (unsigned long) cmbe_align(cmb_data->hw_block) : 0; | ||
906 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
665 | 907 | ||
666 | return set_schib_wait(cdev, mme, 1, mba); | 908 | return set_schib_wait(cdev, mme, 1, mba); |
667 | } | 909 | } |
668 | 910 | ||
669 | 911 | ||
670 | u64 | 912 | static u64 read_cmbe (struct ccw_device *cdev, int index) |
671 | read_cmbe (struct ccw_device *cdev, int index) | ||
672 | { | 913 | { |
673 | /* yes, we have to put it on the stack | 914 | struct cmbe *cmb; |
674 | * because the cmb must only be accessed | 915 | struct cmb_data *cmb_data; |
675 | * atomically, e.g. with mvc */ | ||
676 | struct cmbe cmb; | ||
677 | unsigned long flags; | ||
678 | u32 val; | 916 | u32 val; |
917 | int ret; | ||
918 | unsigned long flags; | ||
679 | 919 | ||
680 | spin_lock_irqsave(cdev->ccwlock, flags); | 920 | ret = cmf_cmb_copy_wait(cdev); |
681 | if (!cdev->private->cmb) { | 921 | if (ret < 0) |
682 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
683 | return 0; | 922 | return 0; |
684 | } | ||
685 | 923 | ||
686 | cmb = *cmbe_align(cdev->private->cmb); | 924 | spin_lock_irqsave(cdev->ccwlock, flags); |
687 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 925 | cmb_data = cdev->private->cmb; |
926 | if (!cmb_data) { | ||
927 | ret = 0; | ||
928 | goto out; | ||
929 | } | ||
930 | cmb = cmb_data->last_block; | ||
688 | 931 | ||
689 | switch (index) { | 932 | switch (index) { |
690 | case cmb_ssch_rsch_count: | 933 | case cmb_ssch_rsch_count: |
691 | return cmb.ssch_rsch_count; | 934 | ret = cmb->ssch_rsch_count; |
935 | goto out; | ||
692 | case cmb_sample_count: | 936 | case cmb_sample_count: |
693 | return cmb.sample_count; | 937 | ret = cmb->sample_count; |
938 | goto out; | ||
694 | case cmb_device_connect_time: | 939 | case cmb_device_connect_time: |
695 | val = cmb.device_connect_time; | 940 | val = cmb->device_connect_time; |
696 | break; | 941 | break; |
697 | case cmb_function_pending_time: | 942 | case cmb_function_pending_time: |
698 | val = cmb.function_pending_time; | 943 | val = cmb->function_pending_time; |
699 | break; | 944 | break; |
700 | case cmb_device_disconnect_time: | 945 | case cmb_device_disconnect_time: |
701 | val = cmb.device_disconnect_time; | 946 | val = cmb->device_disconnect_time; |
702 | break; | 947 | break; |
703 | case cmb_control_unit_queuing_time: | 948 | case cmb_control_unit_queuing_time: |
704 | val = cmb.control_unit_queuing_time; | 949 | val = cmb->control_unit_queuing_time; |
705 | break; | 950 | break; |
706 | case cmb_device_active_only_time: | 951 | case cmb_device_active_only_time: |
707 | val = cmb.device_active_only_time; | 952 | val = cmb->device_active_only_time; |
708 | break; | 953 | break; |
709 | case cmb_device_busy_time: | 954 | case cmb_device_busy_time: |
710 | val = cmb.device_busy_time; | 955 | val = cmb->device_busy_time; |
711 | break; | 956 | break; |
712 | case cmb_initial_command_response_time: | 957 | case cmb_initial_command_response_time: |
713 | val = cmb.initial_command_response_time; | 958 | val = cmb->initial_command_response_time; |
714 | break; | 959 | break; |
715 | default: | 960 | default: |
716 | return 0; | 961 | ret = 0; |
962 | goto out; | ||
717 | } | 963 | } |
718 | return time_to_avg_nsec(val, cmb.sample_count); | 964 | ret = time_to_avg_nsec(val, cmb->sample_count); |
965 | out: | ||
966 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
967 | return ret; | ||
719 | } | 968 | } |
720 | 969 | ||
721 | static int | 970 | static int readall_cmbe (struct ccw_device *cdev, struct cmbdata *data) |
722 | readall_cmbe (struct ccw_device *cdev, struct cmbdata *data) | ||
723 | { | 971 | { |
724 | /* yes, we have to put it on the stack | 972 | struct cmbe *cmb; |
725 | * because the cmb must only be accessed | 973 | struct cmb_data *cmb_data; |
726 | * atomically, e.g. with mvc */ | ||
727 | struct cmbe cmb; | ||
728 | unsigned long flags; | ||
729 | u64 time; | 974 | u64 time; |
975 | unsigned long flags; | ||
976 | int ret; | ||
730 | 977 | ||
978 | ret = cmf_cmb_copy_wait(cdev); | ||
979 | if (ret < 0) | ||
980 | return ret; | ||
731 | spin_lock_irqsave(cdev->ccwlock, flags); | 981 | spin_lock_irqsave(cdev->ccwlock, flags); |
732 | if (!cdev->private->cmb) { | 982 | cmb_data = cdev->private->cmb; |
733 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 983 | if (!cmb_data) { |
734 | return -ENODEV; | 984 | ret = -ENODEV; |
985 | goto out; | ||
735 | } | 986 | } |
736 | 987 | if (cmb_data->last_update == 0) { | |
737 | cmb = *cmbe_align(cdev->private->cmb); | 988 | ret = -EAGAIN; |
738 | time = get_clock() - cdev->private->cmb_start_time; | 989 | goto out; |
739 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 990 | } |
991 | time = cmb_data->last_update - cdev->private->cmb_start_time; | ||
740 | 992 | ||
741 | memset (data, 0, sizeof(struct cmbdata)); | 993 | memset (data, 0, sizeof(struct cmbdata)); |
742 | 994 | ||
@@ -746,35 +998,38 @@ readall_cmbe (struct ccw_device *cdev, struct cmbdata *data) | |||
746 | /* conver to nanoseconds */ | 998 | /* conver to nanoseconds */ |
747 | data->elapsed_time = (time * 1000) >> 12; | 999 | data->elapsed_time = (time * 1000) >> 12; |
748 | 1000 | ||
1001 | cmb = cmb_data->last_block; | ||
749 | /* copy data to new structure */ | 1002 | /* copy data to new structure */ |
750 | data->ssch_rsch_count = cmb.ssch_rsch_count; | 1003 | data->ssch_rsch_count = cmb->ssch_rsch_count; |
751 | data->sample_count = cmb.sample_count; | 1004 | data->sample_count = cmb->sample_count; |
752 | 1005 | ||
753 | /* time fields are converted to nanoseconds while copying */ | 1006 | /* time fields are converted to nanoseconds while copying */ |
754 | data->device_connect_time = time_to_nsec(cmb.device_connect_time); | 1007 | data->device_connect_time = time_to_nsec(cmb->device_connect_time); |
755 | data->function_pending_time = time_to_nsec(cmb.function_pending_time); | 1008 | data->function_pending_time = time_to_nsec(cmb->function_pending_time); |
756 | data->device_disconnect_time = time_to_nsec(cmb.device_disconnect_time); | 1009 | data->device_disconnect_time = |
1010 | time_to_nsec(cmb->device_disconnect_time); | ||
757 | data->control_unit_queuing_time | 1011 | data->control_unit_queuing_time |
758 | = time_to_nsec(cmb.control_unit_queuing_time); | 1012 | = time_to_nsec(cmb->control_unit_queuing_time); |
759 | data->device_active_only_time | 1013 | data->device_active_only_time |
760 | = time_to_nsec(cmb.device_active_only_time); | 1014 | = time_to_nsec(cmb->device_active_only_time); |
761 | data->device_busy_time = time_to_nsec(cmb.device_busy_time); | 1015 | data->device_busy_time = time_to_nsec(cmb->device_busy_time); |
762 | data->initial_command_response_time | 1016 | data->initial_command_response_time |
763 | = time_to_nsec(cmb.initial_command_response_time); | 1017 | = time_to_nsec(cmb->initial_command_response_time); |
764 | 1018 | ||
765 | return 0; | 1019 | ret = 0; |
1020 | out: | ||
1021 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
1022 | return ret; | ||
766 | } | 1023 | } |
767 | 1024 | ||
768 | static void | 1025 | static void reset_cmbe(struct ccw_device *cdev) |
769 | reset_cmbe(struct ccw_device *cdev) | ||
770 | { | 1026 | { |
771 | struct cmbe *cmb; | 1027 | cmf_generic_reset(cdev); |
772 | spin_lock_irq(cdev->ccwlock); | 1028 | } |
773 | cmb = cmbe_align(cdev->private->cmb); | 1029 | |
774 | if (cmb) | 1030 | static void * align_cmbe(void *area) |
775 | memset (cmb, 0, sizeof (*cmb)); | 1031 | { |
776 | cdev->private->cmb_start_time = get_clock(); | 1032 | return cmbe_align(area); |
777 | spin_unlock_irq(cdev->ccwlock); | ||
778 | } | 1033 | } |
779 | 1034 | ||
780 | static struct attribute_group cmf_attr_group_ext; | 1035 | static struct attribute_group cmf_attr_group_ext; |
@@ -786,6 +1041,7 @@ static struct cmb_operations cmbops_extended = { | |||
786 | .read = read_cmbe, | 1041 | .read = read_cmbe, |
787 | .readall = readall_cmbe, | 1042 | .readall = readall_cmbe, |
788 | .reset = reset_cmbe, | 1043 | .reset = reset_cmbe, |
1044 | .align = align_cmbe, | ||
789 | .attr_group = &cmf_attr_group_ext, | 1045 | .attr_group = &cmf_attr_group_ext, |
790 | }; | 1046 | }; |
791 | 1047 | ||
@@ -803,14 +1059,19 @@ cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr, | |||
803 | struct ccw_device *cdev; | 1059 | struct ccw_device *cdev; |
804 | long interval; | 1060 | long interval; |
805 | unsigned long count; | 1061 | unsigned long count; |
1062 | struct cmb_data *cmb_data; | ||
806 | 1063 | ||
807 | cdev = to_ccwdev(dev); | 1064 | cdev = to_ccwdev(dev); |
808 | interval = get_clock() - cdev->private->cmb_start_time; | ||
809 | count = cmf_read(cdev, cmb_sample_count); | 1065 | count = cmf_read(cdev, cmb_sample_count); |
810 | if (count) | 1066 | spin_lock_irq(cdev->ccwlock); |
1067 | cmb_data = cdev->private->cmb; | ||
1068 | if (count) { | ||
1069 | interval = cmb_data->last_update - | ||
1070 | cdev->private->cmb_start_time; | ||
811 | interval /= count; | 1071 | interval /= count; |
812 | else | 1072 | } else |
813 | interval = -1; | 1073 | interval = -1; |
1074 | spin_unlock_irq(cdev->ccwlock); | ||
814 | return sprintf(buf, "%ld\n", interval); | 1075 | return sprintf(buf, "%ld\n", interval); |
815 | } | 1076 | } |
816 | 1077 | ||
@@ -823,7 +1084,10 @@ cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char | |||
823 | int ret; | 1084 | int ret; |
824 | 1085 | ||
825 | ret = cmf_readall(to_ccwdev(dev), &data); | 1086 | ret = cmf_readall(to_ccwdev(dev), &data); |
826 | if (ret) | 1087 | if (ret == -EAGAIN || ret == -ENODEV) |
1088 | /* No data (yet/currently) available to use for calculation. */ | ||
1089 | return sprintf(buf, "n/a\n"); | ||
1090 | else if (ret) | ||
827 | return ret; | 1091 | return ret; |
828 | 1092 | ||
829 | utilization = data.device_connect_time + | 1093 | utilization = data.device_connect_time + |
@@ -982,6 +1246,13 @@ cmf_readall(struct ccw_device *cdev, struct cmbdata *data) | |||
982 | return cmbops->readall(cdev, data); | 1246 | return cmbops->readall(cdev, data); |
983 | } | 1247 | } |
984 | 1248 | ||
1249 | /* Reenable cmf when a disconnected device becomes available again. */ | ||
1250 | int cmf_reenable(struct ccw_device *cdev) | ||
1251 | { | ||
1252 | cmbops->reset(cdev); | ||
1253 | return cmbops->set(cdev, 2); | ||
1254 | } | ||
1255 | |||
985 | static int __init | 1256 | static int __init |
986 | init_cmf(void) | 1257 | init_cmf(void) |
987 | { | 1258 | { |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 74ea8aac4b7d..1d3be80797f8 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -19,9 +19,11 @@ | |||
19 | #include "cio_debug.h" | 19 | #include "cio_debug.h" |
20 | #include "ioasm.h" | 20 | #include "ioasm.h" |
21 | #include "chsc.h" | 21 | #include "chsc.h" |
22 | #include "device.h" | ||
22 | 23 | ||
23 | int need_rescan = 0; | 24 | int need_rescan = 0; |
24 | int css_init_done = 0; | 25 | int css_init_done = 0; |
26 | static int need_reprobe = 0; | ||
25 | static int max_ssid = 0; | 27 | static int max_ssid = 0; |
26 | 28 | ||
27 | struct channel_subsystem *css[__MAX_CSSID + 1]; | 29 | struct channel_subsystem *css[__MAX_CSSID + 1]; |
@@ -339,6 +341,67 @@ typedef void (*workfunc)(void *); | |||
339 | DECLARE_WORK(slow_path_work, (workfunc)css_trigger_slow_path, NULL); | 341 | DECLARE_WORK(slow_path_work, (workfunc)css_trigger_slow_path, NULL); |
340 | struct workqueue_struct *slow_path_wq; | 342 | struct workqueue_struct *slow_path_wq; |
341 | 343 | ||
344 | /* Reprobe subchannel if unregistered. */ | ||
345 | static int reprobe_subchannel(struct subchannel_id schid, void *data) | ||
346 | { | ||
347 | struct subchannel *sch; | ||
348 | int ret; | ||
349 | |||
350 | CIO_DEBUG(KERN_INFO, 6, "cio: reprobe 0.%x.%04x\n", | ||
351 | schid.ssid, schid.sch_no); | ||
352 | if (need_reprobe) | ||
353 | return -EAGAIN; | ||
354 | |||
355 | sch = get_subchannel_by_schid(schid); | ||
356 | if (sch) { | ||
357 | /* Already known. */ | ||
358 | put_device(&sch->dev); | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | ret = css_probe_device(schid); | ||
363 | switch (ret) { | ||
364 | case 0: | ||
365 | break; | ||
366 | case -ENXIO: | ||
367 | case -ENOMEM: | ||
368 | /* These should abort looping */ | ||
369 | break; | ||
370 | default: | ||
371 | ret = 0; | ||
372 | } | ||
373 | |||
374 | return ret; | ||
375 | } | ||
376 | |||
377 | /* Work function used to reprobe all unregistered subchannels. */ | ||
378 | static void reprobe_all(void *data) | ||
379 | { | ||
380 | int ret; | ||
381 | |||
382 | CIO_MSG_EVENT(2, "reprobe start\n"); | ||
383 | |||
384 | need_reprobe = 0; | ||
385 | /* Make sure initial subchannel scan is done. */ | ||
386 | wait_event(ccw_device_init_wq, | ||
387 | atomic_read(&ccw_device_init_count) == 0); | ||
388 | ret = for_each_subchannel(reprobe_subchannel, NULL); | ||
389 | |||
390 | CIO_MSG_EVENT(2, "reprobe done (rc=%d, need_reprobe=%d)\n", ret, | ||
391 | need_reprobe); | ||
392 | } | ||
393 | |||
394 | DECLARE_WORK(css_reprobe_work, reprobe_all, NULL); | ||
395 | |||
396 | /* Schedule reprobing of all unregistered subchannels. */ | ||
397 | void css_schedule_reprobe(void) | ||
398 | { | ||
399 | need_reprobe = 1; | ||
400 | queue_work(ccw_device_work, &css_reprobe_work); | ||
401 | } | ||
402 | |||
403 | EXPORT_SYMBOL_GPL(css_schedule_reprobe); | ||
404 | |||
342 | /* | 405 | /* |
343 | * Rescan for new devices. FIXME: This is slow. | 406 | * Rescan for new devices. FIXME: This is slow. |
344 | * This function is called when we have lost CRWs due to overflows and we have | 407 | * This function is called when we have lost CRWs due to overflows and we have |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 8e3053c2a451..eafde43e8410 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -133,8 +133,8 @@ struct css_driver io_subchannel_driver = { | |||
133 | 133 | ||
134 | struct workqueue_struct *ccw_device_work; | 134 | struct workqueue_struct *ccw_device_work; |
135 | struct workqueue_struct *ccw_device_notify_work; | 135 | struct workqueue_struct *ccw_device_notify_work; |
136 | static wait_queue_head_t ccw_device_init_wq; | 136 | wait_queue_head_t ccw_device_init_wq; |
137 | static atomic_t ccw_device_init_count; | 137 | atomic_t ccw_device_init_count; |
138 | 138 | ||
139 | static int __init | 139 | static int __init |
140 | init_ccw_bus_type (void) | 140 | init_ccw_bus_type (void) |
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 11587ebb7289..00be9a5b4acd 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
@@ -1,6 +1,10 @@ | |||
1 | #ifndef S390_DEVICE_H | 1 | #ifndef S390_DEVICE_H |
2 | #define S390_DEVICE_H | 2 | #define S390_DEVICE_H |
3 | 3 | ||
4 | #include <asm/ccwdev.h> | ||
5 | #include <asm/atomic.h> | ||
6 | #include <linux/wait.h> | ||
7 | |||
4 | /* | 8 | /* |
5 | * states of the device statemachine | 9 | * states of the device statemachine |
6 | */ | 10 | */ |
@@ -23,6 +27,7 @@ enum dev_state { | |||
23 | DEV_STATE_DISCONNECTED, | 27 | DEV_STATE_DISCONNECTED, |
24 | DEV_STATE_DISCONNECTED_SENSE_ID, | 28 | DEV_STATE_DISCONNECTED_SENSE_ID, |
25 | DEV_STATE_CMFCHANGE, | 29 | DEV_STATE_CMFCHANGE, |
30 | DEV_STATE_CMFUPDATE, | ||
26 | /* last element! */ | 31 | /* last element! */ |
27 | NR_DEV_STATES | 32 | NR_DEV_STATES |
28 | }; | 33 | }; |
@@ -67,6 +72,8 @@ dev_fsm_final_state(struct ccw_device *cdev) | |||
67 | 72 | ||
68 | extern struct workqueue_struct *ccw_device_work; | 73 | extern struct workqueue_struct *ccw_device_work; |
69 | extern struct workqueue_struct *ccw_device_notify_work; | 74 | extern struct workqueue_struct *ccw_device_notify_work; |
75 | extern wait_queue_head_t ccw_device_init_wq; | ||
76 | extern atomic_t ccw_device_init_count; | ||
70 | 77 | ||
71 | void io_subchannel_recog_done(struct ccw_device *cdev); | 78 | void io_subchannel_recog_done(struct ccw_device *cdev); |
72 | 79 | ||
@@ -112,5 +119,8 @@ int ccw_device_stlck(struct ccw_device *); | |||
112 | void ccw_device_set_timeout(struct ccw_device *, int); | 119 | void ccw_device_set_timeout(struct ccw_device *, int); |
113 | extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *); | 120 | extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *); |
114 | 121 | ||
122 | /* Channel measurement facility related */ | ||
115 | void retry_set_schib(struct ccw_device *cdev); | 123 | void retry_set_schib(struct ccw_device *cdev); |
124 | void cmf_retry_copy_block(struct ccw_device *); | ||
125 | int cmf_reenable(struct ccw_device *); | ||
116 | #endif | 126 | #endif |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 49ec562d7f60..7d0dd72635eb 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -336,8 +336,11 @@ ccw_device_oper_notify(void *data) | |||
336 | if (!ret) | 336 | if (!ret) |
337 | /* Driver doesn't want device back. */ | 337 | /* Driver doesn't want device back. */ |
338 | ccw_device_do_unreg_rereg((void *)cdev); | 338 | ccw_device_do_unreg_rereg((void *)cdev); |
339 | else | 339 | else { |
340 | /* Reenable channel measurements, if needed. */ | ||
341 | cmf_reenable(cdev); | ||
340 | wake_up(&cdev->private->wait_q); | 342 | wake_up(&cdev->private->wait_q); |
343 | } | ||
341 | } | 344 | } |
342 | 345 | ||
343 | /* | 346 | /* |
@@ -861,6 +864,8 @@ ccw_device_clear_verify(struct ccw_device *cdev, enum dev_event dev_event) | |||
861 | irb = (struct irb *) __LC_IRB; | 864 | irb = (struct irb *) __LC_IRB; |
862 | /* Accumulate status. We don't do basic sense. */ | 865 | /* Accumulate status. We don't do basic sense. */ |
863 | ccw_device_accumulate_irb(cdev, irb); | 866 | ccw_device_accumulate_irb(cdev, irb); |
867 | /* Remember to clear irb to avoid residuals. */ | ||
868 | memset(&cdev->private->irb, 0, sizeof(struct irb)); | ||
864 | /* Try to start delayed device verification. */ | 869 | /* Try to start delayed device verification. */ |
865 | ccw_device_online_verify(cdev, 0); | 870 | ccw_device_online_verify(cdev, 0); |
866 | /* Note: Don't call handler for cio initiated clear! */ | 871 | /* Note: Don't call handler for cio initiated clear! */ |
@@ -1093,6 +1098,13 @@ ccw_device_change_cmfstate(struct ccw_device *cdev, enum dev_event dev_event) | |||
1093 | dev_fsm_event(cdev, dev_event); | 1098 | dev_fsm_event(cdev, dev_event); |
1094 | } | 1099 | } |
1095 | 1100 | ||
1101 | static void ccw_device_update_cmfblock(struct ccw_device *cdev, | ||
1102 | enum dev_event dev_event) | ||
1103 | { | ||
1104 | cmf_retry_copy_block(cdev); | ||
1105 | cdev->private->state = DEV_STATE_ONLINE; | ||
1106 | dev_fsm_event(cdev, dev_event); | ||
1107 | } | ||
1096 | 1108 | ||
1097 | static void | 1109 | static void |
1098 | ccw_device_quiesce_done(struct ccw_device *cdev, enum dev_event dev_event) | 1110 | ccw_device_quiesce_done(struct ccw_device *cdev, enum dev_event dev_event) |
@@ -1247,6 +1259,12 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { | |||
1247 | [DEV_EVENT_TIMEOUT] = ccw_device_change_cmfstate, | 1259 | [DEV_EVENT_TIMEOUT] = ccw_device_change_cmfstate, |
1248 | [DEV_EVENT_VERIFY] = ccw_device_change_cmfstate, | 1260 | [DEV_EVENT_VERIFY] = ccw_device_change_cmfstate, |
1249 | }, | 1261 | }, |
1262 | [DEV_STATE_CMFUPDATE] = { | ||
1263 | [DEV_EVENT_NOTOPER] = ccw_device_update_cmfblock, | ||
1264 | [DEV_EVENT_INTERRUPT] = ccw_device_update_cmfblock, | ||
1265 | [DEV_EVENT_TIMEOUT] = ccw_device_update_cmfblock, | ||
1266 | [DEV_EVENT_VERIFY] = ccw_device_update_cmfblock, | ||
1267 | }, | ||
1250 | }; | 1268 | }; |
1251 | 1269 | ||
1252 | /* | 1270 | /* |
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 795abb5a65ba..b266ad8e14ff 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c | |||
@@ -78,7 +78,8 @@ ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, | |||
78 | return -ENODEV; | 78 | return -ENODEV; |
79 | if (cdev->private->state == DEV_STATE_NOT_OPER) | 79 | if (cdev->private->state == DEV_STATE_NOT_OPER) |
80 | return -ENODEV; | 80 | return -ENODEV; |
81 | if (cdev->private->state == DEV_STATE_VERIFY) { | 81 | if (cdev->private->state == DEV_STATE_VERIFY || |
82 | cdev->private->state == DEV_STATE_CLEAR_VERIFY) { | ||
82 | /* Remember to fake irb when finished. */ | 83 | /* Remember to fake irb when finished. */ |
83 | if (!cdev->private->flags.fake_irb) { | 84 | if (!cdev->private->flags.fake_irb) { |
84 | cdev->private->flags.fake_irb = 1; | 85 | cdev->private->flags.fake_irb = 1; |
@@ -270,7 +271,8 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb) | |||
270 | * We didn't get channel end / device end. Check if path | 271 | * We didn't get channel end / device end. Check if path |
271 | * verification has been started; we can retry after it has | 272 | * verification has been started; we can retry after it has |
272 | * finished. We also retry unit checks except for command reject | 273 | * finished. We also retry unit checks except for command reject |
273 | * or intervention required. | 274 | * or intervention required. Also check for long busy |
275 | * conditions. | ||
274 | */ | 276 | */ |
275 | if (cdev->private->flags.doverify || | 277 | if (cdev->private->flags.doverify || |
276 | cdev->private->state == DEV_STATE_VERIFY) | 278 | cdev->private->state == DEV_STATE_VERIFY) |
@@ -279,6 +281,10 @@ ccw_device_wake_up(struct ccw_device *cdev, unsigned long ip, struct irb *irb) | |||
279 | !(irb->ecw[0] & | 281 | !(irb->ecw[0] & |
280 | (SNS0_CMD_REJECT | SNS0_INTERVENTION_REQ))) | 282 | (SNS0_CMD_REJECT | SNS0_INTERVENTION_REQ))) |
281 | cdev->private->intparm = -EAGAIN; | 283 | cdev->private->intparm = -EAGAIN; |
284 | else if ((irb->scsw.dstat & DEV_STAT_ATTENTION) && | ||
285 | (irb->scsw.dstat & DEV_STAT_DEV_END) && | ||
286 | (irb->scsw.dstat & DEV_STAT_UNIT_EXCEP)) | ||
287 | cdev->private->intparm = -EAGAIN; | ||
282 | else | 288 | else |
283 | cdev->private->intparm = -EIO; | 289 | cdev->private->intparm = -EIO; |
284 | 290 | ||
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index f99e55308b32..8dc75002acbe 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/workqueue.h> | 15 | #include <linux/workqueue.h> |
16 | #include <linux/time.h> | 16 | #include <linux/time.h> |
17 | #include <linux/kthread.h> | ||
17 | 18 | ||
18 | #include <asm/lowcore.h> | 19 | #include <asm/lowcore.h> |
19 | 20 | ||
@@ -56,8 +57,6 @@ s390_collect_crw_info(void *param) | |||
56 | unsigned int chain; | 57 | unsigned int chain; |
57 | 58 | ||
58 | sem = (struct semaphore *)param; | 59 | sem = (struct semaphore *)param; |
59 | /* Set a nice name. */ | ||
60 | daemonize("kmcheck"); | ||
61 | repeat: | 60 | repeat: |
62 | down_interruptible(sem); | 61 | down_interruptible(sem); |
63 | slow = 0; | 62 | slow = 0; |
@@ -516,7 +515,7 @@ arch_initcall(machine_check_init); | |||
516 | static int __init | 515 | static int __init |
517 | machine_check_crw_init (void) | 516 | machine_check_crw_init (void) |
518 | { | 517 | { |
519 | kernel_thread(s390_collect_crw_info, &m_sem, CLONE_FS|CLONE_FILES); | 518 | kthread_run(s390_collect_crw_info, &m_sem, "kmcheck"); |
520 | ctl_set_bit(14, 28); /* enable channel report MCH */ | 519 | ctl_set_bit(14, 28); /* enable channel report MCH */ |
521 | return 0; | 520 | return 0; |
522 | } | 521 | } |
diff --git a/include/asm-s390/bitops.h b/include/asm-s390/bitops.h index 4d2b126ba159..0ddcdba79e4a 100644 --- a/include/asm-s390/bitops.h +++ b/include/asm-s390/bitops.h | |||
@@ -12,6 +12,9 @@ | |||
12 | * Copyright (C) 1992, Linus Torvalds | 12 | * Copyright (C) 1992, Linus Torvalds |
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | |||
16 | #ifdef __KERNEL__ | ||
17 | |||
15 | #include <linux/compiler.h> | 18 | #include <linux/compiler.h> |
16 | 19 | ||
17 | /* | 20 | /* |
@@ -50,19 +53,6 @@ | |||
50 | * with operation of the form "set_bit(bitnr, flags)". | 53 | * with operation of the form "set_bit(bitnr, flags)". |
51 | */ | 54 | */ |
52 | 55 | ||
53 | /* set ALIGN_CS to 1 if the SMP safe bit operations should | ||
54 | * align the address to 4 byte boundary. It seems to work | ||
55 | * without the alignment. | ||
56 | */ | ||
57 | #ifdef __KERNEL__ | ||
58 | #define ALIGN_CS 0 | ||
59 | #else | ||
60 | #define ALIGN_CS 1 | ||
61 | #ifndef CONFIG_SMP | ||
62 | #error "bitops won't work without CONFIG_SMP" | ||
63 | #endif | ||
64 | #endif | ||
65 | |||
66 | /* bitmap tables from arch/S390/kernel/bitmap.S */ | 56 | /* bitmap tables from arch/S390/kernel/bitmap.S */ |
67 | extern const char _oi_bitmap[]; | 57 | extern const char _oi_bitmap[]; |
68 | extern const char _ni_bitmap[]; | 58 | extern const char _ni_bitmap[]; |
@@ -121,10 +111,6 @@ static inline void set_bit_cs(unsigned long nr, volatile unsigned long *ptr) | |||
121 | unsigned long addr, old, new, mask; | 111 | unsigned long addr, old, new, mask; |
122 | 112 | ||
123 | addr = (unsigned long) ptr; | 113 | addr = (unsigned long) ptr; |
124 | #if ALIGN_CS == 1 | ||
125 | nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ | ||
126 | addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ | ||
127 | #endif | ||
128 | /* calculate address for CS */ | 114 | /* calculate address for CS */ |
129 | addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; | 115 | addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; |
130 | /* make OR mask */ | 116 | /* make OR mask */ |
@@ -141,10 +127,6 @@ static inline void clear_bit_cs(unsigned long nr, volatile unsigned long *ptr) | |||
141 | unsigned long addr, old, new, mask; | 127 | unsigned long addr, old, new, mask; |
142 | 128 | ||
143 | addr = (unsigned long) ptr; | 129 | addr = (unsigned long) ptr; |
144 | #if ALIGN_CS == 1 | ||
145 | nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ | ||
146 | addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ | ||
147 | #endif | ||
148 | /* calculate address for CS */ | 130 | /* calculate address for CS */ |
149 | addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; | 131 | addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; |
150 | /* make AND mask */ | 132 | /* make AND mask */ |
@@ -161,10 +143,6 @@ static inline void change_bit_cs(unsigned long nr, volatile unsigned long *ptr) | |||
161 | unsigned long addr, old, new, mask; | 143 | unsigned long addr, old, new, mask; |
162 | 144 | ||
163 | addr = (unsigned long) ptr; | 145 | addr = (unsigned long) ptr; |
164 | #if ALIGN_CS == 1 | ||
165 | nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ | ||
166 | addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ | ||
167 | #endif | ||
168 | /* calculate address for CS */ | 146 | /* calculate address for CS */ |
169 | addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; | 147 | addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; |
170 | /* make XOR mask */ | 148 | /* make XOR mask */ |
@@ -182,10 +160,6 @@ test_and_set_bit_cs(unsigned long nr, volatile unsigned long *ptr) | |||
182 | unsigned long addr, old, new, mask; | 160 | unsigned long addr, old, new, mask; |
183 | 161 | ||
184 | addr = (unsigned long) ptr; | 162 | addr = (unsigned long) ptr; |
185 | #if ALIGN_CS == 1 | ||
186 | nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ | ||
187 | addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ | ||
188 | #endif | ||
189 | /* calculate address for CS */ | 163 | /* calculate address for CS */ |
190 | addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; | 164 | addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; |
191 | /* make OR/test mask */ | 165 | /* make OR/test mask */ |
@@ -205,10 +179,6 @@ test_and_clear_bit_cs(unsigned long nr, volatile unsigned long *ptr) | |||
205 | unsigned long addr, old, new, mask; | 179 | unsigned long addr, old, new, mask; |
206 | 180 | ||
207 | addr = (unsigned long) ptr; | 181 | addr = (unsigned long) ptr; |
208 | #if ALIGN_CS == 1 | ||
209 | nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ | ||
210 | addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ | ||
211 | #endif | ||
212 | /* calculate address for CS */ | 182 | /* calculate address for CS */ |
213 | addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; | 183 | addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; |
214 | /* make AND/test mask */ | 184 | /* make AND/test mask */ |
@@ -228,10 +198,6 @@ test_and_change_bit_cs(unsigned long nr, volatile unsigned long *ptr) | |||
228 | unsigned long addr, old, new, mask; | 198 | unsigned long addr, old, new, mask; |
229 | 199 | ||
230 | addr = (unsigned long) ptr; | 200 | addr = (unsigned long) ptr; |
231 | #if ALIGN_CS == 1 | ||
232 | nr += (addr & __BITOPS_ALIGN) << 3; /* add alignment to bit number */ | ||
233 | addr ^= addr & __BITOPS_ALIGN; /* align address to 8 */ | ||
234 | #endif | ||
235 | /* calculate address for CS */ | 201 | /* calculate address for CS */ |
236 | addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; | 202 | addr += (nr ^ (nr & (__BITOPS_WORDSIZE - 1))) >> 3; |
237 | /* make XOR/test mask */ | 203 | /* make XOR/test mask */ |
@@ -834,8 +800,6 @@ static inline int sched_find_first_bit(unsigned long *b) | |||
834 | 800 | ||
835 | #include <asm-generic/bitops/hweight.h> | 801 | #include <asm-generic/bitops/hweight.h> |
836 | 802 | ||
837 | #ifdef __KERNEL__ | ||
838 | |||
839 | /* | 803 | /* |
840 | * ATTENTION: intel byte ordering convention for ext2 and minix !! | 804 | * ATTENTION: intel byte ordering convention for ext2 and minix !! |
841 | * bit 0 is the LSB of addr; bit 31 is the MSB of addr; | 805 | * bit 0 is the LSB of addr; bit 31 is the MSB of addr; |
diff --git a/include/asm-s390/cio.h b/include/asm-s390/cio.h index 089cf567c317..2b1619306351 100644 --- a/include/asm-s390/cio.h +++ b/include/asm-s390/cio.h | |||
@@ -276,6 +276,8 @@ extern void wait_cons_dev(void); | |||
276 | 276 | ||
277 | extern void clear_all_subchannels(void); | 277 | extern void clear_all_subchannels(void); |
278 | 278 | ||
279 | extern void css_schedule_reprobe(void); | ||
280 | |||
279 | #endif | 281 | #endif |
280 | 282 | ||
281 | #endif | 283 | #endif |
diff --git a/include/asm-s390/cmb.h b/include/asm-s390/cmb.h index 2d09950a9c11..241756f80df3 100644 --- a/include/asm-s390/cmb.h +++ b/include/asm-s390/cmb.h | |||
@@ -44,10 +44,6 @@ struct cmbdata { | |||
44 | #define BIODASDCMFENABLE _IO(DASD_IOCTL_LETTER,32) | 44 | #define BIODASDCMFENABLE _IO(DASD_IOCTL_LETTER,32) |
45 | /* enable channel measurement */ | 45 | /* enable channel measurement */ |
46 | #define BIODASDCMFDISABLE _IO(DASD_IOCTL_LETTER,33) | 46 | #define BIODASDCMFDISABLE _IO(DASD_IOCTL_LETTER,33) |
47 | /* reset channel measurement block */ | ||
48 | #define BIODASDRESETCMB _IO(DASD_IOCTL_LETTER,34) | ||
49 | /* read channel measurement data */ | ||
50 | #define BIODASDREADCMB _IOWR(DASD_IOCTL_LETTER,32,__u64) | ||
51 | /* read channel measurement data */ | 47 | /* read channel measurement data */ |
52 | #define BIODASDREADALLCMB _IOWR(DASD_IOCTL_LETTER,33,struct cmbdata) | 48 | #define BIODASDREADALLCMB _IOWR(DASD_IOCTL_LETTER,33,struct cmbdata) |
53 | 49 | ||
diff --git a/include/asm-s390/dasd.h b/include/asm-s390/dasd.h index 1630c26e8f45..c042f9578081 100644 --- a/include/asm-s390/dasd.h +++ b/include/asm-s390/dasd.h | |||
@@ -68,10 +68,12 @@ typedef struct dasd_information2_t { | |||
68 | * 0x00: default features | 68 | * 0x00: default features |
69 | * 0x01: readonly (ro) | 69 | * 0x01: readonly (ro) |
70 | * 0x02: use diag discipline (diag) | 70 | * 0x02: use diag discipline (diag) |
71 | * 0x04: set the device initially online (internal use only) | ||
71 | */ | 72 | */ |
72 | #define DASD_FEATURE_DEFAULT 0 | 73 | #define DASD_FEATURE_DEFAULT 0x00 |
73 | #define DASD_FEATURE_READONLY 1 | 74 | #define DASD_FEATURE_READONLY 0x01 |
74 | #define DASD_FEATURE_USEDIAG 2 | 75 | #define DASD_FEATURE_USEDIAG 0x02 |
76 | #define DASD_FEATURE_INITIAL_ONLINE 0x04 | ||
75 | 77 | ||
76 | #define DASD_PARTN_BITS 2 | 78 | #define DASD_PARTN_BITS 2 |
77 | 79 | ||
diff --git a/include/asm-s390/thread_info.h b/include/asm-s390/thread_info.h index 8e0c7ed73d03..0a518915bf90 100644 --- a/include/asm-s390/thread_info.h +++ b/include/asm-s390/thread_info.h | |||
@@ -63,6 +63,7 @@ struct thread_info { | |||
63 | .exec_domain = &default_exec_domain, \ | 63 | .exec_domain = &default_exec_domain, \ |
64 | .flags = 0, \ | 64 | .flags = 0, \ |
65 | .cpu = 0, \ | 65 | .cpu = 0, \ |
66 | .preempt_count = 1, \ | ||
66 | .restart_block = { \ | 67 | .restart_block = { \ |
67 | .fn = do_no_restart_syscall, \ | 68 | .fn = do_no_restart_syscall, \ |
68 | }, \ | 69 | }, \ |
diff --git a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h index e21443d3ea1d..aa7a243862e1 100644 --- a/include/asm-s390/unistd.h +++ b/include/asm-s390/unistd.h | |||
@@ -394,11 +394,9 @@ | |||
394 | 394 | ||
395 | #ifdef __KERNEL__ | 395 | #ifdef __KERNEL__ |
396 | 396 | ||
397 | /* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */ | ||
398 | |||
399 | #define __syscall_return(type, res) \ | 397 | #define __syscall_return(type, res) \ |
400 | do { \ | 398 | do { \ |
401 | if ((unsigned long)(res) >= (unsigned long)(-125)) { \ | 399 | if ((unsigned long)(res) >= (unsigned long)(-4095)) {\ |
402 | errno = -(res); \ | 400 | errno = -(res); \ |
403 | res = -1; \ | 401 | res = -1; \ |
404 | } \ | 402 | } \ |