diff options
Diffstat (limited to 'drivers/s390')
51 files changed, 892 insertions, 1494 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 1825fa8d05a7..6efacadc8fcd 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -75,7 +75,6 @@ static int dasd_flush_block_queue(struct dasd_block *); static void dasd_device_tasklet(unsigned long); static void dasd_block_tasklet(unsigned long); static void do_kick_device(struct work_struct *); -static void do_restore_device(struct work_struct *); static void do_reload_device(struct work_struct *); static void do_requeue_requests(struct work_struct *); static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); @@ -138,7 +137,6 @@ struct dasd_device *dasd_alloc_device(void) INIT_LIST_HEAD(&device->ccw_queue); timer_setup(&device->timer, dasd_device_timeout, 0); INIT_WORK(&device->kick_work, do_kick_device); - INIT_WORK(&device->restore_device, do_restore_device); INIT_WORK(&device->reload_device, do_reload_device); INIT_WORK(&device->requeue_requests, do_requeue_requests); device->state = DASD_STATE_NEW; @@ -621,26 +619,6 @@ void dasd_reload_device(struct dasd_device *device) EXPORT_SYMBOL(dasd_reload_device); /* - * dasd_restore_device will schedule a call do do_restore_device to the kernel - * event daemon. - */ -static void do_restore_device(struct work_struct *work) -{ - struct dasd_device *device = container_of(work, struct dasd_device, - restore_device); - device->cdev->drv->restore(device->cdev); - dasd_put_device(device); -} - -void dasd_restore_device(struct dasd_device *device) -{ - dasd_get_device(device); - /* queue call to dasd_restore_device to the kernel event daemon. */ - if (!schedule_work(&device->restore_device)) - dasd_put_device(device); -} - -/* * Set the target state for a device and starts the state change. */ void dasd_set_target_state(struct dasd_device *device, int target) @@ -1514,7 +1492,6 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) "start_IO: -EIO device gone, retry"); break; case -EINVAL: - /* most likely caused in power management context */ DBF_DEV_EVENT(DBF_WARNING, device, "%s", "start_IO: -EINVAL device currently " "not accessible"); @@ -2048,7 +2025,7 @@ static void __dasd_device_check_expire(struct dasd_device *device) static int __dasd_device_is_unusable(struct dasd_device *device, struct dasd_ccw_req *cqr) { - int mask = ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM | DASD_STOPPED_NOSPC); + int mask = ~(DASD_STOPPED_DC_WAIT | DASD_STOPPED_NOSPC); if (test_bit(DASD_FLAG_OFFLINE, &device->flags) && !test_bit(DASD_FLAG_SAFE_OFFLINE_RUNNING, &device->flags)) { @@ -2112,8 +2089,7 @@ static void __dasd_device_check_path_events(struct dasd_device *device) if (!dasd_path_get_tbvpm(device)) return; - if (device->stopped & - ~(DASD_STOPPED_DC_WAIT | DASD_UNRESUMED_PM)) + if (device->stopped & ~(DASD_STOPPED_DC_WAIT)) return; rc = device->discipline->verify_path(device, dasd_path_get_tbvpm(device)); @@ -2980,6 +2956,12 @@ static int _dasd_requeue_request(struct dasd_ccw_req *cqr) if (!block) return -EINVAL; + /* + * If the request is an ERP request there is nothing to requeue. + * This will be done with the remaining original request. + */ + if (cqr->refers) + return 0; spin_lock_irq(&cqr->dq->lock); req = (struct request *) cqr->callback_data; blk_mq_requeue_request(req, false); @@ -3789,11 +3771,6 @@ int dasd_generic_path_operational(struct dasd_device *device) "operational\n"); DBF_DEV_EVENT(DBF_WARNING, device, "%s", "path operational"); dasd_device_remove_stop_bits(device, DASD_STOPPED_DC_WAIT); - if (device->stopped & DASD_UNRESUMED_PM) { - dasd_device_remove_stop_bits(device, DASD_UNRESUMED_PM); - dasd_restore_device(device); - return 1; - } dasd_schedule_device_bh(device); if (device->block) { dasd_schedule_block_bh(device->block); @@ -4053,66 +4030,6 @@ void dasd_schedule_requeue(struct dasd_device *device) } EXPORT_SYMBOL(dasd_schedule_requeue); -int dasd_generic_pm_freeze(struct ccw_device *cdev) -{ - struct dasd_device *device = dasd_device_from_cdev(cdev); - - if (IS_ERR(device)) - return PTR_ERR(device); - - /* mark device as suspended */ - set_bit(DASD_FLAG_SUSPENDED, &device->flags); - - if (device->discipline->freeze) - device->discipline->freeze(device); - - /* disallow new I/O */ - dasd_device_set_stop_bits(device, DASD_STOPPED_PM); - - return dasd_generic_requeue_all_requests(device); -} -EXPORT_SYMBOL_GPL(dasd_generic_pm_freeze); - -int dasd_generic_restore_device(struct ccw_device *cdev) -{ - struct dasd_device *device = dasd_device_from_cdev(cdev); - int rc = 0; - - if (IS_ERR(device)) - return PTR_ERR(device); - - /* allow new IO again */ - dasd_device_remove_stop_bits(device, - (DASD_STOPPED_PM | DASD_UNRESUMED_PM)); - - dasd_schedule_device_bh(device); - - /* - * call discipline restore function - * if device is stopped do nothing e.g. for disconnected devices - */ - if (device->discipline->restore && !(device->stopped)) - rc = device->discipline->restore(device); - if (rc || device->stopped) - /* - * if the resume failed for the DASD we put it in - * an UNRESUMED stop state - */ - device->stopped |= DASD_UNRESUMED_PM; - - if (device->block) { - dasd_schedule_block_bh(device->block); - if (device->block->request_queue) - blk_mq_run_hw_queues(device->block->request_queue, - true); - } - - clear_bit(DASD_FLAG_SUSPENDED, &device->flags); - dasd_put_device(device); - return 0; -} -EXPORT_SYMBOL_GPL(dasd_generic_restore_device); - static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, int rdc_buffer_size, int magic) diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index ad44d22e8859..758ee4153ac1 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -5716,95 +5716,6 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, } } -static int dasd_eckd_pm_freeze(struct dasd_device *device) -{ - /* - * the device should be disconnected from our LCU structure - * on restore we will reconnect it and reread LCU specific - * information like PAV support that might have changed - */ - dasd_alias_remove_device(device); - dasd_alias_disconnect_device_from_lcu(device); - - return 0; -} - -static int dasd_eckd_restore_device(struct dasd_device *device) -{ - struct dasd_eckd_private *private = device->private; - struct dasd_eckd_characteristics temp_rdc_data; - int rc; - struct dasd_uid temp_uid; - unsigned long flags; - unsigned long cqr_flags = 0; - - /* Read Configuration Data */ - rc = dasd_eckd_read_conf(device); - if (rc) { - DBF_EVENT_DEVID(DBF_WARNING, device->cdev, - "Read configuration data failed, rc=%d", rc); - goto out_err; - } - - dasd_eckd_get_uid(device, &temp_uid); - /* Generate device unique id */ - rc = dasd_eckd_generate_uid(device); - spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); - if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0) - dev_err(&device->cdev->dev, "The UID of the DASD has " - "changed\n"); - spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); - if (rc) - goto out_err; - - /* register lcu with alias handling, enable PAV if this is a new lcu */ - rc = dasd_alias_make_device_known_to_lcu(device); - if (rc) - goto out_err; - - set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr_flags); - dasd_eckd_validate_server(device, cqr_flags); - - /* RE-Read Configuration Data */ - rc = dasd_eckd_read_conf(device); - if (rc) { - DBF_EVENT_DEVID(DBF_WARNING, device->cdev, - "Read configuration data failed, rc=%d", rc); - goto out_err2; - } - - /* Read Feature Codes */ - dasd_eckd_read_features(device); - - /* Read Volume Information */ - dasd_eckd_read_vol_info(device); - - /* Read Extent Pool Information */ - dasd_eckd_read_ext_pool_info(device); - - /* Read Device Characteristics */ - rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC, - &temp_rdc_data, 64); - if (rc) { - DBF_EVENT_DEVID(DBF_WARNING, device->cdev, - "Read device characteristic failed, rc=%d", rc); - goto out_err2; - } - spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); - memcpy(&private->rdc_data, &temp_rdc_data, sizeof(temp_rdc_data)); - spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); - - /* add device to alias management */ - dasd_alias_add_device(device); - - return 0; - -out_err2: - dasd_alias_disconnect_device_from_lcu(device); -out_err: - return -1; -} - static int dasd_eckd_reload_device(struct dasd_device *device) { struct dasd_eckd_private *private = device->private; @@ -6668,9 +6579,6 @@ static struct ccw_driver dasd_eckd_driver = { .notify = dasd_generic_notify, .path_event = dasd_generic_path_event, .shutdown = dasd_generic_shutdown, - .freeze = dasd_generic_pm_freeze, - .thaw = dasd_generic_restore_device, - .restore = dasd_generic_restore_device, .uc_handler = dasd_generic_uc_handler, .int_class = IRQIO_DAS, }; @@ -6702,8 +6610,6 @@ static struct dasd_discipline dasd_eckd_discipline = { .dump_sense_dbf = dasd_eckd_dump_sense_dbf, .fill_info = dasd_eckd_fill_info, .ioctl = dasd_eckd_ioctl, - .freeze = dasd_eckd_pm_freeze, - .restore = dasd_eckd_restore_device, .reload = dasd_eckd_reload_device, .get_uid = dasd_eckd_get_uid, .kick_validate = dasd_eckd_kick_validate_server, diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 1a44e321b54e..c027344ee225 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -79,9 +79,6 @@ static struct ccw_driver dasd_fba_driver = { .set_online = dasd_fba_set_online, .notify = dasd_generic_notify, .path_event = dasd_generic_path_event, - .freeze = dasd_generic_pm_freeze, - .thaw = dasd_generic_restore_device, - .restore = dasd_generic_restore_device, .int_class = IRQIO_DAS, }; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index c59a0d63b506..8ca077fbdf4f 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -355,10 +355,6 @@ struct dasd_discipline { int (*fill_info) (struct dasd_device *, struct dasd_information2_t *); int (*ioctl) (struct dasd_block *, unsigned int, void __user *); - /* suspend/resume functions */ - int (*freeze) (struct dasd_device *); - int (*restore) (struct dasd_device *); - /* reload device after state change */ int (*reload) (struct dasd_device *); @@ -520,7 +516,6 @@ struct dasd_device { atomic_t tasklet_scheduled; struct tasklet_struct tasklet; struct work_struct kick_work; - struct work_struct restore_device; struct work_struct reload_device; struct work_struct kick_validate; struct work_struct suc_work; @@ -592,8 +587,6 @@ struct dasd_queue { #define DASD_STOPPED_PENDING 4 /* long busy */ #define DASD_STOPPED_DC_WAIT 8 /* disconnected, wait */ #define DASD_STOPPED_SU 16 /* summary unit check handling */ -#define DASD_STOPPED_PM 32 /* pm state transition */ -#define DASD_UNRESUMED_PM 64 /* pm resume failed state */ #define DASD_STOPPED_NOSPC 128 /* no space left */ /* per device flags */ @@ -753,7 +746,6 @@ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved); void dasd_enable_device(struct dasd_device *); void dasd_set_target_state(struct dasd_device *, int); void dasd_kick_device(struct dasd_device *); -void dasd_restore_device(struct dasd_device *); void dasd_reload_device(struct dasd_device *); void dasd_schedule_requeue(struct dasd_device *); @@ -785,8 +777,6 @@ int dasd_generic_path_operational(struct dasd_device *); void dasd_generic_shutdown(struct ccw_device *); void dasd_generic_handle_state_change(struct dasd_device *); -int dasd_generic_pm_freeze(struct ccw_device *); -int dasd_generic_restore_device(struct ccw_device *); enum uc_todo dasd_generic_uc_handler(struct ccw_device *, struct irb *); void dasd_generic_path_event(struct ccw_device *, int *); int dasd_generic_verify_path(struct dasd_device *, __u8); diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index d8acabbb1ed3..1354c42d95aa 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -289,16 +289,14 @@ static void raw3215_timeout(struct timer_list *t) spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); raw->flags &= ~RAW3215_TIMER_RUNS; - if (!tty_port_suspended(&raw->port)) { - raw3215_mk_write_req(raw); - raw3215_start_io(raw); - if ((raw->queued_read || raw->queued_write) && - !(raw->flags & RAW3215_WORKING) && - !(raw->flags & RAW3215_TIMER_RUNS)) { - raw->timer.expires = RAW3215_TIMEOUT + jiffies; - add_timer(&raw->timer); - raw->flags |= RAW3215_TIMER_RUNS; - } + raw3215_mk_write_req(raw); + raw3215_start_io(raw); + if ((raw->queued_read || raw->queued_write) && + !(raw->flags & RAW3215_WORKING) && + !(raw->flags & RAW3215_TIMER_RUNS)) { + raw->timer.expires = RAW3215_TIMEOUT + jiffies; + add_timer(&raw->timer); + raw->flags |= RAW3215_TIMER_RUNS; } spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); } @@ -311,7 +309,7 @@ static void raw3215_timeout(struct timer_list *t) */ static inline void raw3215_try_io(struct raw3215_info *raw) { - if (!tty_port_initialized(&raw->port) || tty_port_suspended(&raw->port)) + if (!tty_port_initialized(&raw->port)) return; if (raw->queued_read != NULL) raw3215_start_io(raw); @@ -464,26 +462,6 @@ put_tty: } /* - * Drop the oldest line from the output buffer. - */ -static void raw3215_drop_line(struct raw3215_info *raw) -{ - int ix; - char ch; - - BUG_ON(raw->written != 0); - ix = (raw->head - raw->count) & (RAW3215_BUFFER_SIZE - 1); - while (raw->count > 0) { - ch = raw->buffer[ix]; - ix = (ix + 1) & (RAW3215_BUFFER_SIZE - 1); - raw->count--; - if (ch == 0x15) - break; - } - raw->head = ix; -} - -/* * Wait until length bytes are available int the output buffer. * Has to be called with the s390irq lock held. Can be called * disabled. @@ -491,13 +469,6 @@ static void raw3215_drop_line(struct raw3215_info *raw) static void raw3215_make_room(struct raw3215_info *raw, unsigned int length) { while (RAW3215_BUFFER_SIZE - raw->count < length) { - /* While console is frozen for suspend we have no other - * choice but to drop message from the buffer to make - * room for even more messages. */ - if (tty_port_suspended(&raw->port)) { - raw3215_drop_line(raw); - continue; - } /* there might be a request pending */ raw->flags |= RAW3215_FLUSHING; raw3215_mk_write_req(raw); @@ -763,36 +734,6 @@ static int raw3215_set_offline (struct ccw_device *cdev) return 0; } -static int raw3215_pm_stop(struct ccw_device *cdev) -{ - struct raw3215_info *raw; - unsigned long flags; - - /* Empty the output buffer, then prevent new I/O. */ - raw = dev_get_drvdata(&cdev->dev); - spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); - raw3215_make_room(raw, RAW3215_BUFFER_SIZE); - tty_port_set_suspended(&raw->port, 1); - spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); - return 0; -} - -static int raw3215_pm_start(struct ccw_device *cdev) -{ - struct raw3215_info *raw; - unsigned long flags; - - /* Allow I/O again and flush output buffer. */ - raw = dev_get_drvdata(&cdev->dev); - spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); - tty_port_set_suspended(&raw->port, 0); - raw->flags |= RAW3215_FLUSHING; - raw3215_try_io(raw); - raw->flags &= ~RAW3215_FLUSHING; - spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); - return 0; -} - static struct ccw_device_id raw3215_id[] = { { CCW_DEVICE(0x3215, 0) }, { /* end of list */ }, @@ -808,9 +749,6 @@ static struct ccw_driver raw3215_ccw_driver = { .remove = &raw3215_remove, .set_online = &raw3215_set_online, .set_offline = &raw3215_set_offline, - .freeze = &raw3215_pm_stop, - .thaw = &raw3215_pm_start, - .restore = &raw3215_pm_start, .int_class = IRQIO_C15, }; @@ -858,11 +796,6 @@ static void con3215_flush(void) unsigned long flags; raw = raw3215[0]; /* console 3215 is the first one */ - if (tty_port_suspended(&raw->port)) - /* The console is still frozen for suspend. */ - if (ccw_device_force_console(raw->cdev)) - /* Forcing didn't work, no panic message .. */ - return; spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); raw3215_make_room(raw, RAW3215_BUFFER_SIZE); spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index e17364e13d2f..e21962c0fd94 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c @@ -544,7 +544,6 @@ con3270_flush(void) cp = condev; if (!cp->view.dev) return; - raw3270_pm_unfreeze(&cp->view); raw3270_activate_view(&cp->view); spin_lock_irqsave(&cp->view.lock, flags); con3270_wait_write(cp); diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 63a41b168761..646ec796bb83 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -67,7 +67,6 @@ struct raw3270 { #define RAW3270_FLAGS_14BITADDR 0 /* 14-bit buffer addresses */ #define RAW3270_FLAGS_BUSY 1 /* Device busy, leave it alone */ #define RAW3270_FLAGS_CONSOLE 2 /* Device is the console. */ -#define RAW3270_FLAGS_FROZEN 3 /* set if 3270 is frozen for suspend */ /* Semaphore to protect global data of raw3270 (devices, views, etc). */ static DEFINE_MUTEX(raw3270_mutex); @@ -260,8 +259,7 @@ raw3270_view_active(struct raw3270_view *view) { struct raw3270 *rp = view->dev; - return rp && rp->view == view && - !test_bit(RAW3270_FLAGS_FROZEN, &rp->flags); + return rp && rp->view == view; } int @@ -273,8 +271,7 @@ raw3270_start(struct raw3270_view *view, struct raw3270_request *rq) spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags); rp = view->dev; - if (!rp || rp->view != view || - test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) + if (!rp || rp->view != view) rc = -EACCES; else if (!raw3270_state_ready(rp)) rc = -EBUSY; @@ -291,8 +288,7 @@ raw3270_start_locked(struct raw3270_view *view, struct raw3270_request *rq) int rc; rp = view->dev; - if (!rp || rp->view != view || - test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) + if (!rp || rp->view != view) rc = -EACCES; else if (!raw3270_state_ready(rp)) rc = -EBUSY; @@ -629,8 +625,7 @@ raw3270_reset(struct raw3270_view *view) int rc; rp = view->dev; - if (!rp || rp->view != view || - test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) + if (!rp || rp->view != view) rc = -EACCES; else if (!raw3270_state_ready(rp)) rc = -EBUSY; @@ -854,8 +849,6 @@ raw3270_activate_view(struct raw3270_view *view) rc = 0; else if (!raw3270_state_ready(rp)) rc = -EBUSY; - else if (test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) - rc = -EACCES; else { oldview = NULL; if (rp->view && rp->view->fn->deactivate) { @@ -903,8 +896,7 @@ raw3270_deactivate_view(struct raw3270_view *view) list_del_init(&view->list); list_add_tail(&view->list, &rp->view_list); /* Try to activate another view. */ - if (raw3270_state_ready(rp) && - !test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) { + if (raw3270_state_ready(rp)) { list_for_each_entry(view, &rp->view_list, list) { rp->view = view; if (view->fn->activate(view) == 0) @@ -999,8 +991,7 @@ raw3270_del_view(struct raw3270_view *view) rp->view = NULL; } list_del_init(&view->list); - if (!rp->view && raw3270_state_ready(rp) && - !test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) { + if (!rp->view && raw3270_state_ready(rp)) { /* Try to activate another view. */ list_for_each_entry(nv, &rp->view_list, list) { if (nv->fn->activate(nv) == 0) { @@ -1215,60 +1206,6 @@ raw3270_set_offline (struct ccw_device *cdev) return 0; } -static int raw3270_pm_stop(struct ccw_device *cdev) -{ - struct raw3270 *rp; - struct raw3270_view *view; - unsigned long flags; - - rp = dev_get_drvdata(&cdev->dev); - if (!rp) - return 0; - spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); - if (rp->view && rp->view->fn->deactivate) - rp->view->fn->deactivate(rp->view); - if (!test_bit(RAW3270_FLAGS_CONSOLE, &rp->flags)) { - /* - * Release tty and fullscreen for all non-console - * devices. - */ - list_for_each_entry(view, &rp->view_list, list) { - if (view->fn->release) - view->fn->release(view); - } - } - set_bit(RAW3270_FLAGS_FROZEN, &rp->flags); - spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); - return 0; -} - -static int raw3270_pm_start(struct ccw_device *cdev) -{ - struct raw3270 *rp; - unsigned long flags; - - rp = dev_get_drvdata(&cdev->dev); - if (!rp) - return 0; - spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); - clear_bit(RAW3270_FLAGS_FROZEN, &rp->flags); - if (rp->view && rp->view->fn->activate) - rp->view->fn->activate(rp->view); - spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); - return 0; -} - -void raw3270_pm_unfreeze(struct raw3270_view *view) -{ -#ifdef CONFIG_TN3270_CONSOLE - struct raw3270 *rp; - - rp = view->dev; - if (rp && test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) - ccw_device_force_console(rp->cdev); -#endif -} - static struct ccw_device_id raw3270_id[] = { { CCW_DEVICE(0x3270, 0) }, { CCW_DEVICE(0x3271, 0) }, @@ -1294,9 +1231,6 @@ static struct ccw_driver raw3270_ccw_driver = { .remove = &raw3270_remove, .set_online = &raw3270_set_online, .set_offline = &raw3270_set_offline, - .freeze = &raw3270_pm_stop, - .thaw = &raw3270_pm_start, - .restore = &raw3270_pm_start, .int_class = IRQIO_C70, }; diff --git a/drivers/s390/char/raw3270.h b/drivers/s390/char/raw3270.h index 8d979e0ee605..c6645167cd2b 100644 --- a/drivers/s390/char/raw3270.h +++ b/drivers/s390/char/raw3270.h @@ -199,7 +199,6 @@ struct raw3270_notifier { int raw3270_register_notifier(struct raw3270_notifier *); void raw3270_unregister_notifier(struct raw3270_notifier *); -void raw3270_pm_unfreeze(struct raw3270_view *); /* * Little memory allocator for string objects. diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 69d9cde9ff5a..6de919944a39 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h @@ -156,7 +156,11 @@ struct read_cpu_info_sccb { u16 offset_configured; u16 nr_standby; u16 offset_standby; - u8 reserved[4096 - 16]; + /* + * Without ext sccb, struct size is PAGE_SIZE. + * With ext sccb, struct size is EXT_SCCB_READ_CPU. + */ + u8 reserved[]; } __attribute__((packed, aligned(PAGE_SIZE))); struct read_info_sccb { @@ -199,7 +203,7 @@ struct read_info_sccb { u8 byte_134; /* 134 */ u8 cpudirq; /* 135 */ u16 cbl; /* 136-137 */ - u8 _pad_138[4096 - 138]; /* 138-4095 */ + u8 _pad_138[EXT_SCCB_READ_SCP - 138]; } __packed __aligned(PAGE_SIZE); struct read_storage_sccb { @@ -328,7 +332,7 @@ unsigned int sclp_early_con_check_vt220(struct init_sccb *sccb); int sclp_early_set_event_mask(struct init_sccb *sccb, sccb_mask_t receive_mask, sccb_mask_t send_mask); -int sclp_early_get_info(struct read_info_sccb *info); +struct read_info_sccb * __init sclp_early_get_info(void); /* useful inlines */ diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index f6e97f0830f6..d41bc144c183 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -27,6 +27,7 @@ #include <asm/page.h> #include <asm/sclp.h> #include <asm/numa.h> +#include <asm/facility.h> #include "sclp.h" @@ -87,14 +88,17 @@ out: int _sclp_get_core_info(struct sclp_core_info *info) { int rc; + int length = test_facility(140) ? EXT_SCCB_READ_CPU : PAGE_SIZE; struct read_cpu_info_sccb *sccb; if (!SCLP_HAS_CPU_INFO) return -EOPNOTSUPP; - sccb = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); + + sccb = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA | __GFP_ZERO, get_order(length)); if (!sccb) return -ENOMEM; - sccb->header.length = sizeof(*sccb); + sccb->header.length = length; + sccb->header.control_mask[2] = 0x80; rc = sclp_sync_request_timeout(SCLP_CMDW_READ_CPU_INFO, sccb, SCLP_QUEUE_INTERVAL); if (rc) @@ -107,7 +111,7 @@ int _sclp_get_core_info(struct sclp_core_info *info) } sclp_fill_core_info(info, sccb); out: - free_page((unsigned long) sccb); + free_pages((unsigned long) sccb, get_order(length)); return rc; } @@ -397,10 +401,10 @@ static void __init add_memory_merged(u16 rn) goto skip_add; if (start + size > VMEM_MAX_PHYS) size = VMEM_MAX_PHYS - start; - if (memory_end_set && (start >= memory_end)) + if (start >= ident_map_size) goto skip_add; - if (memory_end_set && (start + size > memory_end)) - size = memory_end - start; + if (start + size > ident_map_size) + size = ident_map_size - start; block_size = memory_block_size_bytes(); align_to_block_size(&start, &size, block_size); if (!size) diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c index cc5e84b80c69..2f3515fa242a 100644 --- a/drivers/s390/char/sclp_early.c +++ b/drivers/s390/char/sclp_early.c @@ -9,9 +9,12 @@ #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt #include <linux/errno.h> +#include <linux/memblock.h> #include <asm/ctl_reg.h> #include <asm/sclp.h> #include <asm/ipl.h> +#include <asm/setup.h> +#include <asm/facility.h> #include "sclp_sdias.h" #include "sclp.h" @@ -20,12 +23,14 @@ static struct sclp_ipl_info sclp_ipl_info; struct sclp_info sclp; EXPORT_SYMBOL(sclp); -static void __init sclp_early_facilities_detect(struct read_info_sccb *sccb) +static void __init sclp_early_facilities_detect(void) { struct sclp_core_entry *cpue; + struct read_info_sccb *sccb; u16 boot_cpu_address, cpu; - if (sclp_early_get_info(sccb)) + sccb = sclp_early_get_info(); + if (!sccb) return; sclp.facilities = sccb->facilities; @@ -107,29 +112,34 @@ void __init sclp_early_get_ipl_info(struct sclp_ipl_info *info) *info = sclp_ipl_info; } -static struct sclp_core_info sclp_early_core_info __initdata; -static int sclp_early_core_info_valid __initdata; - -static void __init sclp_early_init_core_info(struct read_cpu_info_sccb *sccb) -{ - if (!SCLP_HAS_CPU_INFO) - return; - memset(sccb, 0, sizeof(*sccb)); - sccb->header.length = sizeof(*sccb); - if (sclp_early_cmd(SCLP_CMDW_READ_CPU_INFO, sccb)) - return; - if (sccb->header.response_code != 0x0010) - return; - sclp_fill_core_info(&sclp_early_core_info, sccb); - sclp_early_core_info_valid = 1; -} - int __init sclp_early_get_core_info(struct sclp_core_info *info) { - if (!sclp_early_core_info_valid) - return -EIO; - *info = sclp_early_core_info; - return 0; + struct read_cpu_info_sccb *sccb; + int length = test_facility(140) ? EXT_SCCB_READ_CPU : PAGE_SIZE; + int rc = 0; + + if (!SCLP_HAS_CPU_INFO) + return -EOPNOTSUPP; + + sccb = memblock_alloc_low(length, PAGE_SIZE); + if (!sccb) + return -ENOMEM; + + memset(sccb, 0, length); + sccb->header.length = length; + sccb->header.control_mask[2] = 0x80; + if (sclp_early_cmd(SCLP_CMDW_READ_CPU_INFO, sccb)) { + rc = -EIO; + goto out; + } + if (sccb->header.response_code != 0x0010) { + rc = -EIO; + goto out; + } + sclp_fill_core_info(info, sccb); +out: + memblock_free_early((unsigned long)sccb, length); + return rc; } static void __init sclp_early_console_detect(struct init_sccb *sccb) @@ -148,8 +158,7 @@ void __init sclp_early_detect(void) { void *sccb = sclp_early_sccb; - sclp_early_facilities_detect(sccb); - sclp_early_init_core_info(sccb); + sclp_early_facilities_detect(); /* * Turn off SCLP event notifications. Also save remote masks in the diff --git a/drivers/s390/char/sclp_early_core.c b/drivers/s390/char/sclp_early_core.c index a960afa974bf..ec9f8ad5341c 100644 --- a/drivers/s390/char/sclp_early_core.c +++ b/drivers/s390/char/sclp_early_core.c @@ -11,6 +11,7 @@ #include <asm/irq.h> #include <asm/sections.h> #include <asm/mem_detect.h> +#include <asm/facility.h> #include "sclp.h" #include "sclp_rw.h" @@ -237,13 +238,14 @@ void sclp_early_printk(const char *str) int __init sclp_early_read_info(void) { int i; + int length = test_facility(140) ? EXT_SCCB_READ_SCP : PAGE_SIZE; struct read_info_sccb *sccb = &sclp_info_sccb; sclp_cmdw_t commands[] = {SCLP_CMDW_READ_SCP_INFO_FORCED, SCLP_CMDW_READ_SCP_INFO}; for (i = 0; i < ARRAY_SIZE(commands); i++) { - memset(sccb, 0, sizeof(*sccb)); - sccb->header.length = sizeof(*sccb); + memset(sccb, 0, length); + sccb->header.length = length; sccb->header.function_code = 0x80; sccb->header.control_mask[2] = 0x80; if (sclp_early_cmd(commands[i], sccb)) @@ -258,13 +260,12 @@ int __init sclp_early_read_info(void) return -EIO; } -int __init sclp_early_get_info(struct read_info_sccb *info) +struct read_info_sccb * __init sclp_early_get_info(void) { if (!sclp_info_sccb_valid) - return -EIO; + return NULL; - *info = sclp_info_sccb; - return 0; + return &sclp_info_sccb; } int __init sclp_early_get_memsize(unsigned long *mem) diff --git a/drivers/s390/char/tape.h b/drivers/s390/char/tape.h index e2c60475dfa8..4e5d5efa978f 100644 --- a/drivers/s390/char/tape.h +++ b/drivers/s390/char/tape.h @@ -264,7 +264,6 @@ extern void tape_state_set(struct tape_device *, enum tape_state); extern int tape_generic_online(struct tape_device *, struct tape_discipline *); extern int tape_generic_offline(struct ccw_device *); -extern int tape_generic_pm_suspend(struct ccw_device *); /* Externals from tape_devmap.c */ extern int tape_generic_probe(struct ccw_device *); diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 6d73ee3f827a..7ada994d4592 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c @@ -1191,7 +1191,6 @@ static struct ccw_driver tape_34xx_driver = { .remove = tape_generic_remove, .set_online = tape_34xx_online, .set_offline = tape_generic_offline, - .freeze = tape_generic_pm_suspend, .int_class = IRQIO_TAP, }; diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 4554cdf4d6bd..ecf8c5006a0e 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c @@ -1651,7 +1651,6 @@ static struct ccw_driver tape_3590_driver = { .remove = tape_generic_remove, .set_offline = tape_generic_offline, .set_online = tape_3590_online, - .freeze = tape_generic_pm_suspend, .int_class = IRQIO_TAP, }; diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 380e6a67719c..a6d2a4792185 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -428,55 +428,6 @@ tape_cleanup_device(struct tape_device *device) } /* - * Suspend device. - * - * Called by the common I/O layer if the drive should be suspended on user - * request. We refuse to suspend if the device is loaded or in use for the - * following reason: - * While the Linux guest is suspended, it might be logged off which causes - * devices to be detached. Tape devices are automatically rewound and unloaded - * during DETACH processing (unless the tape device was attached with the - * NOASSIGN or MULTIUSER option). After rewind/unload, there is no way to - * resume the original state of the tape device, since we would need to - * manually re-load the cartridge which was active at suspend time. - */ -int tape_generic_pm_suspend(struct ccw_device *cdev) -{ - struct tape_device *device; - - device = dev_get_drvdata(&cdev->dev); - if (!device) { - return -ENODEV; - } - - DBF_LH(3, "(%08x): tape_generic_pm_suspend(%p)\n", - device->cdev_id, device); - - if (device->medium_state != MS_UNLOADED) { - pr_err("A cartridge is loaded in tape device %s, " - "refusing to suspend\n", dev_name(&cdev->dev)); - return -EBUSY; - } - - spin_lock_irq(get_ccwdev_lock(device->cdev)); - switch (device->tape_state) { - case TS_INIT: - case TS_NOT_OPER: - case TS_UNUSED: - spin_unlock_irq(get_ccwdev_lock(device->cdev)); - break; - default: - pr_err("Tape device %s is busy, refusing to " - "suspend\n", dev_name(&cdev->dev)); - spin_unlock_irq(get_ccwdev_lock(device->cdev)); - return -EBUSY; - } - - DBF_LH(3, "(%08x): Drive suspended.\n", device->cdev_id); - return 0; -} - -/* * Set device offline. * * Called by the common I/O layer if the drive should set offline on user @@ -1360,7 +1311,6 @@ EXPORT_SYMBOL(tape_generic_remove); EXPORT_SYMBOL(tape_generic_probe); EXPORT_SYMBOL(tape_generic_online); EXPORT_SYMBOL(tape_generic_offline); -EXPORT_SYMBOL(tape_generic_pm_suspend); EXPORT_SYMBOL(tape_put_device); EXPORT_SYMBOL(tape_get_device); EXPORT_SYMBOL(tape_state_verbose); diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index cbde65ab2170..1bbf27b98cf6 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c @@ -62,7 +62,6 @@ static int ur_probe(struct ccw_device *cdev); static void ur_remove(struct ccw_device *cdev); static int ur_set_online(struct ccw_device *cdev); static int ur_set_offline(struct ccw_device *cdev); -static int ur_pm_suspend(struct ccw_device *cdev); static struct ccw_driver ur_driver = { .driver = { @@ -74,7 +73,6 @@ static struct ccw_driver ur_driver = { .remove = ur_remove, .set_online = ur_set_online, .set_offline = ur_set_offline, - .freeze = ur_pm_suspend, .int_class = IRQIO_VMR, }; @@ -165,28 +163,6 @@ static void urdev_put(struct urdev *urd) } /* - * State and contents of ur devices can be changed by class D users issuing - * CP commands such as PURGE or TRANSFER, while the Linux guest is suspended. - * Also the Linux guest might be logged off, which causes all active spool - * files to be closed. - * So we cannot guarantee that spool files are still the same when the Linux - * guest is resumed. In order to avoid unpredictable results at resume time - * we simply refuse to suspend if a ur device node is open. - */ -static int ur_pm_suspend(struct ccw_device *cdev) -{ - struct urdev *urd = dev_get_drvdata(&cdev->dev); - - TRACE("ur_pm_suspend: cdev=%p\n", cdev); - if (urd->open_flag) { - pr_err("Unit record device %s is busy, %s refusing to " - "suspend.\n", dev_name(&cdev->dev), ur_banner); - return -EBUSY; - } - return 0; -} - -/* * Low-level functions to do I/O to a ur device. * alloc_chan_prog * free_chan_prog diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 483a9ecfcbb1..444385da5792 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -210,18 +210,12 @@ out: static DEVICE_ATTR(ungroup, 0200, NULL, ccwgroup_ungroup_store); static DEVICE_ATTR(online, 0644, ccwgroup_online_show, ccwgroup_online_store); -static struct attribute *ccwgroup_attrs[] = { +static struct attribute *ccwgroup_dev_attrs[] = { &dev_attr_online.attr, &dev_attr_ungroup.attr, NULL, }; -static struct attribute_group ccwgroup_attr_group = { - .attrs = ccwgroup_attrs, -}; -static const struct attribute_group *ccwgroup_attr_groups[] = { - &ccwgroup_attr_group, - NULL, -}; +ATTRIBUTE_GROUPS(ccwgroup_dev); static void ccwgroup_ungroup_workfn(struct work_struct *work) { @@ -384,7 +378,6 @@ int ccwgroup_create_dev(struct device *parent, struct ccwgroup_driver *gdrv, } dev_set_name(&gdev->dev, "%s", dev_name(&gdev->cdev[0]->dev)); - gdev->dev.groups = ccwgroup_attr_groups; if (gdrv) { gdev->dev.driver = &gdrv->driver; @@ -487,6 +480,7 @@ static void ccwgroup_shutdown(struct device *dev) static struct bus_type ccwgroup_bus_type = { .name = "ccwgroup", + .dev_groups = ccwgroup_dev_groups, .remove = ccwgroup_remove, .shutdown = ccwgroup_shutdown, }; diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 8f080d3fd380..c42405c620b5 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c @@ -120,31 +120,6 @@ static void chsc_subchannel_shutdown(struct subchannel *sch) cio_disable_subchannel(sch); } -static int chsc_subchannel_prepare(struct subchannel *sch) -{ - int cc; - struct schib schib; - /* - * Don't allow suspend while the subchannel is not idle - * since we don't have a way to clear the subchannel and - * cannot disable it with a request running. - */ - cc = stsch(sch->schid, &schib); - if (!cc && scsw_stctl(&schib.scsw)) - return -EAGAIN; - return 0; -} - -static int chsc_subchannel_freeze(struct subchannel *sch) -{ - return cio_disable_subchannel(sch); -} - -static int chsc_subchannel_restore(struct subchannel *sch) -{ - return cio_enable_subchannel(sch, (u32)(unsigned long)sch); -} - static struct css_device_id chsc_subchannel_ids[] = { { .match_flags = 0x1, .type =SUBCHANNEL_TYPE_CHSC, }, { /* end of list */ }, @@ -161,10 +136,6 @@ static struct css_driver chsc_subchannel_driver = { .probe = chsc_subchannel_probe, .remove = chsc_subchannel_remove, .shutdown = chsc_subchannel_shutdown, - .prepare = chsc_subchannel_prepare, - .freeze = chsc_subchannel_freeze, - .thaw = chsc_subchannel_restore, - .restore = chsc_subchannel_restore, }; static int __init chsc_init_dbfs(void) diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 72dd2471ec1e..b7b590646d58 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c @@ -1109,11 +1109,6 @@ static ssize_t cmb_enable_store(struct device *dev, } DEVICE_ATTR_RW(cmb_enable); -int ccw_set_cmf(struct ccw_device *cdev, int enable) -{ - return cmbops->set(cdev, enable ? 2 : 0); -} - /** * enable_cmf() - switch on the channel measurement for a specific device * @cdev: The ccw device to be enabled diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index cca1a7c4bb33..94c6470de635 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -18,7 +18,6 @@ #include <linux/errno.h> #include <linux/list.h> #include <linux/reboot.h> -#include <linux/suspend.h> #include <linux/proc_fs.h> #include <linux/genalloc.h> #include <linux/dma-mapping.h> @@ -1044,59 +1043,6 @@ static struct notifier_block css_reboot_notifier = { .notifier_call = css_reboot_event, }; -/* - * Since the css devices are neither on a bus nor have a class - * nor have a special device type, we cannot stop/restart channel - * path measurements via the normal suspend/resume callbacks, but have - * to use notifiers. - */ -static int css_power_event(struct notifier_block *this, unsigned long event, - void *ptr) -{ - struct channel_subsystem *css; - int ret; - - switch (event) { - case PM_HIBERNATION_PREPARE: - case PM_SUSPEND_PREPARE: - ret = NOTIFY_DONE; - for_each_css(css) { - mutex_lock(&css->mutex); - if (!css->cm_enabled) { - mutex_unlock(&css->mutex); - continue; - } - ret = __chsc_do_secm(css, 0); - ret = notifier_from_errno(ret); - mutex_unlock(&css->mutex); - } - break; - case PM_POST_HIBERNATION: - case PM_POST_SUSPEND: - ret = NOTIFY_DONE; - for_each_css(css) { - mutex_lock(&css->mutex); - if (!css->cm_enabled) { - mutex_unlock(&css->mutex); - continue; - } - ret = __chsc_do_secm(css, 1); - ret = notifier_from_errno(ret); - mutex_unlock(&css->mutex); - } - /* search for subchannels, which appeared during hibernation */ - css_schedule_reprobe(); - break; - default: - ret = NOTIFY_DONE; - } - return ret; - -} -static struct notifier_block css_power_notifier = { - .notifier_call = css_power_event, -}; - #define CIO_DMA_GFP (GFP_KERNEL | __GFP_ZERO) static struct gen_pool *cio_dma_pool; @@ -1242,12 +1188,9 @@ static int __init css_bus_init(void) ret = register_reboot_notifier(&css_reboot_notifier); if (ret) goto out_unregister; - ret = register_pm_notifier(&css_power_notifier); - if (ret) - goto out_unregister_rn; ret = cio_dma_pool_init(); if (ret) - goto out_unregister_pmn; + goto out_unregister_rn; airq_init(); css_init_done = 1; @@ -1255,8 +1198,6 @@ static int __init css_bus_init(void) isc_register(IO_SCH_ISC); return 0; -out_unregister_pmn: - unregister_pm_notifier(&css_power_notifier); out_unregister_rn: unregister_reboot_notifier(&css_reboot_notifier); out_unregister: @@ -1456,74 +1397,6 @@ static int css_uevent(struct device *dev, struct kobj_uevent_env *env) return ret; } -static int css_pm_prepare(struct device *dev) -{ - struct subchannel *sch = to_subchannel(dev); - struct css_driver *drv; - - if (mutex_is_locked(&sch->reg_mutex)) - return -EAGAIN; - if (!sch->dev.driver) - return 0; - drv = to_cssdriver(sch->dev.driver); - /* Notify drivers that they may not register children. */ - return drv->prepare ? drv->prepare(sch) : 0; -} - -static void css_pm_complete(struct device *dev) -{ - struct subchannel *sch = to_subchannel(dev); - struct css_driver *drv; - - if (!sch->dev.driver) - return; - drv = to_cssdriver(sch->dev.driver); - if (drv->complete) - drv->complete(sch); -} - -static int css_pm_freeze(struct device *dev) -{ - struct subchannel *sch = to_subchannel(dev); - struct css_driver *drv; - - if (!sch->dev.driver) - return 0; - drv = to_cssdriver(sch->dev.driver); - return drv->freeze ? drv->freeze(sch) : 0; -} - -static int css_pm_thaw(struct device *dev) -{ - struct subchannel *sch = to_subchannel(dev); - struct css_driver *drv; - - if (!sch->dev.driver) - return 0; - drv = to_cssdriver(sch->dev.driver); - return drv->thaw ? drv->thaw(sch) : 0; -} - -static int css_pm_restore(struct device *dev) -{ - struct subchannel *sch = to_subchannel(dev); - struct css_driver *drv; - - css_update_ssd_info(sch); - if (!sch->dev.driver) - return 0; - drv = to_cssdriver(sch->dev.driver); - return drv->restore ? drv->restore(sch) : 0; -} - -static const struct dev_pm_ops css_pm_ops = { - .prepare = css_pm_prepare, - .complete = css_pm_complete, - .freeze = css_pm_freeze, - .thaw = css_pm_thaw, - .restore = css_pm_restore, -}; - static struct bus_type css_bus_type = { .name = "css", .match = css_bus_match, @@ -1531,7 +1404,6 @@ static struct bus_type css_bus_type = { .remove = css_remove, .shutdown = css_shutdown, .uevent = css_uevent, - .pm = &css_pm_ops, }; /** diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 3f322ea0f498..2eddfc47f687 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h @@ -72,11 +72,6 @@ struct chp_link; * @probe: function called on probe * @remove: function called on remove * @shutdown: called at device shutdown - * @prepare: prepare for pm state transition - * @complete: undo work done in @prepare - * @freeze: callback for freezing during hibernation snapshotting - * @thaw: undo work done in @freeze - * @restore: callback for restoring after hibernation * @settle: wait for asynchronous work to finish */ struct css_driver { @@ -88,11 +83,6 @@ struct css_driver { int (*probe)(struct subchannel *); int (*remove)(struct subchannel *); void (*shutdown)(struct subchannel *); - int (*prepare) (struct subchannel *); - void (*complete) (struct subchannel *); - int (*freeze)(struct subchannel *); - int (*thaw) (struct subchannel *); - int (*restore)(struct subchannel *); int (*settle)(void); }; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index b29fe8d50baf..e0005a4fc978 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -149,19 +149,6 @@ static struct css_device_id io_subchannel_ids[] = { { /* end of list */ }, }; -static int io_subchannel_prepare(struct subchannel *sch) -{ - struct ccw_device *cdev; - /* - * Don't allow suspend while a ccw device registration - * is still outstanding. - */ - cdev = sch_get_cdev(sch); - if (cdev && !device_is_registered(&cdev->dev)) - return -EAGAIN; - return 0; -} - static int io_subchannel_settle(void) { int ret; @@ -186,7 +173,6 @@ static struct css_driver io_subchannel_driver = { .probe = io_subchannel_probe, .remove = io_subchannel_remove, .shutdown = io_subchannel_shutdown, - .prepare = io_subchannel_prepare, .settle = io_subchannel_settle, }; @@ -1422,7 +1408,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch) } if (device_is_disconnected(cdev)) return IO_SCH_REPROBE; - if (cdev->online && !cdev->private->flags.resuming) + if (cdev->online) return IO_SCH_VERIFY; if (cdev->private->state == DEV_STATE_NOT_OPER) return IO_SCH_UNREG_ATTACH; @@ -1514,11 +1500,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) break; case IO_SCH_UNREG_ATTACH: spin_lock_irqsave(sch->lock, flags); - if (cdev->private->flags.resuming) { - /* Device will be handled later. */ - rc = 0; - goto out_unlock; - } sch_set_cdev(sch, NULL); spin_unlock_irqrestore(sch->lock, flags); /* Unregister ccw device. */ @@ -1531,7 +1512,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process) switch (action) { case IO_SCH_ORPH_UNREG: case IO_SCH_UNREG: - if (!cdev || !cdev->private->flags.resuming) + if (!cdev) css_sch_device_unregister(sch); break; case IO_SCH_ORPH_ATTACH: @@ -1664,10 +1645,10 @@ void __init ccw_device_destroy_console(struct ccw_device *cdev) struct io_subchannel_private *io_priv = to_io_private(sch); set_io_private(sch, NULL); - put_device(&sch->dev); - put_device(&cdev->dev); dma_free_coherent(&sch->dev, sizeof(*io_priv->dma_area), io_priv->dma_area, io_priv->dma_area_dma); + put_device(&sch->dev); + put_device(&cdev->dev); kfree(io_priv); } @@ -1690,14 +1671,6 @@ void ccw_device_wait_idle(struct ccw_device *cdev) udelay_simple(100); } } - -static int ccw_device_pm_restore(struct device *dev); - -int ccw_device_force_console(struct ccw_device *cdev) -{ - return ccw_device_pm_restore(&cdev->dev); -} -EXPORT_SYMBOL_GPL(ccw_device_force_console); #endif /** @@ -1798,235 +1771,6 @@ static void ccw_device_shutdown(struct device *dev) __disable_cmf(cdev); } -static int ccw_device_pm_prepare(struct device *dev) -{ - struct ccw_device *cdev = to_ccwdev(dev); - - if (work_pending(&cdev->private->todo_work)) - return -EAGAIN; - /* Fail while device is being set online/offline. */ - if (atomic_read(&cdev->private->onoff)) - return -EAGAIN; - - if (cdev->online && cdev->drv && cdev->drv->prepare) - return cdev->drv->prepare(cdev); - - return 0; -} - -static void ccw_device_pm_complete(struct device *dev) -{ - struct ccw_device *cdev = to_ccwdev(dev); - - if (cdev->online && cdev->drv && cdev->drv->complete) - cdev->drv->complete(cdev); -} - -static int ccw_device_pm_freeze(struct device *dev) -{ - struct ccw_device *cdev = to_ccwdev(dev); - struct subchannel *sch = to_subchannel(cdev->dev.parent); - int ret, cm_enabled; - - /* Fail suspend while device is in transistional state. */ - if (!dev_fsm_final_state(cdev)) - return -EAGAIN; - if (!cdev->online) - return 0; - if (cdev->drv && cdev->drv->freeze) { - ret = cdev->drv->freeze(cdev); - if (ret) - return ret; - } - - spin_lock_irq(sch->lock); - cm_enabled = cdev->private->cmb != NULL; - spin_unlock_irq(sch->lock); - if (cm_enabled) { - /* Don't have the css write on memory. */ - ret = ccw_set_cmf(cdev, 0); - if (ret) - return ret; - } - /* From here on, disallow device driver I/O. */ - spin_lock_irq(sch->lock); - ret = cio_disable_subchannel(sch); - spin_unlock_irq(sch->lock); - - return ret; -} - -static int ccw_device_pm_thaw(struct device *dev) -{ - struct ccw_device *cdev = to_ccwdev(dev); - struct subchannel *sch = to_subchannel(cdev->dev.parent); - int ret, cm_enabled; - - if (!cdev->online) - return 0; - - spin_lock_irq(sch->lock); - /* Allow device driver I/O again. */ - ret = cio_enable_subchannel(sch, (u32)(addr_t)sch); - cm_enabled = cdev->private->cmb != NULL; - spin_unlock_irq(sch->lock); - if (ret) - return ret; - - if (cm_enabled) { - ret = ccw_set_cmf(cdev, 1); - if (ret) - return ret; - } - - if (cdev->drv && cdev->drv->thaw) - ret = cdev->drv->thaw(cdev); - - return ret; -} - -static void __ccw_device_pm_restore(struct ccw_device *cdev) -{ - struct subchannel *sch = to_subchannel(cdev->dev.parent); - - spin_lock_irq(sch->lock); - if (cio_is_console(sch->schid)) { - cio_enable_subchannel(sch, (u32)(addr_t)sch); - goto out_unlock; - } - /* - * While we were sleeping, devices may have gone or become - * available again. Kick re-detection. - */ - cdev->private->flags.resuming = 1; - cdev->private->path_new_mask = LPM_ANYPATH; - css_sched_sch_todo(sch, SCH_TODO_EVAL); - spin_unlock_irq(sch->lock); - css_wait_for_slow_path(); - - /* cdev may have been moved to a different subchannel. */ - sch = to_subchannel(cdev->dev.parent); - spin_lock_irq(sch->lock); - if (cdev->private->state != DEV_STATE_ONLINE && - cdev->private->state != DEV_STATE_OFFLINE) - goto out_unlock; - - ccw_device_recognition(cdev); - spin_unlock_irq(sch->lock); - wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev) || - cdev->private->state == DEV_STATE_DISCONNECTED); - spin_lock_irq(sch->lock); - -out_unlock: - cdev->private->flags.resuming = 0; - spin_unlock_irq(sch->lock); -} - -static int resume_handle_boxed(struct ccw_device *cdev) -{ - cdev->private->state = DEV_STATE_BOXED; - if (ccw_device_notify(cdev, CIO_BOXED) == NOTIFY_OK) - return 0; - ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); - return -ENODEV; -} - -static int resume_handle_disc(struct ccw_device *cdev) -{ - cdev->private->state = DEV_STATE_DISCONNECTED; - if (ccw_device_notify(cdev, CIO_GONE) == NOTIFY_OK) - return 0; - ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); - return -ENODEV; -} - -static int ccw_device_pm_restore(struct device *dev) -{ - struct ccw_device *cdev = to_ccwdev(dev); - struct subchannel *sch; - int ret = 0; - - __ccw_device_pm_restore(cdev); - sch = to_subchannel(cdev->dev.parent); - spin_lock_irq(sch->lock); - if (cio_is_console(sch->schid)) - goto out_restore; - - /* check recognition results */ - switch (cdev->private->state) { - case DEV_STATE_OFFLINE: - case DEV_STATE_ONLINE: - cdev->private->flags.donotify = 0; - break; - case DEV_STATE_BOXED: - ret = resume_handle_boxed(cdev); - if (ret) - goto out_unlock; - goto out_restore; - default: - ret = resume_handle_disc(cdev); - if (ret) - goto out_unlock; - goto out_restore; - } - /* check if the device type has changed */ - if (!ccw_device_test_sense_data(cdev)) { - ccw_device_update_sense_data(cdev); - ccw_device_sched_todo(cdev, CDEV_TODO_REBIND); - ret = -ENODEV; - goto out_unlock; - } - if (!cdev->online) - goto out_unlock; - - if (ccw_device_online(cdev)) { - ret = resume_handle_disc(cdev); - if (ret) - goto out_unlock; - goto out_restore; - } - spin_unlock_irq(sch->lock); - wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); - spin_lock_irq(sch->lock); - - if (ccw_device_notify(cdev, CIO_OPER) == NOTIFY_BAD) { - ccw_device_sched_todo(cdev, CDEV_TODO_UNREG); - ret = -ENODEV; - goto out_unlock; - } - - /* reenable cmf, if needed */ - if (cdev->private->cmb) { - spin_unlock_irq(sch->lock); - ret = ccw_set_cmf(cdev, 1); - spin_lock_irq(sch->lock); - if (ret) { - CIO_MSG_EVENT(2, "resume: cdev 0.%x.%04x: cmf failed " - "(rc=%d)\n", cdev->private->dev_id.ssid, - cdev->private->dev_id.devno, ret); - ret = 0; - } - } - -out_restore: - spin_unlock_irq(sch->lock); - if (cdev->online && cdev->drv && cdev->drv->restore) - ret = cdev->drv->restore(cdev); - return ret; - -out_unlock: - spin_unlock_irq(sch->lock); - return ret; -} - -static const struct dev_pm_ops ccw_pm_ops = { - .prepare = ccw_device_pm_prepare, - .complete = ccw_device_pm_complete, - .freeze = ccw_device_pm_freeze, - .thaw = ccw_device_pm_thaw, - .restore = ccw_device_pm_restore, -}; - static struct bus_type ccw_bus_type = { .name = "ccw", .match = ccw_bus_match, @@ -2034,7 +1778,6 @@ static struct bus_type ccw_bus_type = { .probe = ccw_device_probe, .remove = ccw_device_remove, .shutdown = ccw_device_shutdown, - .pm = &ccw_pm_ops, }; /** diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 853b6a8ca095..24b2fce69590 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -143,6 +143,5 @@ void retry_set_schib(struct ccw_device *cdev); void cmf_retry_copy_block(struct ccw_device *); int cmf_reenable(struct ccw_device *); void cmf_reactivate(void); -int ccw_set_cmf(struct ccw_device *cdev, int enable); extern struct device_attribute dev_attr_cmb_enable; #endif diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8fc267324ebb..6420b197bb05 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -224,12 +224,6 @@ ccw_device_recog_done(struct ccw_device *cdev, int state) wake_up(&cdev->private->wait_q); return; } - if (cdev->private->flags.resuming) { - cdev->private->state = state; - cdev->private->flags.recog_done = 1; - wake_up(&cdev->private->wait_q); - return; - } switch (state) { case DEV_STATE_NOT_OPER: break; diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c index 53468ae64b99..c8964e0a23e7 100644 --- a/drivers/s390/cio/eadm_sch.c +++ b/drivers/s390/cio/eadm_sch.c @@ -306,16 +306,6 @@ static void eadm_subchannel_shutdown(struct subchannel *sch) eadm_quiesce(sch); } -static int eadm_subchannel_freeze(struct subchannel *sch) -{ - return cio_disable_subchannel(sch); -} - -static int eadm_subchannel_restore(struct subchannel *sch) -{ - return cio_enable_subchannel(sch, (u32)(unsigned long)sch); -} - /** * eadm_subchannel_sch_event - process subchannel event * @sch: subchannel @@ -369,9 +359,6 @@ static struct css_driver eadm_subchannel_driver = { .remove = eadm_subchannel_remove, .shutdown = eadm_subchannel_shutdown, .sch_event = eadm_subchannel_sch_event, - .freeze = eadm_subchannel_freeze, - .thaw = eadm_subchannel_restore, - .restore = eadm_subchannel_restore, }; static int __init eadm_sch_init(void) diff --git a/drivers/s390/cio/io_sch.h b/drivers/s390/cio/io_sch.h index c03b4a19974e..85a11c1836e5 100644 --- a/drivers/s390/cio/io_sch.h +++ b/drivers/s390/cio/io_sch.h @@ -160,7 +160,6 @@ struct ccw_device_private { unsigned int donotify:1; /* call notify function */ unsigned int recog_done:1; /* dev. recog. complete */ unsigned int fake_irb:2; /* deliver faked irb */ - unsigned int resuming:1; /* recognition while resume */ unsigned int pgroup:1; /* pathgroup is set up */ unsigned int mpath:1; /* multipathing is set up */ unsigned int pgid_unknown:1;/* unknown pgid state */ diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index ef738b42a092..2758d05a802d 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -1,11 +1,12 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Copyright IBM Corp. 2006, 2012 + * Copyright IBM Corp. 2006, 2020 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com> * Martin Schwidefsky <schwidefsky@de.ibm.com> * Ralph Wuerthner <rwuerthn@de.ibm.com> * Felix Beck <felix.beck@de.ibm.com> * Holger Dengler <hd@linux.vnet.ibm.com> + * Harald Freudenberger <freude@linux.ibm.com> * * Adjunct processor bus. */ @@ -73,6 +74,12 @@ EXPORT_SYMBOL(ap_perms); DEFINE_MUTEX(ap_perms_mutex); EXPORT_SYMBOL(ap_perms_mutex); +/* # of bus scans since init */ +static atomic64_t ap_scan_bus_count; + +/* completion for initial APQN bindings complete */ +static DECLARE_COMPLETION(ap_init_apqn_bindings_complete); + static struct ap_config_info *ap_qci_info; /* @@ -577,23 +584,125 @@ static int ap_bus_match(struct device *dev, struct device_driver *drv) */ static int ap_uevent(struct device *dev, struct kobj_uevent_env *env) { + int rc; struct ap_device *ap_dev = to_ap_dev(dev); - int retval = 0; - if (!ap_dev) - return -ENODEV; + /* Uevents from ap bus core don't need extensions to the env */ + if (dev == ap_root_device) + return 0; /* Set up DEV_TYPE environment variable. */ - retval = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type); - if (retval) - return retval; + rc = add_uevent_var(env, "DEV_TYPE=%04X", ap_dev->device_type); + if (rc) + return rc; /* Add MODALIAS= */ - retval = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type); + rc = add_uevent_var(env, "MODALIAS=ap:t%02X", ap_dev->device_type); + if (rc) + return rc; + + return 0; +} + +static void ap_send_init_scan_done_uevent(void) +{ + char *envp[] = { "INITSCAN=done", NULL }; - return retval; + kobject_uevent_env(&ap_root_device->kobj, KOBJ_CHANGE, envp); } +static void ap_send_bindings_complete_uevent(void) +{ + char *envp[] = { "BINDINGS=complete", NULL }; + + kobject_uevent_env(&ap_root_device->kobj, KOBJ_CHANGE, envp); +} + +/* + * calc # of bound APQNs + */ + +struct __ap_calc_ctrs { + unsigned int apqns; + unsigned int bound; +}; + +static int __ap_calc_helper(struct device *dev, void *arg) +{ + struct __ap_calc_ctrs *pctrs = (struct __ap_calc_ctrs *) arg; + + if (is_queue_dev(dev)) { + pctrs->apqns++; + if ((to_ap_dev(dev))->drv) + pctrs->bound++; + } + + return 0; +} + +static void ap_calc_bound_apqns(unsigned int *apqns, unsigned int *bound) +{ + struct __ap_calc_ctrs ctrs; + + memset(&ctrs, 0, sizeof(ctrs)); + bus_for_each_dev(&ap_bus_type, NULL, (void *) &ctrs, __ap_calc_helper); + + *apqns = ctrs.apqns; + *bound = ctrs.bound; +} + +/* + * After initial ap bus scan do check if all existing APQNs are + * bound to device drivers. + */ +static void ap_check_bindings_complete(void) +{ + unsigned int apqns, bound; + + if (atomic64_read(&ap_scan_bus_count) >= 1) { + ap_calc_bound_apqns(&apqns, &bound); + if (bound == apqns) { + if (!completion_done(&ap_init_apqn_bindings_complete)) { + complete_all(&ap_init_apqn_bindings_complete); + AP_DBF(DBF_INFO, "%s complete\n", __func__); + } + ap_send_bindings_complete_uevent(); + } + } +} + +/* + * Interface to wait for the AP bus to have done one initial ap bus + * scan and all detected APQNs have been bound to device drivers. + * If these both conditions are not fulfilled, this function blocks + * on a condition with wait_for_completion_interruptible_timeout(). + * If these both conditions are fulfilled (before the timeout hits) + * the return value is 0. If the timeout (in jiffies) hits instead + * -ETIME is returned. On failures negative return values are + * returned to the caller. + */ +int ap_wait_init_apqn_bindings_complete(unsigned long timeout) +{ + long l; + + if (completion_done(&ap_init_apqn_bindings_complete)) + return 0; + + if (timeout) + l = wait_for_completion_interruptible_timeout( + &ap_init_apqn_bindings_complete, timeout); + else + l = wait_for_completion_interruptible( + &ap_init_apqn_bindings_complete); + if (l < 0) + return l == -ERESTARTSYS ? -EINTR : l; + else if (l == 0 && timeout) + return -ETIME; + + return 0; +} +EXPORT_SYMBOL(ap_wait_init_apqn_bindings_complete); + static int __ap_queue_devices_with_id_unregister(struct device *dev, void *data) { if (is_queue_dev(dev) && @@ -602,12 +711,6 @@ static int __ap_queue_devices_with_id_unregister(struct device *dev, void *data) return 0; } -static struct bus_type ap_bus_type = { - .name = "ap", - .match = &ap_bus_match, - .uevent = &ap_uevent, -}; - static int __ap_revise_reserved(struct device *dev, void *dummy) { int rc, card, queue, devres, drvres; @@ -719,7 +822,8 @@ static int ap_device_probe(struct device *dev) hash_del(&to_ap_queue(dev)->hnode); spin_unlock_bh(&ap_queues_lock); ap_dev->drv = NULL; - } + } else + ap_check_bindings_complete(); out: if (rc) @@ -749,6 +853,7 @@ static int ap_device_remove(struct device *dev) if (is_queue_dev(dev)) hash_del(&to_ap_queue(dev)->hnode); spin_unlock_bh(&ap_queues_lock); + ap_dev->drv = NULL; put_device(dev); @@ -1166,21 +1271,55 @@ static ssize_t aqmask_store(struct bus_type *bus, const char *buf, static BUS_ATTR_RW(aqmask); -static struct bus_attribute *const ap_bus_attrs[] = { - &bus_attr_ap_domain, - &bus_attr_ap_control_domain_mask, - &bus_attr_ap_usage_domain_mask, - &bus_attr_ap_adapter_mask, - &bus_attr_config_time, - &bus_attr_poll_thread, - &bus_attr_ap_interrupts, - &bus_attr_poll_timeout, - &bus_attr_ap_max_domain_id, - &bus_attr_ap_max_adapter_id, - &bus_attr_apmask, - &bus_attr_aqmask, +static ssize_t scans_show(struct bus_type *bus, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%llu\n", + atomic64_read(&ap_scan_bus_count)); +} + +static BUS_ATTR_RO(scans); + +static ssize_t bindings_show(struct bus_type *bus, char *buf) +{ + int rc; + unsigned int apqns, n; + + ap_calc_bound_apqns(&apqns, &n); + if (atomic64_read(&ap_scan_bus_count) >= 1 && n == apqns) + rc = scnprintf(buf, PAGE_SIZE, "%u/%u (complete)\n", n, apqns); + else + rc = scnprintf(buf, PAGE_SIZE, "%u/%u\n", n, apqns); + + return rc; +} + +static BUS_ATTR_RO(bindings); + +static struct attribute *ap_bus_attrs[] = { + &bus_attr_ap_domain.attr, + &bus_attr_ap_control_domain_mask.attr, + &bus_attr_ap_usage_domain_mask.attr, + &bus_attr_ap_adapter_mask.attr, + &bus_attr_config_time.attr, + &bus_attr_poll_thread.attr, + &bus_attr_ap_interrupts.attr, + &bus_attr_poll_timeout.attr, + &bus_attr_ap_max_domain_id.attr, + &bus_attr_ap_max_adapter_id.attr, + &bus_attr_apmask.attr, + &bus_attr_aqmask.attr, + &bus_attr_scans.attr, + &bus_attr_bindings.attr, NULL, }; +ATTRIBUTE_GROUPS(ap_bus); + +static struct bus_type ap_bus_type = { + .name = "ap", + .bus_groups = ap_bus_groups, + .match = &ap_bus_match, + .uevent = &ap_uevent, +}; /** * ap_select_domain(): Select an AP domain if possible and we haven't @@ -1608,6 +1747,12 @@ static void ap_scan_bus(struct work_struct *unused) ap_domain_index); } + if (atomic64_inc_return(&ap_scan_bus_count) == 1) { + AP_DBF(DBF_DEBUG, "%s init scan complete\n", __func__); + ap_send_init_scan_done_uevent(); + ap_check_bindings_complete(); + } + mod_timer(&ap_config_timer, jiffies + ap_config_time * HZ); } @@ -1655,7 +1800,7 @@ static void __init ap_perms_init(void) */ static int __init ap_module_init(void) { - int rc, i; + int rc; rc = ap_debug_init(); if (rc) @@ -1694,17 +1839,13 @@ static int __init ap_module_init(void) rc = bus_register(&ap_bus_type); if (rc) goto out; - for (i = 0; ap_bus_attrs[i]; i++) { - rc = bus_create_file(&ap_bus_type, ap_bus_attrs[i]); - if (rc) - goto out_bus; - } /* Create /sys/devices/ap. */ ap_root_device = root_device_register("ap"); rc = PTR_ERR_OR_ZERO(ap_root_device); if (rc) goto out_bus; + ap_root_device->bus = &ap_bus_type; /* Setup the AP bus rescan timer. */ timer_setup(&ap_config_timer, ap_config_timeout, 0); @@ -1733,8 +1874,6 @@ out_work: hrtimer_cancel(&ap_poll_timer); root_device_unregister(ap_root_device); out_bus: - while (i--) - bus_remove_file(&ap_bus_type, ap_bus_attrs[i]); bus_unregister(&ap_bus_type); out: if (ap_using_interrupts()) diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 5029b80132aa..472efd3a755c 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -350,4 +350,16 @@ int ap_parse_mask_str(const char *str, unsigned long *bitmap, int bits, struct mutex *lock); +/* + * Interface to wait for the AP bus to have done one initial ap bus + * scan and all detected APQNs have been bound to device drivers. + * If these both conditions are not fulfilled, this function blocks + * on a condition with wait_for_completion_killable_timeout(). + * If these both conditions are fulfilled (before the timeout hits) + * the return value is 0. If the timeout (in jiffies) hits instead + * -ETIME is returned. On failures negative return values are + * returned to the caller. + */ +int ap_wait_init_apqn_bindings_complete(unsigned long timeout); + #endif /* _AP_BUS_H_ */ diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index dd84995049b9..cf23ce1b1146 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -150,6 +150,8 @@ static int pkey_skey2pkey(const u8 *key, struct pkey_protkey *pkey) u16 cardnr, domain; struct keytoken_header *hdr = (struct keytoken_header *)key; + zcrypt_wait_api_operational(); + /* * The cca_xxx2protkey call may fail when a card has been * addressed where the master key was changed after last fetch @@ -197,6 +199,8 @@ static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, u16 card, dom; u32 nr_apqns, *apqns = NULL; + zcrypt_wait_api_operational(); + /* build a list of apqns suitable for ep11 keys with cpacf support */ rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, ZCRYPT_CEX7, EP11_API_V, NULL); @@ -230,6 +234,8 @@ static int pkey_ep11key2pkey(const u8 *key, struct pkey_protkey *pkey) u32 nr_apqns, *apqns = NULL; struct ep11keyblob *kb = (struct ep11keyblob *) key; + zcrypt_wait_api_operational(); + /* build a list of apqns suitable for this key */ rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, ZCRYPT_CEX7, EP11_API_V, kb->wkvp); @@ -436,6 +442,7 @@ static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, if (rc == 0) break; /* PCKMO failed, so try the CCA secure key way */ + zcrypt_wait_api_operational(); rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, ckey.clrkey, tmpbuf); if (rc == 0) @@ -625,6 +632,8 @@ static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, return -EINVAL; } + zcrypt_wait_api_operational(); + /* simple try all apqns from the list */ for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { card = apqns[i].card; @@ -801,6 +810,8 @@ static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, return -EINVAL; } + zcrypt_wait_api_operational(); + /* simple try all apqns from the list */ for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { card = apqns[i].card; @@ -838,6 +849,8 @@ static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, if (keylen < sizeof(struct keytoken_header) || flags == 0) return -EINVAL; + zcrypt_wait_api_operational(); + if (hdr->type == TOKTYPE_NON_CCA && (hdr->version == TOKVER_EP11_AES_WITH_HEADER || hdr->version == TOKVER_EP11_ECC_WITH_HEADER) @@ -941,6 +954,8 @@ static int pkey_apqns4keytype(enum pkey_key_type ktype, int rc; u32 _nr_apqns, *_apqns = NULL; + zcrypt_wait_api_operational(); + if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { u64 cur_mkvp = 0, old_mkvp = 0; int minhwtype = ZCRYPT_CEX3C; diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index f60f9fb25214..10206e4498d0 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c @@ -1992,6 +1992,72 @@ void zcrypt_rng_device_remove(void) mutex_unlock(&zcrypt_rng_mutex); } +/* + * Wait until the zcrypt api is operational. + * The AP bus scan and the binding of ap devices to device drivers is + * an asynchronous job. This function waits until these initial jobs + * are done and so the zcrypt api should be ready to serve crypto + * requests - if there are resources available. The function uses an + * internal timeout of 60s. The very first caller will either wait for + * ap bus bindings complete or the timeout happens. This state will be + * remembered for further callers which will only be blocked until a + * decision is made (timeout or bindings complete). + * On timeout -ETIME is returned, on success the return value is 0. + */ +int zcrypt_wait_api_operational(void) +{ + static DEFINE_MUTEX(zcrypt_wait_api_lock); + static int zcrypt_wait_api_state; + int rc; + + rc = mutex_lock_interruptible(&zcrypt_wait_api_lock); + if (rc) + return rc; + + switch (zcrypt_wait_api_state) { + case 0: + /* initial state, invoke wait for the ap bus complete */ + rc = ap_wait_init_apqn_bindings_complete( + msecs_to_jiffies(60 * 1000)); + switch (rc) { + case 0: + /* ap bus bindings are complete */ + zcrypt_wait_api_state = 1; + break; + case -EINTR: + /* interrupted, go back to caller */ + break; + case -ETIME: + /* timeout */ + ZCRYPT_DBF(DBF_WARN, + "%s ap_wait_init_apqn_bindings_complete() returned with ETIME\n", + __func__); + zcrypt_wait_api_state = -ETIME; + break; + default: + /* other failure */ + ZCRYPT_DBF(DBF_DEBUG, + "%s ap_wait_init_apqn_bindings_complete() failure rc=%d\n", + __func__, rc); + break; + } + break; + case 1: + /* a previous caller already found ap bus bindings complete */ + rc = 0; + break; + default: + /* a previous caller had timeout or other failure */ + rc = zcrypt_wait_api_state; + break; + } + + mutex_unlock(&zcrypt_wait_api_lock); + + return rc; +} +EXPORT_SYMBOL(zcrypt_wait_api_operational); + int __init zcrypt_debug_init(void) { zcrypt_dbf_info = debug_register("zcrypt", 1, 1, diff --git a/drivers/s390/crypto/zcrypt_api.h b/drivers/s390/crypto/zcrypt_api.h index 51c0b8bdef50..16219efb2f61 100644 --- a/drivers/s390/crypto/zcrypt_api.h +++ b/drivers/s390/crypto/zcrypt_api.h @@ -162,6 +162,8 @@ void zcrypt_device_status_mask_ext(struct zcrypt_device_status_ext *devstatus); int zcrypt_device_status_ext(int card, int queue, struct zcrypt_device_status_ext *devstatus); +int zcrypt_wait_api_operational(void); + static inline unsigned long z_copy_from_user(bool userspace, void *to, const void __user *from, diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c index 661d2a49bce9..b341075397d9 100644 --- a/drivers/s390/net/ctcm_fsms.c +++ b/drivers/s390/net/ctcm_fsms.c @@ -1303,12 +1303,10 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg) /* p_header points to the last one we handled */ if (p_header) p_header->pdu_flag |= PDU_LAST; /*Say it's the last one*/ - header = kzalloc(TH_HEADER_LENGTH, gfp_type()); - if (!header) { - spin_unlock(&ch->collect_lock); - fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev); - goto done; - } + + header = skb_push(ch->trans_skb, TH_HEADER_LENGTH); + memset(header, 0, TH_HEADER_LENGTH); + header->th_ch_flag = TH_HAS_PDU; /* Normal data */ ch->th_seq_num++; header->th_seq_num = ch->th_seq_num; @@ -1316,11 +1314,6 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg) CTCM_PR_DBGDATA("%s: ToVTAM_th_seq= %08x\n" , __func__, ch->th_seq_num); - memcpy(skb_push(ch->trans_skb, TH_HEADER_LENGTH), header, - TH_HEADER_LENGTH); /* put the TH on the packet */ - - kfree(header); - CTCM_PR_DBGDATA("%s: trans_skb len:%04x \n", __func__, ch->trans_skb->len); CTCM_PR_DBGDATA("%s: up-to-50 bytes of trans_skb " diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index d06809eac16d..fd705429708e 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -623,25 +623,10 @@ static void ctcmpc_send_sweep_req(struct channel *rch) goto nomem; } - header = kmalloc(TH_SWEEP_LENGTH, gfp_type()); - - if (!header) { - dev_kfree_skb_any(sweep_skb); - /* rc = -ENOMEM; */ - goto nomem; - } - - header->th.th_seg = 0x00 ; + header = skb_put_zero(sweep_skb, TH_SWEEP_LENGTH); header->th.th_ch_flag = TH_SWEEP_REQ; /* 0x0f */ - header->th.th_blk_flag = 0x00; - header->th.th_is_xid = 0x00; - header->th.th_seq_num = 0x00; header->sw.th_last_seq = ch->th_seq_num; - skb_put_data(sweep_skb, header, TH_SWEEP_LENGTH); - - kfree(header); - netif_trans_update(dev); skb_queue_tail(&ch->sweep_queue, sweep_skb); @@ -680,24 +665,16 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) { spin_lock_irqsave(&ch->collect_lock, saveflags); refcount_inc(&skb->users); - p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type()); - - if (!p_header) { - spin_unlock_irqrestore(&ch->collect_lock, saveflags); - goto nomem_exit; - } - p_header->pdu_offset = skb->len; + p_header = skb_push(skb, PDU_HEADER_LENGTH); + p_header->pdu_offset = skb->len - PDU_HEADER_LENGTH; p_header->pdu_proto = 0x01; - p_header->pdu_flag = 0x00; if (be16_to_cpu(skb->protocol) == ETH_P_SNAP) { - p_header->pdu_flag |= PDU_FIRST | PDU_CNTL; + p_header->pdu_flag = PDU_FIRST | PDU_CNTL; } else { - p_header->pdu_flag |= PDU_FIRST; + p_header->pdu_flag = PDU_FIRST; } p_header->pdu_seq = 0; - memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header, - PDU_HEADER_LENGTH); CTCM_PR_DEBUG("%s(%s): Put on collect_q - skb len: %04x \n" "pdu header and data for up to 32 bytes:\n", @@ -706,7 +683,6 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) skb_queue_tail(&ch->collect_queue, skb); ch->collect_len += skb->len; - kfree(p_header); spin_unlock_irqrestore(&ch->collect_lock, saveflags); goto done; @@ -736,23 +712,15 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) } } - p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type()); - - if (!p_header) - goto nomem_exit; - - p_header->pdu_offset = skb->len; + p_header = skb_push(skb, PDU_HEADER_LENGTH); + p_header->pdu_offset = skb->len - PDU_HEADER_LENGTH; p_header->pdu_proto = 0x01; - p_header->pdu_flag = 0x00; p_header->pdu_seq = 0; if (be16_to_cpu(skb->protocol) == ETH_P_SNAP) { - p_header->pdu_flag |= PDU_FIRST | PDU_CNTL; + p_header->pdu_flag = PDU_FIRST | PDU_CNTL; } else { - p_header->pdu_flag |= PDU_FIRST; + p_header->pdu_flag = PDU_FIRST; } - memcpy(skb_push(skb, PDU_HEADER_LENGTH), p_header, PDU_HEADER_LENGTH); - - kfree(p_header); if (ch->collect_len > 0) { spin_lock_irqsave(&ch->collect_lock, saveflags); @@ -768,25 +736,17 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) ch->prof.txlen += skb->len - PDU_HEADER_LENGTH; - header = kmalloc(TH_HEADER_LENGTH, gfp_type()); - if (!header) - goto nomem_exit; + /* put the TH on the packet */ + header = skb_push(skb, TH_HEADER_LENGTH); + memset(header, 0, TH_HEADER_LENGTH); - header->th_seg = 0x00; header->th_ch_flag = TH_HAS_PDU; /* Normal data */ - header->th_blk_flag = 0x00; - header->th_is_xid = 0x00; /* Just data here */ ch->th_seq_num++; header->th_seq_num = ch->th_seq_num; CTCM_PR_DBGDATA("%s(%s) ToVTAM_th_seq= %08x\n" , __func__, dev->name, ch->th_seq_num); - /* put the TH on the packet */ - memcpy(skb_push(skb, TH_HEADER_LENGTH), header, TH_HEADER_LENGTH); - - kfree(header); - CTCM_PR_DBGDATA("%s(%s): skb len: %04x\n - pdu header and data for " "up to 32 bytes sent to vtam:\n", __func__, dev->name, skb->len); @@ -943,7 +903,7 @@ static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) CTCM_D3_DUMP((char *)skb->data, min_t(int, 32, skb->len)); len = skb->len + TH_HEADER_LENGTH + PDU_HEADER_LENGTH; - newskb = __dev_alloc_skb(len, gfp_type() | GFP_DMA); + newskb = __dev_alloc_skb(len, GFP_ATOMIC | GFP_DMA); if (!newskb) { CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_ERROR, @@ -1361,7 +1321,7 @@ static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type, ch->protocol = priv->protocol; if (IS_MPC(priv)) { - ch->discontact_th = kzalloc(TH_HEADER_LENGTH, gfp_type()); + ch->discontact_th = kzalloc(TH_HEADER_LENGTH, GFP_KERNEL); if (ch->discontact_th == NULL) goto nomem_return; diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h index 16bdf23ee02b..90bd7b3f80c3 100644 --- a/drivers/s390/net/ctcm_main.h +++ b/drivers/s390/net/ctcm_main.h @@ -298,11 +298,6 @@ struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv); /* test if struct ctcm_priv of struct net_device has MPC protocol setting */ #define IS_MPCDEV(dev) IS_MPC((struct ctcm_priv *)dev->ml_priv) -static inline gfp_t gfp_type(void) -{ - return in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; -} - /* * Definition of our link level header. */ diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index 85a1a4533cbe..19ee91acb89d 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c @@ -655,24 +655,10 @@ static void ctcmpc_send_sweep_resp(struct channel *rch) goto done; } - header = kmalloc(sizeof(struct th_sweep), gfp_type()); - - if (!header) { - dev_kfree_skb_any(sweep_skb); - goto done; - } - - header->th.th_seg = 0x00 ; + header = skb_put_zero(sweep_skb, TH_SWEEP_LENGTH); header->th.th_ch_flag = TH_SWEEP_RESP; - header->th.th_blk_flag = 0x00; - header->th.th_is_xid = 0x00; - header->th.th_seq_num = 0x00; header->sw.th_last_seq = ch->th_seq_num; - skb_put_data(sweep_skb, header, TH_SWEEP_LENGTH); - - kfree(header); - netif_trans_update(dev); skb_queue_tail(&ch->sweep_queue, sweep_skb); @@ -1177,7 +1163,7 @@ static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb) skb_pull(pskb, new_len); /* point to next PDU */ } } else { - mpcginfo = kmalloc(sizeof(struct mpcg_info), gfp_type()); + mpcginfo = kmalloc(sizeof(struct mpcg_info), GFP_ATOMIC); if (mpcginfo == NULL) goto done; @@ -2062,7 +2048,6 @@ static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg) */ static int mpc_send_qllc_discontact(struct net_device *dev) { - __u32 new_len = 0; struct sk_buff *skb; struct qllc *qllcptr; struct ctcm_priv *priv = dev->ml_priv; @@ -2093,31 +2078,19 @@ static int mpc_send_qllc_discontact(struct net_device *dev) case MPCG_STATE_FLOWC: case MPCG_STATE_READY: grp->send_qllc_disc = 2; - new_len = sizeof(struct qllc); - qllcptr = kzalloc(new_len, gfp_type() | GFP_DMA); - if (qllcptr == NULL) { - CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, - "%s(%s): qllcptr allocation error", - CTCM_FUNTAIL, dev->name); - return -ENOMEM; - } - - qllcptr->qllc_address = 0xcc; - qllcptr->qllc_commands = 0x03; - - skb = __dev_alloc_skb(new_len, GFP_ATOMIC); + skb = __dev_alloc_skb(sizeof(struct qllc), GFP_ATOMIC); if (skb == NULL) { CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, "%s(%s): skb allocation error", CTCM_FUNTAIL, dev->name); priv->stats.rx_dropped++; - kfree(qllcptr); return -ENOMEM; } - skb_put_data(skb, qllcptr, new_len); - kfree(qllcptr); + qllcptr = skb_put(skb, sizeof(struct qllc)); + qllcptr->qllc_address = 0xcc; + qllcptr->qllc_commands = 0x03; if (skb_headroom(skb) < 4) { CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index f73b4756ed5e..6f5ddc3eab8c 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -417,12 +417,13 @@ enum qeth_qdio_out_buffer_state { QETH_QDIO_BUF_EMPTY, /* Filled by driver; owned by hardware in order to be sent. */ QETH_QDIO_BUF_PRIMED, - /* Identified to be pending in TPQ. */ + /* Discovered by the TX completion code: */ QETH_QDIO_BUF_PENDING, - /* Found in completion queue. */ - QETH_QDIO_BUF_IN_CQ, - /* Handled via transfer pending / completion queue. */ - QETH_QDIO_BUF_HANDLED_DELAYED, + /* Finished by the TX completion code: */ + QETH_QDIO_BUF_NEED_QAOB, + /* Received QAOB notification on CQ: */ + QETH_QDIO_BUF_QAOB_OK, + QETH_QDIO_BUF_QAOB_ERROR, }; struct qeth_qdio_out_buffer { @@ -621,7 +622,7 @@ struct qeth_reply { }; struct qeth_cmd_buffer { - struct list_head list; + struct list_head list_entry; struct completion done; spinlock_t lock; unsigned int length; @@ -701,6 +702,19 @@ enum qeth_pnso_mode { QETH_PNSO_ADDR_INFO, }; +enum qeth_link_mode { + QETH_LINK_MODE_UNKNOWN, + QETH_LINK_MODE_FIBRE_SHORT, + QETH_LINK_MODE_FIBRE_LONG, +}; + +struct qeth_link_info { + u32 speed; + u8 duplex; + u8 port; + enum qeth_link_mode link_mode; +}; + #define QETH_BROADCAST_WITH_ECHO 0x01 #define QETH_BROADCAST_WITHOUT_ECHO 0x02 struct qeth_card_info { @@ -732,6 +746,7 @@ struct qeth_card_info { struct qeth_card_blkt blkt; __u32 diagass_support; __u32 hwtrap; + struct qeth_link_info link_info; }; enum qeth_discipline_id { @@ -796,12 +811,6 @@ struct qeth_rx { u8 bufs_refill; }; -struct carrier_info { - __u8 card_type; - __u16 port_mode; - __u32 port_speed; -}; - struct qeth_switch_info { __u32 capabilities; __u32 settings; @@ -1052,10 +1061,8 @@ extern const struct qeth_discipline qeth_l2_discipline; extern const struct qeth_discipline qeth_l3_discipline; extern const struct ethtool_ops qeth_ethtool_ops; extern const struct ethtool_ops qeth_osn_ethtool_ops; -extern const struct attribute_group *qeth_generic_attr_groups[]; -extern const struct attribute_group *qeth_osn_attr_groups[]; -extern const struct attribute_group qeth_device_attr_group; -extern const struct attribute_group qeth_device_blkt_group; +extern const struct attribute_group *qeth_dev_groups[]; +extern const struct attribute_group *qeth_osn_dev_groups[]; extern const struct device_type qeth_generic_devtype; const char *qeth_get_cardname_short(struct qeth_card *); @@ -1108,7 +1115,7 @@ void qeth_prepare_ipa_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob, int qeth_query_switch_attributes(struct qeth_card *card, struct qeth_switch_info *sw_info); int qeth_query_card_info(struct qeth_card *card, - struct carrier_info *carrier_info); + struct qeth_link_info *link_info); int qeth_setadpparms_set_access_ctrl(struct qeth_card *card, enum qeth_ipa_isolation_modes mode); diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 93c9b30ab17a..f4b60294a969 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -33,6 +33,7 @@ #include <net/iucv/af_iucv.h> #include <net/dsfield.h> +#include <net/sock.h> #include <asm/ebcdic.h> #include <asm/chpid.h> @@ -74,7 +75,6 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue, enum iucv_tx_notify notification); static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error, int budget); -static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int); static void qeth_close_dev_handler(struct work_struct *work) { @@ -477,8 +477,7 @@ static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx, while (c) { if (forced_cleanup || - atomic_read(&c->state) == - QETH_QDIO_BUF_HANDLED_DELAYED) { + atomic_read(&c->state) == QETH_QDIO_BUF_EMPTY) { struct qeth_qdio_out_buffer *f = c; QETH_CARD_TEXT(f->q->card, 5, "fp"); @@ -499,17 +498,12 @@ static void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q, int bidx, } } - if (forced_cleanup && (atomic_read(&(q->bufs[bidx]->state)) == - QETH_QDIO_BUF_HANDLED_DELAYED)) { - /* for recovery situations */ - qeth_init_qdio_out_buf(q, bidx); - QETH_CARD_TEXT(q->card, 2, "clprecov"); - } } static void qeth_qdio_handle_aob(struct qeth_card *card, unsigned long phys_aob_addr) { + enum qeth_qdio_out_buffer_state new_state = QETH_QDIO_BUF_QAOB_OK; struct qaob *aob; struct qeth_qdio_out_buffer *buffer; enum iucv_tx_notify notification; @@ -521,34 +515,45 @@ static void qeth_qdio_handle_aob(struct qeth_card *card, buffer = (struct qeth_qdio_out_buffer *) aob->user1; QETH_CARD_TEXT_(card, 5, "%lx", aob->user1); - if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED, - QETH_QDIO_BUF_IN_CQ) == QETH_QDIO_BUF_PRIMED) { - notification = TX_NOTIFY_OK; - } else { - WARN_ON_ONCE(atomic_read(&buffer->state) != - QETH_QDIO_BUF_PENDING); - atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ); - notification = TX_NOTIFY_DELAYED_OK; + if (aob->aorc) { + QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc); + new_state = QETH_QDIO_BUF_QAOB_ERROR; } - if (aob->aorc != 0) { - QETH_CARD_TEXT_(card, 2, "aorc%02X", aob->aorc); + switch (atomic_xchg(&buffer->state, new_state)) { + case QETH_QDIO_BUF_PRIMED: + /* Faster than TX completion code, let it handle the async + * completion for us. + */ + break; + case QETH_QDIO_BUF_PENDING: + /* TX completion code is active and will handle the async + * completion for us. + */ + break; + case QETH_QDIO_BUF_NEED_QAOB: + /* TX completion code is already finished. */ notification = qeth_compute_cq_notification(aob->aorc, 1); - } - qeth_notify_skbs(buffer->q, buffer, notification); + qeth_notify_skbs(buffer->q, buffer, notification); - /* Free dangling allocations. The attached skbs are handled by - * qeth_cleanup_handled_pending(). - */ - for (i = 0; - i < aob->sb_count && i < QETH_MAX_BUFFER_ELEMENTS(card); - i++) { - void *data = phys_to_virt(aob->sba[i]); + /* Free dangling allocations. The attached skbs are handled by + * qeth_cleanup_handled_pending(). + */ + for (i = 0; + i < aob->sb_count && i < QETH_MAX_BUFFER_ELEMENTS(card); + i++) { + void *data = phys_to_virt(aob->sba[i]); + + if (data && buffer->is_header[i]) + kmem_cache_free(qeth_core_header_cache, data); + buffer->is_header[i] = 0; + } - if (data && buffer->is_header[i]) - kmem_cache_free(qeth_core_header_cache, data); + atomic_set(&buffer->state, QETH_QDIO_BUF_EMPTY); + break; + default: + WARN_ON_ONCE(1); } - atomic_set(&buffer->state, QETH_QDIO_BUF_HANDLED_DELAYED); qdio_release_aob(aob); } @@ -609,7 +614,7 @@ static void qeth_enqueue_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob) { spin_lock_irq(&card->lock); - list_add_tail(&iob->list, &card->cmd_waiter_list); + list_add_tail(&iob->list_entry, &card->cmd_waiter_list); spin_unlock_irq(&card->lock); } @@ -617,7 +622,7 @@ static void qeth_dequeue_cmd(struct qeth_card *card, struct qeth_cmd_buffer *iob) { spin_lock_irq(&card->lock); - list_del(&iob->list); + list_del(&iob->list_entry); spin_unlock_irq(&card->lock); } @@ -971,7 +976,7 @@ static void qeth_clear_ipacmd_list(struct qeth_card *card) QETH_CARD_TEXT(card, 4, "clipalst"); spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(iob, &card->cmd_waiter_list, list) + list_for_each_entry(iob, &card->cmd_waiter_list, list_entry) qeth_notify_cmd(iob, -ECANCELED); spin_unlock_irqrestore(&card->lock, flags); } @@ -1041,7 +1046,6 @@ struct qeth_cmd_buffer *qeth_alloc_cmd(struct qeth_channel *channel, init_completion(&iob->done); spin_lock_init(&iob->lock); - INIT_LIST_HEAD(&iob->list); refcount_set(&iob->ref_count, 1); iob->channel = channel; iob->timeout = timeout; @@ -1088,7 +1092,7 @@ static void qeth_issue_next_read_cb(struct qeth_card *card, /* match against pending cmd requests */ spin_lock_irqsave(&card->lock, flags); - list_for_each_entry(tmp, &card->cmd_waiter_list, list) { + list_for_each_entry(tmp, &card->cmd_waiter_list, list_entry) { if (tmp->match && tmp->match(tmp, iob)) { request = tmp; /* take the object outside the lock */ @@ -1405,7 +1409,7 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *q, skb_queue_walk(&buf->skb_list, skb) { QETH_CARD_TEXT_(q->card, 5, "skbn%d", notification); QETH_CARD_TEXT_(q->card, 5, "%lx", (long) skb); - if (skb->protocol == htons(ETH_P_AF_IUCV) && skb->sk) + if (skb->sk && skb->sk->sk_family == PF_IUCV) iucv_sk(skb->sk)->sk_txnotify(skb, notification); } } @@ -1416,9 +1420,6 @@ static void qeth_tx_complete_buf(struct qeth_qdio_out_buffer *buf, bool error, struct qeth_qdio_out_q *queue = buf->q; struct sk_buff *skb; - /* release may never happen from within CQ tasklet scope */ - WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ); - if (atomic_read(&buf->state) == QETH_QDIO_BUF_PENDING) qeth_notify_skbs(queue, buf, TX_NOTIFY_GENERALERROR); @@ -4868,8 +4869,8 @@ out_free: static int qeth_query_card_info_cb(struct qeth_card *card, struct qeth_reply *reply, unsigned long data) { - struct carrier_info *carrier_info = (struct carrier_info *)reply->param; struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data; + struct qeth_link_info *link_info = reply->param; struct qeth_query_card_info *card_info; QETH_CARD_TEXT(card, 2, "qcrdincb"); @@ -4877,14 +4878,67 @@ static int qeth_query_card_info_cb(struct qeth_card *card, return -EIO; card_info = &cmd->data.setadapterparms.data.card_info; - carrier_info->card_type = card_info->card_type; - carrier_info->port_mode = card_info->port_mode; - carrier_info->port_speed = card_info->port_speed; + netdev_dbg(card->dev, + "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n", + card_info->card_type, card_info->port_mode, + card_info->port_speed); + + switch (card_info->port_mode) { + case CARD_INFO_PORTM_FULLDUPLEX: + link_info->duplex = DUPLEX_FULL; + break; + case CARD_INFO_PORTM_HALFDUPLEX: + link_info->duplex = DUPLEX_HALF; + break; + default: + link_info->duplex = DUPLEX_UNKNOWN; + } + + switch (card_info->card_type) { + case CARD_INFO_TYPE_1G_COPPER_A: + case CARD_INFO_TYPE_1G_COPPER_B: + link_info->speed = SPEED_1000; + link_info->port = PORT_TP; + break; + case CARD_INFO_TYPE_1G_FIBRE_A: + case CARD_INFO_TYPE_1G_FIBRE_B: + link_info->speed = SPEED_1000; + link_info->port = PORT_FIBRE; + break; + case CARD_INFO_TYPE_10G_FIBRE_A: + case CARD_INFO_TYPE_10G_FIBRE_B: + link_info->speed = SPEED_10000; + link_info->port = PORT_FIBRE; + break; + default: + switch (card_info->port_speed) { + case CARD_INFO_PORTS_10M: + link_info->speed = SPEED_10; + break; + case CARD_INFO_PORTS_100M: + link_info->speed = SPEED_100; + break; + case CARD_INFO_PORTS_1G: + link_info->speed = SPEED_1000; + break; + case CARD_INFO_PORTS_10G: + link_info->speed = SPEED_10000; + break; + case CARD_INFO_PORTS_25G: + link_info->speed = SPEED_25000; + break; + default: + link_info->speed = SPEED_UNKNOWN; + } + + link_info->port = PORT_OTHER; + } + return 0; } int qeth_query_card_info(struct qeth_card *card, - struct carrier_info *carrier_info) + struct qeth_link_info *link_info) { struct qeth_cmd_buffer *iob; @@ -4894,8 +4948,162 @@ int qeth_query_card_info(struct qeth_card *card, iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_CARD_INFO, 0); if (!iob) return -ENOMEM; - return qeth_send_ipa_cmd(card, iob, qeth_query_card_info_cb, - (void *)carrier_info); + + return qeth_send_ipa_cmd(card, iob, qeth_query_card_info_cb, link_info); +} + +static int qeth_init_link_info_oat_cb(struct qeth_card *card, + struct qeth_reply *reply_priv, + unsigned long data) +{ + struct qeth_ipa_cmd *cmd = (struct qeth_ipa_cmd *)data; + struct qeth_link_info *link_info = reply_priv->param; + struct qeth_query_oat_physical_if *phys_if; + struct qeth_query_oat_reply *reply; + + if (qeth_setadpparms_inspect_rc(cmd)) + return -EIO; + + /* Multi-part reply is unexpected, don't bother: */ + if (cmd->data.setadapterparms.hdr.used_total > 1) + return -EINVAL; + + /* Expect the reply to start with phys_if data: */ + reply = &cmd->data.setadapterparms.data.query_oat.reply[0]; + if (reply->type != QETH_QOAT_REPLY_TYPE_PHYS_IF || + reply->length < sizeof(*reply)) + return -EINVAL; + + phys_if = &reply->phys_if; + + switch (phys_if->speed_duplex) { + case QETH_QOAT_PHYS_SPEED_10M_HALF: + link_info->speed = SPEED_10; + link_info->duplex = DUPLEX_HALF; + break; + case QETH_QOAT_PHYS_SPEED_10M_FULL: + link_info->speed = SPEED_10; + link_info->duplex = DUPLEX_FULL; + break; + case QETH_QOAT_PHYS_SPEED_100M_HALF: + link_info->speed = SPEED_100; + link_info->duplex = DUPLEX_HALF; + break; + case QETH_QOAT_PHYS_SPEED_100M_FULL: + link_info->speed = SPEED_100; + link_info->duplex = DUPLEX_FULL; + break; + case QETH_QOAT_PHYS_SPEED_1000M_HALF: + link_info->speed = SPEED_1000; + link_info->duplex = DUPLEX_HALF; + break; + case QETH_QOAT_PHYS_SPEED_1000M_FULL: + link_info->speed = SPEED_1000; + link_info->duplex = DUPLEX_FULL; + break; + case QETH_QOAT_PHYS_SPEED_10G_FULL: + link_info->speed = SPEED_10000; + link_info->duplex = DUPLEX_FULL; + break; + case QETH_QOAT_PHYS_SPEED_25G_FULL: + link_info->speed = SPEED_25000; + link_info->duplex = DUPLEX_FULL; + break; + case QETH_QOAT_PHYS_SPEED_UNKNOWN: + default: + link_info->speed = SPEED_UNKNOWN; + link_info->duplex = DUPLEX_UNKNOWN; + break; + } + + switch (phys_if->media_type) { + case QETH_QOAT_PHYS_MEDIA_COPPER: + link_info->port = PORT_TP; + link_info->link_mode = QETH_LINK_MODE_UNKNOWN; + break; + case QETH_QOAT_PHYS_MEDIA_FIBRE_SHORT: + link_info->port = PORT_FIBRE; + link_info->link_mode = QETH_LINK_MODE_FIBRE_SHORT; + break; + case QETH_QOAT_PHYS_MEDIA_FIBRE_LONG: + link_info->port = PORT_FIBRE; + link_info->link_mode = QETH_LINK_MODE_FIBRE_LONG; + break; + default: + link_info->port = PORT_OTHER; + link_info->link_mode = QETH_LINK_MODE_UNKNOWN; + break; + } + + return 0; +} + +static void qeth_init_link_info(struct qeth_card *card) +{ + card->info.link_info.duplex = DUPLEX_FULL; + + if (IS_IQD(card) || IS_VM_NIC(card)) { + card->info.link_info.speed = SPEED_10000; + card->info.link_info.port = PORT_FIBRE; + card->info.link_info.link_mode = QETH_LINK_MODE_FIBRE_SHORT; + } else { + switch (card->info.link_type) { + case QETH_LINK_TYPE_FAST_ETH: + case QETH_LINK_TYPE_LANE_ETH100: + card->info.link_info.speed = SPEED_100; + card->info.link_info.port = PORT_TP; + break; + case QETH_LINK_TYPE_GBIT_ETH: + case QETH_LINK_TYPE_LANE_ETH1000: + card->info.link_info.speed = SPEED_1000; + card->info.link_info.port = PORT_FIBRE; + break; + case QETH_LINK_TYPE_10GBIT_ETH: + card->info.link_info.speed = SPEED_10000; + card->info.link_info.port = PORT_FIBRE; + break; + case QETH_LINK_TYPE_25GBIT_ETH: + card->info.link_info.speed = SPEED_25000; + card->info.link_info.port = PORT_FIBRE; + break; + default: + dev_info(&card->gdev->dev, "Unknown link type %x\n", + card->info.link_type); + card->info.link_info.speed = SPEED_UNKNOWN; + card->info.link_info.port = PORT_OTHER; + } + + card->info.link_info.link_mode = QETH_LINK_MODE_UNKNOWN; + } + + /* Get more accurate data via QUERY OAT: */ + if (qeth_adp_supported(card, IPA_SETADP_QUERY_OAT)) { + struct qeth_link_info link_info; + struct qeth_cmd_buffer *iob; + + iob = qeth_get_adapter_cmd(card, IPA_SETADP_QUERY_OAT, + SETADP_DATA_SIZEOF(query_oat)); + if (iob) { + struct qeth_ipa_cmd *cmd = __ipa_cmd(iob); + struct qeth_query_oat *oat_req; + + oat_req = &cmd->data.setadapterparms.data.query_oat; + oat_req->subcmd_code = QETH_QOAT_SCOPE_INTERFACE; + + if (!qeth_send_ipa_cmd(card, iob, + qeth_init_link_info_oat_cb, + &link_info)) { + if (link_info.speed != SPEED_UNKNOWN) + card->info.link_info.speed = link_info.speed; + if (link_info.duplex != DUPLEX_UNKNOWN) + card->info.link_info.duplex = link_info.duplex; + if (link_info.port != PORT_OTHER) + card->info.link_info.port = link_info.port; + if (link_info.link_mode != QETH_LINK_MODE_UNKNOWN) + card->info.link_info.link_mode = link_info.link_mode; + } + } + } } /** @@ -5282,6 +5490,8 @@ retriable: goto out; } + qeth_init_link_info(card); + rc = qeth_init_qdio_queues(card); if (rc) { QETH_CARD_TEXT_(card, 2, "9err%d", rc); @@ -5867,26 +6077,63 @@ static void qeth_iqd_tx_complete(struct qeth_qdio_out_q *queue, QDIO_OUTBUF_STATE_FLAG_PENDING)) { WARN_ON_ONCE(card->options.cq != QETH_CQ_ENABLED); - if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED, - QETH_QDIO_BUF_PENDING) == - QETH_QDIO_BUF_PRIMED) - qeth_notify_skbs(queue, buffer, TX_NOTIFY_PENDING); - QETH_CARD_TEXT_(card, 5, "pel%u", bidx); - /* prepare the queue slot for re-use: */ - qeth_scrub_qdio_buffer(buffer->buffer, queue->max_elements); - if (qeth_init_qdio_out_buf(queue, bidx)) { - QETH_CARD_TEXT(card, 2, "outofbuf"); - qeth_schedule_recovery(card); - } + switch (atomic_cmpxchg(&buffer->state, + QETH_QDIO_BUF_PRIMED, + QETH_QDIO_BUF_PENDING)) { + case QETH_QDIO_BUF_PRIMED: + /* We have initial ownership, no QAOB (yet): */ + qeth_notify_skbs(queue, buffer, TX_NOTIFY_PENDING); - return; - } + /* Handle race with qeth_qdio_handle_aob(): */ + switch (atomic_xchg(&buffer->state, + QETH_QDIO_BUF_NEED_QAOB)) { + case QETH_QDIO_BUF_PENDING: + /* No concurrent QAOB notification. */ + + /* Prepare the queue slot for immediate re-use: */ + qeth_scrub_qdio_buffer(buffer->buffer, queue->max_elements); + if (qeth_init_qdio_out_buf(queue, bidx)) { + QETH_CARD_TEXT(card, 2, "outofbuf"); + qeth_schedule_recovery(card); + } - if (card->options.cq == QETH_CQ_ENABLED) + /* Skip clearing the buffer: */ + return; + case QETH_QDIO_BUF_QAOB_OK: + qeth_notify_skbs(queue, buffer, + TX_NOTIFY_DELAYED_OK); + error = false; + break; + case QETH_QDIO_BUF_QAOB_ERROR: + qeth_notify_skbs(queue, buffer, + TX_NOTIFY_DELAYED_GENERALERROR); + error = true; + break; + default: + WARN_ON_ONCE(1); + } + + break; + case QETH_QDIO_BUF_QAOB_OK: + /* qeth_qdio_handle_aob() already received a QAOB: */ + qeth_notify_skbs(queue, buffer, TX_NOTIFY_OK); + error = false; + break; + case QETH_QDIO_BUF_QAOB_ERROR: + /* qeth_qdio_handle_aob() already received a QAOB: */ + qeth_notify_skbs(queue, buffer, TX_NOTIFY_GENERALERROR); + error = true; + break; + default: + WARN_ON_ONCE(1); + } + } else if (card->options.cq == QETH_CQ_ENABLED) { qeth_notify_skbs(queue, buffer, qeth_compute_cq_notification(sflags, 0)); + } + qeth_clear_output_buffer(queue, buffer, error, budget); } @@ -6141,13 +6388,11 @@ void qeth_core_free_discipline(struct qeth_card *card) const struct device_type qeth_generic_devtype = { .name = "qeth_generic", - .groups = qeth_generic_attr_groups, }; EXPORT_SYMBOL_GPL(qeth_generic_devtype); static const struct device_type qeth_osn_devtype = { .name = "qeth_osn", - .groups = qeth_osn_attr_groups, }; #define DBF_NAME_LEN 20 @@ -6327,6 +6572,11 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev) if (rc) goto err_chp_desc; + if (IS_OSN(card)) + gdev->dev.groups = qeth_osn_dev_groups; + else + gdev->dev.groups = qeth_dev_groups; + enforced_disc = qeth_enforce_discipline(card); switch (enforced_disc) { case QETH_DISCIPLINE_UNDETERMINED: diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index 6541bab96822..e4bde7daf083 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -489,9 +489,45 @@ struct qeth_set_access_ctrl { __u8 reserved[8]; } __attribute__((packed)); +#define QETH_QOAT_PHYS_SPEED_UNKNOWN 0x00 +#define QETH_QOAT_PHYS_SPEED_10M_HALF 0x01 +#define QETH_QOAT_PHYS_SPEED_10M_FULL 0x02 +#define QETH_QOAT_PHYS_SPEED_100M_HALF 0x03 +#define QETH_QOAT_PHYS_SPEED_100M_FULL 0x04 +#define QETH_QOAT_PHYS_SPEED_1000M_HALF 0x05 +#define QETH_QOAT_PHYS_SPEED_1000M_FULL 0x06 +// n/a 0x07 +#define QETH_QOAT_PHYS_SPEED_10G_FULL 0x08 +// n/a 0x09 +#define QETH_QOAT_PHYS_SPEED_25G_FULL 0x0A + +#define QETH_QOAT_PHYS_MEDIA_COPPER 0x01 +#define QETH_QOAT_PHYS_MEDIA_FIBRE_SHORT 0x02 +#define QETH_QOAT_PHYS_MEDIA_FIBRE_LONG 0x04 + +struct qeth_query_oat_physical_if { + u8 res_head[33]; + u8 speed_duplex; + u8 media_type; + u8 res_tail[29]; +}; + +#define QETH_QOAT_REPLY_TYPE_PHYS_IF 0x0004 + +struct qeth_query_oat_reply { + u16 type; + u16 length; + u16 version; + u8 res[10]; + struct qeth_query_oat_physical_if phys_if; +}; + +#define QETH_QOAT_SCOPE_INTERFACE 0x00000001 + struct qeth_query_oat { - __u32 subcmd_code; - __u8 reserved[12]; + u32 subcmd_code; + u8 reserved[12]; + struct qeth_query_oat_reply reply[]; } __packed; struct qeth_qoat_priv { diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 4441b3393eaf..a0f777f76f66 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -640,23 +640,17 @@ static struct attribute *qeth_blkt_device_attrs[] = { &dev_attr_inter_jumbo.attr, NULL, }; -const struct attribute_group qeth_device_blkt_group = { + +static const struct attribute_group qeth_dev_blkt_group = { .name = "blkt", .attrs = qeth_blkt_device_attrs, }; -EXPORT_SYMBOL_GPL(qeth_device_blkt_group); -static struct attribute *qeth_device_attrs[] = { - &dev_attr_state.attr, - &dev_attr_chpid.attr, - &dev_attr_if_name.attr, - &dev_attr_card_type.attr, +static struct attribute *qeth_dev_extended_attrs[] = { &dev_attr_inbuf_size.attr, &dev_attr_portno.attr, &dev_attr_portname.attr, &dev_attr_priority_queueing.attr, - &dev_attr_buffer_count.attr, - &dev_attr_recover.attr, &dev_attr_performance_stats.attr, &dev_attr_layer2.attr, &dev_attr_isolation.attr, @@ -664,18 +658,12 @@ static struct attribute *qeth_device_attrs[] = { &dev_attr_switch_attrs.attr, NULL, }; -const struct attribute_group qeth_device_attr_group = { - .attrs = qeth_device_attrs, -}; -EXPORT_SYMBOL_GPL(qeth_device_attr_group); -const struct attribute_group *qeth_generic_attr_groups[] = { - &qeth_device_attr_group, - &qeth_device_blkt_group, - NULL, +static const struct attribute_group qeth_dev_extended_group = { + .attrs = qeth_dev_extended_attrs, }; -static struct attribute *qeth_osn_device_attrs[] = { +static struct attribute *qeth_dev_attrs[] = { &dev_attr_state.attr, &dev_attr_chpid.attr, &dev_attr_if_name.attr, @@ -684,10 +672,19 @@ static struct attribute *qeth_osn_device_attrs[] = { &dev_attr_recover.attr, NULL, }; -static struct attribute_group qeth_osn_device_attr_group = { - .attrs = qeth_osn_device_attrs, + +static const struct attribute_group qeth_dev_group = { + .attrs = qeth_dev_attrs, }; -const struct attribute_group *qeth_osn_attr_groups[] = { - &qeth_osn_device_attr_group, + +const struct attribute_group *qeth_osn_dev_groups[] = { + &qeth_dev_group, + NULL, +}; + +const struct attribute_group *qeth_dev_groups[] = { + &qeth_dev_group, + &qeth_dev_extended_group, + &qeth_dev_blkt_group, NULL, }; diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c index b5caa723326e..3a51bbff0ffe 100644 --- a/drivers/s390/net/qeth_ethtool.c +++ b/drivers/s390/net/qeth_ethtool.c @@ -324,8 +324,8 @@ static int qeth_set_per_queue_coalesce(struct net_device *dev, u32 queue, /* Autoneg and full-duplex are supported and advertised unconditionally. */ /* Always advertise and support all speeds up to specified, and only one */ /* specified port type. */ -static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd, - int maxspeed, int porttype) +static void qeth_set_ethtool_link_modes(struct ethtool_link_ksettings *cmd, + enum qeth_link_mode link_mode) { ethtool_link_ksettings_zero_link_mode(cmd, supported); ethtool_link_ksettings_zero_link_mode(cmd, advertising); @@ -334,186 +334,119 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd, ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg); - switch (porttype) { + switch (cmd->base.port) { case PORT_TP: ethtool_link_ksettings_add_link_mode(cmd, supported, TP); ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); + + switch (cmd->base.speed) { + case SPEED_10000: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10000baseT_Full); + fallthrough; + case SPEED_1000: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 1000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 1000baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, + 1000baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 1000baseT_Half); + fallthrough; + case SPEED_100: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 100baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 100baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, + 100baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 100baseT_Half); + fallthrough; + case SPEED_10: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10baseT_Full); + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10baseT_Half); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10baseT_Half); + break; + default: + break; + } + break; case PORT_FIBRE: ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE); - break; - default: - ethtool_link_ksettings_add_link_mode(cmd, supported, TP); - ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); - WARN_ON_ONCE(1); - } - /* partially does fall through, to also select lower speeds */ - switch (maxspeed) { - case SPEED_25000: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 25000baseSR_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 25000baseSR_Full); - break; - case SPEED_10000: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10000baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10000baseT_Full); - fallthrough; - case SPEED_1000: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 1000baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 1000baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, - 1000baseT_Half); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 1000baseT_Half); - fallthrough; - case SPEED_100: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 100baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 100baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, - 100baseT_Half); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 100baseT_Half); - fallthrough; - case SPEED_10: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10baseT_Half); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10baseT_Half); + switch (cmd->base.speed) { + case SPEED_25000: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 25000baseSR_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 25000baseSR_Full); + break; + case SPEED_10000: + if (link_mode == QETH_LINK_MODE_FIBRE_LONG) { + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10000baseLR_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10000baseLR_Full); + } else if (link_mode == QETH_LINK_MODE_FIBRE_SHORT) { + ethtool_link_ksettings_add_link_mode(cmd, supported, + 10000baseSR_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 10000baseSR_Full); + } + break; + case SPEED_1000: + ethtool_link_ksettings_add_link_mode(cmd, supported, + 1000baseX_Full); + ethtool_link_ksettings_add_link_mode(cmd, advertising, + 1000baseX_Full); + break; + default: + break; + } + break; default: - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10baseT_Full); - ethtool_link_ksettings_add_link_mode(cmd, supported, - 10baseT_Half); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - 10baseT_Half); - WARN_ON_ONCE(1); + break; } } - static int qeth_get_link_ksettings(struct net_device *netdev, struct ethtool_link_ksettings *cmd) { struct qeth_card *card = netdev->ml_priv; - enum qeth_link_types link_type; - struct carrier_info carrier_info; - int rc; + struct qeth_link_info link_info; - if (IS_IQD(card) || IS_VM_NIC(card)) - link_type = QETH_LINK_TYPE_10GBIT_ETH; - else - link_type = card->info.link_type; - - cmd->base.duplex = DUPLEX_FULL; + cmd->base.speed = card->info.link_info.speed; + cmd->base.duplex = card->info.link_info.duplex; + cmd->base.port = card->info.link_info.port; cmd->base.autoneg = AUTONEG_ENABLE; cmd->base.phy_address = 0; cmd->base.mdio_support = 0; cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID; cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID; - switch (link_type) { - case QETH_LINK_TYPE_FAST_ETH: - case QETH_LINK_TYPE_LANE_ETH100: - cmd->base.speed = SPEED_100; - cmd->base.port = PORT_TP; - break; - case QETH_LINK_TYPE_GBIT_ETH: - case QETH_LINK_TYPE_LANE_ETH1000: - cmd->base.speed = SPEED_1000; - cmd->base.port = PORT_FIBRE; - break; - case QETH_LINK_TYPE_10GBIT_ETH: - cmd->base.speed = SPEED_10000; - cmd->base.port = PORT_FIBRE; - break; - case QETH_LINK_TYPE_25GBIT_ETH: - cmd->base.speed = SPEED_25000; - cmd->base.port = PORT_FIBRE; - break; - default: - cmd->base.speed = SPEED_10; - cmd->base.port = PORT_TP; - } - qeth_set_cmd_adv_sup(cmd, cmd->base.speed, cmd->base.port); - /* Check if we can obtain more accurate information. */ - /* If QUERY_CARD_INFO command is not supported or fails, */ - /* just return the heuristics that was filled above. */ - rc = qeth_query_card_info(card, &carrier_info); - if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */ - return 0; - if (rc) /* report error from the hardware operation */ - return rc; - /* on success, fill in the information got from the hardware */ - - netdev_dbg(netdev, - "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n", - carrier_info.card_type, - carrier_info.port_mode, - carrier_info.port_speed); - - /* Update attributes for which we've obtained more authoritative */ - /* information, leave the rest the way they where filled above. */ - switch (carrier_info.card_type) { - case CARD_INFO_TYPE_1G_COPPER_A: - case CARD_INFO_TYPE_1G_COPPER_B: - cmd->base.port = PORT_TP; - qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port); - break; - case CARD_INFO_TYPE_1G_FIBRE_A: - case CARD_INFO_TYPE_1G_FIBRE_B: - cmd->base.port = PORT_FIBRE; - qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port); - break; - case CARD_INFO_TYPE_10G_FIBRE_A: - case CARD_INFO_TYPE_10G_FIBRE_B: - cmd->base.port = PORT_FIBRE; - qeth_set_cmd_adv_sup(cmd, SPEED_10000, cmd->base.port); - break; - } - - switch (carrier_info.port_mode) { - case CARD_INFO_PORTM_FULLDUPLEX: - cmd->base.duplex = DUPLEX_FULL; - break; - case CARD_INFO_PORTM_HALFDUPLEX: - cmd->base.duplex = DUPLEX_HALF; - break; + if (!qeth_query_card_info(card, &link_info)) { + if (link_info.speed != SPEED_UNKNOWN) + cmd->base.speed = link_info.speed; + if (link_info.duplex != DUPLEX_UNKNOWN) + cmd->base.duplex = link_info.duplex; + if (link_info.port != PORT_OTHER) + cmd->base.port = link_info.port; } - switch (carrier_info.port_speed) { - case CARD_INFO_PORTS_10M: - cmd->base.speed = SPEED_10; - break; - case CARD_INFO_PORTS_100M: - cmd->base.speed = SPEED_100; - break; - case CARD_INFO_PORTS_1G: - cmd->base.speed = SPEED_1000; - break; - case CARD_INFO_PORTS_10G: - cmd->base.speed = SPEED_10000; - break; - case CARD_INFO_PORTS_25G: - cmd->base.speed = SPEED_25000; - break; - } + qeth_set_ethtool_link_modes(cmd, card->info.link_info.link_mode); return 0; } diff --git a/drivers/s390/net/qeth_l2.h b/drivers/s390/net/qeth_l2.h index 296d73d84326..7c646e2fed7e 100644 --- a/drivers/s390/net/qeth_l2.h +++ b/drivers/s390/net/qeth_l2.h @@ -11,8 +11,6 @@ extern const struct attribute_group *qeth_l2_attr_groups[]; -int qeth_l2_create_device_attributes(struct device *); -void qeth_l2_remove_device_attributes(struct device *); int qeth_bridgeport_query_ports(struct qeth_card *card, enum qeth_sbp_roles *role, enum qeth_sbp_states *state); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 28f6dda95736..4ed0fb0705a5 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -737,8 +737,6 @@ static void qeth_l2_dev2br_an_set_cb(void *priv, * * On enable, emits a series of address notifications for all * currently registered hosts. - * - * Must be called under rtnl_lock */ static int qeth_l2_dev2br_an_set(struct qeth_card *card, bool enable) { @@ -985,32 +983,19 @@ static void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card) * change notification' and thus can support the learning_sync bridgeport * attribute * @card: qeth_card structure pointer - * - * This is a destructive test and must be called before dev2br or - * bridgeport address notification is enabled! */ static void qeth_l2_detect_dev2br_support(struct qeth_card *card) { struct qeth_priv *priv = netdev_priv(card->dev); bool dev2br_supported; - int rc; QETH_CARD_TEXT(card, 2, "d2brsup"); if (!IS_IQD(card)) return; /* dev2br requires valid cssid,iid,chid */ - if (!card->info.ids_valid) { - dev2br_supported = false; - } else if (css_general_characteristics.enarf) { - dev2br_supported = true; - } else { - /* Old machines don't have the feature bit: - * Probe by testing whether a disable succeeds - */ - rc = qeth_l2_pnso(card, PNSO_OC_NET_ADDR_INFO, 0, NULL, NULL); - dev2br_supported = !rc; - } + dev2br_supported = card->info.ids_valid && + css_general_characteristics.enarf; QETH_CARD_TEXT_(card, 2, "D2Bsup%02x", dev2br_supported); if (dev2br_supported) @@ -1289,16 +1274,19 @@ static void qeth_l2_dev2br_worker(struct work_struct *work) if (READ_ONCE(card->info.pnso_mode) == QETH_PNSO_NONE) goto free; - /* Potential re-config in progress, try again later: */ - if (!rtnl_trylock()) { - queue_delayed_work(card->event_wq, dwork, - msecs_to_jiffies(100)); - return; - } - if (!netif_device_present(card->dev)) - goto out_unlock; - if (data->ac_event.lost_event_mask) { + /* Potential re-config in progress, try again later: */ + if (!rtnl_trylock()) { + queue_delayed_work(card->event_wq, dwork, + msecs_to_jiffies(100)); + return; + } + + if (!netif_device_present(card->dev)) { + rtnl_unlock(); + goto free; + } + QETH_DBF_MESSAGE(3, "Address change notification overflow on device %x\n", CARD_DEVID(card)); @@ -1328,6 +1316,8 @@ static void qeth_l2_dev2br_worker(struct work_struct *work) "Address Notification resynced on device %x\n", CARD_DEVID(card)); } + + rtnl_unlock(); } else { for (i = 0; i < data->ac_event.num_entries; i++) { struct qeth_ipacmd_addr_change_entry *entry = @@ -1339,9 +1329,6 @@ static void qeth_l2_dev2br_worker(struct work_struct *work) } } -out_unlock: - rtnl_unlock(); - free: kfree(data); } @@ -2202,7 +2189,7 @@ static int qeth_l2_probe_device(struct ccwgroup_device *gdev) mutex_init(&card->sbp_lock); if (gdev->dev.type == &qeth_generic_devtype) { - rc = qeth_l2_create_device_attributes(&gdev->dev); + rc = device_add_groups(&gdev->dev, qeth_l2_attr_groups); if (rc) return rc; } @@ -2216,7 +2203,7 @@ static void qeth_l2_remove_device(struct ccwgroup_device *gdev) struct qeth_card *card = dev_get_drvdata(&gdev->dev); if (gdev->dev.type == &qeth_generic_devtype) - qeth_l2_remove_device_attributes(&gdev->dev); + device_remove_groups(&gdev->dev, qeth_l2_attr_groups); qeth_set_allowed_threads(card, 0, 1); wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); @@ -2233,7 +2220,6 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok) struct net_device *dev = card->dev; int rc = 0; - /* query before bridgeport_notification may be enabled */ qeth_l2_detect_dev2br_support(card); mutex_lock(&card->sbp_lock); @@ -2310,11 +2296,8 @@ static void qeth_l2_set_offline(struct qeth_card *card) card->state = CARD_STATE_DOWN; qeth_l2_set_pnso_mode(card, QETH_PNSO_NONE); - if (priv->brport_features & BR_LEARNING_SYNC) { - rtnl_lock(); + if (priv->brport_features & BR_LEARNING_SYNC) qeth_l2_dev2br_fdb_flush(card); - rtnl_unlock(); - } } /* Returns zero if the command is successfully "consumed" */ diff --git a/drivers/s390/net/qeth_l2_sys.c b/drivers/s390/net/qeth_l2_sys.c index 4ba3bc57263f..a617351fff57 100644 --- a/drivers/s390/net/qeth_l2_sys.c +++ b/drivers/s390/net/qeth_l2_sys.c @@ -376,26 +376,7 @@ static struct attribute_group qeth_l2_vnicc_attr_group = { .name = "vnicc", }; -static const struct attribute_group *qeth_l2_only_attr_groups[] = { - &qeth_l2_bridgeport_attr_group, - &qeth_l2_vnicc_attr_group, - NULL, -}; - -int qeth_l2_create_device_attributes(struct device *dev) -{ - return sysfs_create_groups(&dev->kobj, qeth_l2_only_attr_groups); -} - -void qeth_l2_remove_device_attributes(struct device *dev) -{ - sysfs_remove_groups(&dev->kobj, qeth_l2_only_attr_groups); -} - const struct attribute_group *qeth_l2_attr_groups[] = { - &qeth_device_attr_group, - &qeth_device_blkt_group, - /* l2 specific, see qeth_l2_only_attr_groups: */ &qeth_l2_bridgeport_attr_group, &qeth_l2_vnicc_attr_group, NULL, diff --git a/drivers/s390/net/qeth_l3.h b/drivers/s390/net/qeth_l3.h index acd130cfbab3..30c2b31d99f6 100644 --- a/drivers/s390/net/qeth_l3.h +++ b/drivers/s390/net/qeth_l3.h @@ -103,8 +103,6 @@ extern const struct attribute_group *qeth_l3_attr_groups[]; int qeth_l3_ipaddr_to_string(enum qeth_prot_versions proto, const u8 *addr, char *buf); -int qeth_l3_create_device_attributes(struct device *); -void qeth_l3_remove_device_attributes(struct device *); int qeth_l3_setrouting_v4(struct qeth_card *); int qeth_l3_setrouting_v6(struct qeth_card *); int qeth_l3_add_ipato_entry(struct qeth_card *, struct qeth_ipato_entry *); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index b1c1d2510d55..d138ac432d01 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -104,10 +104,7 @@ static bool qeth_l3_is_addr_covered_by_ipato(struct qeth_card *card, qeth_l3_convert_addr_to_bits(ipatoe->addr, ipatoe_bits, (ipatoe->proto == QETH_PROT_IPV4) ? 4 : 16); - if (addr->proto == QETH_PROT_IPV4) - rc = !memcmp(addr_bits, ipatoe_bits, ipatoe->mask_bits); - else - rc = !memcmp(addr_bits, ipatoe_bits, ipatoe->mask_bits); + rc = !memcmp(addr_bits, ipatoe_bits, ipatoe->mask_bits); if (rc) break; } @@ -1952,7 +1949,7 @@ static int qeth_l3_probe_device(struct ccwgroup_device *gdev) return -ENOMEM; if (gdev->dev.type == &qeth_generic_devtype) { - rc = qeth_l3_create_device_attributes(&gdev->dev); + rc = device_add_groups(&gdev->dev, qeth_l3_attr_groups); if (rc) { destroy_workqueue(card->cmd_wq); return rc; @@ -1968,7 +1965,7 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev) struct qeth_card *card = dev_get_drvdata(&cgdev->dev); if (cgdev->dev.type == &qeth_generic_devtype) - qeth_l3_remove_device_attributes(&cgdev->dev); + device_remove_groups(&cgdev->dev, qeth_l3_attr_groups); qeth_set_allowed_threads(card, 0, 1); wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0); diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index 997fbb7006a7..1082380b21f8 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -805,28 +805,7 @@ static const struct attribute_group qeth_device_rxip_group = { .attrs = qeth_rxip_device_attrs, }; -static const struct attribute_group *qeth_l3_only_attr_groups[] = { - &qeth_l3_device_attr_group, - &qeth_device_ipato_group, - &qeth_device_vipa_group, - &qeth_device_rxip_group, - NULL, -}; - -int qeth_l3_create_device_attributes(struct device *dev) -{ - return sysfs_create_groups(&dev->kobj, qeth_l3_only_attr_groups); -} - -void qeth_l3_remove_device_attributes(struct device *dev) -{ - sysfs_remove_groups(&dev->kobj, qeth_l3_only_attr_groups); -} - const struct attribute_group *qeth_l3_attr_groups[] = { - &qeth_device_attr_group, - &qeth_device_blkt_group, - /* l3 specific, see qeth_l3_only_attr_groups: */ &qeth_l3_device_attr_group, &qeth_device_ipato_group, &qeth_device_vipa_group, diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index d9fd0a41da64..bdf2cc1ea713 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -194,23 +194,21 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev) } /** - * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish + * zfcp_ccw_set_offline - set_offline function of zfcp driver * @cdev: pointer to belonging ccw device - * @set: Status flags to set. - * @tag: s390dbf trace record tag * * This function gets called by the common i/o layer and sets an adapter * into state offline. */ -static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag) +static int zfcp_ccw_set_offline(struct ccw_device *cdev) { struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); if (!adapter) return 0; - zfcp_erp_set_adapter_status(adapter, set); - zfcp_erp_adapter_shutdown(adapter, 0, tag); + zfcp_erp_set_adapter_status(adapter, 0); + zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1"); zfcp_erp_wait(adapter); zfcp_ccw_adapter_put(adapter); @@ -218,18 +216,6 @@ static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag) } /** - * zfcp_ccw_set_offline - set_offline function of zfcp driver - * @cdev: pointer to belonging ccw device - * - * This function gets called by the common i/o layer and sets an adapter - * into state offline. - */ -static int zfcp_ccw_set_offline(struct ccw_device *cdev) -{ - return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1"); -} - -/** * zfcp_ccw_notify - ccw notify function * @cdev: pointer to belonging ccw device * @event: indicates if adapter was detached or attached @@ -246,11 +232,6 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event) switch (event) { case CIO_GONE: - if (atomic_read(&adapter->status) & - ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ - zfcp_dbf_hba_basic("ccnigo1", adapter); - break; - } dev_warn(&cdev->dev, "The FCP device has been detached\n"); zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1"); break; @@ -260,11 +241,6 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event) zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2"); break; case CIO_OPER: - if (atomic_read(&adapter->status) & - ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ - zfcp_dbf_hba_basic("ccniop1", adapter); - break; - } dev_info(&cdev->dev, "The FCP device is operational again\n"); zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); @@ -300,28 +276,6 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) zfcp_ccw_adapter_put(adapter); } -static int zfcp_ccw_suspend(struct ccw_device *cdev) -{ - zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1"); - return 0; -} - -static int zfcp_ccw_thaw(struct ccw_device *cdev) -{ - /* trace records for thaw and final shutdown during suspend - can only be found in system dump until the end of suspend - but not after resume because it's based on the memory image - right after the very first suspend (freeze) callback */ - zfcp_ccw_activate(cdev, 0, "ccthaw1"); - return 0; -} - -static int zfcp_ccw_resume(struct ccw_device *cdev) -{ - zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1"); - return 0; -} - struct ccw_driver zfcp_ccw_driver = { .driver = { .owner = THIS_MODULE, @@ -334,7 +288,4 @@ struct ccw_driver zfcp_ccw_driver = { .set_offline = zfcp_ccw_set_offline, .notify = zfcp_ccw_notify, .shutdown = zfcp_ccw_shutdown, - .freeze = zfcp_ccw_suspend, - .thaw = zfcp_ccw_thaw, - .restore = zfcp_ccw_resume, }; diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 673e42defb91..ca473b368905 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -263,31 +263,6 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount, spin_unlock_irqrestore(&dbf->pay_lock, flags); } -/** - * zfcp_dbf_hba_basic - trace event for basic adapter events - * @tag: identifier for event - * @adapter: pointer to struct zfcp_adapter - */ -void zfcp_dbf_hba_basic(char *tag, struct zfcp_adapter *adapter) -{ - struct zfcp_dbf *dbf = adapter->dbf; - struct zfcp_dbf_hba *rec = &dbf->hba_buf; - static int const level = 1; - unsigned long flags; - - if (unlikely(!debug_level_enabled(dbf->hba, level))) - return; - - spin_lock_irqsave(&dbf->hba_lock, flags); - memset(rec, 0, sizeof(*rec)); - - memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); - rec->id = ZFCP_DBF_HBA_BASIC; - - debug_event(dbf->hba, level, rec, sizeof(*rec)); - spin_unlock_irqrestore(&dbf->hba_lock, flags); -} - static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, struct zfcp_adapter *adapter, struct zfcp_port *port, diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index da8a5ceb615c..5069b555c6c1 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -70,7 +70,6 @@ #define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004 #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 -#define ZFCP_STATUS_ADAPTER_SUSPENDED 0x00000040 #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 #define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED 0x00000400 diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 3ef5d74331c3..fdac6350c579 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -49,7 +49,6 @@ extern void zfcp_dbf_hba_fsf_fces(char *tag, const struct zfcp_fsf_req *req, u32 fc_security_new); extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **); -extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *); extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); |