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

📄 zfcp_aux.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * * linux/drivers/s390/scsi/zfcp_aux.c * * FCP adapter driver for IBM eServer zSeries * * (C) Copyright IBM Corp. 2002, 2004 * * Author(s): Martin Peschke <mpeschke@de.ibm.com> *            Raimund Schroeder <raimund.schroeder@de.ibm.com> *            Aron Zeh *            Wolfgang Taphorn *            Stefan Bader <stefan.bader@de.ibm.com> *            Heiko Carstens <heiko.carstens@de.ibm.com> *            Andreas Herrmann <aherrman@de.ibm.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#define ZFCP_AUX_REVISION "$Revision: 1.145 $"#include "zfcp_ext.h"/* accumulated log level (module parameter) */static u32 loglevel = ZFCP_LOG_LEVEL_DEFAULTS;static char *device;/*********************** FUNCTION PROTOTYPES *********************************//* written against the module interface */static int __init  zfcp_module_init(void);/* FCP related */static void zfcp_ns_gid_pn_handler(unsigned long);/* miscellaneous */static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);static inline void zfcp_sg_list_free(struct zfcp_sg_list *);static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,					      void __user *, size_t);static inline int zfcp_sg_list_copy_to_user(void __user *,					    struct zfcp_sg_list *, size_t);static long zfcp_cfdc_dev_ioctl(struct file *, unsigned int, unsigned long);#define ZFCP_CFDC_IOC_MAGIC                     0xDD#define ZFCP_CFDC_IOC \	_IOWR(ZFCP_CFDC_IOC_MAGIC, 0, struct zfcp_cfdc_sense_data)static struct file_operations zfcp_cfdc_fops = {	.unlocked_ioctl = zfcp_cfdc_dev_ioctl,#ifdef CONFIG_COMPAT	.compat_ioctl = zfcp_cfdc_dev_ioctl#endif};static struct miscdevice zfcp_cfdc_misc = {	.minor = ZFCP_CFDC_DEV_MINOR,	.name = ZFCP_CFDC_DEV_NAME,	.fops = &zfcp_cfdc_fops};/*********************** KERNEL/MODULE PARAMETERS  ***************************//* declare driver module init/cleanup functions */module_init(zfcp_module_init);MODULE_AUTHOR("Heiko Carstens <heiko.carstens@de.ibm.com>, "	      "Andreas Herrman <aherrman@de.ibm.com>, "	      "Martin Peschke <mpeschke@de.ibm.com>, "	      "Raimund Schroeder <raimund.schroeder@de.ibm.com>, "	      "Wolfgang Taphorn <taphorn@de.ibm.com>, "	      "Aron Zeh <arzeh@de.ibm.com>, "	      "IBM Deutschland Entwicklung GmbH");MODULE_DESCRIPTION    ("FCP (SCSI over Fibre Channel) HBA driver for IBM eServer zSeries");MODULE_LICENSE("GPL");module_param(device, charp, 0400);MODULE_PARM_DESC(device, "specify initial device");module_param(loglevel, uint, 0400);MODULE_PARM_DESC(loglevel,		 "log levels, 8 nibbles: "		 "FC ERP QDIO CIO Config FSF SCSI Other, "		 "levels: 0=none 1=normal 2=devel 3=trace");/****************************************************************//************** Functions without logging ***********************//****************************************************************/void_zfcp_hex_dump(char *addr, int count){	int i;	for (i = 0; i < count; i++) {		printk("%02x", addr[i]);		if ((i % 4) == 3)			printk(" ");		if ((i % 32) == 31)			printk("\n");	}	if (((i-1) % 32) != 31)		printk("\n");}/****************************************************************//************** Uncategorised Functions *************************//****************************************************************/#define ZFCP_LOG_AREA			ZFCP_LOG_AREA_OTHER/** * zfcp_device_setup - setup function * @str: pointer to parameter string * * Parse "device=..." parameter string. */static int __initzfcp_device_setup(char *devstr){	char *tmp, *str;	size_t len;	if (!devstr)		return 0;	len = strlen(devstr) + 1;	str = (char *) kmalloc(len, GFP_KERNEL);	if (!str)		goto err_out;	memcpy(str, devstr, len);	tmp = strchr(str, ',');	if (!tmp)		goto err_out;	*tmp++ = '\0';	strncpy(zfcp_data.init_busid, str, BUS_ID_SIZE);	zfcp_data.init_busid[BUS_ID_SIZE-1] = '\0';	zfcp_data.init_wwpn = simple_strtoull(tmp, &tmp, 0);	if (*tmp++ != ',')		goto err_out;	if (*tmp == '\0')		goto err_out;	zfcp_data.init_fcp_lun = simple_strtoull(tmp, &tmp, 0);	if (*tmp != '\0')		goto err_out;	kfree(str);	return 1; err_out:	ZFCP_LOG_NORMAL("Parse error for device parameter string %s\n", str);	kfree(str);	return 0;}static void __initzfcp_init_device_configure(void){	struct zfcp_adapter *adapter;	struct zfcp_port *port;	struct zfcp_unit *unit;	down(&zfcp_data.config_sema);	read_lock_irq(&zfcp_data.config_lock);	adapter = zfcp_get_adapter_by_busid(zfcp_data.init_busid);	if (adapter)		zfcp_adapter_get(adapter);	read_unlock_irq(&zfcp_data.config_lock);	if (adapter == NULL)		goto out_adapter;	port = zfcp_port_enqueue(adapter, zfcp_data.init_wwpn, 0, 0);	if (!port)		goto out_port;	unit = zfcp_unit_enqueue(port, zfcp_data.init_fcp_lun);	if (!unit)		goto out_unit;	up(&zfcp_data.config_sema);	ccw_device_set_online(adapter->ccw_device);	zfcp_erp_wait(adapter);	down(&zfcp_data.config_sema);	zfcp_unit_put(unit); out_unit:	zfcp_port_put(port); out_port:	zfcp_adapter_put(adapter); out_adapter:	up(&zfcp_data.config_sema);	return;}static int __initzfcp_module_init(void){	int retval = 0;	atomic_set(&zfcp_data.loglevel, loglevel);	/* initialize adapter list */	INIT_LIST_HEAD(&zfcp_data.adapter_list_head);	/* initialize adapters to be removed list head */	INIT_LIST_HEAD(&zfcp_data.adapter_remove_lh);	zfcp_transport_template = fc_attach_transport(&zfcp_transport_functions);	if (!zfcp_transport_template)		return -ENODEV;	retval = misc_register(&zfcp_cfdc_misc);	if (retval != 0) {		ZFCP_LOG_INFO("registration of misc device "			      "zfcp_cfdc failed\n");		goto out;	}	ZFCP_LOG_TRACE("major/minor for zfcp_cfdc: %d/%d\n",		       ZFCP_CFDC_DEV_MAJOR, zfcp_cfdc_misc.minor);	/* Initialise proc semaphores */	sema_init(&zfcp_data.config_sema, 1);	/* initialise configuration rw lock */	rwlock_init(&zfcp_data.config_lock);	/* save address of data structure managing the driver module */	zfcp_data.scsi_host_template.module = THIS_MODULE;	/* setup dynamic I/O */	retval = zfcp_ccw_register();	if (retval) {		ZFCP_LOG_NORMAL("registration with common I/O layer failed\n");		goto out_ccw_register;	}	if (zfcp_device_setup(device))		zfcp_init_device_configure();	goto out; out_ccw_register:	misc_deregister(&zfcp_cfdc_misc); out:	return retval;}/* * function:    zfcp_cfdc_dev_ioctl * * purpose:     Handle control file upload/download transaction via IOCTL *		interface * * returns:     0           - Operation completed successfuly *              -ENOTTY     - Unknown IOCTL command *              -EINVAL     - Invalid sense data record *              -ENXIO      - The FCP adapter is not available *              -EOPNOTSUPP - The FCP adapter does not have CFDC support *              -ENOMEM     - Insufficient memory *              -EFAULT     - User space memory I/O operation fault *              -EPERM      - Cannot create or queue FSF request or create SBALs *              -ERESTARTSYS- Received signal (is mapped to EAGAIN by VFS) */static longzfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,		    unsigned long buffer){	struct zfcp_cfdc_sense_data *sense_data, __user *sense_data_user;	struct zfcp_adapter *adapter = NULL;	struct zfcp_fsf_req *fsf_req = NULL;	struct zfcp_sg_list *sg_list = NULL;	u32 fsf_command, option;	char *bus_id = NULL;	int retval = 0;	sense_data = kmalloc(sizeof(struct zfcp_cfdc_sense_data), GFP_KERNEL);	if (sense_data == NULL) {		retval = -ENOMEM;		goto out;	}	sg_list = kmalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL);	if (sg_list == NULL) {		retval = -ENOMEM;		goto out;	}	memset(sg_list, 0, sizeof(*sg_list));	if (command != ZFCP_CFDC_IOC) {		ZFCP_LOG_INFO("IOC request code 0x%x invalid\n", command);		retval = -ENOTTY;		goto out;	}	if ((sense_data_user = (void __user *) buffer) == NULL) {		ZFCP_LOG_INFO("sense data record is required\n");		retval = -EINVAL;		goto out;	}	retval = copy_from_user(sense_data, sense_data_user,				sizeof(struct zfcp_cfdc_sense_data));	if (retval) {		retval = -EFAULT;		goto out;	}	if (sense_data->signature != ZFCP_CFDC_SIGNATURE) {		ZFCP_LOG_INFO("invalid sense data request signature 0x%08x\n",			      ZFCP_CFDC_SIGNATURE);		retval = -EINVAL;		goto out;	}	switch (sense_data->command) {	case ZFCP_CFDC_CMND_DOWNLOAD_NORMAL:		fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;		option = FSF_CFDC_OPTION_NORMAL_MODE;		break;	case ZFCP_CFDC_CMND_DOWNLOAD_FORCE:		fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;		option = FSF_CFDC_OPTION_FORCE;		break;	case ZFCP_CFDC_CMND_FULL_ACCESS:		fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;		option = FSF_CFDC_OPTION_FULL_ACCESS;		break;	case ZFCP_CFDC_CMND_RESTRICTED_ACCESS:		fsf_command = FSF_QTCB_DOWNLOAD_CONTROL_FILE;		option = FSF_CFDC_OPTION_RESTRICTED_ACCESS;		break;	case ZFCP_CFDC_CMND_UPLOAD:		fsf_command = FSF_QTCB_UPLOAD_CONTROL_FILE;		option = 0;		break;	default:		ZFCP_LOG_INFO("invalid command code 0x%08x\n",			      sense_data->command);		retval = -EINVAL;		goto out;	}	bus_id = kmalloc(BUS_ID_SIZE, GFP_KERNEL);	if (bus_id == NULL) {		retval = -ENOMEM;		goto out;	}	snprintf(bus_id, BUS_ID_SIZE, "%d.%d.%04x",		(sense_data->devno >> 24),		(sense_data->devno >> 16) & 0xFF,		(sense_data->devno & 0xFFFF));	read_lock_irq(&zfcp_data.config_lock);	adapter = zfcp_get_adapter_by_busid(bus_id);	if (adapter)		zfcp_adapter_get(adapter);	read_unlock_irq(&zfcp_data.config_lock);	kfree(bus_id);	if (adapter == NULL) {		ZFCP_LOG_INFO("invalid adapter\n");		retval = -ENXIO;		goto out;	}	if (sense_data->command & ZFCP_CFDC_WITH_CONTROL_FILE) {		retval = zfcp_sg_list_alloc(sg_list,					    ZFCP_CFDC_MAX_CONTROL_FILE_SIZE);		if (retval) {			retval = -ENOMEM;			goto out;		}	}	if ((sense_data->command & ZFCP_CFDC_DOWNLOAD) &&	    (sense_data->command & ZFCP_CFDC_WITH_CONTROL_FILE)) {		retval = zfcp_sg_list_copy_from_user(			sg_list, &sense_data_user->control_file,			ZFCP_CFDC_MAX_CONTROL_FILE_SIZE);		if (retval) {			retval = -EFAULT;			goto out;		}	}	retval = zfcp_fsf_control_file(adapter, &fsf_req, fsf_command,				       option, sg_list);	if (retval)		goto out;	if ((fsf_req->qtcb->prefix.prot_status != FSF_PROT_GOOD) &&	    (fsf_req->qtcb->prefix.prot_status != FSF_PROT_FSF_STATUS_PRESENTED)) {		retval = -ENXIO;		goto out;	}	sense_data->fsf_status = fsf_req->qtcb->header.fsf_status;	memcpy(&sense_data->fsf_status_qual,	       &fsf_req->qtcb->header.fsf_status_qual,	       sizeof(union fsf_status_qual));	memcpy(&sense_data->payloads, &fsf_req->qtcb->bottom.support.els, 256);	retval = copy_to_user(sense_data_user, sense_data,		sizeof(struct zfcp_cfdc_sense_data));	if (retval) {		retval = -EFAULT;		goto out;	}	if (sense_data->command & ZFCP_CFDC_UPLOAD) {		retval = zfcp_sg_list_copy_to_user(			&sense_data_user->control_file, sg_list,			ZFCP_CFDC_MAX_CONTROL_FILE_SIZE);		if (retval) {			retval = -EFAULT;			goto out;		}	} out:	if (fsf_req != NULL)		zfcp_fsf_req_free(fsf_req);	if ((adapter != NULL) && (retval != -ENXIO))		zfcp_adapter_put(adapter);

⌨️ 快捷键说明

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