aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/chsc_sch.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/chsc_sch.c')
-rw-r--r--drivers/s390/cio/chsc_sch.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index a83877c664a6..e950f1ad4dd1 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -50,7 +50,7 @@ MODULE_LICENSE("GPL");
50 50
51static void chsc_subchannel_irq(struct subchannel *sch) 51static void chsc_subchannel_irq(struct subchannel *sch)
52{ 52{
53 struct chsc_private *private = sch->private; 53 struct chsc_private *private = dev_get_drvdata(&sch->dev);
54 struct chsc_request *request = private->request; 54 struct chsc_request *request = private->request;
55 struct irb *irb = (struct irb *)&S390_lowcore.irb; 55 struct irb *irb = (struct irb *)&S390_lowcore.irb;
56 56
@@ -80,13 +80,14 @@ static int chsc_subchannel_probe(struct subchannel *sch)
80 private = kzalloc(sizeof(*private), GFP_KERNEL); 80 private = kzalloc(sizeof(*private), GFP_KERNEL);
81 if (!private) 81 if (!private)
82 return -ENOMEM; 82 return -ENOMEM;
83 dev_set_drvdata(&sch->dev, private);
83 ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch); 84 ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
84 if (ret) { 85 if (ret) {
85 CHSC_MSG(0, "Failed to enable 0.%x.%04x: %d\n", 86 CHSC_MSG(0, "Failed to enable 0.%x.%04x: %d\n",
86 sch->schid.ssid, sch->schid.sch_no, ret); 87 sch->schid.ssid, sch->schid.sch_no, ret);
88 dev_set_drvdata(&sch->dev, NULL);
87 kfree(private); 89 kfree(private);
88 } else { 90 } else {
89 sch->private = private;
90 if (dev_get_uevent_suppress(&sch->dev)) { 91 if (dev_get_uevent_suppress(&sch->dev)) {
91 dev_set_uevent_suppress(&sch->dev, 0); 92 dev_set_uevent_suppress(&sch->dev, 0);
92 kobject_uevent(&sch->dev.kobj, KOBJ_ADD); 93 kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
@@ -100,8 +101,8 @@ static int chsc_subchannel_remove(struct subchannel *sch)
100 struct chsc_private *private; 101 struct chsc_private *private;
101 102
102 cio_disable_subchannel(sch); 103 cio_disable_subchannel(sch);
103 private = sch->private; 104 private = dev_get_drvdata(&sch->dev);
104 sch->private = NULL; 105 dev_set_drvdata(&sch->dev, NULL);
105 if (private->request) { 106 if (private->request) {
106 complete(&private->request->completion); 107 complete(&private->request->completion);
107 put_device(&sch->dev); 108 put_device(&sch->dev);
@@ -147,7 +148,10 @@ static struct css_device_id chsc_subchannel_ids[] = {
147MODULE_DEVICE_TABLE(css, chsc_subchannel_ids); 148MODULE_DEVICE_TABLE(css, chsc_subchannel_ids);
148 149
149static struct css_driver chsc_subchannel_driver = { 150static struct css_driver chsc_subchannel_driver = {
150 .owner = THIS_MODULE, 151 .drv = {
152 .owner = THIS_MODULE,
153 .name = "chsc_subchannel",
154 },
151 .subchannel_type = chsc_subchannel_ids, 155 .subchannel_type = chsc_subchannel_ids,
152 .irq = chsc_subchannel_irq, 156 .irq = chsc_subchannel_irq,
153 .probe = chsc_subchannel_probe, 157 .probe = chsc_subchannel_probe,
@@ -157,7 +161,6 @@ static struct css_driver chsc_subchannel_driver = {
157 .freeze = chsc_subchannel_freeze, 161 .freeze = chsc_subchannel_freeze,
158 .thaw = chsc_subchannel_restore, 162 .thaw = chsc_subchannel_restore,
159 .restore = chsc_subchannel_restore, 163 .restore = chsc_subchannel_restore,
160 .name = "chsc_subchannel",
161}; 164};
162 165
163static int __init chsc_init_dbfs(void) 166static int __init chsc_init_dbfs(void)
@@ -241,7 +244,7 @@ static int chsc_async(struct chsc_async_area *chsc_area,
241 chsc_area->header.key = PAGE_DEFAULT_KEY >> 4; 244 chsc_area->header.key = PAGE_DEFAULT_KEY >> 4;
242 while ((sch = chsc_get_next_subchannel(sch))) { 245 while ((sch = chsc_get_next_subchannel(sch))) {
243 spin_lock(sch->lock); 246 spin_lock(sch->lock);
244 private = sch->private; 247 private = dev_get_drvdata(&sch->dev);
245 if (private->request) { 248 if (private->request) {
246 spin_unlock(sch->lock); 249 spin_unlock(sch->lock);
247 ret = -EBUSY; 250 ret = -EBUSY;
@@ -688,25 +691,31 @@ out_free:
688 691
689static int chsc_ioctl_chpd(void __user *user_chpd) 692static int chsc_ioctl_chpd(void __user *user_chpd)
690{ 693{
694 struct chsc_scpd *scpd_area;
691 struct chsc_cpd_info *chpd; 695 struct chsc_cpd_info *chpd;
692 int ret; 696 int ret;
693 697
694 chpd = kzalloc(sizeof(*chpd), GFP_KERNEL); 698 chpd = kzalloc(sizeof(*chpd), GFP_KERNEL);
695 if (!chpd) 699 scpd_area = (void *)get_zeroed_page(GFP_KERNEL | GFP_DMA);
696 return -ENOMEM; 700 if (!scpd_area || !chpd) {
701 ret = -ENOMEM;
702 goto out_free;
703 }
697 if (copy_from_user(chpd, user_chpd, sizeof(*chpd))) { 704 if (copy_from_user(chpd, user_chpd, sizeof(*chpd))) {
698 ret = -EFAULT; 705 ret = -EFAULT;
699 goto out_free; 706 goto out_free;
700 } 707 }
701 ret = chsc_determine_channel_path_desc(chpd->chpid, chpd->fmt, 708 ret = chsc_determine_channel_path_desc(chpd->chpid, chpd->fmt,
702 chpd->rfmt, chpd->c, chpd->m, 709 chpd->rfmt, chpd->c, chpd->m,
703 &chpd->chpdb); 710 scpd_area);
704 if (ret) 711 if (ret)
705 goto out_free; 712 goto out_free;
713 memcpy(&chpd->chpdb, &scpd_area->response, scpd_area->response.length);
706 if (copy_to_user(user_chpd, chpd, sizeof(*chpd))) 714 if (copy_to_user(user_chpd, chpd, sizeof(*chpd)))
707 ret = -EFAULT; 715 ret = -EFAULT;
708out_free: 716out_free:
709 kfree(chpd); 717 kfree(chpd);
718 free_page((unsigned long)scpd_area);
710 return ret; 719 return ret;
711} 720}
712 721
@@ -806,6 +815,7 @@ static const struct file_operations chsc_fops = {
806 .open = nonseekable_open, 815 .open = nonseekable_open,
807 .unlocked_ioctl = chsc_ioctl, 816 .unlocked_ioctl = chsc_ioctl,
808 .compat_ioctl = chsc_ioctl, 817 .compat_ioctl = chsc_ioctl,
818 .llseek = no_llseek,
809}; 819};
810 820
811static struct miscdevice chsc_misc_device = { 821static struct miscdevice chsc_misc_device = {