#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/poll.h>
-#include <linux/device.h>
#include <linux/slab.h>
#include <net/iucv/iucv.h>
#include <linux/uaccess.h>
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
-static struct device *monreader_device;
-
/******************************************************************************
* helper functions *
*****************************************************************************/
goto out_path;
}
filp->private_data = monpriv;
- dev_set_drvdata(monreader_device, monpriv);
return nonseekable_open(inode, filp);
out_path:
atomic_set(&monpriv->msglim_count, 0);
monpriv->write_index = 0;
monpriv->read_index = 0;
- dev_set_drvdata(monreader_device, NULL);
for (i = 0; i < MON_MSGLIM; i++)
kfree(monpriv->msg_array[i]);
.minor = MISC_DYNAMIC_MINOR,
};
-
-/******************************************************************************
- * suspend / resume *
- *****************************************************************************/
-static int monreader_freeze(struct device *dev)
-{
- struct mon_private *monpriv = dev_get_drvdata(dev);
- int rc;
-
- if (!monpriv)
- return 0;
- if (monpriv->path) {
- rc = iucv_path_sever(monpriv->path, user_data_sever);
- if (rc)
- pr_warn("Disconnecting the z/VM *MONITOR system service failed with rc=%i\n",
- rc);
- iucv_path_free(monpriv->path);
- }
- atomic_set(&monpriv->iucv_severed, 0);
- atomic_set(&monpriv->iucv_connected, 0);
- atomic_set(&monpriv->read_ready, 0);
- atomic_set(&monpriv->msglim_count, 0);
- monpriv->write_index = 0;
- monpriv->read_index = 0;
- monpriv->path = NULL;
- return 0;
-}
-
-static int monreader_thaw(struct device *dev)
-{
- struct mon_private *monpriv = dev_get_drvdata(dev);
- int rc;
-
- if (!monpriv)
- return 0;
- rc = -ENOMEM;
- monpriv->path = iucv_path_alloc(MON_MSGLIM, IUCV_IPRMDATA, GFP_KERNEL);
- if (!monpriv->path)
- goto out;
- rc = iucv_path_connect(monpriv->path, &monreader_iucv_handler,
- MON_SERVICE, NULL, user_data_connect, monpriv);
- if (rc) {
- pr_err("Connecting to the z/VM *MONITOR system service "
- "failed with rc=%i\n", rc);
- goto out_path;
- }
- wait_event(mon_conn_wait_queue,
- atomic_read(&monpriv->iucv_connected) ||
- atomic_read(&monpriv->iucv_severed));
- if (atomic_read(&monpriv->iucv_severed))
- goto out_path;
- return 0;
-out_path:
- rc = -EIO;
- iucv_path_free(monpriv->path);
- monpriv->path = NULL;
-out:
- atomic_set(&monpriv->iucv_severed, 1);
- return rc;
-}
-
-static int monreader_restore(struct device *dev)
-{
- int rc;
-
- segment_unload(mon_dcss_name);
- rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
- &mon_dcss_start, &mon_dcss_end);
- if (rc < 0) {
- segment_warning(rc, mon_dcss_name);
- panic("fatal monreader resume error: no monitor dcss\n");
- }
- return monreader_thaw(dev);
-}
-
-static const struct dev_pm_ops monreader_pm_ops = {
- .freeze = monreader_freeze,
- .thaw = monreader_thaw,
- .restore = monreader_restore,
-};
-
-static struct device_driver monreader_driver = {
- .name = "monreader",
- .bus = &iucv_bus,
- .pm = &monreader_pm_ops,
-};
-
-
/******************************************************************************
* module init/exit *
*****************************************************************************/
return rc;
}
- rc = driver_register(&monreader_driver);
- if (rc)
- goto out_iucv;
- monreader_device = kzalloc(sizeof(struct device), GFP_KERNEL);
- if (!monreader_device) {
- rc = -ENOMEM;
- goto out_driver;
- }
-
- dev_set_name(monreader_device, "monreader-dev");
- monreader_device->bus = &iucv_bus;
- monreader_device->parent = iucv_root;
- monreader_device->driver = &monreader_driver;
- monreader_device->release = (void (*)(struct device *))kfree;
- rc = device_register(monreader_device);
- if (rc) {
- put_device(monreader_device);
- goto out_driver;
- }
-
rc = segment_type(mon_dcss_name);
if (rc < 0) {
segment_warning(rc, mon_dcss_name);
- goto out_device;
+ goto out_iucv;
}
if (rc != SEG_TYPE_SC) {
pr_err("The specified *MONITOR DCSS %s does not have the "
"required type SC\n", mon_dcss_name);
rc = -EINVAL;
- goto out_device;
+ goto out_iucv;
}
rc = segment_load(mon_dcss_name, SEGMENT_SHARED,
if (rc < 0) {
segment_warning(rc, mon_dcss_name);
rc = -EINVAL;
- goto out_device;
+ goto out_iucv;
}
dcss_mkname(mon_dcss_name, &user_data_connect[8]);
out:
segment_unload(mon_dcss_name);
-out_device:
- device_unregister(monreader_device);
-out_driver:
- driver_unregister(&monreader_driver);
out_iucv:
iucv_unregister(&monreader_iucv_handler, 1);
return rc;
{
segment_unload(mon_dcss_name);
misc_deregister(&mon_dev);
- device_unregister(monreader_device);
- driver_unregister(&monreader_driver);
iucv_unregister(&monreader_iucv_handler, 1);
return;
}