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

📄 ib_srp.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	}	for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {		target->tx_ring[i] = srp_alloc_iu(target->srp_host,						  srp_max_iu_len,						  GFP_KERNEL, DMA_TO_DEVICE);		if (!target->tx_ring[i])			goto err;	}	return 0;err:	for (i = 0; i < SRP_RQ_SIZE; ++i) {		srp_free_iu(target->srp_host, target->rx_ring[i]);		target->rx_ring[i] = NULL;	}	for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {		srp_free_iu(target->srp_host, target->tx_ring[i]);		target->tx_ring[i] = NULL;	}	return -ENOMEM;}static void srp_cm_rej_handler(struct ib_cm_id *cm_id,			       struct ib_cm_event *event,			       struct srp_target_port *target){	struct ib_class_port_info *cpi;	int opcode;	switch (event->param.rej_rcvd.reason) {	case IB_CM_REJ_PORT_CM_REDIRECT:		cpi = event->param.rej_rcvd.ari;		target->path.dlid = cpi->redirect_lid;		target->path.pkey = cpi->redirect_pkey;		cm_id->remote_cm_qpn = be32_to_cpu(cpi->redirect_qp) & 0x00ffffff;		memcpy(target->path.dgid.raw, cpi->redirect_gid, 16);		target->status = target->path.dlid ?			SRP_DLID_REDIRECT : SRP_PORT_REDIRECT;		break;	case IB_CM_REJ_PORT_REDIRECT:		if (srp_target_is_topspin(target)) {			/*			 * Topspin/Cisco SRP gateways incorrectly send			 * reject reason code 25 when they mean 24			 * (port redirect).			 */			memcpy(target->path.dgid.raw,			       event->param.rej_rcvd.ari, 16);			printk(KERN_DEBUG PFX "Topspin/Cisco redirect to target port GID %016llx%016llx\n",			       (unsigned long long) be64_to_cpu(target->path.dgid.global.subnet_prefix),			       (unsigned long long) be64_to_cpu(target->path.dgid.global.interface_id));			target->status = SRP_PORT_REDIRECT;		} else {			printk(KERN_WARNING "  REJ reason: IB_CM_REJ_PORT_REDIRECT\n");			target->status = -ECONNRESET;		}		break;	case IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID:		printk(KERN_WARNING "  REJ reason: IB_CM_REJ_DUPLICATE_LOCAL_COMM_ID\n");		target->status = -ECONNRESET;		break;	case IB_CM_REJ_CONSUMER_DEFINED:		opcode = *(u8 *) event->private_data;		if (opcode == SRP_LOGIN_REJ) {			struct srp_login_rej *rej = event->private_data;			u32 reason = be32_to_cpu(rej->reason);			if (reason == SRP_LOGIN_REJ_REQ_IT_IU_LENGTH_TOO_LARGE)				printk(KERN_WARNING PFX				       "SRP_LOGIN_REJ: requested max_it_iu_len too large\n");			else				printk(KERN_WARNING PFX				       "SRP LOGIN REJECTED, reason 0x%08x\n", reason);		} else			printk(KERN_WARNING "  REJ reason: IB_CM_REJ_CONSUMER_DEFINED,"			       " opcode 0x%02x\n", opcode);		target->status = -ECONNRESET;		break;	default:		printk(KERN_WARNING "  REJ reason 0x%x\n",		       event->param.rej_rcvd.reason);		target->status = -ECONNRESET;	}}static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event){	struct srp_target_port *target = cm_id->context;	struct ib_qp_attr *qp_attr = NULL;	int attr_mask = 0;	int comp = 0;	int opcode = 0;	switch (event->event) {	case IB_CM_REQ_ERROR:		printk(KERN_DEBUG PFX "Sending CM REQ failed\n");		comp = 1;		target->status = -ECONNRESET;		break;	case IB_CM_REP_RECEIVED:		comp = 1;		opcode = *(u8 *) event->private_data;		if (opcode == SRP_LOGIN_RSP) {			struct srp_login_rsp *rsp = event->private_data;			target->max_ti_iu_len = be32_to_cpu(rsp->max_ti_iu_len);			target->req_lim       = be32_to_cpu(rsp->req_lim_delta);			target->scsi_host->can_queue = min(target->req_lim,							   target->scsi_host->can_queue);		} else {			printk(KERN_WARNING PFX "Unhandled RSP opcode %#x\n", opcode);			target->status = -ECONNRESET;			break;		}		if (!target->rx_ring[0]) {			target->status = srp_alloc_iu_bufs(target);			if (target->status)				break;		}		qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL);		if (!qp_attr) {			target->status = -ENOMEM;			break;		}		qp_attr->qp_state = IB_QPS_RTR;		target->status = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);		if (target->status)			break;		target->status = ib_modify_qp(target->qp, qp_attr, attr_mask);		if (target->status)			break;		target->status = srp_post_recv(target);		if (target->status)			break;		qp_attr->qp_state = IB_QPS_RTS;		target->status = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);		if (target->status)			break;		target->status = ib_modify_qp(target->qp, qp_attr, attr_mask);		if (target->status)			break;		target->status = ib_send_cm_rtu(cm_id, NULL, 0);		if (target->status)			break;		break;	case IB_CM_REJ_RECEIVED:		printk(KERN_DEBUG PFX "REJ received\n");		comp = 1;		srp_cm_rej_handler(cm_id, event, target);		break;	case IB_CM_DREQ_RECEIVED:		printk(KERN_WARNING PFX "DREQ received - connection closed\n");		if (ib_send_cm_drep(cm_id, NULL, 0))			printk(KERN_ERR PFX "Sending CM DREP failed\n");		break;	case IB_CM_TIMEWAIT_EXIT:		printk(KERN_ERR PFX "connection closed\n");		comp = 1;		target->status = 0;		break;	case IB_CM_MRA_RECEIVED:	case IB_CM_DREQ_ERROR:	case IB_CM_DREP_RECEIVED:		break;	default:		printk(KERN_WARNING PFX "Unhandled CM event %d\n", event->event);		break;	}	if (comp)		complete(&target->done);	kfree(qp_attr);	return 0;}static int srp_send_tsk_mgmt(struct srp_target_port *target,			     struct srp_request *req, u8 func){	struct srp_iu *iu;	struct srp_tsk_mgmt *tsk_mgmt;	spin_lock_irq(target->scsi_host->host_lock);	if (target->state == SRP_TARGET_DEAD ||	    target->state == SRP_TARGET_REMOVED) {		req->scmnd->result = DID_BAD_TARGET << 16;		goto out;	}	init_completion(&req->done);	iu = __srp_get_tx_iu(target);	if (!iu)		goto out;	tsk_mgmt = iu->buf;	memset(tsk_mgmt, 0, sizeof *tsk_mgmt);	tsk_mgmt->opcode 	= SRP_TSK_MGMT;	tsk_mgmt->lun 		= cpu_to_be64((u64) req->scmnd->device->lun << 48);	tsk_mgmt->tag 		= req->index | SRP_TAG_TSK_MGMT;	tsk_mgmt->tsk_mgmt_func = func;	tsk_mgmt->task_tag 	= req->index;	if (__srp_post_send(target, iu, sizeof *tsk_mgmt))		goto out;	req->tsk_mgmt = iu;	spin_unlock_irq(target->scsi_host->host_lock);	if (!wait_for_completion_timeout(&req->done,					 msecs_to_jiffies(SRP_ABORT_TIMEOUT_MS)))		return -1;	return 0;out:	spin_unlock_irq(target->scsi_host->host_lock);	return -1;}static int srp_find_req(struct srp_target_port *target,			struct scsi_cmnd *scmnd,			struct srp_request **req){	if (scmnd->host_scribble == (void *) -1L)		return -1;	*req = &target->req_ring[(long) scmnd->host_scribble];	return 0;}static int srp_abort(struct scsi_cmnd *scmnd){	struct srp_target_port *target = host_to_target(scmnd->device->host);	struct srp_request *req;	int ret = SUCCESS;	printk(KERN_ERR "SRP abort called\n");	if (target->qp_in_error)		return FAILED;	if (srp_find_req(target, scmnd, &req))		return FAILED;	if (srp_send_tsk_mgmt(target, req, SRP_TSK_ABORT_TASK))		return FAILED;	spin_lock_irq(target->scsi_host->host_lock);	if (req->cmd_done) {		srp_remove_req(target, req);		scmnd->scsi_done(scmnd);	} else if (!req->tsk_status) {		srp_remove_req(target, req);		scmnd->result = DID_ABORT << 16;	} else		ret = FAILED;	spin_unlock_irq(target->scsi_host->host_lock);	return ret;}static int srp_reset_device(struct scsi_cmnd *scmnd){	struct srp_target_port *target = host_to_target(scmnd->device->host);	struct srp_request *req, *tmp;	printk(KERN_ERR "SRP reset_device called\n");	if (target->qp_in_error)		return FAILED;	if (srp_find_req(target, scmnd, &req))		return FAILED;	if (srp_send_tsk_mgmt(target, req, SRP_TSK_LUN_RESET))		return FAILED;	if (req->tsk_status)		return FAILED;	spin_lock_irq(target->scsi_host->host_lock);	list_for_each_entry_safe(req, tmp, &target->req_queue, list)		if (req->scmnd->device == scmnd->device)			srp_reset_req(target, req);	spin_unlock_irq(target->scsi_host->host_lock);	return SUCCESS;}static int srp_reset_host(struct scsi_cmnd *scmnd){	struct srp_target_port *target = host_to_target(scmnd->device->host);	int ret = FAILED;	printk(KERN_ERR PFX "SRP reset_host called\n");	if (!srp_reconnect_target(target))		ret = SUCCESS;	return ret;}static ssize_t show_id_ext(struct class_device *cdev, char *buf){	struct srp_target_port *target = host_to_target(class_to_shost(cdev));	if (target->state == SRP_TARGET_DEAD ||	    target->state == SRP_TARGET_REMOVED)		return -ENODEV;	return sprintf(buf, "0x%016llx\n",		       (unsigned long long) be64_to_cpu(target->id_ext));}static ssize_t show_ioc_guid(struct class_device *cdev, char *buf){	struct srp_target_port *target = host_to_target(class_to_shost(cdev));	if (target->state == SRP_TARGET_DEAD ||	    target->state == SRP_TARGET_REMOVED)		return -ENODEV;	return sprintf(buf, "0x%016llx\n",		       (unsigned long long) be64_to_cpu(target->ioc_guid));}static ssize_t show_service_id(struct class_device *cdev, char *buf){	struct srp_target_port *target = host_to_target(class_to_shost(cdev));	if (target->state == SRP_TARGET_DEAD ||	    target->state == SRP_TARGET_REMOVED)		return -ENODEV;	return sprintf(buf, "0x%016llx\n",		       (unsigned long long) be64_to_cpu(target->service_id));}static ssize_t show_pkey(struct class_device *cdev, char *buf){	struct srp_target_port *target = host_to_target(class_to_shost(cdev));	if (target->state == SRP_TARGET_DEAD ||	    target->state == SRP_TARGET_REMOVED)		return -ENODEV;	return sprintf(buf, "0x%04x\n", be16_to_cpu(target->path.pkey));}static ssize_t show_dgid(struct class_device *cdev, char *buf){	struct srp_target_port *target = host_to_target(class_to_shost(cdev));	if (target->state == SRP_TARGET_DEAD ||	    target->state == SRP_TARGET_REMOVED)		return -ENODEV;	return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[0]),		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[1]),		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[2]),		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[3]),		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[4]),		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[5]),		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[6]),		       be16_to_cpu(((__be16 *) target->path.dgid.raw)[7]));}static ssize_t show_orig_dgid(struct class_device *cdev, char *buf){	struct srp_target_port *target = host_to_target(class_to_shost(cdev));	if (target->state == SRP_TARGET_DEAD ||	    target->state == SRP_TARGET_REMOVED)		return -ENODEV;	return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",		       be16_to_cpu(target->orig_dgid[0]),		       be16_to_cpu(target->orig_dgid[1]),		       be16_to_cpu(target->orig_dgid[2]),		       be16_to_cpu(target->orig_dgid[3]),		       be16_to_cpu(target->orig_dgid[4]),		       be16_to_cpu(target->orig_dgid[5]),		       be16_to_cpu(target->orig_dgid[6]),		       be16_to_cpu(target->orig_dgid[7]));}static ssize_t show_zero_req_lim(struct class_device *cdev, char *buf){	struct srp_target_port *target = host_to_target(class_to_shost(cdev));	if (target->state == SRP_TARGET_DEAD ||	    target->state == SRP_TARGET_REMOVED)		return -ENODEV;	return sprintf(buf, "%d\n", target->zero_req_lim);}static ssize_t show_local_ib_port(struct class_device *cdev, char *buf){	struct srp_target_port *target = host_to_target(class_to_shost(cdev));	return sprintf(buf, "%d\n", target->srp_host->port);}static ssize_t show_local_ib_device(struct class_device *cdev, char *buf){	struct srp_target_port *target = host_to_target(class_to_shost(cdev));	return sprintf(buf, "%s\n", target->srp_host->dev->dev->name);}static CLASS_DEVICE_ATTR(id_ext,	  S_IRUGO, show_id_ext,		 NULL);static CLASS_DEVICE_ATTR(ioc_guid,	  S_IRUGO, show_ioc_guid,	 NULL);static CLASS_DEVICE_ATTR(service_id,	  S_IRUGO, show_service_id,	 NULL);static CLASS_DEVICE_ATTR(pkey,		  S_IRUGO, show_pkey,		 NULL);static CLASS_DEVICE_ATTR(dgid,		  S_IRUGO, show_dgid,		 NULL);static CLASS_DEVICE_ATTR(orig_dgid,	  S_IRUGO, show_orig_dgid,	 NULL);static CLASS_DEVICE_ATTR(zero_req_lim,	  S_IRUGO, show_zero_req_lim,	 NULL);static CLASS_DEVICE_ATTR(local_ib_port,   S_IRUGO, show_local_ib_port,	 NULL);static CLASS_DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);static struct class_device_attribute *srp_host_attrs[] = {	&class_device_attr_id_ext,	&class_device_attr_ioc_guid,	&class_device_attr_service_id,	&class_device_attr_pkey,	&class_device_attr_dgid,	&class_device_attr_orig_dgid,	&class_device_attr_zero_req_lim,	&class_device_attr_local_ib_port,	&class_device_attr_local_ib_device,	NULL};static struct scsi_host_template srp_template = {	.module				= THIS_MODULE,	.name				= "InfiniBand SRP initiator",	.proc_name			= DRV_NAME,	.info				= srp_target_info,	.queuecommand			= srp_queuecommand,	.eh_abort_handler		= srp_abort,	.eh_device_reset_handler	= srp_reset_device,	.eh_host_reset_handler		= srp_reset_host,	.can_queue			= SRP_SQ_SIZE,	.this_id			= -1,	.cmd_per_lun			= SRP_SQ_SIZE,	.use_clustering			= ENABLE_CLUSTERING,	.shost_attrs			= srp_host_attrs};static int srp_add_target(struct srp_host *host, struct srp_target_port *target){	struct srp_rport_identifiers ids;	struct srp_rport *rport;	sprintf(target->target_name, "SRP.T10:%016llX",		 (unsigned long long) be64_to_cpu(target->id_ext));	if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device))		return -ENODEV;	memcpy(ids.port_id, &target->id_ext, 8);	memcpy(ids.port_id + 8, &target->ioc_guid, 8);	ids.roles = SRP_RPORT_ROLE_TARGET;	rport = srp_rport_add(target->scsi_host, &ids);	if (IS_ERR(rport)) {		scsi_remove_host(target->scsi_host);		return PTR_ERR(rport);	}	spin_lock(&host->target_lock);	list_add_tail(&target->list, &host->target_list);	spin_unlock(&host->target_lock);	target->state = SRP_TARGET_LIVE;	scsi_scan_target(&target->scsi_host->shost_gendev,			 0, target->scsi_id, SCAN_WILD_CARD, 0);	return 0;}static void srp_release_class_dev(struct class_device *class_dev){	struct srp_host *host =		container_of(class_dev, struct srp_host, class_dev);	complete(&host->released);}static struct class srp_class = {	.name    = "infiniband_srp",	.release = srp_release_class_dev};

⌨️ 快捷键说明

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