linux/drivers/infiniband/hw/cxgb3/iwch.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2006 Chelsio, Inc. All rights reserved.
   3 *
   4 * This software is available to you under a choice of one of two
   5 * licenses.  You may choose to be licensed under the terms of the GNU
   6 * General Public License (GPL) Version 2, available from the file
   7 * COPYING in the main directory of this source tree, or the
   8 * OpenIB.org BSD license below:
   9 *
  10 *     Redistribution and use in source and binary forms, with or
  11 *     without modification, are permitted provided that the following
  12 *     conditions are met:
  13 *
  14 *      - Redistributions of source code must retain the above
  15 *        copyright notice, this list of conditions and the following
  16 *        disclaimer.
  17 *
  18 *      - Redistributions in binary form must reproduce the above
  19 *        copyright notice, this list of conditions and the following
  20 *        disclaimer in the documentation and/or other materials
  21 *        provided with the distribution.
  22 *
  23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  30 * SOFTWARE.
  31 */
  32#include <linux/module.h>
  33#include <linux/moduleparam.h>
  34
  35#include <rdma/ib_verbs.h>
  36
  37#include "cxgb3_offload.h"
  38#include "iwch_provider.h"
  39#include "iwch_user.h"
  40#include "iwch.h"
  41#include "iwch_cm.h"
  42
  43#define DRV_VERSION "1.1"
  44
  45MODULE_AUTHOR("Boyd Faulkner, Steve Wise");
  46MODULE_DESCRIPTION("Chelsio T3 RDMA Driver");
  47MODULE_LICENSE("Dual BSD/GPL");
  48MODULE_VERSION(DRV_VERSION);
  49
  50cxgb3_cpl_handler_func t3c_handlers[NUM_CPL_CMDS];
  51
  52static void open_rnic_dev(struct t3cdev *);
  53static void close_rnic_dev(struct t3cdev *);
  54static void iwch_event_handler(struct t3cdev *, u32, u32);
  55
  56struct cxgb3_client t3c_client = {
  57        .name = "iw_cxgb3",
  58        .add = open_rnic_dev,
  59        .remove = close_rnic_dev,
  60        .handlers = t3c_handlers,
  61        .redirect = iwch_ep_redirect,
  62        .event_handler = iwch_event_handler
  63};
  64
  65static LIST_HEAD(dev_list);
  66static DEFINE_MUTEX(dev_mutex);
  67
  68static void rnic_init(struct iwch_dev *rnicp)
  69{
  70        PDBG("%s iwch_dev %p\n", __func__,  rnicp);
  71        idr_init(&rnicp->cqidr);
  72        idr_init(&rnicp->qpidr);
  73        idr_init(&rnicp->mmidr);
  74        spin_lock_init(&rnicp->lock);
  75
  76        rnicp->attr.max_qps = T3_MAX_NUM_QP - 32;
  77        rnicp->attr.max_wrs = T3_MAX_QP_DEPTH;
  78        rnicp->attr.max_sge_per_wr = T3_MAX_SGE;
  79        rnicp->attr.max_sge_per_rdma_write_wr = T3_MAX_SGE;
  80        rnicp->attr.max_cqs = T3_MAX_NUM_CQ - 1;
  81        rnicp->attr.max_cqes_per_cq = T3_MAX_CQ_DEPTH;
  82        rnicp->attr.max_mem_regs = cxio_num_stags(&rnicp->rdev);
  83        rnicp->attr.max_phys_buf_entries = T3_MAX_PBL_SIZE;
  84        rnicp->attr.max_pds = T3_MAX_NUM_PD - 1;
  85        rnicp->attr.mem_pgsizes_bitmask = T3_PAGESIZE_MASK;
  86        rnicp->attr.max_mr_size = T3_MAX_MR_SIZE;
  87        rnicp->attr.can_resize_wq = 0;
  88        rnicp->attr.max_rdma_reads_per_qp = 8;
  89        rnicp->attr.max_rdma_read_resources =
  90            rnicp->attr.max_rdma_reads_per_qp * rnicp->attr.max_qps;
  91        rnicp->attr.max_rdma_read_qp_depth = 8; /* IRD */
  92        rnicp->attr.max_rdma_read_depth =
  93            rnicp->attr.max_rdma_read_qp_depth * rnicp->attr.max_qps;
  94        rnicp->attr.rq_overflow_handled = 0;
  95        rnicp->attr.can_modify_ird = 0;
  96        rnicp->attr.can_modify_ord = 0;
  97        rnicp->attr.max_mem_windows = rnicp->attr.max_mem_regs - 1;
  98        rnicp->attr.stag0_value = 1;
  99        rnicp->attr.zbva_support = 1;
 100        rnicp->attr.local_invalidate_fence = 1;
 101        rnicp->attr.cq_overflow_detection = 1;
 102        return;
 103}
 104
 105static void open_rnic_dev(struct t3cdev *tdev)
 106{
 107        struct iwch_dev *rnicp;
 108
 109        PDBG("%s t3cdev %p\n", __func__,  tdev);
 110        printk_once(KERN_INFO MOD "Chelsio T3 RDMA Driver - version %s\n",
 111                       DRV_VERSION);
 112        rnicp = (struct iwch_dev *)ib_alloc_device(sizeof(*rnicp));
 113        if (!rnicp) {
 114                printk(KERN_ERR MOD "Cannot allocate ib device\n");
 115                return;
 116        }
 117        rnicp->rdev.ulp = rnicp;
 118        rnicp->rdev.t3cdev_p = tdev;
 119
 120        mutex_lock(&dev_mutex);
 121
 122        if (cxio_rdev_open(&rnicp->rdev)) {
 123                mutex_unlock(&dev_mutex);
 124                printk(KERN_ERR MOD "Unable to open CXIO rdev\n");
 125                ib_dealloc_device(&rnicp->ibdev);
 126                return;
 127        }
 128
 129        rnic_init(rnicp);
 130
 131        list_add_tail(&rnicp->entry, &dev_list);
 132        mutex_unlock(&dev_mutex);
 133
 134        if (iwch_register_device(rnicp)) {
 135                printk(KERN_ERR MOD "Unable to register device\n");
 136                close_rnic_dev(tdev);
 137        }
 138        printk(KERN_INFO MOD "Initialized device %s\n",
 139               pci_name(rnicp->rdev.rnic_info.pdev));
 140        return;
 141}
 142
 143static void close_rnic_dev(struct t3cdev *tdev)
 144{
 145        struct iwch_dev *dev, *tmp;
 146        PDBG("%s t3cdev %p\n", __func__,  tdev);
 147        mutex_lock(&dev_mutex);
 148        list_for_each_entry_safe(dev, tmp, &dev_list, entry) {
 149                if (dev->rdev.t3cdev_p == tdev) {
 150                        list_del(&dev->entry);
 151                        iwch_unregister_device(dev);
 152                        cxio_rdev_close(&dev->rdev);
 153                        idr_destroy(&dev->cqidr);
 154                        idr_destroy(&dev->qpidr);
 155                        idr_destroy(&dev->mmidr);
 156                        ib_dealloc_device(&dev->ibdev);
 157                        break;
 158                }
 159        }
 160        mutex_unlock(&dev_mutex);
 161}
 162
 163static void iwch_event_handler(struct t3cdev *tdev, u32 evt, u32 port_id)
 164{
 165        struct cxio_rdev *rdev = tdev->ulp;
 166        struct iwch_dev *rnicp;
 167        struct ib_event event;
 168        u32    portnum = port_id + 1;
 169
 170        if (!rdev)
 171                return;
 172        rnicp = rdev_to_iwch_dev(rdev);
 173        switch (evt) {
 174        case OFFLOAD_STATUS_DOWN: {
 175                rdev->flags = CXIO_ERROR_FATAL;
 176                event.event  = IB_EVENT_DEVICE_FATAL;
 177                break;
 178                }
 179        case OFFLOAD_PORT_DOWN: {
 180                event.event  = IB_EVENT_PORT_ERR;
 181                break;
 182                }
 183        case OFFLOAD_PORT_UP: {
 184                event.event  = IB_EVENT_PORT_ACTIVE;
 185                break;
 186                }
 187        }
 188
 189        event.device = &rnicp->ibdev;
 190        event.element.port_num = portnum;
 191        ib_dispatch_event(&event);
 192
 193        return;
 194}
 195
 196static int __init iwch_init_module(void)
 197{
 198        int err;
 199
 200        err = cxio_hal_init();
 201        if (err)
 202                return err;
 203        err = iwch_cm_init();
 204        if (err)
 205                return err;
 206        cxio_register_ev_cb(iwch_ev_dispatch);
 207        cxgb3_register_client(&t3c_client);
 208        return 0;
 209}
 210
 211static void __exit iwch_exit_module(void)
 212{
 213        cxgb3_unregister_client(&t3c_client);
 214        cxio_unregister_ev_cb(iwch_ev_dispatch);
 215        iwch_cm_term();
 216        cxio_hal_exit();
 217}
 218
 219module_init(iwch_init_module);
 220module_exit(iwch_exit_module);
 221