11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Character device driver for reading z/VM *MONITOR service records. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 42b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer * Copyright IBM Corp. 2004, 2009 52b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer * 62b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 9a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer#define KMSG_COMPONENT "monreader" 10a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 11a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/miscdevice.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ctype.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/spinlock.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 222ca5b6e288d02503cba5a6d3409cb9a0600e01ddGerald Schaefer#include <linux/poll.h> 232b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer#include <linux/device.h> 245a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 252ca5b6e288d02503cba5a6d3409cb9a0600e01ddGerald Schaefer#include <net/iucv/iucv.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/ebcdic.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/extmem.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MON_COLLECT_SAMPLE 0x80 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MON_COLLECT_EVENT 0x40 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MON_SERVICE "*MONITOR" 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MON_IN_USE 0x01 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MON_MSGLIM 255 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char mon_dcss_name[9] = "MONDCSS\0"; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mon_msg { 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 pos; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 mca_offset; 42c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky struct iucv_message msg; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char msglim_reached; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char replied_msglim; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mon_private { 48c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky struct iucv_path *path; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mon_msg *msg_array[MON_MSGLIM]; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int write_index; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned int read_index; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_t msglim_count; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_t read_ready; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_t iucv_connected; 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_t iucv_severed; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long mon_in_use = 0; 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long mon_dcss_start; 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long mon_dcss_end; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DECLARE_WAIT_QUEUE_HEAD(mon_read_wait_queue); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic DECLARE_WAIT_QUEUE_HEAD(mon_conn_wait_queue); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 user_data_connect[16] = { 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Version code, must be 0x01 for shared mode */ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x01, 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* what to collect */ 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MON_COLLECT_SAMPLE | MON_COLLECT_EVENT, 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* DCSS name in EBCDIC, 8 bytes padded with blanks */ 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 user_data_sever[16] = { 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 812b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaeferstatic struct device *monreader_device; 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************** 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * helper functions * 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Create the 8 bytes EBCDIC DCSS segment name from 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * an ASCII name, incl. padding 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 909b0c455a04d73d8ffa388a1006925620ad684ad8Martin Schwidefskystatic void dcss_mkname(char *ascii_name, char *ebcdic_name) 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 8; i++) { 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ascii_name[i] == '\0') 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ebcdic_name[i] = toupper(ascii_name[i]); 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds }; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (; i < 8; i++) 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ebcdic_name[i] = ' '; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ASCEBC(ebcdic_name, 8); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 104c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic inline unsigned long mon_mca_start(struct mon_msg *monmsg) 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 106c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky return *(u32 *) &monmsg->msg.rmmsg; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 109c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic inline unsigned long mon_mca_end(struct mon_msg *monmsg) 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 111c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky return *(u32 *) &monmsg->msg.rmmsg[4]; 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 114c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic inline u8 mon_mca_type(struct mon_msg *monmsg, u8 index) 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return *((u8 *) mon_mca_start(monmsg) + monmsg->mca_offset + index); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 119c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic inline u32 mon_mca_size(struct mon_msg *monmsg) 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return mon_mca_end(monmsg) - mon_mca_start(monmsg) + 1; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 124c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic inline u32 mon_rec_start(struct mon_msg *monmsg) 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 4)); 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 129c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic inline u32 mon_rec_end(struct mon_msg *monmsg) 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return *((u32 *) (mon_mca_start(monmsg) + monmsg->mca_offset + 8)); 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1349b0c455a04d73d8ffa388a1006925620ad684ad8Martin Schwidefskystatic int mon_check_mca(struct mon_msg *monmsg) 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((mon_rec_end(monmsg) <= mon_rec_start(monmsg)) || 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (mon_rec_start(monmsg) < mon_dcss_start) || 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (mon_rec_end(monmsg) > mon_dcss_end) || 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (mon_mca_type(monmsg, 0) == 0) || 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (mon_mca_size(monmsg) % 12 != 0) || 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (mon_mca_end(monmsg) <= mon_mca_start(monmsg)) || 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (mon_mca_end(monmsg) > mon_dcss_end) || 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (mon_mca_start(monmsg) < mon_dcss_start) || 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ((mon_mca_type(monmsg, 1) == 0) && (mon_mca_type(monmsg, 2) == 0))) 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1499b0c455a04d73d8ffa388a1006925620ad684ad8Martin Schwidefskystatic int mon_send_reply(struct mon_msg *monmsg, 1509b0c455a04d73d8ffa388a1006925620ad684ad8Martin Schwidefsky struct mon_private *monpriv) 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 154c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky rc = iucv_message_reply(monpriv->path, &monmsg->msg, 155c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky IUCV_IPRMDATA, NULL, 0); 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_dec(&monpriv->msglim_count); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely(!monmsg->msglim_reached)) { 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->pos = 0; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->mca_offset = 0; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monpriv->read_index = (monpriv->read_index + 1) % 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MON_MSGLIM; 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_dec(&monpriv->read_ready); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->replied_msglim = 1; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 166a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer pr_err("Reading monitor data failed with rc=%i\n", rc); 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1729b0c455a04d73d8ffa388a1006925620ad684ad8Martin Schwidefskystatic void mon_free_mem(struct mon_private *monpriv) 173c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky{ 174c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky int i; 175c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky 176c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky for (i = 0; i < MON_MSGLIM; i++) 177a75a282d7238f6020957b14d8a14a1e851b9e1ddSyam Sidhardhan kfree(monpriv->msg_array[i]); 178c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky kfree(monpriv); 179c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky} 180c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky 1819b0c455a04d73d8ffa388a1006925620ad684ad8Martin Schwidefskystatic struct mon_private *mon_alloc_mem(void) 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 183c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky int i; 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mon_private *monpriv; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 18688abaab4f9b08381e30e737980a1c49d6b524dfcEric Sesterhenn monpriv = kzalloc(sizeof(struct mon_private), GFP_KERNEL); 1872ca5b6e288d02503cba5a6d3409cb9a0600e01ddGerald Schaefer if (!monpriv) 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MON_MSGLIM; i++) { 19088abaab4f9b08381e30e737980a1c49d6b524dfcEric Sesterhenn monpriv->msg_array[i] = kzalloc(sizeof(struct mon_msg), 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds GFP_KERNEL); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!monpriv->msg_array[i]) { 193c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky mon_free_mem(monpriv); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return monpriv; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 200c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic inline void mon_next_mca(struct mon_msg *monmsg) 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (likely((mon_mca_size(monmsg) - monmsg->mca_offset) == 12)) 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->mca_offset += 12; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->pos = 0; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2089b0c455a04d73d8ffa388a1006925620ad684ad8Martin Schwidefskystatic struct mon_msg *mon_next_message(struct mon_private *monpriv) 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mon_msg *monmsg; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!atomic_read(&monpriv->read_ready)) 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg = monpriv->msg_array[monpriv->read_index]; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(monmsg->replied_msglim)) { 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->replied_msglim = 0; 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->msglim_reached = 0; 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->pos = 0; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->mca_offset = 0; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monpriv->read_index = (monpriv->read_index + 1) % 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MON_MSGLIM; 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_dec(&monpriv->read_ready); 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-EOVERFLOW); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return monmsg; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************** 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IUCV handler * 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 232c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic void mon_iucv_path_complete(struct iucv_path *path, u8 ipuser[16]) 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 234c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky struct mon_private *monpriv = path->private; 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set(&monpriv->iucv_connected, 1); 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up(&mon_conn_wait_queue); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 240c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic void mon_iucv_path_severed(struct iucv_path *path, u8 ipuser[16]) 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 242c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky struct mon_private *monpriv = path->private; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 244a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer pr_err("z/VM *MONITOR system service disconnected with rc=%i\n", 245a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer ipuser[0]); 246c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky iucv_path_sever(path, NULL); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set(&monpriv->iucv_severed, 1); 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up(&mon_conn_wait_queue); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up_interruptible(&mon_read_wait_queue); 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 252c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic void mon_iucv_message_pending(struct iucv_path *path, 253c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky struct iucv_message *msg) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 255c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky struct mon_private *monpriv = path->private; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 257c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky memcpy(&monpriv->msg_array[monpriv->write_index]->msg, 258c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky msg, sizeof(*msg)); 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_inc_return(&monpriv->msglim_count) == MON_MSGLIM) { 260a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer pr_warning("The read queue for monitor data is full\n"); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monpriv->msg_array[monpriv->write_index]->msglim_reached = 1; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monpriv->write_index = (monpriv->write_index + 1) % MON_MSGLIM; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_inc(&monpriv->read_ready); 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wake_up_interruptible(&mon_read_wait_queue); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 268c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic struct iucv_handler monreader_iucv_handler = { 269c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky .path_complete = mon_iucv_path_complete, 270c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky .path_severed = mon_iucv_path_severed, 271c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky .message_pending = mon_iucv_message_pending, 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************** 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * file operations * 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 277c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic int mon_open(struct inode *inode, struct file *filp) 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mon_private *monpriv; 280c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky int rc; 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * only one user allowed 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 285c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky rc = -EBUSY; 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (test_and_set_bit(MON_IN_USE, &mon_in_use)) 287c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky goto out; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 289c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky rc = -ENOMEM; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monpriv = mon_alloc_mem(); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!monpriv) 292c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky goto out_use; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 295c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky * Connect to *MONITOR service 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 297c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky monpriv->path = iucv_path_alloc(MON_MSGLIM, IUCV_IPRMDATA, GFP_KERNEL); 298c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky if (!monpriv->path) 299c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky goto out_priv; 300c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky rc = iucv_path_connect(monpriv->path, &monreader_iucv_handler, 301c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky MON_SERVICE, NULL, user_data_connect, monpriv); 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc) { 303a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer pr_err("Connecting to the z/VM *MONITOR system service " 304a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer "failed with rc=%i\n", rc); 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -EIO; 306c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky goto out_path; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Wait for connection confirmation 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_event(mon_conn_wait_queue, 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_read(&monpriv->iucv_connected) || 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_read(&monpriv->iucv_severed)); 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_read(&monpriv->iucv_severed)) { 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set(&monpriv->iucv_severed, 0); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set(&monpriv->iucv_connected, 0); 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = -EIO; 318c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky goto out_path; 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds filp->private_data = monpriv; 3219935774217afd4cdda81ffd70e56dc6406710b06Heiko Carstens dev_set_drvdata(monreader_device, monpriv); 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return nonseekable_open(inode, filp); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 324c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskyout_path: 3252b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer iucv_path_free(monpriv->path); 326c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskyout_priv: 327c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky mon_free_mem(monpriv); 328c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskyout_use: 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clear_bit(MON_IN_USE, &mon_in_use); 330c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskyout: 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 334c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic int mon_close(struct inode *inode, struct file *filp) 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc, i; 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mon_private *monpriv = filp->private_data; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Close IUCV connection and unregister 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 3422b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer if (monpriv->path) { 3432b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer rc = iucv_path_sever(monpriv->path, user_data_sever); 3442b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer if (rc) 3452b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer pr_warning("Disconnecting the z/VM *MONITOR system " 3462b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer "service failed with rc=%i\n", rc); 3472b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer iucv_path_free(monpriv->path); 3482b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer } 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set(&monpriv->iucv_severed, 0); 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set(&monpriv->iucv_connected, 0); 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set(&monpriv->read_ready, 0); 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_set(&monpriv->msglim_count, 0); 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monpriv->write_index = 0; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monpriv->read_index = 0; 356ccaf6553963bc6304d5820962a08a4397d0a2dc2Gerald Schaefer dev_set_drvdata(monreader_device, NULL); 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < MON_MSGLIM; i++) 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(monpriv->msg_array[i]); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(monpriv); 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clear_bit(MON_IN_USE, &mon_in_use); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 365c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic ssize_t mon_read(struct file *filp, char __user *data, 366c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky size_t count, loff_t *ppos) 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mon_private *monpriv = filp->private_data; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mon_msg *monmsg; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 mce_start; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg = mon_next_message(monpriv); 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (IS_ERR(monmsg)) 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return PTR_ERR(monmsg); 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!monmsg) { 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (filp->f_flags & O_NONBLOCK) 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EAGAIN; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = wait_event_interruptible(mon_read_wait_queue, 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_read(&monpriv->read_ready) || 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds atomic_read(&monpriv->iucv_severed)); 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(atomic_read(&monpriv->iucv_severed))) 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg = monpriv->msg_array[monpriv->read_index]; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3902ca5b6e288d02503cba5a6d3409cb9a0600e01ddGerald Schaefer if (!monmsg->pos) 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->pos = mon_mca_start(monmsg) + monmsg->mca_offset; 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mon_check_mca(monmsg)) 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto reply; 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* read monitor control element (12 bytes) first */ 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mce_start = mon_mca_start(monmsg) + monmsg->mca_offset; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((monmsg->pos >= mce_start) && (monmsg->pos < mce_start + 12)) { 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = min(count, (size_t) mce_start + 12 - monmsg->pos); 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = copy_to_user(data, (void *) (unsigned long) monmsg->pos, 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count); 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->pos += count; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (monmsg->pos == mce_start + 12) 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->pos = mon_rec_start(monmsg); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_copy; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* read records */ 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (monmsg->pos <= mon_rec_end(monmsg)) { 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = min(count, (size_t) mon_rec_end(monmsg) - monmsg->pos 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds + 1); 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = copy_to_user(data, (void *) (unsigned long) monmsg->pos, 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count); 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds monmsg->pos += count; 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (monmsg->pos > mon_rec_end(monmsg)) 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mon_next_mca(monmsg); 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_copy; 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreply: 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = mon_send_reply(monmsg, monpriv); 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_copy: 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *ppos += count; 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic unsigned int mon_poll(struct file *filp, struct poll_table_struct *p) 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct mon_private *monpriv = filp->private_data; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds poll_wait(filp, &mon_read_wait_queue, p); 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (unlikely(atomic_read(&monpriv->iucv_severed))) 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return POLLERR; 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (atomic_read(&monpriv->read_ready)) 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return POLLIN | POLLRDNORM; 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 443d54b1fdb1d9f82e375a299e22bd366aad52d4c34Arjan van de Venstatic const struct file_operations mon_fops = { 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .owner = THIS_MODULE, 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .open = &mon_open, 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .release = &mon_close, 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .read = &mon_read, 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .poll = &mon_poll, 4496038f373a3dc1f1c26496e60b6c40b164716f07eArnd Bergmann .llseek = noop_llseek, 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct miscdevice mon_dev = { 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "monreader", 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .fops = &mon_fops, 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .minor = MISC_DYNAMIC_MINOR, 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4582b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer 4592b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer/****************************************************************************** 4602b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer * suspend / resume * 4612b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer *****************************************************************************/ 4622b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaeferstatic int monreader_freeze(struct device *dev) 4632b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer{ 4649935774217afd4cdda81ffd70e56dc6406710b06Heiko Carstens struct mon_private *monpriv = dev_get_drvdata(dev); 4652b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer int rc; 4662b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer 4672b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer if (!monpriv) 4682b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer return 0; 4692b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer if (monpriv->path) { 4702b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer rc = iucv_path_sever(monpriv->path, user_data_sever); 4712b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer if (rc) 4722b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer pr_warning("Disconnecting the z/VM *MONITOR system " 4732b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer "service failed with rc=%i\n", rc); 4742b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer iucv_path_free(monpriv->path); 4752b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer } 4762b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer atomic_set(&monpriv->iucv_severed, 0); 4772b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer atomic_set(&monpriv->iucv_connected, 0); 4782b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer atomic_set(&monpriv->read_ready, 0); 4792b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer atomic_set(&monpriv->msglim_count, 0); 4802b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer monpriv->write_index = 0; 4812b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer monpriv->read_index = 0; 4822b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer monpriv->path = NULL; 4832b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer return 0; 4842b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer} 4852b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer 4862b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaeferstatic int monreader_thaw(struct device *dev) 4872b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer{ 4884f0076f77fb64889d4e5e425b63333e5764b446dMartin Schwidefsky struct mon_private *monpriv = dev_get_drvdata(dev); 4892b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer int rc; 4902b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer 4912b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer if (!monpriv) 4922b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer return 0; 4932b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer rc = -ENOMEM; 4942b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer monpriv->path = iucv_path_alloc(MON_MSGLIM, IUCV_IPRMDATA, GFP_KERNEL); 4952b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer if (!monpriv->path) 4962b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer goto out; 4972b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer rc = iucv_path_connect(monpriv->path, &monreader_iucv_handler, 4982b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer MON_SERVICE, NULL, user_data_connect, monpriv); 4992b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer if (rc) { 5002b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer pr_err("Connecting to the z/VM *MONITOR system service " 5012b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer "failed with rc=%i\n", rc); 5022b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer goto out_path; 5032b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer } 5042b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer wait_event(mon_conn_wait_queue, 5052b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer atomic_read(&monpriv->iucv_connected) || 5062b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer atomic_read(&monpriv->iucv_severed)); 5072b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer if (atomic_read(&monpriv->iucv_severed)) 5082b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer goto out_path; 5092b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer return 0; 5102b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaeferout_path: 5112b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer rc = -EIO; 5122b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer iucv_path_free(monpriv->path); 5132b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer monpriv->path = NULL; 5142b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaeferout: 5152b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer atomic_set(&monpriv->iucv_severed, 1); 5162b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer return rc; 5172b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer} 5182b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer 5192b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaeferstatic int monreader_restore(struct device *dev) 5202b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer{ 5212b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer int rc; 5222b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer 5232b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer segment_unload(mon_dcss_name); 5242b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer rc = segment_load(mon_dcss_name, SEGMENT_SHARED, 5252b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer &mon_dcss_start, &mon_dcss_end); 5262b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer if (rc < 0) { 5272b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer segment_warning(rc, mon_dcss_name); 5282b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer panic("fatal monreader resume error: no monitor dcss\n"); 5292b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer } 5302b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer return monreader_thaw(dev); 5312b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer} 5322b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer 533471452104b8520337ae2fb48c4e61cd4896e025dAlexey Dobriyanstatic const struct dev_pm_ops monreader_pm_ops = { 5342b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer .freeze = monreader_freeze, 5352b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer .thaw = monreader_thaw, 5362b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer .restore = monreader_restore, 5372b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer}; 5382b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer 5392b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaeferstatic struct device_driver monreader_driver = { 5402b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer .name = "monreader", 5412b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer .bus = &iucv_bus, 5422b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer .pm = &monreader_pm_ops, 5432b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer}; 5442b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer 5452b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/****************************************************************************** 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * module init/exit * 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *****************************************************************************/ 549c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic int __init mon_init(void) 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int rc; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!MACHINE_IS_VM) { 554a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer pr_err("The z/VM *MONITOR record device driver cannot be " 555a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer "loaded without z/VM\n"); 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 559c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky /* 560c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky * Register with IUCV and connect to *MONITOR service 561c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky */ 562c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky rc = iucv_register(&monreader_iucv_handler, 1); 563c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky if (rc) { 564a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer pr_err("The z/VM *MONITOR record device driver failed to " 565a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer "register with IUCV\n"); 566c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky return rc; 567c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky } 568c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky 5692b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer rc = driver_register(&monreader_driver); 5702b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer if (rc) 5712b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer goto out_iucv; 5722b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer monreader_device = kzalloc(sizeof(struct device), GFP_KERNEL); 57372abaadf25f2bc6098740622e4ed526775b197f9Peter Senna Tschudin if (!monreader_device) { 57472abaadf25f2bc6098740622e4ed526775b197f9Peter Senna Tschudin rc = -ENOMEM; 5752b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer goto out_driver; 57672abaadf25f2bc6098740622e4ed526775b197f9Peter Senna Tschudin } 57772abaadf25f2bc6098740622e4ed526775b197f9Peter Senna Tschudin 5782b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer dev_set_name(monreader_device, "monreader-dev"); 5792b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer monreader_device->bus = &iucv_bus; 5802b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer monreader_device->parent = iucv_root; 5812b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer monreader_device->driver = &monreader_driver; 5822b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer monreader_device->release = (void (*)(struct device *))kfree; 5832b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer rc = device_register(monreader_device); 5842b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer if (rc) { 585c6304933274f8e3cc6983d496456757ac8ab2e0bSebastian Ott put_device(monreader_device); 5862b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer goto out_driver; 5872b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer } 5882b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = segment_type(mon_dcss_name); 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc < 0) { 591ca68305bf3c76c4a7cd1c77d5423219f39164df8Martin Schwidefsky segment_warning(rc, mon_dcss_name); 5922b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer goto out_device; 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc != SEG_TYPE_SC) { 595a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer pr_err("The specified *MONITOR DCSS %s does not have the " 596a4f5a299cf8468619dc17f0711017c6d72d6ab94Gerald Schaefer "required type SC\n", mon_dcss_name); 597c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky rc = -EINVAL; 5982b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer goto out_device; 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = segment_load(mon_dcss_name, SEGMENT_SHARED, 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &mon_dcss_start, &mon_dcss_end); 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (rc < 0) { 604ca68305bf3c76c4a7cd1c77d5423219f39164df8Martin Schwidefsky segment_warning(rc, mon_dcss_name); 605c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky rc = -EINVAL; 6062b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer goto out_device; 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dcss_mkname(mon_dcss_name, &user_data_connect[8]); 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6101963403aae0fc5a4e20cf2e51e4f0148fdf938b4Gerald Schaefer /* 6111963403aae0fc5a4e20cf2e51e4f0148fdf938b4Gerald Schaefer * misc_register() has to be the last action in module_init(), because 6121963403aae0fc5a4e20cf2e51e4f0148fdf938b4Gerald Schaefer * file operations will be available right after this. 6131963403aae0fc5a4e20cf2e51e4f0148fdf938b4Gerald Schaefer */ 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rc = misc_register(&mon_dev); 6152ca5b6e288d02503cba5a6d3409cb9a0600e01ddGerald Schaefer if (rc < 0 ) 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout: 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds segment_unload(mon_dcss_name); 6212b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaeferout_device: 6222b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer device_unregister(monreader_device); 6232b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaeferout_driver: 6242b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer driver_unregister(&monreader_driver); 625c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskyout_iucv: 626c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky iucv_unregister(&monreader_iucv_handler, 1); 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return rc; 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 630c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefskystatic void __exit mon_exit(void) 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds segment_unload(mon_dcss_name); 633547415d5edf8660aee040dc81d8c71b081a59bdaAkinobu Mita misc_deregister(&mon_dev); 6342b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer device_unregister(monreader_device); 6352b1e3e5558b9de0f85ed9183a7adb2d61aab363bGerald Schaefer driver_unregister(&monreader_driver); 636c667aac8009b41ecaecb1fc72476553cf12d4732Martin Schwidefsky iucv_unregister(&monreader_iucv_handler, 1); 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mon_init); 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mon_exit); 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_string(mondcss, mon_dcss_name, 9, 0444); 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(mondcss, "Name of DCSS segment to be used for *MONITOR " 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "service, max. 8 chars. Default is MONDCSS"); 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Gerald Schaefer <geraldsc@de.ibm.com>"); 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Character device driver for reading z/VM " 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "monitor service records."); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 652