|
@@ -58,6 +58,123 @@ static int beiscsi_slave_configure(struct scsi_device *sdev)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int beiscsi_eh_abort(struct scsi_cmnd *sc)
|
|
|
+{
|
|
|
+ struct iscsi_cls_session *cls_session;
|
|
|
+ struct iscsi_task *aborted_task = (struct iscsi_task *)sc->SCp.ptr;
|
|
|
+ struct beiscsi_io_task *aborted_io_task;
|
|
|
+ struct iscsi_conn *conn;
|
|
|
+ struct beiscsi_conn *beiscsi_conn;
|
|
|
+ struct beiscsi_hba *phba;
|
|
|
+ struct iscsi_session *session;
|
|
|
+ struct invalidate_command_table *inv_tbl;
|
|
|
+ unsigned int cid, tag, num_invalidate;
|
|
|
+
|
|
|
+ cls_session = starget_to_session(scsi_target(sc->device));
|
|
|
+ session = cls_session->dd_data;
|
|
|
+
|
|
|
+ spin_lock_bh(&session->lock);
|
|
|
+ if (!aborted_task || !aborted_task->sc) {
|
|
|
+ /* we raced */
|
|
|
+ spin_unlock_bh(&session->lock);
|
|
|
+ return SUCCESS;
|
|
|
+ }
|
|
|
+
|
|
|
+ aborted_io_task = aborted_task->dd_data;
|
|
|
+ if (!aborted_io_task->scsi_cmnd) {
|
|
|
+ /* raced or invalid command */
|
|
|
+ spin_unlock_bh(&session->lock);
|
|
|
+ return SUCCESS;
|
|
|
+ }
|
|
|
+ spin_unlock_bh(&session->lock);
|
|
|
+ conn = aborted_task->conn;
|
|
|
+ beiscsi_conn = conn->dd_data;
|
|
|
+ phba = beiscsi_conn->phba;
|
|
|
+
|
|
|
+ /* invalidate iocb */
|
|
|
+ cid = beiscsi_conn->beiscsi_conn_cid;
|
|
|
+ inv_tbl = phba->inv_tbl;
|
|
|
+ memset(inv_tbl, 0x0, sizeof(*inv_tbl));
|
|
|
+ inv_tbl->cid = cid;
|
|
|
+ inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index;
|
|
|
+ num_invalidate = 1;
|
|
|
+ tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid);
|
|
|
+ if (!tag) {
|
|
|
+ shost_printk(KERN_WARNING, phba->shost,
|
|
|
+ "mgmt_invalidate_icds could not be"
|
|
|
+ " submitted\n");
|
|
|
+ return FAILED;
|
|
|
+ } else {
|
|
|
+ wait_event_interruptible(phba->ctrl.mcc_wait[tag],
|
|
|
+ phba->ctrl.mcc_numtag[tag]);
|
|
|
+ free_mcc_tag(&phba->ctrl, tag);
|
|
|
+ }
|
|
|
+
|
|
|
+ return iscsi_eh_abort(sc);
|
|
|
+}
|
|
|
+
|
|
|
+static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)
|
|
|
+{
|
|
|
+ struct iscsi_task *abrt_task;
|
|
|
+ struct beiscsi_io_task *abrt_io_task;
|
|
|
+ struct iscsi_conn *conn;
|
|
|
+ struct beiscsi_conn *beiscsi_conn;
|
|
|
+ struct beiscsi_hba *phba;
|
|
|
+ struct iscsi_session *session;
|
|
|
+ struct iscsi_cls_session *cls_session;
|
|
|
+ struct invalidate_command_table *inv_tbl;
|
|
|
+ unsigned int cid, tag, i, num_invalidate;
|
|
|
+ int rc = FAILED;
|
|
|
+
|
|
|
+ /* invalidate iocbs */
|
|
|
+ cls_session = starget_to_session(scsi_target(sc->device));
|
|
|
+ session = cls_session->dd_data;
|
|
|
+ spin_lock_bh(&session->lock);
|
|
|
+ if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN)
|
|
|
+ goto unlock;
|
|
|
+
|
|
|
+ conn = session->leadconn;
|
|
|
+ beiscsi_conn = conn->dd_data;
|
|
|
+ phba = beiscsi_conn->phba;
|
|
|
+ cid = beiscsi_conn->beiscsi_conn_cid;
|
|
|
+ inv_tbl = phba->inv_tbl;
|
|
|
+ memset(inv_tbl, 0x0, sizeof(*inv_tbl) * BE2_CMDS_PER_CXN);
|
|
|
+ num_invalidate = 0;
|
|
|
+ for (i = 0; i < conn->session->cmds_max; i++) {
|
|
|
+ abrt_task = conn->session->cmds[i];
|
|
|
+ abrt_io_task = abrt_task->dd_data;
|
|
|
+ if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (abrt_task->sc->device->lun != abrt_task->sc->device->lun)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ inv_tbl->cid = cid;
|
|
|
+ inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index;
|
|
|
+ num_invalidate++;
|
|
|
+ inv_tbl++;
|
|
|
+ }
|
|
|
+ spin_unlock_bh(&session->lock);
|
|
|
+ inv_tbl = phba->inv_tbl;
|
|
|
+
|
|
|
+ tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid);
|
|
|
+ if (!tag) {
|
|
|
+ shost_printk(KERN_WARNING, phba->shost,
|
|
|
+ "mgmt_invalidate_icds could not be"
|
|
|
+ " submitted\n");
|
|
|
+ return FAILED;
|
|
|
+ } else {
|
|
|
+ wait_event_interruptible(phba->ctrl.mcc_wait[tag],
|
|
|
+ phba->ctrl.mcc_numtag[tag]);
|
|
|
+ free_mcc_tag(&phba->ctrl, tag);
|
|
|
+ }
|
|
|
+
|
|
|
+ return iscsi_eh_device_reset(sc);
|
|
|
+unlock:
|
|
|
+ spin_unlock_bh(&session->lock);
|
|
|
+ return rc;
|
|
|
+}
|
|
|
+
|
|
|
/*------------------- PCI Driver operations and data ----------------- */
|
|
|
static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {
|
|
|
{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) },
|
|
@@ -74,11 +191,11 @@ static struct scsi_host_template beiscsi_sht = {
|
|
|
.name = "ServerEngines 10Gbe open-iscsi Initiator Driver",
|
|
|
.proc_name = DRV_NAME,
|
|
|
.queuecommand = iscsi_queuecommand,
|
|
|
- .eh_abort_handler = iscsi_eh_abort,
|
|
|
.change_queue_depth = iscsi_change_queue_depth,
|
|
|
.slave_configure = beiscsi_slave_configure,
|
|
|
.target_alloc = iscsi_target_alloc,
|
|
|
- .eh_device_reset_handler = iscsi_eh_device_reset,
|
|
|
+ .eh_abort_handler = beiscsi_eh_abort,
|
|
|
+ .eh_device_reset_handler = beiscsi_eh_device_reset,
|
|
|
.eh_target_reset_handler = iscsi_eh_session_reset,
|
|
|
.sg_tablesize = BEISCSI_SGLIST_ELEMENTS,
|
|
|
.can_queue = BE2_IO_DEPTH,
|
|
@@ -3486,9 +3603,9 @@ static int beiscsi_mtask(struct iscsi_task *task)
|
|
|
struct hwi_wrb_context *pwrb_context;
|
|
|
struct wrb_handle *pwrb_handle;
|
|
|
unsigned int doorbell = 0;
|
|
|
- unsigned int i, cid;
|
|
|
+ struct invalidate_command_table *inv_tbl;
|
|
|
struct iscsi_task *aborted_task;
|
|
|
- unsigned int tag;
|
|
|
+ unsigned int i, cid, tag, num_invalidate;
|
|
|
|
|
|
cid = beiscsi_conn->beiscsi_conn_cid;
|
|
|
pwrb = io_task->pwrb_handle->pwrb;
|
|
@@ -3538,9 +3655,12 @@ static int beiscsi_mtask(struct iscsi_task *task)
|
|
|
if (!aborted_io_task->scsi_cmnd)
|
|
|
return 0;
|
|
|
|
|
|
- tag = mgmt_invalidate_icds(phba,
|
|
|
- aborted_io_task->psgl_handle->sgl_index,
|
|
|
- cid);
|
|
|
+ inv_tbl = phba->inv_tbl;
|
|
|
+ memset(inv_tbl, 0x0, sizeof(*inv_tbl));
|
|
|
+ inv_tbl->cid = cid;
|
|
|
+ inv_tbl->icd = aborted_io_task->psgl_handle->sgl_index;
|
|
|
+ num_invalidate = 1;
|
|
|
+ tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate, cid);
|
|
|
if (!tag) {
|
|
|
shost_printk(KERN_WARNING, phba->shost,
|
|
|
"mgmt_invalidate_icds could not be"
|