extern int scsi_internal_device_block(struct scsi_device *sdev);
extern u8 mpt2sas_stm_zero_smid_handler(struct MPT2SAS_ADAPTER *ioc,
u8 msix_index, u32 reply);
-extern int scsi_internal_device_unblock(struct scsi_device *sdev);
+extern int scsi_internal_device_unblock(struct scsi_device *sdev,
+ enum scsi_device_state new_state);
#endif /* MPT2SAS_BASE_H_INCLUDED */
dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, "device_running, "
"handle(0x%04x)\n",
sas_device_priv_data->sas_target->handle));
- scsi_internal_device_unblock(sdev);
+ scsi_internal_device_unblock(sdev, SDEV_RUNNING);
}
}
/**
"sas address(0x%016llx)\n", ioc->name,
(unsigned long long)sas_address));
sas_device_priv_data->block = 0;
- scsi_internal_device_unblock(sdev);
+ scsi_internal_device_unblock(sdev, SDEV_RUNNING);
}
}
}
/**
* scsi_internal_device_unblock - resume a device after a block request
* @sdev: device to resume
+ * @new_state: state to set devices to after unblocking
*
* Called by scsi lld's or the midlayer to restart the device queue
* for the previously suspended scsi device. Called from interrupt or
*
* Notes:
* This routine transitions the device to the SDEV_RUNNING state
- * (which must be a legal transition) allowing the midlayer to
- * goose the queue for this device. This routine assumes the
- * host_lock is held upon entry.
+ * or to one of the offline states (which must be a legal transition)
+ * allowing the midlayer to goose the queue for this device. This
+ * routine assumes the host_lock is held upon entry.
*/
int
-scsi_internal_device_unblock(struct scsi_device *sdev)
+scsi_internal_device_unblock(struct scsi_device *sdev,
+ enum scsi_device_state new_state)
{
struct request_queue *q = sdev->request_queue;
unsigned long flags;
-
- /*
- * Try to transition the scsi device to SDEV_RUNNING
- * and goose the device queue if successful.
+
+ /*
+ * Try to transition the scsi device to SDEV_RUNNING or one of the
+ * offlined states and goose the device queue if successful.
*/
if (sdev->sdev_state == SDEV_BLOCK)
- sdev->sdev_state = SDEV_RUNNING;
- else if (sdev->sdev_state == SDEV_CREATED_BLOCK)
- sdev->sdev_state = SDEV_CREATED;
- else if (sdev->sdev_state != SDEV_CANCEL &&
+ sdev->sdev_state = new_state;
+ else if (sdev->sdev_state == SDEV_CREATED_BLOCK) {
+ if (new_state == SDEV_TRANSPORT_OFFLINE ||
+ new_state == SDEV_OFFLINE)
+ sdev->sdev_state = new_state;
+ else
+ sdev->sdev_state = SDEV_CREATED;
+ } else if (sdev->sdev_state != SDEV_CANCEL &&
sdev->sdev_state != SDEV_OFFLINE)
return -EINVAL;
static void
device_unblock(struct scsi_device *sdev, void *data)
{
- scsi_internal_device_unblock(sdev);
+ scsi_internal_device_unblock(sdev, *(enum scsi_device_state *)data);
}
static int
target_unblock(struct device *dev, void *data)
{
if (scsi_is_target_device(dev))
- starget_for_each_device(to_scsi_target(dev), NULL,
+ starget_for_each_device(to_scsi_target(dev), data,
device_unblock);
return 0;
}
void
-scsi_target_unblock(struct device *dev)
+scsi_target_unblock(struct device *dev, enum scsi_device_state new_state)
{
if (scsi_is_target_device(dev))
- starget_for_each_device(to_scsi_target(dev), NULL,
+ starget_for_each_device(to_scsi_target(dev), &new_state,
device_unblock);
else
- device_for_each_child(dev, NULL, target_unblock);
+ device_for_each_child(dev, &new_state, target_unblock);
}
EXPORT_SYMBOL_GPL(scsi_target_unblock);
#define _SCSI_PRIV_H
#include <linux/device.h>
+#include <scsi/scsi_device.h>
struct request_queue;
struct request;
#define SCSI_DEVICE_BLOCK_MAX_TIMEOUT 600 /* units in seconds */
extern int scsi_internal_device_block(struct scsi_device *sdev);
-extern int scsi_internal_device_unblock(struct scsi_device *sdev);
+extern int scsi_internal_device_unblock(struct scsi_device *sdev,
+ enum scsi_device_state new_state);
#endif /* _SCSI_PRIV_H */
i->f->terminate_rport_io(rport);
/*
- * must unblock to flush queued IO. The caller will have set
- * the port_state or flags, so that fc_remote_port_chkready will
- * fail IO.
+ * Must unblock to flush queued IO. scsi-ml will fail incoming reqs.
*/
- scsi_target_unblock(&rport->dev);
+ scsi_target_unblock(&rport->dev, SDEV_TRANSPORT_OFFLINE);
}
/**
/* if target, initiate a scan */
if (rport->scsi_target_id != -1) {
- scsi_target_unblock(&rport->dev);
-
+ scsi_target_unblock(&rport->dev,
+ SDEV_RUNNING);
spin_lock_irqsave(shost->host_lock,
flags);
rport->flags |= FC_RPORT_SCAN_PENDING;
spin_unlock_irqrestore(shost->host_lock, flags);
if (ids->roles & FC_PORT_ROLE_FCP_TARGET) {
- scsi_target_unblock(&rport->dev);
+ scsi_target_unblock(&rport->dev, SDEV_RUNNING);
/* initiate a scan of the target */
spin_lock_irqsave(shost->host_lock, flags);
/* ensure any stgt delete functions are done */
fc_flush_work(shost);
- scsi_target_unblock(&rport->dev);
+ scsi_target_unblock(&rport->dev, SDEV_RUNNING);
/* initiate a scan of the target */
spin_lock_irqsave(shost->host_lock, flags);
rport->flags |= FC_RPORT_SCAN_PENDING;
"blocked FC remote port time out: no longer"
" a FCP target, removing starget\n");
spin_unlock_irqrestore(shost->host_lock, flags);
- scsi_target_unblock(&rport->dev);
+ scsi_target_unblock(&rport->dev, SDEV_TRANSPORT_OFFLINE);
fc_queue_work(shost, &rport->stgt_delete_work);
return;
}
session->transport->session_recovery_timedout(session);
ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n");
- scsi_target_unblock(&session->dev);
+ scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n");
}
session->state = ISCSI_SESSION_LOGGED_IN;
spin_unlock_irqrestore(&session->lock, flags);
/* start IO */
- scsi_target_unblock(&session->dev);
+ scsi_target_unblock(&session->dev, SDEV_RUNNING);
/*
* Only do kernel scanning if the driver is properly hooked into
* the async scanning code (drivers like iscsi_tcp do login and
session->state = ISCSI_SESSION_FREE;
spin_unlock_irqrestore(&session->lock, flags);
- scsi_target_unblock(&session->dev);
+ scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
/* flush running scans then delete devices */
scsi_flush_work(shost);
__iscsi_unbind_session(&session->unbind_work);
unsigned int id, unsigned int lun, int rescan);
extern void scsi_target_reap(struct scsi_target *);
extern void scsi_target_block(struct device *);
-extern void scsi_target_unblock(struct device *);
+extern void scsi_target_unblock(struct device *, enum scsi_device_state);
extern void scsi_remove_target(struct device *);
extern void int_to_scsilun(unsigned int, struct scsi_lun *);
extern int scsilun_to_int(struct scsi_lun *);