diff options
| author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2006-12-08 09:54:21 -0500 |
|---|---|---|
| committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-12-08 09:54:21 -0500 |
| commit | 7674da77cb2d27ae6559c55151da171ceb02beb4 (patch) | |
| tree | dca2646cd8d6d2a36cbddbeb4f38fab2e12e8f7b /drivers/s390 | |
| parent | 34249d0f9243fce773c2fa352934ba108320e234 (diff) | |
[S390] Some preparations for the dynamic subchannel mapping patch.
- Move adding subchannel attributes to css_register_subchannel().
- Don't call device_trigger_reprobe() for non-operational devices.
- Introduce io_subchannel_create_ccwdev().
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
| -rw-r--r-- | drivers/s390/cio/css.c | 13 | ||||
| -rw-r--r-- | drivers/s390/cio/css.h | 2 | ||||
| -rw-r--r-- | drivers/s390/cio/device.c | 107 | ||||
| -rw-r--r-- | drivers/s390/cio/device_fsm.c | 3 |
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 | ||
| 190 | extern struct workqueue_struct *slow_path_wq; | 190 | extern struct workqueue_struct *slow_path_wq; |
| 191 | extern struct work_struct slow_path_work; | 191 | extern struct work_struct slow_path_work; |
| 192 | |||
| 193 | int 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 | ||
| 297 | static 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 | |||
| 297 | static void | 309 | static void |
| 298 | ccw_device_remove_disconnected(struct ccw_device *cdev) | 310 | ccw_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 | ||
| 501 | static inline int | 513 | int subchannel_add_files (struct device *dev) |
| 502 | subchannel_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 | ||
| 690 | static 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 | |||
| 705 | static 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 | |||
| 723 | static 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); |
| 733 | out: | 788 | out: |
| 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 | ||
| 902 | static 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 | |||
| 914 | static int | 937 | static int |
| 915 | io_subchannel_remove (struct subchannel *sch) | 938 | io_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 :/ |
