diff options
| -rw-r--r-- | arch/s390/include/asm/eadm.h | 2 | ||||
| -rw-r--r-- | drivers/s390/block/scm_drv.c | 7 | ||||
| -rw-r--r-- | drivers/s390/cio/chsc.c | 17 | ||||
| -rw-r--r-- | drivers/s390/cio/chsc.h | 2 | ||||
| -rw-r--r-- | drivers/s390/cio/scm.c | 16 | 
5 files changed, 43 insertions, 1 deletions
diff --git a/arch/s390/include/asm/eadm.h b/arch/s390/include/asm/eadm.h index 78141be88b3..dc9200ca32e 100644 --- a/arch/s390/include/asm/eadm.h +++ b/arch/s390/include/asm/eadm.h @@ -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; diff --git a/drivers/s390/block/scm_drv.c b/drivers/s390/block/scm_drv.c index ff8558c4fe2..5f6180d6ff0 100644 --- a/drivers/s390/block/scm_drv.c +++ b/drivers/s390/block/scm_drv.c @@ -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;  	}  } diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 31ceef1beb8..e16c553f655 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -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); diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 227e05f674b..349d5fc4719 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h @@ -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 */ diff --git a/drivers/s390/cio/scm.c b/drivers/s390/cio/scm.c index 31ac2649997..46ec25632e8 100644 --- a/drivers/s390/cio/scm.c +++ b/drivers/s390/cio/scm.c @@ -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;  |