#define ZFCP_STATUS_UNIT_SHARED 0x00000004
#define ZFCP_STATUS_UNIT_READONLY 0x00000008
#define ZFCP_STATUS_UNIT_REGISTERED 0x00000010
+#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020
/* FSF request status (this does not have a common part) */
#define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000
struct scsi_device *device; /* scsi device struct pointer */
struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter;
+ wait_queue_head_t scsi_scan_wq; /* can be used to wait until
+ all scsi_scan_target
+ requests have been
+ completed. */
};
/* FSF request */
return result;
}
+struct zfcp_erp_add_work {
+ struct zfcp_unit *unit;
+ struct work_struct work;
+};
+
+/**
+ * zfcp_erp_scsi_scan
+ * @data: pointer to a struct zfcp_erp_add_work
+ *
+ * Registers a logical unit with the SCSI stack.
+ */
+static void zfcp_erp_scsi_scan(struct work_struct *work)
+{
+ struct zfcp_erp_add_work *p =
+ container_of(work, struct zfcp_erp_add_work, work);
+ struct zfcp_unit *unit = p->unit;
+ struct fc_rport *rport = unit->port->rport;
+ scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
+ unit->scsi_lun, 0);
+ atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
+ wake_up(&unit->scsi_scan_wq);
+ zfcp_unit_put(unit);
+ kfree(p);
+}
+
+/**
+ * zfcp_erp_schedule_work
+ * @unit: pointer to unit which should be registered with SCSI stack
+ *
+ * Schedules work which registers a unit with the SCSI stack
+ */
+static void
+zfcp_erp_schedule_work(struct zfcp_unit *unit)
+{
+ struct zfcp_erp_add_work *p;
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p) {
+ ZFCP_LOG_NORMAL("error: Out of resources. Could not register "
+ "the FCP-LUN 0x%Lx connected to "
+ "the port with WWPN 0x%Lx connected to "
+ "the adapter %s with the SCSI stack.\n",
+ unit->fcp_lun,
+ unit->port->wwpn,
+ zfcp_get_busid_by_unit(unit));
+ return;
+ }
+
+ zfcp_unit_get(unit);
+ memset(p, 0, sizeof(*p));
+ atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
+ INIT_WORK(&p->work, zfcp_erp_scsi_scan);
+ p->unit = unit;
+ schedule_work(&p->work);
+}
+
/*
* function:
*
&& port->rport) {
atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED,
&unit->status);
- scsi_scan_target(&port->rport->dev, 0,
- port->rport->scsi_target_id,
- unit->scsi_lun, 0);
+ if (atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING,
+ &unit->status) == 0)
+ zfcp_erp_schedule_work(unit);
}
zfcp_unit_put(unit);
break;
zfcp_get_busid_by_port(port),
port->wwpn);
else {
- scsi_flush_work(adapter->scsi_host);
+ scsi_target_unblock(&port->rport->dev);
port->rport->maxframe_size = port->maxframe_size;
port->rport->supported_classes =
port->supported_classes;
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI
#include "zfcp_ext.h"
+#include <asm/atomic.h>
static void zfcp_scsi_slave_destroy(struct scsi_device *sdp);
static int zfcp_scsi_slave_alloc(struct scsi_device *sdp);
struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
if (unit) {
+ zfcp_erp_wait(unit->port->adapter);
+ wait_event(unit->scsi_scan_wq,
+ atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING,
+ &unit->status) == 0);
atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
sdpnt->hostdata = NULL;
unit->device = NULL;