aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/s390/scsi/zfcp_aux.c2
-rw-r--r--drivers/s390/scsi/zfcp_def.h5
-rw-r--r--drivers/s390/scsi/zfcp_erp.c64
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c5
4 files changed, 72 insertions, 4 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index ec3f664f6c80..49d5fc729bef 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -913,6 +913,8 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
913 unit->sysfs_device.release = zfcp_sysfs_unit_release; 913 unit->sysfs_device.release = zfcp_sysfs_unit_release;
914 dev_set_drvdata(&unit->sysfs_device, unit); 914 dev_set_drvdata(&unit->sysfs_device, unit);
915 915
916 init_waitqueue_head(&unit->scsi_scan_wq);
917
916 /* mark unit unusable as long as sysfs registration is not complete */ 918 /* mark unit unusable as long as sysfs registration is not complete */
917 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); 919 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
918 920
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index 32933ed54b8a..07b0957b82f3 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -637,6 +637,7 @@ do { \
637#define ZFCP_STATUS_UNIT_SHARED 0x00000004 637#define ZFCP_STATUS_UNIT_SHARED 0x00000004
638#define ZFCP_STATUS_UNIT_READONLY 0x00000008 638#define ZFCP_STATUS_UNIT_READONLY 0x00000008
639#define ZFCP_STATUS_UNIT_REGISTERED 0x00000010 639#define ZFCP_STATUS_UNIT_REGISTERED 0x00000010
640#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020
640 641
641/* FSF request status (this does not have a common part) */ 642/* FSF request status (this does not have a common part) */
642#define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000 643#define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000
@@ -980,6 +981,10 @@ struct zfcp_unit {
980 struct scsi_device *device; /* scsi device struct pointer */ 981 struct scsi_device *device; /* scsi device struct pointer */
981 struct zfcp_erp_action erp_action; /* pending error recovery */ 982 struct zfcp_erp_action erp_action; /* pending error recovery */
982 atomic_t erp_counter; 983 atomic_t erp_counter;
984 wait_queue_head_t scsi_scan_wq; /* can be used to wait until
985 all scsi_scan_target
986 requests have been
987 completed. */
983}; 988};
984 989
985/* FSF request */ 990/* FSF request */
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index f326bbe49fa7..885572300589 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -1591,6 +1591,62 @@ zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
1591 return result; 1591 return result;
1592} 1592}
1593 1593
1594struct zfcp_erp_add_work {
1595 struct zfcp_unit *unit;
1596 struct work_struct work;
1597};
1598
1599/**
1600 * zfcp_erp_scsi_scan
1601 * @data: pointer to a struct zfcp_erp_add_work
1602 *
1603 * Registers a logical unit with the SCSI stack.
1604 */
1605static void zfcp_erp_scsi_scan(struct work_struct *work)
1606{
1607 struct zfcp_erp_add_work *p =
1608 container_of(work, struct zfcp_erp_add_work, work);
1609 struct zfcp_unit *unit = p->unit;
1610 struct fc_rport *rport = unit->port->rport;
1611 scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
1612 unit->scsi_lun, 0);
1613 atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
1614 wake_up(&unit->scsi_scan_wq);
1615 zfcp_unit_put(unit);
1616 kfree(p);
1617}
1618
1619/**
1620 * zfcp_erp_schedule_work
1621 * @unit: pointer to unit which should be registered with SCSI stack
1622 *
1623 * Schedules work which registers a unit with the SCSI stack
1624 */
1625static void
1626zfcp_erp_schedule_work(struct zfcp_unit *unit)
1627{
1628 struct zfcp_erp_add_work *p;
1629
1630 p = kmalloc(sizeof(*p), GFP_KERNEL);
1631 if (!p) {
1632 ZFCP_LOG_NORMAL("error: Out of resources. Could not register "
1633 "the FCP-LUN 0x%Lx connected to "
1634 "the port with WWPN 0x%Lx connected to "
1635 "the adapter %s with the SCSI stack.\n",
1636 unit->fcp_lun,
1637 unit->port->wwpn,
1638 zfcp_get_busid_by_unit(unit));
1639 return;
1640 }
1641
1642 zfcp_unit_get(unit);
1643 memset(p, 0, sizeof(*p));
1644 atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
1645 INIT_WORK(&p->work, zfcp_erp_scsi_scan);
1646 p->unit = unit;
1647 schedule_work(&p->work);
1648}
1649
1594/* 1650/*
1595 * function: 1651 * function:
1596 * 1652 *
@@ -3092,9 +3148,9 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
3092 && port->rport) { 3148 && port->rport) {
3093 atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED, 3149 atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED,
3094 &unit->status); 3150 &unit->status);
3095 scsi_scan_target(&port->rport->dev, 0, 3151 if (atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING,
3096 port->rport->scsi_target_id, 3152 &unit->status) == 0)
3097 unit->scsi_lun, 0); 3153 zfcp_erp_schedule_work(unit);
3098 } 3154 }
3099 zfcp_unit_put(unit); 3155 zfcp_unit_put(unit);
3100 break; 3156 break;
@@ -3121,7 +3177,7 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
3121 zfcp_get_busid_by_port(port), 3177 zfcp_get_busid_by_port(port),
3122 port->wwpn); 3178 port->wwpn);
3123 else { 3179 else {
3124 scsi_flush_work(adapter->scsi_host); 3180 scsi_target_unblock(&port->rport->dev);
3125 port->rport->maxframe_size = port->maxframe_size; 3181 port->rport->maxframe_size = port->maxframe_size;
3126 port->rport->supported_classes = 3182 port->rport->supported_classes =
3127 port->supported_classes; 3183 port->supported_classes;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 99db02062c3b..e742b3de16ac 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -22,6 +22,7 @@
22#define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI 22#define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI
23 23
24#include "zfcp_ext.h" 24#include "zfcp_ext.h"
25#include <asm/atomic.h>
25 26
26static void zfcp_scsi_slave_destroy(struct scsi_device *sdp); 27static void zfcp_scsi_slave_destroy(struct scsi_device *sdp);
27static int zfcp_scsi_slave_alloc(struct scsi_device *sdp); 28static int zfcp_scsi_slave_alloc(struct scsi_device *sdp);
@@ -179,6 +180,10 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
179 struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; 180 struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
180 181
181 if (unit) { 182 if (unit) {
183 zfcp_erp_wait(unit->port->adapter);
184 wait_event(unit->scsi_scan_wq,
185 atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING,
186 &unit->status) == 0);
182 atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); 187 atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
183 sdpnt->hostdata = NULL; 188 sdpnt->hostdata = NULL;
184 unit->device = NULL; 189 unit->device = NULL;