Skip to contentSkip to conversation

zfcp update

PATCH In review Christof Schmitt 3 participants 12 messages Jun 10, 2008 – Jun 11, 2008

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover zfcp update

James,

here is a large update for zfcp. The patch series cleans up parts of the code in the driver, removes the driver specific message macros and removes unnecessary debug messages. FC ports are now automatically attached and the port_state attribute is added in the FC host sysfs.

The patches apply to current scsi-misc.

Christof

#1 lore raw

PATCH 1/8 zfcp: Move FC code to new file

From: Christof Schmitt <[email protected]>

Move all Fibre Channel related code to new file and cleanup the code while doing so.

---
 drivers/s390/scsi/Makefile   |    2 
 drivers/s390/scsi/zfcp_aux.c |  518 -------------------------------------------
 drivers/s390/scsi/zfcp_dbf.c |    4 
 drivers/s390/scsi/zfcp_def.h |    8 
 drivers/s390/scsi/zfcp_erp.c |  188 ---------------
 drivers/s390/scsi/zfcp_ext.h |   12 
 drivers/s390/scsi/zfcp_fc.c  |  305 +++++++++++++++++++++++++
 drivers/s390/scsi/zfcp_fsf.c |    8 
 8 files changed, 319 insertions(+), 726 deletions(-)
drivers/s390/scsi/Makefile +1 -1
@@ -4,6 +4,6 @@
 
 zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \
 	     zfcp_fsf.o zfcp_dbf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \
-	     zfcp_sysfs_unit.o zfcp_sysfs_driver.o
+	     zfcp_sysfs_unit.o zfcp_sysfs_driver.o zfcp_fc.o
 
 obj-$(CONFIG_ZFCP) += zfcp.o
drivers/s390/scsi/zfcp_aux.c +0 -518

527 lines not on this page · raw message

drivers/s390/scsi/zfcp_fc.c new file +305 -0

305 lines not on this page · raw message

drivers/s390/scsi/zfcp_erp.c +1 -187

206 lines not on this page · raw message

drivers/s390/scsi/zfcp_ext.h +5 -7
@@ -103,7 +103,6 @@ extern int  zfcp_fsf_send_fcp_command_ta
 					   struct zfcp_unit *,
 					   struct scsi_cmnd *, int, int);
 extern int  zfcp_fsf_req_complete(struct zfcp_fsf_req *);
-extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *);
 extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
 extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_command_task_management(
 	struct zfcp_adapter *, struct zfcp_unit *, u8, int);
@@ -111,11 +110,12 @@ extern struct zfcp_fsf_req *zfcp_fsf_abo
 	unsigned long, struct zfcp_adapter *, struct zfcp_unit *, int);
 
 /******************************* FC/FCP **************************************/
+extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *);
+extern int  zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *);
+extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
+extern void  zfcp_test_link(struct zfcp_port *);
+
 extern int  zfcp_nameserver_enqueue(struct zfcp_adapter *);
-extern int  zfcp_ns_gid_pn_request(struct zfcp_erp_action *);
-extern int  zfcp_check_ct_response(struct ct_hdr *);
-extern int  zfcp_handle_els_rjt(u32, struct zfcp_ls_rjt_par *);
-extern void zfcp_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
 
 /******************************* SCSI ****************************************/
 extern int  zfcp_adapter_scsi_register(struct zfcp_adapter *);
@@ -158,8 +158,6 @@ extern int  zfcp_erp_thread_kill(struct 
 extern int  zfcp_erp_wait(struct zfcp_adapter *);
 extern void zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long);
 
-extern int  zfcp_test_link(struct zfcp_port *);
-
 extern void zfcp_erp_port_boxed(struct zfcp_port *, u8 id, void *ref);
 extern void zfcp_erp_unit_boxed(struct zfcp_unit *, u8 id, void *ref);
 extern void zfcp_erp_port_access_denied(struct zfcp_port *, u8 id, void *ref);
drivers/s390/scsi/zfcp_fsf.c +2 -6
@@ -848,7 +848,7 @@ zfcp_fsf_status_read_handler(struct zfcp
 		break;
 
 	case FSF_STATUS_READ_INCOMING_ELS:
-		zfcp_fsf_incoming_els(fsf_req);
+		zfcp_fc_incoming_els(fsf_req);
 		break;
 
 	case FSF_STATUS_READ_SENSE_DATA_AVAIL:
@@ -1742,10 +1742,6 @@ static int zfcp_fsf_send_els_handler(str
 			break;
 		case FSF_SQ_ULP_DEPENDENT_ERP_REQUIRED:
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
-			retval =
-			  zfcp_handle_els_rjt(header->fsf_status_qual.word[1],
-					      (struct zfcp_ls_rjt_par *)
-					      &header->fsf_status_qual.word[2]);
 			break;
 		case FSF_SQ_RETRY_IF_POSSIBLE:
 			fsf_req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -2534,7 +2530,7 @@ zfcp_fsf_open_port_handler(struct zfcp_f
 						&port->status);
 				} else {
 					port->wwnn = plogi->serv_param.wwnn;
-					zfcp_plogi_evaluate(port, plogi);
+					zfcp_fc_plogi_evaluate(port, plogi);
 				}
 			}
 		}
drivers/s390/scsi/zfcp_def.h +3 -5
@@ -223,9 +223,9 @@ struct fcp_rsp_iu {
 #define RSP_CODE_TASKMAN_FAILED	 5
 
 /* see fc-fs */
-#define LS_RSCN  0x61040000
-#define LS_LOGO  0x05000000
-#define LS_PLOGI 0x03000000
+#define LS_RSCN  0x61
+#define LS_LOGO  0x05
+#define LS_PLOGI 0x03
 
 struct fcp_rscn_head {
         u8  command;
@@ -622,7 +622,6 @@ typedef void (*zfcp_send_ct_handler_t)(u
  * @resp_count: number of elements in response scatter-gather list
  * @handler: handler function (called for response to the request)
  * @handler_data: data passed to handler function
- * @pool: pointer to memory pool for ct request structure
  * @timeout: FSF timeout for this request
  * @completion: completion for synchronization purposes
  * @status: used to pass error status to calling function
@@ -635,7 +634,6 @@ struct zfcp_send_ct {
 	unsigned int resp_count;
 	zfcp_send_ct_handler_t handler;
 	unsigned long handler_data;
-	mempool_t *pool;
 	int timeout;
 	struct completion *completion;
 	int status;
drivers/s390/scsi/zfcp_dbf.c +2 -2
@@ -546,8 +546,8 @@ static const char *zfcp_rec_dbf_ids[] = 
 	[80]	= "exclusive read-only unit access unsupported",
 	[81]	= "shared read-write unit access unsupported",
 	[82]	= "incoming rscn",
-	[83]	= "incoming plogi",
-	[84]	= "incoming logo",
+	[83]	= "incoming wwpn",
+	[84]	= "",
 	[85]	= "online",
 	[86]	= "offline",
 	[87]	= "ccw device gone",
#2 lore raw

PATCH 2/8 zfcp: Move CFDC code to new file.

In reply to Christof Schmitt

From: Christof Schmitt <[email protected]>

zfcp implements a device file to allow Linux guests changing the Access Control Tables stored in the adapter. The code for the device file has nothing to do with the other parts of the driver, so move it to a new file and cleanup the code while doing so.

---
 drivers/s390/scsi/Makefile    |    2 
 drivers/s390/scsi/zfcp_aux.c  |  425 ++----------------------------------------
 drivers/s390/scsi/zfcp_cfdc.c |  259 +++++++++++++++++++++++++
 drivers/s390/scsi/zfcp_def.h  |   43 ----
 drivers/s390/scsi/zfcp_ext.h  |    8 
 drivers/s390/scsi/zfcp_fsf.c  |  244 ++----------------------
 drivers/s390/scsi/zfcp_fsf.h  |   12 +
 7 files changed, 330 insertions(+), 663 deletions(-)
drivers/s390/scsi/zfcp_aux.c +29 -396
@@ -33,6 +33,7 @@
  *            Ralph Wuerthner
  */
 
+#include <linux/miscdevice.h>
 #include "zfcp_ext.h"
 
 /* accumulated log level (module parameter) */
@@ -43,33 +44,6 @@ static char *device;
 /* written against the module interface */
 static int __init  zfcp_module_init(void);
 
-/* miscellaneous */
-static int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
-static void zfcp_sg_list_free(struct zfcp_sg_list *);
-static int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
-				       void __user *, size_t);
-static 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 const 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 */
@@ -294,9 +268,6 @@ zfcp_module_init(void)
 		goto out_misc;
 	}
 
-	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);
 
@@ -329,372 +300,6 @@ zfcp_module_init(void)
 	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 long
-zfcp_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 = kzalloc(sizeof(struct zfcp_sg_list), GFP_KERNEL);
-	if (sg_list == NULL) {
-		retval = -ENOMEM;
-		goto out;
-	}
-
-	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);
-
-	if (sg_list != NULL) {
-		zfcp_sg_list_free(sg_list);
-		kfree(sg_list);
-	}
-
-	kfree(sense_data);
-
-	return retval;
-}
-
-
-/**
- * zfcp_sg_list_alloc - create a scatter-gather list of the specified size
- * @sg_list: structure describing a scatter gather list
- * @size: size of scatter-gather list
- * Return: 0 on success, else -ENOMEM
- *
- * In sg_list->sg a pointer to the created scatter-gather list is returned,
- * or NULL if we run out of memory. sg_list->count specifies the number of
- * elements of the scatter-gather list. The maximum size of a single element
- * in the scatter-gather list is PAGE_SIZE.
- */
-static int
-zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
-{
-	struct scatterlist *sg;
-	unsigned int i;
-	int retval = 0;
-	void *address;
-
-	BUG_ON(sg_list == NULL);
-
-	sg_list->count = size >> PAGE_SHIFT;
-	if (size & ~PAGE_MASK)
-		sg_list->count++;
-	sg_list->sg = kcalloc(sg_list->count, sizeof(struct scatterlist),
-			      GFP_KERNEL);
-	if (sg_list->sg == NULL) {
-		sg_list->count = 0;
-		retval = -ENOMEM;
-		goto out;
-	}
-	sg_init_table(sg_list->sg, sg_list->count);
-
-	for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) {
-		address = (void *) get_zeroed_page(GFP_KERNEL);
-		if (address == NULL) {
-			sg_list->count = i;
-			zfcp_sg_list_free(sg_list);
-			retval = -ENOMEM;
-			goto out;
-		}
-		zfcp_address_to_sg(address, sg, min(size, PAGE_SIZE));
-		size -= sg->length;
-	}
-
- out:
-	return retval;
-}
-
-
-/**
- * zfcp_sg_list_free - free memory of a scatter-gather list
- * @sg_list: structure describing a scatter-gather list
- *
- * Memory for each element in the scatter-gather list is freed.
- * Finally sg_list->sg is freed itself and sg_list->count is reset.
- */
-static void
-zfcp_sg_list_free(struct zfcp_sg_list *sg_list)
-{
-	struct scatterlist *sg;
-	unsigned int i;
-
-	BUG_ON(sg_list == NULL);
-
-	for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++)
-		free_page((unsigned long) zfcp_sg_to_address(sg));
-
-	sg_list->count = 0;
-	kfree(sg_list->sg);
-}
-
-/**
- * zfcp_sg_size - determine size of a scatter-gather list
- * @sg: array of (struct scatterlist)
- * @sg_count: elements in array
- * Return: size of entire scatter-gather list
- */
-static size_t zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count)
-{
-	unsigned int i;
-	struct scatterlist *p;
-	size_t size;
-
-	size = 0;
-	for (i = 0, p = sg; i < sg_count; i++, p++) {
-		BUG_ON(p == NULL);
-		size += p->length;
-	}
-
-	return size;
-}
-
-
-/**
- * zfcp_sg_list_copy_from_user -copy data from user space to scatter-gather list
- * @sg_list: structure describing a scatter-gather list
- * @user_buffer: pointer to buffer in user space
- * @size: number of bytes to be copied
- * Return: 0 on success, -EFAULT if copy_from_user fails.
- */
-static int
-zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list,
-			    void __user *user_buffer,
-                            size_t size)
-{
-	struct scatterlist *sg;
-	unsigned int length;
-	void *zfcp_buffer;
-	int retval = 0;
-
-	BUG_ON(sg_list == NULL);
-
-	if (zfcp_sg_size(sg_list->sg, sg_list->count) < size)
-		return -EFAULT;
-
-	for (sg = sg_list->sg; size > 0; sg++) {
-		length = min((unsigned int)size, sg->length);
-		zfcp_buffer = zfcp_sg_to_address(sg);
-		if (copy_from_user(zfcp_buffer, user_buffer, length)) {
-			retval = -EFAULT;
-			goto out;
-		}
-		user_buffer += length;
-		size -= length;
-	}
-
- out:
-	return retval;
-}
-
-
-/**
- * zfcp_sg_list_copy_to_user - copy data from scatter-gather list to user space
- * @user_buffer: pointer to buffer in user space
- * @sg_list: structure describing a scatter-gather list
- * @size: number of bytes to be copied
- * Return: 0 on success, -EFAULT if copy_to_user fails
- */
-static int
-zfcp_sg_list_copy_to_user(void __user  *user_buffer,
-			  struct zfcp_sg_list *sg_list,
-                          size_t size)
-{
-	struct scatterlist *sg;
-	unsigned int length;
-	void *zfcp_buffer;
-	int retval = 0;
-
-	BUG_ON(sg_list == NULL);
-
-	if (zfcp_sg_size(sg_list->sg, sg_list->count) < size)
-		return -EFAULT;
-
-	for (sg = sg_list->sg; size > 0; sg++) {
-		length = min((unsigned int) size, sg->length);
-		zfcp_buffer = zfcp_sg_to_address(sg);
-		if (copy_to_user(user_buffer, zfcp_buffer, length)) {
-			retval = -EFAULT;
-			goto out;
-		}
-		user_buffer += length;
-		size -= length;
-	}
-
- out:
-	return retval;
-}
-
-
 #undef ZFCP_LOG_AREA
 
 /****************************************************************/
@@ -1345,4 +950,32 @@ zfcp_nameserver_enqueue(struct zfcp_adap
 	return 0;
 }
 
+void zfcp_sg_free_table(struct scatterlist *sg, int count)
+{
+	int i;
+
+	for (i = 0; i < count; i++, sg++)
+		if (sg)
+			free_page((unsigned long) sg_virt(sg));
+		else
+			break;
+}
+
+int zfcp_sg_setup_table(struct scatterlist *sg, int count)
+{
+	void *addr;
+	int i;
+
+	sg_init_table(sg, count);
+	for (i = 0; i < count; i++, sg++) {
+		addr = (void *) get_zeroed_page(GFP_KERNEL);
+		if (!addr) {
+			zfcp_sg_free_table(sg, i);
+			return -ENOMEM;
+		}
+		sg_set_buf(sg, addr, PAGE_SIZE);
+	}
+	return 0;
+}
+
 #undef ZFCP_LOG_AREA
drivers/s390/scsi/zfcp_ext.h +6 -2
@@ -86,8 +86,8 @@ extern int  zfcp_fsf_exchange_config_dat
 extern int  zfcp_fsf_exchange_port_data(struct zfcp_erp_action *);
 extern int  zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *,
                                              struct fsf_qtcb_bottom_port *);
-extern int  zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **,
-				  u32, u32, struct zfcp_sg_list *);
+extern struct zfcp_fsf_req *zfcp_fsf_control_file(struct zfcp_adapter *adapter,
+					   struct zfcp_fsf_cfdc *fsf_cfdc);
 extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long);
 extern void zfcp_erp_start_timer(struct zfcp_fsf_req *);
 extern void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *);
@@ -167,6 +167,8 @@ extern void zfcp_erp_port_access_changed
 extern void zfcp_erp_unit_access_changed(struct zfcp_unit *, u8, void *);
 
 /******************************** AUX ****************************************/
+extern void zfcp_sg_free_table(struct scatterlist *sg, int count);
+extern int  zfcp_sg_setup_table(struct scatterlist *sg, int count);
 extern void zfcp_rec_dbf_event_thread(u8 id, struct zfcp_adapter *adapter);
 extern void zfcp_rec_dbf_event_thread_lock(u8 id, struct zfcp_adapter *adapter);
 extern void zfcp_rec_dbf_event_adapter(u8 id, void *ref, struct zfcp_adapter *);
@@ -200,4 +202,6 @@ extern void zfcp_scsi_dbf_event_devreset
 					 struct scsi_cmnd *);
 extern int zfcp_reqlist_isempty(struct zfcp_adapter *);
 
+extern struct miscdevice zfcp_cfdc_misc;
+
 #endif	/* ZFCP_EXT_H */
drivers/s390/scsi/Makefile +1 -1
@@ -4,6 +4,6 @@
 
 zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \
 	     zfcp_fsf.o zfcp_dbf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \
-	     zfcp_sysfs_unit.o zfcp_sysfs_driver.o zfcp_fc.o
+	     zfcp_sysfs_unit.o zfcp_sysfs_driver.o zfcp_fc.o zfcp_cfdc.o
 
 obj-$(CONFIG_ZFCP) += zfcp.o
drivers/s390/scsi/zfcp_def.h +0 -43

61 lines not on this page · raw message

drivers/s390/scsi/zfcp_cfdc.c new file +259 -0

259 lines not on this page · raw message

drivers/s390/scsi/zfcp_fsf.c +23 -221

303 lines not on this page · raw message

drivers/s390/scsi/zfcp_fsf.h +12 -0
@@ -22,6 +22,8 @@
 #ifndef FSF_H
 #define FSF_H
 
+#include <linux/pfn.h>
+
 #define FSF_QTCB_CURRENT_VERSION		0x00000001
 
 /* FSF commands */
@@ -258,6 +260,16 @@
 #define FSF_UNIT_ACCESS_EXCLUSIVE		0x02000000
 #define FSF_UNIT_ACCESS_OUTBOUND_TRANSFER	0x10000000
 
+/* FSF interface for CFDC */
+#define ZFCP_CFDC_MAX_SIZE		127 * 1024
+#define ZFCP_CFDC_PAGES 		PFN_UP(ZFCP_CFDC_MAX_SIZE)
+
+struct zfcp_fsf_cfdc {
+	struct scatterlist sg[ZFCP_CFDC_PAGES];
+	u32 command;
+	u32 option;
+};
+
 struct fsf_queue_designator {
 	u8  cssid;
 	u8  chpid;
#3 lore raw

PATCH 3/8 zfcp: Cleanup code in zfcp_ccw

In reply to Christof Schmitt

From: Christof Schmitt <[email protected]>

Overall cleanup in file zfcp_ccw.c. Fix coding style issues, remove useless macros and messages and convert remaining messages to standard macros.

---
 drivers/s390/scsi/zfcp_ccw.c |  150 ++++++++++++++-----------------------------
 1 file changed, 50 insertions(+), 100 deletions(-)
drivers/s390/scsi/zfcp_ccw.c +50 -100
@@ -1,64 +1,13 @@
 /*
- * This file is part of the zfcp device driver for
- * FCP adapters for IBM System z9 and zSeries.
+ * zfcp device driver
  *
- * (C) Copyright IBM Corp. 2002, 2006
+ * Registration and callback for the s390 common I/O layer.
  *
- * 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.
+ * Copyright IBM Corporation 2002, 2008
  */
 
 #include "zfcp_ext.h"
 
-#define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
-
-static int zfcp_ccw_probe(struct ccw_device *);
-static void zfcp_ccw_remove(struct ccw_device *);
-static int zfcp_ccw_set_online(struct ccw_device *);
-static int zfcp_ccw_set_offline(struct ccw_device *);
-static int zfcp_ccw_notify(struct ccw_device *, int);
-static void zfcp_ccw_shutdown(struct ccw_device *);
-
-static struct ccw_device_id zfcp_ccw_device_id[] = {
-	{CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE,
-			    ZFCP_CONTROL_UNIT_MODEL,
-			    ZFCP_DEVICE_TYPE,
-			    ZFCP_DEVICE_MODEL)},
-	{CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE,
-			    ZFCP_CONTROL_UNIT_MODEL,
-			    ZFCP_DEVICE_TYPE,
-			    ZFCP_DEVICE_MODEL_PRIV)},
-	{},
-};
-
-static struct ccw_driver zfcp_ccw_driver = {
-	.owner       = THIS_MODULE,
-	.name        = ZFCP_NAME,
-	.ids         = zfcp_ccw_device_id,
-	.probe       = zfcp_ccw_probe,
-	.remove      = zfcp_ccw_remove,
-	.set_online  = zfcp_ccw_set_online,
-	.set_offline = zfcp_ccw_set_offline,
-	.notify      = zfcp_ccw_notify,
-	.shutdown    = zfcp_ccw_shutdown,
-	.driver = {
-		.groups = zfcp_driver_attr_groups,
-	},
-};
-
-MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);
-
 /**
  * zfcp_ccw_probe - probe function of zfcp driver
  * @ccw_device: pointer to belonging ccw device
@@ -69,19 +18,18 @@ MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device
  * In addition the nameserver port will be added to the ports of the adapter
  * and its sysfs representation will be created too.
  */
-static int
-zfcp_ccw_probe(struct ccw_device *ccw_device)
+static int zfcp_ccw_probe(struct ccw_device *ccw_device)
 {
 	struct zfcp_adapter *adapter;
 	int retval = 0;
 
 	down(&zfcp_data.config_sema);
 	adapter = zfcp_adapter_enqueue(ccw_device);
-	if (!adapter)
+	if (!adapter) {
+		dev_err(&ccw_device->dev,
+			"Setup of data structures failed.\n");
 		retval = -EINVAL;
-	else
-		ZFCP_LOG_DEBUG("Probed adapter %s\n",
-			       zfcp_get_busid_by_adapter(adapter));
+	}
 	up(&zfcp_data.config_sema);
 	return retval;
 }
@@ -95,8 +43,7 @@ zfcp_ccw_probe(struct ccw_device *ccw_de
  * ports that belong to this adapter. And in addition all resources of this
  * adapter will be freed too.
  */
-static void
-zfcp_ccw_remove(struct ccw_device *ccw_device)
+static void zfcp_ccw_remove(struct ccw_device *ccw_device)
 {
 	struct zfcp_adapter *adapter;
 	struct zfcp_port *port, *p;
@@ -106,8 +53,6 @@ zfcp_ccw_remove(struct ccw_device *ccw_d
 	down(&zfcp_data.config_sema);
 	adapter = dev_get_drvdata(&ccw_device->dev);
 
-	ZFCP_LOG_DEBUG("Removing adapter %s\n",
-		       zfcp_get_busid_by_adapter(adapter));
 	write_lock_irq(&zfcp_data.config_lock);
 	list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
 		list_for_each_entry_safe(unit, u, &port->unit_list_head, list) {
@@ -145,8 +90,7 @@ zfcp_ccw_remove(struct ccw_device *ccw_d
  * registered with the SCSI stack, that the QDIO queues will be set up
  * and that the adapter will be opened (asynchronously).
  */
-static int
-zfcp_ccw_set_online(struct ccw_device *ccw_device)
+static int zfcp_ccw_set_online(struct ccw_device *ccw_device)
 {
 	struct zfcp_adapter *adapter;
 	int retval;
@@ -155,12 +99,8 @@ zfcp_ccw_set_online(struct ccw_device *c
 	adapter = dev_get_drvdata(&ccw_device->dev);
 
 	retval = zfcp_erp_thread_setup(adapter);
-	if (retval) {
-		ZFCP_LOG_INFO("error: start of error recovery thread for "
-			      "adapter %s failed\n",
-			      zfcp_get_busid_by_adapter(adapter));
+	if (retval)
 		goto out;
-	}
 
 	retval = zfcp_adapter_scsi_register(adapter);
 	if (retval)
@@ -191,8 +131,7 @@ zfcp_ccw_set_online(struct ccw_device *c
  * This function gets called by the common i/o layer and sets an adapter
  * into state offline.
  */
-static int
-zfcp_ccw_set_offline(struct ccw_device *ccw_device)
+static int zfcp_ccw_set_offline(struct ccw_device *ccw_device)
 {
 	struct zfcp_adapter *adapter;
 
@@ -206,15 +145,14 @@ zfcp_ccw_set_offline(struct ccw_device *
 }
 
 /**
- * zfcp_ccw_notify
+ * zfcp_ccw_notify - ccw notify function
  * @ccw_device: pointer to belonging ccw device
  * @event: indicates if adapter was detached or attached
  *
  * This function gets called by the common i/o layer if an adapter has gone
  * or reappeared.
  */
-static int
-zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
+static int zfcp_ccw_notify(struct ccw_device *ccw_device, int event)
 {
 	struct zfcp_adapter *adapter;
 
@@ -222,18 +160,15 @@ zfcp_ccw_notify(struct ccw_device *ccw_d
 	adapter = dev_get_drvdata(&ccw_device->dev);
 	switch (event) {
 	case CIO_GONE:
-		ZFCP_LOG_NORMAL("adapter %s: device gone\n",
-				zfcp_get_busid_by_adapter(adapter));
+		dev_warn(&adapter->ccw_device->dev, "device gone\n");
 		zfcp_erp_adapter_shutdown(adapter, 0, 87, NULL);
 		break;
 	case CIO_NO_PATH:
-		ZFCP_LOG_NORMAL("adapter %s: no path\n",
-				zfcp_get_busid_by_adapter(adapter));
+		dev_warn(&adapter->ccw_device->dev, "no path\n");
 		zfcp_erp_adapter_shutdown(adapter, 0, 88, NULL);
 		break;
 	case CIO_OPER:
-		ZFCP_LOG_NORMAL("adapter %s: operational again\n",
-				zfcp_get_busid_by_adapter(adapter));
+		dev_info(&adapter->ccw_device->dev, "operational again\n");
 		zfcp_erp_modify_adapter_status(adapter, 11, NULL,
 					       ZFCP_STATUS_COMMON_RUNNING,
 					       ZFCP_SET);
@@ -247,24 +182,10 @@ zfcp_ccw_notify(struct ccw_device *ccw_d
 }
 
 /**
- * zfcp_ccw_register - ccw register function
- *
- * Registers the driver at the common i/o layer. This function will be called
- * at module load time/system start.
+ * zfcp_ccw_shutdown - handle shutdown from cio
+ * @cdev: device for adapter to shutdown.
  */
-int __init
-zfcp_ccw_register(void)
-{
-	return ccw_driver_register(&zfcp_ccw_driver);
-}
-
-/**
- * zfcp_ccw_shutdown - gets called on reboot/shutdown
- *
- * Makes sure that QDIO queues are down when the system gets stopped.
- */
-static void
-zfcp_ccw_shutdown(struct ccw_device *cdev)
+static void zfcp_ccw_shutdown(struct ccw_device *cdev)
 {
 	struct zfcp_adapter *adapter;
 
@@ -275,4 +196,33 @@ zfcp_ccw_shutdown(struct ccw_device *cde
 	up(&zfcp_data.config_sema);
 }
 
-#undef ZFCP_LOG_AREA
+static struct ccw_device_id zfcp_ccw_device_id[] = {
+	{ CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, 0x3) },
+	{ CCW_DEVICE_DEVTYPE(0x1731, 0x3, 0x1732, 0x4) }, /* priv. */
+	{},
+};
+
+MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id);
+
+static struct ccw_driver zfcp_ccw_driver = {
+	.owner       = THIS_MODULE,
+	.name        = "zfcp",
+	.ids         = zfcp_ccw_device_id,
+	.probe       = zfcp_ccw_probe,
+	.remove      = zfcp_ccw_remove,
+	.set_online  = zfcp_ccw_set_online,
+	.set_offline = zfcp_ccw_set_offline,
+	.notify      = zfcp_ccw_notify,
+	.shutdown    = zfcp_ccw_shutdown,
+};
+
+/**
+ * zfcp_ccw_register - ccw register function
+ *
+ * Registers the driver at the common i/o layer. This function will be called
+ * at module load time/system start.
+ */
+int __init zfcp_ccw_register(void)
+{
+	return ccw_driver_register(&zfcp_ccw_driver);
+}
#4 lore raw

PATCH 4/8 zfcp: Cleanup qdio code

In reply to Christof Schmitt

From: Swen Schillig <[email protected]>

Cleanup the interface code from zfcp to qdio. Also move code that belongs to the qdio interface from the erp to the qdio file.

---
 drivers/s390/scsi/zfcp_aux.c  |   45 --
 drivers/s390/scsi/zfcp_dbf.c  |    3 
 drivers/s390/scsi/zfcp_def.h  |   26 -
 drivers/s390/scsi/zfcp_erp.c  |  114 -----
 drivers/s390/scsi/zfcp_ext.h  |   18 
 drivers/s390/scsi/zfcp_fsf.c  |  178 +++------
 drivers/s390/scsi/zfcp_qdio.c |  819 ++++++++++++++++--------------------------
 7 files changed, 414 insertions(+), 789 deletions(-)
drivers/s390/scsi/zfcp_qdio.c +320 -499
@@ -1,241 +1,92 @@
 /*
- * This file is part of the zfcp device driver for
- * FCP adapters for IBM System z9 and zSeries.
+ * zfcp device driver
  *
- * (C) Copyright IBM Corp. 2002, 2006
+ * Setup and helper functions to access QDIO.
  *
- * 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.
+ * Copyright IBM Corporation 2002, 2008
  */
 
 #include "zfcp_ext.h"
 
-static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *, int);
-static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_get
-	(struct zfcp_qdio_queue *, int, int);
-static inline volatile struct qdio_buffer_element *zfcp_qdio_sbale_resp
-	(struct zfcp_fsf_req *, int, int);
-static volatile struct qdio_buffer_element *zfcp_qdio_sbal_chain
-	(struct zfcp_fsf_req *, unsigned long);
-static volatile struct qdio_buffer_element *zfcp_qdio_sbale_next
-	(struct zfcp_fsf_req *, unsigned long);
-static int zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *, int, int);
-static inline int zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *);
-static void zfcp_qdio_sbale_fill
-	(struct zfcp_fsf_req *, unsigned long, void *, int);
-static int zfcp_qdio_sbals_from_segment
-	(struct zfcp_fsf_req *, unsigned long, void *, unsigned long);
-
-static qdio_handler_t zfcp_qdio_request_handler;
-static qdio_handler_t zfcp_qdio_response_handler;
-static int zfcp_qdio_handler_error_check(struct zfcp_adapter *,
-	unsigned int, unsigned int, unsigned int, int, int);
+/* FIXME(tune): free space should be one max. SBAL chain plus what? */
+#define ZFCP_QDIO_PCI_INTERVAL	(QDIO_MAX_BUFFERS_PER_Q \
+				- (ZFCP_MAX_SBALS_PER_REQ + 4))
 
-#define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_QDIO
-
-/*
- * Frees BUFFER memory for each of the pointers of the struct qdio_buffer array
- * in the adapter struct sbuf is the pointer array.
- *
- * locks:       must only be called with zfcp_data.config_sema taken
- */
-static void
-zfcp_qdio_buffers_dequeue(struct qdio_buffer **sbuf)
-{
-	int pos;
-
-	for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos += QBUFF_PER_PAGE)
-		free_page((unsigned long) sbuf[pos]);
-}
-
-/*
- * Allocates BUFFER memory to each of the pointers of the qdio_buffer_t
- * array in the adapter struct.
- * Cur_buf is the pointer array
- *
- * returns:	zero on success else -ENOMEM
- * locks:       must only be called with zfcp_data.config_sema taken
- */
-static int
-zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbuf)
+static int zfcp_qdio_buffers_enqueue(struct qdio_buffer **sbal)
 {
 	int pos;
 
 	for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos += QBUFF_PER_PAGE) {
-		sbuf[pos] = (struct qdio_buffer *) get_zeroed_page(GFP_KERNEL);
-		if (!sbuf[pos]) {
-			zfcp_qdio_buffers_dequeue(sbuf);
+		sbal[pos] = (struct qdio_buffer *) get_zeroed_page(GFP_KERNEL);
+		if (!sbal[pos])
 			return -ENOMEM;
-		}
 	}
 	for (pos = 0; pos < QDIO_MAX_BUFFERS_PER_Q; pos++)
 		if (pos % QBUFF_PER_PAGE)
-			sbuf[pos] = sbuf[pos - 1] + 1;
+			sbal[pos] = sbal[pos - 1] + 1;
 	return 0;
 }
 
-/* locks:       must only be called with zfcp_data.config_sema taken */
-int
-zfcp_qdio_allocate_queues(struct zfcp_adapter *adapter)
+static volatile struct qdio_buffer_element *
+zfcp_qdio_sbale(struct zfcp_qdio_queue *q, int sbal_idx, int sbale_idx)
 {
-	int ret;
-
-	ret = zfcp_qdio_buffers_enqueue(adapter->request_queue.buffer);
-	if (ret)
-		return ret;
-	return zfcp_qdio_buffers_enqueue(adapter->response_queue.buffer);
+	return &q->sbal[sbal_idx]->element[sbale_idx];
 }
 
-/* locks:       must only be called with zfcp_data.config_sema taken */
-void
-zfcp_qdio_free_queues(struct zfcp_adapter *adapter)
+/**
+ * zfcp_qdio_free - free memory used by request- and resposne queue
+ * @adapter: pointer to the zfcp_adapter structure
+ */
+void zfcp_qdio_free(struct zfcp_adapter *adapter)
 {
-	ZFCP_LOG_TRACE("freeing request_queue buffers\n");
-	zfcp_qdio_buffers_dequeue(adapter->request_queue.buffer);
+	struct qdio_buffer **sbal_req, **sbal_resp;
+	int p;
 
-	ZFCP_LOG_TRACE("freeing response_queue buffers\n");
-	zfcp_qdio_buffers_dequeue(adapter->response_queue.buffer);
-}
+	if (adapter->ccw_device)
+		qdio_free(adapter->ccw_device);
 
-int
-zfcp_qdio_allocate(struct zfcp_adapter *adapter)
-{
-	struct qdio_initialize *init_data;
+	sbal_req = adapter->req_q.sbal;
+	sbal_resp = adapter->resp_q.sbal;
 
-	init_data = &adapter->qdio_init_data;
+	for (p = 0; p < QDIO_MAX_BUFFERS_PER_Q; p += QBUFF_PER_PAGE) {
+		free_page((unsigned long) sbal_req[p]);
+		free_page((unsigned long) sbal_resp[p]);
+	}
+}
 
-	init_data->cdev = adapter->ccw_device;
-	init_data->q_format = QDIO_SCSI_QFMT;
-	memcpy(init_data->adapter_name, zfcp_get_busid_by_adapter(adapter), 8);
-	ASCEBC(init_data->adapter_name, 8);
-	init_data->qib_param_field_format = 0;
-	init_data->qib_param_field = NULL;
-	init_data->input_slib_elements = NULL;
-	init_data->output_slib_elements = NULL;
-	init_data->min_input_threshold = ZFCP_MIN_INPUT_THRESHOLD;
-	init_data->max_input_threshold = ZFCP_MAX_INPUT_THRESHOLD;
-	init_data->min_output_threshold = ZFCP_MIN_OUTPUT_THRESHOLD;
-	init_data->max_output_threshold = ZFCP_MAX_OUTPUT_THRESHOLD;
-	init_data->no_input_qs = 1;
-	init_data->no_output_qs = 1;
-	init_data->input_handler = zfcp_qdio_response_handler;
-	init_data->output_handler = zfcp_qdio_request_handler;
-	init_data->int_parm = (unsigned long) adapter;
-	init_data->flags = QDIO_INBOUND_0COPY_SBALS |
-	    QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS;
-	init_data->input_sbal_addr_array =
-	    (void **) (adapter->response_queue.buffer);
-	init_data->output_sbal_addr_array =
-	    (void **) (adapter->request_queue.buffer);
+static void zfcp_qdio_handler_error(struct zfcp_adapter *adapter, u8 id)
+{
+	dev_warn(&adapter->ccw_device->dev, "QDIO problem occurred.\n");
 
-	return qdio_allocate(init_data);
+	zfcp_erp_adapter_reopen(adapter,
+				ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
+				ZFCP_STATUS_COMMON_ERP_FAILED, id, NULL);
 }
 
-/*
- * function:   	zfcp_qdio_handler_error_check
- *
- * purpose:     called by the response handler to determine error condition
- *
- * returns:	error flag
- *
- */
-static int
-zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status,
-			      unsigned int qdio_error, unsigned int siga_error,
-			      int first_element, int elements_processed)
+static void zfcp_qdio_int_req(struct ccw_device *cdev, unsigned int status,
+			      unsigned int qdio_err, unsigned int siga_err,
+			      unsigned int queue_no, int first, int count,
+			      unsigned long parm)
 {
-	int retval = 0;
+	struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm;
+	struct zfcp_qdio_queue *queue = &adapter->req_q;
 
 	if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) {
-		retval = -EIO;
-
-		ZFCP_LOG_INFO("QDIO problem occurred (status=0x%x, "
-			      "qdio_error=0x%x, siga_error=0x%x)\n",
-			      status, qdio_error, siga_error);
-
-		zfcp_hba_dbf_event_qdio(adapter, status, qdio_error, siga_error,
-				first_element, elements_processed);
-               /*
-               	* Restarting IO on the failed adapter from scratch.
-                * Since we have been using this adapter, it is save to assume
-                * that it is not failed but recoverable. The card seems to
-                * report link-up events by self-initiated queue shutdown.
-                * That is why we need to clear the link-down flag
-                * which is set again in case we have missed by a mile.
-                */
-		zfcp_erp_adapter_reopen(adapter,
-					ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
-					ZFCP_STATUS_COMMON_ERP_FAILED, 140,
-					NULL);
+		zfcp_hba_dbf_event_qdio(adapter, status, qdio_err, siga_err,
+					first, count);
+		zfcp_qdio_handler_error(adapter, 140);
+		return;
 	}
-	return retval;
-}
-
-/*
- * function:    zfcp_qdio_request_handler
- *
- * purpose:	is called by QDIO layer for completed SBALs in request queue
- *
- * returns:	(void)
- */
-static void
-zfcp_qdio_request_handler(struct ccw_device *ccw_device,
-			  unsigned int status,
-			  unsigned int qdio_error,
-			  unsigned int siga_error,
-			  unsigned int queue_number,
-			  int first_element,
-			  int elements_processed,
-			  unsigned long int_parm)
-{
-	struct zfcp_adapter *adapter;
-	struct zfcp_qdio_queue *queue;
-
-	adapter = (struct zfcp_adapter *) int_parm;
-	queue = &adapter->request_queue;
-
-	ZFCP_LOG_DEBUG("adapter %s, first=%d, elements_processed=%d\n",
-		       zfcp_get_busid_by_adapter(adapter),
-		       first_element, elements_processed);
-
-	if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error,
-						   siga_error, first_element,
-						   elements_processed)))
-		goto out;
-	/*
-	 * we stored address of struct zfcp_adapter  data structure
-	 * associated with irq in int_parm
-	 */
 
 	/* cleanup all SBALs being program-owned now */
-	zfcp_qdio_zero_sbals(queue->buffer, first_element, elements_processed);
+	zfcp_qdio_zero_sbals(queue->sbal, first, count);
 
-	/* increase free space in outbound queue */
-	atomic_add(elements_processed, &queue->free_count);
-	ZFCP_LOG_DEBUG("free_count=%d\n", atomic_read(&queue->free_count));
+	atomic_add(count, &queue->count);
 	wake_up(&adapter->request_wq);
-	ZFCP_LOG_DEBUG("elements_processed=%d, free count=%d\n",
-		       elements_processed, atomic_read(&queue->free_count));
- out:
-	return;
 }
 
-/**
- * zfcp_qdio_reqid_check - checks for valid reqids.
- */
 static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
-				  unsigned long req_id, int sbal)
+				  unsigned long req_id, int sbal_idx)
 {
 	struct zfcp_fsf_req *fsf_req;
 	unsigned long flags;
@@ -248,204 +99,117 @@ static void zfcp_qdio_reqid_check(struct
 		 * Unknown request means that we have potentially memory
 		 * corruption and must stop the machine immediatly.
 		 */
-		panic("error: unknown request id (%ld) on adapter %s.\n",
+		panic("error: unknown request id (%lx) on adapter %s.\n",
 		      req_id, zfcp_get_busid_by_adapter(adapter));
 
 	zfcp_reqlist_remove(adapter, fsf_req);
-	atomic_dec(&adapter->reqs_active);
 	spin_unlock_irqrestore(&adapter->req_list_lock, flags);
 
-	fsf_req->sbal_response = sbal;
-	/* finish the FSF request */
+	fsf_req->sbal_response = sbal_idx;
 	zfcp_fsf_req_complete(fsf_req);
 }
 
-/*
- * function:   	zfcp_qdio_response_handler
- *
- * purpose:	is called by QDIO layer for completed SBALs in response queue
- *
- * returns:	(void)
- */
-static void
-zfcp_qdio_response_handler(struct ccw_device *ccw_device,
-			   unsigned int status,
-			   unsigned int qdio_error,
-			   unsigned int siga_error,
-			   unsigned int queue_number,
-			   int first_element,
-			   int elements_processed,
-			   unsigned long int_parm)
-{
-	struct zfcp_adapter *adapter;
-	struct zfcp_qdio_queue *queue;
-	int buffer_index;
-	int i;
-	struct qdio_buffer *buffer;
-	int retval = 0;
-	u8 count;
-	u8 start;
-	volatile struct qdio_buffer_element *buffere = NULL;
-	int buffere_index;
-
-	adapter = (struct zfcp_adapter *) int_parm;
-	queue = &adapter->response_queue;
-
-	if (unlikely(zfcp_qdio_handler_error_check(adapter, status, qdio_error,
-						   siga_error, first_element,
-						   elements_processed)))
-		goto out;
+static void zfcp_qdio_resp_put_back(struct zfcp_adapter *adapter, int processed)
+{
+	struct zfcp_qdio_queue *queue = &adapter->resp_q;
+	struct ccw_device *cdev = adapter->ccw_device;
+	u8 count, start = queue->first;
+	unsigned int retval;
 
-	/*
-	 * we stored address of struct zfcp_adapter  data structure
-	 * associated with irq in int_parm
-	 */
+	count = atomic_read(&queue->count) + processed;
+
+	retval = do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
+			 0, start, count, NULL);
+
+	if (unlikely(retval)) {
+		atomic_set(&queue->count, count);
+		/* FIXME: Recover this with an adapter reopen? */
+	} else {
+		queue->first += count;
+		queue->first %= QDIO_MAX_BUFFERS_PER_Q;
+		atomic_set(&queue->count, 0);
+	}
+}
+
+static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int status,
+			       unsigned int qdio_err, unsigned int siga_err,
+			       unsigned int queue_no, int first, int count,
+			       unsigned long parm)
+{
+	struct zfcp_adapter *adapter = (struct zfcp_adapter *) parm;
+	struct zfcp_qdio_queue *queue = &adapter->resp_q;
+	volatile struct qdio_buffer_element *sbale;
+	int sbal_idx, sbale_idx, sbal_no;
+
+	if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) {
+		zfcp_hba_dbf_event_qdio(adapter, status, qdio_err, siga_err,
+					first, count);
+		zfcp_qdio_handler_error(adapter, 147);
+		return;
+	}
 
-	buffere = &(queue->buffer[first_element]->element[0]);
-	ZFCP_LOG_DEBUG("first BUFFERE flags=0x%x\n", buffere->flags);
 	/*
 	 * go through all SBALs from input queue currently
 	 * returned by QDIO layer
 	 */
-
-	for (i = 0; i < elements_processed; i++) {
-
-		buffer_index = first_element + i;
-		buffer_index %= QDIO_MAX_BUFFERS_PER_Q;
-		buffer = queue->buffer[buffer_index];
+	for (sbal_no = 0; sbal_no < count; sbal_no++) {
+		sbal_idx = (first + sbal_no) % QDIO_MAX_BUFFERS_PER_Q;
 
 		/* go through all SBALEs of SBAL */
-		for (buffere_index = 0;
-		     buffere_index < QDIO_MAX_ELEMENTS_PER_BUFFER;
-		     buffere_index++) {
-
-			/* look for QDIO request identifiers in SB */
-			buffere = &buffer->element[buffere_index];
+		for (sbale_idx = 0; sbale_idx < QDIO_MAX_ELEMENTS_PER_BUFFER;
+		     sbale_idx++) {
+			sbale = zfcp_qdio_sbale(queue, sbal_idx, sbale_idx);
 			zfcp_qdio_reqid_check(adapter,
-					      (unsigned long) buffere->addr, i);
-
-			/*
-			 * A single used SBALE per inbound SBALE has been
-			 * implemented by QDIO so far. Hope they will
-			 * do some optimisation. Will need to change to
-			 * unlikely() then.
-			 */
-			if (likely(buffere->flags & SBAL_FLAGS_LAST_ENTRY))
+					      (unsigned long) sbale->addr,
+					      sbal_idx);
+			if (likely(sbale->flags & SBAL_FLAGS_LAST_ENTRY))
 				break;
 		};
 
-		if (unlikely(!(buffere->flags & SBAL_FLAGS_LAST_ENTRY))) {
-			ZFCP_LOG_NORMAL("bug: End of inbound data "
-					"not marked!\n");
-		}
+		if (unlikely(!(sbale->flags & SBAL_FLAGS_LAST_ENTRY)))
+			dev_warn(&adapter->ccw_device->dev,
+				 "Protocol violation by adapter. "
+				 "Continuing operations.\n");
 	}
 
 	/*
 	 * put range of SBALs back to response queue
 	 * (including SBALs which have already been free before)
 	 */
-	count = atomic_read(&queue->free_count) + elements_processed;
-	start = queue->free_index;
-
-	ZFCP_LOG_TRACE("calling do_QDIO on adapter %s (flags=0x%x, "
-		       "queue_no=%i, index_in_queue=%i, count=%i, "
-		       "buffers=0x%lx\n",
-		       zfcp_get_busid_by_adapter(adapter),
-		       QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
-		       0, start, count, (unsigned long) &queue->buffer[start]);
-
-	retval = do_QDIO(ccw_device,
-			 QDIO_FLAG_SYNC_INPUT | QDIO_FLAG_UNDER_INTERRUPT,
-			 0, start, count, NULL);
-
-	if (unlikely(retval)) {
-		atomic_set(&queue->free_count, count);
-		ZFCP_LOG_DEBUG("clearing of inbound data regions failed, "
-			       "queues may be down "
-			       "(count=%d, start=%d, retval=%d)\n",
-			       count, start, retval);
-	} else {
-		queue->free_index += count;
-		queue->free_index %= QDIO_MAX_BUFFERS_PER_Q;
-		atomic_set(&queue->free_count, 0);
-		ZFCP_LOG_TRACE("%i buffers enqueued to response "
-			       "queue at position %i\n", count, start);
-	}
- out:
-	return;
-}
-
-/**
- * zfcp_qdio_sbale_get - return pointer to SBALE of qdio_queue
- * @queue: queue from which SBALE should be returned
- * @sbal: specifies number of SBAL in queue
- * @sbale: specifes number of SBALE in SBAL
- */
-static inline volatile struct qdio_buffer_element *
-zfcp_qdio_sbale_get(struct zfcp_qdio_queue *queue, int sbal, int sbale)
-{
-	return &queue->buffer[sbal]->element[sbale];
+	zfcp_qdio_resp_put_back(adapter, count);
 }
 
 /**
- * zfcp_qdio_sbale_req - return pointer to SBALE of request_queue for
- *	a struct zfcp_fsf_req
+ * zfcp_qdio_sbale_req - return ptr to SBALE of req_q for a struct zfcp_fsf_req
+ * @fsf_req: pointer to struct fsf_req
+ * Returns: pointer to qdio_buffer_element (SBALE) structure
  */
 volatile struct qdio_buffer_element *
-zfcp_qdio_sbale_req(struct zfcp_fsf_req *fsf_req, int sbal, int sbale)
-{
-	return zfcp_qdio_sbale_get(&fsf_req->adapter->request_queue,
-				   sbal, sbale);
-}
-
-/**
- * zfcp_qdio_sbale_resp - return pointer to SBALE of response_queue for
- *	a struct zfcp_fsf_req
- */
-static inline volatile struct qdio_buffer_element *
-zfcp_qdio_sbale_resp(struct zfcp_fsf_req *fsf_req, int sbal, int sbale)
+zfcp_qdio_sbale_req(struct zfcp_fsf_req *req)
 {
-	return zfcp_qdio_sbale_get(&fsf_req->adapter->response_queue,
-				   sbal, sbale);
+	return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last, 0);
 }
 
 /**
- * zfcp_qdio_sbale_curr - return current SBALE on request_queue for
- *	a struct zfcp_fsf_req
+ * zfcp_qdio_sbale_curr - return curr SBALE on req_q for a struct zfcp_fsf_req
+ * @fsf_req: pointer to struct fsf_req
+ * Returns: pointer to qdio_buffer_element (SBALE) structure
  */
 volatile struct qdio_buffer_element *
-zfcp_qdio_sbale_curr(struct zfcp_fsf_req *fsf_req)
+zfcp_qdio_sbale_curr(struct zfcp_fsf_req *req)
 {
-	return zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_last,
-				   fsf_req->sbale_curr);
+	return zfcp_qdio_sbale(&req->adapter->req_q, req->sbal_last,
+			       req->sbale_curr);
 }
 
-/**
- * zfcp_qdio_sbal_limit - determine maximum number of SBALs that can be used
- *	on the request_queue for a struct zfcp_fsf_req
- * @fsf_req: the number of the last SBAL that can be used is stored herein
- * @max_sbals: used to pass an upper limit for the number of SBALs
- *
- * Note: We can assume at least one free SBAL in the request_queue when called.
- */
-static void
-zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals)
+static void zfcp_qdio_sbal_limit(struct zfcp_fsf_req *fsf_req, int max_sbals)
 {
-	int count = atomic_read(&fsf_req->adapter->request_queue.free_count);
+	int count = atomic_read(&fsf_req->adapter->req_q.count);
 	count = min(count, max_sbals);
-	fsf_req->sbal_limit  = fsf_req->sbal_first;
-	fsf_req->sbal_limit += (count - 1);
-	fsf_req->sbal_limit %= QDIO_MAX_BUFFERS_PER_Q;
+	fsf_req->sbal_limit = (fsf_req->sbal_first + count - 1)
+					% QDIO_MAX_BUFFERS_PER_Q;
 }
 
-/**
- * zfcp_qdio_sbal_chain - chain SBALs if more than one SBAL is needed for a
- *	request
- * @fsf_req: zfcp_fsf_req to be processed
- * @sbtype: SBAL flags which have to be set in first SBALE of new SBAL
- *
- * This function changes sbal_last, sbale_curr, sbal_number of fsf_req.
- */
 static volatile struct qdio_buffer_element *
 zfcp_qdio_sbal_chain(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
 {
@@ -460,7 +224,7 @@ zfcp_qdio_sbal_chain(struct zfcp_fsf_req
 		return NULL;
 
 	/* set chaining flag in first SBALE of current SBAL */
-	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_last, 0);
+	sbale = zfcp_qdio_sbale_req(fsf_req);
 	sbale->flags |= SBAL_FLAGS0_MORE_SBALS;
 
 	/* calculate index of next SBAL */
@@ -480,214 +244,271 @@ zfcp_qdio_sbal_chain(struct zfcp_fsf_req
 	return sbale;
 }
 
-/**
- * zfcp_qdio_sbale_next - switch to next SBALE, chain SBALs if needed
- */
 static volatile struct qdio_buffer_element *
 zfcp_qdio_sbale_next(struct zfcp_fsf_req *fsf_req, unsigned long sbtype)
 {
 	if (fsf_req->sbale_curr == ZFCP_LAST_SBALE_PER_SBAL)
 		return zfcp_qdio_sbal_chain(fsf_req, sbtype);
-
 	fsf_req->sbale_curr++;
-
 	return zfcp_qdio_sbale_curr(fsf_req);
 }
 
-/**
- * zfcp_qdio_sbals_zero - initialize SBALs between first and last in queue
- *	with zero from
- */
-static int
-zfcp_qdio_sbals_zero(struct zfcp_qdio_queue *queue, int first, int last)
+static void zfcp_qdio_undo_sbals(struct zfcp_fsf_req *fsf_req)
 {
-	struct qdio_buffer **buf = queue->buffer;
-	int curr = first;
-	int count = 0;
-
-	for(;;) {
-		curr %= QDIO_MAX_BUFFERS_PER_Q;
-		count++;
-		memset(buf[curr], 0, sizeof(struct qdio_buffer));
-		if (curr == last)
-			break;
-		curr++;
-	}
-	return count;
+	struct qdio_buffer **sbal = fsf_req->adapter->req_q.sbal;
+	int first = fsf_req->sbal_first;
+	int last = fsf_req->sbal_last;
+	int count = (last - first + QDIO_MAX_BUFFERS_PER_Q) %
+		QDIO_MAX_BUFFERS_PER_Q + 1;
+	zfcp_qdio_zero_sbals(sbal, first, count);
 }
 
-
-/**
- * zfcp_qdio_sbals_wipe - reset all changes in SBALs for an fsf_req
- */
-static inline int
-zfcp_qdio_sbals_wipe(struct zfcp_fsf_req *fsf_req)
-{
-	return zfcp_qdio_sbals_zero(&fsf_req->adapter->request_queue,
-				    fsf_req->sbal_first, fsf_req->sbal_last);
-}
-
-
-/**
- * zfcp_qdio_sbale_fill - set address and length in current SBALE
- *	on request_queue
- */
-static void
-zfcp_qdio_sbale_fill(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
-		     void *addr, int length)
+static int zfcp_qdio_fill_sbals(struct zfcp_fsf_req *fsf_req,
+				unsigned int sbtype, void *start_addr,
+				unsigned int total_length)
 {
 	volatile struct qdio_buffer_element *sbale;
-
-	sbale = zfcp_qdio_sbale_curr(fsf_req);
-	sbale->addr = addr;
-	sbale->length = length;
-}
-
-/**
- * zfcp_qdio_sbals_from_segment - map memory segment to SBALE(s)
- * @fsf_req: request to be processed
- * @sbtype: SBALE flags
- * @start_addr: address of memory segment
- * @total_length: length of memory segment
- *
- * Alignment and length of the segment determine how many SBALEs are needed
- * for the memory segment.
- */
-static int
-zfcp_qdio_sbals_from_segment(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
-			     void *start_addr, unsigned long total_length)
-{
 	unsigned long remaining, length;
 	void *addr;
 
-	/* split segment up heeding page boundaries */
+	/* split segment up */
 	for (addr = start_addr, remaining = total_length; remaining > 0;
 	     addr += length, remaining -= length) {
-		/* get next free SBALE for new piece */
-		if (NULL == zfcp_qdio_sbale_next(fsf_req, sbtype)) {
-			/* no SBALE left, clean up and leave */
-			zfcp_qdio_sbals_wipe(fsf_req);
+		sbale = zfcp_qdio_sbale_next(fsf_req, sbtype);
+		if (!sbale) {
+			zfcp_qdio_undo_sbals(fsf_req);
 			return -EINVAL;
 		}
-		/* calculate length of new piece */
+
+		/* new piece must not exceed next page boundary */
 		length = min(remaining,
-			     (PAGE_SIZE - ((unsigned long) addr &
+			     (PAGE_SIZE - ((unsigned long)addr &
 					   (PAGE_SIZE - 1))));
-		/* fill current SBALE with calculated piece */
-		zfcp_qdio_sbale_fill(fsf_req, sbtype, addr, length);
+		sbale->addr = addr;
+		sbale->length = length;
 	}
-	return total_length;
+	return 0;
 }
 
-
 /**
  * zfcp_qdio_sbals_from_sg - fill SBALs from scatter-gather list
  * @fsf_req: request to be processed
  * @sbtype: SBALE flags
  * @sg: scatter-gather list
- * @sg_count: number of elements in scatter-gather list
  * @max_sbals: upper bound for number of SBALs to be used
+ * Returns: number of bytes, or error (negativ)
  */
-int
-zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
-                        struct scatterlist *sgl, int sg_count, int max_sbals)
-{
-	int sg_index;
-	struct scatterlist *sg_segment;
-	int retval;
+int zfcp_qdio_sbals_from_sg(struct zfcp_fsf_req *fsf_req, unsigned long sbtype,
+			    struct scatterlist *sg, int max_sbals)
+{
 	volatile struct qdio_buffer_element *sbale;
-	int bytes = 0;
+	int retval, bytes = 0;
 
 	/* figure out last allowed SBAL */
 	zfcp_qdio_sbal_limit(fsf_req, max_sbals);
 
-	/* set storage-block type for current SBAL */
-	sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_last, 0);
+	/* set storage-block type for this request */
+	sbale = zfcp_qdio_sbale_req(fsf_req);
 	sbale->flags |= sbtype;
 
-	/* process all segements of scatter-gather list */
-	for_each_sg(sgl, sg_segment, sg_count, sg_index) {
-		retval = zfcp_qdio_sbals_from_segment(
-				fsf_req,
-				sbtype,
-				zfcp_sg_to_address(sg_segment),
-				sg_segment->length);
-		if (retval < 0) {
-			bytes = retval;
-			goto out;
-		} else
-                        bytes += retval;
+	for (; sg; sg = sg_next(sg)) {
+		retval = zfcp_qdio_fill_sbals(fsf_req, sbtype, sg_virt(sg),
+					      sg->length);
+		if (retval < 0)
+			return retval;
+		bytes += sg->length;
 	}
+
 	/* assume that no other SBALEs are to follow in the same SBAL */
 	sbale = zfcp_qdio_sbale_curr(fsf_req);
 	sbale->flags |= SBAL_FLAGS_LAST_ENTRY;
-out:
+
 	return bytes;
 }
 
+/**
+ * zfcp_qdio_send - set PCI flag in first SBALE and send req to QDIO
+ * @fsf_req: pointer to struct zfcp_fsf_req
+ * Returns: 0 on success, error otherwise
+ */
+int zfcp_qdio_send(struct zfcp_fsf_req *fsf_req)
+{
+	struct zfcp_adapter *adapter = fsf_req->adapter;
+	struct zfcp_qdio_queue *req_q = &adapter->req_q;
+	int first = fsf_req->sbal_first;
+	int count = fsf_req->sbal_number;
+	int retval, pci, pci_batch;
+	volatile struct qdio_buffer_element *sbale;
+
+	/* acknowledgements for transferred buffers */
+	pci_batch = req_q->pci_batch + count;
+	if (unlikely(pci_batch >= ZFCP_QDIO_PCI_INTERVAL)) {
+		pci_batch %= ZFCP_QDIO_PCI_INTERVAL;
+		pci = first + count - (pci_batch + 1);
+		pci %= QDIO_MAX_BUFFERS_PER_Q;
+		sbale = zfcp_qdio_sbale(req_q, pci, 0);
+		sbale->flags |= SBAL_FLAGS0_PCI;
+	}
+
+	retval = do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_OUTPUT, 0, first,
+			 count, NULL);
+	if (unlikely(retval)) {
+		zfcp_qdio_zero_sbals(req_q->sbal, first, count);
+		return retval;
+	}
+
+	/* account for transferred buffers */
+	atomic_sub(count, &req_q->count);
+	req_q->first += count;
+	req_q->first %= QDIO_MAX_BUFFERS_PER_Q;
+	req_q->pci_batch = pci_batch;
+	return 0;
+}
 
 /**
- * zfcp_qdio_sbals_from_scsicmnd - fill SBALs from scsi command
- * @fsf_req: request to be processed
- * @sbtype: SBALE flags
- * @scsi_cmnd: either scatter-gather list or buffer contained herein is used
- *	to fill SBALs
- */
-int
-zfcp_qdio_sbals_from_scsicmnd(struct zfcp_fsf_req *fsf_req,
-			      unsigned long sbtype, struct scsi_cmnd *scsi_cmnd)
-{
-	return zfcp_qdio_sbals_from_sg(fsf_req,	sbtype, scsi_sglist(scsi_cmnd),
-				       scsi_sg_count(scsi_cmnd),
-				       ZFCP_MAX_SBALS_PER_REQ);
+ * zfcp_qdio_zero_sbals - zero all sbals of the specified area and queue
+ * @buf: pointer to array of SBALS
+ * @first: integer specifying the SBAL number to start
+ * @count: integer specifying the number of SBALS to process
+ */
+void zfcp_qdio_zero_sbals(struct qdio_buffer *sbal[], int first, int count)
+{
+	int i, sbal_idx;
+
+	for (i = first; i < first + count; i++) {
+		sbal_idx = i % QDIO_MAX_BUFFERS_PER_Q;
+		memset(sbal[sbal_idx], 0, sizeof(struct qdio_buffer));
+	}
 }
 
 /**
- * zfcp_qdio_determine_pci - set PCI flag in first SBALE on qdio queue if needed
+ * zfcp_qdio_allocate - allocate queue memory and initialize QDIO data
+ * @adapter: pointer to struct zfcp_adapter
+ * Returns: -ENOMEM on memory allocation error or return value from
+ *          qdio_allocate
  */
-int
-zfcp_qdio_determine_pci(struct zfcp_qdio_queue *req_queue,
-			struct zfcp_fsf_req *fsf_req)
+int zfcp_qdio_allocate(struct zfcp_adapter *adapter)
 {
-	int new_distance_from_int;
-	int pci_pos;
-	volatile struct qdio_buffer_element *sbale;
+	struct qdio_initialize *init_data;
 
-	new_distance_from_int = req_queue->distance_from_int +
-                fsf_req->sbal_number;
+	if (zfcp_qdio_buffers_enqueue(adapter->req_q.sbal) ||
+		   zfcp_qdio_buffers_enqueue(adapter->resp_q.sbal))
+		return -ENOMEM;
 
-	if (unlikely(new_distance_from_int >= ZFCP_QDIO_PCI_INTERVAL)) {
-		new_distance_from_int %= ZFCP_QDIO_PCI_INTERVAL;
-                pci_pos  = fsf_req->sbal_first;
-		pci_pos += fsf_req->sbal_number;
-		pci_pos -= new_distance_from_int;
-		pci_pos -= 1;
-		pci_pos %= QDIO_MAX_BUFFERS_PER_Q;
-		sbale = zfcp_qdio_sbale_req(fsf_req, pci_pos, 0);
-		sbale->flags |= SBAL_FLAGS0_PCI;
-	}
-	return new_distance_from_int;
+	init_data = &adapter->qdio_init_data;
+
+	init_data->cdev = adapter->ccw_device;
+	init_data->q_format = QDIO_ZFCP_QFMT;
+	memcpy(init_data->adapter_name, zfcp_get_busid_by_adapter(adapter), 8);
+	ASCEBC(init_data->adapter_name, 8);
+	init_data->qib_param_field_format = 0;
+	init_data->qib_param_field = NULL;
+	init_data->input_slib_elements = NULL;
+	init_data->output_slib_elements = NULL;
+	init_data->min_input_threshold = 1;
+	init_data->max_input_threshold = 5000;
+	init_data->min_output_threshold = 1;
+	init_data->max_output_threshold = 1000;
+	init_data->no_input_qs = 1;
+	init_data->no_output_qs = 1;
+	init_data->input_handler = zfcp_qdio_int_resp;
+	init_data->output_handler = zfcp_qdio_int_req;
+	init_data->int_parm = (unsigned long) adapter;
+	init_data->flags = QDIO_INBOUND_0COPY_SBALS |
+			QDIO_OUTBOUND_0COPY_SBALS | QDIO_USE_OUTBOUND_PCIS;
+	init_data->input_sbal_addr_array =
+			(void **) (adapter->resp_q.sbal);
+	init_data->output_sbal_addr_array =
+			(void **) (adapter->req_q.sbal);
+
+	return qdio_allocate(init_data);
 }
 
-/*
- * function:	zfcp_zero_sbals
- *
- * purpose:	zeros specified range of SBALs
- *
- * returns:
+/**
+ * zfcp_close_qdio - close qdio queues for an adapter
  */
-void
-zfcp_qdio_zero_sbals(struct qdio_buffer *buf[], int first, int clean_count)
+void zfcp_qdio_close(struct zfcp_adapter *adapter)
 {
-	int cur_pos;
-	int index;
+	struct zfcp_qdio_queue *req_q;
+	int first, count;
 
-	for (cur_pos = first; cur_pos < (first + clean_count); cur_pos++) {
-		index = cur_pos % QDIO_MAX_BUFFERS_PER_Q;
-		memset(buf[index], 0, sizeof (struct qdio_buffer));
-		ZFCP_LOG_TRACE("zeroing BUFFER %d at address %p\n",
-			       index, buf[index]);
+	if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status))
+		return;
+
+	/* clear QDIOUP flag, thus do_QDIO is not called during qdio_shutdown */
+	req_q = &adapter->req_q;
+	write_lock_irq(&req_q->lock);
+	atomic_clear_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status);
+	write_unlock_irq(&req_q->lock);
+
+	while (qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR)
+			== -EINPROGRESS)
+		ssleep(1);
+
+	/* cleanup used outbound sbals */
+	count = atomic_read(&req_q->count);
+	if (count < QDIO_MAX_BUFFERS_PER_Q) {
+		first = (req_q->first + count) % QDIO_MAX_BUFFERS_PER_Q;
+		count = QDIO_MAX_BUFFERS_PER_Q - count;
+		zfcp_qdio_zero_sbals(req_q->sbal, first, count);
 	}
+	req_q->first = 0;
+	atomic_set(&req_q->count, 0);
+	req_q->pci_batch = 0;
+	adapter->resp_q.first = 0;
+	atomic_set(&adapter->resp_q.count, 0);
 }
 
-#undef ZFCP_LOG_AREA
+/**
+ * zfcp_qdio_open - prepare and initialize response queue
+ * @adapter: pointer to struct zfcp_adapter
+ * Returns: 0 on success, otherwise -EIO
+ */
+int zfcp_qdio_open(struct zfcp_adapter *adapter)
+{
+	volatile struct qdio_buffer_element *sbale;
+	int cc;
+
+	if (atomic_test_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &adapter->status))
+		return -EIO;
+
+	if (qdio_establish(&adapter->qdio_init_data)) {
+		dev_err(&adapter->ccw_device->dev,
+			 "Establish of QDIO queues failed.\n");
+		return -EIO;
+	}
+
+	if (qdio_activate(adapter->ccw_device, 0)) {
+		dev_err(&adapter->ccw_device->dev,
+			 "Activate of QDIO queues failed.\n");
+		goto failed_qdio;
+	}
+
+	for (cc = 0; cc < QDIO_MAX_BUFFERS_PER_Q; cc++) {
+		sbale = &(adapter->resp_q.sbal[cc]->element[0]);
+		sbale->length = 0;
+		sbale->flags = SBAL_FLAGS_LAST_ENTRY;
+		sbale->addr = NULL;
+	}
+
+	if (do_QDIO(adapter->ccw_device, QDIO_FLAG_SYNC_INPUT, 0, 0,
+		     QDIO_MAX_BUFFERS_PER_Q, NULL)) {
+		dev_err(&adapter->ccw_device->dev,
+			 "Init of QDIO response queue failed.\n");
+		goto failed_qdio;
+	}
+
+	/* set index of first avalable SBALS / number of available SBALS */
+	adapter->req_q.first = 0;
+	atomic_set(&adapter->req_q.count, QDIO_MAX_BUFFERS_PER_Q);
+	adapter->req_q.pci_batch = 0;
+
+	return 0;
+
+failed_qdio:
+	while (qdio_shutdown(adapter->ccw_device, QDIO_FLAG_CLEANUP_USING_CLEAR)
+			== -EINPROGRESS)
+		ssleep(1);
+
+	return -EIO;
+}
drivers/s390/scsi/zfcp_aux.c +7 -38

100 lines not on this page · raw message

drivers/s390/scsi/zfcp_ext.h +7 -11
@@ -57,21 +57,17 @@ extern int  zfcp_ccw_register(void);
 
 extern void zfcp_qdio_zero_sbals(struct qdio_buffer **, int, int);
 extern int  zfcp_qdio_allocate(struct zfcp_adapter *);
-extern int  zfcp_qdio_allocate_queues(struct zfcp_adapter *);
-extern void zfcp_qdio_free_queues(struct zfcp_adapter *);
-extern int  zfcp_qdio_determine_pci(struct zfcp_qdio_queue *,
-				    struct zfcp_fsf_req *);
+extern void zfcp_qdio_free(struct zfcp_adapter *);
+extern int  zfcp_qdio_send(struct zfcp_fsf_req *fsf_req);
 
 extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req
-	(struct zfcp_fsf_req *, int, int);
+	(struct zfcp_fsf_req *);
 extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_curr
 	(struct zfcp_fsf_req *);
 extern int zfcp_qdio_sbals_from_sg
-	(struct zfcp_fsf_req *, unsigned long, struct scatterlist *, int, int);
-extern int zfcp_qdio_sbals_from_scsicmnd
-	(struct zfcp_fsf_req *, unsigned long, struct scsi_cmnd *);
-
-
+	(struct zfcp_fsf_req *, unsigned long, struct scatterlist *, int);
+extern int zfcp_qdio_open(struct zfcp_adapter *adapter);
+extern void zfcp_qdio_close(struct zfcp_adapter *adapter);
 /******************************** FSF ****************************************/
 extern int  zfcp_fsf_open_port(struct zfcp_erp_action *);
 extern int  zfcp_fsf_close_port(struct zfcp_erp_action *);
@@ -95,7 +91,7 @@ extern int  zfcp_fsf_status_read(struct 
 extern int zfcp_status_read_refill(struct zfcp_adapter *adapter);
 extern int zfcp_fsf_req_create(struct zfcp_adapter *, u32, int, mempool_t *,
 			       unsigned long *, struct zfcp_fsf_req **)
-	__acquires(adapter->request_queue.queue_lock);
+	__acquires(adapter->req_q.lock);
 extern int zfcp_fsf_send_ct(struct zfcp_send_ct *, mempool_t *,
 			    struct zfcp_erp_action *);
 extern int zfcp_fsf_send_els(struct zfcp_send_els *);
drivers/s390/scsi/zfcp_def.h +7 -19
@@ -112,21 +112,10 @@ zfcp_address_to_sg(void *address, struct
         /* max. number of (data buffer) SBALEs in largest SBAL chain
            multiplied with number of sectors per 4k block */
 
-/* FIXME(tune): free space should be one max. SBAL chain plus what? */
-#define ZFCP_QDIO_PCI_INTERVAL		(QDIO_MAX_BUFFERS_PER_Q \
-                                         - (ZFCP_MAX_SBALS_PER_REQ + 4))
-
 #define ZFCP_SBAL_TIMEOUT               (5*HZ)
 
 #define ZFCP_TYPE2_RECOVERY_TIME        8	/* seconds */
 
-/* queue polling (values in microseconds) */
-#define ZFCP_MAX_INPUT_THRESHOLD 	5000	/* FIXME: tune */
-#define ZFCP_MAX_OUTPUT_THRESHOLD 	1000	/* FIXME: tune */
-#define ZFCP_MIN_INPUT_THRESHOLD 	1	/* ignored by QDIO layer */
-#define ZFCP_MIN_OUTPUT_THRESHOLD 	1	/* ignored by QDIO layer */
-
-#define QDIO_SCSI_QFMT			1	/* 1 for FSF */
 #define QBUFF_PER_PAGE			(PAGE_SIZE / sizeof(struct qdio_buffer))
 
 /********************* FSF SPECIFIC DEFINES *********************************/
@@ -649,13 +638,13 @@ struct zfcp_send_els {
 };
 
 struct zfcp_qdio_queue {
-	struct qdio_buffer *buffer[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */
-	u8		   free_index;	      /* index of next free bfr
+	struct qdio_buffer *sbal[QDIO_MAX_BUFFERS_PER_Q]; /* SBALs */
+	u8		   first;	      /* index of next free bfr
 						 in queue (free_count>0) */
-	atomic_t           free_count;	      /* number of free buffers
+	atomic_t           count;	      /* number of free buffers
 						 in queue */
-	rwlock_t	   queue_lock;	      /* lock for operations on queue */
-        int                distance_from_int; /* SBALs used since PCI indication
+	rwlock_t	   lock;	      /* lock for operations on queue */
+	int                pci_batch;	      /* SBALs since PCI indication
 						 was last set */
 };
 
@@ -711,15 +700,14 @@ struct zfcp_adapter {
 	struct list_head        port_remove_lh;    /* head of ports to be
 						      removed */
 	u32			ports;	           /* number of remote ports */
-	atomic_t		reqs_active;	   /* # active FSF reqs */
 	unsigned long		req_no;		   /* unique FSF req number */
 	struct list_head	*req_list;	   /* list of pending reqs */
 	spinlock_t		req_list_lock;	   /* request list lock */
-	struct zfcp_qdio_queue	request_queue;	   /* request queue */
+	struct zfcp_qdio_queue	req_q;		   /* request queue */
 	u32			fsf_req_seq_no;	   /* FSF cmnd seq number */
 	wait_queue_head_t	request_wq;	   /* can be used to wait for
 						      more avaliable SBALs */
-	struct zfcp_qdio_queue	response_queue;	   /* response queue */
+	struct zfcp_qdio_queue	resp_q;	   /* response queue */
 	rwlock_t		abort_lock;        /* Protects against SCSI
 						      stack abort/command
 						      completion races */
drivers/s390/scsi/zfcp_fsf.c +67 -111

527 lines not on this page · raw message

drivers/s390/scsi/zfcp_erp.c +4 -110

140 lines not on this page · raw message

drivers/s390/scsi/zfcp_dbf.c +2 -1
@@ -603,13 +603,14 @@ static const char *zfcp_rec_dbf_ids[] = 
 	[137]	= "hbaapi port open",
 	[138]	= "hbaapi unit open",
 	[139]	= "hbaapi unit shutdown",
-	[140]	= "qdio error",
+	[140]	= "qdio error outbound",
 	[141]	= "scsi host reset",
 	[142]	= "dismissing fsf request for recovery action",
 	[143]	= "recovery action timed out",
 	[144]	= "recovery action gone",
 	[145]	= "recovery action being processed",
 	[146]	= "recovery action ready for next step",
+	[147]	= "qdio error inbound",
 };
 
 static int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view,
#5 lore raw

PATCH 5/8 zfcp: Message cleanup

In reply to Christof Schmitt

From: Christof Schmitt <[email protected]>

Cleanup the messages used in the zfcp driver: Remove unnecessary debug and trace message and convert the remaining messages to standard kernel macros. Remove the zfcp message macros and while updating the whole flie also update the copyright headers.

---
 drivers/s390/scsi/Makefile             |    2 
 drivers/s390/scsi/zfcp_aux.c           |   75 -
 drivers/s390/scsi/zfcp_dbf.c           |   41 
 drivers/s390/scsi/zfcp_def.h           |  124 --
 drivers/s390/scsi/zfcp_erp.c           |  293 +-----
 drivers/s390/scsi/zfcp_ext.h           |   20 
 drivers/s390/scsi/zfcp_fsf.c           | 1557 +++++----------------------------
 drivers/s390/scsi/zfcp_fsf.h           |   20 
 drivers/s390/scsi/zfcp_scsi.c          |   64 -
 drivers/s390/scsi/zfcp_sysfs_adapter.c |   23 
 drivers/s390/scsi/zfcp_sysfs_driver.c  |  106 --
 drivers/s390/scsi/zfcp_sysfs_port.c    |   23 
 drivers/s390/scsi/zfcp_sysfs_unit.c    |   23 
 13 files changed, 396 insertions(+), 1975 deletions(-)
drivers/s390/scsi/zfcp_aux.c +21 -54
@@ -1,22 +1,9 @@
 /*
- * This file is part of the zfcp device driver for
- * FCP adapters for IBM System z9 and zSeries.
+ * zfcp device driver
  *
- * (C) Copyright IBM Corp. 2002, 2006
+ * Module interface and handling of zfcp data structures.
  *
- * 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.
+ * Copyright IBM Corporation 2002, 2008
  */
 
 /*
@@ -31,13 +18,16 @@
  *            Maxim Shchetynin
  *            Volker Sameske
  *            Ralph Wuerthner
+ *            Michael Loehr
+ *            Swen Schillig
+ *            Christof Schmitt
+ *            Martin Petermann
+ *            Sven Schuetz
  */
 
 #include <linux/miscdevice.h>
 #include "zfcp_ext.h"
 
-/* accumulated log level (module parameter) */
-static u32 loglevel = ZFCP_LOG_LEVEL_DEFAULTS;
 static char *device;
 /*********************** FUNCTION PROTOTYPES *********************************/
 
@@ -57,12 +47,6 @@ 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 ***********************/
 /****************************************************************/
@@ -87,8 +71,6 @@ _zfcp_hex_dump(char *addr, int count)
 /****** Functions to handle the request ID hash table    ********/
 /****************************************************************/
 
-#define ZFCP_LOG_AREA			ZFCP_LOG_AREA_FSF
-
 static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter)
 {
 	int idx;
@@ -118,14 +100,10 @@ int zfcp_reqlist_isempty(struct zfcp_ada
 	return 1;
 }
 
-#undef ZFCP_LOG_AREA
-
 /****************************************************************/
 /************** Uncategorised Functions *************************/
 /****************************************************************/
 
-#define ZFCP_LOG_AREA			ZFCP_LOG_AREA_OTHER
-
 /**
  * zfcp_device_setup - setup function
  * @str: pointer to parameter string
@@ -143,8 +121,11 @@ zfcp_device_setup(char *devstr)
 
 	len = strlen(devstr) + 1;
 	str = kmalloc(len, GFP_KERNEL);
-	if (!str)
-		goto err_out;
+	if (!str) {
+		pr_err("zfcp: Could not allocate memory for "
+		       "device parameter string, device not attached.\n");
+		return 0;
+	}
 	memcpy(str, devstr, len);
 
 	tmp = strchr(str, ',');
@@ -167,7 +148,8 @@ zfcp_device_setup(char *devstr)
 	return 1;
 
  err_out:
-	ZFCP_LOG_NORMAL("Parse error for device parameter string %s\n", str);
+	pr_err("zfcp: Parse error for device parameter string %s, "
+	       "device not attached.\n", str);
 	kfree(str);
 	return 0;
 }
@@ -248,8 +230,6 @@ zfcp_module_init(void)
 	if (!zfcp_data.gid_pn_cache)
 		goto out_gid_cache;
 
-	atomic_set(&zfcp_data.loglevel, loglevel);
-
 	/* initialize adapter list */
 	INIT_LIST_HEAD(&zfcp_data.adapter_list_head);
 
@@ -263,8 +243,7 @@ zfcp_module_init(void)
 
 	retval = misc_register(&zfcp_cfdc_misc);
 	if (retval != 0) {
-		ZFCP_LOG_INFO("registration of misc device "
-			      "zfcp_cfdc failed\n");
+		pr_err("zfcp: registration of misc device zfcp_cfdc failed\n");
 		goto out_misc;
 	}
 
@@ -277,7 +256,7 @@ zfcp_module_init(void)
 	/* setup dynamic I/O */
 	retval = zfcp_ccw_register();
 	if (retval) {
-		ZFCP_LOG_NORMAL("registration with common I/O layer failed\n");
+		pr_err("zfcp: Registration with common I/O layer failed.\n");
 		goto out_ccw_register;
 	}
 
@@ -300,14 +279,10 @@ zfcp_module_init(void)
 	return retval;
 }
 
-#undef ZFCP_LOG_AREA
-
 /****************************************************************/
 /****** Functions for configuration/set-up of structures ********/
 /****************************************************************/
 
-#define ZFCP_LOG_AREA			ZFCP_LOG_AREA_CONFIG
-
 /**
  * zfcp_get_unit_by_lun - find unit in unit list of port by FCP LUN
  * @port: pointer to port to search for unit
@@ -598,6 +573,8 @@ static void _zfcp_status_read_scheduler(
  * All adapter internal structures are set up.
  * Proc-fs entries are also created.
  *
+ * FIXME: Use -ENOMEM as return code for allocation failures
+ *
  * returns:	0             if a new adapter was successfully enqueued
  *              ZFCP_KNOWN    if an adapter with this devno was already present
  *		-ENOMEM       if alloc failed
@@ -615,11 +592,8 @@ zfcp_adapter_enqueue(struct ccw_device *
 
 	/* try to allocate new adapter data structure (zeroed) */
 	adapter = kzalloc(sizeof (struct zfcp_adapter), GFP_KERNEL);
-	if (!adapter) {
-		ZFCP_LOG_INFO("error: allocation of base adapter "
-			      "structure failed\n");
+	if (!adapter)
 		goto out;
-	}
 
 	ccw_device->handler = NULL;
 
@@ -760,7 +734,6 @@ zfcp_adapter_dequeue(struct zfcp_adapter
 	zfcp_reqlist_free(adapter);
 	kfree(adapter->fc_stats);
 	kfree(adapter->stats_reset_data);
-	ZFCP_LOG_TRACE("freeing adapter structure\n");
 	kfree(adapter);
  out:
 	return;
@@ -908,12 +881,8 @@ zfcp_nameserver_enqueue(struct zfcp_adap
 
 	port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_WKA,
 				 ZFCP_DID_DIRECTORY_SERVICE);
-	if (!port) {
-		ZFCP_LOG_INFO("error: enqueue of nameserver port for "
-			      "adapter %s failed\n",
-			      zfcp_get_busid_by_adapter(adapter));
+	if (!port)
 		return -ENXIO;
-	}
 	zfcp_port_put(port);
 
 	return 0;
@@ -946,5 +915,3 @@ int zfcp_sg_setup_table(struct scatterli
 	}
 	return 0;
 }
-
-#undef ZFCP_LOG_AREA
drivers/s390/scsi/zfcp_dbf.c +12 -29

75 lines not on this page · raw message

drivers/s390/scsi/zfcp_def.h +3 -121

148 lines not on this page · raw message

drivers/s390/scsi/zfcp_erp.c +57 -236

592 lines not on this page · raw message

drivers/s390/scsi/zfcp_ext.h +3 -17
@@ -1,22 +1,9 @@
 /*
- * This file is part of the zfcp device driver for
- * FCP adapters for IBM System z9 and zSeries.
+ * zfcp device driver
  *
- * (C) Copyright IBM Corp. 2002, 2006
+ * External function declarations.
  *
- * 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.
+ * Copyright IBM Corporation 2002, 2008
  */
 
 #ifndef ZFCP_EXT_H
@@ -27,7 +14,6 @@
 extern struct zfcp_data zfcp_data;
 
 /******************************** SYSFS  *************************************/
-extern struct attribute_group *zfcp_driver_attr_groups[];
 extern int  zfcp_sysfs_adapter_create_files(struct device *);
 extern void zfcp_sysfs_adapter_remove_files(struct device *);
 extern int  zfcp_sysfs_port_create_files(struct device *, u32);
drivers/s390/scsi/zfcp_fsf.c +277 -1280

1,970 lines not on this page · raw message

drivers/s390/scsi/zfcp_fsf.h +4 -16

Lines of this file are not shown. View the raw message.

drivers/s390/scsi/zfcp_scsi.c +9 -55

64 lines not on this page · raw message

drivers/s390/scsi/zfcp_sysfs_adapter.c +3 -20

Lines of this file are not shown. View the raw message.

drivers/s390/scsi/zfcp_sysfs_port.c +3 -20

Lines of this file are not shown. View the raw message.

drivers/s390/scsi/zfcp_sysfs_unit.c +3 -20

Lines of this file are not shown. View the raw message.

drivers/s390/scsi/zfcp_sysfs_driver.c deleted +0 -106

106 lines not on this page · raw message

drivers/s390/scsi/Makefile +1 -1

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Part of the diff is not shown here. View the raw message.

#6 lore raw

PATCH 6/8 zfcp: Add port_state attribute to sysfs

In reply to Christof Schmitt

From: Sven Schuetz <[email protected]>

The sysfs attribute /sys/class/fc_host/hostX/port_state was not set by zfcp so far.

Now, the appropriate members of the fc_function_template struct are set during its initialziation. The first is a boolean to show the port state. The second is a function pointer to the function zfcp_get_host_port_state, which reads the port state from our adapter status bits and calls fc_host_port_state with the approriate port state afterwards.

---
 drivers/s390/scsi/zfcp_scsi.c |   19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
drivers/s390/scsi/zfcp_scsi.c +19 -0
@@ -704,6 +704,23 @@ zfcp_reset_fc_host_stats(struct Scsi_Hos
 	}
 }
 
+static void zfcp_get_host_port_state(struct Scsi_Host *shost)
+{
+	struct zfcp_adapter *adapter =
+		(struct zfcp_adapter *)shost->hostdata[0];
+	int status = atomic_read(&adapter->status);
+
+	if ((status & ZFCP_STATUS_COMMON_RUNNING) &&
+	    !(status & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED))
+		fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
+	else if (status & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
+		fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN;
+	else if (status & ZFCP_STATUS_COMMON_ERP_FAILED)
+		fc_host_port_state(shost) = FC_PORTSTATE_ERROR;
+	else
+		fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
+}
+
 static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
 {
 	rport->dev_loss_tmo = timeout;
@@ -726,6 +743,8 @@ struct fc_function_template zfcp_transpo
 	.get_fc_host_stats = zfcp_get_fc_host_stats,
 	.reset_fc_host_stats = zfcp_reset_fc_host_stats,
 	.set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo,
+	.get_host_port_state = zfcp_get_host_port_state,
+	.show_host_port_state = 1,
 	/* no functions registered for following dynamic attributes but
 	   directly set by LLDD */
 	.show_host_port_type = 1,
#7 lore raw

PATCH 7/8 zfcp: Automatically attach remote ports

In reply to Christof Schmitt

From: Swen Schillig <[email protected]>

Automatically attach the remote ports in zfcp when the adapter is set online. This is done by querying all available ports from the FC namesever. The scan for remote ports is also triggered by RSCNs and can be triggered manually with the sysfs attribute 'port_rescan'.

---
 drivers/s390/scsi/zfcp_aux.c           |   36 ++--
 drivers/s390/scsi/zfcp_dbf.c           |    4 
 drivers/s390/scsi/zfcp_def.h           |    5 
 drivers/s390/scsi/zfcp_erp.c           |   42 +++--
 drivers/s390/scsi/zfcp_ext.h           |    4 
 drivers/s390/scsi/zfcp_fc.c            |  248 +++++++++++++++++++++++++++++++++
 drivers/s390/scsi/zfcp_fsf.c           |    3 
 drivers/s390/scsi/zfcp_sysfs_adapter.c |   25 +++
 8 files changed, 336 insertions(+), 31 deletions(-)
drivers/s390/scsi/zfcp_aux.c +20 -16
@@ -568,6 +568,19 @@ static void _zfcp_status_read_scheduler(
 					     stat_work));
 }
 
+static int zfcp_nameserver_enqueue(struct zfcp_adapter *adapter)
+{
+	struct zfcp_port *port;
+
+	port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_WKA,
+				 ZFCP_DID_DIRECTORY_SERVICE);
+	if (!port)
+		return -ENXIO;
+	zfcp_port_put(port);
+
+	return 0;
+}
+
 /*
  * Enqueues an adapter at the end of the adapter list in the driver data.
  * All adapter internal structures are set up.
@@ -648,6 +661,7 @@ zfcp_adapter_enqueue(struct ccw_device *
 	/* initialize lock of associated request queue */
 	rwlock_init(&adapter->req_q.lock);
 	INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
+	INIT_WORK(&adapter->scan_work, _zfcp_scan_ports_later);
 
 	/* mark adapter unusable as long as sysfs registration is not complete */
 	atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
@@ -673,6 +687,8 @@ zfcp_adapter_enqueue(struct ccw_device *
 
 	zfcp_data.adapters++;
 
+	zfcp_nameserver_enqueue(adapter);
+
 	goto out;
 
  generic_services_failed:
@@ -704,6 +720,7 @@ zfcp_adapter_dequeue(struct zfcp_adapter
 	int retval = 0;
 	unsigned long flags;
 
+	cancel_work_sync(&adapter->scan_work);
 	cancel_work_sync(&adapter->stat_work);
 	zfcp_adapter_scsi_unregister(adapter);
 	device_unregister(&adapter->generic_services);
@@ -816,13 +833,15 @@ zfcp_port_enqueue(struct zfcp_adapter *a
 			kfree(port);
 			return NULL;
 		}
-		port->d_id = d_id;
 		port->sysfs_device.parent = &adapter->generic_services;
 	} else {
 		snprintf(port->sysfs_device.bus_id,
 			 BUS_ID_SIZE, "0x%016llx", wwpn);
 		port->sysfs_device.parent = &adapter->ccw_device->dev;
 	}
+
+	port->d_id = d_id;
+
 	port->sysfs_device.release = zfcp_sysfs_port_release;
 	dev_set_drvdata(&port->sysfs_device, port);
 
@@ -873,21 +892,6 @@ zfcp_port_dequeue(struct zfcp_port *port
 	device_unregister(&port->sysfs_device);
 }
 
-/* Enqueues a nameserver port */
-int
-zfcp_nameserver_enqueue(struct zfcp_adapter *adapter)
-{
-	struct zfcp_port *port;
-
-	port = zfcp_port_enqueue(adapter, 0, ZFCP_STATUS_PORT_WKA,
-				 ZFCP_DID_DIRECTORY_SERVICE);
-	if (!port)
-		return -ENXIO;
-	zfcp_port_put(port);
-
-	return 0;
-}
-
 void zfcp_sg_free_table(struct scatterlist *sg, int count)
 {
 	int i;
drivers/s390/scsi/zfcp_def.h +5 -0
@@ -282,7 +282,10 @@ struct zfcp_rc_entry {
 #define ZFCP_CT_DIRECTORY_SERVICE	0xFC
 #define ZFCP_CT_NAME_SERVER		0x02
 #define ZFCP_CT_SYNCHRONOUS		0x00
+#define ZFCP_CT_SCSI_FCP		0x08
+#define ZFCP_CT_UNABLE_TO_PERFORM_CMD	0x09
 #define ZFCP_CT_GID_PN			0x0121
+#define ZFCP_CT_GPN_FT			0x0172
 #define ZFCP_CT_MAX_SIZE		0x1020
 #define ZFCP_CT_ACCEPT			0x8002
 #define ZFCP_CT_REJECT			0x8001
@@ -311,6 +314,7 @@ struct zfcp_rc_entry {
 #define ZFCP_STATUS_COMMON_ERP_INUSE		0x01000000
 #define ZFCP_STATUS_COMMON_ACCESS_DENIED	0x00800000
 #define ZFCP_STATUS_COMMON_ACCESS_BOXED		0x00400000
+#define ZFCP_STATUS_COMMON_NOESC		0x00200000
 
 /* adapter status */
 #define ZFCP_STATUS_ADAPTER_QDIOUP		0x00000002
@@ -629,6 +633,7 @@ struct zfcp_adapter {
 	struct fc_host_statistics *fc_stats;
 	struct fsf_qtcb_bottom_port *stats_reset_data;
 	unsigned long		stats_reset;
+	struct work_struct	scan_work;
 };
 
 /*
drivers/s390/scsi/zfcp_ext.h +2 -2
@@ -37,6 +37,8 @@ extern struct zfcp_port *zfcp_port_enque
 extern void   zfcp_port_dequeue(struct zfcp_port *);
 extern struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *, fcp_lun_t);
 extern void   zfcp_unit_dequeue(struct zfcp_unit *);
+extern int zfcp_scan_ports(struct zfcp_adapter *);
+extern void _zfcp_scan_ports_later(struct work_struct *work);
 
 /******************************* S/390 IO ************************************/
 extern int  zfcp_ccw_register(void);
@@ -97,8 +99,6 @@ extern int  zfcp_fc_ns_gid_pn_request(st
 extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
 extern void  zfcp_test_link(struct zfcp_port *);
 
-extern int  zfcp_nameserver_enqueue(struct zfcp_adapter *);
-
 /******************************* SCSI ****************************************/
 extern int  zfcp_adapter_scsi_register(struct zfcp_adapter *);
 extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
drivers/s390/scsi/zfcp_dbf.c +4 -0
@@ -596,6 +596,10 @@ static const char *zfcp_rec_dbf_ids[] = 
 	[145]	= "recovery action being processed",
 	[146]	= "recovery action ready for next step",
 	[147]	= "qdio error inbound",
+	[148]   = "nameserver needed for port scan",
+	[149]   = "port scan",
+	[150]	= "ptp attach",
+	[151]   = "port validation failed",
 };
 
 static int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view,
drivers/s390/scsi/zfcp_fc.c +248 -0

263 lines not on this page · raw message

drivers/s390/scsi/zfcp_erp.c +29 -13

82 lines not on this page · raw message

drivers/s390/scsi/zfcp_fsf.c +3 -0
@@ -874,6 +874,9 @@ zfcp_fsf_status_read_handler(struct zfcp
 		if (status_buffer->status_subtype &
 		    FSF_STATUS_READ_SUB_ACT_UPDATED)
 			zfcp_erp_adapter_access_changed(adapter, 135, fsf_req);
+		if (status_buffer->status_subtype &
+		    FSF_STATUS_READ_SUB_INCOMING_ELS)
+			schedule_work(&adapter->scan_work);
 		break;
 
 	case FSF_STATUS_READ_CFDC_UPDATED:
drivers/s390/scsi/zfcp_sysfs_adapter.c +25 -0
@@ -85,6 +85,30 @@ zfcp_sysfs_port_add_store(struct device 
 static DEVICE_ATTR(port_add, S_IWUSR, NULL, zfcp_sysfs_port_add_store);
 
 /**
+ * zfcp_sysfs_port_rescan - trigger manual port rescan
+ * @dev: pointer to belonging device
+ * @attr: pointer to struct device_attribute
+ * @buf: pointer to input buffer
+ * @count: number of bytes in buffer
+ */
+static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
+					    struct device_attribute *attr,
+					    const char *buf, size_t count)
+{
+	struct zfcp_adapter *adapter;
+	int ret;
+
+	adapter = dev_get_drvdata(dev);
+	if (atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status))
+		return -EBUSY;
+
+	ret = zfcp_scan_ports(adapter);
+
+	return ret ? ret : (ssize_t) count;
+}
+static DEVICE_ATTR(port_rescan, S_IWUSR, NULL, zfcp_sysfs_port_rescan_store);
+
+/**
  * zfcp_sysfs_port_remove_store - remove a port from sysfs tree
  * @dev: pointer to belonging device
  * @buf: pointer to input buffer
@@ -214,6 +238,7 @@ static struct attribute *zfcp_adapter_at
 	&dev_attr_in_recovery.attr,
 	&dev_attr_port_remove.attr,
 	&dev_attr_port_add.attr,
+	&dev_attr_port_rescan.attr,
 	&dev_attr_peer_wwnn.attr,
 	&dev_attr_peer_wwpn.attr,
 	&dev_attr_peer_d_id.attr,
#8 lore raw

Re: [patch 7/8] zfcp: Automatically attach remote ports

Quoted 2 lines · Christof Schmitt

Automatically attach the remote ports in zfcp when the adapter is set online.

What do you mean with "remote ports"?

Bastian

Signature · 2 lines
In the strict scientific sense we all feed on death -- even vegetarians.
		-- Spock, "Wolf in the Fold", stardate 3615.4
#9 lore raw

Re: [patch 7/8] zfcp: Automatically attach remote ports

Quoted 4 lines · Bastian Blank
Quoted 2 lines · Christof Schmitt

Automatically attach the remote ports in zfcp when the adapter is set online.

What do you mean with "remote ports"?

Ah, the part with the wwpn. Are you sure that this does not break on z900? I'm not sure about ports, but it restricts each lun to exactly one guest.

Bastian

Signature · 2 lines
To live is always desirable.
		-- Eleen the Capellan, "Friday's Child", stardate 3498.9
#10 lore raw

Re: [patch 7/8] zfcp: Automatically attach remote ports

Quoted 4 lines · Bastian Blank
Quoted 3 lines · Bastian Blank
Quoted 2 lines · Christof Schmitt

Automatically attach the remote ports in zfcp when the adapter is set online.

Quoted 8 lines
Quoted 1 line

What do you mean with "remote ports"?

Ah, the part with the wwpn. Are you sure that this does not break on z900? I'm not sure about ports, but it restricts each lun to exactly one guest.

Bastian

With remote ports I mean "remote storage ports", so something like a DS8000. In a switched environment a single adapter can have access to multiple storage ports, accessing a bunch of drives (LUNs).

A port itself is not restricting anything and remote ports are not limited to be used by only one adapter, that's the whole purpose of those setups.

This feature has nothing to do with LUNs but only with ports, so I don't really get what you wanted to say with your LUN restriction.

Swen

#11 lore raw

PATCH 8/8 zfcp: Remove sysfs attribute port_add

In reply to Christof Schmitt

From: Martin Peschke <[email protected]>

With the automatic scanning of remote ports in place, there is no need to add remote ports manually. So, remove the port_add attribute.

---
 drivers/s390/scsi/zfcp_sysfs_adapter.c |   46 ---------------------------------
 1 file changed, 46 deletions(-)
drivers/s390/scsi/zfcp_sysfs_adapter.c +0 -46
@@ -40,51 +40,6 @@ ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%
 			 (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status));
 
 /**
- * zfcp_sysfs_port_add_store - add a port to sysfs tree
- * @dev: pointer to belonging device
- * @buf: pointer to input buffer
- * @count: number of bytes in buffer
- *
- * Store function of the "port_add" attribute of an adapter.
- */
-static ssize_t
-zfcp_sysfs_port_add_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-	wwn_t wwpn;
-	char *endp;
-	struct zfcp_adapter *adapter;
-	struct zfcp_port *port;
-	int retval = -EINVAL;
-
-	down(&zfcp_data.config_sema);
-
-	adapter = dev_get_drvdata(dev);
-	if (atomic_test_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status)) {
-		retval = -EBUSY;
-		goto out;
-	}
-
-	wwpn = simple_strtoull(buf, &endp, 0);
-	if ((endp + 1) < (buf + count))
-		goto out;
-
-	port = zfcp_port_enqueue(adapter, wwpn, 0, 0);
-	if (!port)
-		goto out;
-
-	retval = 0;
-
-	zfcp_erp_port_reopen(port, 0, 91, NULL);
-	zfcp_erp_wait(port->adapter);
-	zfcp_port_put(port);
- out:
-	up(&zfcp_data.config_sema);
-	return retval ? retval : (ssize_t) count;
-}
-
-static DEVICE_ATTR(port_add, S_IWUSR, NULL, zfcp_sysfs_port_add_store);
-
-/**
  * zfcp_sysfs_port_rescan - trigger manual port rescan
  * @dev: pointer to belonging device
  * @attr: pointer to struct device_attribute
@@ -237,7 +192,6 @@ static struct attribute *zfcp_adapter_at
 	&dev_attr_failed.attr,
 	&dev_attr_in_recovery.attr,
 	&dev_attr_port_remove.attr,
-	&dev_attr_port_add.attr,
 	&dev_attr_port_rescan.attr,
 	&dev_attr_peer_wwnn.attr,
 	&dev_attr_peer_wwpn.attr,