--- /dev/null
+From: Gerald Schaefer <geraldsc@de.ibm.com>
+Subject: zfcp: Fix oops when port disappears
+References: bnc#487755,LTC#52844
+
+Symptom: Kernel oops when port disappears.
+Problem: The zfcp_port might have been removed, while the FC
+ fast_io_fail timer is still running and could trigger
+ the terminate_rport_io callback.
+Solution: Set the pointer to the zfcp_port to NULL and check
+ accordingly before using it.
+
+Acked-by: John Jolly <jjolly@suse.de>
+---
+ drivers/s390/scsi/zfcp_aux.c | 3 +--
+ drivers/s390/scsi/zfcp_fsf.c | 4 ++++
+ drivers/s390/scsi/zfcp_scsi.c | 25 +++++++++++++++++++------
+ 3 files changed, 24 insertions(+), 8 deletions(-)
+
+--- a/drivers/s390/scsi/zfcp_aux.c
++++ b/drivers/s390/scsi/zfcp_aux.c
+@@ -677,8 +677,7 @@ void zfcp_port_dequeue(struct zfcp_port
+ list_del(&port->list);
+ write_unlock_irq(&zfcp_data.config_lock);
+ if (port->rport)
+- fc_remote_port_delete(port->rport);
+- port->rport = NULL;
++ port->rport->dd_data = NULL;
+ zfcp_adapter_put(port->adapter);
+ sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
+ device_unregister(&port->sysfs_device);
+--- a/drivers/s390/scsi/zfcp_fsf.c
++++ b/drivers/s390/scsi/zfcp_fsf.c
+@@ -175,12 +175,16 @@ static void zfcp_fsf_link_down_info_eval
+ struct fsf_link_down_info *link_down)
+ {
+ struct zfcp_adapter *adapter = req->adapter;
++ unsigned long flags;
+
+ if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
+ return;
+
+ atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
++
++ read_lock_irqsave(&zfcp_data.config_lock, flags);
+ zfcp_scsi_schedule_rports_block(adapter);
++ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+
+ if (!link_down)
+ goto out;
+--- a/drivers/s390/scsi/zfcp_scsi.c
++++ b/drivers/s390/scsi/zfcp_scsi.c
+@@ -491,10 +491,12 @@ static void zfcp_set_rport_dev_loss_tmo(
+ */
+ static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
+ {
+- struct zfcp_port *port = rport->dd_data;
++ struct zfcp_port *port;
+
+ write_lock_irq(&zfcp_data.config_lock);
+- port->rport = NULL;
++ port = rport->dd_data;
++ if (port)
++ port->rport = NULL;
+ write_unlock_irq(&zfcp_data.config_lock);
+ }
+
+@@ -508,9 +510,18 @@ static void zfcp_scsi_dev_loss_tmo_callb
+ */
+ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
+ {
+- struct zfcp_port *port = rport->dd_data;
++ struct zfcp_port *port;
+
+- zfcp_erp_port_reopen(port, 0, 152, NULL);
++ write_lock_irq(&zfcp_data.config_lock);
++ port = rport->dd_data;
++ if (port)
++ zfcp_port_get(port);
++ write_unlock_irq(&zfcp_data.config_lock);
++
++ if (port) {
++ zfcp_erp_port_reopen(port, 0, 152, NULL);
++ zfcp_port_put(port);
++ }
+ }
+
+ static void zfcp_scsi_rport_register(struct zfcp_port *port)
+@@ -539,8 +550,10 @@ static void zfcp_scsi_rport_register(str
+
+ static void zfcp_scsi_rport_block(struct zfcp_port *port)
+ {
+- if (port->rport)
+- fc_remote_port_delete(port->rport);
++ struct fc_rport *rport = port->rport;
++
++ if (rport)
++ fc_remote_port_delete(rport);
+ }
+
+ void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)