s390/scm: process availability

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>
This commit is contained in:
Sebastian Ott 2013-02-28 12:07:55 +01:00 committed by Martin Schwidefsky
parent 4fa3c01964
commit aebfa669d9
5 changed files with 43 additions and 1 deletions

View File

@ -98,7 +98,7 @@ struct scm_device {
#define OP_STATE_TEMP_ERR 2 #define OP_STATE_TEMP_ERR 2
#define OP_STATE_PERM_ERR 3 #define OP_STATE_PERM_ERR 3
enum scm_event {SCM_CHANGE}; enum scm_event {SCM_CHANGE, SCM_AVAIL};
struct scm_driver { struct scm_driver {
struct device_driver drv; struct device_driver drv;

View File

@ -15,6 +15,8 @@
static void scm_notify(struct scm_device *scmdev, enum scm_event event) static void scm_notify(struct scm_device *scmdev, enum scm_event event)
{ {
struct scm_blk_dev *bdev = dev_get_drvdata(&scmdev->dev);
switch (event) { switch (event) {
case SCM_CHANGE: case SCM_CHANGE:
pr_info("%lu: The capabilities of the SCM increment changed\n", 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(2, "State changed");
SCM_LOG_STATE(2, scmdev); SCM_LOG_STATE(2, scmdev);
break; break;
case SCM_AVAIL:
SCM_LOG(2, "Increment available");
SCM_LOG_STATE(2, scmdev);
scm_blk_set_available(bdev);
break;
} }
} }

View File

@ -433,6 +433,20 @@ static void chsc_process_sei_scm_change(struct chsc_sei_nt0_area *sei_area)
" failed (rc=%d).\n", ret); " 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) static void chsc_process_sei_nt2(struct chsc_sei_nt2_area *sei_area)
{ {
switch (sei_area->cc) { 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 */ case 12: /* scm change notification */
chsc_process_sei_scm_change(sei_area); chsc_process_sei_scm_change(sei_area);
break; break;
case 14: /* scm available notification */
chsc_process_sei_scm_avail(sei_area);
break;
default: /* other stuff */ default: /* other stuff */
CIO_CRW_EVENT(2, "chsc: sei nt0 unhandled cc=%d\n", CIO_CRW_EVENT(2, "chsc: sei nt0 unhandled cc=%d\n",
sei_area->cc); sei_area->cc);

View File

@ -156,8 +156,10 @@ int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token);
#ifdef CONFIG_SCM_BUS #ifdef CONFIG_SCM_BUS
int scm_update_information(void); int scm_update_information(void);
int scm_process_availability_information(void);
#else /* CONFIG_SCM_BUS */ #else /* CONFIG_SCM_BUS */
static inline int scm_update_information(void) { return 0; } static inline int scm_update_information(void) { return 0; }
static inline int scm_process_availability_information(void) { return 0; }
#endif /* CONFIG_SCM_BUS */ #endif /* CONFIG_SCM_BUS */

View File

@ -297,6 +297,22 @@ int scm_update_information(void)
return ret; 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) static int __init scm_init(void)
{ {
int ret; int ret;