aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-08 15:02:28 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-08 15:02:28 -0400
commitd586c86d50cefa0897a51a2dbc714060ccedae76 (patch)
tree76a7f454637badb74390047aebca5c071c0988fe /drivers/s390/char
parente9f37d3a8d126e73f5737ef548cdf6f618e295e4 (diff)
parent457f2180951cdcbfb4657ddcc83b486e93497f56 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull second set of s390 patches from Martin Schwidefsky: "The second part of Heikos uaccess rework, the page table walker for uaccess is now a thing of the past (yay!) The code change to fix the theoretical TLB flush problem allows us to add a TLB flush optimization for zEC12, this machine has new instructions that allow to do CPU local TLB flushes for single pages and for all pages of a specific address space. Plus the usual bug fixing and some more cleanup" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: s390/uaccess: rework uaccess code - fix locking issues s390/mm,tlb: optimize TLB flushing for zEC12 s390/mm,tlb: safeguard against speculative TLB creation s390/irq: Use defines for external interruption codes s390/irq: Add defines for external interruption codes s390/sclp: add timeout for queued requests kvm/s390: also set guest pages back to stable on kexec/kdump lcs: Add missing destroy_timer_on_stack() s390/tape: Add missing destroy_timer_on_stack() s390/tape: Use del_timer_sync() s390/3270: fix crash with multiple reset device requests s390/bitops,atomic: add missing memory barriers s390/zcrypt: add length check for aligned data to avoid overflow in msg-type 6
Diffstat (limited to 'drivers/s390/char')
-rw-r--r--drivers/s390/char/raw3270.c9
-rw-r--r--drivers/s390/char/sclp.c88
-rw-r--r--drivers/s390/char/sclp.h9
-rw-r--r--drivers/s390/char/sclp_cmd.c17
-rw-r--r--drivers/s390/char/tape_std.c3
5 files changed, 115 insertions, 11 deletions
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index 9f849df4381e..15b3459f8656 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -632,6 +632,8 @@ raw3270_reset_device_cb(struct raw3270_request *rq, void *data)
632 raw3270_size_device_done(rp); 632 raw3270_size_device_done(rp);
633 } else 633 } else
634 raw3270_writesf_readpart(rp); 634 raw3270_writesf_readpart(rp);
635 memset(&rp->init_reset, 0, sizeof(rp->init_reset));
636 memset(&rp->init_data, 0, sizeof(rp->init_data));
635} 637}
636 638
637static int 639static int
@@ -639,9 +641,10 @@ __raw3270_reset_device(struct raw3270 *rp)
639{ 641{
640 int rc; 642 int rc;
641 643
644 /* Check if reset is already pending */
645 if (rp->init_reset.view)
646 return -EBUSY;
642 /* Store reset data stream to init_data/init_reset */ 647 /* Store reset data stream to init_data/init_reset */
643 memset(&rp->init_reset, 0, sizeof(rp->init_reset));
644 memset(&rp->init_data, 0, sizeof(rp->init_data));
645 rp->init_data[0] = TW_KR; 648 rp->init_data[0] = TW_KR;
646 rp->init_reset.ccw.cmd_code = TC_EWRITEA; 649 rp->init_reset.ccw.cmd_code = TC_EWRITEA;
647 rp->init_reset.ccw.flags = CCW_FLAG_SLI; 650 rp->init_reset.ccw.flags = CCW_FLAG_SLI;
@@ -850,7 +853,7 @@ raw3270_create_device(struct ccw_device *cdev)
850 char *ascebc; 853 char *ascebc;
851 int rc; 854 int rc;
852 855
853 rp = kmalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA); 856 rp = kzalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA);
854 if (!rp) 857 if (!rp)
855 return ERR_PTR(-ENOMEM); 858 return ERR_PTR(-ENOMEM);
856 ascebc = kmalloc(256, GFP_KERNEL); 859 ascebc = kmalloc(256, GFP_KERNEL);
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 1fe264379e0d..1990285296c6 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -91,6 +91,9 @@ static struct sclp_req sclp_suspend_req;
91/* Timer for request retries. */ 91/* Timer for request retries. */
92static struct timer_list sclp_request_timer; 92static struct timer_list sclp_request_timer;
93 93
94/* Timer for queued requests. */
95static struct timer_list sclp_queue_timer;
96
94/* Internal state: is the driver initialized? */ 97/* Internal state: is the driver initialized? */
95static volatile enum sclp_init_state_t { 98static volatile enum sclp_init_state_t {
96 sclp_init_state_uninitialized, 99 sclp_init_state_uninitialized,
@@ -215,6 +218,76 @@ sclp_request_timeout(unsigned long data)
215 sclp_process_queue(); 218 sclp_process_queue();
216} 219}
217 220
221/*
222 * Returns the expire value in jiffies of the next pending request timeout,
223 * if any. Needs to be called with sclp_lock.
224 */
225static unsigned long __sclp_req_queue_find_next_timeout(void)
226{
227 unsigned long expires_next = 0;
228 struct sclp_req *req;
229
230 list_for_each_entry(req, &sclp_req_queue, list) {
231 if (!req->queue_expires)
232 continue;
233 if (!expires_next ||
234 (time_before(req->queue_expires, expires_next)))
235 expires_next = req->queue_expires;
236 }
237 return expires_next;
238}
239
240/*
241 * Returns expired request, if any, and removes it from the list.
242 */
243static struct sclp_req *__sclp_req_queue_remove_expired_req(void)
244{
245 unsigned long flags, now;
246 struct sclp_req *req;
247
248 spin_lock_irqsave(&sclp_lock, flags);
249 now = jiffies;
250 /* Don't need list_for_each_safe because we break out after list_del */
251 list_for_each_entry(req, &sclp_req_queue, list) {
252 if (!req->queue_expires)
253 continue;
254 if (time_before_eq(req->queue_expires, now)) {
255 if (req->status == SCLP_REQ_QUEUED) {
256 req->status = SCLP_REQ_QUEUED_TIMEOUT;
257 list_del(&req->list);
258 goto out;
259 }
260 }
261 }
262 req = NULL;
263out:
264 spin_unlock_irqrestore(&sclp_lock, flags);
265 return req;
266}
267
268/*
269 * Timeout handler for queued requests. Removes request from list and
270 * invokes callback. This timer can be set per request in situations where
271 * waiting too long would be harmful to the system, e.g. during SE reboot.
272 */
273static void sclp_req_queue_timeout(unsigned long data)
274{
275 unsigned long flags, expires_next;
276 struct sclp_req *req;
277
278 do {
279 req = __sclp_req_queue_remove_expired_req();
280 if (req && req->callback)
281 req->callback(req, req->callback_data);
282 } while (req);
283
284 spin_lock_irqsave(&sclp_lock, flags);
285 expires_next = __sclp_req_queue_find_next_timeout();
286 if (expires_next)
287 mod_timer(&sclp_queue_timer, expires_next);
288 spin_unlock_irqrestore(&sclp_lock, flags);
289}
290
218/* Try to start a request. Return zero if the request was successfully 291/* Try to start a request. Return zero if the request was successfully
219 * started or if it will be started at a later time. Return non-zero otherwise. 292 * started or if it will be started at a later time. Return non-zero otherwise.
220 * Called while sclp_lock is locked. */ 293 * Called while sclp_lock is locked. */
@@ -317,6 +390,13 @@ sclp_add_request(struct sclp_req *req)
317 req->start_count = 0; 390 req->start_count = 0;
318 list_add_tail(&req->list, &sclp_req_queue); 391 list_add_tail(&req->list, &sclp_req_queue);
319 rc = 0; 392 rc = 0;
393 if (req->queue_timeout) {
394 req->queue_expires = jiffies + req->queue_timeout * HZ;
395 if (!timer_pending(&sclp_queue_timer) ||
396 time_after(sclp_queue_timer.expires, req->queue_expires))
397 mod_timer(&sclp_queue_timer, req->queue_expires);
398 } else
399 req->queue_expires = 0;
320 /* Start if request is first in list */ 400 /* Start if request is first in list */
321 if (sclp_running_state == sclp_running_state_idle && 401 if (sclp_running_state == sclp_running_state_idle &&
322 req->list.prev == &sclp_req_queue) { 402 req->list.prev == &sclp_req_queue) {
@@ -892,7 +972,7 @@ sclp_check_interface(void)
892 972
893 spin_lock_irqsave(&sclp_lock, flags); 973 spin_lock_irqsave(&sclp_lock, flags);
894 /* Prepare init mask command */ 974 /* Prepare init mask command */
895 rc = register_external_interrupt(0x2401, sclp_check_handler); 975 rc = register_external_irq(EXT_IRQ_SERVICE_SIG, sclp_check_handler);
896 if (rc) { 976 if (rc) {
897 spin_unlock_irqrestore(&sclp_lock, flags); 977 spin_unlock_irqrestore(&sclp_lock, flags);
898 return rc; 978 return rc;
@@ -925,7 +1005,7 @@ sclp_check_interface(void)
925 } else 1005 } else
926 rc = -EBUSY; 1006 rc = -EBUSY;
927 } 1007 }
928 unregister_external_interrupt(0x2401, sclp_check_handler); 1008 unregister_external_irq(EXT_IRQ_SERVICE_SIG, sclp_check_handler);
929 spin_unlock_irqrestore(&sclp_lock, flags); 1009 spin_unlock_irqrestore(&sclp_lock, flags);
930 return rc; 1010 return rc;
931} 1011}
@@ -1113,6 +1193,8 @@ sclp_init(void)
1113 INIT_LIST_HEAD(&sclp_reg_list); 1193 INIT_LIST_HEAD(&sclp_reg_list);
1114 list_add(&sclp_state_change_event.list, &sclp_reg_list); 1194 list_add(&sclp_state_change_event.list, &sclp_reg_list);
1115 init_timer(&sclp_request_timer); 1195 init_timer(&sclp_request_timer);
1196 init_timer(&sclp_queue_timer);
1197 sclp_queue_timer.function = sclp_req_queue_timeout;
1116 /* Check interface */ 1198 /* Check interface */
1117 spin_unlock_irqrestore(&sclp_lock, flags); 1199 spin_unlock_irqrestore(&sclp_lock, flags);
1118 rc = sclp_check_interface(); 1200 rc = sclp_check_interface();
@@ -1124,7 +1206,7 @@ sclp_init(void)
1124 if (rc) 1206 if (rc)
1125 goto fail_init_state_uninitialized; 1207 goto fail_init_state_uninitialized;
1126 /* Register interrupt handler */ 1208 /* Register interrupt handler */
1127 rc = register_external_interrupt(0x2401, sclp_interrupt_handler); 1209 rc = register_external_irq(EXT_IRQ_SERVICE_SIG, sclp_interrupt_handler);
1128 if (rc) 1210 if (rc)
1129 goto fail_unregister_reboot_notifier; 1211 goto fail_unregister_reboot_notifier;
1130 sclp_init_state = sclp_init_state_initialized; 1212 sclp_init_state = sclp_init_state_initialized;
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h
index fea76aed9eea..a68b5ec7d042 100644
--- a/drivers/s390/char/sclp.h
+++ b/drivers/s390/char/sclp.h
@@ -133,6 +133,11 @@ struct sclp_req {
133 /* Callback that is called after reaching final status. */ 133 /* Callback that is called after reaching final status. */
134 void (*callback)(struct sclp_req *, void *data); 134 void (*callback)(struct sclp_req *, void *data);
135 void *callback_data; 135 void *callback_data;
136 int queue_timeout; /* request queue timeout (sec), set by
137 caller of sclp_add_request(), if
138 needed */
139 /* Internal fields */
140 unsigned long queue_expires; /* request queue timeout (jiffies) */
136}; 141};
137 142
138#define SCLP_REQ_FILLED 0x00 /* request is ready to be processed */ 143#define SCLP_REQ_FILLED 0x00 /* request is ready to be processed */
@@ -140,6 +145,9 @@ struct sclp_req {
140#define SCLP_REQ_RUNNING 0x02 /* request is currently running */ 145#define SCLP_REQ_RUNNING 0x02 /* request is currently running */
141#define SCLP_REQ_DONE 0x03 /* request is completed successfully */ 146#define SCLP_REQ_DONE 0x03 /* request is completed successfully */
142#define SCLP_REQ_FAILED 0x05 /* request is finally failed */ 147#define SCLP_REQ_FAILED 0x05 /* request is finally failed */
148#define SCLP_REQ_QUEUED_TIMEOUT 0x06 /* request on queue timed out */
149
150#define SCLP_QUEUE_INTERVAL 5 /* timeout interval for request queue */
143 151
144/* function pointers that a high level driver has to use for registration */ 152/* function pointers that a high level driver has to use for registration */
145/* of some routines it wants to be called from the low level driver */ 153/* of some routines it wants to be called from the low level driver */
@@ -173,6 +181,7 @@ int sclp_deactivate(void);
173int sclp_reactivate(void); 181int sclp_reactivate(void);
174int sclp_service_call(sclp_cmdw_t command, void *sccb); 182int sclp_service_call(sclp_cmdw_t command, void *sccb);
175int sclp_sync_request(sclp_cmdw_t command, void *sccb); 183int sclp_sync_request(sclp_cmdw_t command, void *sccb);
184int sclp_sync_request_timeout(sclp_cmdw_t command, void *sccb, int timeout);
176 185
177int sclp_sdias_init(void); 186int sclp_sdias_init(void);
178void sclp_sdias_exit(void); 187void sclp_sdias_exit(void);
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 49af8eeb90ea..6e8f90f84e49 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -37,6 +37,11 @@ static void sclp_sync_callback(struct sclp_req *req, void *data)
37 37
38int sclp_sync_request(sclp_cmdw_t cmd, void *sccb) 38int sclp_sync_request(sclp_cmdw_t cmd, void *sccb)
39{ 39{
40 return sclp_sync_request_timeout(cmd, sccb, 0);
41}
42
43int sclp_sync_request_timeout(sclp_cmdw_t cmd, void *sccb, int timeout)
44{
40 struct completion completion; 45 struct completion completion;
41 struct sclp_req *request; 46 struct sclp_req *request;
42 int rc; 47 int rc;
@@ -44,6 +49,8 @@ int sclp_sync_request(sclp_cmdw_t cmd, void *sccb)
44 request = kzalloc(sizeof(*request), GFP_KERNEL); 49 request = kzalloc(sizeof(*request), GFP_KERNEL);
45 if (!request) 50 if (!request)
46 return -ENOMEM; 51 return -ENOMEM;
52 if (timeout)
53 request->queue_timeout = timeout;
47 request->command = cmd; 54 request->command = cmd;
48 request->sccb = sccb; 55 request->sccb = sccb;
49 request->status = SCLP_REQ_FILLED; 56 request->status = SCLP_REQ_FILLED;
@@ -110,7 +117,8 @@ int sclp_get_cpu_info(struct sclp_cpu_info *info)
110 if (!sccb) 117 if (!sccb)
111 return -ENOMEM; 118 return -ENOMEM;
112 sccb->header.length = sizeof(*sccb); 119 sccb->header.length = sizeof(*sccb);
113 rc = sclp_sync_request(SCLP_CMDW_READ_CPU_INFO, sccb); 120 rc = sclp_sync_request_timeout(SCLP_CMDW_READ_CPU_INFO, sccb,
121 SCLP_QUEUE_INTERVAL);
114 if (rc) 122 if (rc)
115 goto out; 123 goto out;
116 if (sccb->header.response_code != 0x0010) { 124 if (sccb->header.response_code != 0x0010) {
@@ -144,7 +152,7 @@ static int do_cpu_configure(sclp_cmdw_t cmd)
144 if (!sccb) 152 if (!sccb)
145 return -ENOMEM; 153 return -ENOMEM;
146 sccb->header.length = sizeof(*sccb); 154 sccb->header.length = sizeof(*sccb);
147 rc = sclp_sync_request(cmd, sccb); 155 rc = sclp_sync_request_timeout(cmd, sccb, SCLP_QUEUE_INTERVAL);
148 if (rc) 156 if (rc)
149 goto out; 157 goto out;
150 switch (sccb->header.response_code) { 158 switch (sccb->header.response_code) {
@@ -214,7 +222,7 @@ static int do_assign_storage(sclp_cmdw_t cmd, u16 rn)
214 return -ENOMEM; 222 return -ENOMEM;
215 sccb->header.length = PAGE_SIZE; 223 sccb->header.length = PAGE_SIZE;
216 sccb->rn = rn; 224 sccb->rn = rn;
217 rc = sclp_sync_request(cmd, sccb); 225 rc = sclp_sync_request_timeout(cmd, sccb, SCLP_QUEUE_INTERVAL);
218 if (rc) 226 if (rc)
219 goto out; 227 goto out;
220 switch (sccb->header.response_code) { 228 switch (sccb->header.response_code) {
@@ -269,7 +277,8 @@ static int sclp_attach_storage(u8 id)
269 if (!sccb) 277 if (!sccb)
270 return -ENOMEM; 278 return -ENOMEM;
271 sccb->header.length = PAGE_SIZE; 279 sccb->header.length = PAGE_SIZE;
272 rc = sclp_sync_request(0x00080001 | id << 8, sccb); 280 rc = sclp_sync_request_timeout(0x00080001 | id << 8, sccb,
281 SCLP_QUEUE_INTERVAL);
273 if (rc) 282 if (rc)
274 goto out; 283 goto out;
275 switch (sccb->header.response_code) { 284 switch (sccb->header.response_code) {
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c
index 981a99fd8d42..3478e19ae194 100644
--- a/drivers/s390/char/tape_std.c
+++ b/drivers/s390/char/tape_std.c
@@ -78,7 +78,8 @@ tape_std_assign(struct tape_device *device)
78 78
79 rc = tape_do_io_interruptible(device, request); 79 rc = tape_do_io_interruptible(device, request);
80 80
81 del_timer(&timeout); 81 del_timer_sync(&timeout);
82 destroy_timer_on_stack(&timeout);
82 83
83 if (rc != 0) { 84 if (rc != 0) {
84 DBF_EVENT(3, "%08x: assign failed - device might be busy\n", 85 DBF_EVENT(3, "%08x: assign failed - device might be busy\n",