Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd52e0ea authored by Heiko Carstens's avatar Heiko Carstens Committed by James Bottomley
Browse files

[SCSI] zfcp: create private slab caches to guarantee proper data alignment



Create private slab caches in order to guarantee proper alignment of
data structures that get passed to hardware.

Sidenote: with this patch slab cache debugging will finally work on s390
(at least no known problems left).

Furthermore this patch does some minor cleanups:
- store ptr for transport template in struct zfcp_data

Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarAndreas Herrmann <aherrman@de.ibm.com>
Compile fix ups and
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent d1362051
Loading
Loading
Loading
Loading
+58 −18
Original line number Diff line number Diff line
@@ -299,11 +299,45 @@ zfcp_init_device_configure(void)
	return;
}

static int calc_alignment(int size)
{
	int align = 1;

	if (!size)
		return 0;

	while ((size - align) > 0)
		align <<= 1;

	return align;
}

static int __init
zfcp_module_init(void)
{
	int retval = -ENOMEM;
	int size, align;

	size = sizeof(struct zfcp_fsf_req_qtcb);
	align = calc_alignment(size);
	zfcp_data.fsf_req_qtcb_cache =
		kmem_cache_create("zfcp_fsf", size, align, 0, NULL, NULL);
	if (!zfcp_data.fsf_req_qtcb_cache)
		goto out;

	int retval = 0;
	size = sizeof(struct fsf_status_read_buffer);
	align = calc_alignment(size);
	zfcp_data.sr_buffer_cache =
		kmem_cache_create("zfcp_sr", size, align, 0, NULL, NULL);
	if (!zfcp_data.sr_buffer_cache)
		goto out_sr_cache;

	size = sizeof(struct zfcp_gid_pn_data);
	align = calc_alignment(size);
	zfcp_data.gid_pn_cache =
		kmem_cache_create("zfcp_gid", size, align, 0, NULL, NULL);
	if (!zfcp_data.gid_pn_cache)
		goto out_gid_cache;

	atomic_set(&zfcp_data.loglevel, loglevel);

@@ -313,15 +347,16 @@ zfcp_module_init(void)
	/* 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;
	zfcp_data.scsi_transport_template =
		fc_attach_transport(&zfcp_transport_functions);
	if (!zfcp_data.scsi_transport_template)
		goto out_transport;

	retval = misc_register(&zfcp_cfdc_misc);
	if (retval != 0) {
		ZFCP_LOG_INFO("registration of misc device "
			      "zfcp_cfdc failed\n");
		goto out;
		goto out_misc;
	}

	ZFCP_LOG_TRACE("major/minor for zfcp_cfdc: %d/%d\n",
@@ -333,9 +368,6 @@ zfcp_module_init(void)
	/* 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) {
@@ -350,6 +382,14 @@ zfcp_module_init(void)

 out_ccw_register:
	misc_deregister(&zfcp_cfdc_misc);
 out_misc:
	fc_release_transport(zfcp_data.scsi_transport_template);
 out_transport:
	kmem_cache_destroy(zfcp_data.gid_pn_cache);
 out_gid_cache:
	kmem_cache_destroy(zfcp_data.sr_buffer_cache);
 out_sr_cache:
	kmem_cache_destroy(zfcp_data.fsf_req_qtcb_cache);
 out:
	return retval;
}
@@ -935,20 +975,20 @@ static int
zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
{
	adapter->pool.fsf_req_erp =
		mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_ERP_NR,
				sizeof(struct zfcp_fsf_req_pool_element));
		mempool_create_slab_pool(ZFCP_POOL_FSF_REQ_ERP_NR,
					 zfcp_data.fsf_req_qtcb_cache);
	if (!adapter->pool.fsf_req_erp)
		return -ENOMEM;

	adapter->pool.fsf_req_scsi =
		mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_SCSI_NR,
				sizeof(struct zfcp_fsf_req_pool_element));
		mempool_create_slab_pool(ZFCP_POOL_FSF_REQ_SCSI_NR,
					 zfcp_data.fsf_req_qtcb_cache);
	if (!adapter->pool.fsf_req_scsi)
		return -ENOMEM;

	adapter->pool.fsf_req_abort =
		mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_ABORT_NR,
				sizeof(struct zfcp_fsf_req_pool_element));
		mempool_create_slab_pool(ZFCP_POOL_FSF_REQ_ABORT_NR,
					 zfcp_data.fsf_req_qtcb_cache);
	if (!adapter->pool.fsf_req_abort)
		return -ENOMEM;

@@ -959,14 +999,14 @@ zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
		return -ENOMEM;

	adapter->pool.data_status_read =
		mempool_create_kmalloc_pool(ZFCP_POOL_STATUS_READ_NR,
					sizeof(struct fsf_status_read_buffer));
		mempool_create_slab_pool(ZFCP_POOL_STATUS_READ_NR,
					 zfcp_data.sr_buffer_cache);
	if (!adapter->pool.data_status_read)
		return -ENOMEM;

	adapter->pool.data_gid_pn =
		mempool_create_kmalloc_pool(ZFCP_POOL_DATA_GID_PN_NR,
					    sizeof(struct zfcp_gid_pn_data));
		mempool_create_slab_pool(ZFCP_POOL_DATA_GID_PN_NR,
					 zfcp_data.gid_pn_cache);
	if (!adapter->pool.data_gid_pn)
		return -ENOMEM;

+10 −6
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 */ 


#ifndef ZFCP_DEF_H
#define ZFCP_DEF_H

@@ -32,6 +31,10 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/slab.h>
#include <linux/mempool.h>
#include <linux/syscalls.h>
#include <linux/ioctl.h>
#include <scsi/scsi.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_cmnd.h>
@@ -39,14 +42,11 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_fc.h>
#include "zfcp_fsf.h"
#include <asm/ccwdev.h>
#include <asm/qdio.h>
#include <asm/debug.h>
#include <asm/ebcdic.h>
#include <linux/mempool.h>
#include <linux/syscalls.h>
#include <linux/ioctl.h>
#include "zfcp_fsf.h"


/********************* GENERAL DEFINES *********************************/
@@ -1016,6 +1016,7 @@ typedef void zfcp_fsf_req_handler_t(struct zfcp_fsf_req*);
/* driver data */
struct zfcp_data {
	struct scsi_host_template scsi_host_template;
	struct scsi_transport_template *scsi_transport_template;
        atomic_t                status;             /* Module status flags */
	struct list_head	adapter_list_head;  /* head of adapter list */
	struct list_head	adapter_remove_lh;  /* head of adapters to be
@@ -1031,6 +1032,9 @@ struct zfcp_data {
	wwn_t                   init_wwpn;
	fcp_lun_t               init_fcp_lun;
	char 			*driver_version;
	kmem_cache_t		*fsf_req_qtcb_cache;
	kmem_cache_t		*sr_buffer_cache;
	kmem_cache_t		*gid_pn_cache;
};

/**
@@ -1051,7 +1055,7 @@ struct zfcp_sg_list {
#define ZFCP_POOL_DATA_GID_PN_NR	1

/* struct used by memory pools for fsf_requests */
struct zfcp_fsf_req_pool_element {
struct zfcp_fsf_req_qtcb {
	struct zfcp_fsf_req fsf_req;
	struct fsf_qtcb qtcb;
};
+0 −1
Original line number Diff line number Diff line
@@ -130,7 +130,6 @@ extern int zfcp_scsi_command_async(struct zfcp_adapter *,struct zfcp_unit *,
				   struct scsi_cmnd *, struct timer_list *);
extern int zfcp_scsi_command_sync(struct zfcp_unit *, struct scsi_cmnd *,
				  struct timer_list *);
extern struct scsi_transport_template *zfcp_transport_template;
extern struct fc_function_template zfcp_transport_functions;

/******************************** ERP ****************************************/
+22 −11
Original line number Diff line number Diff line
@@ -100,14 +100,19 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
	if (req_flags & ZFCP_REQ_NO_QTCB)
		size = sizeof(struct zfcp_fsf_req);
	else
		size = sizeof(struct zfcp_fsf_req_pool_element);
		size = sizeof(struct zfcp_fsf_req_qtcb);

	if (likely(pool != NULL))
	if (likely(pool))
		ptr = mempool_alloc(pool, GFP_ATOMIC);
	else
	else {
		if (req_flags & ZFCP_REQ_NO_QTCB)
			ptr = kmalloc(size, GFP_ATOMIC);
		else
			ptr = kmem_cache_alloc(zfcp_data.fsf_req_qtcb_cache,
					       SLAB_ATOMIC);
	}

	if (unlikely(NULL == ptr))
	if (unlikely(!ptr))
		goto out;

	memset(ptr, 0, size);
@@ -115,9 +120,8 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
	if (req_flags & ZFCP_REQ_NO_QTCB) {
		fsf_req = (struct zfcp_fsf_req *) ptr;
	} else {
		fsf_req = &((struct zfcp_fsf_req_pool_element *) ptr)->fsf_req;
		fsf_req->qtcb =
			&((struct zfcp_fsf_req_pool_element *) ptr)->qtcb;
		fsf_req = &((struct zfcp_fsf_req_qtcb *) ptr)->fsf_req;
		fsf_req->qtcb =	&((struct zfcp_fsf_req_qtcb *) ptr)->qtcb;
	}

	fsf_req->pool = pool;
@@ -139,9 +143,16 @@ zfcp_fsf_req_alloc(mempool_t *pool, int req_flags)
void
zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req)
{
	if (likely(fsf_req->pool != NULL))
	if (likely(fsf_req->pool)) {
		mempool_free(fsf_req, fsf_req->pool);
	else
		return;
	}

	if (fsf_req->qtcb) {
		kmem_cache_free(zfcp_data.fsf_req_qtcb_cache, fsf_req);
		return;
	}

	kfree(fsf_req);
}

+2 −3
Original line number Diff line number Diff line
@@ -39,11 +39,10 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int,

static struct device_attribute *zfcp_sysfs_sdev_attrs[];

struct scsi_transport_template *zfcp_transport_template;

struct zfcp_data zfcp_data = {
	.scsi_host_template = {
		.name			= ZFCP_NAME,
		.module			= THIS_MODULE,
		.proc_name		= "zfcp",
		.slave_alloc		= zfcp_scsi_slave_alloc,
		.slave_configure	= zfcp_scsi_slave_configure,
@@ -607,7 +606,7 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
	adapter->scsi_host->max_channel = 0;
	adapter->scsi_host->unique_id = unique_id++;	/* FIXME */
	adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH;
	adapter->scsi_host->transportt = zfcp_transport_template;
	adapter->scsi_host->transportt = zfcp_data.scsi_transport_template;

	/*
	 * save a pointer to our own adapter data structure within