diff options
| -rw-r--r-- | drivers/s390/char/monreader.c | 74 |
1 files changed, 7 insertions, 67 deletions
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 1e1f50655bbf..f0e4c96afbf8 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c | |||
| @@ -3,9 +3,8 @@ | |||
| 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> |
| @@ -18,12 +17,11 @@ | |||
| 18 | #include <linux/ctype.h> | 17 | #include <linux/ctype.h> |
| 19 | #include <linux/spinlock.h> | 18 | #include <linux/spinlock.h> |
| 20 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
| 20 | #include <linux/poll.h> | ||
| 21 | #include <net/iucv/iucv.h> | ||
| 21 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
| 22 | #include <asm/ebcdic.h> | 23 | #include <asm/ebcdic.h> |
| 23 | #include <asm/extmem.h> | 24 | #include <asm/extmem.h> |
| 24 | #include <linux/poll.h> | ||
| 25 | #include <net/iucv/iucv.h> | ||
| 26 | |||
| 27 | 25 | ||
| 28 | //#define MON_DEBUG /* Debug messages on/off */ | 26 | //#define MON_DEBUG /* Debug messages on/off */ |
| 29 | 27 | ||
| @@ -152,10 +150,7 @@ static int mon_check_mca(struct mon_msg *monmsg) | |||
| 152 | (mon_mca_end(monmsg) > mon_dcss_end) || | 150 | (mon_mca_end(monmsg) > mon_dcss_end) || |
| 153 | (mon_mca_start(monmsg) < mon_dcss_start) || | 151 | (mon_mca_start(monmsg) < mon_dcss_start) || |
| 154 | ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0))) | 152 | ((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; | 153 | return -EINVAL; |
| 158 | } | ||
| 159 | return 0; | 154 | return 0; |
| 160 | } | 155 | } |
| 161 | 156 | ||
| @@ -164,10 +159,6 @@ static int mon_send_reply(struct mon_msg *monmsg, | |||
| 164 | { | 159 | { |
| 165 | int rc; | 160 | int rc; |
| 166 | 161 | ||
| 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, | 162 | rc = iucv_message_reply(monpriv->path, &monmsg->msg, |
| 172 | IUCV_IPRMDATA, NULL, 0); | 163 | IUCV_IPRMDATA, NULL, 0); |
| 173 | atomic_dec(&monpriv->msglim_count); | 164 | atomic_dec(&monpriv->msglim_count); |
| @@ -202,15 +193,12 @@ static struct mon_private *mon_alloc_mem(void) | |||
| 202 | struct mon_private *monpriv; | 193 | struct mon_private *monpriv; |
| 203 | 194 | ||
| 204 | monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); | 195 | monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); |
| 205 | if (!monpriv) { | 196 | if (!monpriv) |
| 206 | P_ERROR("no memory for monpriv\n"); | ||
| 207 | return NULL; | 197 | return NULL; |
| 208 | } | ||
| 209 | for (i = 0; i < MON_MSGLIM; i++) { | 198 | for (i = 0; i < MON_MSGLIM; i++) { |
| 210 | monpriv->msg_array[i] = kzalloc(sizeof(struct mon_msg), | 199 | monpriv->msg_array[i] = kzalloc(sizeof(struct mon_msg), |
| 211 | GFP_KERNEL); | 200 | GFP_KERNEL); |
| 212 | if (!monpriv->msg_array[i]) { | 201 | if (!monpriv->msg_array[i]) { |
| 213 | P_ERROR("open, no memory for msg_array\n"); | ||
| 214 | mon_free_mem(monpriv); | 202 | mon_free_mem(monpriv); |
| 215 | return NULL; | 203 | return NULL; |
| 216 | } | 204 | } |
| @@ -218,41 +206,10 @@ static struct mon_private *mon_alloc_mem(void) | |||
| 218 | return monpriv; | 206 | return monpriv; |
| 219 | } | 207 | } |
| 220 | 208 | ||
| 221 | static 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 | |||
| 251 | static inline void mon_next_mca(struct mon_msg *monmsg) | 209 | static inline void mon_next_mca(struct mon_msg *monmsg) |
| 252 | { | 210 | { |
| 253 | if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12)) | 211 | if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12)) |
| 254 | return; | 212 | return; |
| 255 | P_DEBUG("READ, NEXT MCA\n\n"); | ||
| 256 | monmsg->mca_offset += 12; | 213 | monmsg->mca_offset += 12; |
| 257 | monmsg->pos = 0; | 214 | monmsg->pos = 0; |
| 258 | } | 215 | } |
| @@ -269,7 +226,6 @@ static struct mon_msg *mon_next_message(struct mon_private *monpriv) | |||
| 269 | monmsg->msglim_reached = 0; | 226 | monmsg->msglim_reached = 0; |
| 270 | monmsg->pos = 0; | 227 | monmsg->pos = 0; |
| 271 | monmsg->mca_offset = 0; | 228 | monmsg->mca_offset = 0; |
| 272 | P_WARNING("read, message limit reached\n"); | ||
| 273 | monpriv->read_index = (monpriv->read_index + 1) % | 229 | monpriv->read_index = (monpriv->read_index + 1) % |
| 274 | MON_MSGLIM; | 230 | MON_MSGLIM; |
| 275 | atomic_dec(&monpriv->read_ready); | 231 | atomic_dec(&monpriv->read_ready); |
| @@ -286,10 +242,6 @@ static void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16]) | |||
| 286 | { | 242 | { |
| 287 | struct mon_private *monpriv = path->private; | 243 | struct mon_private *monpriv = path->private; |
| 288 | 244 | ||
| 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); | 245 | atomic_set(&monpriv->iucv_connected, 1); |
| 294 | wake_up(&mon_conn_wait_queue); | 246 | wake_up(&mon_conn_wait_queue); |
| 295 | } | 247 | } |
| @@ -310,7 +262,6 @@ static void mon_iucv_message_pending(struct iucv_path *path, | |||
| 310 | { | 262 | { |
| 311 | struct mon_private *monpriv = path->private; | 263 | struct mon_private *monpriv = path->private; |
| 312 | 264 | ||
| 313 | P_DEBUG("IUCV message pending\n"); | ||
| 314 | memcpy(&monpriv->msg_array[monpriv->write_index]->msg, | 265 | memcpy(&monpriv->msg_array[monpriv->write_index]->msg, |
| 315 | msg, sizeof(*msg)); | 266 | msg, sizeof(*msg)); |
| 316 | if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) { | 267 | if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) { |
| @@ -375,7 +326,6 @@ static int mon_open(struct inode *inode, struct file *filp) | |||
| 375 | rc = -EIO; | 326 | rc = -EIO; |
| 376 | goto out_path; | 327 | goto out_path; |
| 377 | } | 328 | } |
| 378 | P_INFO("open, established connection to *MONITOR service\n\n"); | ||
| 379 | filp->private_data = monpriv; | 329 | filp->private_data = monpriv; |
| 380 | return nonseekable_open(inode, filp); | 330 | return nonseekable_open(inode, filp); |
| 381 | 331 | ||
| @@ -400,8 +350,6 @@ static int mon_close(struct inode *inode, struct file *filp) | |||
| 400 | rc = iucv_path_sever(monpriv->path, user_data_sever); | 350 | rc = iucv_path_sever(monpriv->path, user_data_sever); |
| 401 | if (rc) | 351 | if (rc) |
| 402 | P_ERROR("close, iucv_sever failed with rc = %i\n", rc); | 352 | P_ERROR("close, iucv_sever failed with rc = %i\n", rc); |
| 403 | else | ||
| 404 | P_INFO("close, terminated connection to *MONITOR service\n"); | ||
| 405 | 353 | ||
| 406 | atomic_set(&monpriv->iucv_severed, 0); | 354 | atomic_set(&monpriv->iucv_severed, 0); |
| 407 | atomic_set(&monpriv->iucv_connected, 0); | 355 | atomic_set(&monpriv->iucv_connected, 0); |
| @@ -442,10 +390,8 @@ static ssize_t mon_read(struct file *filp, char __user *data, | |||
| 442 | monmsg = monpriv->msg_array[monpriv->read_index]; | 390 | monmsg = monpriv->msg_array[monpriv->read_index]; |
| 443 | } | 391 | } |
| 444 | 392 | ||
| 445 | if (!monmsg->pos) { | 393 | if (!monmsg->pos) |
| 446 | monmsg->pos = mon_mca_start(monmsg) + monmsg->mca_offset; | 394 | monmsg->pos = mon_mca_start(monmsg) + monmsg->mca_offset; |
| 447 | mon_read_debug(monmsg, monpriv); | ||
| 448 | } | ||
| 449 | if (mon_check_mca(monmsg)) | 395 | if (mon_check_mca(monmsg)) |
| 450 | goto reply; | 396 | goto reply; |
| 451 | 397 | ||
| @@ -531,7 +477,6 @@ static int __init mon_init(void) | |||
| 531 | P_ERROR("failed to register with iucv driver\n"); | 477 | P_ERROR("failed to register with iucv driver\n"); |
| 532 | return rc; | 478 | return rc; |
| 533 | } | 479 | } |
| 534 | P_INFO("open, registered with IUCV\n"); | ||
| 535 | 480 | ||
| 536 | rc = segment_type(mon_dcss_name); | 481 | rc = segment_type(mon_dcss_name); |
| 537 | if (rc < 0) { | 482 | if (rc < 0) { |
| @@ -555,13 +500,8 @@ static int __init mon_init(void) | |||
| 555 | dcss_mkname(mon_dcss_name, &user_data_connect[8]); | 500 | dcss_mkname(mon_dcss_name, &user_data_connect[8]); |
| 556 | 501 | ||
| 557 | rc = misc_register(&mon_dev); | 502 | rc = misc_register(&mon_dev); |
| 558 | if (rc < 0 ) { | 503 | if (rc < 0 ) |
| 559 | P_ERROR("misc_register failed, rc = %i\n", rc); | ||
| 560 | goto out; | 504 | 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; | 505 | return 0; |
| 566 | 506 | ||
| 567 | out: | 507 | out: |
