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);
 
        /* 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",
        /* 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) {
 
  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;
 }
 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;
 
                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;
 
 
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  */ 
 
-
 #ifndef ZFCP_DEF_H
 #define ZFCP_DEF_H
 
 #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>
 #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 *********************************/
 /* 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
        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;
 };
 
 /**
 #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;
 };
 
        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
-               ptr = kmalloc(size, GFP_ATOMIC);
+       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);
        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;
 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
-               kfree(fsf_req);
+               return;
+       }
+
+       if (fsf_req->qtcb) {
+               kmem_cache_free(zfcp_data.fsf_req_qtcb_cache, fsf_req);
+               return;
+       }
+
+       kfree(fsf_req);
 }
 
 /**