Merge branch 'linus' into cont_syslog
[safe/jmp/linux-2.6] / drivers / infiniband / hw / mthca / mthca_profile.c
index 9ffe76e..8edb28a 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
+ * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  * SOFTWARE.
- *
- * $Id: mthca_profile.c 1349 2004-12-16 21:09:43Z roland $
  */
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/string.h>
+#include <linux/slab.h>
 
 #include "mthca_profile.h"
 
@@ -60,7 +61,7 @@ enum {
        MTHCA_NUM_PDS = 1 << 15
 };
 
-u64 mthca_make_profile(struct mthca_dev *dev,
+s64 mthca_make_profile(struct mthca_dev *dev,
                       struct mthca_profile *request,
                       struct mthca_dev_lim *dev_lim,
                       struct mthca_init_hca_param *init_hca)
@@ -74,17 +75,15 @@ u64 mthca_make_profile(struct mthca_dev *dev,
        };
 
        u64 mem_base, mem_avail;
-       u64 total_size = 0;
+       s64 total_size = 0;
        struct mthca_resource *profile;
        struct mthca_resource tmp;
        int i, j;
 
-       profile = kmalloc(MTHCA_RES_NUM * sizeof *profile, GFP_KERNEL);
+       profile = kzalloc(MTHCA_RES_NUM * sizeof *profile, GFP_KERNEL);
        if (!profile)
                return -ENOMEM;
 
-       memset(profile, 0, MTHCA_RES_NUM * sizeof *profile);
-
        profile[MTHCA_RES_QP].size   = dev_lim->qpc_entry_sz;
        profile[MTHCA_RES_EEC].size  = dev_lim->eec_entry_sz;
        profile[MTHCA_RES_SRQ].size  = dev_lim->srq_entry_sz;
@@ -95,12 +94,13 @@ u64 mthca_make_profile(struct mthca_dev *dev,
        profile[MTHCA_RES_RDB].size  = MTHCA_RDB_ENTRY_SIZE;
        profile[MTHCA_RES_MCG].size  = MTHCA_MGM_ENTRY_SIZE;
        profile[MTHCA_RES_MPT].size  = dev_lim->mpt_entry_sz;
-       profile[MTHCA_RES_MTT].size  = dev_lim->mtt_seg_sz;
+       profile[MTHCA_RES_MTT].size  = dev->limits.mtt_seg_size;
        profile[MTHCA_RES_UAR].size  = dev_lim->uar_scratch_entry_sz;
        profile[MTHCA_RES_UDAV].size = MTHCA_AV_SIZE;
        profile[MTHCA_RES_UARC].size = request->uarc_size;
 
        profile[MTHCA_RES_QP].num    = request->num_qp;
+       profile[MTHCA_RES_SRQ].num   = request->num_srq;
        profile[MTHCA_RES_EQP].num   = request->num_qp;
        profile[MTHCA_RES_RDB].num   = request->num_qp * request->rdb_per_qp;
        profile[MTHCA_RES_CQ].num    = request->num_cq;
@@ -116,11 +116,11 @@ u64 mthca_make_profile(struct mthca_dev *dev,
                profile[i].type     = i;
                profile[i].log_num  = max(ffs(profile[i].num) - 1, 0);
                profile[i].size    *= profile[i].num;
-               if (dev->hca_type == ARBEL_NATIVE)
+               if (mthca_is_memfree(dev))
                        profile[i].size = max(profile[i].size, (u64) PAGE_SIZE);
        }
 
-       if (dev->hca_type == ARBEL_NATIVE) {
+       if (mthca_is_memfree(dev)) {
                mem_base  = 0;
                mem_avail = dev_lim->hca.arbel.max_icm_sz;
        } else {
@@ -150,7 +150,7 @@ u64 mthca_make_profile(struct mthca_dev *dev,
                }
                if (total_size > mem_avail) {
                        mthca_err(dev, "Profile requires 0x%llx bytes; "
-                                 "won't in 0x%llx bytes of context memory.\n",
+                                 "won't fit in 0x%llx bytes of context memory.\n",
                                  (unsigned long long) total_size,
                                  (unsigned long long) mem_avail);
                        kfree(profile);
@@ -165,7 +165,7 @@ u64 mthca_make_profile(struct mthca_dev *dev,
                                  (unsigned long long) profile[i].size);
        }
 
-       if (dev->hca_type == ARBEL_NATIVE)
+       if (mthca_is_memfree(dev))
                mthca_dbg(dev, "HCA context memory: reserving %d KB\n",
                          (int) (total_size >> 10));
        else
@@ -223,16 +223,16 @@ u64 mthca_make_profile(struct mthca_dev *dev,
                        init_hca->mc_hash_sz      = 1 << (profile[i].log_num - 1);
                        break;
                case MTHCA_RES_MPT:
-                       dev->limits.num_mpts = profile[i].num;
-                       init_hca->mpt_base   = profile[i].start;
-                       init_hca->log_mpt_sz = profile[i].log_num;
+                       dev->limits.num_mpts   = profile[i].num;
+                       dev->mr_table.mpt_base = profile[i].start;
+                       init_hca->mpt_base     = profile[i].start;
+                       init_hca->log_mpt_sz   = profile[i].log_num;
                        break;
                case MTHCA_RES_MTT:
                        dev->limits.num_mtt_segs = profile[i].num;
-                       dev->limits.mtt_seg_size = dev_lim->mtt_seg_sz;
                        dev->mr_table.mtt_base   = profile[i].start;
                        init_hca->mtt_base       = profile[i].start;
-                       init_hca->mtt_seg_sz     = ffs(dev_lim->mtt_seg_sz) - 7;
+                       init_hca->mtt_seg_sz     = ffs(dev->limits.mtt_seg_size) - 7;
                        break;
                case MTHCA_RES_UAR:
                        dev->limits.num_uars       = profile[i].num;
@@ -260,6 +260,26 @@ u64 mthca_make_profile(struct mthca_dev *dev,
         */
        dev->limits.num_pds = MTHCA_NUM_PDS;
 
+       if (dev->mthca_flags & MTHCA_FLAG_SINAI_OPT &&
+           init_hca->log_mpt_sz > 23) {
+               mthca_warn(dev, "MPT table too large (requested size 2^%d >= 2^24)\n",
+                          init_hca->log_mpt_sz);
+               mthca_warn(dev, "Disabling memory key throughput optimization.\n");
+               dev->mthca_flags &= ~MTHCA_FLAG_SINAI_OPT;
+       }
+
+       /*
+        * For Tavor, FMRs use ioremapped PCI memory. For 32 bit
+        * systems it may use too much vmalloc space to map all MTT
+        * memory, so we reserve some MTTs for FMR access, taking them
+        * out of the MR pool. They don't use additional memory, but
+        * we assign them as part of the HCA profile anyway.
+        */
+       if (mthca_is_memfree(dev) || BITS_PER_LONG == 64)
+               dev->limits.fmr_reserved_mtts = 0;
+       else
+               dev->limits.fmr_reserved_mtts = request->fmr_reserved_mtts;
+
        kfree(profile);
        return total_size;
 }