コード例 #1
0
static int clariion_activate(struct scsi_device *sdev)
{
	struct clariion_dh_data *csdev = get_clariion_data(sdev);
	int result;

	result = clariion_send_inquiry(sdev, csdev);
	if (result != SCSI_DH_OK)
		goto done;

	if (csdev->lun_state == CLARIION_LUN_OWNED)
		goto done;

	result = send_trespass_cmd(sdev, csdev);
	if (result != SCSI_DH_OK)
		goto done;
	sdev_printk(KERN_INFO, sdev,"%s: %s trespass command sent\n",
		    CLARIION_NAME,
		    csdev->flags&CLARIION_SHORT_TRESPASS?"short":"long" );

	/* Update status */
	result = clariion_send_inquiry(sdev, csdev);
	if (result != SCSI_DH_OK)
		goto done;

done:
	sdev_printk(KERN_INFO, sdev,
		    "%s: at SP %c Port %d (%s, default SP %c)\n",
		    CLARIION_NAME, csdev->current_sp + 'A',
		    csdev->port, lun_state[csdev->lun_state],
		    csdev->default_sp + 'A');

	return result;
}
コード例 #2
0
static int clariion_prep_fn(struct scsi_device *sdev, struct request *req)
{
	struct clariion_dh_data *h = get_clariion_data(sdev);
	int ret = BLKPREP_OK;

	if (h->lun_state != CLARIION_LUN_OWNED) {
		ret = BLKPREP_KILL;
		req->cmd_flags |= REQ_QUIET;
	}
	return ret;

}
コード例 #3
0
ファイル: scsi_dh_emc.c プロジェクト: maraz/linux-2.6
static int parse_sp_info_reply(struct scsi_device *sdev, int result,
		int *default_sp, int *current_sp, int *new_current_sp)
{
	int err = SCSI_DH_OK;
	struct clariion_dh_data *csdev = get_clariion_data(sdev);

	if (result == 0) {
		/* check for in-progress ucode upgrade (NDU) */
		if (csdev->buffer[48] != 0) {
			sdev_printk(KERN_NOTICE, sdev, "Detected in-progress "
			       "ucode upgrade NDU operation while finding "
			       "current active SP.");
			err = SCSI_DH_DEV_TEMP_BUSY;
		} else {
			*default_sp = csdev->buffer[5];

			if (csdev->buffer[4] == 2)
				/* SP for path is current */
				*current_sp = csdev->buffer[8];
			else {
				if (csdev->buffer[4] == 1)
					/* SP for this path is NOT current */
					if (csdev->buffer[8] == 0)
						*current_sp = 1;
					else
						*current_sp = 0;
				else
					/* unbound LU or LUNZ */
					*current_sp = CLARIION_UNBOUND_LU;
			}
			*new_current_sp =  csdev->buffer[8];
		}
	} else {
		struct scsi_sense_hdr sshdr;

		err = SCSI_DH_IO;

		if (scsi_normalize_sense(csdev->sense, SCSI_SENSE_BUFFERSIZE,
							   &sshdr))
			sdev_printk(KERN_ERR, sdev, "Found valid sense data "
			      "0x%2x, 0x%2x, 0x%2x while finding current "
			      "active SP.", sshdr.sense_key, sshdr.asc,
			      sshdr.ascq);
		else
			sdev_printk(KERN_ERR, sdev, "Error 0x%x finding "
			      "current active SP.", result);
	}

	return err;
}
コード例 #4
0
/*
 * params - parameters in the following format
 *      "no_of_params\0param1\0param2\0param3\0...\0"
 *      for example, string for 2 parameters with value 10 and 21
 *      is specified as "2\010\021\0".
 */
static int clariion_set_params(struct scsi_device *sdev, const char *params)
{
	struct clariion_dh_data *csdev = get_clariion_data(sdev);
	unsigned int hr = 0, st = 0, argc;
	const char *p = params;
	int result = SCSI_DH_OK;

	if ((sscanf(params, "%u", &argc) != 1) || (argc != 2))
		return -EINVAL;

	while (*p++)
		;
	if ((sscanf(p, "%u", &st) != 1) || (st > 1))
		return -EINVAL;

	while (*p++)
		;
	if ((sscanf(p, "%u", &hr) != 1) || (hr > 1))
		return -EINVAL;

	if (st)
		csdev->flags |= CLARIION_SHORT_TRESPASS;
	else
		csdev->flags &= ~CLARIION_SHORT_TRESPASS;

	if (hr)
		csdev->flags |= CLARIION_HONOR_RESERVATIONS;
	else
		csdev->flags &= ~CLARIION_HONOR_RESERVATIONS;

	/*
	 * If this path is owned, we have to send a trespass command
	 * with the new parameters. If not, simply return. Next trespass
	 * command would use the parameters.
	 */
	if (csdev->lun_state != CLARIION_LUN_OWNED)
		goto done;

	csdev->lun_state = CLARIION_LUN_UNINITIALIZED;
	result = send_trespass_cmd(sdev, csdev);
	if (result != SCSI_DH_OK)
		goto done;

	/* Update status */
	result = clariion_send_inquiry(sdev, csdev);

done:
	return result;
}
コード例 #5
0
ファイル: scsi_dh_emc.c プロジェクト: maraz/linux-2.6
/*
 * Parse MODE_SELECT cmd reply.
 */
static int trespass_endio(struct scsi_device *sdev, int result)
{
	int err = SCSI_DH_OK;
	struct scsi_sense_hdr sshdr;
	struct clariion_dh_data *csdev = get_clariion_data(sdev);
	char *sense = csdev->sense;

	if (status_byte(result) == CHECK_CONDITION &&
	    scsi_normalize_sense(sense, SCSI_SENSE_BUFFERSIZE, &sshdr)) {
		sdev_printk(KERN_ERR, sdev, "Found valid sense data 0x%2x, "
			    "0x%2x, 0x%2x while sending CLARiiON trespass "
			    "command.\n", sshdr.sense_key, sshdr.asc,
			     sshdr.ascq);

		if ((sshdr.sense_key == 0x05) && (sshdr.asc == 0x04) &&
		     (sshdr.ascq == 0x00)) {
			/*
			 * Array based copy in progress -- do not send
			 * mode_select or copy will be aborted mid-stream.
			 */
			sdev_printk(KERN_INFO, sdev, "Array Based Copy in "
				    "progress while sending CLARiiON trespass "
				    "command.\n");
			err = SCSI_DH_DEV_TEMP_BUSY;
		} else if ((sshdr.sense_key == 0x02) && (sshdr.asc == 0x04) &&
			    (sshdr.ascq == 0x03)) {
			/*
			 * LUN Not Ready - Manual Intervention Required
			 * indicates in-progress ucode upgrade (NDU).
			 */
			sdev_printk(KERN_INFO, sdev, "Detected in-progress "
				    "ucode upgrade NDU operation while sending "
				    "CLARiiON trespass command.\n");
			err = SCSI_DH_DEV_TEMP_BUSY;
		} else
			err = SCSI_DH_DEV_FAILED;
	} else if (result) {
		sdev_printk(KERN_ERR, sdev, "Error 0x%x while sending "
			    "CLARiiON trespass command.\n", result);
		err = SCSI_DH_IO;
	}

	return err;
}
コード例 #6
0
ファイル: scsi_dh_emc.c プロジェクト: maraz/linux-2.6
static int sp_info_endio(struct scsi_device *sdev, int result,
					int mode_select_sent, int *done)
{
	struct clariion_dh_data *csdev = get_clariion_data(sdev);
	int err_flags, default_sp, current_sp, new_current_sp;

	err_flags = parse_sp_info_reply(sdev, result, &default_sp,
					     &current_sp, &new_current_sp);

	if (err_flags != SCSI_DH_OK)
		goto done;

	if (mode_select_sent) {
		csdev->default_sp = default_sp;
		csdev->current_sp = current_sp;
	} else {
		/*
		 * Issue the actual module_selec request IFF either
		 * (1) we do not know the identity of the current SP OR
		 * (2) what we think we know is actually correct.
		 */
		if ((current_sp != CLARIION_UNBOUND_LU) &&
		    (new_current_sp != current_sp)) {

			csdev->default_sp = default_sp;
			csdev->current_sp = current_sp;

			sdev_printk(KERN_INFO, sdev, "Ignoring path group "
			       "switch-over command for CLARiiON SP%s since "
			       " mapped device is already initialized.",
			       current_sp ? "B" : "A");
			if (done)
				*done = 1; /* as good as doing it */
		}
	}
done:
	return err_flags;
}
コード例 #7
0
static int clariion_activate(struct scsi_device *sdev,
				activate_complete fn, void *data)
{
	struct clariion_dh_data *csdev = get_clariion_data(sdev);
	int result;

	result = clariion_send_inquiry(sdev, csdev);
	if (result != SCSI_DH_OK)
		goto done;

	if (csdev->lun_state == CLARIION_LUN_OWNED)
		goto done;

	result = send_trespass_cmd(sdev, csdev);
	if (result != SCSI_DH_OK)
		goto done;
//	sdev_printk(KERN_INFO, sdev,"%s: %s trespass command sent\n",
//		    CLARIION_NAME,
;

	/* Update status */
	result = clariion_send_inquiry(sdev, csdev);
	if (result != SCSI_DH_OK)
		goto done;

done:
//	sdev_printk(KERN_INFO, sdev,
//		    "%s: at SP %c Port %d (%s, default SP %c)\n",
//		    CLARIION_NAME, csdev->current_sp + 'A',
//		    csdev->port, lun_state[csdev->lun_state],
;

	if (fn)
		fn(data, result);
	return 0;
}
コード例 #8
0
ファイル: scsi_dh_emc.c プロジェクト: maraz/linux-2.6
/*
* Get block request for REQ_BLOCK_PC command issued to path.  Currently
* limited to MODE_SELECT (trespass) and INQUIRY (VPD page 0xC0) commands.
*
* Uses data and sense buffers in hardware handler context structure and
* assumes serial servicing of commands, both issuance and completion.
*/
static struct request *get_req(struct scsi_device *sdev, int cmd)
{
	struct clariion_dh_data *csdev = get_clariion_data(sdev);
	struct request *rq;
	unsigned char *page22;
	int len = 0;

	rq = blk_get_request(sdev->request_queue,
			(cmd == MODE_SELECT) ? WRITE : READ, GFP_ATOMIC);
	if (!rq) {
		sdev_printk(KERN_INFO, sdev, "get_req: blk_get_request failed");
		return NULL;
	}

	memset(&rq->cmd, 0, BLK_MAX_CDB);
	rq->cmd[0] = cmd;
	rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);

	switch (cmd) {
	case MODE_SELECT:
		if (csdev->short_trespass) {
			page22 = csdev->hr ? short_trespass_hr : short_trespass;
			len = sizeof(short_trespass);
		} else {
			page22 = csdev->hr ? long_trespass_hr : long_trespass;
			len = sizeof(long_trespass);
		}
		/*
		 * Can't DMA from kernel BSS -- must copy selected trespass
		 * command mode page contents to context buffer which is
		 * allocated by kmalloc.
		 */
		BUG_ON((len > CLARIION_BUFFER_SIZE));
		memcpy(csdev->buffer, page22, len);
		rq->cmd_flags |= REQ_RW;
		rq->cmd[1] = 0x10;
		break;
	case INQUIRY:
		rq->cmd[1] = 0x1;
		rq->cmd[2] = 0xC0;
		len = CLARIION_BUFFER_SIZE;
		memset(csdev->buffer, 0, CLARIION_BUFFER_SIZE);
		break;
	default:
		BUG_ON(1);
		break;
	}

	rq->cmd[4] = len;
	rq->cmd_type = REQ_TYPE_BLOCK_PC;
	rq->cmd_flags |= REQ_FAILFAST;
	rq->timeout = CLARIION_TIMEOUT;
	rq->retries = CLARIION_RETRIES;

	rq->sense = csdev->sense;
	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
	rq->sense_len = 0;

	if (blk_rq_map_kern(sdev->request_queue, rq, csdev->buffer,
							len, GFP_ATOMIC)) {
		__blk_put_request(rq->q, rq);
		return NULL;
	}

	return rq;
}