s390/scm: process availability
authorSebastian Ott <sebott@linux.vnet.ibm.com>
Thu, 28 Feb 2013 11:07:55 +0000 (12:07 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 7 Mar 2013 08:52:24 +0000 (09:52 +0100)
Let the bus code process scm availability information and
notify scm device drivers about the new state.

Reviewed-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/eadm.h
drivers/s390/block/scm_drv.c
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc.h
drivers/s390/cio/scm.c

index 78141be88b3de314331834e4a159cb54c22dc40d..dc9200ca32eda4d3e5a819025b176f7af5a06d60 100644 (file)
@@ -98,7 +98,7 @@ struct scm_device {
 #define OP_STATE_TEMP_ERR      2
 #define OP_STATE_PERM_ERR      3
 
-enum scm_event {SCM_CHANGE};
+enum scm_event {SCM_CHANGE, SCM_AVAIL};
 
 struct scm_driver {
        struct device_driver drv;
index ff8558c4fe256c27fd28c3505b28d574c9adad66..5f6180d6ff08f50516215c20553f0c1ce5f4da42 100644 (file)
@@ -15,6 +15,8 @@
 
 static void scm_notify(struct scm_device *scmdev, enum scm_event event)
 {
+       struct scm_blk_dev *bdev = dev_get_drvdata(&scmdev->dev);
+
        switch (event) {
        case SCM_CHANGE:
                pr_info("%lu: The capabilities of the SCM increment changed\n",
@@ -22,6 +24,11 @@ static void scm_notify(struct scm_device *scmdev, enum scm_event event)
                SCM_LOG(2, "State changed");
                SCM_LOG_STATE(2, scmdev);
                break;
+       case SCM_AVAIL:
+               SCM_LOG(2, "Increment available");
+               SCM_LOG_STATE(2, scmdev);
+               scm_blk_set_available(bdev);
+               break;
        }
 }
 
index 31ceef1beb8b06715090b9459f879997067896dd..e16c553f65561f453c4eed2a97eb4cda8a539231 100644 (file)
@@ -433,6 +433,20 @@ static void chsc_process_sei_scm_change(struct chsc_sei_nt0_area *sei_area)
                              " failed (rc=%d).\n", ret);
 }
 
+static void chsc_process_sei_scm_avail(struct chsc_sei_nt0_area *sei_area)
+{
+       int ret;
+
+       CIO_CRW_EVENT(4, "chsc: scm available information\n");
+       if (sei_area->rs != 7)
+               return;
+
+       ret = scm_process_availability_information();
+       if (ret)
+               CIO_CRW_EVENT(0, "chsc: process availability information"
+                             " failed (rc=%d).\n", ret);
+}
+
 static void chsc_process_sei_nt2(struct chsc_sei_nt2_area *sei_area)
 {
        switch (sei_area->cc) {
@@ -468,6 +482,9 @@ static void chsc_process_sei_nt0(struct chsc_sei_nt0_area *sei_area)
        case 12: /* scm change notification */
                chsc_process_sei_scm_change(sei_area);
                break;
+       case 14: /* scm available notification */
+               chsc_process_sei_scm_avail(sei_area);
+               break;
        default: /* other stuff */
                CIO_CRW_EVENT(2, "chsc: sei nt0 unhandled cc=%d\n",
                              sei_area->cc);
index 227e05f674b38a6151a3c3b99534c6700835640f..349d5fc471963a20d7f1dd4fec393ef44877d6a6 100644 (file)
@@ -156,8 +156,10 @@ int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token);
 
 #ifdef CONFIG_SCM_BUS
 int scm_update_information(void);
+int scm_process_availability_information(void);
 #else /* CONFIG_SCM_BUS */
 static inline int scm_update_information(void) { return 0; }
+static inline int scm_process_availability_information(void) { return 0; }
 #endif /* CONFIG_SCM_BUS */
 
 
index 31ac26499979d487172bade96efc1db9f728c2bb..46ec25632e8bd4ef8e0be26a3f515697abd7f760 100644 (file)
@@ -297,6 +297,22 @@ int scm_update_information(void)
        return ret;
 }
 
+static int scm_dev_avail(struct device *dev, void *unused)
+{
+       struct scm_driver *scmdrv = to_scm_drv(dev->driver);
+       struct scm_device *scmdev = to_scm_dev(dev);
+
+       if (dev->driver && scmdrv->notify)
+               scmdrv->notify(scmdev, SCM_AVAIL);
+
+       return 0;
+}
+
+int scm_process_availability_information(void)
+{
+       return bus_for_each_dev(&scm_bus_type, NULL, NULL, scm_dev_avail);
+}
+
 static int __init scm_init(void)
 {
        int ret;