Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband:
  IB/ehca: Reject dynamic memory add/remove when ehca adapter is present
  IB/ehca: Fix reported max number of QPs and CQs in systems with >1 adapter
  IPoIB: Set netdev offload features properly for child (VLAN) interfaces
  IPoIB: Clean up ethtool support
  mlx4_core: Add Ethernet PCI device IDs
  mlx4_en: Add driver for Mellanox ConnectX 10GbE NIC
  mlx4_core: Multiple port type support
  mlx4_core: Ethernet MAC/VLAN management
  mlx4_core: Get ethernet MTU and default address from firmware
  mlx4_core: Support multiple pre-reserved QP regions
  Update NetEffect maintainer emails to Intel emails
  RDMA/cxgb3: Remove cmid reference on tid allocation failures
  IB/mad: Use krealloc() to resize snoop table
  IPoIB: Always initialize poll_timer to avoid crash on unload
  IB/ehca: Don't allow creating UC QP with SRQ
  mlx4_core: Add QP range reservation support
  RDMA/ucma: Test ucma_alloc_multicast() return against NULL, not with IS_ERR()
This commit is contained in:
Linus Torvalds
2008-10-23 08:16:03 -07:00
44 changed files with 6394 additions and 125 deletions
+2 -2
View File
@@ -2928,9 +2928,9 @@ S: Maintained
NETEFFECT IWARP RNIC DRIVER (IW_NES)
P: Faisal Latif
M: flatif@neteffect.com
M: faisal.latif@intel.com
P: Chien Tung
M: ctung@neteffect.com
M: chien.tin.tung@intel.com
L: general@lists.openfabrics.org
W: http://www.neteffect.com
S: Supported
+5 -9
View File
@@ -406,19 +406,15 @@ static int register_snoop_agent(struct ib_mad_qp_info *qp_info,
if (i == qp_info->snoop_table_size) {
/* Grow table. */
new_snoop_table = kmalloc(sizeof mad_snoop_priv *
qp_info->snoop_table_size + 1,
GFP_ATOMIC);
new_snoop_table = krealloc(qp_info->snoop_table,
sizeof mad_snoop_priv *
(qp_info->snoop_table_size + 1),
GFP_ATOMIC);
if (!new_snoop_table) {
i = -ENOMEM;
goto out;
}
if (qp_info->snoop_table) {
memcpy(new_snoop_table, qp_info->snoop_table,
sizeof mad_snoop_priv *
qp_info->snoop_table_size);
kfree(qp_info->snoop_table);
}
qp_info->snoop_table = new_snoop_table;
qp_info->snoop_table_size++;
}
+2 -2
View File
@@ -904,8 +904,8 @@ static ssize_t ucma_join_multicast(struct ucma_file *file,
mutex_lock(&file->mut);
mc = ucma_alloc_multicast(ctx);
if (IS_ERR(mc)) {
ret = PTR_ERR(mc);
if (!mc) {
ret = -ENOMEM;
goto err1;
}
+1
View File
@@ -1942,6 +1942,7 @@ fail4:
fail3:
cxgb3_free_atid(ep->com.tdev, ep->atid);
fail2:
cm_id->rem_ref(cm_id);
put_ep(&ep->com);
out:
return err;
@@ -128,6 +128,8 @@ struct ehca_shca {
/* MR pgsize: bit 0-3 means 4K, 64K, 1M, 16M respectively */
u32 hca_cap_mr_pgsize;
int max_mtu;
int max_num_qps;
int max_num_cqs;
atomic_t num_cqs;
atomic_t num_qps;
};
+2 -2
View File
@@ -132,9 +132,9 @@ struct ib_cq *ehca_create_cq(struct ib_device *device, int cqe, int comp_vector,
if (cqe >= 0xFFFFFFFF - 64 - additional_cqe)
return ERR_PTR(-EINVAL);
if (!atomic_add_unless(&shca->num_cqs, 1, ehca_max_cq)) {
if (!atomic_add_unless(&shca->num_cqs, 1, shca->max_num_cqs)) {
ehca_err(device, "Unable to create CQ, max number of %i "
"CQs reached.", ehca_max_cq);
"CQs reached.", shca->max_num_cqs);
ehca_err(device, "To increase the maximum number of CQs "
"use the number_of_cqs module parameter.\n");
return ERR_PTR(-ENOSPC);
+68 -15
View File
@@ -44,6 +44,8 @@
#include <linux/slab.h>
#endif
#include <linux/notifier.h>
#include <linux/memory.h>
#include "ehca_classes.h"
#include "ehca_iverbs.h"
#include "ehca_mrmw.h"
@@ -366,22 +368,23 @@ static int ehca_sense_attributes(struct ehca_shca *shca)
shca->hca_cap_mr_pgsize |= pgsize_map[i + 1];
/* Set maximum number of CQs and QPs to calculate EQ size */
if (ehca_max_qp == -1)
ehca_max_qp = min_t(int, rblock->max_qp, EHCA_MAX_NUM_QUEUES);
else if (ehca_max_qp < 1 || ehca_max_qp > rblock->max_qp) {
ehca_gen_err("Requested number of QPs is out of range (1 - %i) "
"specified by HW", rblock->max_qp);
ret = -EINVAL;
goto sense_attributes1;
if (shca->max_num_qps == -1)
shca->max_num_qps = min_t(int, rblock->max_qp,
EHCA_MAX_NUM_QUEUES);
else if (shca->max_num_qps < 1 || shca->max_num_qps > rblock->max_qp) {
ehca_gen_warn("The requested number of QPs is out of range "
"(1 - %i) specified by HW. Value is set to %i",
rblock->max_qp, rblock->max_qp);
shca->max_num_qps = rblock->max_qp;
}
if (ehca_max_cq == -1)
ehca_max_cq = min_t(int, rblock->max_cq, EHCA_MAX_NUM_QUEUES);
else if (ehca_max_cq < 1 || ehca_max_cq > rblock->max_cq) {
ehca_gen_err("Requested number of CQs is out of range (1 - %i) "
"specified by HW", rblock->max_cq);
ret = -EINVAL;
goto sense_attributes1;
if (shca->max_num_cqs == -1)
shca->max_num_cqs = min_t(int, rblock->max_cq,
EHCA_MAX_NUM_QUEUES);
else if (shca->max_num_cqs < 1 || shca->max_num_cqs > rblock->max_cq) {
ehca_gen_warn("The requested number of CQs is out of range "
"(1 - %i) specified by HW. Value is set to %i",
rblock->max_cq, rblock->max_cq);
}
/* query max MTU from first port -- it's the same for all ports */
@@ -733,9 +736,13 @@ static int __devinit ehca_probe(struct of_device *dev,
ehca_gen_err("Cannot allocate shca memory.");
return -ENOMEM;
}
mutex_init(&shca->modify_mutex);
atomic_set(&shca->num_cqs, 0);
atomic_set(&shca->num_qps, 0);
shca->max_num_qps = ehca_max_qp;
shca->max_num_cqs = ehca_max_cq;
for (i = 0; i < ARRAY_SIZE(shca->sport); i++)
spin_lock_init(&shca->sport[i].mod_sqp_lock);
@@ -755,7 +762,7 @@ static int __devinit ehca_probe(struct of_device *dev,
goto probe1;
}
eq_size = 2 * ehca_max_cq + 4 * ehca_max_qp;
eq_size = 2 * shca->max_num_cqs + 4 * shca->max_num_qps;
/* create event queues */
ret = ehca_create_eq(shca, &shca->eq, EHCA_EQ, eq_size);
if (ret) {
@@ -964,6 +971,41 @@ void ehca_poll_eqs(unsigned long data)
spin_unlock(&shca_list_lock);
}
static int ehca_mem_notifier(struct notifier_block *nb,
unsigned long action, void *data)
{
static unsigned long ehca_dmem_warn_time;
switch (action) {
case MEM_CANCEL_OFFLINE:
case MEM_CANCEL_ONLINE:
case MEM_ONLINE:
case MEM_OFFLINE:
return NOTIFY_OK;
case MEM_GOING_ONLINE:
case MEM_GOING_OFFLINE:
/* only ok if no hca is attached to the lpar */
spin_lock(&shca_list_lock);
if (list_empty(&shca_list)) {
spin_unlock(&shca_list_lock);
return NOTIFY_OK;
} else {
spin_unlock(&shca_list_lock);
if (printk_timed_ratelimit(&ehca_dmem_warn_time,
30 * 1000))
ehca_gen_err("DMEM operations are not allowed"
"as long as an ehca adapter is"
"attached to the LPAR");
return NOTIFY_BAD;
}
}
return NOTIFY_OK;
}
static struct notifier_block ehca_mem_nb = {
.notifier_call = ehca_mem_notifier,
};
static int __init ehca_module_init(void)
{
int ret;
@@ -991,6 +1033,12 @@ static int __init ehca_module_init(void)
goto module_init2;
}
ret = register_memory_notifier(&ehca_mem_nb);
if (ret) {
ehca_gen_err("Failed registering memory add/remove notifier");
goto module_init3;
}
if (ehca_poll_all_eqs != 1) {
ehca_gen_err("WARNING!!!");
ehca_gen_err("It is possible to lose interrupts.");
@@ -1003,6 +1051,9 @@ static int __init ehca_module_init(void)
return 0;
module_init3:
ibmebus_unregister_driver(&ehca_driver);
module_init2:
ehca_destroy_slab_caches();
@@ -1018,6 +1069,8 @@ static void __exit ehca_module_exit(void)
ibmebus_unregister_driver(&ehca_driver);
unregister_memory_notifier(&ehca_mem_nb);
ehca_destroy_slab_caches();
ehca_destroy_comp_pool();
+8 -2
View File
@@ -465,9 +465,9 @@ static struct ehca_qp *internal_create_qp(
u32 swqe_size = 0, rwqe_size = 0, ib_qp_num;
unsigned long flags;
if (!atomic_add_unless(&shca->num_qps, 1, ehca_max_qp)) {
if (!atomic_add_unless(&shca->num_qps, 1, shca->max_num_qps)) {
ehca_err(pd->device, "Unable to create QP, max number of %i "
"QPs reached.", ehca_max_qp);
"QPs reached.", shca->max_num_qps);
ehca_err(pd->device, "To increase the maximum number of QPs "
"use the number_of_qps module parameter.\n");
return ERR_PTR(-ENOSPC);
@@ -502,6 +502,12 @@ static struct ehca_qp *internal_create_qp(
if (init_attr->srq) {
my_srq = container_of(init_attr->srq, struct ehca_qp, ib_srq);
if (qp_type == IB_QPT_UC) {
ehca_err(pd->device, "UC with SRQ not supported");
atomic_dec(&shca->num_qps);
return ERR_PTR(-EINVAL);
}
has_srq = 1;
parms.ext_type = EQPT_SRQBASE;
parms.srq_qpn = my_srq->real_qp_num;
+3 -3
View File
@@ -298,7 +298,7 @@ int mlx4_ib_mad_init(struct mlx4_ib_dev *dev)
int p, q;
int ret;
for (p = 0; p < dev->dev->caps.num_ports; ++p)
for (p = 0; p < dev->num_ports; ++p)
for (q = 0; q <= 1; ++q) {
agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
q ? IB_QPT_GSI : IB_QPT_SMI,
@@ -314,7 +314,7 @@ int mlx4_ib_mad_init(struct mlx4_ib_dev *dev)
return 0;
err:
for (p = 0; p < dev->dev->caps.num_ports; ++p)
for (p = 0; p < dev->num_ports; ++p)
for (q = 0; q <= 1; ++q)
if (dev->send_agent[p][q])
ib_unregister_mad_agent(dev->send_agent[p][q]);
@@ -327,7 +327,7 @@ void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev)
struct ib_mad_agent *agent;
int p, q;
for (p = 0; p < dev->dev->caps.num_ports; ++p) {
for (p = 0; p < dev->num_ports; ++p) {
for (q = 0; q <= 1; ++q) {
agent = dev->send_agent[p][q];
dev->send_agent[p][q] = NULL;
+9 -2
View File
@@ -574,7 +574,10 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
ibdev->ib_dev.owner = THIS_MODULE;
ibdev->ib_dev.node_type = RDMA_NODE_IB_CA;
ibdev->ib_dev.local_dma_lkey = dev->caps.reserved_lkey;
ibdev->ib_dev.phys_port_cnt = dev->caps.num_ports;
ibdev->num_ports = 0;
mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
ibdev->num_ports++;
ibdev->ib_dev.phys_port_cnt = ibdev->num_ports;
ibdev->ib_dev.num_comp_vectors = 1;
ibdev->ib_dev.dma_device = &dev->pdev->dev;
@@ -691,7 +694,7 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
struct mlx4_ib_dev *ibdev = ibdev_ptr;
int p;
for (p = 1; p <= dev->caps.num_ports; ++p)
for (p = 1; p <= ibdev->num_ports; ++p)
mlx4_CLOSE_PORT(dev, p);
mlx4_ib_mad_cleanup(ibdev);
@@ -706,6 +709,10 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
enum mlx4_dev_event event, int port)
{
struct ib_event ibev;
struct mlx4_ib_dev *ibdev = to_mdev((struct ib_device *) ibdev_ptr);
if (port > ibdev->num_ports)
return;
switch (event) {
case MLX4_DEV_EVENT_PORT_UP:
+1
View File
@@ -162,6 +162,7 @@ struct mlx4_ib_ah {
struct mlx4_ib_dev {
struct ib_device ib_dev;
struct mlx4_dev *dev;
int num_ports;
void __iomem *uar_map;
struct mlx4_uar priv_uar;
+19 -2
View File
@@ -451,6 +451,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
struct ib_qp_init_attr *init_attr,
struct ib_udata *udata, int sqpn, struct mlx4_ib_qp *qp)
{
int qpn;
int err;
mutex_init(&qp->mutex);
@@ -545,9 +546,17 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
}
}
err = mlx4_qp_alloc(dev->dev, sqpn, &qp->mqp);
if (sqpn) {
qpn = sqpn;
} else {
err = mlx4_qp_reserve_range(dev->dev, 1, 1, &qpn);
if (err)
goto err_wrid;
}
err = mlx4_qp_alloc(dev->dev, qpn, &qp->mqp);
if (err)
goto err_wrid;
goto err_qpn;
/*
* Hardware wants QPN written in big-endian order (after
@@ -560,6 +569,10 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
return 0;
err_qpn:
if (!sqpn)
mlx4_qp_release_range(dev->dev, qpn, 1);
err_wrid:
if (pd->uobject) {
if (!init_attr->srq)
@@ -655,6 +668,10 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
mlx4_ib_unlock_cqs(send_cq, recv_cq);
mlx4_qp_free(dev->dev, &qp->mqp);
if (!is_sqp(dev, qp))
mlx4_qp_release_range(dev->dev, qp->mqp.qpn, 1);
mlx4_mtt_cleanup(dev->dev, &qp->mtt);
if (is_user) {
+1
View File
@@ -507,6 +507,7 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev);
void ipoib_drain_cq(struct net_device *dev);
void ipoib_set_ethtool_ops(struct net_device *dev);
int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca);
#ifdef CONFIG_INFINIBAND_IPOIB_CM
+8 -1
View File
@@ -42,6 +42,13 @@ static void ipoib_get_drvinfo(struct net_device *netdev,
strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1);
}
static u32 ipoib_get_rx_csum(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
return test_bit(IPOIB_FLAG_CSUM, &priv->flags) &&
!test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
}
static int ipoib_get_coalesce(struct net_device *dev,
struct ethtool_coalesce *coal)
{
@@ -129,7 +136,7 @@ static void ipoib_get_ethtool_stats(struct net_device *dev,
static const struct ethtool_ops ipoib_ethtool_ops = {
.get_drvinfo = ipoib_get_drvinfo,
.get_tso = ethtool_op_get_tso,
.get_rx_csum = ipoib_get_rx_csum,
.get_coalesce = ipoib_get_coalesce,
.set_coalesce = ipoib_set_coalesce,
.get_flags = ethtool_op_get_flags,
+3 -4
View File
@@ -685,10 +685,6 @@ int ipoib_ib_dev_open(struct net_device *dev)
queue_delayed_work(ipoib_workqueue, &priv->ah_reap_task,
round_jiffies_relative(HZ));
init_timer(&priv->poll_timer);
priv->poll_timer.function = ipoib_ib_tx_timer_func;
priv->poll_timer.data = (unsigned long)dev;
set_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
return 0;
@@ -906,6 +902,9 @@ int ipoib_ib_dev_init(struct net_device *dev, struct ib_device *ca, int port)
return -ENODEV;
}
setup_timer(&priv->poll_timer, ipoib_ib_tx_timer_func,
(unsigned long) dev);
if (dev->flags & IFF_UP) {
if (ipoib_ib_dev_open(dev)) {
ipoib_transport_dev_cleanup(dev);
+39 -28
View File
@@ -1173,11 +1173,48 @@ int ipoib_add_pkey_attr(struct net_device *dev)
return device_create_file(&dev->dev, &dev_attr_pkey);
}
int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca)
{
struct ib_device_attr *device_attr;
int result = -ENOMEM;
device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
if (!device_attr) {
printk(KERN_WARNING "%s: allocation of %zu bytes failed\n",
hca->name, sizeof *device_attr);
return result;
}
result = ib_query_device(hca, device_attr);
if (result) {
printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n",
hca->name, result);
kfree(device_attr);
return result;
}
priv->hca_caps = device_attr->device_cap_flags;
kfree(device_attr);
if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) {
set_bit(IPOIB_FLAG_CSUM, &priv->flags);
priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
}
if (lro)
priv->dev->features |= NETIF_F_LRO;
if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO)
priv->dev->features |= NETIF_F_TSO;
return 0;
}
static struct net_device *ipoib_add_port(const char *format,
struct ib_device *hca, u8 port)
{
struct ipoib_dev_priv *priv;
struct ib_device_attr *device_attr;
struct ib_port_attr attr;
int result = -ENOMEM;
@@ -1206,31 +1243,8 @@ static struct net_device *ipoib_add_port(const char *format,
goto device_init_failed;
}
device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
if (!device_attr) {
printk(KERN_WARNING "%s: allocation of %zu bytes failed\n",
hca->name, sizeof *device_attr);
if (ipoib_set_dev_features(priv, hca))
goto device_init_failed;
}
result = ib_query_device(hca, device_attr);
if (result) {
printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n",
hca->name, result);
kfree(device_attr);
goto device_init_failed;
}
priv->hca_caps = device_attr->device_cap_flags;
kfree(device_attr);
if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) {
set_bit(IPOIB_FLAG_CSUM, &priv->flags);
priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
}
if (lro)
priv->dev->features |= NETIF_F_LRO;
/*
* Set the full membership bit, so that we join the right
@@ -1266,9 +1280,6 @@ static struct net_device *ipoib_add_port(const char *format,
goto event_failed;
}
if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO)
priv->dev->features |= NETIF_F_TSO;
result = register_netdev(priv->dev);
if (result) {
printk(KERN_WARNING "%s: couldn't register ipoib port %d; error %d\n",
@@ -93,6 +93,10 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
priv->mcast_mtu = priv->admin_mtu = priv->dev->mtu;
set_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags);
result = ipoib_set_dev_features(priv, ppriv->ca);
if (result)
goto device_init_failed;
priv->pkey = pkey;
memcpy(priv->dev->dev_addr, ppriv->dev->dev_addr, INFINIBAND_ALEN);
+9
View File
@@ -2504,6 +2504,15 @@ config PASEMI_MAC
This driver supports the on-chip 1/10Gbit Ethernet controller on
PA Semi's PWRficient line of chips.
config MLX4_EN
tristate "Mellanox Technologies 10Gbit Ethernet support"
depends on PCI && INET
select MLX4_CORE
select INET_LRO
help
This driver supports Mellanox Technologies ConnectX Ethernet
devices.
config MLX4_CORE
tristate
depends on PCI
+6 -1
View File
@@ -1,4 +1,9 @@
obj-$(CONFIG_MLX4_CORE) += mlx4_core.o
mlx4_core-y := alloc.o catas.o cmd.o cq.o eq.o fw.o icm.o intf.o main.o mcg.o \
mr.o pd.o profile.o qp.o reset.o srq.o
mr.o pd.o port.o profile.o qp.o reset.o srq.o
obj-$(CONFIG_MLX4_EN) += mlx4_en.o
mlx4_en-y := en_main.o en_tx.o en_rx.o en_params.o en_port.o en_cq.o \
en_resources.o en_netdev.o
+88 -9
View File
@@ -48,13 +48,16 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
obj = find_next_zero_bit(bitmap->table, bitmap->max, bitmap->last);
if (obj >= bitmap->max) {
bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask;
bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
& bitmap->mask;
obj = find_first_zero_bit(bitmap->table, bitmap->max);
}
if (obj < bitmap->max) {
set_bit(obj, bitmap->table);
bitmap->last = (obj + 1) & (bitmap->max - 1);
bitmap->last = (obj + 1);
if (bitmap->last == bitmap->max)
bitmap->last = 0;
obj |= bitmap->top;
} else
obj = -1;
@@ -66,16 +69,90 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj)
{
obj &= bitmap->max - 1;
mlx4_bitmap_free_range(bitmap, obj, 1);
}
static unsigned long find_aligned_range(unsigned long *bitmap,
u32 start, u32 nbits,
int len, int align)
{
unsigned long end, i;
again:
start = ALIGN(start, align);
while ((start < nbits) && test_bit(start, bitmap))
start += align;
if (start >= nbits)
return -1;
end = start+len;
if (end > nbits)
return -1;
for (i = start + 1; i < end; i++) {
if (test_bit(i, bitmap)) {
start = i + 1;
goto again;
}
}
return start;
}
u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align)
{
u32 obj, i;
if (likely(cnt == 1 && align == 1))
return mlx4_bitmap_alloc(bitmap);
spin_lock(&bitmap->lock);
clear_bit(obj, bitmap->table);
obj = find_aligned_range(bitmap->table, bitmap->last,
bitmap->max, cnt, align);
if (obj >= bitmap->max) {
bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
& bitmap->mask;
obj = find_aligned_range(bitmap->table, 0, bitmap->max,
cnt, align);
}
if (obj < bitmap->max) {
for (i = 0; i < cnt; i++)
set_bit(obj + i, bitmap->table);
if (obj == bitmap->last) {
bitmap->last = (obj + cnt);
if (bitmap->last >= bitmap->max)
bitmap->last = 0;
}
obj |= bitmap->top;
} else
obj = -1;
spin_unlock(&bitmap->lock);
return obj;
}
void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
{
u32 i;
obj &= bitmap->max + bitmap->reserved_top - 1;
spin_lock(&bitmap->lock);
for (i = 0; i < cnt; i++)
clear_bit(obj + i, bitmap->table);
bitmap->last = min(bitmap->last, obj);
bitmap->top = (bitmap->top + bitmap->max) & bitmap->mask;
bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
& bitmap->mask;
spin_unlock(&bitmap->lock);
}
int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved)
int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
u32 reserved_bot, u32 reserved_top)
{
int i;
@@ -85,14 +162,16 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask, u32 reserved
bitmap->last = 0;
bitmap->top = 0;
bitmap->max = num;
bitmap->max = num - reserved_top;
bitmap->mask = mask;
bitmap->reserved_top = reserved_top;
spin_lock_init(&bitmap->lock);
bitmap->table = kzalloc(BITS_TO_LONGS(num) * sizeof (long), GFP_KERNEL);
bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) *
sizeof (long), GFP_KERNEL);
if (!bitmap->table)
return -ENOMEM;
for (i = 0; i < reserved; ++i)
for (i = 0; i < reserved_bot; ++i)
set_bit(i, bitmap->table);
return 0;

Some files were not shown because too many files have changed in this diff Show More