aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char/monreader.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/char/monreader.c')
-rw-r--r--drivers/s390/char/monreader.c78
1 files changed, 11 insertions, 67 deletions
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c
index 1e1f50655bbf..35fd8dfcaaa6 100644
--- a/drivers/s390/char/monreader.c
+++ b/drivers/s390/char/monreader.c
@@ -3,14 +3,14 @@
3 * 3 *
4 * Character device driver for reading z/VM *MONITOR service records. 4 * Character device driver for reading z/VM *MONITOR service records.
5 * 5 *
6 * Copyright 2004 IBM Corporation, IBM Deutschland Entwicklung GmbH. 6 * Copyright IBM Corp. 2004, 2008
7 * 7 * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
8 * Author: Gerald Schaefer <geraldsc@de.ibm.com>
9 */ 8 */
10 9
11#include <linux/module.h> 10#include <linux/module.h>
12#include <linux/moduleparam.h> 11#include <linux/moduleparam.h>
13#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/smp_lock.h>
14#include <linux/errno.h> 14#include <linux/errno.h>
15#include <linux/types.h> 15#include <linux/types.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
@@ -18,12 +18,11 @@
18#include <linux/ctype.h> 18#include <linux/ctype.h>
19#include <linux/spinlock.h> 19#include <linux/spinlock.h>
20#include <linux/interrupt.h> 20#include <linux/interrupt.h>
21#include <linux/poll.h>
22#include <net/iucv/iucv.h>
21#include <asm/uaccess.h> 23#include <asm/uaccess.h>
22#include <asm/ebcdic.h> 24#include <asm/ebcdic.h>
23#include <asm/extmem.h> 25#include <asm/extmem.h>
24#include <linux/poll.h>
25#include <net/iucv/iucv.h>
26
27 26
28//#define MON_DEBUG /* Debug messages on/off */ 27//#define MON_DEBUG /* Debug messages on/off */
29 28
@@ -152,10 +151,7 @@ static int mon_check_mca(struct mon_msg *monmsg)
152 (mon_mca_end(monmsg) > mon_dcss_end) || 151 (mon_mca_end(monmsg) > mon_dcss_end) ||
153 (mon_mca_start(monmsg) < mon_dcss_start) || 152 (mon_mca_start(monmsg) < mon_dcss_start) ||
154 ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0))) 153 ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0)))
155 {
156 P_DEBUG("READ, IGNORED INVALID MCA\n\n");
157 return -EINVAL; 154 return -EINVAL;
158 }
159 return 0; 155 return 0;
160} 156}
161 157
@@ -164,10 +160,6 @@ static int mon_send_reply(struct mon_msg *monmsg,
164{ 160{
165 int rc; 161 int rc;
166 162
167 P_DEBUG("read, REPLY: pathid = 0x%04X, msgid = 0x%08X, trgcls = "
168 "0x%08X\n\n",
169 monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
170
171 rc = iucv_message_reply(monpriv->path, &monmsg->msg, 163 rc = iucv_message_reply(monpriv->path, &monmsg->msg,
172 IUCV_IPRMDATA, NULL, 0); 164 IUCV_IPRMDATA, NULL, 0);
173 atomic_dec(&monpriv->msglim_count); 165 atomic_dec(&monpriv->msglim_count);
@@ -202,15 +194,12 @@ static struct mon_private *mon_alloc_mem(void)
202 struct mon_private *monpriv; 194 struct mon_private *monpriv;
203 195
204 monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); 196 monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL);
205 if (!monpriv) { 197 if (!monpriv)
206 P_ERROR("no memory for monpriv\n");
207 return NULL; 198 return NULL;
208 }
209 for (i = 0; i < MON_MSGLIM; i++) { 199 for (i = 0; i < MON_MSGLIM; i++) {
210 monpriv->msg_array[i] = kzalloc(sizeof(struct mon_msg), 200 monpriv->msg_array[i] = kzalloc(sizeof(struct mon_msg),
211 GFP_KERNEL); 201 GFP_KERNEL);
212 if (!monpriv->msg_array[i]) { 202 if (!monpriv->msg_array[i]) {
213 P_ERROR("open, no memory for msg_array\n");
214 mon_free_mem(monpriv); 203 mon_free_mem(monpriv);
215 return NULL; 204 return NULL;
216 } 205 }
@@ -218,41 +207,10 @@ static struct mon_private *mon_alloc_mem(void)
218 return monpriv; 207 return monpriv;
219} 208}
220 209
221static inline void mon_read_debug(struct mon_msg *monmsg,
222 struct mon_private *monpriv)
223{
224#ifdef MON_DEBUG
225 u8 msg_type[2], mca_type;
226 unsigned long records_len;
227
228 records_len = mon_rec_end(monmsg) - mon_rec_start(monmsg) + 1;
229
230 memcpy(msg_type, &monmsg->msg.class, 2);
231 EBCASC(msg_type, 2);
232 mca_type = mon_mca_type(monmsg, 0);
233 EBCASC(&mca_type, 1);
234
235 P_DEBUG("read, mon_read_index = %i, mon_write_index = %i\n",
236 monpriv->read_index, monpriv->write_index);
237 P_DEBUG("read, pathid = 0x%04X, msgid = 0x%08X, trgcls = 0x%08X\n",
238 monpriv->path->pathid, monmsg->msg.id, monmsg->msg.class);
239 P_DEBUG("read, msg_type = '%c%c', mca_type = '%c' / 0x%X / 0x%X\n",
240 msg_type[0], msg_type[1], mca_type ? mca_type : 'X',
241 mon_mca_type(monmsg, 1), mon_mca_type(monmsg, 2));
242 P_DEBUG("read, MCA: start = 0x%lX, end = 0x%lX\n",
243 mon_mca_start(monmsg), mon_mca_end(monmsg));
244 P_DEBUG("read, REC: start = 0x%X, end = 0x%X, len = %lu\n\n",
245 mon_rec_start(monmsg), mon_rec_end(monmsg), records_len);
246 if (mon_mca_size(monmsg) > 12)
247 P_DEBUG("READ, MORE THAN ONE MCA\n\n");
248#endif
249}
250
251static inline void mon_next_mca(struct mon_msg *monmsg) 210static inline void mon_next_mca(struct mon_msg *monmsg)
252{ 211{
253 if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12)) 212 if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12))
254 return; 213 return;
255 P_DEBUG("READ, NEXT MCA\n\n");
256 monmsg->mca_offset += 12; 214 monmsg->mca_offset += 12;
257 monmsg->pos = 0; 215 monmsg->pos = 0;
258} 216}
@@ -269,7 +227,6 @@ static struct mon_msg *mon_next_message(struct mon_private *monpriv)
269 monmsg->msglim_reached = 0; 227 monmsg->msglim_reached = 0;
270 monmsg->pos = 0; 228 monmsg->pos = 0;
271 monmsg->mca_offset = 0; 229 monmsg->mca_offset = 0;
272 P_WARNING("read, message limit reached\n");
273 monpriv->read_index = (monpriv->read_index + 1) % 230 monpriv->read_index = (monpriv->read_index + 1) %
274 MON_MSGLIM; 231 MON_MSGLIM;
275 atomic_dec(&monpriv->read_ready); 232 atomic_dec(&monpriv->read_ready);
@@ -286,10 +243,6 @@ static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16])
286{ 243{
287 struct mon_private *monpriv = path->private; 244 struct mon_private *monpriv = path->private;
288 245
289 P_DEBUG("IUCV connection completed\n");
290 P_DEBUG("IUCV ACCEPT (from *MONITOR): Version = 0x%02X, Event = "
291 "0x%02X, Sample = 0x%02X\n",
292 ipuser[0], ipuser[1], ipuser[2]);
293 atomic_set(&monpriv->iucv_connected, 1); 246 atomic_set(&monpriv->iucv_connected, 1);
294 wake_up(&mon_conn_wait_queue); 247 wake_up(&mon_conn_wait_queue);
295} 248}
@@ -310,7 +263,6 @@ static void mon_iucv_message_pending(struct iucv_path *path,
310{ 263{
311 struct mon_private *monpriv = path->private; 264 struct mon_private *monpriv = path->private;
312 265
313 P_DEBUG("IUCV message pending\n");
314 memcpy(&monpriv->msg_array[monpriv->write_index]->msg, 266 memcpy(&monpriv->msg_array[monpriv->write_index]->msg,
315 msg, sizeof(*msg)); 267 msg, sizeof(*msg));
316 if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) { 268 if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) {
@@ -340,6 +292,7 @@ static int mon_open(struct inode *inode, struct file *filp)
340 /* 292 /*
341 * only one user allowed 293 * only one user allowed
342 */ 294 */
295 lock_kernel();
343 rc = -EBUSY; 296 rc = -EBUSY;
344 if (test_and_set_bit(MON_IN_USE, &mon_in_use)) 297 if (test_and_set_bit(MON_IN_USE, &mon_in_use))
345 goto out; 298 goto out;
@@ -375,8 +328,8 @@ static int mon_open(struct inode *inode, struct file *filp)
375 rc = -EIO; 328 rc = -EIO;
376 goto out_path; 329 goto out_path;
377 } 330 }
378 P_INFO("open, established connection to *MONITOR service\n\n");
379 filp->private_data = monpriv; 331 filp->private_data = monpriv;
332 unlock_kernel();
380 return nonseekable_open(inode, filp); 333 return nonseekable_open(inode, filp);
381 334
382out_path: 335out_path:
@@ -386,6 +339,7 @@ out_priv:
386out_use: 339out_use:
387 clear_bit(MON_IN_USE, &mon_in_use); 340 clear_bit(MON_IN_USE, &mon_in_use);
388out: 341out:
342 unlock_kernel();
389 return rc; 343 return rc;
390} 344}
391 345
@@ -400,8 +354,6 @@ static int mon_close(struct inode *inode, struct file *filp)
400 rc = iucv_path_sever(monpriv->path, user_data_sever); 354 rc = iucv_path_sever(monpriv->path, user_data_sever);
401 if (rc) 355 if (rc)
402 P_ERROR("close, iucv_sever failed with rc = %i\n", rc); 356 P_ERROR("close, iucv_sever failed with rc = %i\n", rc);
403 else
404 P_INFO("close, terminated connection to *MONITOR service\n");
405 357
406 atomic_set(&monpriv->iucv_severed, 0); 358 atomic_set(&monpriv->iucv_severed, 0);
407 atomic_set(&monpriv->iucv_connected, 0); 359 atomic_set(&monpriv->iucv_connected, 0);
@@ -442,10 +394,8 @@ static ssize_t mon_read(struct file *filp, char __user *data,
442 monmsg = monpriv->msg_array[monpriv->read_index]; 394 monmsg = monpriv->msg_array[monpriv->read_index];
443 } 395 }
444 396
445 if (!monmsg->pos) { 397 if (!monmsg->pos)
446 monmsg->pos = mon_mca_start(monmsg) + monmsg->mca_offset; 398 monmsg->pos = mon_mca_start(monmsg) + monmsg->mca_offset;
447 mon_read_debug(monmsg, monpriv);
448 }
449 if (mon_check_mca(monmsg)) 399 if (mon_check_mca(monmsg))
450 goto reply; 400 goto reply;
451 401
@@ -531,7 +481,6 @@ static int __init mon_init(void)
531 P_ERROR("failed to register with iucv driver\n"); 481 P_ERROR("failed to register with iucv driver\n");
532 return rc; 482 return rc;
533 } 483 }
534 P_INFO("open, registered with IUCV\n");
535 484
536 rc = segment_type(mon_dcss_name); 485 rc = segment_type(mon_dcss_name);
537 if (rc < 0) { 486 if (rc < 0) {
@@ -555,13 +504,8 @@ static int __init mon_init(void)
555 dcss_mkname(mon_dcss_name, &user_data_connect[8]); 504 dcss_mkname(mon_dcss_name, &user_data_connect[8]);
556 505
557 rc = misc_register(&mon_dev); 506 rc = misc_register(&mon_dev);
558 if (rc < 0 ) { 507 if (rc < 0 )
559 P_ERROR("misc_register failed, rc = %i\n", rc);
560 goto out; 508 goto out;
561 }
562 P_INFO("Loaded segment %s from %p to %p, size = %lu Byte\n",
563 mon_dcss_name, (void *) mon_dcss_start, (void *) mon_dcss_end,
564 mon_dcss_end - mon_dcss_start + 1);
565 return 0; 509 return 0;
566 510
567out: 511out: