[SCSI] libfc: fcoe_transport_create fails in single-CPU environment
authorSteven Clark <sclark@crossbeam.com>
Fri, 9 Mar 2012 22:50:30 +0000 (14:50 -0800)
committerJames Bottomley <JBottomley@Parallels.com>
Wed, 28 Mar 2012 08:33:04 +0000 (09:33 +0100)
Starting fcoe fails at fcoe_transport_create when attempting to allocate a
pool of 4K exchanges on a 64-bit single-CPU environment because the call to
__alloc_percpu() is greater than the max of 32K.  This patch reduces the
number of exchanges to fit within the maximum allowed space.

[ Whitespace problems fixed by Robert Love to satisfy chechpatch.pl ]

Signed-off-by: Steven Clark <sclark@crossbeam.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/libfc/fc_exch.c

index 630291f018262a3143645afe911ea97be1365f55..aceffadb21c79d347fdc7f138bce81afaf2394c9 100644 (file)
@@ -2263,7 +2263,18 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport,
        mp->class = class;
        /* adjust em exch xid range for offload */
        mp->min_xid = min_xid;
-       mp->max_xid = max_xid;
+
+       /* reduce range so per cpu pool fits into PCPU_MIN_UNIT_SIZE pool */
+       pool_exch_range = (PCPU_MIN_UNIT_SIZE - sizeof(*pool)) /
+               sizeof(struct fc_exch *);
+       if ((max_xid - min_xid + 1) / (fc_cpu_mask + 1) > pool_exch_range) {
+               mp->max_xid = pool_exch_range * (fc_cpu_mask + 1) +
+                       min_xid - 1;
+       } else {
+               mp->max_xid = max_xid;
+               pool_exch_range = (mp->max_xid - mp->min_xid + 1) /
+                       (fc_cpu_mask + 1);
+       }
 
        mp->ep_pool = mempool_create_slab_pool(2, fc_em_cachep);
        if (!mp->ep_pool)
@@ -2274,7 +2285,6 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport,
         * divided across all cpus. The exch pointers array memory is
         * allocated for exch range per pool.
         */
-       pool_exch_range = (mp->max_xid - mp->min_xid + 1) / (fc_cpu_mask + 1);
        mp->pool_max_index = pool_exch_range - 1;
 
        /*