⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ibmvscsi.c

📁 h内核
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Copy the IU into the transfer area */	*evt_struct->xfer_iu = evt_struct->iu;	evt_struct->xfer_iu->srp.generic.tag = (u64)evt_struct;	/* Add this to the sent list.  We need to do this 	 * before we actually send 	 * in case it comes back REALLY fast	 */	list_add_tail(&evt_struct->list, &hostdata->sent);	if ((rc =	     ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {		list_del(&evt_struct->list);		printk(KERN_ERR "ibmvscsi: failed to send event struct rc %d\n",		       rc);		goto send_error;	}	return 0; send_error:	unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);	if ((cmnd = evt_struct->cmnd) != NULL) {		cmnd->result = DID_ERROR << 16;		evt_struct->cmnd_done(cmnd);	} else if (evt_struct->done)		evt_struct->done(evt_struct);		free_event_struct(&hostdata->pool, evt_struct);	return 0;}/** * handle_cmd_rsp: -  Handle responses from commands * @evt_struct:	srp_event_struct to be handled * * Used as a callback by when sending scsi cmds. * Gets called by ibmvscsi_handle_crq()*/static void handle_cmd_rsp(struct srp_event_struct *evt_struct){	struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp;	struct scsi_cmnd *cmnd = evt_struct->cmnd;	if (unlikely(rsp->type != SRP_RSP_TYPE)) {		if (printk_ratelimit())			printk(KERN_WARNING 			       "ibmvscsi: bad SRP RSP type %d\n",			       rsp->type);	}		if (cmnd) {		cmnd->result = rsp->status;		if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION)			memcpy(cmnd->sense_buffer,			       rsp->sense_and_response_data,			       rsp->sense_data_list_length);		unmap_cmd_data(&evt_struct->iu.srp.cmd, 			       evt_struct->hostdata->dev);		if (rsp->doover)			cmnd->resid = rsp->data_out_residual_count;		else if (rsp->diover)			cmnd->resid = rsp->data_in_residual_count;	}	if (evt_struct->cmnd_done)		evt_struct->cmnd_done(cmnd);}/** * lun_from_dev: - Returns the lun of the scsi device * @dev:	struct scsi_device **/static inline u16 lun_from_dev(struct scsi_device *dev){	return (0x2 << 14) | (dev->id << 8) | (dev->channel << 5) | dev->lun;}/** * ibmvscsi_queue: - The queuecommand function of the scsi template  * @cmd:	struct scsi_cmnd to be executed * @done:	Callback function to be called when cmd is completed*/static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,				 void (*done) (struct scsi_cmnd *)){	struct srp_cmd *srp_cmd;	struct srp_event_struct *evt_struct;	struct ibmvscsi_host_data *hostdata =		(struct ibmvscsi_host_data *)&cmnd->device->host->hostdata;	u16 lun = lun_from_dev(cmnd->device);	evt_struct = get_event_struct(&hostdata->pool);	if (!evt_struct)		return SCSI_MLQUEUE_HOST_BUSY;	init_event_struct(evt_struct,			  handle_cmd_rsp,			  VIOSRP_SRP_FORMAT,			  cmnd->timeout);	evt_struct->cmnd = cmnd;	evt_struct->cmnd_done = done;	/* Set up the actual SRP IU */	srp_cmd = &evt_struct->iu.srp.cmd;	memset(srp_cmd, 0x00, sizeof(*srp_cmd));	srp_cmd->type = SRP_CMD_TYPE;	memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));	srp_cmd->lun = ((u64) lun) << 48;	if (!map_data_for_srp_cmd(cmnd, srp_cmd, hostdata->dev)) {		printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n");		free_event_struct(&hostdata->pool, evt_struct);		return SCSI_MLQUEUE_HOST_BUSY;	}	/* Fix up dma address of the buffer itself */	if ((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) ||	    (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) {		struct indirect_descriptor *indirect =		    (struct indirect_descriptor *)srp_cmd->additional_data;		indirect->head.virtual_address = evt_struct->crq.IU_data_ptr +		    offsetof(struct srp_cmd, additional_data) +		    offsetof(struct indirect_descriptor, list);	}	return ibmvscsi_send_srp_event(evt_struct, hostdata);}/* ------------------------------------------------------------ * Routines for driver initialization *//** * adapter_info_rsp: - Handle response to MAD adapter info request * @evt_struct:	srp_event_struct with the response * * Used as a "done" callback by when sending adapter_info. Gets called * by ibmvscsi_handle_crq()*/static void adapter_info_rsp(struct srp_event_struct *evt_struct){	struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;	dma_unmap_single(hostdata->dev,			 evt_struct->iu.mad.adapter_info.buffer,			 evt_struct->iu.mad.adapter_info.common.length,			 DMA_BIDIRECTIONAL);	if (evt_struct->xfer_iu->mad.adapter_info.common.status) {		printk("ibmvscsi: error %d getting adapter info\n",		       evt_struct->xfer_iu->mad.adapter_info.common.status);	} else {		printk("ibmvscsi: host srp version: %s, "		       "host partition %s (%d), OS %d, max io %u\n",		       hostdata->madapter_info.srp_version,		       hostdata->madapter_info.partition_name,		       hostdata->madapter_info.partition_number,		       hostdata->madapter_info.os_type,		       hostdata->madapter_info.port_max_txu[0]);				if (hostdata->madapter_info.port_max_txu[0]) 			hostdata->host->max_sectors = 				hostdata->madapter_info.port_max_txu[0] >> 9;	}}/** * send_mad_adapter_info: - Sends the mad adapter info request *      and stores the result so it can be retrieved with *      sysfs.  We COULD consider causing a failure if the *      returned SRP version doesn't match ours. * @hostdata:	ibmvscsi_host_data of host *  * Returns zero if successful.*/static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata){	struct viosrp_adapter_info *req;	struct srp_event_struct *evt_struct;		memset(&hostdata->madapter_info, 0x00, sizeof(hostdata->madapter_info));		evt_struct = get_event_struct(&hostdata->pool);	if (!evt_struct) {		printk(KERN_ERR "ibmvscsi: couldn't allocate an event "		       "for ADAPTER_INFO_REQ!\n");		return;	}	init_event_struct(evt_struct,			  adapter_info_rsp,			  VIOSRP_MAD_FORMAT,			  init_timeout * HZ);		req = &evt_struct->iu.mad.adapter_info;	memset(req, 0x00, sizeof(*req));		req->common.type = VIOSRP_ADAPTER_INFO_TYPE;	req->common.length = sizeof(hostdata->madapter_info);	req->buffer = dma_map_single(hostdata->dev,				     &hostdata->madapter_info,				     sizeof(hostdata->madapter_info),				     DMA_BIDIRECTIONAL);	if (dma_mapping_error(req->buffer)) {		printk(KERN_ERR		       "ibmvscsi: Unable to map request_buffer "		       "for adapter_info!\n");		free_event_struct(&hostdata->pool, evt_struct);		return;	}		if (ibmvscsi_send_srp_event(evt_struct, hostdata))		printk(KERN_ERR "ibmvscsi: couldn't send ADAPTER_INFO_REQ!\n");};/** * login_rsp: - Handle response to SRP login request * @evt_struct:	srp_event_struct with the response * * Used as a "done" callback by when sending srp_login. Gets called * by ibmvscsi_handle_crq()*/static void login_rsp(struct srp_event_struct *evt_struct){	struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;	switch (evt_struct->xfer_iu->srp.generic.type) {	case SRP_LOGIN_RSP_TYPE:	/* it worked! */		break;	case SRP_LOGIN_REJ_TYPE:	/* refused! */		printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REQ rejected\n");		/* Login failed.  */		atomic_set(&hostdata->request_limit, -1);		return;	default:		printk(KERN_ERR		       "ibmvscsi: Invalid login response typecode 0x%02x!\n",		       evt_struct->xfer_iu->srp.generic.type);		/* Login failed.  */		atomic_set(&hostdata->request_limit, -1);		return;	}	printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");	if (evt_struct->xfer_iu->srp.login_rsp.request_limit_delta >	    (max_requests - 2))		evt_struct->xfer_iu->srp.login_rsp.request_limit_delta =		    max_requests - 2;	/* Now we know what the real request-limit is */	atomic_set(&hostdata->request_limit,		   evt_struct->xfer_iu->srp.login_rsp.request_limit_delta);	hostdata->host->can_queue =	    evt_struct->xfer_iu->srp.login_rsp.request_limit_delta - 2;	if (hostdata->host->can_queue < 1) {		printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n");		return;	}	send_mad_adapter_info(hostdata);	return;}/** * send_srp_login: - Sends the srp login * @hostdata:	ibmvscsi_host_data of host *  * Returns zero if successful.*/static int send_srp_login(struct ibmvscsi_host_data *hostdata){	int rc;	unsigned long flags;	struct srp_login_req *login;	struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool);	if (!evt_struct) {		printk(KERN_ERR		       "ibmvscsi: couldn't allocate an event for login req!\n");		return FAILED;	}	init_event_struct(evt_struct,			  login_rsp,			  VIOSRP_SRP_FORMAT,			  init_timeout * HZ);	login = &evt_struct->iu.srp.login_req;	login->type = SRP_LOGIN_REQ_TYPE;	login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu);	login->required_buffer_formats = 0x0006;		/* Start out with a request limit of 1, since this is negotiated in	 * the login request we are just sending	 */	atomic_set(&hostdata->request_limit, 1);	spin_lock_irqsave(hostdata->host->host_lock, flags);	rc = ibmvscsi_send_srp_event(evt_struct, hostdata);	spin_unlock_irqrestore(hostdata->host->host_lock, flags);	return rc;};/** * sync_completion: Signal that a synchronous command has completed * Note that after returning from this call, the evt_struct is freed. * the caller waiting on this completion shouldn't touch the evt_struct * again. */static void sync_completion(struct srp_event_struct *evt_struct){	/* copy the response back */	if (evt_struct->sync_srp)		*evt_struct->sync_srp = *evt_struct->xfer_iu;		complete(&evt_struct->comp);}/** * ibmvscsi_abort: Abort a command...from scsi host template * send this over to the server and wait synchronously for the response */static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd){	struct ibmvscsi_host_data *hostdata =	    (struct ibmvscsi_host_data *)cmd->device->host->hostdata;	struct srp_tsk_mgmt *tsk_mgmt;	struct srp_event_struct *evt;	struct srp_event_struct *tmp_evt, *found_evt;	union viosrp_iu srp_rsp;	int rsp_rc;	u16 lun = lun_from_dev(cmd->device);	/* First, find this command in our sent list so we can figure	 * out the correct tag	 */	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) 		return FAILED;	evt = get_event_struct(&hostdata->pool);	if (evt == NULL) {		printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n");		return FAILED;	}		init_event_struct(evt,			  sync_completion,			  VIOSRP_SRP_FORMAT,			  init_timeout * HZ);	tsk_mgmt = &evt->iu.srp.tsk_mgmt;		/* Set up an abort SRP command */	memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));	tsk_mgmt->type = SRP_TSK_MGMT_TYPE;	tsk_mgmt->lun = ((u64) lun) << 48;	tsk_mgmt->task_mgmt_flags = 0x01;	/* ABORT TASK */	tsk_mgmt->managed_task_tag = (u64) found_evt;	printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",	       tsk_mgmt->lun, tsk_mgmt->managed_task_tag);	evt->sync_srp = &srp_rsp;	init_completion(&evt->comp);	if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {		printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");		return FAILED;	}	spin_unlock_irq(hostdata->host->host_lock);	wait_for_completion(&evt->comp);	spin_lock_irq(hostdata->host->host_lock);	/* make sure we got a good response */	if (unlikely(srp_rsp.srp.generic.type != SRP_RSP_TYPE)) {		if (printk_ratelimit())			printk(KERN_WARNING 			       "ibmvscsi: abort bad SRP RSP type %d\n",			       srp_rsp.srp.generic.type);		return FAILED;	}	if (srp_rsp.srp.rsp.rspvalid)		rsp_rc = *((int *)srp_rsp.srp.rsp.sense_and_response_data);	else		rsp_rc = srp_rsp.srp.rsp.status;	if (rsp_rc) {		if (printk_ratelimit())			printk(KERN_WARNING 		       "ibmvscsi: abort code %d for task tag 0x%lx\n",			       rsp_rc,			       tsk_mgmt->managed_task_tag);		return FAILED;	}	/* Because we dropped the spinlock above, it's possible	 * The event is no longer in our list.  Make sure it didn't	 * complete while we were aborting	 */	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 == NULL) {		printk(KERN_INFO		       "ibmvscsi: aborted task tag 0x%lx completed\n",		       tsk_mgmt->managed_task_tag);		return SUCCESS;	}	printk(KERN_INFO	       "ibmvscsi: successfully aborted task tag 0x%lx\n",	       tsk_mgmt->managed_task_tag);	cmd->result = (DID_ABORT << 16);	list_del(&found_evt->list);	unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);	free_event_struct(&found_evt->hostdata->pool, found_evt);	atomic_inc(&hostdata->request_limit);	return SUCCESS;}/** * ibmvscsi_eh_device_reset_handler: Reset a single LUN...from scsi host  * template send this over to the server and wait synchronously for the  * response */static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd){	struct ibmvscsi_host_data *hostdata =	    (struct ibmvscsi_host_data *)cmd->device->host->hostdata;	struct srp_tsk_mgmt *tsk_mgmt;	struct srp_event_struct *evt;	struct srp_event_struct *tmp_evt, *pos;	union viosrp_iu srp_rsp;	int rsp_rc;	u16 lun = lun_from_dev(cmd->device);	evt = get_event_struct(&hostdata->pool);	if (evt == NULL) {		printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n");		return FAILED;	}		init_event_struct(evt,			  sync_completion,			  VIOSRP_SRP_FORMAT,			  init_timeout * HZ);	tsk_mgmt = &evt->iu.srp.tsk_mgmt;	/* Set up a lun reset SRP command */	memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));	tsk_mgmt->type = SRP_TSK_MGMT_TYPE;	tsk_mgmt->lun = ((u64) lun) << 48;	tsk_mgmt->task_mgmt_flags = 0x08;	/* LUN RESET */	printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",	       tsk_mgmt->lun);	evt->sync_srp = &srp_rsp;	init_completion(&evt->comp);	if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {		printk(KERN_ERR "ibmvscsi: failed to send reset event\n");		return FAILED;	}	spin_unlock_irq(hostdata->host->host_lock);	wait_for_completion(&evt->comp);	spin_lock_irq(hostdata->host->host_lock);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -