linux/drivers/infiniband/hw/mthca/mthca_mcg.c
Goldwyn Rodrigues cdb73db0b6 IB/mthca: Stop returning separate error and status from FW commands
Instead of having firmware command functions return an error and also
a status, leading to code like:

	err = mthca_FW_COMMAND(..., &status);
	if (err)
		goto out;
        if (status) {
		err = -E...;
		goto out;
	}

all over the place, just handle the FW status inside the FW command
handling code (the way mlx4 does it), so we can simply write:

	err = mthca_FW_COMMAND(...);
	if (err)
		goto out;

In addition to simplifying the source code, this also saves a healthy
chunk of text:

    add/remove: 0/0 grow/shrink: 10/88 up/down: 510/-3357 (-2847)
    function                                     old     new   delta
    static.trans_table                           324     584    +260
    mthca_cmd_poll                               352     477    +125
    mthca_cmd_wait                               511     567     +56
    mthca_table_put                              213     240     +27
    mthca_cleanup_db_tab                         372     387     +15
    __mthca_remove_one                           314     323      +9
    mthca_cleanup_user_db_tab                    275     283      +8
    __mthca_init_one                            1738    1746      +8
    mthca_cleanup                                 20      21      +1
    mthca_MAD_IFC                               1081    1082      +1
    mthca_MGID_HASH                               43      40      -3
    mthca_MAP_ICM_AUX                             23      20      -3
    mthca_MAP_ICM                                 19      16      -3
    mthca_MAP_FA                                  23      20      -3
    mthca_READ_MGM                                43      38      -5
    mthca_QUERY_SRQ                               43      38      -5
    mthca_QUERY_QP                                59      54      -5
    mthca_HW2SW_SRQ                               43      38      -5
    mthca_HW2SW_MPT                               60      55      -5
    mthca_HW2SW_EQ                                43      38      -5
    mthca_HW2SW_CQ                                43      38      -5
    mthca_free_icm_table                         120     114      -6
    mthca_query_srq                              214     206      -8
    mthca_free_qp                                662     654      -8
    mthca_cmd                                     38      28     -10
    mthca_alloc_db                              1321    1311     -10
    mthca_setup_hca                             1067    1055     -12
    mthca_WRITE_MTT                               35      22     -13
    mthca_WRITE_MGM                               40      27     -13
    mthca_UNMAP_ICM_AUX                           36      23     -13
    mthca_UNMAP_FA                                36      23     -13
    mthca_SYS_DIS                                 36      23     -13
    mthca_SYNC_TPT                                36      23     -13
    mthca_SW2HW_SRQ                               35      22     -13
    mthca_SW2HW_MPT                               35      22     -13
    mthca_SW2HW_EQ                                35      22     -13
    mthca_SW2HW_CQ                                35      22     -13
    mthca_RUN_FW                                  36      23     -13
    mthca_DISABLE_LAM                             36      23     -13
    mthca_CLOSE_IB                                36      23     -13
    mthca_CLOSE_HCA                               38      25     -13
    mthca_ARM_SRQ                                 39      26     -13
    mthca_free_icms                              178     164     -14
    mthca_QUERY_DDR                              389     375     -14
    mthca_resize_cq                             1063    1048     -15
    mthca_unmap_eq_icm                           123     107     -16
    mthca_map_eq_icm                             396     380     -16
    mthca_cmd_box                                 90      74     -16
    mthca_SET_IB                                 433     417     -16
    mthca_RESIZE_CQ                              369     353     -16
    mthca_MAP_ICM_page                           240     224     -16
    mthca_MAP_EQ                                 183     167     -16
    mthca_INIT_IB                                473     457     -16
    mthca_INIT_HCA                               745     729     -16
    mthca_map_user_db                            816     798     -18
    mthca_SYS_EN                                 157     139     -18
    mthca_cleanup_qp_table                        78      59     -19
    mthca_cleanup_eq_table                       168     149     -19
    mthca_UNMAP_ICM                              143     121     -22
    mthca_modify_srq                             172     149     -23
    mthca_unmap_fmr                              198     174     -24
    mthca_query_qp                               814     790     -24
    mthca_query_pkey                             343     319     -24
    mthca_SET_ICM_SIZE                            34      10     -24
    mthca_QUERY_DEV_LIM                         1870    1846     -24
    mthca_map_cmd                               1130    1105     -25
    mthca_ENABLE_LAM                             401     375     -26
    mthca_modify_port                            247     220     -27
    mthca_query_device                           884     850     -34
    mthca_NOP                                     75      41     -34
    mthca_table_get                              287     249     -38
    mthca_init_qp_table                          333     293     -40
    mthca_MODIFY_QP                              348     308     -40
    mthca_close_hca                              131      89     -42
    mthca_free_eq                                435     390     -45
    mthca_query_port                             755     705     -50
    mthca_free_cq                                581     528     -53
    mthca_alloc_icm_table                        578     524     -54
    mthca_multicast_attach                      1041     986     -55
    mthca_init_hca                               326     271     -55
    mthca_query_gid                              487     431     -56
    mthca_free_srq                               524     468     -56
    mthca_free_mr                                168     111     -57
    mthca_create_eq                             1560    1501     -59
    mthca_multicast_detach                       790     728     -62
    mthca_write_mtt                              918     854     -64
    mthca_register_device                       1406    1342     -64
    mthca_fmr_alloc                              947     883     -64
    mthca_mr_alloc                               652     582     -70
    mthca_process_mad                           1242    1164     -78
    mthca_dev_lim                                910     830     -80
    find_mgm                                     482     400     -82
    mthca_modify_qp                             3852    3753     -99
    mthca_init_cq                               1281    1181    -100
    mthca_alloc_srq                             1719    1610    -109
    mthca_init_eq_table                         1807    1679    -128
    mthca_init_tavor                             761     491    -270
    mthca_init_arbel                            2617    2098    -519

Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.de>
2011-07-15 13:33:20 -07:00

336 lines
7.9 KiB
C

/*
* Copyright (c) 2004 Topspin Communications. 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
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* 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.
*/
#include <linux/string.h>
#include <linux/gfp.h>
#include "mthca_dev.h"
#include "mthca_cmd.h"
struct mthca_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 */
/*
* Caller must hold MCG table semaphore. gid and mgm parameters must
* be properly aligned for command interface.
*
* Returns 0 unless a firmware command error occurs.
*
* If GID is found in MGM or MGM is empty, *index = *hash, *prev = -1
* and *mgm holds MGM entry.
*
* if GID is found in AMGM, *index = index in AMGM, *prev = index of
* previous entry in hash chain and *mgm holds AMGM entry.
*
* If no AMGM exists for given gid, *index = -1, *prev = index of last
* entry in hash chain and *mgm holds end of hash chain.
*/
static int find_mgm(struct mthca_dev *dev,
u8 *gid, struct mthca_mailbox *mgm_mailbox,
u16 *hash, int *prev, int *index)
{
struct mthca_mailbox *mailbox;
struct mthca_mgm *mgm = mgm_mailbox->buf;
u8 *mgid;
int err;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
return -ENOMEM;
mgid = mailbox->buf;
memcpy(mgid, gid, 16);
err = mthca_MGID_HASH(dev, mailbox, hash);
if (err) {
mthca_err(dev, "MGID_HASH failed (%d)\n", err);
goto out;
}
if (0)
mthca_dbg(dev, "Hash for %pI6 is %04x\n", gid, *hash);
*index = *hash;
*prev = -1;
do {
err = mthca_READ_MGM(dev, *index, mgm_mailbox);
if (err) {
mthca_err(dev, "READ_MGM failed (%d)\n", err);
goto out;
}
if (!memcmp(mgm->gid, zero_gid, 16)) {
if (*index != *hash) {
mthca_err(dev, "Found zero MGID in AMGM.\n");
err = -EINVAL;
}
goto out;
}
if (!memcmp(mgm->gid, gid, 16))
goto out;
*prev = *index;
*index = be32_to_cpu(mgm->next_gid_index) >> 6;
} while (*index);
*index = -1;
out:
mthca_free_mailbox(dev, mailbox);
return err;
}
int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
{
struct mthca_dev *dev = to_mdev(ibqp->device);
struct mthca_mailbox *mailbox;
struct mthca_mgm *mgm;
u16 hash;
int index, prev;
int link = 0;
int i;
int err;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
mgm = mailbox->buf;
mutex_lock(&dev->mcg_table.mutex);
err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
if (err)
goto out;
if (index != -1) {
if (!memcmp(mgm->gid, zero_gid, 16))
memcpy(mgm->gid, gid->raw, 16);
} else {
link = 1;
index = mthca_alloc(&dev->mcg_table.alloc);
if (index == -1) {
mthca_err(dev, "No AMGM entries left\n");
err = -ENOMEM;
goto out;
}
err = mthca_READ_MGM(dev, index, mailbox);
if (err) {
mthca_err(dev, "READ_MGM failed (%d)\n", err);
goto out;
}
memset(mgm, 0, sizeof *mgm);
memcpy(mgm->gid, gid->raw, 16);
}
for (i = 0; i < MTHCA_QP_PER_MGM; ++i)
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 (i == MTHCA_QP_PER_MGM) {
mthca_err(dev, "MGM at index %x is full.\n", index);
err = -ENOMEM;
goto out;
}
err = mthca_WRITE_MGM(dev, index, mailbox);
if (err) {
mthca_err(dev, "WRITE_MGM failed %d\n", err);
err = -EINVAL;
goto out;
}
if (!link)
goto out;
err = mthca_READ_MGM(dev, prev, mailbox);
if (err) {
mthca_err(dev, "READ_MGM failed %d\n", err);
goto out;
}
mgm->next_gid_index = cpu_to_be32(index << 6);
err = mthca_WRITE_MGM(dev, prev, mailbox);
if (err)
mthca_err(dev, "WRITE_MGM returned %d\n", err);
out:
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;
}
int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
{
struct mthca_dev *dev = to_mdev(ibqp->device);
struct mthca_mailbox *mailbox;
struct mthca_mgm *mgm;
u16 hash;
int prev, index;
int i, loc;
int err;
mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
if (IS_ERR(mailbox))
return PTR_ERR(mailbox);
mgm = mailbox->buf;
mutex_lock(&dev->mcg_table.mutex);
err = find_mgm(dev, gid->raw, mailbox, &hash, &prev, &index);
if (err)
goto out;
if (index == -1) {
mthca_err(dev, "MGID %pI6 not found\n", gid->raw);
err = -EINVAL;
goto out;
}
for (loc = -1, i = 0; i < MTHCA_QP_PER_MGM; ++i) {
if (mgm->qp[i] == cpu_to_be32(ibqp->qp_num | (1 << 31)))
loc = i;
if (!(mgm->qp[i] & cpu_to_be32(1 << 31)))
break;
}
if (loc == -1) {
mthca_err(dev, "QP %06x not found in MGM\n", ibqp->qp_num);
err = -EINVAL;
goto out;
}
mgm->qp[loc] = mgm->qp[i - 1];
mgm->qp[i - 1] = 0;
err = mthca_WRITE_MGM(dev, index, mailbox);
if (err) {
mthca_err(dev, "WRITE_MGM returned %d\n", err);
goto out;
}
if (i != 1)
goto out;
if (prev == -1) {
/* Remove entry from MGM */
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);
if (err) {
mthca_err(dev, "READ_MGM returned %d\n", err);
goto out;
}
} else
memset(mgm->gid, 0, 16);
err = mthca_WRITE_MGM(dev, index, mailbox);
if (err) {
mthca_err(dev, "WRITE_MGM returned %d\n", err);
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 */
int curr_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
err = mthca_READ_MGM(dev, prev, mailbox);
if (err) {
mthca_err(dev, "READ_MGM returned %d\n", err);
goto out;
}
mgm->next_gid_index = cpu_to_be32(curr_next_index << 6);
err = mthca_WRITE_MGM(dev, prev, mailbox);
if (err) {
mthca_err(dev, "WRITE_MGM returned %d\n", err);
goto out;
}
BUG_ON(index < dev->limits.num_mgms);
mthca_free(&dev->mcg_table.alloc, index);
}
out:
mutex_unlock(&dev->mcg_table.mutex);
mthca_free_mailbox(dev, mailbox);
return err;
}
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,
table_size,
table_size - 1,
dev->limits.num_mgms);
if (err)
return err;
mutex_init(&dev->mcg_table.mutex);
return 0;
}
void mthca_cleanup_mcg_table(struct mthca_dev *dev)
{
mthca_alloc_cleanup(&dev->mcg_table.alloc);
}