diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-20 12:23:31 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-01-20 12:23:31 -0500 |
commit | f479c01c8e81096e01eb20cec67dbaebae669aee (patch) | |
tree | 951890b22992aa6366b55308cdc05b1568cb8622 /drivers/s390 | |
parent | d8ec26d7f8287f5788a494f56e8814210f0e64be (diff) | |
parent | f85168e4d96b31b09ecf09a679820b031224e69e (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky:
"The bulk of the s390 updates for v3.14.
New features are the perf support for the CPU-Measurement Sample
Facility and the EP11 support for the crypto cards. And the normal
cleanups and bug-fixes"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (44 commits)
s390/cpum_sf: fix printk format warnings
s390: Fix misspellings using 'codespell' tool
s390/qdio: bridgeport support - CHSC part
s390: delete new instances of __cpuinit usage
s390/compat: fix PSW32_USER_BITS definition
s390/zcrypt: add support for EP11 coprocessor cards
s390/mm: optimize randomize_et_dyn for !PF_RANDOMIZE
s390: use IS_ENABLED to check if a CONFIG is set to y or m
s390/cio: use device_lock to synchronize calls to the ccwgroup driver
s390/cio: use device_lock to synchronize calls to the ccw driver
s390/cio: fix unlocked access of online member
s390/cpum_sf: Add flag to process full SDBs only
s390/cpum_sf: Add raw data sampling to support the diagnostic-sampling function
s390/cpum_sf: Filter perf events based event->attr.exclude_* settings
s390/cpum_sf: Detect KVM guest samples
s390/cpum_sf: Add helper to read TOD from trailer entries
s390/cpum_sf: Atomically reset trailer entry fields of sample-data-blocks
s390/cpum_sf: Dynamically extend the sampling buffer if overflows occur
s390/pci: reenable per default
s390/pci/dma: fix accounting of allocated_pages
...
Diffstat (limited to 'drivers/s390')
24 files changed, 755 insertions, 152 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index f302efa937ef..1eef0f586950 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -3386,7 +3386,7 @@ int dasd_generic_set_offline(struct ccw_device *cdev) | |||
3386 | 3386 | ||
3387 | if (test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) { | 3387 | if (test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) { |
3388 | /* | 3388 | /* |
3389 | * safe offline allready running | 3389 | * safe offline already running |
3390 | * could only be called by normal offline so safe_offline flag | 3390 | * could only be called by normal offline so safe_offline flag |
3391 | * needs to be removed to run normal offline and kill all I/O | 3391 | * needs to be removed to run normal offline and kill all I/O |
3392 | */ | 3392 | */ |
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 6fbe09686d18..fea76aed9eea 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h | |||
@@ -183,7 +183,6 @@ extern unsigned long sclp_console_full; | |||
183 | extern u8 sclp_fac84; | 183 | extern u8 sclp_fac84; |
184 | extern unsigned long long sclp_rzm; | 184 | extern unsigned long long sclp_rzm; |
185 | extern unsigned long long sclp_rnmax; | 185 | extern unsigned long long sclp_rnmax; |
186 | extern __initdata int sclp_early_read_info_sccb_valid; | ||
187 | 186 | ||
188 | /* useful inlines */ | 187 | /* useful inlines */ |
189 | 188 | ||
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index eaa21d542c5c..cb3c4e05a385 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c | |||
@@ -455,8 +455,6 @@ static int __init sclp_detect_standby_memory(void) | |||
455 | 455 | ||
456 | if (OLDMEM_BASE) /* No standby memory in kdump mode */ | 456 | if (OLDMEM_BASE) /* No standby memory in kdump mode */ |
457 | return 0; | 457 | return 0; |
458 | if (!sclp_early_read_info_sccb_valid) | ||
459 | return 0; | ||
460 | if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL) | 458 | if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL) |
461 | return 0; | 459 | return 0; |
462 | rc = -ENOMEM; | 460 | rc = -ENOMEM; |
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index 1465e9563101..82f2c389b4d1 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c | |||
@@ -35,11 +35,12 @@ struct read_info_sccb { | |||
35 | u8 _reserved5[4096 - 112]; /* 112-4095 */ | 35 | u8 _reserved5[4096 - 112]; /* 112-4095 */ |
36 | } __packed __aligned(PAGE_SIZE); | 36 | } __packed __aligned(PAGE_SIZE); |
37 | 37 | ||
38 | static __initdata struct read_info_sccb early_read_info_sccb; | 38 | static char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE) __initdata; |
39 | static __initdata char sccb_early[PAGE_SIZE] __aligned(PAGE_SIZE); | 39 | static unsigned int sclp_con_has_vt220 __initdata; |
40 | static unsigned int sclp_con_has_linemode __initdata; | ||
40 | static unsigned long sclp_hsa_size; | 41 | static unsigned long sclp_hsa_size; |
42 | static struct sclp_ipl_info sclp_ipl_info; | ||
41 | 43 | ||
42 | __initdata int sclp_early_read_info_sccb_valid; | ||
43 | u64 sclp_facilities; | 44 | u64 sclp_facilities; |
44 | u8 sclp_fac84; | 45 | u8 sclp_fac84; |
45 | unsigned long long sclp_rzm; | 46 | unsigned long long sclp_rzm; |
@@ -63,15 +64,12 @@ out: | |||
63 | return rc; | 64 | return rc; |
64 | } | 65 | } |
65 | 66 | ||
66 | static void __init sclp_read_info_early(void) | 67 | static int __init sclp_read_info_early(struct read_info_sccb *sccb) |
67 | { | 68 | { |
68 | int rc; | 69 | int rc, i; |
69 | int i; | ||
70 | struct read_info_sccb *sccb; | ||
71 | sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, | 70 | sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, |
72 | SCLP_CMDW_READ_SCP_INFO}; | 71 | SCLP_CMDW_READ_SCP_INFO}; |
73 | 72 | ||
74 | sccb = &early_read_info_sccb; | ||
75 | for (i = 0; i < ARRAY_SIZE(commands); i++) { | 73 | for (i = 0; i < ARRAY_SIZE(commands); i++) { |
76 | do { | 74 | do { |
77 | memset(sccb, 0, sizeof(*sccb)); | 75 | memset(sccb, 0, sizeof(*sccb)); |
@@ -83,24 +81,19 @@ static void __init sclp_read_info_early(void) | |||
83 | 81 | ||
84 | if (rc) | 82 | if (rc) |
85 | break; | 83 | break; |
86 | if (sccb->header.response_code == 0x10) { | 84 | if (sccb->header.response_code == 0x10) |
87 | sclp_early_read_info_sccb_valid = 1; | 85 | return 0; |
88 | break; | ||
89 | } | ||
90 | if (sccb->header.response_code != 0x1f0) | 86 | if (sccb->header.response_code != 0x1f0) |
91 | break; | 87 | break; |
92 | } | 88 | } |
89 | return -EIO; | ||
93 | } | 90 | } |
94 | 91 | ||
95 | static void __init sclp_facilities_detect(void) | 92 | static void __init sclp_facilities_detect(struct read_info_sccb *sccb) |
96 | { | 93 | { |
97 | struct read_info_sccb *sccb; | 94 | if (sclp_read_info_early(sccb)) |
98 | |||
99 | sclp_read_info_early(); | ||
100 | if (!sclp_early_read_info_sccb_valid) | ||
101 | return; | 95 | return; |
102 | 96 | ||
103 | sccb = &early_read_info_sccb; | ||
104 | sclp_facilities = sccb->facilities; | 97 | sclp_facilities = sccb->facilities; |
105 | sclp_fac84 = sccb->fac84; | 98 | sclp_fac84 = sccb->fac84; |
106 | if (sccb->fac85 & 0x02) | 99 | if (sccb->fac85 & 0x02) |
@@ -108,30 +101,22 @@ static void __init sclp_facilities_detect(void) | |||
108 | sclp_rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; | 101 | sclp_rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2; |
109 | sclp_rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; | 102 | sclp_rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2; |
110 | sclp_rzm <<= 20; | 103 | sclp_rzm <<= 20; |
104 | |||
105 | /* Save IPL information */ | ||
106 | sclp_ipl_info.is_valid = 1; | ||
107 | if (sccb->flags & 0x2) | ||
108 | sclp_ipl_info.has_dump = 1; | ||
109 | memcpy(&sclp_ipl_info.loadparm, &sccb->loadparm, LOADPARM_LEN); | ||
111 | } | 110 | } |
112 | 111 | ||
113 | bool __init sclp_has_linemode(void) | 112 | bool __init sclp_has_linemode(void) |
114 | { | 113 | { |
115 | struct init_sccb *sccb = (void *) &sccb_early; | 114 | return !!sclp_con_has_linemode; |
116 | |||
117 | if (sccb->header.response_code != 0x20) | ||
118 | return 0; | ||
119 | if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK))) | ||
120 | return 0; | ||
121 | if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) | ||
122 | return 0; | ||
123 | return 1; | ||
124 | } | 115 | } |
125 | 116 | ||
126 | bool __init sclp_has_vt220(void) | 117 | bool __init sclp_has_vt220(void) |
127 | { | 118 | { |
128 | struct init_sccb *sccb = (void *) &sccb_early; | 119 | return !!sclp_con_has_vt220; |
129 | |||
130 | if (sccb->header.response_code != 0x20) | ||
131 | return 0; | ||
132 | if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) | ||
133 | return 1; | ||
134 | return 0; | ||
135 | } | 120 | } |
136 | 121 | ||
137 | unsigned long long sclp_get_rnmax(void) | 122 | unsigned long long sclp_get_rnmax(void) |
@@ -146,19 +131,12 @@ unsigned long long sclp_get_rzm(void) | |||
146 | 131 | ||
147 | /* | 132 | /* |
148 | * This function will be called after sclp_facilities_detect(), which gets | 133 | * This function will be called after sclp_facilities_detect(), which gets |
149 | * called from early.c code. Therefore the sccb should have valid contents. | 134 | * called from early.c code. The sclp_facilities_detect() function retrieves |
135 | * and saves the IPL information. | ||
150 | */ | 136 | */ |
151 | void __init sclp_get_ipl_info(struct sclp_ipl_info *info) | 137 | void __init sclp_get_ipl_info(struct sclp_ipl_info *info) |
152 | { | 138 | { |
153 | struct read_info_sccb *sccb; | 139 | *info = sclp_ipl_info; |
154 | |||
155 | if (!sclp_early_read_info_sccb_valid) | ||
156 | return; | ||
157 | sccb = &early_read_info_sccb; | ||
158 | info->is_valid = 1; | ||
159 | if (sccb->flags & 0x2) | ||
160 | info->has_dump = 1; | ||
161 | memcpy(&info->loadparm, &sccb->loadparm, LOADPARM_LEN); | ||
162 | } | 140 | } |
163 | 141 | ||
164 | static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb) | 142 | static int __init sclp_cmd_early(sclp_cmdw_t cmd, void *sccb) |
@@ -189,11 +167,10 @@ static void __init sccb_init_eq_size(struct sdias_sccb *sccb) | |||
189 | sccb->evbuf.dbs = 1; | 167 | sccb->evbuf.dbs = 1; |
190 | } | 168 | } |
191 | 169 | ||
192 | static int __init sclp_set_event_mask(unsigned long receive_mask, | 170 | static int __init sclp_set_event_mask(struct init_sccb *sccb, |
171 | unsigned long receive_mask, | ||
193 | unsigned long send_mask) | 172 | unsigned long send_mask) |
194 | { | 173 | { |
195 | struct init_sccb *sccb = (void *) &sccb_early; | ||
196 | |||
197 | memset(sccb, 0, sizeof(*sccb)); | 174 | memset(sccb, 0, sizeof(*sccb)); |
198 | sccb->header.length = sizeof(*sccb); | 175 | sccb->header.length = sizeof(*sccb); |
199 | sccb->mask_length = sizeof(sccb_mask_t); | 176 | sccb->mask_length = sizeof(sccb_mask_t); |
@@ -202,10 +179,8 @@ static int __init sclp_set_event_mask(unsigned long receive_mask, | |||
202 | return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); | 179 | return sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_MASK, sccb); |
203 | } | 180 | } |
204 | 181 | ||
205 | static long __init sclp_hsa_size_init(void) | 182 | static long __init sclp_hsa_size_init(struct sdias_sccb *sccb) |
206 | { | 183 | { |
207 | struct sdias_sccb *sccb = (void *) &sccb_early; | ||
208 | |||
209 | sccb_init_eq_size(sccb); | 184 | sccb_init_eq_size(sccb); |
210 | if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb)) | 185 | if (sclp_cmd_early(SCLP_CMDW_WRITE_EVENT_DATA, sccb)) |
211 | return -EIO; | 186 | return -EIO; |
@@ -214,10 +189,8 @@ static long __init sclp_hsa_size_init(void) | |||
214 | return 0; | 189 | return 0; |
215 | } | 190 | } |
216 | 191 | ||
217 | static long __init sclp_hsa_copy_wait(void) | 192 | static long __init sclp_hsa_copy_wait(struct sccb_header *sccb) |
218 | { | 193 | { |
219 | struct sccb_header *sccb = (void *) &sccb_early; | ||
220 | |||
221 | memset(sccb, 0, PAGE_SIZE); | 194 | memset(sccb, 0, PAGE_SIZE); |
222 | sccb->length = PAGE_SIZE; | 195 | sccb->length = PAGE_SIZE; |
223 | if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb)) | 196 | if (sclp_cmd_early(SCLP_CMDW_READ_EVENT_DATA, sccb)) |
@@ -230,34 +203,62 @@ unsigned long sclp_get_hsa_size(void) | |||
230 | return sclp_hsa_size; | 203 | return sclp_hsa_size; |
231 | } | 204 | } |
232 | 205 | ||
233 | static void __init sclp_hsa_size_detect(void) | 206 | static void __init sclp_hsa_size_detect(void *sccb) |
234 | { | 207 | { |
235 | long size; | 208 | long size; |
236 | 209 | ||
237 | /* First try synchronous interface (LPAR) */ | 210 | /* First try synchronous interface (LPAR) */ |
238 | if (sclp_set_event_mask(0, 0x40000010)) | 211 | if (sclp_set_event_mask(sccb, 0, 0x40000010)) |
239 | return; | 212 | return; |
240 | size = sclp_hsa_size_init(); | 213 | size = sclp_hsa_size_init(sccb); |
241 | if (size < 0) | 214 | if (size < 0) |
242 | return; | 215 | return; |
243 | if (size != 0) | 216 | if (size != 0) |
244 | goto out; | 217 | goto out; |
245 | /* Then try asynchronous interface (z/VM) */ | 218 | /* Then try asynchronous interface (z/VM) */ |
246 | if (sclp_set_event_mask(0x00000010, 0x40000010)) | 219 | if (sclp_set_event_mask(sccb, 0x00000010, 0x40000010)) |
247 | return; | 220 | return; |
248 | size = sclp_hsa_size_init(); | 221 | size = sclp_hsa_size_init(sccb); |
249 | if (size < 0) | 222 | if (size < 0) |
250 | return; | 223 | return; |
251 | size = sclp_hsa_copy_wait(); | 224 | size = sclp_hsa_copy_wait(sccb); |
252 | if (size < 0) | 225 | if (size < 0) |
253 | return; | 226 | return; |
254 | out: | 227 | out: |
255 | sclp_hsa_size = size; | 228 | sclp_hsa_size = size; |
256 | } | 229 | } |
257 | 230 | ||
231 | static unsigned int __init sclp_con_check_linemode(struct init_sccb *sccb) | ||
232 | { | ||
233 | if (!(sccb->sclp_send_mask & (EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK))) | ||
234 | return 0; | ||
235 | if (!(sccb->sclp_receive_mask & (EVTYP_MSG_MASK | EVTYP_PMSGCMD_MASK))) | ||
236 | return 0; | ||
237 | return 1; | ||
238 | } | ||
239 | |||
240 | static void __init sclp_console_detect(struct init_sccb *sccb) | ||
241 | { | ||
242 | if (sccb->header.response_code != 0x20) | ||
243 | return; | ||
244 | |||
245 | if (sccb->sclp_send_mask & EVTYP_VT220MSG_MASK) | ||
246 | sclp_con_has_vt220 = 1; | ||
247 | |||
248 | if (sclp_con_check_linemode(sccb)) | ||
249 | sclp_con_has_linemode = 1; | ||
250 | } | ||
251 | |||
258 | void __init sclp_early_detect(void) | 252 | void __init sclp_early_detect(void) |
259 | { | 253 | { |
260 | sclp_facilities_detect(); | 254 | void *sccb = &sccb_early; |
261 | sclp_hsa_size_detect(); | 255 | |
262 | sclp_set_event_mask(0, 0); | 256 | sclp_facilities_detect(sccb); |
257 | sclp_hsa_size_detect(sccb); | ||
258 | |||
259 | /* Turn off SCLP event notifications. Also save remote masks in the | ||
260 | * sccb. These are sufficient to detect sclp console capabilities. | ||
261 | */ | ||
262 | sclp_set_event_mask(sccb, 0, 0); | ||
263 | sclp_console_detect(sccb); | ||
263 | } | 264 | } |
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 34629ea913d4..e91b89dc6d1f 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c | |||
@@ -125,10 +125,7 @@ static void tty3270_resize_work(struct work_struct *work); | |||
125 | */ | 125 | */ |
126 | static void tty3270_set_timer(struct tty3270 *tp, int expires) | 126 | static void tty3270_set_timer(struct tty3270 *tp, int expires) |
127 | { | 127 | { |
128 | if (expires == 0) | 128 | mod_timer(&tp->timer, jiffies + expires); |
129 | del_timer(&tp->timer); | ||
130 | else | ||
131 | mod_timer(&tp->timer, jiffies + expires); | ||
132 | } | 129 | } |
133 | 130 | ||
134 | /* | 131 | /* |
@@ -744,7 +741,6 @@ tty3270_free_view(struct tty3270 *tp) | |||
744 | { | 741 | { |
745 | int pages; | 742 | int pages; |
746 | 743 | ||
747 | del_timer_sync(&tp->timer); | ||
748 | kbd_free(tp->kbd); | 744 | kbd_free(tp->kbd); |
749 | raw3270_request_free(tp->kreset); | 745 | raw3270_request_free(tp->kreset); |
750 | raw3270_request_free(tp->read); | 746 | raw3270_request_free(tp->read); |
@@ -877,6 +873,7 @@ tty3270_free(struct raw3270_view *view) | |||
877 | { | 873 | { |
878 | struct tty3270 *tp = container_of(view, struct tty3270, view); | 874 | struct tty3270 *tp = container_of(view, struct tty3270, view); |
879 | 875 | ||
876 | del_timer_sync(&tp->timer); | ||
880 | tty3270_free_screen(tp->screen, tp->view.rows); | 877 | tty3270_free_screen(tp->screen, tp->view.rows); |
881 | tty3270_free_view(tp); | 878 | tty3270_free_view(tp); |
882 | } | 879 | } |
diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index a9fe3de2dec1..b3f791b2c1f8 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c | |||
@@ -260,16 +260,16 @@ static int blacklist_parse_proc_parameters(char *buf) | |||
260 | 260 | ||
261 | parm = strsep(&buf, " "); | 261 | parm = strsep(&buf, " "); |
262 | 262 | ||
263 | if (strcmp("free", parm) == 0) | 263 | if (strcmp("free", parm) == 0) { |
264 | rc = blacklist_parse_parameters(buf, free, 0); | 264 | rc = blacklist_parse_parameters(buf, free, 0); |
265 | else if (strcmp("add", parm) == 0) | 265 | css_schedule_eval_all_unreg(0); |
266 | } else if (strcmp("add", parm) == 0) | ||
266 | rc = blacklist_parse_parameters(buf, add, 0); | 267 | rc = blacklist_parse_parameters(buf, add, 0); |
267 | else if (strcmp("purge", parm) == 0) | 268 | else if (strcmp("purge", parm) == 0) |
268 | return ccw_purge_blacklisted(); | 269 | return ccw_purge_blacklisted(); |
269 | else | 270 | else |
270 | return -EINVAL; | 271 | return -EINVAL; |
271 | 272 | ||
272 | css_schedule_reprobe(); | ||
273 | 273 | ||
274 | return rc; | 274 | return rc; |
275 | } | 275 | } |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 959135a01847..fd3367a1dc7a 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -128,14 +128,14 @@ static ssize_t ccwgroup_online_store(struct device *dev, | |||
128 | const char *buf, size_t count) | 128 | const char *buf, size_t count) |
129 | { | 129 | { |
130 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); | 130 | struct ccwgroup_device *gdev = to_ccwgroupdev(dev); |
131 | struct ccwgroup_driver *gdrv = to_ccwgroupdrv(dev->driver); | ||
132 | unsigned long value; | 131 | unsigned long value; |
133 | int ret; | 132 | int ret; |
134 | 133 | ||
135 | if (!dev->driver) | 134 | device_lock(dev); |
136 | return -EINVAL; | 135 | if (!dev->driver) { |
137 | if (!try_module_get(gdrv->driver.owner)) | 136 | ret = -EINVAL; |
138 | return -EINVAL; | 137 | goto out; |
138 | } | ||
139 | 139 | ||
140 | ret = kstrtoul(buf, 0, &value); | 140 | ret = kstrtoul(buf, 0, &value); |
141 | if (ret) | 141 | if (ret) |
@@ -148,7 +148,7 @@ static ssize_t ccwgroup_online_store(struct device *dev, | |||
148 | else | 148 | else |
149 | ret = -EINVAL; | 149 | ret = -EINVAL; |
150 | out: | 150 | out: |
151 | module_put(gdrv->driver.owner); | 151 | device_unlock(dev); |
152 | return (ret == 0) ? count : ret; | 152 | return (ret == 0) ? count : ret; |
153 | } | 153 | } |
154 | 154 | ||
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 13299f902676..f6b9188c5af5 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -55,6 +55,7 @@ int chsc_error_from_response(int response) | |||
55 | case 0x0004: | 55 | case 0x0004: |
56 | return -EOPNOTSUPP; | 56 | return -EOPNOTSUPP; |
57 | case 0x000b: | 57 | case 0x000b: |
58 | case 0x0107: /* "Channel busy" for the op 0x003d */ | ||
58 | return -EBUSY; | 59 | return -EBUSY; |
59 | case 0x0100: | 60 | case 0x0100: |
60 | case 0x0102: | 61 | case 0x0102: |
@@ -237,26 +238,6 @@ void chsc_chp_offline(struct chp_id chpid) | |||
237 | for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link); | 238 | for_each_subchannel_staged(s390_subchannel_remove_chpid, NULL, &link); |
238 | } | 239 | } |
239 | 240 | ||
240 | static int s390_process_res_acc_new_sch(struct subchannel_id schid, void *data) | ||
241 | { | ||
242 | struct schib schib; | ||
243 | /* | ||
244 | * We don't know the device yet, but since a path | ||
245 | * may be available now to the device we'll have | ||
246 | * to do recognition again. | ||
247 | * Since we don't have any idea about which chpid | ||
248 | * that beast may be on we'll have to do a stsch | ||
249 | * on all devices, grr... | ||
250 | */ | ||
251 | if (stsch_err(schid, &schib)) | ||
252 | /* We're through */ | ||
253 | return -ENXIO; | ||
254 | |||
255 | /* Put it on the slow path. */ | ||
256 | css_schedule_eval(schid); | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | static int __s390_process_res_acc(struct subchannel *sch, void *data) | 241 | static int __s390_process_res_acc(struct subchannel *sch, void *data) |
261 | { | 242 | { |
262 | spin_lock_irq(sch->lock); | 243 | spin_lock_irq(sch->lock); |
@@ -287,8 +268,8 @@ static void s390_process_res_acc(struct chp_link *link) | |||
287 | * The more information we have (info), the less scanning | 268 | * The more information we have (info), the less scanning |
288 | * will we have to do. | 269 | * will we have to do. |
289 | */ | 270 | */ |
290 | for_each_subchannel_staged(__s390_process_res_acc, | 271 | for_each_subchannel_staged(__s390_process_res_acc, NULL, link); |
291 | s390_process_res_acc_new_sch, link); | 272 | css_schedule_reprobe(); |
292 | } | 273 | } |
293 | 274 | ||
294 | static int | 275 | static int |
@@ -663,19 +644,6 @@ static int s390_subchannel_vary_chpid_on(struct subchannel *sch, void *data) | |||
663 | return 0; | 644 | return 0; |
664 | } | 645 | } |
665 | 646 | ||
666 | static int | ||
667 | __s390_vary_chpid_on(struct subchannel_id schid, void *data) | ||
668 | { | ||
669 | struct schib schib; | ||
670 | |||
671 | if (stsch_err(schid, &schib)) | ||
672 | /* We're through */ | ||
673 | return -ENXIO; | ||
674 | /* Put it on the slow path. */ | ||
675 | css_schedule_eval(schid); | ||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | /** | 647 | /** |
680 | * chsc_chp_vary - propagate channel-path vary operation to subchannels | 648 | * chsc_chp_vary - propagate channel-path vary operation to subchannels |
681 | * @chpid: channl-path ID | 649 | * @chpid: channl-path ID |
@@ -694,7 +662,8 @@ int chsc_chp_vary(struct chp_id chpid, int on) | |||
694 | /* Try to update the channel path description. */ | 662 | /* Try to update the channel path description. */ |
695 | chp_update_desc(chp); | 663 | chp_update_desc(chp); |
696 | for_each_subchannel_staged(s390_subchannel_vary_chpid_on, | 664 | for_each_subchannel_staged(s390_subchannel_vary_chpid_on, |
697 | __s390_vary_chpid_on, &chpid); | 665 | NULL, &chpid); |
666 | css_schedule_reprobe(); | ||
698 | } else | 667 | } else |
699 | for_each_subchannel_staged(s390_subchannel_vary_chpid_off, | 668 | for_each_subchannel_staged(s390_subchannel_vary_chpid_off, |
700 | NULL, &chpid); | 669 | NULL, &chpid); |
@@ -1234,3 +1203,35 @@ out: | |||
1234 | return ret; | 1203 | return ret; |
1235 | } | 1204 | } |
1236 | EXPORT_SYMBOL_GPL(chsc_scm_info); | 1205 | EXPORT_SYMBOL_GPL(chsc_scm_info); |
1206 | |||
1207 | /** | ||
1208 | * chsc_pnso_brinfo() - Perform Network-Subchannel Operation, Bridge Info. | ||
1209 | * @schid: id of the subchannel on which PNSO is performed | ||
1210 | * @brinfo_area: request and response block for the operation | ||
1211 | * @resume_token: resume token for multiblock response | ||
1212 | * @cnc: Boolean change-notification control | ||
1213 | * | ||
1214 | * brinfo_area must be allocated by the caller with get_zeroed_page(GFP_KERNEL) | ||
1215 | * | ||
1216 | * Returns 0 on success. | ||
1217 | */ | ||
1218 | int chsc_pnso_brinfo(struct subchannel_id schid, | ||
1219 | struct chsc_pnso_area *brinfo_area, | ||
1220 | struct chsc_brinfo_resume_token resume_token, | ||
1221 | int cnc) | ||
1222 | { | ||
1223 | memset(brinfo_area, 0, sizeof(*brinfo_area)); | ||
1224 | brinfo_area->request.length = 0x0030; | ||
1225 | brinfo_area->request.code = 0x003d; /* network-subchannel operation */ | ||
1226 | brinfo_area->m = schid.m; | ||
1227 | brinfo_area->ssid = schid.ssid; | ||
1228 | brinfo_area->sch = schid.sch_no; | ||
1229 | brinfo_area->cssid = schid.cssid; | ||
1230 | brinfo_area->oc = 0; /* Store-network-bridging-information list */ | ||
1231 | brinfo_area->resume_token = resume_token; | ||
1232 | brinfo_area->n = (cnc != 0); | ||
1233 | if (chsc(brinfo_area)) | ||
1234 | return -EIO; | ||
1235 | return chsc_error_from_response(brinfo_area->response.code); | ||
1236 | } | ||
1237 | EXPORT_SYMBOL_GPL(chsc_pnso_brinfo); | ||
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 23d072e70eb2..7e53a9c8b0b9 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
@@ -61,7 +61,9 @@ struct css_chsc_char { | |||
61 | u32 : 20; | 61 | u32 : 20; |
62 | u32 scssc : 1; /* bit 107 */ | 62 | u32 scssc : 1; /* bit 107 */ |
63 | u32 scsscf : 1; /* bit 108 */ | 63 | u32 scsscf : 1; /* bit 108 */ |
64 | u32 : 19; | 64 | u32:7; |
65 | u32 pnso:1; /* bit 116 */ | ||
66 | u32:11; | ||
65 | }__attribute__((packed)); | 67 | }__attribute__((packed)); |
66 | 68 | ||
67 | extern struct css_chsc_char css_chsc_characteristics; | 69 | extern struct css_chsc_char css_chsc_characteristics; |
@@ -188,6 +190,53 @@ struct chsc_scm_info { | |||
188 | 190 | ||
189 | int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token); | 191 | int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token); |
190 | 192 | ||
193 | struct chsc_brinfo_resume_token { | ||
194 | u64 t1; | ||
195 | u64 t2; | ||
196 | } __packed; | ||
197 | |||
198 | struct chsc_brinfo_naihdr { | ||
199 | struct chsc_brinfo_resume_token resume_token; | ||
200 | u32:32; | ||
201 | u32 instance; | ||
202 | u32:24; | ||
203 | u8 naids; | ||
204 | u32 reserved[3]; | ||
205 | } __packed; | ||
206 | |||
207 | struct chsc_pnso_area { | ||
208 | struct chsc_header request; | ||
209 | u8:2; | ||
210 | u8 m:1; | ||
211 | u8:5; | ||
212 | u8:2; | ||
213 | u8 ssid:2; | ||
214 | u8 fmt:4; | ||
215 | u16 sch; | ||
216 | u8:8; | ||
217 | u8 cssid; | ||
218 | u16:16; | ||
219 | u8 oc; | ||
220 | u32:24; | ||
221 | struct chsc_brinfo_resume_token resume_token; | ||
222 | u32 n:1; | ||
223 | u32:31; | ||
224 | u32 reserved[3]; | ||
225 | struct chsc_header response; | ||
226 | u32:32; | ||
227 | struct chsc_brinfo_naihdr naihdr; | ||
228 | union { | ||
229 | struct qdio_brinfo_entry_l3_ipv6 l3_ipv6[0]; | ||
230 | struct qdio_brinfo_entry_l3_ipv4 l3_ipv4[0]; | ||
231 | struct qdio_brinfo_entry_l2 l2[0]; | ||
232 | } entries; | ||
233 | } __packed; | ||
234 | |||
235 | int chsc_pnso_brinfo(struct subchannel_id schid, | ||
236 | struct chsc_pnso_area *brinfo_area, | ||
237 | struct chsc_brinfo_resume_token resume_token, | ||
238 | int cnc); | ||
239 | |||
191 | #ifdef CONFIG_SCM_BUS | 240 | #ifdef CONFIG_SCM_BUS |
192 | int scm_update_information(void); | 241 | int scm_update_information(void); |
193 | int scm_process_availability_information(void); | 242 | int scm_process_availability_information(void); |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 8c2cb87bccc5..0268e5fd59b5 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -69,7 +69,8 @@ static int call_fn_known_sch(struct device *dev, void *data) | |||
69 | struct cb_data *cb = data; | 69 | struct cb_data *cb = data; |
70 | int rc = 0; | 70 | int rc = 0; |
71 | 71 | ||
72 | idset_sch_del(cb->set, sch->schid); | 72 | if (cb->set) |
73 | idset_sch_del(cb->set, sch->schid); | ||
73 | if (cb->fn_known_sch) | 74 | if (cb->fn_known_sch) |
74 | rc = cb->fn_known_sch(sch, cb->data); | 75 | rc = cb->fn_known_sch(sch, cb->data); |
75 | return rc; | 76 | return rc; |
@@ -115,6 +116,13 @@ int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), | |||
115 | cb.fn_known_sch = fn_known; | 116 | cb.fn_known_sch = fn_known; |
116 | cb.fn_unknown_sch = fn_unknown; | 117 | cb.fn_unknown_sch = fn_unknown; |
117 | 118 | ||
119 | if (fn_known && !fn_unknown) { | ||
120 | /* Skip idset allocation in case of known-only loop. */ | ||
121 | cb.set = NULL; | ||
122 | return bus_for_each_dev(&css_bus_type, NULL, &cb, | ||
123 | call_fn_known_sch); | ||
124 | } | ||
125 | |||
118 | cb.set = idset_sch_new(); | 126 | cb.set = idset_sch_new(); |
119 | if (!cb.set) | 127 | if (!cb.set) |
120 | /* fall back to brute force scanning in case of oom */ | 128 | /* fall back to brute force scanning in case of oom */ |
@@ -553,6 +561,9 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data) | |||
553 | default: | 561 | default: |
554 | rc = 0; | 562 | rc = 0; |
555 | } | 563 | } |
564 | /* Allow scheduling here since the containing loop might | ||
565 | * take a while. */ | ||
566 | cond_resched(); | ||
556 | } | 567 | } |
557 | return rc; | 568 | return rc; |
558 | } | 569 | } |
@@ -572,7 +583,7 @@ static void css_slow_path_func(struct work_struct *unused) | |||
572 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 583 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
573 | } | 584 | } |
574 | 585 | ||
575 | static DECLARE_WORK(slow_path_work, css_slow_path_func); | 586 | static DECLARE_DELAYED_WORK(slow_path_work, css_slow_path_func); |
576 | struct workqueue_struct *cio_work_q; | 587 | struct workqueue_struct *cio_work_q; |
577 | 588 | ||
578 | void css_schedule_eval(struct subchannel_id schid) | 589 | void css_schedule_eval(struct subchannel_id schid) |
@@ -582,7 +593,7 @@ void css_schedule_eval(struct subchannel_id schid) | |||
582 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 593 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
583 | idset_sch_add(slow_subchannel_set, schid); | 594 | idset_sch_add(slow_subchannel_set, schid); |
584 | atomic_set(&css_eval_scheduled, 1); | 595 | atomic_set(&css_eval_scheduled, 1); |
585 | queue_work(cio_work_q, &slow_path_work); | 596 | queue_delayed_work(cio_work_q, &slow_path_work, 0); |
586 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 597 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
587 | } | 598 | } |
588 | 599 | ||
@@ -593,7 +604,7 @@ void css_schedule_eval_all(void) | |||
593 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 604 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
594 | idset_fill(slow_subchannel_set); | 605 | idset_fill(slow_subchannel_set); |
595 | atomic_set(&css_eval_scheduled, 1); | 606 | atomic_set(&css_eval_scheduled, 1); |
596 | queue_work(cio_work_q, &slow_path_work); | 607 | queue_delayed_work(cio_work_q, &slow_path_work, 0); |
597 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 608 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
598 | } | 609 | } |
599 | 610 | ||
@@ -606,7 +617,7 @@ static int __unset_registered(struct device *dev, void *data) | |||
606 | return 0; | 617 | return 0; |
607 | } | 618 | } |
608 | 619 | ||
609 | static void css_schedule_eval_all_unreg(void) | 620 | void css_schedule_eval_all_unreg(unsigned long delay) |
610 | { | 621 | { |
611 | unsigned long flags; | 622 | unsigned long flags; |
612 | struct idset *unreg_set; | 623 | struct idset *unreg_set; |
@@ -624,7 +635,7 @@ static void css_schedule_eval_all_unreg(void) | |||
624 | spin_lock_irqsave(&slow_subchannel_lock, flags); | 635 | spin_lock_irqsave(&slow_subchannel_lock, flags); |
625 | idset_add_set(slow_subchannel_set, unreg_set); | 636 | idset_add_set(slow_subchannel_set, unreg_set); |
626 | atomic_set(&css_eval_scheduled, 1); | 637 | atomic_set(&css_eval_scheduled, 1); |
627 | queue_work(cio_work_q, &slow_path_work); | 638 | queue_delayed_work(cio_work_q, &slow_path_work, delay); |
628 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); | 639 | spin_unlock_irqrestore(&slow_subchannel_lock, flags); |
629 | idset_free(unreg_set); | 640 | idset_free(unreg_set); |
630 | } | 641 | } |
@@ -637,7 +648,8 @@ void css_wait_for_slow_path(void) | |||
637 | /* Schedule reprobing of all unregistered subchannels. */ | 648 | /* Schedule reprobing of all unregistered subchannels. */ |
638 | void css_schedule_reprobe(void) | 649 | void css_schedule_reprobe(void) |
639 | { | 650 | { |
640 | css_schedule_eval_all_unreg(); | 651 | /* Schedule with a delay to allow merging of subsequent calls. */ |
652 | css_schedule_eval_all_unreg(1 * HZ); | ||
641 | } | 653 | } |
642 | EXPORT_SYMBOL_GPL(css_schedule_reprobe); | 654 | EXPORT_SYMBOL_GPL(css_schedule_reprobe); |
643 | 655 | ||
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 29351321bad6..2c9107e20251 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -133,6 +133,7 @@ extern struct channel_subsystem *channel_subsystems[]; | |||
133 | /* Helper functions to build lists for the slow path. */ | 133 | /* Helper functions to build lists for the slow path. */ |
134 | void css_schedule_eval(struct subchannel_id schid); | 134 | void css_schedule_eval(struct subchannel_id schid); |
135 | void css_schedule_eval_all(void); | 135 | void css_schedule_eval_all(void); |
136 | void css_schedule_eval_all_unreg(unsigned long delay); | ||
136 | int css_complete_work(void); | 137 | int css_complete_work(void); |
137 | 138 | ||
138 | int sch_is_pseudo_sch(struct subchannel *); | 139 | int sch_is_pseudo_sch(struct subchannel *); |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index e4a7ab2bb629..e9d783563cbb 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -333,9 +333,9 @@ int ccw_device_set_offline(struct ccw_device *cdev) | |||
333 | if (ret != 0) | 333 | if (ret != 0) |
334 | return ret; | 334 | return ret; |
335 | } | 335 | } |
336 | cdev->online = 0; | ||
337 | spin_lock_irq(cdev->ccwlock); | 336 | spin_lock_irq(cdev->ccwlock); |
338 | sch = to_subchannel(cdev->dev.parent); | 337 | sch = to_subchannel(cdev->dev.parent); |
338 | cdev->online = 0; | ||
339 | /* Wait until a final state or DISCONNECTED is reached */ | 339 | /* Wait until a final state or DISCONNECTED is reached */ |
340 | while (!dev_fsm_final_state(cdev) && | 340 | while (!dev_fsm_final_state(cdev) && |
341 | cdev->private->state != DEV_STATE_DISCONNECTED) { | 341 | cdev->private->state != DEV_STATE_DISCONNECTED) { |
@@ -446,7 +446,10 @@ int ccw_device_set_online(struct ccw_device *cdev) | |||
446 | ret = cdev->drv->set_online(cdev); | 446 | ret = cdev->drv->set_online(cdev); |
447 | if (ret) | 447 | if (ret) |
448 | goto rollback; | 448 | goto rollback; |
449 | |||
450 | spin_lock_irq(cdev->ccwlock); | ||
449 | cdev->online = 1; | 451 | cdev->online = 1; |
452 | spin_unlock_irq(cdev->ccwlock); | ||
450 | return 0; | 453 | return 0; |
451 | 454 | ||
452 | rollback: | 455 | rollback: |
@@ -546,17 +549,12 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, | |||
546 | if (!dev_fsm_final_state(cdev) && | 549 | if (!dev_fsm_final_state(cdev) && |
547 | cdev->private->state != DEV_STATE_DISCONNECTED) { | 550 | cdev->private->state != DEV_STATE_DISCONNECTED) { |
548 | ret = -EAGAIN; | 551 | ret = -EAGAIN; |
549 | goto out_onoff; | 552 | goto out; |
550 | } | 553 | } |
551 | /* Prevent conflict between pending work and on-/offline processing.*/ | 554 | /* Prevent conflict between pending work and on-/offline processing.*/ |
552 | if (work_pending(&cdev->private->todo_work)) { | 555 | if (work_pending(&cdev->private->todo_work)) { |
553 | ret = -EAGAIN; | 556 | ret = -EAGAIN; |
554 | goto out_onoff; | 557 | goto out; |
555 | } | ||
556 | |||
557 | if (cdev->drv && !try_module_get(cdev->drv->driver.owner)) { | ||
558 | ret = -EINVAL; | ||
559 | goto out_onoff; | ||
560 | } | 558 | } |
561 | if (!strncmp(buf, "force\n", count)) { | 559 | if (!strncmp(buf, "force\n", count)) { |
562 | force = 1; | 560 | force = 1; |
@@ -568,6 +566,8 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, | |||
568 | } | 566 | } |
569 | if (ret) | 567 | if (ret) |
570 | goto out; | 568 | goto out; |
569 | |||
570 | device_lock(dev); | ||
571 | switch (i) { | 571 | switch (i) { |
572 | case 0: | 572 | case 0: |
573 | ret = online_store_handle_offline(cdev); | 573 | ret = online_store_handle_offline(cdev); |
@@ -578,10 +578,9 @@ static ssize_t online_store (struct device *dev, struct device_attribute *attr, | |||
578 | default: | 578 | default: |
579 | ret = -EINVAL; | 579 | ret = -EINVAL; |
580 | } | 580 | } |
581 | device_unlock(dev); | ||
582 | |||
581 | out: | 583 | out: |
582 | if (cdev->drv) | ||
583 | module_put(cdev->drv->driver.owner); | ||
584 | out_onoff: | ||
585 | atomic_set(&cdev->private->onoff, 0); | 584 | atomic_set(&cdev->private->onoff, 0); |
586 | return (ret < 0) ? ret : count; | 585 | return (ret < 0) ? ret : count; |
587 | } | 586 | } |
@@ -1745,8 +1744,7 @@ ccw_device_probe (struct device *dev) | |||
1745 | return 0; | 1744 | return 0; |
1746 | } | 1745 | } |
1747 | 1746 | ||
1748 | static int | 1747 | static int ccw_device_remove(struct device *dev) |
1749 | ccw_device_remove (struct device *dev) | ||
1750 | { | 1748 | { |
1751 | struct ccw_device *cdev = to_ccwdev(dev); | 1749 | struct ccw_device *cdev = to_ccwdev(dev); |
1752 | struct ccw_driver *cdrv = cdev->drv; | 1750 | struct ccw_driver *cdrv = cdev->drv; |
@@ -1754,9 +1752,10 @@ ccw_device_remove (struct device *dev) | |||
1754 | 1752 | ||
1755 | if (cdrv->remove) | 1753 | if (cdrv->remove) |
1756 | cdrv->remove(cdev); | 1754 | cdrv->remove(cdev); |
1755 | |||
1756 | spin_lock_irq(cdev->ccwlock); | ||
1757 | if (cdev->online) { | 1757 | if (cdev->online) { |
1758 | cdev->online = 0; | 1758 | cdev->online = 0; |
1759 | spin_lock_irq(cdev->ccwlock); | ||
1760 | ret = ccw_device_offline(cdev); | 1759 | ret = ccw_device_offline(cdev); |
1761 | spin_unlock_irq(cdev->ccwlock); | 1760 | spin_unlock_irq(cdev->ccwlock); |
1762 | if (ret == 0) | 1761 | if (ret == 0) |
@@ -1769,10 +1768,12 @@ ccw_device_remove (struct device *dev) | |||
1769 | cdev->private->dev_id.devno); | 1768 | cdev->private->dev_id.devno); |
1770 | /* Give up reference obtained in ccw_device_set_online(). */ | 1769 | /* Give up reference obtained in ccw_device_set_online(). */ |
1771 | put_device(&cdev->dev); | 1770 | put_device(&cdev->dev); |
1771 | spin_lock_irq(cdev->ccwlock); | ||
1772 | } | 1772 | } |
1773 | ccw_device_set_timeout(cdev, 0); | 1773 | ccw_device_set_timeout(cdev, 0); |
1774 | cdev->drv = NULL; | 1774 | cdev->drv = NULL; |
1775 | cdev->private->int_class = IRQIO_CIO; | 1775 | cdev->private->int_class = IRQIO_CIO; |
1776 | spin_unlock_irq(cdev->ccwlock); | ||
1776 | return 0; | 1777 | return 0; |
1777 | } | 1778 | } |
1778 | 1779 | ||
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 3e602e8affa7..c883a085c059 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -1752,6 +1752,97 @@ int qdio_stop_irq(struct ccw_device *cdev, int nr) | |||
1752 | } | 1752 | } |
1753 | EXPORT_SYMBOL(qdio_stop_irq); | 1753 | EXPORT_SYMBOL(qdio_stop_irq); |
1754 | 1754 | ||
1755 | /** | ||
1756 | * qdio_pnso_brinfo() - perform network subchannel op #0 - bridge info. | ||
1757 | * @schid: Subchannel ID. | ||
1758 | * @cnc: Boolean Change-Notification Control | ||
1759 | * @response: Response code will be stored at this address | ||
1760 | * @cb: Callback function will be executed for each element | ||
1761 | * of the address list | ||
1762 | * @priv: Pointer passed from the caller to qdio_pnso_brinfo() | ||
1763 | * @type: Type of the address entry passed to the callback | ||
1764 | * @entry: Entry containg the address of the specified type | ||
1765 | * @priv: Pointer to pass to the callback function. | ||
1766 | * | ||
1767 | * Performs "Store-network-bridging-information list" operation and calls | ||
1768 | * the callback function for every entry in the list. If "change- | ||
1769 | * notification-control" is set, further changes in the address list | ||
1770 | * will be reported via the IPA command. | ||
1771 | */ | ||
1772 | int qdio_pnso_brinfo(struct subchannel_id schid, | ||
1773 | int cnc, u16 *response, | ||
1774 | void (*cb)(void *priv, enum qdio_brinfo_entry_type type, | ||
1775 | void *entry), | ||
1776 | void *priv) | ||
1777 | { | ||
1778 | struct chsc_pnso_area *rr; | ||
1779 | int rc; | ||
1780 | u32 prev_instance = 0; | ||
1781 | int isfirstblock = 1; | ||
1782 | int i, size, elems; | ||
1783 | |||
1784 | rr = (struct chsc_pnso_area *)get_zeroed_page(GFP_KERNEL); | ||
1785 | if (rr == NULL) | ||
1786 | return -ENOMEM; | ||
1787 | do { | ||
1788 | /* on the first iteration, naihdr.resume_token will be zero */ | ||
1789 | rc = chsc_pnso_brinfo(schid, rr, rr->naihdr.resume_token, cnc); | ||
1790 | if (rc != 0 && rc != -EBUSY) | ||
1791 | goto out; | ||
1792 | if (rr->response.code != 1) { | ||
1793 | rc = -EIO; | ||
1794 | continue; | ||
1795 | } else | ||
1796 | rc = 0; | ||
1797 | |||
1798 | if (cb == NULL) | ||
1799 | continue; | ||
1800 | |||
1801 | size = rr->naihdr.naids; | ||
1802 | elems = (rr->response.length - | ||
1803 | sizeof(struct chsc_header) - | ||
1804 | sizeof(struct chsc_brinfo_naihdr)) / | ||
1805 | size; | ||
1806 | |||
1807 | if (!isfirstblock && (rr->naihdr.instance != prev_instance)) { | ||
1808 | /* Inform the caller that they need to scrap */ | ||
1809 | /* the data that was already reported via cb */ | ||
1810 | rc = -EAGAIN; | ||
1811 | break; | ||
1812 | } | ||
1813 | isfirstblock = 0; | ||
1814 | prev_instance = rr->naihdr.instance; | ||
1815 | for (i = 0; i < elems; i++) | ||
1816 | switch (size) { | ||
1817 | case sizeof(struct qdio_brinfo_entry_l3_ipv6): | ||
1818 | (*cb)(priv, l3_ipv6_addr, | ||
1819 | &rr->entries.l3_ipv6[i]); | ||
1820 | break; | ||
1821 | case sizeof(struct qdio_brinfo_entry_l3_ipv4): | ||
1822 | (*cb)(priv, l3_ipv4_addr, | ||
1823 | &rr->entries.l3_ipv4[i]); | ||
1824 | break; | ||
1825 | case sizeof(struct qdio_brinfo_entry_l2): | ||
1826 | (*cb)(priv, l2_addr_lnid, | ||
1827 | &rr->entries.l2[i]); | ||
1828 | break; | ||
1829 | default: | ||
1830 | WARN_ON_ONCE(1); | ||
1831 | rc = -EIO; | ||
1832 | goto out; | ||
1833 | } | ||
1834 | } while (rr->response.code == 0x0107 || /* channel busy */ | ||
1835 | (rr->response.code == 1 && /* list stored */ | ||
1836 | /* resume token is non-zero => list incomplete */ | ||
1837 | (rr->naihdr.resume_token.t1 || rr->naihdr.resume_token.t2))); | ||
1838 | (*response) = rr->response.code; | ||
1839 | |||
1840 | out: | ||
1841 | free_page((unsigned long)rr); | ||
1842 | return rc; | ||
1843 | } | ||
1844 | EXPORT_SYMBOL_GPL(qdio_pnso_brinfo); | ||
1845 | |||
1755 | static int __init init_QDIO(void) | 1846 | static int __init init_QDIO(void) |
1756 | { | 1847 | { |
1757 | int rc; | 1848 | int rc; |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 02300dcfac91..ab3baa7f9508 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -591,7 +591,13 @@ static int ap_init_queue(ap_qid_t qid) | |||
591 | if (rc != -ENODEV && rc != -EBUSY) | 591 | if (rc != -ENODEV && rc != -EBUSY) |
592 | break; | 592 | break; |
593 | if (i < AP_MAX_RESET - 1) { | 593 | if (i < AP_MAX_RESET - 1) { |
594 | udelay(5); | 594 | /* Time we are waiting until we give up (0.7sec * 90). |
595 | * Since the actual request (in progress) will not | ||
596 | * interrupted immediately for the reset command, | ||
597 | * we have to be patient. In worst case we have to | ||
598 | * wait 60sec + reset time (some msec). | ||
599 | */ | ||
600 | schedule_timeout(AP_RESET_TIMEOUT); | ||
595 | status = ap_test_queue(qid, &dummy, &dummy); | 601 | status = ap_test_queue(qid, &dummy, &dummy); |
596 | } | 602 | } |
597 | } | 603 | } |
@@ -992,6 +998,28 @@ static ssize_t ap_domain_show(struct bus_type *bus, char *buf) | |||
992 | 998 | ||
993 | static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL); | 999 | static BUS_ATTR(ap_domain, 0444, ap_domain_show, NULL); |
994 | 1000 | ||
1001 | static ssize_t ap_control_domain_mask_show(struct bus_type *bus, char *buf) | ||
1002 | { | ||
1003 | if (ap_configuration != NULL) { /* QCI not supported */ | ||
1004 | if (test_facility(76)) { /* format 1 - 256 bit domain field */ | ||
1005 | return snprintf(buf, PAGE_SIZE, | ||
1006 | "0x%08x%08x%08x%08x%08x%08x%08x%08x\n", | ||
1007 | ap_configuration->adm[0], ap_configuration->adm[1], | ||
1008 | ap_configuration->adm[2], ap_configuration->adm[3], | ||
1009 | ap_configuration->adm[4], ap_configuration->adm[5], | ||
1010 | ap_configuration->adm[6], ap_configuration->adm[7]); | ||
1011 | } else { /* format 0 - 16 bit domain field */ | ||
1012 | return snprintf(buf, PAGE_SIZE, "%08x%08x\n", | ||
1013 | ap_configuration->adm[0], ap_configuration->adm[1]); | ||
1014 | } | ||
1015 | } else { | ||
1016 | return snprintf(buf, PAGE_SIZE, "not supported\n"); | ||
1017 | } | ||
1018 | } | ||
1019 | |||
1020 | static BUS_ATTR(ap_control_domain_mask, 0444, | ||
1021 | ap_control_domain_mask_show, NULL); | ||
1022 | |||
995 | static ssize_t ap_config_time_show(struct bus_type *bus, char *buf) | 1023 | static ssize_t ap_config_time_show(struct bus_type *bus, char *buf) |
996 | { | 1024 | { |
997 | return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time); | 1025 | return snprintf(buf, PAGE_SIZE, "%d\n", ap_config_time); |
@@ -1077,6 +1105,7 @@ static BUS_ATTR(poll_timeout, 0644, poll_timeout_show, poll_timeout_store); | |||
1077 | 1105 | ||
1078 | static struct bus_attribute *const ap_bus_attrs[] = { | 1106 | static struct bus_attribute *const ap_bus_attrs[] = { |
1079 | &bus_attr_ap_domain, | 1107 | &bus_attr_ap_domain, |
1108 | &bus_attr_ap_control_domain_mask, | ||
1080 | &bus_attr_config_time, | 1109 | &bus_attr_config_time, |
1081 | &bus_attr_poll_thread, | 1110 | &bus_attr_poll_thread, |
1082 | &bus_attr_ap_interrupts, | 1111 | &bus_attr_ap_interrupts, |
diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 685f6cc022f9..6405ae24a7a6 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h | |||
@@ -33,7 +33,7 @@ | |||
33 | #define AP_DEVICES 64 /* Number of AP devices. */ | 33 | #define AP_DEVICES 64 /* Number of AP devices. */ |
34 | #define AP_DOMAINS 16 /* Number of AP domains. */ | 34 | #define AP_DOMAINS 16 /* Number of AP domains. */ |
35 | #define AP_MAX_RESET 90 /* Maximum number of resets. */ | 35 | #define AP_MAX_RESET 90 /* Maximum number of resets. */ |
36 | #define AP_RESET_TIMEOUT (HZ/2) /* Time in ticks for reset timeouts. */ | 36 | #define AP_RESET_TIMEOUT (HZ*0.7) /* Time in ticks for reset timeouts. */ |
37 | #define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */ | 37 | #define AP_CONFIG_TIME 30 /* Time in seconds between AP bus rescans. */ |
38 | #define AP_POLL_TIME 1 /* Time in ticks between receive polls. */ | 38 | #define AP_POLL_TIME 1 /* Time in ticks between receive polls. */ |
39 | 39 | ||
@@ -125,6 +125,8 @@ static inline int ap_test_bit(unsigned int *ptr, unsigned int nr) | |||
125 | #define AP_FUNC_CRT4K 2 | 125 | #define AP_FUNC_CRT4K 2 |
126 | #define AP_FUNC_COPRO 3 | 126 | #define AP_FUNC_COPRO 3 |
127 | #define AP_FUNC_ACCEL 4 | 127 | #define AP_FUNC_ACCEL 4 |
128 | #define AP_FUNC_EP11 5 | ||
129 | #define AP_FUNC_APXA 6 | ||
128 | 130 | ||
129 | /* | 131 | /* |
130 | * AP reset flag states | 132 | * AP reset flag states |
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 31cfaa556072..4b824b15194f 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
@@ -44,6 +44,8 @@ | |||
44 | #include "zcrypt_debug.h" | 44 | #include "zcrypt_debug.h" |
45 | #include "zcrypt_api.h" | 45 | #include "zcrypt_api.h" |
46 | 46 | ||
47 | #include "zcrypt_msgtype6.h" | ||
48 | |||
47 | /* | 49 | /* |
48 | * Module description. | 50 | * Module description. |
49 | */ | 51 | */ |
@@ -554,9 +556,9 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) | |||
554 | spin_lock_bh(&zcrypt_device_lock); | 556 | spin_lock_bh(&zcrypt_device_lock); |
555 | list_for_each_entry(zdev, &zcrypt_device_list, list) { | 557 | list_for_each_entry(zdev, &zcrypt_device_list, list) { |
556 | if (!zdev->online || !zdev->ops->send_cprb || | 558 | if (!zdev->online || !zdev->ops->send_cprb || |
557 | (xcRB->user_defined != AUTOSELECT && | 559 | (zdev->ops->variant == MSGTYPE06_VARIANT_EP11) || |
558 | AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined) | 560 | (xcRB->user_defined != AUTOSELECT && |
559 | ) | 561 | AP_QID_DEVICE(zdev->ap_dev->qid) != xcRB->user_defined)) |
560 | continue; | 562 | continue; |
561 | zcrypt_device_get(zdev); | 563 | zcrypt_device_get(zdev); |
562 | get_device(&zdev->ap_dev->device); | 564 | get_device(&zdev->ap_dev->device); |
@@ -581,6 +583,90 @@ static long zcrypt_send_cprb(struct ica_xcRB *xcRB) | |||
581 | return -ENODEV; | 583 | return -ENODEV; |
582 | } | 584 | } |
583 | 585 | ||
586 | struct ep11_target_dev_list { | ||
587 | unsigned short targets_num; | ||
588 | struct ep11_target_dev *targets; | ||
589 | }; | ||
590 | |||
591 | static bool is_desired_ep11dev(unsigned int dev_qid, | ||
592 | struct ep11_target_dev_list dev_list) | ||
593 | { | ||
594 | int n; | ||
595 | |||
596 | for (n = 0; n < dev_list.targets_num; n++, dev_list.targets++) { | ||
597 | if ((AP_QID_DEVICE(dev_qid) == dev_list.targets->ap_id) && | ||
598 | (AP_QID_QUEUE(dev_qid) == dev_list.targets->dom_id)) { | ||
599 | return true; | ||
600 | } | ||
601 | } | ||
602 | return false; | ||
603 | } | ||
604 | |||
605 | static long zcrypt_send_ep11_cprb(struct ep11_urb *xcrb) | ||
606 | { | ||
607 | struct zcrypt_device *zdev; | ||
608 | bool autoselect = false; | ||
609 | int rc; | ||
610 | struct ep11_target_dev_list ep11_dev_list = { | ||
611 | .targets_num = 0x00, | ||
612 | .targets = NULL, | ||
613 | }; | ||
614 | |||
615 | ep11_dev_list.targets_num = (unsigned short) xcrb->targets_num; | ||
616 | |||
617 | /* empty list indicates autoselect (all available targets) */ | ||
618 | if (ep11_dev_list.targets_num == 0) | ||
619 | autoselect = true; | ||
620 | else { | ||
621 | ep11_dev_list.targets = kcalloc((unsigned short) | ||
622 | xcrb->targets_num, | ||
623 | sizeof(struct ep11_target_dev), | ||
624 | GFP_KERNEL); | ||
625 | if (!ep11_dev_list.targets) | ||
626 | return -ENOMEM; | ||
627 | |||
628 | if (copy_from_user(ep11_dev_list.targets, | ||
629 | (struct ep11_target_dev *)xcrb->targets, | ||
630 | xcrb->targets_num * | ||
631 | sizeof(struct ep11_target_dev))) | ||
632 | return -EFAULT; | ||
633 | } | ||
634 | |||
635 | spin_lock_bh(&zcrypt_device_lock); | ||
636 | list_for_each_entry(zdev, &zcrypt_device_list, list) { | ||
637 | /* check if device is eligible */ | ||
638 | if (!zdev->online || | ||
639 | zdev->ops->variant != MSGTYPE06_VARIANT_EP11) | ||
640 | continue; | ||
641 | |||
642 | /* check if device is selected as valid target */ | ||
643 | if (!is_desired_ep11dev(zdev->ap_dev->qid, ep11_dev_list) && | ||
644 | !autoselect) | ||
645 | continue; | ||
646 | |||
647 | zcrypt_device_get(zdev); | ||
648 | get_device(&zdev->ap_dev->device); | ||
649 | zdev->request_count++; | ||
650 | __zcrypt_decrease_preference(zdev); | ||
651 | if (try_module_get(zdev->ap_dev->drv->driver.owner)) { | ||
652 | spin_unlock_bh(&zcrypt_device_lock); | ||
653 | rc = zdev->ops->send_ep11_cprb(zdev, xcrb); | ||
654 | spin_lock_bh(&zcrypt_device_lock); | ||
655 | module_put(zdev->ap_dev->drv->driver.owner); | ||
656 | } else { | ||
657 | rc = -EAGAIN; | ||
658 | } | ||
659 | zdev->request_count--; | ||
660 | __zcrypt_increase_preference(zdev); | ||
661 | put_device(&zdev->ap_dev->device); | ||
662 | zcrypt_device_put(zdev); | ||
663 | spin_unlock_bh(&zcrypt_device_lock); | ||
664 | return rc; | ||
665 | } | ||
666 | spin_unlock_bh(&zcrypt_device_lock); | ||
667 | return -ENODEV; | ||
668 | } | ||
669 | |||
584 | static long zcrypt_rng(char *buffer) | 670 | static long zcrypt_rng(char *buffer) |
585 | { | 671 | { |
586 | struct zcrypt_device *zdev; | 672 | struct zcrypt_device *zdev; |
@@ -784,6 +870,23 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, | |||
784 | return -EFAULT; | 870 | return -EFAULT; |
785 | return rc; | 871 | return rc; |
786 | } | 872 | } |
873 | case ZSENDEP11CPRB: { | ||
874 | struct ep11_urb __user *uxcrb = (void __user *)arg; | ||
875 | struct ep11_urb xcrb; | ||
876 | if (copy_from_user(&xcrb, uxcrb, sizeof(xcrb))) | ||
877 | return -EFAULT; | ||
878 | do { | ||
879 | rc = zcrypt_send_ep11_cprb(&xcrb); | ||
880 | } while (rc == -EAGAIN); | ||
881 | /* on failure: retry once again after a requested rescan */ | ||
882 | if ((rc == -ENODEV) && (zcrypt_process_rescan())) | ||
883 | do { | ||
884 | rc = zcrypt_send_ep11_cprb(&xcrb); | ||
885 | } while (rc == -EAGAIN); | ||
886 | if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb))) | ||
887 | return -EFAULT; | ||
888 | return rc; | ||
889 | } | ||
787 | case Z90STAT_STATUS_MASK: { | 890 | case Z90STAT_STATUS_MASK: { |
788 | char status[AP_DEVICES]; | 891 | char status[AP_DEVICES]; |
789 | zcrypt_status_mask(status); | 892 | zcrypt_status_mask(status); |
diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index 89632919c993..b3d496bfaa7e 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h | |||
@@ -74,6 +74,7 @@ struct ica_z90_status { | |||
74 | #define ZCRYPT_CEX2A 6 | 74 | #define ZCRYPT_CEX2A 6 |
75 | #define ZCRYPT_CEX3C 7 | 75 | #define ZCRYPT_CEX3C 7 |
76 | #define ZCRYPT_CEX3A 8 | 76 | #define ZCRYPT_CEX3A 8 |
77 | #define ZCRYPT_CEX4 10 | ||
77 | 78 | ||
78 | /** | 79 | /** |
79 | * Large random numbers are pulled in 4096 byte chunks from the crypto cards | 80 | * Large random numbers are pulled in 4096 byte chunks from the crypto cards |
@@ -89,6 +90,7 @@ struct zcrypt_ops { | |||
89 | long (*rsa_modexpo_crt)(struct zcrypt_device *, | 90 | long (*rsa_modexpo_crt)(struct zcrypt_device *, |
90 | struct ica_rsa_modexpo_crt *); | 91 | struct ica_rsa_modexpo_crt *); |
91 | long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *); | 92 | long (*send_cprb)(struct zcrypt_device *, struct ica_xcRB *); |
93 | long (*send_ep11_cprb)(struct zcrypt_device *, struct ep11_urb *); | ||
92 | long (*rng)(struct zcrypt_device *, char *); | 94 | long (*rng)(struct zcrypt_device *, char *); |
93 | struct list_head list; /* zcrypt ops list. */ | 95 | struct list_head list; /* zcrypt ops list. */ |
94 | struct module *owner; | 96 | struct module *owner; |
diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c index ce1226398ac9..569f8b1d86c0 100644 --- a/drivers/s390/crypto/zcrypt_cex4.c +++ b/drivers/s390/crypto/zcrypt_cex4.c | |||
@@ -30,7 +30,12 @@ | |||
30 | #define CEX4A_MAX_MESSAGE_SIZE MSGTYPE50_CRB3_MAX_MSG_SIZE | 30 | #define CEX4A_MAX_MESSAGE_SIZE MSGTYPE50_CRB3_MAX_MSG_SIZE |
31 | #define CEX4C_MAX_MESSAGE_SIZE MSGTYPE06_MAX_MSG_SIZE | 31 | #define CEX4C_MAX_MESSAGE_SIZE MSGTYPE06_MAX_MSG_SIZE |
32 | 32 | ||
33 | #define CEX4_CLEANUP_TIME (15*HZ) | 33 | /* Waiting time for requests to be processed. |
34 | * Currently there are some types of request which are not deterministic. | ||
35 | * But the maximum time limit managed by the stomper code is set to 60sec. | ||
36 | * Hence we have to wait at least that time period. | ||
37 | */ | ||
38 | #define CEX4_CLEANUP_TIME (61*HZ) | ||
34 | 39 | ||
35 | static struct ap_device_id zcrypt_cex4_ids[] = { | 40 | static struct ap_device_id zcrypt_cex4_ids[] = { |
36 | { AP_DEVICE(AP_DEVICE_TYPE_CEX4) }, | 41 | { AP_DEVICE(AP_DEVICE_TYPE_CEX4) }, |
@@ -101,6 +106,19 @@ static int zcrypt_cex4_probe(struct ap_device *ap_dev) | |||
101 | zdev->speed_rating = CEX4C_SPEED_RATING; | 106 | zdev->speed_rating = CEX4C_SPEED_RATING; |
102 | zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, | 107 | zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, |
103 | MSGTYPE06_VARIANT_DEFAULT); | 108 | MSGTYPE06_VARIANT_DEFAULT); |
109 | } else if (ap_test_bit(&ap_dev->functions, AP_FUNC_EP11)) { | ||
110 | zdev = zcrypt_device_alloc(CEX4C_MAX_MESSAGE_SIZE); | ||
111 | if (!zdev) | ||
112 | return -ENOMEM; | ||
113 | zdev->type_string = "CEX4P"; | ||
114 | zdev->user_space_type = ZCRYPT_CEX4; | ||
115 | zdev->min_mod_size = CEX4C_MIN_MOD_SIZE; | ||
116 | zdev->max_mod_size = CEX4C_MAX_MOD_SIZE; | ||
117 | zdev->max_exp_bit_length = CEX4C_MAX_MOD_SIZE; | ||
118 | zdev->short_crt = 0; | ||
119 | zdev->speed_rating = CEX4C_SPEED_RATING; | ||
120 | zdev->ops = zcrypt_msgtype_request(MSGTYPE06_NAME, | ||
121 | MSGTYPE06_VARIANT_EP11); | ||
104 | } | 122 | } |
105 | break; | 123 | break; |
106 | } | 124 | } |
diff --git a/drivers/s390/crypto/zcrypt_error.h b/drivers/s390/crypto/zcrypt_error.h index 0079b6617211..7b23f43c7b08 100644 --- a/drivers/s390/crypto/zcrypt_error.h +++ b/drivers/s390/crypto/zcrypt_error.h | |||
@@ -106,15 +106,15 @@ static inline int convert_error(struct zcrypt_device *zdev, | |||
106 | // REP88_ERROR_MESSAGE_TYPE // '20' CEX2A | 106 | // REP88_ERROR_MESSAGE_TYPE // '20' CEX2A |
107 | /* | 107 | /* |
108 | * To sent a message of the wrong type is a bug in the | 108 | * To sent a message of the wrong type is a bug in the |
109 | * device driver. Warn about it, disable the device | 109 | * device driver. Send error msg, disable the device |
110 | * and then repeat the request. | 110 | * and then repeat the request. |
111 | */ | 111 | */ |
112 | WARN_ON(1); | ||
113 | atomic_set(&zcrypt_rescan_req, 1); | 112 | atomic_set(&zcrypt_rescan_req, 1); |
114 | zdev->online = 0; | 113 | zdev->online = 0; |
114 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
115 | zdev->ap_dev->qid); | ||
115 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | 116 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", |
116 | zdev->ap_dev->qid, | 117 | zdev->ap_dev->qid, zdev->online, ehdr->reply_code); |
117 | zdev->online, ehdr->reply_code); | ||
118 | return -EAGAIN; | 118 | return -EAGAIN; |
119 | case REP82_ERROR_TRANSPORT_FAIL: | 119 | case REP82_ERROR_TRANSPORT_FAIL: |
120 | case REP82_ERROR_MACHINE_FAILURE: | 120 | case REP82_ERROR_MACHINE_FAILURE: |
@@ -122,15 +122,17 @@ static inline int convert_error(struct zcrypt_device *zdev, | |||
122 | /* If a card fails disable it and repeat the request. */ | 122 | /* If a card fails disable it and repeat the request. */ |
123 | atomic_set(&zcrypt_rescan_req, 1); | 123 | atomic_set(&zcrypt_rescan_req, 1); |
124 | zdev->online = 0; | 124 | zdev->online = 0; |
125 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
126 | zdev->ap_dev->qid); | ||
125 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | 127 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", |
126 | zdev->ap_dev->qid, | 128 | zdev->ap_dev->qid, zdev->online, ehdr->reply_code); |
127 | zdev->online, ehdr->reply_code); | ||
128 | return -EAGAIN; | 129 | return -EAGAIN; |
129 | default: | 130 | default: |
130 | zdev->online = 0; | 131 | zdev->online = 0; |
132 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
133 | zdev->ap_dev->qid); | ||
131 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | 134 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", |
132 | zdev->ap_dev->qid, | 135 | zdev->ap_dev->qid, zdev->online, ehdr->reply_code); |
133 | zdev->online, ehdr->reply_code); | ||
134 | return -EAGAIN; /* repeat the request on a different device. */ | 136 | return -EAGAIN; /* repeat the request on a different device. */ |
135 | } | 137 | } |
136 | } | 138 | } |
diff --git a/drivers/s390/crypto/zcrypt_msgtype50.c b/drivers/s390/crypto/zcrypt_msgtype50.c index 7c522f338bda..334e282f255b 100644 --- a/drivers/s390/crypto/zcrypt_msgtype50.c +++ b/drivers/s390/crypto/zcrypt_msgtype50.c | |||
@@ -25,6 +25,9 @@ | |||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #define KMSG_COMPONENT "zcrypt" | ||
29 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
30 | |||
28 | #include <linux/module.h> | 31 | #include <linux/module.h> |
29 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
30 | #include <linux/init.h> | 33 | #include <linux/init.h> |
@@ -332,6 +335,11 @@ static int convert_type80(struct zcrypt_device *zdev, | |||
332 | if (t80h->len < sizeof(*t80h) + outputdatalength) { | 335 | if (t80h->len < sizeof(*t80h) + outputdatalength) { |
333 | /* The result is too short, the CEX2A card may not do that.. */ | 336 | /* The result is too short, the CEX2A card may not do that.. */ |
334 | zdev->online = 0; | 337 | zdev->online = 0; |
338 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
339 | zdev->ap_dev->qid); | ||
340 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | ||
341 | zdev->ap_dev->qid, zdev->online, t80h->code); | ||
342 | |||
335 | return -EAGAIN; /* repeat the request on a different device. */ | 343 | return -EAGAIN; /* repeat the request on a different device. */ |
336 | } | 344 | } |
337 | if (zdev->user_space_type == ZCRYPT_CEX2A) | 345 | if (zdev->user_space_type == ZCRYPT_CEX2A) |
@@ -359,6 +367,10 @@ static int convert_response(struct zcrypt_device *zdev, | |||
359 | outputdata, outputdatalength); | 367 | outputdata, outputdatalength); |
360 | default: /* Unknown response type, this should NEVER EVER happen */ | 368 | default: /* Unknown response type, this should NEVER EVER happen */ |
361 | zdev->online = 0; | 369 | zdev->online = 0; |
370 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
371 | zdev->ap_dev->qid); | ||
372 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
373 | zdev->ap_dev->qid, zdev->online); | ||
362 | return -EAGAIN; /* repeat the request on a different device. */ | 374 | return -EAGAIN; /* repeat the request on a different device. */ |
363 | } | 375 | } |
364 | } | 376 | } |
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.c b/drivers/s390/crypto/zcrypt_msgtype6.c index 7d97fa5a26d0..dc542e0a3055 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.c +++ b/drivers/s390/crypto/zcrypt_msgtype6.c | |||
@@ -25,6 +25,9 @@ | |||
25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 25 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #define KMSG_COMPONENT "zcrypt" | ||
29 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
30 | |||
28 | #include <linux/module.h> | 31 | #include <linux/module.h> |
29 | #include <linux/init.h> | 32 | #include <linux/init.h> |
30 | #include <linux/err.h> | 33 | #include <linux/err.h> |
@@ -50,6 +53,7 @@ struct response_type { | |||
50 | }; | 53 | }; |
51 | #define PCIXCC_RESPONSE_TYPE_ICA 0 | 54 | #define PCIXCC_RESPONSE_TYPE_ICA 0 |
52 | #define PCIXCC_RESPONSE_TYPE_XCRB 1 | 55 | #define PCIXCC_RESPONSE_TYPE_XCRB 1 |
56 | #define PCIXCC_RESPONSE_TYPE_EP11 2 | ||
53 | 57 | ||
54 | MODULE_AUTHOR("IBM Corporation"); | 58 | MODULE_AUTHOR("IBM Corporation"); |
55 | MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \ | 59 | MODULE_DESCRIPTION("Cryptographic Coprocessor (message type 6), " \ |
@@ -358,6 +362,91 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, | |||
358 | return 0; | 362 | return 0; |
359 | } | 363 | } |
360 | 364 | ||
365 | static int xcrb_msg_to_type6_ep11cprb_msgx(struct zcrypt_device *zdev, | ||
366 | struct ap_message *ap_msg, | ||
367 | struct ep11_urb *xcRB) | ||
368 | { | ||
369 | unsigned int lfmt; | ||
370 | |||
371 | static struct type6_hdr static_type6_ep11_hdr = { | ||
372 | .type = 0x06, | ||
373 | .rqid = {0x00, 0x01}, | ||
374 | .function_code = {0x00, 0x00}, | ||
375 | .agent_id[0] = 0x58, /* {'X'} */ | ||
376 | .agent_id[1] = 0x43, /* {'C'} */ | ||
377 | .offset1 = 0x00000058, | ||
378 | }; | ||
379 | |||
380 | struct { | ||
381 | struct type6_hdr hdr; | ||
382 | struct ep11_cprb cprbx; | ||
383 | unsigned char pld_tag; /* fixed value 0x30 */ | ||
384 | unsigned char pld_lenfmt; /* payload length format */ | ||
385 | } __packed * msg = ap_msg->message; | ||
386 | |||
387 | struct pld_hdr { | ||
388 | unsigned char func_tag; /* fixed value 0x4 */ | ||
389 | unsigned char func_len; /* fixed value 0x4 */ | ||
390 | unsigned int func_val; /* function ID */ | ||
391 | unsigned char dom_tag; /* fixed value 0x4 */ | ||
392 | unsigned char dom_len; /* fixed value 0x4 */ | ||
393 | unsigned int dom_val; /* domain id */ | ||
394 | } __packed * payload_hdr; | ||
395 | |||
396 | /* length checks */ | ||
397 | ap_msg->length = sizeof(struct type6_hdr) + xcRB->req_len; | ||
398 | if (CEIL4(xcRB->req_len) > MSGTYPE06_MAX_MSG_SIZE - | ||
399 | (sizeof(struct type6_hdr))) | ||
400 | return -EINVAL; | ||
401 | |||
402 | if (CEIL4(xcRB->resp_len) > MSGTYPE06_MAX_MSG_SIZE - | ||
403 | (sizeof(struct type86_fmt2_msg))) | ||
404 | return -EINVAL; | ||
405 | |||
406 | /* prepare type6 header */ | ||
407 | msg->hdr = static_type6_ep11_hdr; | ||
408 | msg->hdr.ToCardLen1 = xcRB->req_len; | ||
409 | msg->hdr.FromCardLen1 = xcRB->resp_len; | ||
410 | |||
411 | /* Import CPRB data from the ioctl input parameter */ | ||
412 | if (copy_from_user(&(msg->cprbx.cprb_len), | ||
413 | (char *)xcRB->req, xcRB->req_len)) { | ||
414 | return -EFAULT; | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | The target domain field within the cprb body/payload block will be | ||
419 | replaced by the usage domain for non-management commands only. | ||
420 | Therefore we check the first bit of the 'flags' parameter for | ||
421 | management command indication. | ||
422 | 0 - non management command | ||
423 | 1 - management command | ||
424 | */ | ||
425 | if (!((msg->cprbx.flags & 0x80) == 0x80)) { | ||
426 | msg->cprbx.target_id = (unsigned int) | ||
427 | AP_QID_QUEUE(zdev->ap_dev->qid); | ||
428 | |||
429 | if ((msg->pld_lenfmt & 0x80) == 0x80) { /*ext.len.fmt 2 or 3*/ | ||
430 | switch (msg->pld_lenfmt & 0x03) { | ||
431 | case 1: | ||
432 | lfmt = 2; | ||
433 | break; | ||
434 | case 2: | ||
435 | lfmt = 3; | ||
436 | break; | ||
437 | default: | ||
438 | return -EINVAL; | ||
439 | } | ||
440 | } else { | ||
441 | lfmt = 1; /* length format #1 */ | ||
442 | } | ||
443 | payload_hdr = (struct pld_hdr *)((&(msg->pld_lenfmt))+lfmt); | ||
444 | payload_hdr->dom_val = (unsigned int) | ||
445 | AP_QID_QUEUE(zdev->ap_dev->qid); | ||
446 | } | ||
447 | return 0; | ||
448 | } | ||
449 | |||
361 | /** | 450 | /** |
362 | * Copy results from a type 86 ICA reply message back to user space. | 451 | * Copy results from a type 86 ICA reply message back to user space. |
363 | * | 452 | * |
@@ -377,6 +466,12 @@ struct type86x_reply { | |||
377 | char text[0]; | 466 | char text[0]; |
378 | } __packed; | 467 | } __packed; |
379 | 468 | ||
469 | struct type86_ep11_reply { | ||
470 | struct type86_hdr hdr; | ||
471 | struct type86_fmt2_ext fmt2; | ||
472 | struct ep11_cprb cprbx; | ||
473 | } __packed; | ||
474 | |||
380 | static int convert_type86_ica(struct zcrypt_device *zdev, | 475 | static int convert_type86_ica(struct zcrypt_device *zdev, |
381 | struct ap_message *reply, | 476 | struct ap_message *reply, |
382 | char __user *outputdata, | 477 | char __user *outputdata, |
@@ -440,6 +535,11 @@ static int convert_type86_ica(struct zcrypt_device *zdev, | |||
440 | if (service_rc == 8 && service_rs == 72) | 535 | if (service_rc == 8 && service_rs == 72) |
441 | return -EINVAL; | 536 | return -EINVAL; |
442 | zdev->online = 0; | 537 | zdev->online = 0; |
538 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
539 | zdev->ap_dev->qid); | ||
540 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | ||
541 | zdev->ap_dev->qid, zdev->online, | ||
542 | msg->hdr.reply_code); | ||
443 | return -EAGAIN; /* repeat the request on a different device. */ | 543 | return -EAGAIN; /* repeat the request on a different device. */ |
444 | } | 544 | } |
445 | data = msg->text; | 545 | data = msg->text; |
@@ -503,6 +603,33 @@ static int convert_type86_xcrb(struct zcrypt_device *zdev, | |||
503 | return 0; | 603 | return 0; |
504 | } | 604 | } |
505 | 605 | ||
606 | /** | ||
607 | * Copy results from a type 86 EP11 XCRB reply message back to user space. | ||
608 | * | ||
609 | * @zdev: crypto device pointer | ||
610 | * @reply: reply AP message. | ||
611 | * @xcRB: pointer to EP11 user request block | ||
612 | * | ||
613 | * Returns 0 on success or -EINVAL, -EFAULT, -EAGAIN in case of an error. | ||
614 | */ | ||
615 | static int convert_type86_ep11_xcrb(struct zcrypt_device *zdev, | ||
616 | struct ap_message *reply, | ||
617 | struct ep11_urb *xcRB) | ||
618 | { | ||
619 | struct type86_fmt2_msg *msg = reply->message; | ||
620 | char *data = reply->message; | ||
621 | |||
622 | if (xcRB->resp_len < msg->fmt2.count1) | ||
623 | return -EINVAL; | ||
624 | |||
625 | /* Copy response CPRB to user */ | ||
626 | if (copy_to_user((char *)xcRB->resp, | ||
627 | data + msg->fmt2.offset1, msg->fmt2.count1)) | ||
628 | return -EFAULT; | ||
629 | xcRB->resp_len = msg->fmt2.count1; | ||
630 | return 0; | ||
631 | } | ||
632 | |||
506 | static int convert_type86_rng(struct zcrypt_device *zdev, | 633 | static int convert_type86_rng(struct zcrypt_device *zdev, |
507 | struct ap_message *reply, | 634 | struct ap_message *reply, |
508 | char *buffer) | 635 | char *buffer) |
@@ -551,6 +678,10 @@ static int convert_response_ica(struct zcrypt_device *zdev, | |||
551 | * response */ | 678 | * response */ |
552 | default: /* Unknown response type, this should NEVER EVER happen */ | 679 | default: /* Unknown response type, this should NEVER EVER happen */ |
553 | zdev->online = 0; | 680 | zdev->online = 0; |
681 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
682 | zdev->ap_dev->qid); | ||
683 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
684 | zdev->ap_dev->qid, zdev->online); | ||
554 | return -EAGAIN; /* repeat the request on a different device. */ | 685 | return -EAGAIN; /* repeat the request on a different device. */ |
555 | } | 686 | } |
556 | } | 687 | } |
@@ -579,10 +710,40 @@ static int convert_response_xcrb(struct zcrypt_device *zdev, | |||
579 | default: /* Unknown response type, this should NEVER EVER happen */ | 710 | default: /* Unknown response type, this should NEVER EVER happen */ |
580 | xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ | 711 | xcRB->status = 0x0008044DL; /* HDD_InvalidParm */ |
581 | zdev->online = 0; | 712 | zdev->online = 0; |
713 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
714 | zdev->ap_dev->qid); | ||
715 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
716 | zdev->ap_dev->qid, zdev->online); | ||
582 | return -EAGAIN; /* repeat the request on a different device. */ | 717 | return -EAGAIN; /* repeat the request on a different device. */ |
583 | } | 718 | } |
584 | } | 719 | } |
585 | 720 | ||
721 | static int convert_response_ep11_xcrb(struct zcrypt_device *zdev, | ||
722 | struct ap_message *reply, struct ep11_urb *xcRB) | ||
723 | { | ||
724 | struct type86_ep11_reply *msg = reply->message; | ||
725 | |||
726 | /* Response type byte is the second byte in the response. */ | ||
727 | switch (((unsigned char *)reply->message)[1]) { | ||
728 | case TYPE82_RSP_CODE: | ||
729 | case TYPE87_RSP_CODE: | ||
730 | return convert_error(zdev, reply); | ||
731 | case TYPE86_RSP_CODE: | ||
732 | if (msg->hdr.reply_code) | ||
733 | return convert_error(zdev, reply); | ||
734 | if (msg->cprbx.cprb_ver_id == 0x04) | ||
735 | return convert_type86_ep11_xcrb(zdev, reply, xcRB); | ||
736 | /* Fall through, no break, incorrect cprb version is an unknown resp.*/ | ||
737 | default: /* Unknown response type, this should NEVER EVER happen */ | ||
738 | zdev->online = 0; | ||
739 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
740 | zdev->ap_dev->qid); | ||
741 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
742 | zdev->ap_dev->qid, zdev->online); | ||
743 | return -EAGAIN; /* repeat the request on a different device. */ | ||
744 | } | ||
745 | } | ||
746 | |||
586 | static int convert_response_rng(struct zcrypt_device *zdev, | 747 | static int convert_response_rng(struct zcrypt_device *zdev, |
587 | struct ap_message *reply, | 748 | struct ap_message *reply, |
588 | char *data) | 749 | char *data) |
@@ -602,6 +763,10 @@ static int convert_response_rng(struct zcrypt_device *zdev, | |||
602 | * response */ | 763 | * response */ |
603 | default: /* Unknown response type, this should NEVER EVER happen */ | 764 | default: /* Unknown response type, this should NEVER EVER happen */ |
604 | zdev->online = 0; | 765 | zdev->online = 0; |
766 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
767 | zdev->ap_dev->qid); | ||
768 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
769 | zdev->ap_dev->qid, zdev->online); | ||
605 | return -EAGAIN; /* repeat the request on a different device. */ | 770 | return -EAGAIN; /* repeat the request on a different device. */ |
606 | } | 771 | } |
607 | } | 772 | } |
@@ -657,6 +822,51 @@ out: | |||
657 | complete(&(resp_type->work)); | 822 | complete(&(resp_type->work)); |
658 | } | 823 | } |
659 | 824 | ||
825 | /** | ||
826 | * This function is called from the AP bus code after a crypto request | ||
827 | * "msg" has finished with the reply message "reply". | ||
828 | * It is called from tasklet context. | ||
829 | * @ap_dev: pointer to the AP device | ||
830 | * @msg: pointer to the AP message | ||
831 | * @reply: pointer to the AP reply message | ||
832 | */ | ||
833 | static void zcrypt_msgtype6_receive_ep11(struct ap_device *ap_dev, | ||
834 | struct ap_message *msg, | ||
835 | struct ap_message *reply) | ||
836 | { | ||
837 | static struct error_hdr error_reply = { | ||
838 | .type = TYPE82_RSP_CODE, | ||
839 | .reply_code = REP82_ERROR_MACHINE_FAILURE, | ||
840 | }; | ||
841 | struct response_type *resp_type = | ||
842 | (struct response_type *)msg->private; | ||
843 | struct type86_ep11_reply *t86r; | ||
844 | int length; | ||
845 | |||
846 | /* Copy the reply message to the request message buffer. */ | ||
847 | if (IS_ERR(reply)) { | ||
848 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | ||
849 | goto out; | ||
850 | } | ||
851 | t86r = reply->message; | ||
852 | if (t86r->hdr.type == TYPE86_RSP_CODE && | ||
853 | t86r->cprbx.cprb_ver_id == 0x04) { | ||
854 | switch (resp_type->type) { | ||
855 | case PCIXCC_RESPONSE_TYPE_EP11: | ||
856 | length = t86r->fmt2.offset1 + t86r->fmt2.count1; | ||
857 | length = min(MSGTYPE06_MAX_MSG_SIZE, length); | ||
858 | memcpy(msg->message, reply->message, length); | ||
859 | break; | ||
860 | default: | ||
861 | memcpy(msg->message, &error_reply, sizeof(error_reply)); | ||
862 | } | ||
863 | } else { | ||
864 | memcpy(msg->message, reply->message, sizeof(error_reply)); | ||
865 | } | ||
866 | out: | ||
867 | complete(&(resp_type->work)); | ||
868 | } | ||
869 | |||
660 | static atomic_t zcrypt_step = ATOMIC_INIT(0); | 870 | static atomic_t zcrypt_step = ATOMIC_INIT(0); |
661 | 871 | ||
662 | /** | 872 | /** |
@@ -782,6 +992,46 @@ out_free: | |||
782 | } | 992 | } |
783 | 993 | ||
784 | /** | 994 | /** |
995 | * The request distributor calls this function if it picked the CEX4P | ||
996 | * device to handle a send_ep11_cprb request. | ||
997 | * @zdev: pointer to zcrypt_device structure that identifies the | ||
998 | * CEX4P device to the request distributor | ||
999 | * @xcRB: pointer to the ep11 user request block | ||
1000 | */ | ||
1001 | static long zcrypt_msgtype6_send_ep11_cprb(struct zcrypt_device *zdev, | ||
1002 | struct ep11_urb *xcrb) | ||
1003 | { | ||
1004 | struct ap_message ap_msg; | ||
1005 | struct response_type resp_type = { | ||
1006 | .type = PCIXCC_RESPONSE_TYPE_EP11, | ||
1007 | }; | ||
1008 | int rc; | ||
1009 | |||
1010 | ap_init_message(&ap_msg); | ||
1011 | ap_msg.message = kmalloc(MSGTYPE06_MAX_MSG_SIZE, GFP_KERNEL); | ||
1012 | if (!ap_msg.message) | ||
1013 | return -ENOMEM; | ||
1014 | ap_msg.receive = zcrypt_msgtype6_receive_ep11; | ||
1015 | ap_msg.psmid = (((unsigned long long) current->pid) << 32) + | ||
1016 | atomic_inc_return(&zcrypt_step); | ||
1017 | ap_msg.private = &resp_type; | ||
1018 | rc = xcrb_msg_to_type6_ep11cprb_msgx(zdev, &ap_msg, xcrb); | ||
1019 | if (rc) | ||
1020 | goto out_free; | ||
1021 | init_completion(&resp_type.work); | ||
1022 | ap_queue_message(zdev->ap_dev, &ap_msg); | ||
1023 | rc = wait_for_completion_interruptible(&resp_type.work); | ||
1024 | if (rc == 0) | ||
1025 | rc = convert_response_ep11_xcrb(zdev, &ap_msg, xcrb); | ||
1026 | else /* Signal pending. */ | ||
1027 | ap_cancel_message(zdev->ap_dev, &ap_msg); | ||
1028 | |||
1029 | out_free: | ||
1030 | kzfree(ap_msg.message); | ||
1031 | return rc; | ||
1032 | } | ||
1033 | |||
1034 | /** | ||
785 | * The request distributor calls this function if it picked the PCIXCC/CEX2C | 1035 | * The request distributor calls this function if it picked the PCIXCC/CEX2C |
786 | * device to generate random data. | 1036 | * device to generate random data. |
787 | * @zdev: pointer to zcrypt_device structure that identifies the | 1037 | * @zdev: pointer to zcrypt_device structure that identifies the |
@@ -839,10 +1089,19 @@ static struct zcrypt_ops zcrypt_msgtype6_ops = { | |||
839 | .rng = zcrypt_msgtype6_rng, | 1089 | .rng = zcrypt_msgtype6_rng, |
840 | }; | 1090 | }; |
841 | 1091 | ||
1092 | static struct zcrypt_ops zcrypt_msgtype6_ep11_ops = { | ||
1093 | .owner = THIS_MODULE, | ||
1094 | .variant = MSGTYPE06_VARIANT_EP11, | ||
1095 | .rsa_modexpo = NULL, | ||
1096 | .rsa_modexpo_crt = NULL, | ||
1097 | .send_ep11_cprb = zcrypt_msgtype6_send_ep11_cprb, | ||
1098 | }; | ||
1099 | |||
842 | int __init zcrypt_msgtype6_init(void) | 1100 | int __init zcrypt_msgtype6_init(void) |
843 | { | 1101 | { |
844 | zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops); | 1102 | zcrypt_msgtype_register(&zcrypt_msgtype6_norng_ops); |
845 | zcrypt_msgtype_register(&zcrypt_msgtype6_ops); | 1103 | zcrypt_msgtype_register(&zcrypt_msgtype6_ops); |
1104 | zcrypt_msgtype_register(&zcrypt_msgtype6_ep11_ops); | ||
846 | return 0; | 1105 | return 0; |
847 | } | 1106 | } |
848 | 1107 | ||
@@ -850,6 +1109,7 @@ void __exit zcrypt_msgtype6_exit(void) | |||
850 | { | 1109 | { |
851 | zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops); | 1110 | zcrypt_msgtype_unregister(&zcrypt_msgtype6_norng_ops); |
852 | zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops); | 1111 | zcrypt_msgtype_unregister(&zcrypt_msgtype6_ops); |
1112 | zcrypt_msgtype_unregister(&zcrypt_msgtype6_ep11_ops); | ||
853 | } | 1113 | } |
854 | 1114 | ||
855 | module_init(zcrypt_msgtype6_init); | 1115 | module_init(zcrypt_msgtype6_init); |
diff --git a/drivers/s390/crypto/zcrypt_msgtype6.h b/drivers/s390/crypto/zcrypt_msgtype6.h index 1e500d3c0735..207247570623 100644 --- a/drivers/s390/crypto/zcrypt_msgtype6.h +++ b/drivers/s390/crypto/zcrypt_msgtype6.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #define MSGTYPE06_NAME "zcrypt_msgtype6" | 32 | #define MSGTYPE06_NAME "zcrypt_msgtype6" |
33 | #define MSGTYPE06_VARIANT_DEFAULT 0 | 33 | #define MSGTYPE06_VARIANT_DEFAULT 0 |
34 | #define MSGTYPE06_VARIANT_NORNG 1 | 34 | #define MSGTYPE06_VARIANT_NORNG 1 |
35 | #define MSGTYPE06_VARIANT_EP11 2 | ||
35 | 36 | ||
36 | #define MSGTYPE06_MAX_MSG_SIZE (12*1024) | 37 | #define MSGTYPE06_MAX_MSG_SIZE (12*1024) |
37 | 38 | ||
@@ -99,6 +100,7 @@ struct type86_hdr { | |||
99 | } __packed; | 100 | } __packed; |
100 | 101 | ||
101 | #define TYPE86_RSP_CODE 0x86 | 102 | #define TYPE86_RSP_CODE 0x86 |
103 | #define TYPE87_RSP_CODE 0x87 | ||
102 | #define TYPE86_FMT2 0x02 | 104 | #define TYPE86_FMT2 0x02 |
103 | 105 | ||
104 | struct type86_fmt2_ext { | 106 | struct type86_fmt2_ext { |
diff --git a/drivers/s390/crypto/zcrypt_pcica.c b/drivers/s390/crypto/zcrypt_pcica.c index f2b71d8df01f..7a743f4c646c 100644 --- a/drivers/s390/crypto/zcrypt_pcica.c +++ b/drivers/s390/crypto/zcrypt_pcica.c | |||
@@ -24,6 +24,9 @@ | |||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #define KMSG_COMPONENT "zcrypt" | ||
28 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
29 | |||
27 | #include <linux/module.h> | 30 | #include <linux/module.h> |
28 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
29 | #include <linux/init.h> | 32 | #include <linux/init.h> |
@@ -199,6 +202,10 @@ static int convert_type84(struct zcrypt_device *zdev, | |||
199 | if (t84h->len < sizeof(*t84h) + outputdatalength) { | 202 | if (t84h->len < sizeof(*t84h) + outputdatalength) { |
200 | /* The result is too short, the PCICA card may not do that.. */ | 203 | /* The result is too short, the PCICA card may not do that.. */ |
201 | zdev->online = 0; | 204 | zdev->online = 0; |
205 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
206 | zdev->ap_dev->qid); | ||
207 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | ||
208 | zdev->ap_dev->qid, zdev->online, t84h->code); | ||
202 | return -EAGAIN; /* repeat the request on a different device. */ | 209 | return -EAGAIN; /* repeat the request on a different device. */ |
203 | } | 210 | } |
204 | BUG_ON(t84h->len > PCICA_MAX_RESPONSE_SIZE); | 211 | BUG_ON(t84h->len > PCICA_MAX_RESPONSE_SIZE); |
@@ -223,6 +230,10 @@ static int convert_response(struct zcrypt_device *zdev, | |||
223 | outputdata, outputdatalength); | 230 | outputdata, outputdatalength); |
224 | default: /* Unknown response type, this should NEVER EVER happen */ | 231 | default: /* Unknown response type, this should NEVER EVER happen */ |
225 | zdev->online = 0; | 232 | zdev->online = 0; |
233 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
234 | zdev->ap_dev->qid); | ||
235 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
236 | zdev->ap_dev->qid, zdev->online); | ||
226 | return -EAGAIN; /* repeat the request on a different device. */ | 237 | return -EAGAIN; /* repeat the request on a different device. */ |
227 | } | 238 | } |
228 | } | 239 | } |
diff --git a/drivers/s390/crypto/zcrypt_pcicc.c b/drivers/s390/crypto/zcrypt_pcicc.c index 0d90a4334055..4d14c04b746e 100644 --- a/drivers/s390/crypto/zcrypt_pcicc.c +++ b/drivers/s390/crypto/zcrypt_pcicc.c | |||
@@ -24,6 +24,9 @@ | |||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #define KMSG_COMPONENT "zcrypt" | ||
28 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
29 | |||
27 | #include <linux/module.h> | 30 | #include <linux/module.h> |
28 | #include <linux/init.h> | 31 | #include <linux/init.h> |
29 | #include <linux/gfp.h> | 32 | #include <linux/gfp.h> |
@@ -372,6 +375,11 @@ static int convert_type86(struct zcrypt_device *zdev, | |||
372 | if (service_rc == 8 && service_rs == 72) | 375 | if (service_rc == 8 && service_rs == 72) |
373 | return -EINVAL; | 376 | return -EINVAL; |
374 | zdev->online = 0; | 377 | zdev->online = 0; |
378 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
379 | zdev->ap_dev->qid); | ||
380 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%drc%d", | ||
381 | zdev->ap_dev->qid, zdev->online, | ||
382 | msg->hdr.reply_code); | ||
375 | return -EAGAIN; /* repeat the request on a different device. */ | 383 | return -EAGAIN; /* repeat the request on a different device. */ |
376 | } | 384 | } |
377 | data = msg->text; | 385 | data = msg->text; |
@@ -425,6 +433,10 @@ static int convert_response(struct zcrypt_device *zdev, | |||
425 | /* no break, incorrect cprb version is an unknown response */ | 433 | /* no break, incorrect cprb version is an unknown response */ |
426 | default: /* Unknown response type, this should NEVER EVER happen */ | 434 | default: /* Unknown response type, this should NEVER EVER happen */ |
427 | zdev->online = 0; | 435 | zdev->online = 0; |
436 | pr_err("Cryptographic device %x failed and was set offline\n", | ||
437 | zdev->ap_dev->qid); | ||
438 | ZCRYPT_DBF_DEV(DBF_ERR, zdev, "dev%04xo%dfail", | ||
439 | zdev->ap_dev->qid, zdev->online); | ||
428 | return -EAGAIN; /* repeat the request on a different device. */ | 440 | return -EAGAIN; /* repeat the request on a different device. */ |
429 | } | 441 | } |
430 | } | 442 | } |