Path: blob/master/drivers/infiniband/hw/cxgb3/iwch.c
15112 views
/*1* Copyright (c) 2006 Chelsio, Inc. All rights reserved.2*3* This software is available to you under a choice of one of two4* licenses. You may choose to be licensed under the terms of the GNU5* General Public License (GPL) Version 2, available from the file6* COPYING in the main directory of this source tree, or the7* OpenIB.org BSD license below:8*9* Redistribution and use in source and binary forms, with or10* without modification, are permitted provided that the following11* conditions are met:12*13* - Redistributions of source code must retain the above14* copyright notice, this list of conditions and the following15* disclaimer.16*17* - Redistributions in binary form must reproduce the above18* copyright notice, this list of conditions and the following19* disclaimer in the documentation and/or other materials20* provided with the distribution.21*22* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,23* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF24* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND25* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS26* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN27* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN28* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE29* SOFTWARE.30*/31#include <linux/module.h>32#include <linux/moduleparam.h>3334#include <rdma/ib_verbs.h>3536#include "cxgb3_offload.h"37#include "iwch_provider.h"38#include "iwch_user.h"39#include "iwch.h"40#include "iwch_cm.h"4142#define DRV_VERSION "1.1"4344MODULE_AUTHOR("Boyd Faulkner, Steve Wise");45MODULE_DESCRIPTION("Chelsio T3 RDMA Driver");46MODULE_LICENSE("Dual BSD/GPL");47MODULE_VERSION(DRV_VERSION);4849static void open_rnic_dev(struct t3cdev *);50static void close_rnic_dev(struct t3cdev *);51static void iwch_event_handler(struct t3cdev *, u32, u32);5253struct cxgb3_client t3c_client = {54.name = "iw_cxgb3",55.add = open_rnic_dev,56.remove = close_rnic_dev,57.handlers = t3c_handlers,58.redirect = iwch_ep_redirect,59.event_handler = iwch_event_handler60};6162static LIST_HEAD(dev_list);63static DEFINE_MUTEX(dev_mutex);6465static int disable_qp_db(int id, void *p, void *data)66{67struct iwch_qp *qhp = p;6869cxio_disable_wq_db(&qhp->wq);70return 0;71}7273static int enable_qp_db(int id, void *p, void *data)74{75struct iwch_qp *qhp = p;7677if (data)78ring_doorbell(qhp->rhp->rdev.ctrl_qp.doorbell, qhp->wq.qpid);79cxio_enable_wq_db(&qhp->wq);80return 0;81}8283static void disable_dbs(struct iwch_dev *rnicp)84{85spin_lock_irq(&rnicp->lock);86idr_for_each(&rnicp->qpidr, disable_qp_db, NULL);87spin_unlock_irq(&rnicp->lock);88}8990static void enable_dbs(struct iwch_dev *rnicp, int ring_db)91{92spin_lock_irq(&rnicp->lock);93idr_for_each(&rnicp->qpidr, enable_qp_db,94(void *)(unsigned long)ring_db);95spin_unlock_irq(&rnicp->lock);96}9798static void iwch_db_drop_task(struct work_struct *work)99{100struct iwch_dev *rnicp = container_of(work, struct iwch_dev,101db_drop_task.work);102enable_dbs(rnicp, 1);103}104105static void rnic_init(struct iwch_dev *rnicp)106{107PDBG("%s iwch_dev %p\n", __func__, rnicp);108idr_init(&rnicp->cqidr);109idr_init(&rnicp->qpidr);110idr_init(&rnicp->mmidr);111spin_lock_init(&rnicp->lock);112INIT_DELAYED_WORK(&rnicp->db_drop_task, iwch_db_drop_task);113114rnicp->attr.max_qps = T3_MAX_NUM_QP - 32;115rnicp->attr.max_wrs = T3_MAX_QP_DEPTH;116rnicp->attr.max_sge_per_wr = T3_MAX_SGE;117rnicp->attr.max_sge_per_rdma_write_wr = T3_MAX_SGE;118rnicp->attr.max_cqs = T3_MAX_NUM_CQ - 1;119rnicp->attr.max_cqes_per_cq = T3_MAX_CQ_DEPTH;120rnicp->attr.max_mem_regs = cxio_num_stags(&rnicp->rdev);121rnicp->attr.max_phys_buf_entries = T3_MAX_PBL_SIZE;122rnicp->attr.max_pds = T3_MAX_NUM_PD - 1;123rnicp->attr.mem_pgsizes_bitmask = T3_PAGESIZE_MASK;124rnicp->attr.max_mr_size = T3_MAX_MR_SIZE;125rnicp->attr.can_resize_wq = 0;126rnicp->attr.max_rdma_reads_per_qp = 8;127rnicp->attr.max_rdma_read_resources =128rnicp->attr.max_rdma_reads_per_qp * rnicp->attr.max_qps;129rnicp->attr.max_rdma_read_qp_depth = 8; /* IRD */130rnicp->attr.max_rdma_read_depth =131rnicp->attr.max_rdma_read_qp_depth * rnicp->attr.max_qps;132rnicp->attr.rq_overflow_handled = 0;133rnicp->attr.can_modify_ird = 0;134rnicp->attr.can_modify_ord = 0;135rnicp->attr.max_mem_windows = rnicp->attr.max_mem_regs - 1;136rnicp->attr.stag0_value = 1;137rnicp->attr.zbva_support = 1;138rnicp->attr.local_invalidate_fence = 1;139rnicp->attr.cq_overflow_detection = 1;140return;141}142143static void open_rnic_dev(struct t3cdev *tdev)144{145struct iwch_dev *rnicp;146147PDBG("%s t3cdev %p\n", __func__, tdev);148printk_once(KERN_INFO MOD "Chelsio T3 RDMA Driver - version %s\n",149DRV_VERSION);150rnicp = (struct iwch_dev *)ib_alloc_device(sizeof(*rnicp));151if (!rnicp) {152printk(KERN_ERR MOD "Cannot allocate ib device\n");153return;154}155rnicp->rdev.ulp = rnicp;156rnicp->rdev.t3cdev_p = tdev;157158mutex_lock(&dev_mutex);159160if (cxio_rdev_open(&rnicp->rdev)) {161mutex_unlock(&dev_mutex);162printk(KERN_ERR MOD "Unable to open CXIO rdev\n");163ib_dealloc_device(&rnicp->ibdev);164return;165}166167rnic_init(rnicp);168169list_add_tail(&rnicp->entry, &dev_list);170mutex_unlock(&dev_mutex);171172if (iwch_register_device(rnicp)) {173printk(KERN_ERR MOD "Unable to register device\n");174close_rnic_dev(tdev);175}176printk(KERN_INFO MOD "Initialized device %s\n",177pci_name(rnicp->rdev.rnic_info.pdev));178return;179}180181static void close_rnic_dev(struct t3cdev *tdev)182{183struct iwch_dev *dev, *tmp;184PDBG("%s t3cdev %p\n", __func__, tdev);185mutex_lock(&dev_mutex);186list_for_each_entry_safe(dev, tmp, &dev_list, entry) {187if (dev->rdev.t3cdev_p == tdev) {188dev->rdev.flags = CXIO_ERROR_FATAL;189synchronize_net();190cancel_delayed_work_sync(&dev->db_drop_task);191list_del(&dev->entry);192iwch_unregister_device(dev);193cxio_rdev_close(&dev->rdev);194idr_destroy(&dev->cqidr);195idr_destroy(&dev->qpidr);196idr_destroy(&dev->mmidr);197ib_dealloc_device(&dev->ibdev);198break;199}200}201mutex_unlock(&dev_mutex);202}203204static void iwch_event_handler(struct t3cdev *tdev, u32 evt, u32 port_id)205{206struct cxio_rdev *rdev = tdev->ulp;207struct iwch_dev *rnicp;208struct ib_event event;209u32 portnum = port_id + 1;210int dispatch = 0;211212if (!rdev)213return;214rnicp = rdev_to_iwch_dev(rdev);215switch (evt) {216case OFFLOAD_STATUS_DOWN: {217rdev->flags = CXIO_ERROR_FATAL;218synchronize_net();219event.event = IB_EVENT_DEVICE_FATAL;220dispatch = 1;221break;222}223case OFFLOAD_PORT_DOWN: {224event.event = IB_EVENT_PORT_ERR;225dispatch = 1;226break;227}228case OFFLOAD_PORT_UP: {229event.event = IB_EVENT_PORT_ACTIVE;230dispatch = 1;231break;232}233case OFFLOAD_DB_FULL: {234disable_dbs(rnicp);235break;236}237case OFFLOAD_DB_EMPTY: {238enable_dbs(rnicp, 1);239break;240}241case OFFLOAD_DB_DROP: {242unsigned long delay = 1000;243unsigned short r;244245disable_dbs(rnicp);246get_random_bytes(&r, 2);247delay += r & 1023;248249/*250* delay is between 1000-2023 usecs.251*/252schedule_delayed_work(&rnicp->db_drop_task,253usecs_to_jiffies(delay));254break;255}256}257258if (dispatch) {259event.device = &rnicp->ibdev;260event.element.port_num = portnum;261ib_dispatch_event(&event);262}263264return;265}266267static int __init iwch_init_module(void)268{269int err;270271err = cxio_hal_init();272if (err)273return err;274err = iwch_cm_init();275if (err)276return err;277cxio_register_ev_cb(iwch_ev_dispatch);278cxgb3_register_client(&t3c_client);279return 0;280}281282static void __exit iwch_exit_module(void)283{284cxgb3_unregister_client(&t3c_client);285cxio_unregister_ev_cb(iwch_ev_dispatch);286iwch_cm_term();287cxio_hal_exit();288}289290module_init(iwch_init_module);291module_exit(iwch_exit_module);292293294