zfcp_scsi.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 921 行 · 第 1/2 页

C
921
字号
						 adapter, unit, 0);	if (!new_fsf_req) {		ZFCP_LOG_INFO("error: initiation of Abort FCP Cmnd failed\n");		zfcp_scsi_dbf_event_abort("nres", adapter, scpnt, NULL,					  old_fsf_req);		retval = FAILED;		goto out;	}	/* wait for completion of abort */	__wait_event(new_fsf_req->completion_wq,		     new_fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);	/* status should be valid since signals were not permitted */	if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED) {		zfcp_scsi_dbf_event_abort("okay", adapter, scpnt, new_fsf_req,					  NULL);		retval = SUCCESS;	} else if (new_fsf_req->status & ZFCP_STATUS_FSFREQ_ABORTNOTNEEDED) {		zfcp_scsi_dbf_event_abort("lte2", adapter, scpnt, new_fsf_req,					  NULL);		retval = SUCCESS;	} else {		zfcp_scsi_dbf_event_abort("fail", adapter, scpnt, new_fsf_req,					  NULL);		retval = FAILED;	}	zfcp_fsf_req_free(new_fsf_req); out:	return retval;}/* * function:	zfcp_scsi_eh_device_reset_handler * * purpose: * * returns: */intzfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt){	int retval;	struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;	if (!unit) {		ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");		retval = SUCCESS;		goto out;	}	ZFCP_LOG_NORMAL("resetting unit 0x%016Lx\n", unit->fcp_lun);	/*	 * If we do not know whether the unit supports 'logical unit reset'	 * then try 'logical unit reset' and proceed with 'target reset'	 * if 'logical unit reset' fails.	 * If the unit is known not to support 'logical unit reset' then	 * skip 'logical unit reset' and try 'target reset' immediately.	 */	if (!atomic_test_mask(ZFCP_STATUS_UNIT_NOTSUPPUNITRESET,			      &unit->status)) {		retval = zfcp_task_management_function(unit,						       FCP_LOGICAL_UNIT_RESET,						       scpnt);		if (retval) {			ZFCP_LOG_DEBUG("unit reset failed (unit=%p)\n", unit);			if (retval == -ENOTSUPP)				atomic_set_mask				    (ZFCP_STATUS_UNIT_NOTSUPPUNITRESET,				     &unit->status);			/* fall through and try 'target reset' next */		} else {			ZFCP_LOG_DEBUG("unit reset succeeded (unit=%p)\n",				       unit);			/* avoid 'target reset' */			retval = SUCCESS;			goto out;		}	}	retval = zfcp_task_management_function(unit, FCP_TARGET_RESET, scpnt);	if (retval) {		ZFCP_LOG_DEBUG("target reset failed (unit=%p)\n", unit);		retval = FAILED;	} else {		ZFCP_LOG_DEBUG("target reset succeeded (unit=%p)\n", unit);		retval = SUCCESS;	} out:	return retval;}static intzfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags,			      struct scsi_cmnd *scpnt){	struct zfcp_adapter *adapter = unit->port->adapter;	struct zfcp_fsf_req *fsf_req;	int retval = 0;	/* issue task management function */	fsf_req = zfcp_fsf_send_fcp_command_task_management		(adapter, unit, tm_flags, 0);	if (!fsf_req) {		ZFCP_LOG_INFO("error: creation of task management request "			      "failed for unit 0x%016Lx on port 0x%016Lx on  "			      "adapter %s\n", unit->fcp_lun, unit->port->wwpn,			      zfcp_get_busid_by_adapter(adapter));		zfcp_scsi_dbf_event_devreset("nres", tm_flags, unit, scpnt);		retval = -ENOMEM;		goto out;	}	__wait_event(fsf_req->completion_wq,		     fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED);	/*	 * check completion status of task management function	 */	if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {		zfcp_scsi_dbf_event_devreset("fail", tm_flags, unit, scpnt);		retval = -EIO;	} else if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCNOTSUPP) {		zfcp_scsi_dbf_event_devreset("nsup", tm_flags, unit, scpnt);		retval = -ENOTSUPP;	} else		zfcp_scsi_dbf_event_devreset("okay", tm_flags, unit, scpnt);	zfcp_fsf_req_free(fsf_req); out:	return retval;}/** * zfcp_scsi_eh_bus_reset_handler - reset bus (reopen adapter) */intzfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt){	struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata;	struct zfcp_adapter *adapter = unit->port->adapter;	ZFCP_LOG_NORMAL("bus reset because of problems with "			"unit 0x%016Lx\n", unit->fcp_lun);	zfcp_erp_adapter_reopen(adapter, 0);	zfcp_erp_wait(adapter);	return SUCCESS;}/** * zfcp_scsi_eh_host_reset_handler - reset host (reopen adapter) */intzfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt){	struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata;	struct zfcp_adapter *adapter = unit->port->adapter;	ZFCP_LOG_NORMAL("host reset because of problems with "			"unit 0x%016Lx\n", unit->fcp_lun);	zfcp_erp_adapter_reopen(adapter, 0);	zfcp_erp_wait(adapter);	return SUCCESS;}/* * function:	 * * purpose:	 * * returns: */intzfcp_adapter_scsi_register(struct zfcp_adapter *adapter){	int retval = 0;	static unsigned int unique_id = 0;	/* register adapter as SCSI host with mid layer of SCSI stack */	adapter->scsi_host = scsi_host_alloc(&zfcp_data.scsi_host_template,					     sizeof (struct zfcp_adapter *));	if (!adapter->scsi_host) {		ZFCP_LOG_NORMAL("error: registration with SCSI stack failed "				"for adapter %s ",				zfcp_get_busid_by_adapter(adapter));		retval = -EIO;		goto out;	}	ZFCP_LOG_DEBUG("host registered, scsi_host=%p\n", adapter->scsi_host);	/* tell the SCSI stack some characteristics of this adapter */	adapter->scsi_host->max_id = 1;	adapter->scsi_host->max_lun = 1;	adapter->scsi_host->max_channel = 0;	adapter->scsi_host->unique_id = unique_id++;	/* FIXME */	adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH;	adapter->scsi_host->transportt = zfcp_transport_template;	/*	 * Reverse mapping of the host number to avoid race condition	 */	adapter->scsi_host_no = adapter->scsi_host->host_no;	/*	 * save a pointer to our own adapter data structure within	 * hostdata field of SCSI host data structure	 */	adapter->scsi_host->hostdata[0] = (unsigned long) adapter;	if (scsi_add_host(adapter->scsi_host, &adapter->ccw_device->dev)) {		scsi_host_put(adapter->scsi_host);		retval = -EIO;		goto out;	}	atomic_set_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status); out:	return retval;}/* * function:	 * * purpose:	 * * returns: */voidzfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter){	struct Scsi_Host *shost;	struct zfcp_port *port;	shost = adapter->scsi_host;	if (!shost)		return;	read_lock_irq(&zfcp_data.config_lock);	list_for_each_entry(port, &adapter->port_list_head, list)		if (port->rport)			port->rport = NULL;	read_unlock_irq(&zfcp_data.config_lock);	fc_remove_host(shost);	scsi_remove_host(shost);	scsi_host_put(shost);	adapter->scsi_host = NULL;	adapter->scsi_host_no = 0;	atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status);	return;}voidzfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter){	adapter->scsi_er_timer.function = zfcp_fsf_scsi_er_timeout_handler;	adapter->scsi_er_timer.data = (unsigned long) adapter;	adapter->scsi_er_timer.expires = jiffies + ZFCP_SCSI_ER_TIMEOUT;	add_timer(&adapter->scsi_er_timer);}/* * Support functions for FC transport class */static struct fc_host_statistics*zfcp_init_fc_host_stats(struct zfcp_adapter *adapter){	struct fc_host_statistics *fc_stats;	if (!adapter->fc_stats) {		fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL);		if (!fc_stats)			return NULL;		adapter->fc_stats = fc_stats; /* freed in adater_dequeue */	}	memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats));	return adapter->fc_stats;}static voidzfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats,			  struct fsf_qtcb_bottom_port *data,			  struct fsf_qtcb_bottom_port *old){	fc_stats->seconds_since_last_reset = data->seconds_since_last_reset -		old->seconds_since_last_reset;	fc_stats->tx_frames = data->tx_frames - old->tx_frames;	fc_stats->tx_words = data->tx_words - old->tx_words;	fc_stats->rx_frames = data->rx_frames - old->rx_frames;	fc_stats->rx_words = data->rx_words - old->rx_words;	fc_stats->lip_count = data->lip - old->lip;	fc_stats->nos_count = data->nos - old->nos;	fc_stats->error_frames = data->error_frames - old->error_frames;	fc_stats->dumped_frames = data->dumped_frames - old->dumped_frames;	fc_stats->link_failure_count = data->link_failure - old->link_failure;	fc_stats->loss_of_sync_count = data->loss_of_sync - old->loss_of_sync;	fc_stats->loss_of_signal_count = data->loss_of_signal -		old->loss_of_signal;	fc_stats->prim_seq_protocol_err_count = data->psp_error_counts -		old->psp_error_counts;	fc_stats->invalid_tx_word_count = data->invalid_tx_words -		old->invalid_tx_words;	fc_stats->invalid_crc_count = data->invalid_crcs - old->invalid_crcs;	fc_stats->fcp_input_requests = data->input_requests -		old->input_requests;	fc_stats->fcp_output_requests = data->output_requests -		old->output_requests;	fc_stats->fcp_control_requests = data->control_requests -		old->control_requests;	fc_stats->fcp_input_megabytes = data->input_mb - old->input_mb;	fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb;}static voidzfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats,		       struct fsf_qtcb_bottom_port *data){	fc_stats->seconds_since_last_reset = data->seconds_since_last_reset;	fc_stats->tx_frames = data->tx_frames;	fc_stats->tx_words = data->tx_words;	fc_stats->rx_frames = data->rx_frames;	fc_stats->rx_words = data->rx_words;	fc_stats->lip_count = data->lip;	fc_stats->nos_count = data->nos;	fc_stats->error_frames = data->error_frames;	fc_stats->dumped_frames = data->dumped_frames;	fc_stats->link_failure_count = data->link_failure;	fc_stats->loss_of_sync_count = data->loss_of_sync;	fc_stats->loss_of_signal_count = data->loss_of_signal;	fc_stats->prim_seq_protocol_err_count = data->psp_error_counts;	fc_stats->invalid_tx_word_count = data->invalid_tx_words;	fc_stats->invalid_crc_count = data->invalid_crcs;	fc_stats->fcp_input_requests = data->input_requests;	fc_stats->fcp_output_requests = data->output_requests;	fc_stats->fcp_control_requests = data->control_requests;	fc_stats->fcp_input_megabytes = data->input_mb;	fc_stats->fcp_output_megabytes = data->output_mb;}/** * zfcp_get_fc_host_stats - provide fc_host_statistics for scsi_transport_fc * * assumption: scsi_transport_fc synchronizes calls of *             get_fc_host_stats and reset_fc_host_stats *             (XXX to be checked otherwise introduce locking) */static struct fc_host_statistics *zfcp_get_fc_host_stats(struct Scsi_Host *shost){	struct zfcp_adapter *adapter;	struct fc_host_statistics *fc_stats;	struct fsf_qtcb_bottom_port *data;	int ret;	adapter = (struct zfcp_adapter *)shost->hostdata[0];	fc_stats = zfcp_init_fc_host_stats(adapter);	if (!fc_stats)		return NULL;	data = kmalloc(sizeof(*data), GFP_KERNEL);	if (!data)		return NULL;	memset(data, 0, sizeof(*data));	ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);	if (ret) {		kfree(data);		return NULL; /* XXX return zeroed fc_stats? */	}	if (adapter->stats_reset &&	    ((jiffies/HZ - adapter->stats_reset) <	     data->seconds_since_last_reset)) {		zfcp_adjust_fc_host_stats(fc_stats, data,					  adapter->stats_reset_data);	} else		zfcp_set_fc_host_stats(fc_stats, data);	kfree(data);	return fc_stats;}static voidzfcp_reset_fc_host_stats(struct Scsi_Host *shost){	struct zfcp_adapter *adapter;	struct fsf_qtcb_bottom_port *data, *old_data;	int ret;	adapter = (struct zfcp_adapter *)shost->hostdata[0];	data = kmalloc(sizeof(*data), GFP_KERNEL);	if (!data)		return;	memset(data, 0, sizeof(*data));	ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);	if (ret == 0) {		adapter->stats_reset = jiffies/HZ;		old_data = adapter->stats_reset_data;		adapter->stats_reset_data = data; /* finally freed in						     adater_dequeue */		kfree(old_data);	}}struct fc_function_template zfcp_transport_functions = {	.show_starget_port_id = 1,	.show_starget_port_name = 1,	.show_starget_node_name = 1,	.show_rport_supported_classes = 1,	.show_host_node_name = 1,	.show_host_port_name = 1,	.show_host_permanent_port_name = 1,	.show_host_supported_classes = 1,	.show_host_supported_speeds = 1,	.show_host_maxframe_size = 1,	.show_host_serial_number = 1,	.get_fc_host_stats = zfcp_get_fc_host_stats,	.reset_fc_host_stats = zfcp_reset_fc_host_stats,	/* no functions registered for following dynamic attributes but	   directly set by LLDD */	.show_host_port_type = 1,	.show_host_speed = 1,	.show_host_port_id = 1,};/** * ZFCP_DEFINE_SCSI_ATTR * @_name:   name of show attribute * @_format: format string * @_value:  value to print * * Generates attribute for a unit. */#define ZFCP_DEFINE_SCSI_ATTR(_name, _format, _value)                    \static ssize_t zfcp_sysfs_scsi_##_name##_show(struct device *dev, struct device_attribute *attr,        \                                              char *buf)                 \{                                                                        \        struct scsi_device *sdev;                                        \        struct zfcp_unit *unit;                                          \                                                                         \        sdev = to_scsi_device(dev);                                      \        unit = sdev->hostdata;                                           \        return sprintf(buf, _format, _value);                            \}                                                                        \                                                                         \static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_scsi_##_name##_show, NULL);ZFCP_DEFINE_SCSI_ATTR(hba_id, "%s\n", zfcp_get_busid_by_unit(unit));ZFCP_DEFINE_SCSI_ATTR(wwpn, "0x%016llx\n", unit->port->wwpn);ZFCP_DEFINE_SCSI_ATTR(fcp_lun, "0x%016llx\n", unit->fcp_lun);static struct device_attribute *zfcp_sysfs_sdev_attrs[] = {	&dev_attr_fcp_lun,	&dev_attr_wwpn,	&dev_attr_hba_id,	NULL};#undef ZFCP_LOG_AREA

⌨️ 快捷键说明

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