summaryrefslogtreecommitdiff
path: root/drivers/infiniband/hw/ehca/ehca_main.c
diff options
context:
space:
mode:
authorHoang-Nam Nguyen <hnguyen@de.ibm.com>2006-11-06 23:56:39 (GMT)
committerRoland Dreier <rolandd@cisco.com>2006-11-09 20:41:57 (GMT)
commit7e28db5d8ff63b1cabc221c5cb84a5f45752f1c2 (patch)
tree4271d9afb545ab7e522a3a6e95c67a171f29cf84 /drivers/infiniband/hw/ehca/ehca_main.c
parent40eb006685387b2861bd7196be0ab7144c5d5b71 (diff)
downloadlinux-7e28db5d8ff63b1cabc221c5cb84a5f45752f1c2.tar.xz
IB/ehca: Assure 4K alignment for firmware control blocks
Assure 4K alignment for firmware control blocks in 64K page mode, because kzalloc()'s result address might not be 4K aligned if 64K pages are enabled. Thus, we introduce wrappers called ehca_{alloc,free}_fw_ctrlblock(), which use a slab cache for objects with 4K length and 4K alignment in order to alloc/free firmware control blocks in 64K page mode. In 4K page mode those wrappers just are defines of get_zeroed_page() and free_page(). Signed-off-by: Hoang-Nam Nguyen <hnguyen@de.ibm.com> Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/hw/ehca/ehca_main.c')
-rw-r--r--drivers/infiniband/hw/ehca/ehca_main.c56
1 files changed, 47 insertions, 9 deletions
diff --git a/drivers/infiniband/hw/ehca/ehca_main.c b/drivers/infiniband/hw/ehca/ehca_main.c
index 024d511..01f5aa9 100644
--- a/drivers/infiniband/hw/ehca/ehca_main.c
+++ b/drivers/infiniband/hw/ehca/ehca_main.c
@@ -40,6 +40,9 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#ifdef CONFIG_PPC_64K_PAGES
+#include <linux/slab.h>
+#endif
#include "ehca_classes.h"
#include "ehca_iverbs.h"
#include "ehca_mrmw.h"
@@ -49,7 +52,7 @@
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Christoph Raisch <raisch@de.ibm.com>");
MODULE_DESCRIPTION("IBM eServer HCA InfiniBand Device Driver");
-MODULE_VERSION("SVNEHCA_0017");
+MODULE_VERSION("SVNEHCA_0018");
int ehca_open_aqp1 = 0;
int ehca_debug_level = 0;
@@ -94,11 +97,31 @@ spinlock_t ehca_cq_idr_lock;
DEFINE_IDR(ehca_qp_idr);
DEFINE_IDR(ehca_cq_idr);
+
static struct list_head shca_list; /* list of all registered ehcas */
static spinlock_t shca_list_lock;
static struct timer_list poll_eqs_timer;
+#ifdef CONFIG_PPC_64K_PAGES
+static struct kmem_cache *ctblk_cache = NULL;
+
+void *ehca_alloc_fw_ctrlblock(void)
+{
+ void *ret = kmem_cache_zalloc(ctblk_cache, SLAB_KERNEL);
+ if (!ret)
+ ehca_gen_err("Out of memory for ctblk");
+ return ret;
+}
+
+void ehca_free_fw_ctrlblock(void *ptr)
+{
+ if (ptr)
+ kmem_cache_free(ctblk_cache, ptr);
+
+}
+#endif
+
static int ehca_create_slab_caches(void)
{
int ret;
@@ -133,6 +156,17 @@ static int ehca_create_slab_caches(void)
goto create_slab_caches5;
}
+#ifdef CONFIG_PPC_64K_PAGES
+ ctblk_cache = kmem_cache_create("ehca_cache_ctblk",
+ EHCA_PAGESIZE, H_CB_ALIGNMENT,
+ SLAB_HWCACHE_ALIGN,
+ NULL, NULL);
+ if (!ctblk_cache) {
+ ehca_gen_err("Cannot create ctblk SLAB cache.");
+ ehca_cleanup_mrmw_cache();
+ goto create_slab_caches5;
+ }
+#endif
return 0;
create_slab_caches5:
@@ -157,6 +191,10 @@ static void ehca_destroy_slab_caches(void)
ehca_cleanup_qp_cache();
ehca_cleanup_cq_cache();
ehca_cleanup_pd_cache();
+#ifdef CONFIG_PPC_64K_PAGES
+ if (ctblk_cache)
+ kmem_cache_destroy(ctblk_cache);
+#endif
}
#define EHCA_HCAAVER EHCA_BMASK_IBM(32,39)
@@ -168,7 +206,7 @@ int ehca_sense_attributes(struct ehca_shca *shca)
u64 h_ret;
struct hipz_query_hca *rblock;
- rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);
+ rblock = ehca_alloc_fw_ctrlblock();
if (!rblock) {
ehca_gen_err("Cannot allocate rblock memory.");
return -ENOMEM;
@@ -211,7 +249,7 @@ int ehca_sense_attributes(struct ehca_shca *shca)
shca->sport[1].rate = IB_RATE_30_GBPS;
num_ports1:
- kfree(rblock);
+ ehca_free_fw_ctrlblock(rblock);
return ret;
}
@@ -220,7 +258,7 @@ static int init_node_guid(struct ehca_shca *shca)
int ret = 0;
struct hipz_query_hca *rblock;
- rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL);
+ rblock = ehca_alloc_fw_ctrlblock();
if (!rblock) {
ehca_err(&shca->ib_device, "Can't allocate rblock memory.");
return -ENOMEM;
@@ -235,7 +273,7 @@ static int init_node_guid(struct ehca_shca *shca)
memcpy(&shca->ib_device.node_guid, &rblock->node_guid, sizeof(u64));
init_node_guid1:
- kfree(rblock);
+ ehca_free_fw_ctrlblock(rblock);
return ret;
}
@@ -431,7 +469,7 @@ static ssize_t ehca_show_##name(struct device *dev, \
\
shca = dev->driver_data; \
\
- rblock = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); \
+ rblock = ehca_alloc_fw_ctrlblock(); \
if (!rblock) { \
dev_err(dev, "Can't allocate rblock memory."); \
return 0; \
@@ -439,12 +477,12 @@ static ssize_t ehca_show_##name(struct device *dev, \
\
if (hipz_h_query_hca(shca->ipz_hca_handle, rblock) != H_SUCCESS) { \
dev_err(dev, "Can't query device properties"); \
- kfree(rblock); \
+ ehca_free_fw_ctrlblock(rblock); \
return 0; \
} \
\
data = rblock->name; \
- kfree(rblock); \
+ ehca_free_fw_ctrlblock(rblock); \
\
if ((strcmp(#name, "num_ports") == 0) && (ehca_nr_ports == 1)) \
return snprintf(buf, 256, "1\n"); \
@@ -752,7 +790,7 @@ int __init ehca_module_init(void)
int ret;
printk(KERN_INFO "eHCA Infiniband Device Driver "
- "(Rel.: SVNEHCA_0017)\n");
+ "(Rel.: SVNEHCA_0018)\n");
idr_init(&ehca_qp_idr);
idr_init(&ehca_cq_idr);
spin_lock_init(&ehca_qp_idr_lock);