aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/cio/css.c13
-rw-r--r--drivers/s390/cio/css.h2
-rw-r--r--drivers/s390/cio/device.c107
-rw-r--r--drivers/s390/cio/device_fsm.c3
4 files changed, 78 insertions, 47 deletions
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
index 26cf2f5ae2e7..55895c83d499 100644
--- a/drivers/s390/cio/css.c
+++ b/drivers/s390/cio/css.c
@@ -135,14 +135,19 @@ css_register_subchannel(struct subchannel *sch)
135 sch->dev.parent = &css[0]->device; 135 sch->dev.parent = &css[0]->device;
136 sch->dev.bus = &css_bus_type; 136 sch->dev.bus = &css_bus_type;
137 sch->dev.release = &css_subchannel_release; 137 sch->dev.release = &css_subchannel_release;
138 138
139 /* make it known to the system */ 139 /* make it known to the system */
140 ret = css_sch_device_register(sch); 140 ret = css_sch_device_register(sch);
141 if (ret) 141 if (ret) {
142 printk (KERN_WARNING "%s: could not register %s\n", 142 printk (KERN_WARNING "%s: could not register %s\n",
143 __func__, sch->dev.bus_id); 143 __func__, sch->dev.bus_id);
144 else 144 return ret;
145 css_get_ssd_info(sch); 145 }
146 css_get_ssd_info(sch);
147 ret = subchannel_add_files(&sch->dev);
148 if (ret)
149 printk(KERN_WARNING "%s: could not add attributes to %s\n",
150 __func__, sch->dev.bus_id);
146 return ret; 151 return ret;
147} 152}
148 153
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
index dfd5462f993f..ac845c1ebf83 100644
--- a/drivers/s390/cio/css.h
+++ b/drivers/s390/cio/css.h
@@ -189,4 +189,6 @@ extern int need_rescan;
189 189
190extern struct workqueue_struct *slow_path_wq; 190extern struct workqueue_struct *slow_path_wq;
191extern struct work_struct slow_path_work; 191extern struct work_struct slow_path_work;
192
193int subchannel_add_files (struct device *);
192#endif 194#endif
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 0f604621de40..e644fd6905ee 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -294,6 +294,18 @@ online_show (struct device *dev, struct device_attribute *attr, char *buf)
294 return sprintf(buf, cdev->online ? "1\n" : "0\n"); 294 return sprintf(buf, cdev->online ? "1\n" : "0\n");
295} 295}
296 296
297static void ccw_device_unregister(struct work_struct *work)
298{
299 struct ccw_device_private *priv;
300 struct ccw_device *cdev;
301
302 priv = container_of(work, struct ccw_device_private, kick_work);
303 cdev = priv->cdev;
304 if (test_and_clear_bit(1, &cdev->private->registered))
305 device_unregister(&cdev->dev);
306 put_device(&cdev->dev);
307}
308
297static void 309static void
298ccw_device_remove_disconnected(struct ccw_device *cdev) 310ccw_device_remove_disconnected(struct ccw_device *cdev)
299{ 311{
@@ -498,8 +510,7 @@ static struct attribute_group subch_attr_group = {
498 .attrs = subch_attrs, 510 .attrs = subch_attrs,
499}; 511};
500 512
501static inline int 513int subchannel_add_files (struct device *dev)
502subchannel_add_files (struct device *dev)
503{ 514{
504 return sysfs_create_group(&dev->kobj, &subch_attr_group); 515 return sysfs_create_group(&dev->kobj, &subch_attr_group);
505} 516}
@@ -676,6 +687,55 @@ ccw_device_release(struct device *dev)
676 kfree(cdev); 687 kfree(cdev);
677} 688}
678 689
690static struct ccw_device * io_subchannel_allocate_dev(struct subchannel *sch)
691{
692 struct ccw_device *cdev;
693
694 cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
695 if (cdev) {
696 cdev->private = kzalloc(sizeof(struct ccw_device_private),
697 GFP_KERNEL | GFP_DMA);
698 if (cdev->private)
699 return cdev;
700 }
701 kfree(cdev);
702 return ERR_PTR(-ENOMEM);
703}
704
705static int io_subchannel_initialize_dev(struct subchannel *sch,
706 struct ccw_device *cdev)
707{
708 cdev->private->cdev = cdev;
709 atomic_set(&cdev->private->onoff, 0);
710 cdev->dev.parent = &sch->dev;
711 cdev->dev.release = ccw_device_release;
712 INIT_LIST_HEAD(&cdev->private->kick_work.entry);
713 /* Do first half of device_register. */
714 device_initialize(&cdev->dev);
715 if (!get_device(&sch->dev)) {
716 if (cdev->dev.release)
717 cdev->dev.release(&cdev->dev);
718 return -ENODEV;
719 }
720 return 0;
721}
722
723static struct ccw_device * io_subchannel_create_ccwdev(struct subchannel *sch)
724{
725 struct ccw_device *cdev;
726 int ret;
727
728 cdev = io_subchannel_allocate_dev(sch);
729 if (!IS_ERR(cdev)) {
730 ret = io_subchannel_initialize_dev(sch, cdev);
731 if (ret) {
732 kfree(cdev);
733 cdev = ERR_PTR(ret);
734 }
735 }
736 return cdev;
737}
738
679/* 739/*
680 * Register recognized device. 740 * Register recognized device.
681 */ 741 */
@@ -724,11 +784,6 @@ io_subchannel_register(struct work_struct *work)
724 wake_up(&ccw_device_init_wq); 784 wake_up(&ccw_device_init_wq);
725 return; 785 return;
726 } 786 }
727
728 ret = subchannel_add_files(cdev->dev.parent);
729 if (ret)
730 printk(KERN_WARNING "%s: could not add attributes to %s\n",
731 __func__, sch->dev.bus_id);
732 put_device(&cdev->dev); 787 put_device(&cdev->dev);
733out: 788out:
734 cdev->private->flags.recog_done = 1; 789 cdev->private->flags.recog_done = 1;
@@ -851,7 +906,6 @@ io_subchannel_probe (struct subchannel *sch)
851 cdev = sch->dev.driver_data; 906 cdev = sch->dev.driver_data;
852 device_initialize(&cdev->dev); 907 device_initialize(&cdev->dev);
853 ccw_device_register(cdev); 908 ccw_device_register(cdev);
854 subchannel_add_files(&sch->dev);
855 /* 909 /*
856 * Check if the device is already online. If it is 910 * Check if the device is already online. If it is
857 * the reference count needs to be corrected 911 * the reference count needs to be corrected
@@ -864,28 +918,9 @@ io_subchannel_probe (struct subchannel *sch)
864 get_device(&cdev->dev); 918 get_device(&cdev->dev);
865 return 0; 919 return 0;
866 } 920 }
867 cdev = kzalloc (sizeof(*cdev), GFP_KERNEL); 921 cdev = io_subchannel_create_ccwdev(sch);
868 if (!cdev) 922 if (IS_ERR(cdev))
869 return -ENOMEM; 923 return PTR_ERR(cdev);
870 cdev->private = kzalloc(sizeof(struct ccw_device_private),
871 GFP_KERNEL | GFP_DMA);
872 if (!cdev->private) {
873 kfree(cdev);
874 return -ENOMEM;
875 }
876 cdev->private->cdev = cdev;
877 atomic_set(&cdev->private->onoff, 0);
878 cdev->dev.parent = &sch->dev;
879 cdev->dev.release = ccw_device_release;
880 INIT_LIST_HEAD(&cdev->private->kick_work.entry);
881 /* Do first half of device_register. */
882 device_initialize(&cdev->dev);
883
884 if (!get_device(&sch->dev)) {
885 if (cdev->dev.release)
886 cdev->dev.release(&cdev->dev);
887 return -ENODEV;
888 }
889 924
890 rc = io_subchannel_recog(cdev, sch); 925 rc = io_subchannel_recog(cdev, sch);
891 if (rc) { 926 if (rc) {
@@ -899,18 +934,6 @@ io_subchannel_probe (struct subchannel *sch)
899 return rc; 934 return rc;
900} 935}
901 936
902static void ccw_device_unregister(struct work_struct *work)
903{
904 struct ccw_device_private *priv;
905 struct ccw_device *cdev;
906
907 priv = container_of(work, struct ccw_device_private, kick_work);
908 cdev = priv->cdev;
909 if (test_and_clear_bit(1, &cdev->private->registered))
910 device_unregister(&cdev->dev);
911 put_device(&cdev->dev);
912}
913
914static int 937static int
915io_subchannel_remove (struct subchannel *sch) 938io_subchannel_remove (struct subchannel *sch)
916{ 939{
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index 0f0301ce37fe..a487fb0e7d3d 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -1106,7 +1106,8 @@ device_trigger_reprobe(struct subchannel *sch)
1106 /* Update some values. */ 1106 /* Update some values. */
1107 if (stsch(sch->schid, &sch->schib)) 1107 if (stsch(sch->schid, &sch->schib))
1108 return; 1108 return;
1109 1109 if (!sch->schib.pmcw.dnv)
1110 return;
1110 /* 1111 /*
1111 * The pim, pam, pom values may not be accurate, but they are the best 1112 * The pim, pam, pom values may not be accurate, but they are the best
1112 * we have before performing device selection :/ 1113 * we have before performing device selection :/