From 03cadd36d51c737d7ad6aa21e2524296be6fe57f Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Wed, 14 Oct 2009 12:43:45 +0200 Subject: [S390] tape390: Fix request queue handling in block driver When setting a channel attached tape online under Linux 2.6.31, the "vol_id" process from udev hangs in sync_page(): 2 sync_page+144 [0x1dfaac] 3 __wait_on_bit_lock+194 [0x58c23e] 4 __lock_page+116 [0x1df9dc] 5 truncate_inode_pages_range+728 [0x1ed7cc] 6 __blkdev_put+244 [0x25f738] 7 __fput+300 [0x229c4c] 8 filp_close+122 [0x225a3a] The reason for that is an error in the request queue handling. It can happen that we fetch a request, but do not process it further because the number of queued requests exceeds TAPEBLOCK_MIN_REQUEUE. To fix this, we should call blk_peek_request() instead of blk_fetch_request() in the while condition and fetch the request in the loop body afterwards. This bug was introduced with the patch "block: implement and enforce request peek/start/fetch" (9934c8c04561413609d2bc38c6b9f268cba774a4) Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- drivers/s390/char/tape_block.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 64f57ef..0c0705b 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c @@ -162,9 +162,10 @@ tapeblock_requeue(struct work_struct *work) { spin_lock_irq(&device->blk_data.request_queue_lock); while ( !blk_queue_plugged(queue) && - (req = blk_fetch_request(queue)) && + blk_peek_request(queue) && nr_queued < TAPEBLOCK_MIN_REQUEUE ) { + req = blk_fetch_request(queue); if (rq_data_dir(req) == WRITE) { DBF_EVENT(1, "TBLOCK: Rejecting write request\n"); spin_unlock_irq(&device->blk_data.request_queue_lock); -- cgit v1.1 From a7602f6c16b2de2962b279980693ad1b3711e84a Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Wed, 14 Oct 2009 12:43:46 +0200 Subject: [S390] dasd: fix locking bug Replace spin_lock with spin_lock_irqsave in dasd_eckd_restore_device. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eckd.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 0be7c15..417b97c 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -3216,6 +3216,7 @@ int dasd_eckd_restore_device(struct dasd_device *device) struct dasd_eckd_characteristics temp_rdc_data; int is_known, rc; struct dasd_uid temp_uid; + unsigned long flags; private = (struct dasd_eckd_private *) device->private; @@ -3228,7 +3229,8 @@ int dasd_eckd_restore_device(struct dasd_device *device) rc = dasd_eckd_generate_uid(device, &private->uid); dasd_get_uid(device->cdev, &temp_uid); if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0) - dev_err(&device->cdev->dev, "The UID of the DASD has changed\n"); + dev_err(&device->cdev->dev, "The UID of the DASD has " + "changed\n"); if (rc) goto out_err; dasd_set_uid(device->cdev, &private->uid); @@ -3256,9 +3258,9 @@ int dasd_eckd_restore_device(struct dasd_device *device) "device: %s", rc, dev_name(&device->cdev->dev)); goto out_err; } - spin_lock(get_ccwdev_lock(device->cdev)); + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); memcpy(&private->rdc_data, &temp_rdc_data, sizeof(temp_rdc_data)); - spin_unlock(get_ccwdev_lock(device->cdev)); + spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); /* add device to alias management */ dasd_alias_add_device(device); -- cgit v1.1 From d9fa9441ed6e0467d7d41de730581874c997e658 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Wed, 14 Oct 2009 12:43:48 +0200 Subject: [S390] dasd: use idal for device characteristics If the rdc_buffer is above 2G we need indirect addresssing so we have to use an idaw to give the rdc_buffer to the ccw. If the rdc_buffer is under 2G nothing changes. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 53b8c25..aaccc8e 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2533,6 +2533,7 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, { struct dasd_ccw_req *cqr; struct ccw1 *ccw; + unsigned long *idaw; cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device); @@ -2546,9 +2547,17 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, ccw = cqr->cpaddr; ccw->cmd_code = CCW_CMD_RDC; - ccw->cda = (__u32)(addr_t)rdc_buffer; - ccw->count = rdc_buffer_size; + if (idal_is_needed(rdc_buffer, rdc_buffer_size)) { + idaw = (unsigned long *) (cqr->data); + ccw->cda = (__u32)(addr_t) idaw; + ccw->flags = CCW_FLAG_IDA; + idaw = idal_create_words(idaw, rdc_buffer, rdc_buffer_size); + } else { + ccw->cda = (__u32)(addr_t) rdc_buffer; + ccw->flags = 0; + } + ccw->count = rdc_buffer_size; cqr->startdev = device; cqr->memdev = device; cqr->expires = 10*HZ; -- cgit v1.1 From d3acf71fb8daecc8ab8b1371d29d15df0c30a315 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 14 Oct 2009 12:43:49 +0200 Subject: [S390] call home support: fix proc handler 8d65af78 "sysctl: remove "struct file *" argument of ->proc_handler" removed the struct file argument from all proc_handlers but didn't change the call home proc handler (or call home was merged later). So fix this now. Cc: Alexey Dobriyan Cc: Hans-Joachim Picht Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_async.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c index daaec18..a4f68e5 100644 --- a/drivers/s390/char/sclp_async.c +++ b/drivers/s390/char/sclp_async.c @@ -62,7 +62,7 @@ static struct notifier_block call_home_panic_nb = { .priority = INT_MAX, }; -static int proc_handler_callhome(ctl_table *ctl, int write, struct file *filp, +static int proc_handler_callhome(struct ctl_table *ctl, int write, void __user *buffer, size_t *count, loff_t *ppos) { @@ -100,7 +100,7 @@ static struct ctl_table callhome_table[] = { { .procname = "callhome", .mode = 0644, - .proc_handler = &proc_handler_callhome, + .proc_handler = proc_handler_callhome, }, { .ctl_name = 0 } }; -- cgit v1.1 From 6d7c5afc890d0c9345ee05ccf0e6c692b6c8f8a8 Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Wed, 14 Oct 2009 12:43:50 +0200 Subject: [S390] cio: change misleading console logic Use cio_is_console() in io_subchannel_probe to indicate that the special handling is console specific. As long as there is no other subchannel for which this might be true, it is misleading to speak of "early devices". Should more of these devices be introduced, a cleanup of all console special handling is in order anyway. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 2ee093e..2490b74 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1250,8 +1250,7 @@ static int io_subchannel_probe(struct subchannel *sch) unsigned long flags; struct ccw_dev_id dev_id; - cdev = sch_get_cdev(sch); - if (cdev) { + if (cio_is_console(sch->schid)) { rc = sysfs_create_group(&sch->dev.kobj, &io_subchannel_attr_group); if (rc) @@ -1260,13 +1259,13 @@ static int io_subchannel_probe(struct subchannel *sch) "0.%x.%04x (rc=%d)\n", sch->schid.ssid, sch->schid.sch_no, rc); /* - * This subchannel already has an associated ccw_device. + * The console subchannel already has an associated ccw_device. * Throw the delayed uevent for the subchannel, register - * the ccw_device and exit. This happens for all early - * devices, e.g. the console. + * the ccw_device and exit. */ dev_set_uevent_suppress(&sch->dev, 0); kobject_uevent(&sch->dev.kobj, KOBJ_ADD); + cdev = sch_get_cdev(sch); cdev->dev.groups = ccwdev_attr_groups; device_initialize(&cdev->dev); ccw_device_register(cdev); -- cgit v1.1 From ac522b638dcb549f9d33085c6fadea88a5f826ae Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Wed, 14 Oct 2009 12:43:51 +0200 Subject: [S390] sclp_vt220 build fix Fix this build error: next-20091013 randconfig build on s390x build breaks with drivers/s390/built-in.o:(.data+0x3354): undefined reference to `sclp_vt220_pm_event_fn' Reported-by: Kamalesh Babulal Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_vt220.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 178724f..b9d2a00 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -705,21 +705,6 @@ out_driver: } __initcall(sclp_vt220_tty_init); -#ifdef CONFIG_SCLP_VT220_CONSOLE - -static void -sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count) -{ - __sclp_vt220_write((const unsigned char *) buf, count, 1, 1, 0); -} - -static struct tty_driver * -sclp_vt220_con_device(struct console *c, int *index) -{ - *index = 0; - return sclp_vt220_driver; -} - static void __sclp_vt220_flush_buffer(void) { unsigned long flags; @@ -776,6 +761,21 @@ static void sclp_vt220_pm_event_fn(struct sclp_register *reg, } } +#ifdef CONFIG_SCLP_VT220_CONSOLE + +static void +sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count) +{ + __sclp_vt220_write((const unsigned char *) buf, count, 1, 1, 0); +} + +static struct tty_driver * +sclp_vt220_con_device(struct console *c, int *index) +{ + *index = 0; + return sclp_vt220_driver; +} + static int sclp_vt220_notify(struct notifier_block *self, unsigned long event, void *data) -- cgit v1.1 From d10c0858f618c20547d4eda8aee9c3afd91599cf Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 13 Oct 2009 10:44:07 +0200 Subject: [SCSI] zfcp: fix kfree handling in zfcp_init_device_setup The pointer that is allocated with kmalloc() is passed to strsep() which modifies it. Later on the modified pointer value will be passed to kfree. Save the original pointer and pass that one to kfree instead. Signed-off-by: Heiko Carstens Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_aux.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 0f79f3a..2889e5f 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -128,12 +128,13 @@ out_ccwdev: static void __init zfcp_init_device_setup(char *devstr) { char *token; - char *str; + char *str, *str_saved; char busid[ZFCP_BUS_ID_SIZE]; u64 wwpn, lun; /* duplicate devstr and keep the original for sysfs presentation*/ - str = kmalloc(strlen(devstr) + 1, GFP_KERNEL); + str_saved = kmalloc(strlen(devstr) + 1, GFP_KERNEL); + str = str_saved; if (!str) return; @@ -152,12 +153,12 @@ static void __init zfcp_init_device_setup(char *devstr) if (!token || strict_strtoull(token, 0, (unsigned long long *) &lun)) goto err_out; - kfree(str); + kfree(str_saved); zfcp_init_device_configure(busid, wwpn, lun); return; - err_out: - kfree(str); +err_out: + kfree(str_saved); pr_err("%s is not a valid SCSI device\n", devstr); } -- cgit v1.1 From 934aeb587bab3173b6dec8e7717b909d8efc77b0 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Wed, 14 Oct 2009 11:00:43 +0200 Subject: [SCSI] zfcp: Handle WWPN mismatch in PLOGI payload For ports, zfcp gets the DID from the FC nameserver and tries to open the port. If the open succeeds, zfcp compares the WWPN from the nameserver with the WWPN in the PLOGI payload. In case of a mismatch, zfcp assumes that the DID of the port just changed and we opened the wrong port. This means that zfcp has to forget the DID, lookup the DID again and retry. This error case had a problem that zfcp forgets the DID, but never looks up a new one, stalling the ERP in this case. Fix this by triggering the DID lookup and properly exit from the ERP. The DID lookup will trigger a new ERP action. Also ensure when trying to open the port again with the new DID, first close the open port, even in the NOESC case. Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_erp.c | 22 ++++++++++------------ drivers/s390/scsi/zfcp_ext.h | 1 + drivers/s390/scsi/zfcp_fc.c | 11 +++++++++++ 3 files changed, 22 insertions(+), 12 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 73d366b..f73e218 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -858,10 +858,7 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) return zfcp_erp_open_ptp_port(act); if (!port->d_id) { - zfcp_port_get(port); - if (!queue_work(adapter->work_queue, - &port->gid_pn_work)) - zfcp_port_put(port); + zfcp_fc_trigger_did_lookup(port); return ZFCP_ERP_EXIT; } return zfcp_erp_port_strategy_open_port(act); @@ -869,12 +866,11 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) case ZFCP_ERP_STEP_PORT_OPENING: /* D_ID might have changed during open */ if (p_status & ZFCP_STATUS_COMMON_OPEN) { - if (port->d_id) - return ZFCP_ERP_SUCCEEDED; - else { - act->step = ZFCP_ERP_STEP_PORT_CLOSING; - return ZFCP_ERP_CONTINUES; + if (!port->d_id) { + zfcp_fc_trigger_did_lookup(port); + return ZFCP_ERP_EXIT; } + return ZFCP_ERP_SUCCEEDED; } if (port->d_id && !(p_status & ZFCP_STATUS_COMMON_NOESC)) { port->d_id = 0; @@ -889,19 +885,21 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act) static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action) { struct zfcp_port *port = erp_action->port; + int p_status = atomic_read(&port->status); - if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC) + if ((p_status & ZFCP_STATUS_COMMON_NOESC) && + !(p_status & ZFCP_STATUS_COMMON_OPEN)) goto close_init_done; switch (erp_action->step) { case ZFCP_ERP_STEP_UNINITIALIZED: zfcp_erp_port_strategy_clearstati(port); - if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN) + if (p_status & ZFCP_STATUS_COMMON_OPEN) return zfcp_erp_port_strategy_close(erp_action); break; case ZFCP_ERP_STEP_PORT_CLOSING: - if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN) + if (p_status & ZFCP_STATUS_COMMON_OPEN) return ZFCP_ERP_FAILED; break; } diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 629edec..b3f28de 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -96,6 +96,7 @@ extern int zfcp_fc_scan_ports(struct zfcp_adapter *); extern void _zfcp_fc_scan_ports_later(struct work_struct *); extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *); extern void zfcp_fc_port_did_lookup(struct work_struct *); +extern void zfcp_fc_trigger_did_lookup(struct zfcp_port *); extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *); extern void zfcp_fc_test_link(struct zfcp_port *); extern void zfcp_fc_link_test_work(struct work_struct *); diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c index 722f22d..df23bce 100644 --- a/drivers/s390/scsi/zfcp_fc.c +++ b/drivers/s390/scsi/zfcp_fc.c @@ -361,6 +361,17 @@ out: } /** + * zfcp_fc_trigger_did_lookup - trigger the d_id lookup using a GID_PN request + * @port: The zfcp_port to lookup the d_id for. + */ +void zfcp_fc_trigger_did_lookup(struct zfcp_port *port) +{ + zfcp_port_get(port); + if (!queue_work(port->adapter->work_queue, &port->gid_pn_work)) + zfcp_port_put(port); +} + +/** * zfcp_fc_plogi_evaluate - evaluate PLOGI playload * @port: zfcp_port structure * @plogi: plogi payload -- cgit v1.1 From 10d00f78e67223ef429fa5f4abfc9ea4ad740490 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 13 Oct 2009 10:44:09 +0200 Subject: [SCSI] zfcp: Warn about storage devices with broken PLOGI data After opening a remote port zfcp checks if the WWPN returned in the PLOGI maches the WWPN of the port that should have been opened. On a mismatch zfcp assumes that the DID just changed, queries the FC nameserver and tries again. If the situation persists the erp will give up. With this strategy, if the remote port always returns the wrong PLOGI data, the remote port will not be opened. Introduce a warning, so that the system administrator knows why the remote port is not being opened and to have a pointer to investigate the problem on the storage system. Reviewed-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 38a7e4a..5126461 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1475,9 +1475,16 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req) plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els; if (req->qtcb->bottom.support.els1_length >= FSF_PLOGI_MIN_LEN) { - if (plogi->serv_param.wwpn != port->wwpn) + if (plogi->serv_param.wwpn != port->wwpn) { port->d_id = 0; - else { + dev_warn(&port->adapter->ccw_device->dev, + "A port opened with WWPN 0x%016Lx " + "returned data that identifies it as " + "WWPN 0x%016Lx\n", + (unsigned long long) port->wwpn, + (unsigned long long) + plogi->serv_param.wwpn); + } else { port->wwnn = plogi->serv_param.wwnn; zfcp_fc_plogi_evaluate(port, plogi); } -- cgit v1.1 From 9d38500de156fb28ffa8741acb90c4dc90a9fb4b Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 13 Oct 2009 10:44:10 +0200 Subject: [SCSI] zfcp: Fix timer initialization for ct and els requests Add HZ since the start_timer function expects jiffies, not seconds. Reviewed-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_fsf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 5126461..4e41baa 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -1079,7 +1079,7 @@ static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req, /* common settings for ct/gs and els requests */ req->qtcb->bottom.support.service_class = FSF_CLASS_3; req->qtcb->bottom.support.timeout = 2 * R_A_TOV; - zfcp_fsf_start_timer(req, 2 * R_A_TOV + 10); + zfcp_fsf_start_timer(req, (2 * R_A_TOV + 10) * HZ); return 0; } -- cgit v1.1 From 9e820afd0c4f3c8e8894aa91f5671fd7d11a787b Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 13 Oct 2009 10:44:11 +0200 Subject: [SCSI] zfcp: Flush SCSI registration work when adding unit When configuring a LUN for use in zfcp, flush the SCSI work to ensure the SCSI device has been created before returning. This means that a configuration procedure can run these commands in a script and the SCSI device is available immediately after the unit_add: echo 1 > /sys/bus/ccw/drivers/zfcp/0.0.181d/online echo 0x401040C300000000 > \ /sys/bus/ccw/drivers/zfcp/0.0.181d/0x500507630313c562/unit_add lsscsi Reviewed-by: Swen Schillig Signed-off-by: Christof Schmitt Signed-off-by: James Bottomley --- drivers/s390/scsi/zfcp_sysfs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/s390') diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 079a8cf..d310008 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -224,6 +224,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL); zfcp_erp_wait(unit->port->adapter); + flush_work(&unit->scsi_work); zfcp_unit_put(unit); out: mutex_unlock(&zfcp_data.config_mutex); -- cgit v1.1 From 3f0b3c33eeed400577b47fab8439ffe6f40aa97a Mon Sep 17 00:00:00 2001 From: Sebastian Ott Date: Thu, 29 Oct 2009 15:04:07 +0100 Subject: [S390] call home: fix local buffer usage in proc handler Fix the size of the local buffer and use snprintf to prevent further miscalculations. Also fix the usage of bitwise vs logic operations. Signed-off-by: Sebastian Ott Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_async.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c index a4f68e5..bf4a9f4 100644 --- a/drivers/s390/char/sclp_async.c +++ b/drivers/s390/char/sclp_async.c @@ -68,15 +68,14 @@ static int proc_handler_callhome(struct ctl_table *ctl, int write, { unsigned long val; int len, rc; - char buf[2]; + char buf[3]; - if (!*count | (*ppos && !write)) { + if (!*count || (*ppos && !write)) { *count = 0; return 0; } if (!write) { - len = sprintf(buf, "%d\n", callhome_enabled); - buf[len] = '\0'; + len = snprintf(buf, sizeof(buf), "%d\n", callhome_enabled); rc = copy_to_user(buffer, buf, sizeof(buf)); if (rc != 0) return -EFAULT; -- cgit v1.1 From 8ca45667f966968132c772ddbb6468b41a817c19 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 29 Oct 2009 15:04:08 +0100 Subject: [S390] s/r: cmm resume fix If a suspended z/VM guest has been logged off before the resume the 'SET SMSG IUCV' CP command need to be repeated to reenable sending message via SMSG. This fixes the following error: HCPMFS057I H4214002 not receiving; SMSG off Error: non-zero CP response for command 'SMSG H4214002 CMM SHRINK 5010': #57 Signed-off-by: Martin Schwidefsky Signed-off-by: Martin Schwidefsky --- drivers/s390/net/smsgiucv.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index 102000d..3012355 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c @@ -158,7 +158,12 @@ static int smsg_pm_restore_thaw(struct device *dev) smsg_path->flags = 0; rc = iucv_path_connect(smsg_path, &smsg_handler, "*MSG ", NULL, NULL, NULL); - printk(KERN_ERR "iucv_path_connect returned with rc %i\n", rc); +#ifdef CONFIG_PM_DEBUG + if (rc) + printk(KERN_ERR + "iucv_path_connect returned with rc %i\n", rc); +#endif + cpcmd("SET SMSG IUCV", NULL, 0, NULL); } return 0; } -- cgit v1.1 From 4a0fb4c44573759f878fc65f6ddbd46080748f8b Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 29 Oct 2009 15:04:10 +0100 Subject: [S390] call home: fix error handling in init function Fix missing unregister_sysctl_table in case the SCLP doesn't provide the requested feature. Also simplify the whole error handling while at it. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_async.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c index bf4a9f4..3c20aa1 100644 --- a/drivers/s390/char/sclp_async.c +++ b/drivers/s390/char/sclp_async.c @@ -170,39 +170,31 @@ static int __init sclp_async_init(void) rc = sclp_register(&sclp_async_register); if (rc) return rc; - callhome_sysctl_header = register_sysctl_table(kern_dir_table); - if (!callhome_sysctl_header) { - rc = -ENOMEM; - goto out_sclp; - } - if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK)) { - rc = -EOPNOTSUPP; + rc = -EOPNOTSUPP; + if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK)) goto out_sclp; - } rc = -ENOMEM; + callhome_sysctl_header = register_sysctl_table(kern_dir_table); + if (!callhome_sysctl_header) + goto out_sclp; request = kzalloc(sizeof(struct sclp_req), GFP_KERNEL); - if (!request) - goto out_sys; sccb = (struct sclp_async_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); - if (!sccb) + if (!request || !sccb) goto out_mem; - rc = atomic_notifier_chain_register(&panic_notifier_list, - &call_home_panic_nb); + rc = atomic_notifier_chain_register(&panic_notifier_list, + &call_home_panic_nb); if (rc) goto out_mem; - strncpy(nodename, init_utsname()->nodename, 64); - return 0; - + goto out; out_mem: kfree(request); free_page((unsigned long) sccb); -out_sys: unregister_sysctl_table(callhome_sysctl_header); out_sclp: sclp_unregister(&sclp_async_register); +out: return rc; - } module_init(sclp_async_init); -- cgit v1.1 From e8a79c9ec779168502402a8b834abf8cf38a325a Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 29 Oct 2009 15:04:11 +0100 Subject: [S390] call home: fix string length handling After copying uts->nodename to the static nodename array the static version isn't necessarily zero termininated, since the size of the array is one byte too short. Afterwards doing strncat(data, nodename, strlen(nodename)); may copy an arbitrary large amount of bytes. Fix this by getting rid of the static array and using strncat with proper length limit. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/char/sclp_async.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c index 3c20aa1..b44462a 100644 --- a/drivers/s390/char/sclp_async.c +++ b/drivers/s390/char/sclp_async.c @@ -26,7 +26,6 @@ static struct sclp_async_sccb *sccb; static int sclp_async_send_wait(char *message); static struct ctl_table_header *callhome_sysctl_header; static DEFINE_SPINLOCK(sclp_async_lock); -static char nodename[64]; #define SCLP_NORMAL_WRITE 0x00 struct async_evbuf { @@ -52,9 +51,10 @@ static struct sclp_register sclp_async_register = { static int call_home_on_panic(struct notifier_block *self, unsigned long event, void *data) { - strncat(data, nodename, strlen(nodename)); - sclp_async_send_wait(data); - return NOTIFY_DONE; + strncat(data, init_utsname()->nodename, + sizeof(init_utsname()->nodename)); + sclp_async_send_wait(data); + return NOTIFY_DONE; } static struct notifier_block call_home_panic_nb = { @@ -183,10 +183,8 @@ static int __init sclp_async_init(void) goto out_mem; rc = atomic_notifier_chain_register(&panic_notifier_list, &call_home_panic_nb); - if (rc) - goto out_mem; - strncpy(nodename, init_utsname()->nodename, 64); - goto out; + if (!rc) + goto out; out_mem: kfree(request); free_page((unsigned long) sccb); -- cgit v1.1