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

📄 ib_srp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		complete(&target->done);	kfree(qp_attr);	return 0;}static int srp_send_tsk_mgmt(struct scsi_cmnd *scmnd, u8 func){	struct srp_target_port *target = host_to_target(scmnd->device->host);	struct srp_request *req;	struct srp_iu *iu;	struct srp_tsk_mgmt *tsk_mgmt;	int req_index;	int ret = FAILED;	spin_lock_irq(target->scsi_host->host_lock);	if (scmnd->host_scribble == (void *) -1L)		goto out;	req_index = (long) scmnd->host_scribble;	printk(KERN_ERR "Abort for req_index %d\n", req_index);	req = &target->req_ring[req_index];	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) 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 FAILED;	spin_lock_irq(target->scsi_host->host_lock);	if (req->cmd_done) {		list_del(&req->list);		req->next = target->req_head;		target->req_head = req_index;		scmnd->scsi_done(scmnd);	} else if (!req->tsk_status) {		scmnd->result = DID_ABORT << 16;		ret = SUCCESS;	}out:	spin_unlock_irq(target->scsi_host->host_lock);	return ret;}static int srp_abort(struct scsi_cmnd *scmnd){	printk(KERN_ERR "SRP abort called\n");	return srp_send_tsk_mgmt(scmnd, SRP_TSK_ABORT_TASK);}static int srp_reset_device(struct scsi_cmnd *scmnd){	printk(KERN_ERR "SRP reset_device called\n");	return srp_send_tsk_mgmt(scmnd, SRP_TSK_LUN_RESET);}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 struct scsi_host_template srp_template = {	.module				= THIS_MODULE,	.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,	.sg_tablesize			= SRP_MAX_INDIRECT,	.cmd_per_lun			= SRP_SQ_SIZE,	.use_clustering			= ENABLE_CLUSTERING};static int srp_add_target(struct srp_host *host, struct srp_target_port *target){	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->dma_device))		return -ENODEV;	down(&host->target_mutex);	list_add_tail(&target->list, &host->target_list);	up(&host->target_mutex);	target->state = SRP_TARGET_LIVE;	/* XXX: are we supposed to have a definition of SCAN_WILD_CARD ?? */	scsi_scan_target(&target->scsi_host->shost_gendev,			 0, target->scsi_id, ~0, 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};/* * Target ports are added by writing * *     id_ext=<SRP ID ext>,ioc_guid=<SRP IOC GUID>,dgid=<dest GID>, *     pkey=<P_Key>,service_id=<service ID> * * to the add_target sysfs attribute. */enum {	SRP_OPT_ERR		= 0,	SRP_OPT_ID_EXT		= 1 << 0,	SRP_OPT_IOC_GUID	= 1 << 1,	SRP_OPT_DGID		= 1 << 2,	SRP_OPT_PKEY		= 1 << 3,	SRP_OPT_SERVICE_ID	= 1 << 4,	SRP_OPT_MAX_SECT	= 1 << 5,	SRP_OPT_ALL		= (SRP_OPT_ID_EXT	|				   SRP_OPT_IOC_GUID	|				   SRP_OPT_DGID		|				   SRP_OPT_PKEY		|				   SRP_OPT_SERVICE_ID),};static match_table_t srp_opt_tokens = {	{ SRP_OPT_ID_EXT,	"id_ext=%s" 	},	{ SRP_OPT_IOC_GUID,	"ioc_guid=%s" 	},	{ SRP_OPT_DGID,		"dgid=%s" 	},	{ SRP_OPT_PKEY,		"pkey=%x" 	},	{ SRP_OPT_SERVICE_ID,	"service_id=%s" },	{ SRP_OPT_MAX_SECT,     "max_sect=%d" 	},	{ SRP_OPT_ERR,		NULL 		}};static int srp_parse_options(const char *buf, struct srp_target_port *target){	char *options, *sep_opt;	char *p;	char dgid[3];	substring_t args[MAX_OPT_ARGS];	int opt_mask = 0;	int token;	int ret = -EINVAL;	int i;	options = kstrdup(buf, GFP_KERNEL);	if (!options)		return -ENOMEM;	sep_opt = options;	while ((p = strsep(&sep_opt, ",")) != NULL) {		if (!*p)			continue;		token = match_token(p, srp_opt_tokens, args);		opt_mask |= token;		switch (token) {		case SRP_OPT_ID_EXT:			p = match_strdup(args);			target->id_ext = cpu_to_be64(simple_strtoull(p, NULL, 16));			kfree(p);			break;		case SRP_OPT_IOC_GUID:			p = match_strdup(args);			target->ioc_guid = cpu_to_be64(simple_strtoull(p, NULL, 16));			kfree(p);			break;		case SRP_OPT_DGID:			p = match_strdup(args);			if (strlen(p) != 32) {				printk(KERN_WARNING PFX "bad dest GID parameter '%s'\n", p);				goto out;			}			for (i = 0; i < 16; ++i) {				strlcpy(dgid, p + i * 2, 3);				target->path.dgid.raw[i] = simple_strtoul(dgid, NULL, 16);			}			break;		case SRP_OPT_PKEY:			if (match_hex(args, &token)) {				printk(KERN_WARNING PFX "bad P_Key parameter '%s'\n", p);				goto out;			}			target->path.pkey = cpu_to_be16(token);			break;		case SRP_OPT_SERVICE_ID:			p = match_strdup(args);			target->service_id = cpu_to_be64(simple_strtoull(p, NULL, 16));			kfree(p);			break;		case SRP_OPT_MAX_SECT:			if (match_int(args, &token)) {				printk(KERN_WARNING PFX "bad max sect parameter '%s'\n", p);				goto out;			}			target->scsi_host->max_sectors = token;			break;		default:			printk(KERN_WARNING PFX "unknown parameter or missing value "			       "'%s' in target creation request\n", p);			goto out;		}	}	if ((opt_mask & SRP_OPT_ALL) == SRP_OPT_ALL)		ret = 0;	else		for (i = 0; i < ARRAY_SIZE(srp_opt_tokens); ++i)			if ((srp_opt_tokens[i].token & SRP_OPT_ALL) &&			    !(srp_opt_tokens[i].token & opt_mask))				printk(KERN_WARNING PFX "target creation request is "				       "missing parameter '%s'\n",				       srp_opt_tokens[i].pattern);out:	kfree(options);	return ret;}static ssize_t srp_create_target(struct class_device *class_dev,				 const char *buf, size_t count){	struct srp_host *host =		container_of(class_dev, struct srp_host, class_dev);	struct Scsi_Host *target_host;	struct srp_target_port *target;	int ret;	int i;	target_host = scsi_host_alloc(&srp_template,				      sizeof (struct srp_target_port));	if (!target_host)		return -ENOMEM;	target_host->max_lun = SRP_MAX_LUN;	target = host_to_target(target_host);	memset(target, 0, sizeof *target);	target->scsi_host  = target_host;	target->srp_host   = host;	INIT_WORK(&target->work, srp_reconnect_work, target);	for (i = 0; i < SRP_SQ_SIZE - 1; ++i)		target->req_ring[i].next = i + 1;	target->req_ring[SRP_SQ_SIZE - 1].next = -1;	INIT_LIST_HEAD(&target->req_queue);	ret = srp_parse_options(buf, target);	if (ret)		goto err;	ib_get_cached_gid(host->dev, host->port, 0, &target->path.sgid);	printk(KERN_DEBUG PFX "new target: id_ext %016llx ioc_guid %016llx pkey %04x "	       "service_id %016llx dgid %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",	       (unsigned long long) be64_to_cpu(target->id_ext),	       (unsigned long long) be64_to_cpu(target->ioc_guid),	       be16_to_cpu(target->path.pkey),	       (unsigned long long) be64_to_cpu(target->service_id),	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[0]),	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[2]),	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[4]),	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[6]),	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[8]),	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[10]),	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[12]),	       (int) be16_to_cpu(*(__be16 *) &target->path.dgid.raw[14]));	ret = srp_create_target_ib(target);	if (ret)		goto err;	target->cm_id = ib_create_cm_id(host->dev, srp_cm_handler, target);	if (IS_ERR(target->cm_id)) {		ret = PTR_ERR(target->cm_id);		goto err_free;	}	ret = srp_connect_target(target);	if (ret) {		printk(KERN_ERR PFX "Connection failed\n");		goto err_cm_id;	}	ret = srp_add_target(host, target);	if (ret)		goto err_disconnect;	return count;err_disconnect:	srp_disconnect_target(target);err_cm_id:	ib_destroy_cm_id(target->cm_id);err_free:	srp_free_target_ib(target);err:	scsi_host_put(target_host);	return ret;}static CLASS_DEVICE_ATTR(add_target, S_IWUSR, NULL, srp_create_target);static ssize_t show_ibdev(struct class_device *class_dev, char *buf){	struct srp_host *host =		container_of(class_dev, struct srp_host, class_dev);	return sprintf(buf, "%s\n", host->dev->name);}static CLASS_DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);static ssize_t show_port(struct class_device *class_dev, char *buf){	struct srp_host *host =		container_of(class_dev, struct srp_host, class_dev);	return sprintf(buf, "%d\n", host->port);}static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);static struct srp_host *srp_add_port(struct ib_device *device,				     __be64 node_guid, u8 port){	struct srp_host *host;	host = kzalloc(sizeof *host, GFP_KERNEL);	if (!host)		return NULL;	INIT_LIST_HEAD(&host->target_list);	init_MUTEX(&host->target_mutex);	init_completion(&host->released);	host->dev  = device;	host->port = port;	host->initiator_port_id[7] = port;	memcpy(host->initiator_port_id + 8, &node_guid, 8);	host->pd   = ib_alloc_pd(device);	if (IS_ERR(host->pd))		goto err_free;	host->mr   = ib_get_dma_mr(host->pd,				   IB_ACCESS_LOCAL_WRITE |				   IB_ACCESS_REMOTE_READ |				   IB_ACCESS_REMOTE_WRITE);	if (IS_ERR(host->mr))		goto err_pd;	host->class_dev.class = &srp_class;	host->class_dev.dev   = device->dma_device;	snprintf(host->class_dev.class_id, BUS_ID_SIZE, "srp-%s-%d",		 device->name, port);	if (class_device_register(&host->class_dev))		goto err_mr;	if (class_device_create_file(&host->class_dev, &class_device_attr_add_target))		goto err_class;	if (class_device_create_file(&host->class_dev, &class_device_attr_ibdev))		goto err_class;	if (class_device_create_file(&host->class_dev, &class_device_attr_port))		goto err_class;	return host;err_class:	class_device_unregister(&host->class_dev);err_mr:	ib_dereg_mr(host->mr);err_pd:	ib_dealloc_pd(host->pd);err_free:	kfree(host);	return NULL;}static void srp_add_one(struct ib_device *device){	struct list_head *dev_list;	struct srp_host *host;	struct ib_device_attr *dev_attr;	int s, e, p;	dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL);	if (!dev_attr)		return;	if (ib_query_device(device, dev_attr)) {		printk(KERN_WARNING PFX "Couldn't query node GUID for %s.\n",		       device->name);		goto out;	}	dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);	if (!dev_list)		goto out;	INIT_LIST_HEAD(dev_list);	if (device->node_type == IB_NODE_SWITCH) {		s = 0;		e = 0;	} else {		s = 1;		e = device->phys_port_cnt;	}	for (p = s; p <= e; ++p) {		host = srp_add_port(device, dev_attr->node_guid, p);		if (host)			list_add_tail(&host->list, dev_list);	}	ib_set_client_data(device, &srp_client, dev_list);out:	kfree(dev_attr);}static void srp_remove_one(struct ib_device *device){	struct list_head *dev_list;	struct srp_host *host, *tmp_host;	LIST_HEAD(target_list);	struct srp_target_port *target, *tmp_target;	unsigned long flags;	dev_list = ib_get_client_data(device, &srp_client);	list_for_each_entry_safe(host, tmp_host, dev_list, list) {		class_device_unregister(&host->class_dev);		/*		 * Wait for the sysfs entry to go away, so that no new		 * target ports can be created.		 */		wait_for_completion(&host->released);		/*		 * Mark all target ports as removed, so we stop queueing		 * commands and don't try to reconnect.		 */		down(&host->target_mutex);		list_for_each_entry_safe(target, tmp_target,					 &host->target_list, list) {			spin_lock_irqsave(target->scsi_host->host_lock, flags);			if (target->state != SRP_TARGET_REMOVED)				target->state = SRP_TARGET_REMOVED;			spin_unlock_irqrestore(target->scsi_host->host_lock, flags);		}		up(&host->target_mutex);		/*		 * Wait for any reconnection tasks that may have		 * started before we marked our target ports as		 * removed, and any target port removal tasks.		 */		flush_scheduled_work();		list_for_each_entry_safe(target, tmp_target,					 &host->target_list, list) {			scsi_remove_host(target->scsi_host);			srp_disconnect_target(target);			ib_destroy_cm_id(target->cm_id);			srp_free_target_ib(target);			scsi_host_put(target->scsi_host);		}		ib_dereg_mr(host->mr);		ib_dealloc_pd(host->pd);		kfree(host);	}	kfree(dev_list);}static int __init srp_init_module(void){	int ret;	ret = class_register(&srp_class);	if (ret) {		printk(KERN_ERR PFX "couldn't register class infiniband_srp\n");		return ret;	}	ret = ib_register_client(&srp_client);	if (ret) {		printk(KERN_ERR PFX "couldn't register IB client\n");		class_unregister(&srp_class);		return ret;	}	return 0;}static void __exit srp_cleanup_module(void){	ib_unregister_client(&srp_client);	class_unregister(&srp_class);}module_init(srp_init_module);module_exit(srp_cleanup_module);

⌨️ 快捷键说明

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