list_del(&evt_struct->list);
del_timer(&evt_struct->timer);
+ /* If send_crq returns H_CLOSED, return SCSI_MLQUEUE_HOST_BUSY.
+ * Firmware will send a CRQ with a transport event (0xFF) to
+ * tell this client what has happened to the transport. This
+ * will be handled in ibmvscsi_handle_crq()
+ */
+ if (rc == H_CLOSED) {
+ dev_warn(hostdata->dev, "send warning. "
+ "Receive queue closed, will retry.\n");
+ goto send_busy;
+ }
dev_err(hostdata->dev, "send error %d\n", rc);
atomic_inc(&hostdata->request_limit);
goto send_error;
}
if (cmnd) {
- cmnd->result = rsp->status;
+ cmnd->result |= rsp->status;
if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION)
memcpy(cmnd->sense_buffer,
rsp->data,
u16 lun = lun_from_dev(cmnd->device);
u8 out_fmt, in_fmt;
+ cmnd->result = (DID_OK << 16);
evt_struct = get_event_struct(&hostdata->pool);
if (!evt_struct)
return SCSI_MLQUEUE_HOST_BUSY;
srp_cmd = &evt_struct->iu.srp.cmd;
memset(srp_cmd, 0x00, SRP_MAX_IU_LEN);
srp_cmd->opcode = SRP_CMD;
- memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
+ memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(srp_cmd->cdb));
srp_cmd->lun = ((u64) lun) << 48;
if (!map_data_for_srp_cmd(cmnd, evt_struct, srp_cmd, hostdata->dev)) {
int rsp_rc;
unsigned long flags;
u16 lun = lun_from_dev(cmd->device);
+ unsigned long wait_switch = 0;
/* First, find this command in our sent list so we can figure
* out the correct tag
*/
spin_lock_irqsave(hostdata->host->host_lock, flags);
- found_evt = NULL;
- list_for_each_entry(tmp_evt, &hostdata->sent, list) {
- if (tmp_evt->cmnd == cmd) {
- found_evt = tmp_evt;
- break;
+ wait_switch = jiffies + (init_timeout * HZ);
+ do {
+ found_evt = NULL;
+ list_for_each_entry(tmp_evt, &hostdata->sent, list) {
+ if (tmp_evt->cmnd == cmd) {
+ found_evt = tmp_evt;
+ break;
+ }
}
- }
- if (!found_evt) {
- spin_unlock_irqrestore(hostdata->host->host_lock, flags);
- return SUCCESS;
- }
+ if (!found_evt) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ return SUCCESS;
+ }
- evt = get_event_struct(&hostdata->pool);
- if (evt == NULL) {
- spin_unlock_irqrestore(hostdata->host->host_lock, flags);
- sdev_printk(KERN_ERR, cmd->device, "failed to allocate abort event\n");
- return FAILED;
- }
+ evt = get_event_struct(&hostdata->pool);
+ if (evt == NULL) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ sdev_printk(KERN_ERR, cmd->device,
+ "failed to allocate abort event\n");
+ return FAILED;
+ }
- init_event_struct(evt,
- sync_completion,
- VIOSRP_SRP_FORMAT,
- init_timeout);
+ init_event_struct(evt,
+ sync_completion,
+ VIOSRP_SRP_FORMAT,
+ init_timeout);
- tsk_mgmt = &evt->iu.srp.tsk_mgmt;
+ tsk_mgmt = &evt->iu.srp.tsk_mgmt;
- /* Set up an abort SRP command */
- memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
- tsk_mgmt->opcode = SRP_TSK_MGMT;
- tsk_mgmt->lun = ((u64) lun) << 48;
- tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK;
- tsk_mgmt->task_tag = (u64) found_evt;
-
- sdev_printk(KERN_INFO, cmd->device, "aborting command. lun 0x%lx, tag 0x%lx\n",
- tsk_mgmt->lun, tsk_mgmt->task_tag);
-
- evt->sync_srp = &srp_rsp;
- init_completion(&evt->comp);
- rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
+ /* Set up an abort SRP command */
+ memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
+ tsk_mgmt->opcode = SRP_TSK_MGMT;
+ tsk_mgmt->lun = ((u64) lun) << 48;
+ tsk_mgmt->tsk_mgmt_func = SRP_TSK_ABORT_TASK;
+ tsk_mgmt->task_tag = (u64) found_evt;
+
+ evt->sync_srp = &srp_rsp;
+
+ init_completion(&evt->comp);
+ rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
+
+ if (rsp_rc != SCSI_MLQUEUE_HOST_BUSY)
+ break;
+
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ msleep(10);
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
+ } while (time_before(jiffies, wait_switch));
+
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+
if (rsp_rc != 0) {
sdev_printk(KERN_ERR, cmd->device,
"failed to send abort() event. rc=%d\n", rsp_rc);
return FAILED;
}
+ sdev_printk(KERN_INFO, cmd->device,
+ "aborting command. lun 0x%lx, tag 0x%lx\n",
+ (((u64) lun) << 48), (u64) found_evt);
+
wait_for_completion(&evt->comp);
/* make sure we got a good response */
int rsp_rc;
unsigned long flags;
u16 lun = lun_from_dev(cmd->device);
+ unsigned long wait_switch = 0;
spin_lock_irqsave(hostdata->host->host_lock, flags);
- evt = get_event_struct(&hostdata->pool);
- if (evt == NULL) {
- spin_unlock_irqrestore(hostdata->host->host_lock, flags);
- sdev_printk(KERN_ERR, cmd->device, "failed to allocate reset event\n");
- return FAILED;
- }
+ wait_switch = jiffies + (init_timeout * HZ);
+ do {
+ evt = get_event_struct(&hostdata->pool);
+ if (evt == NULL) {
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ sdev_printk(KERN_ERR, cmd->device,
+ "failed to allocate reset event\n");
+ return FAILED;
+ }
- init_event_struct(evt,
- sync_completion,
- VIOSRP_SRP_FORMAT,
- init_timeout);
+ init_event_struct(evt,
+ sync_completion,
+ VIOSRP_SRP_FORMAT,
+ init_timeout);
- tsk_mgmt = &evt->iu.srp.tsk_mgmt;
+ tsk_mgmt = &evt->iu.srp.tsk_mgmt;
- /* Set up a lun reset SRP command */
- memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
- tsk_mgmt->opcode = SRP_TSK_MGMT;
- tsk_mgmt->lun = ((u64) lun) << 48;
- tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET;
+ /* Set up a lun reset SRP command */
+ memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
+ tsk_mgmt->opcode = SRP_TSK_MGMT;
+ tsk_mgmt->lun = ((u64) lun) << 48;
+ tsk_mgmt->tsk_mgmt_func = SRP_TSK_LUN_RESET;
- sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%lx\n",
- tsk_mgmt->lun);
+ evt->sync_srp = &srp_rsp;
+
+ init_completion(&evt->comp);
+ rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
+
+ if (rsp_rc != SCSI_MLQUEUE_HOST_BUSY)
+ break;
+
+ spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+ msleep(10);
+ spin_lock_irqsave(hostdata->host->host_lock, flags);
+ } while (time_before(jiffies, wait_switch));
- evt->sync_srp = &srp_rsp;
- init_completion(&evt->comp);
- rsp_rc = ibmvscsi_send_srp_event(evt, hostdata, init_timeout * 2);
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+
if (rsp_rc != 0) {
sdev_printk(KERN_ERR, cmd->device,
"failed to send reset event. rc=%d\n", rsp_rc);
return FAILED;
}
+ sdev_printk(KERN_INFO, cmd->device, "resetting device. lun 0x%lx\n",
+ (((u64) lun) << 48));
+
wait_for_completion(&evt->comp);
/* make sure we got a good response */
del_timer(&evt_struct->timer);
+ if (crq->status != VIOSRP_OK && evt_struct->cmnd)
+ evt_struct->cmnd->result = DID_ERROR << 16;
if (evt_struct->done)
evt_struct->done(evt_struct);
else
unsigned long lock_flags = 0;
spin_lock_irqsave(shost->host_lock, lock_flags);
- if (sdev->type == TYPE_DISK)
+ if (sdev->type == TYPE_DISK) {
sdev->allow_restart = 1;
+ sdev->timeout = 60 * HZ;
+ }
scsi_adjust_queue_depth(sdev, 0, shost->cmd_per_lun);
spin_unlock_irqrestore(shost->host_lock, lock_flags);
return 0;
/* ------------------------------------------------------------
* sysfs attributes
*/
-static ssize_t show_host_srp_version(struct class_device *class_dev, char *buf)
+static ssize_t show_host_srp_version(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ibmvscsi_host_data *hostdata = shost_priv(shost);
int len;
return len;
}
-static struct class_device_attribute ibmvscsi_host_srp_version = {
+static struct device_attribute ibmvscsi_host_srp_version = {
.attr = {
.name = "srp_version",
.mode = S_IRUGO,
.show = show_host_srp_version,
};
-static ssize_t show_host_partition_name(struct class_device *class_dev,
+static ssize_t show_host_partition_name(struct device *dev,
+ struct device_attribute *attr,
char *buf)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ibmvscsi_host_data *hostdata = shost_priv(shost);
int len;
return len;
}
-static struct class_device_attribute ibmvscsi_host_partition_name = {
+static struct device_attribute ibmvscsi_host_partition_name = {
.attr = {
.name = "partition_name",
.mode = S_IRUGO,
.show = show_host_partition_name,
};
-static ssize_t show_host_partition_number(struct class_device *class_dev,
+static ssize_t show_host_partition_number(struct device *dev,
+ struct device_attribute *attr,
char *buf)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ibmvscsi_host_data *hostdata = shost_priv(shost);
int len;
return len;
}
-static struct class_device_attribute ibmvscsi_host_partition_number = {
+static struct device_attribute ibmvscsi_host_partition_number = {
.attr = {
.name = "partition_number",
.mode = S_IRUGO,
.show = show_host_partition_number,
};
-static ssize_t show_host_mad_version(struct class_device *class_dev, char *buf)
+static ssize_t show_host_mad_version(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ibmvscsi_host_data *hostdata = shost_priv(shost);
int len;
return len;
}
-static struct class_device_attribute ibmvscsi_host_mad_version = {
+static struct device_attribute ibmvscsi_host_mad_version = {
.attr = {
.name = "mad_version",
.mode = S_IRUGO,
.show = show_host_mad_version,
};
-static ssize_t show_host_os_type(struct class_device *class_dev, char *buf)
+static ssize_t show_host_os_type(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ibmvscsi_host_data *hostdata = shost_priv(shost);
int len;
return len;
}
-static struct class_device_attribute ibmvscsi_host_os_type = {
+static struct device_attribute ibmvscsi_host_os_type = {
.attr = {
.name = "os_type",
.mode = S_IRUGO,
.show = show_host_os_type,
};
-static ssize_t show_host_config(struct class_device *class_dev, char *buf)
+static ssize_t show_host_config(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ibmvscsi_host_data *hostdata = shost_priv(shost);
/* returns null-terminated host config data */
return 0;
}
-static struct class_device_attribute ibmvscsi_host_config = {
+static struct device_attribute ibmvscsi_host_config = {
.attr = {
.name = "config",
.mode = S_IRUGO,
.show = show_host_config,
};
-static struct class_device_attribute *ibmvscsi_attrs[] = {
+static struct device_attribute *ibmvscsi_attrs[] = {
&ibmvscsi_host_srp_version,
&ibmvscsi_host_partition_name,
&ibmvscsi_host_partition_number,
.this_id = -1,
.sg_tablesize = SG_ALL,
.use_clustering = ENABLE_CLUSTERING,
- .use_sg_chaining = ENABLE_SG_CHAINING,
.shost_attrs = ibmvscsi_attrs,
};