* $Id: mthca_mcg.c 1349 2004-12-16 21:09:43Z roland $
*/
-#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
#include "mthca_dev.h"
#include "mthca_cmd.h"
-enum {
- MTHCA_QP_PER_MGM = 4 * (MTHCA_MGM_ENTRY_SIZE / 16 - 2)
-};
-
struct mthca_mgm {
- u32 next_gid_index;
- u32 reserved[3];
- u8 gid[16];
- u32 qp[MTHCA_QP_PER_MGM];
+ __be32 next_gid_index;
+ u32 reserved[3];
+ u8 gid[16];
+ __be32 qp[MTHCA_QP_PER_MGM];
};
static const u8 zero_gid[16]; /* automatically initialized to 0 */
if (0)
mthca_dbg(dev, "Hash for %04x:%04x:%04x:%04x:"
"%04x:%04x:%04x:%04x is %04x\n",
- be16_to_cpu(((u16 *) gid)[0]), be16_to_cpu(((u16 *) gid)[1]),
- be16_to_cpu(((u16 *) gid)[2]), be16_to_cpu(((u16 *) gid)[3]),
- be16_to_cpu(((u16 *) gid)[4]), be16_to_cpu(((u16 *) gid)[5]),
- be16_to_cpu(((u16 *) gid)[6]), be16_to_cpu(((u16 *) gid)[7]),
+ be16_to_cpu(((__be16 *) gid)[0]),
+ be16_to_cpu(((__be16 *) gid)[1]),
+ be16_to_cpu(((__be16 *) gid)[2]),
+ be16_to_cpu(((__be16 *) gid)[3]),
+ be16_to_cpu(((__be16 *) gid)[4]),
+ be16_to_cpu(((__be16 *) gid)[5]),
+ be16_to_cpu(((__be16 *) gid)[6]),
+ be16_to_cpu(((__be16 *) gid)[7]),
*hash);
*index = *hash;
goto out;
if (status) {
mthca_err(dev, "READ_MGM returned status %02x\n", status);
- return -EINVAL;
+ err = -EINVAL;
+ goto out;
}
if (!memcmp(mgm->gid, zero_gid, 16)) {
goto out;
*prev = *index;
- *index = be32_to_cpu(mgm->next_gid_index) >> 5;
+ *index = be32_to_cpu(mgm->next_gid_index) >> 6;
} while (*index);
*index = -1;
return PTR_ERR(mailbox);
mgm = mailbox->buf;
- if (down_interruptible(&dev->mcg_table.sem))
- return -EINTR;
+ mutex_lock(&dev->mcg_table.mutex);
err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
if (err)
err = -EINVAL;
goto out;
}
-
+ memset(mgm, 0, sizeof *mgm);
memcpy(mgm->gid, gid->raw, 16);
- mgm->next_gid_index = 0;
}
for (i = 0; i < MTHCA_QP_PER_MGM; ++i)
- if (!(mgm->qp[i] & cpu_to_be32(1 << 31))) {
+ if (mgm->qp[i] == cpu_to_be32(ibqp->qp_num | (1 << 31))) {
+ mthca_dbg(dev, "QP %06x already a member of MGM\n",
+ ibqp->qp_num);
+ err = 0;
+ goto out;
+ } else if (!(mgm->qp[i] & cpu_to_be32(1 << 31))) {
mgm->qp[i] = cpu_to_be32(ibqp->qp_num | (1 << 31));
break;
}
if (status) {
mthca_err(dev, "WRITE_MGM returned status %02x\n", status);
err = -EINVAL;
+ goto out;
}
if (!link)
goto out;
}
- mgm->next_gid_index = cpu_to_be32(index << 5);
+ mgm->next_gid_index = cpu_to_be32(index << 6);
err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
if (err)
}
out:
- up(&dev->mcg_table.sem);
+ if (err && link && index != -1) {
+ BUG_ON(index < dev->limits.num_mgms);
+ mthca_free(&dev->mcg_table.alloc, index);
+ }
+ mutex_unlock(&dev->mcg_table.mutex);
+
mthca_free_mailbox(dev, mailbox);
return err;
}
return PTR_ERR(mailbox);
mgm = mailbox->buf;
- if (down_interruptible(&dev->mcg_table.sem))
- return -EINTR;
+ mutex_lock(&dev->mcg_table.mutex);
err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
if (err)
if (index == -1) {
mthca_err(dev, "MGID %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
"not found\n",
- be16_to_cpu(((u16 *) gid->raw)[0]),
- be16_to_cpu(((u16 *) gid->raw)[1]),
- be16_to_cpu(((u16 *) gid->raw)[2]),
- be16_to_cpu(((u16 *) gid->raw)[3]),
- be16_to_cpu(((u16 *) gid->raw)[4]),
- be16_to_cpu(((u16 *) gid->raw)[5]),
- be16_to_cpu(((u16 *) gid->raw)[6]),
- be16_to_cpu(((u16 *) gid->raw)[7]));
+ be16_to_cpu(((__be16 *) gid->raw)[0]),
+ be16_to_cpu(((__be16 *) gid->raw)[1]),
+ be16_to_cpu(((__be16 *) gid->raw)[2]),
+ be16_to_cpu(((__be16 *) gid->raw)[3]),
+ be16_to_cpu(((__be16 *) gid->raw)[4]),
+ be16_to_cpu(((__be16 *) gid->raw)[5]),
+ be16_to_cpu(((__be16 *) gid->raw)[6]),
+ be16_to_cpu(((__be16 *) gid->raw)[7]));
err = -EINVAL;
goto out;
}
if (i != 1)
goto out;
- goto out;
-
if (prev == -1) {
/* Remove entry from MGM */
- if (be32_to_cpu(mgm->next_gid_index) >> 5) {
- err = mthca_READ_MGM(dev,
- be32_to_cpu(mgm->next_gid_index) >> 5,
+ int amgm_index_to_free = be32_to_cpu(mgm->next_gid_index) >> 6;
+ if (amgm_index_to_free) {
+ err = mthca_READ_MGM(dev, amgm_index_to_free,
mailbox, &status);
if (err)
goto out;
err = -EINVAL;
goto out;
}
+ if (amgm_index_to_free) {
+ BUG_ON(amgm_index_to_free < dev->limits.num_mgms);
+ mthca_free(&dev->mcg_table.alloc, amgm_index_to_free);
+ }
} else {
/* Remove entry from AMGM */
- index = be32_to_cpu(mgm->next_gid_index) >> 5;
+ int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
err = mthca_READ_MGM(dev, prev, mailbox, &status);
if (err)
goto out;
goto out;
}
- mgm->next_gid_index = cpu_to_be32(index << 5);
+ mgm->next_gid_index = cpu_to_be32(curr_next_index << 6);
err = mthca_WRITE_MGM(dev, prev, mailbox, &status);
if (err)
err = -EINVAL;
goto out;
}
+ BUG_ON(index < dev->limits.num_mgms);
+ mthca_free(&dev->mcg_table.alloc, index);
}
out:
- up(&dev->mcg_table.sem);
+ mutex_unlock(&dev->mcg_table.mutex);
+
mthca_free_mailbox(dev, mailbox);
return err;
}
-int __devinit mthca_init_mcg_table(struct mthca_dev *dev)
+int mthca_init_mcg_table(struct mthca_dev *dev)
{
int err;
+ int table_size = dev->limits.num_mgms + dev->limits.num_amgms;
err = mthca_alloc_init(&dev->mcg_table.alloc,
- dev->limits.num_amgms,
- dev->limits.num_amgms - 1,
- 0);
+ table_size,
+ table_size - 1,
+ dev->limits.num_mgms);
if (err)
return err;
- init_MUTEX(&dev->mcg_table.sem);
+ mutex_init(&dev->mcg_table.mutex);
return 0;
}
-void __devexit mthca_cleanup_mcg_table(struct mthca_dev *dev)
+void mthca_cleanup_mcg_table(struct mthca_dev *dev)
{
mthca_alloc_cleanup(&dev->mcg_table.alloc);
}