Commit b7294932 authored by Jan Höppner's avatar Jan Höppner Committed by Jens Axboe

s390/dasd: Prepare for additional path event handling

As more path events need to be handled for ECKD the current path
verification infrastructure can be reused. Rename all path verifcation
code to fit the more broadly based task of path event handling and put
the path verification in a new separate function.
Signed-off-by: default avatarJan Höppner <hoeppner@linux.ibm.com>
Signed-off-by: default avatarStefan Haberland <sth@linux.ibm.com>
Reviewed-by: default avatarStefan Haberland <sth@linux.ibm.com>
Reviewed-by: default avatarCornelia Huck <cohuck@redhat.com>
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 19508b20
...@@ -2115,8 +2115,8 @@ static void __dasd_device_check_path_events(struct dasd_device *device) ...@@ -2115,8 +2115,8 @@ static void __dasd_device_check_path_events(struct dasd_device *device)
if (device->stopped & if (device->stopped &
~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM)) ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM))
return; return;
rc = device->discipline->verify_path(device, rc = device->discipline->pe_handler(device,
dasd_path_get_tbvpm(device)); dasd_path_get_tbvpm(device));
if (rc) if (rc)
dasd_device_set_timer(device, 50); dasd_device_set_timer(device, 50);
else else
......
...@@ -103,7 +103,7 @@ struct ext_pool_exhaust_work_data { ...@@ -103,7 +103,7 @@ struct ext_pool_exhaust_work_data {
}; };
/* definitions for the path verification worker */ /* definitions for the path verification worker */
struct path_verification_work_data { struct pe_handler_work_data {
struct work_struct worker; struct work_struct worker;
struct dasd_device *device; struct dasd_device *device;
struct dasd_ccw_req cqr; struct dasd_ccw_req cqr;
...@@ -112,8 +112,8 @@ struct path_verification_work_data { ...@@ -112,8 +112,8 @@ struct path_verification_work_data {
int isglobal; int isglobal;
__u8 tbvpm; __u8 tbvpm;
}; };
static struct path_verification_work_data *path_verification_worker; static struct pe_handler_work_data *pe_handler_worker;
static DEFINE_MUTEX(dasd_path_verification_mutex); static DEFINE_MUTEX(dasd_pe_handler_mutex);
struct check_attention_work_data { struct check_attention_work_data {
struct work_struct worker; struct work_struct worker;
...@@ -1249,7 +1249,7 @@ static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm) ...@@ -1249,7 +1249,7 @@ static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm)
} }
static int rebuild_device_uid(struct dasd_device *device, static int rebuild_device_uid(struct dasd_device *device,
struct path_verification_work_data *data) struct pe_handler_work_data *data)
{ {
struct dasd_eckd_private *private = device->private; struct dasd_eckd_private *private = device->private;
__u8 lpm, opm = dasd_path_get_opm(device); __u8 lpm, opm = dasd_path_get_opm(device);
...@@ -1287,10 +1287,9 @@ static int rebuild_device_uid(struct dasd_device *device, ...@@ -1287,10 +1287,9 @@ static int rebuild_device_uid(struct dasd_device *device,
return rc; return rc;
} }
static void do_path_verification_work(struct work_struct *work) static void dasd_eckd_path_available_action(struct dasd_device *device,
struct pe_handler_work_data *data)
{ {
struct path_verification_work_data *data;
struct dasd_device *device;
struct dasd_eckd_private path_private; struct dasd_eckd_private path_private;
struct dasd_uid *uid; struct dasd_uid *uid;
__u8 path_rcd_buf[DASD_ECKD_RCD_DATA_SIZE]; __u8 path_rcd_buf[DASD_ECKD_RCD_DATA_SIZE];
...@@ -1300,19 +1299,6 @@ static void do_path_verification_work(struct work_struct *work) ...@@ -1300,19 +1299,6 @@ static void do_path_verification_work(struct work_struct *work)
char print_uid[60]; char print_uid[60];
int rc, pos; int rc, pos;
data = container_of(work, struct path_verification_work_data, worker);
device = data->device;
/* delay path verification until device was resumed */
if (test_bit(DASD_FLAG_SUSPENDED, &device->flags)) {
schedule_work(work);
return;
}
/* check if path verification already running and delay if so */
if (test_and_set_bit(DASD_FLAG_PATH_VERIFY, &device->flags)) {
schedule_work(work);
return;
}
opm = 0; opm = 0;
npm = 0; npm = 0;
ppm = 0; ppm = 0;
...@@ -1459,30 +1445,54 @@ static void do_path_verification_work(struct work_struct *work) ...@@ -1459,30 +1445,54 @@ static void do_path_verification_work(struct work_struct *work)
dasd_path_create_kobj(device, pos); dasd_path_create_kobj(device, pos);
} }
}
static void do_pe_handler_work(struct work_struct *work)
{
struct pe_handler_work_data *data;
struct dasd_device *device;
data = container_of(work, struct pe_handler_work_data, worker);
device = data->device;
/* delay path verification until device was resumed */
if (test_bit(DASD_FLAG_SUSPENDED, &device->flags)) {
schedule_work(work);
return;
}
/* check if path verification already running and delay if so */
if (test_and_set_bit(DASD_FLAG_PATH_VERIFY, &device->flags)) {
schedule_work(work);
return;
}
dasd_eckd_path_available_action(device, data);
clear_bit(DASD_FLAG_PATH_VERIFY, &device->flags); clear_bit(DASD_FLAG_PATH_VERIFY, &device->flags);
dasd_put_device(device); dasd_put_device(device);
if (data->isglobal) if (data->isglobal)
mutex_unlock(&dasd_path_verification_mutex); mutex_unlock(&dasd_pe_handler_mutex);
else else
kfree(data); kfree(data);
} }
static int dasd_eckd_verify_path(struct dasd_device *device, __u8 lpm) static int dasd_eckd_pe_handler(struct dasd_device *device, __u8 lpm)
{ {
struct path_verification_work_data *data; struct pe_handler_work_data *data;
data = kmalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA); data = kmalloc(sizeof(*data), GFP_ATOMIC | GFP_DMA);
if (!data) { if (!data) {
if (mutex_trylock(&dasd_path_verification_mutex)) { if (mutex_trylock(&dasd_pe_handler_mutex)) {
data = path_verification_worker; data = pe_handler_worker;
data->isglobal = 1; data->isglobal = 1;
} else } else {
return -ENOMEM; return -ENOMEM;
}
} else { } else {
memset(data, 0, sizeof(*data)); memset(data, 0, sizeof(*data));
data->isglobal = 0; data->isglobal = 0;
} }
INIT_WORK(&data->worker, do_path_verification_work); INIT_WORK(&data->worker, do_pe_handler_work);
dasd_get_device(device); dasd_get_device(device);
data->device = device; data->device = device;
data->tbvpm = lpm; data->tbvpm = lpm;
...@@ -6725,7 +6735,7 @@ static struct dasd_discipline dasd_eckd_discipline = { ...@@ -6725,7 +6735,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
.check_device = dasd_eckd_check_characteristics, .check_device = dasd_eckd_check_characteristics,
.uncheck_device = dasd_eckd_uncheck_device, .uncheck_device = dasd_eckd_uncheck_device,
.do_analysis = dasd_eckd_do_analysis, .do_analysis = dasd_eckd_do_analysis,
.verify_path = dasd_eckd_verify_path, .pe_handler = dasd_eckd_pe_handler,
.basic_to_ready = dasd_eckd_basic_to_ready, .basic_to_ready = dasd_eckd_basic_to_ready,
.online_to_ready = dasd_eckd_online_to_ready, .online_to_ready = dasd_eckd_online_to_ready,
.basic_to_known = dasd_eckd_basic_to_known, .basic_to_known = dasd_eckd_basic_to_known,
...@@ -6786,16 +6796,16 @@ dasd_eckd_init(void) ...@@ -6786,16 +6796,16 @@ dasd_eckd_init(void)
GFP_KERNEL | GFP_DMA); GFP_KERNEL | GFP_DMA);
if (!dasd_vol_info_req) if (!dasd_vol_info_req)
return -ENOMEM; return -ENOMEM;
path_verification_worker = kmalloc(sizeof(*path_verification_worker), pe_handler_worker = kmalloc(sizeof(*pe_handler_worker),
GFP_KERNEL | GFP_DMA); GFP_KERNEL | GFP_DMA);
if (!path_verification_worker) { if (!pe_handler_worker) {
kfree(dasd_reserve_req); kfree(dasd_reserve_req);
kfree(dasd_vol_info_req); kfree(dasd_vol_info_req);
return -ENOMEM; return -ENOMEM;
} }
rawpadpage = (void *)__get_free_page(GFP_KERNEL); rawpadpage = (void *)__get_free_page(GFP_KERNEL);
if (!rawpadpage) { if (!rawpadpage) {
kfree(path_verification_worker); kfree(pe_handler_worker);
kfree(dasd_reserve_req); kfree(dasd_reserve_req);
kfree(dasd_vol_info_req); kfree(dasd_vol_info_req);
return -ENOMEM; return -ENOMEM;
...@@ -6804,7 +6814,7 @@ dasd_eckd_init(void) ...@@ -6804,7 +6814,7 @@ dasd_eckd_init(void)
if (!ret) if (!ret)
wait_for_device_probe(); wait_for_device_probe();
else { else {
kfree(path_verification_worker); kfree(pe_handler_worker);
kfree(dasd_reserve_req); kfree(dasd_reserve_req);
kfree(dasd_vol_info_req); kfree(dasd_vol_info_req);
free_page((unsigned long)rawpadpage); free_page((unsigned long)rawpadpage);
...@@ -6816,7 +6826,7 @@ static void __exit ...@@ -6816,7 +6826,7 @@ static void __exit
dasd_eckd_cleanup(void) dasd_eckd_cleanup(void)
{ {
ccw_driver_unregister(&dasd_eckd_driver); ccw_driver_unregister(&dasd_eckd_driver);
kfree(path_verification_worker); kfree(pe_handler_worker);
kfree(dasd_reserve_req); kfree(dasd_reserve_req);
free_page((unsigned long)rawpadpage); free_page((unsigned long)rawpadpage);
} }
......
...@@ -298,6 +298,7 @@ struct dasd_discipline { ...@@ -298,6 +298,7 @@ struct dasd_discipline {
* configuration. * configuration.
*/ */
int (*verify_path)(struct dasd_device *, __u8); int (*verify_path)(struct dasd_device *, __u8);
int (*pe_handler)(struct dasd_device *, __u8);
/* /*
* Last things to do when a device is set online, and first things * Last things to do when a device is set online, and first things
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment