RE: [PATCH 2/2] qla4xxx: Add target reset functionality

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Mike Christie <michaelc@xxxxxxxxxxx> wrote:

> This patch adds target reset functionalty.
> 
> Signed-off-by: Mike Christie <michaelc@xxxxxxxxxxx>
> ---
>  drivers/scsi/qla4xxx/ql4_fw.h   |    1 +
>  drivers/scsi/qla4xxx/ql4_glbl.h |    2 +
>  drivers/scsi/qla4xxx/ql4_mbx.c  |   39 ++++++++++++++++++++
>  drivers/scsi/qla4xxx/ql4_os.c   |   74 
> ++++++++++++++++++++++++++++++++++-----
>  4 files changed, 107 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/scsi/qla4xxx/ql4_fw.h 
> b/drivers/scsi/qla4xxx/ql4_fw.h
> index fe415ec..ed8ee66 100644
> --- a/drivers/scsi/qla4xxx/ql4_fw.h
> +++ b/drivers/scsi/qla4xxx/ql4_fw.h
> @@ -216,6 +216,7 @@ union external_hw_config_reg {
>  #define MBOX_CMD_ABOUT_FW			0x0009
>  #define MBOX_CMD_PING				0x000B
>  #define MBOX_CMD_LUN_RESET			0x0016
> +#define MBOX_CMD_TARGET_WARM_RESET		0x0017
>  #define MBOX_CMD_GET_MANAGEMENT_DATA		0x001E
>  #define MBOX_CMD_GET_FW_STATUS			0x001F
>  #define MBOX_CMD_SET_ISNS_SERVICE		0x0021
> diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h 
> b/drivers/scsi/qla4xxx/ql4_glbl.h
> index a3608e0..b403a17 100644
> --- a/drivers/scsi/qla4xxx/ql4_glbl.h
> +++ b/drivers/scsi/qla4xxx/ql4_glbl.h
> @@ -27,6 +27,8 @@ int qla4xxx_relogin_device(struct 
> scsi_qla_host * ha,
>  			   struct ddb_entry * ddb_entry);
>  int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct 
> ddb_entry * ddb_entry,
>  		      int lun);
> +int qla4xxx_reset_target(struct scsi_qla_host * ha,
> +			 struct ddb_entry * ddb_entry);
>  int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
>  		      uint32_t offset, uint32_t len);
>  int qla4xxx_get_firmware_status(struct scsi_qla_host * ha);
> diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c 
> b/drivers/scsi/qla4xxx/ql4_mbx.c
> index 35cd73c..c577d79 100644
> --- a/drivers/scsi/qla4xxx/ql4_mbx.c
> +++ b/drivers/scsi/qla4xxx/ql4_mbx.c
> @@ -713,6 +713,45 @@ int qla4xxx_reset_lun(struct 
> scsi_qla_host * ha, struct ddb_entry * ddb_entry,
>  	return status;
>  }
>  
> +/**
> + * qla4xxx_reset_target - issues target Reset
> + * @ha: Pointer to host adapter structure.
> + * @db_entry: Pointer to device database entry
> + * @un_entry: Pointer to lun entry structure
> + *
> + * This routine performs a TARGET RESET on the specified target.
> + * The caller must ensure that the ddb_entry pointers
> + * are valid before calling this routine.
> + **/
> +int qla4xxx_reset_target(struct scsi_qla_host *ha,
> +			 struct ddb_entry *ddb_entry)
> +{
> +	uint32_t mbox_cmd[MBOX_REG_COUNT];
> +	uint32_t mbox_sts[MBOX_REG_COUNT];
> +	int status = QLA_SUCCESS;
> +
> +	DEBUG2(printk("scsi%ld:%d: target reset issued\n", ha->host_no,
> +		      ddb_entry->os_target_id));
> +
> +	/*
> +	 * Send target reset command to ISP, so that the ISP 
> will return all
> +	 * outstanding requests with RESET status
> +	 */
> +	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
> +	memset(&mbox_sts, 0, sizeof(mbox_sts));
> +
> +	mbox_cmd[0] = MBOX_CMD_TARGET_WARM_RESET;
> +	mbox_cmd[1] = ddb_entry->fw_ddb_index;
> +	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
> +
> +	qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0],
> +				&mbox_sts[0]);
> +	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
> +	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
> +		status = QLA_ERROR;
> +
> +	return status;
> +}
>  
>  int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
>  		      uint32_t offset, uint32_t len)
> diff --git a/drivers/scsi/qla4xxx/ql4_os.c 
> b/drivers/scsi/qla4xxx/ql4_os.c
> index f55b9f7..05e6991 100644
> --- a/drivers/scsi/qla4xxx/ql4_os.c
> +++ b/drivers/scsi/qla4xxx/ql4_os.c
> @@ -73,6 +73,7 @@ static void 
> qla4xxx_recovery_timedout(struct iscsi_cls_session *session);
>  static int qla4xxx_queuecommand(struct scsi_cmnd *cmd,
>  				void (*done) (struct scsi_cmnd *));
>  static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd);
> +static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd);
>  static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd);
>  static int qla4xxx_slave_alloc(struct scsi_device *device);
>  static int qla4xxx_slave_configure(struct scsi_device *device);
> @@ -85,6 +86,7 @@ static struct scsi_host_template 
> qla4xxx_driver_template = {
>  	.queuecommand		= qla4xxx_queuecommand,
>  
>  	.eh_device_reset_handler = qla4xxx_eh_device_reset,
> +	.eh_target_reset_handler = qla4xxx_eh_target_reset,
>  	.eh_host_reset_handler	= qla4xxx_eh_host_reset,
>  
>  	.slave_configure	= qla4xxx_slave_configure,
> @@ -1506,7 +1508,7 @@ static int 
> qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
>  }
>  
>  /**
> - * qla4xxx_eh_wait_for_active_target_commands - wait for 
> active cmds to finish.
> + * qla4xxx_eh_wait_for_commands - wait for active cmds to finish.
>   * @ha: pointer to to HBA
>   * @t: target id
>   * @l: lun id
> @@ -1514,20 +1516,22 @@ static int 
> qla4xxx_wait_for_hba_online(struct scsi_qla_host *ha)
>   * This function waits for all outstanding commands to a lun 
> to complete. It
>   * returns 0 if all pending commands are returned and 1 otherwise.
>   **/
> -static int qla4xxx_eh_wait_for_active_target_commands(struct 
> scsi_qla_host *ha,
> -						 int t, int l)
> +static int qla4xxx_eh_wait_for_commands(struct scsi_qla_host *ha,
> +					struct scsi_target *stgt,
> +					struct scsi_device *sdev)
>  {
>  	int cnt;
>  	int status = 0;
>  	struct scsi_cmnd *cmd;
>  
>  	/*
> -	 * Waiting for all commands for the designated target 
> in the active
> -	 * array
> +	 * Waiting for all commands for the designated target or dev
> +	 * in the active array
>  	 */
>  	for (cnt = 0; cnt < ha->host->can_queue; cnt++) {
>  		cmd = scsi_host_find_tag(ha->host, cnt);
> -		if (cmd && cmd->device->id == t && 
> cmd->device->lun == l) {
> +		if (cmd && stgt == scsi_target(cmd->device) &&
> +		    (!sdev || sdev == cmd->device)) {
>  			if (!qla4xxx_eh_wait_on_command(ha, cmd)) {
>  				status++;
>  				break;
> @@ -1580,9 +1584,8 @@ static int 
> qla4xxx_eh_device_reset(struct scsi_cmnd *cmd)
>  	 * for the device.
>  	 */
>  	if (cmd->device->host->shost_state == SHOST_RECOVERY) {
> -		if (qla4xxx_eh_wait_for_active_target_commands(ha,
> -							  
> cmd->device->id,
> -							  
> cmd->device->lun)){
> +		if (qla4xxx_eh_wait_for_commands(ha, 
> scsi_target(cmd->device),
> +						 cmd->device)) {
>  			dev_info(&ha->pdev->dev,
>  				   "DEVICE RESET FAILED - waiting for "
>  				   "commands.\n");
> @@ -1603,6 +1606,59 @@ eh_dev_reset_done:
>  }
>  
>  /**
> + * qla4xxx_eh_target_reset - callback for target reset.
> + * @cmd: Pointer to Linux's SCSI command structure
> + *
> + * This routine is called by the Linux OS to reset the target.
> + **/
> +static int qla4xxx_eh_target_reset(struct scsi_cmnd *cmd)
> +{
> +	struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
> +	struct ddb_entry *ddb_entry = cmd->device->hostdata;
> +	int stat;
> +
> +	if (!ddb_entry)
> +		return FAILED;
> +
> +	starget_printk(KERN_INFO, scsi_target(cmd->device),
> +		       "WARM TARGET RESET ISSUED.\n");
> +
> +	DEBUG2(printk(KERN_INFO
> +		      "scsi%ld: TARGET_DEVICE_RESET cmd=%p 
> jiffies = 0x%lx, "
> +		      "to=%x,dpc_flags=%lx, status=%x allowed=%d\n",
> +		      ha->host_no, cmd, jiffies, 
> cmd->timeout_per_command / HZ,
> +		      ha->dpc_flags, cmd->result, cmd->allowed));
> +
> +	stat = qla4xxx_reset_target(ha, ddb_entry);
> +	if (stat != QLA_SUCCESS) {
> +		starget_printk(KERN_INFO, scsi_target(cmd->device),
> +			       "WARM TARGET RESET FAILED.\n");
> +		return FAILED;
> +	}
> +
> +	/* Send marker. */
> +	ha->marker_needed = 1;
> +
> +	/*
> +	 * If we are coming down the EH path, wait for all 
> commands to complete
> +	 * for the target
> +	 */
> +	if (cmd->device->host->shost_state == SHOST_RECOVERY) {
> +		if (qla4xxx_eh_wait_for_commands(ha, 
> scsi_target(cmd->device),
> +						 NULL)) {
> +			starget_printk(KERN_INFO, 
> scsi_target(cmd->device),
> +				       "WARM TARGET DEVICE 
> RESET FAILED - "
> +				       "waiting for commands.\n");
> +			return FAILED;
> +		}
> +	}
> +
> +	starget_printk(KERN_INFO, scsi_target(cmd->device),
> +		       "WARM TARGET RESET SUCCEEDED.\n");
> +	return SUCCESS;
> +}
> +
> +/**
>   * qla4xxx_eh_host_reset - kernel callback
>   * @cmd: Pointer to Linux's SCSI command structure
>   *
> -- 
> 1.5.1.2

Acked-by: David Somayajulu <david.somayajulu@xxxxxxxxxx>
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux