mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
[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: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com> Compile fix ups and Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
d136205182
commit
dd52e0eaf8
@ -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;
|
||||
|
||||
int retval = 0;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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 ****************************************/
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user