⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mthca_main.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. * Copyright (c) 2005 Mellanox Technologies. 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. * * $Id: mthca_main.c 1396 2004-12-28 04:10:27Z roland $ */#include <linux/module.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/pci.h>#include <linux/interrupt.h>#include "mthca_dev.h"#include "mthca_config_reg.h"#include "mthca_cmd.h"#include "mthca_profile.h"#include "mthca_memfree.h"MODULE_AUTHOR("Roland Dreier");MODULE_DESCRIPTION("Mellanox InfiniBand HCA low-level driver");MODULE_LICENSE("Dual BSD/GPL");MODULE_VERSION(DRV_VERSION);#ifdef CONFIG_INFINIBAND_MTHCA_DEBUGint mthca_debug_level = 0;module_param_named(debug_level, mthca_debug_level, int, 0644);MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");#endif /* CONFIG_INFINIBAND_MTHCA_DEBUG */#ifdef CONFIG_PCI_MSIstatic int msi_x = 1;module_param(msi_x, int, 0444);MODULE_PARM_DESC(msi_x, "attempt to use MSI-X if nonzero");static int msi = 0;module_param(msi, int, 0444);MODULE_PARM_DESC(msi, "attempt to use MSI if nonzero (deprecated, use MSI-X instead)");#else /* CONFIG_PCI_MSI */#define msi_x (0)#define msi   (0)#endif /* CONFIG_PCI_MSI */static int tune_pci = 0;module_param(tune_pci, int, 0444);MODULE_PARM_DESC(tune_pci, "increase PCI burst from the default set by BIOS if nonzero");DEFINE_MUTEX(mthca_device_mutex);#define MTHCA_DEFAULT_NUM_QP            (1 << 16)#define MTHCA_DEFAULT_RDB_PER_QP        (1 << 2)#define MTHCA_DEFAULT_NUM_CQ            (1 << 16)#define MTHCA_DEFAULT_NUM_MCG           (1 << 13)#define MTHCA_DEFAULT_NUM_MPT           (1 << 17)#define MTHCA_DEFAULT_NUM_MTT           (1 << 20)#define MTHCA_DEFAULT_NUM_UDAV          (1 << 15)#define MTHCA_DEFAULT_NUM_RESERVED_MTTS (1 << 18)#define MTHCA_DEFAULT_NUM_UARC_SIZE     (1 << 18)static struct mthca_profile hca_profile = {	.num_qp             = MTHCA_DEFAULT_NUM_QP,	.rdb_per_qp         = MTHCA_DEFAULT_RDB_PER_QP,	.num_cq             = MTHCA_DEFAULT_NUM_CQ,	.num_mcg            = MTHCA_DEFAULT_NUM_MCG,	.num_mpt            = MTHCA_DEFAULT_NUM_MPT,	.num_mtt            = MTHCA_DEFAULT_NUM_MTT,	.num_udav           = MTHCA_DEFAULT_NUM_UDAV,          /* Tavor only */	.fmr_reserved_mtts  = MTHCA_DEFAULT_NUM_RESERVED_MTTS, /* Tavor only */	.uarc_size          = MTHCA_DEFAULT_NUM_UARC_SIZE,     /* Arbel only */};module_param_named(num_qp, hca_profile.num_qp, int, 0444);MODULE_PARM_DESC(num_qp, "maximum number of QPs per HCA");module_param_named(rdb_per_qp, hca_profile.rdb_per_qp, int, 0444);MODULE_PARM_DESC(rdb_per_qp, "number of RDB buffers per QP");module_param_named(num_cq, hca_profile.num_cq, int, 0444);MODULE_PARM_DESC(num_cq, "maximum number of CQs per HCA");module_param_named(num_mcg, hca_profile.num_mcg, int, 0444);MODULE_PARM_DESC(num_mcg, "maximum number of multicast groups per HCA");module_param_named(num_mpt, hca_profile.num_mpt, int, 0444);MODULE_PARM_DESC(num_mpt,		"maximum number of memory protection table entries per HCA");module_param_named(num_mtt, hca_profile.num_mtt, int, 0444);MODULE_PARM_DESC(num_mtt,		 "maximum number of memory translation table segments per HCA");module_param_named(num_udav, hca_profile.num_udav, int, 0444);MODULE_PARM_DESC(num_udav, "maximum number of UD address vectors per HCA");module_param_named(fmr_reserved_mtts, hca_profile.fmr_reserved_mtts, int, 0444);MODULE_PARM_DESC(fmr_reserved_mtts,		 "number of memory translation table segments reserved for FMR");static const char mthca_version[] __devinitdata =	DRV_NAME ": Mellanox InfiniBand HCA driver v"	DRV_VERSION " (" DRV_RELDATE ")\n";static int mthca_tune_pci(struct mthca_dev *mdev){	if (!tune_pci)		return 0;	/* First try to max out Read Byte Count */	if (pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX)) {		if (pcix_set_mmrbc(mdev->pdev, pcix_get_max_mmrbc(mdev->pdev))) {			mthca_err(mdev, "Couldn't set PCI-X max read count, "				"aborting.\n");			return -ENODEV;		}	} else if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE))		mthca_info(mdev, "No PCI-X capability, not setting RBC.\n");	if (pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP)) {		if (pcie_set_readrq(mdev->pdev, 4096)) {			mthca_err(mdev, "Couldn't write PCI Express read request, "				"aborting.\n");			return -ENODEV;		}	} else if (mdev->mthca_flags & MTHCA_FLAG_PCIE)		mthca_info(mdev, "No PCI Express capability, "			   "not setting Max Read Request Size.\n");	return 0;}static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim){	int err;	u8 status;	err = mthca_QUERY_DEV_LIM(mdev, dev_lim, &status);	if (err) {		mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");		return err;	}	if (status) {		mthca_err(mdev, "QUERY_DEV_LIM returned status 0x%02x, "			  "aborting.\n", status);		return -EINVAL;	}	if (dev_lim->min_page_sz > PAGE_SIZE) {		mthca_err(mdev, "HCA minimum page size of %d bigger than "			  "kernel PAGE_SIZE of %ld, aborting.\n",			  dev_lim->min_page_sz, PAGE_SIZE);		return -ENODEV;	}	if (dev_lim->num_ports > MTHCA_MAX_PORTS) {		mthca_err(mdev, "HCA has %d ports, but we only support %d, "			  "aborting.\n",			  dev_lim->num_ports, MTHCA_MAX_PORTS);		return -ENODEV;	}	if (dev_lim->uar_size > pci_resource_len(mdev->pdev, 2)) {		mthca_err(mdev, "HCA reported UAR size of 0x%x bigger than "			  "PCI resource 2 size of 0x%llx, aborting.\n",			  dev_lim->uar_size,			  (unsigned long long)pci_resource_len(mdev->pdev, 2));		return -ENODEV;	}	mdev->limits.num_ports      	= dev_lim->num_ports;	mdev->limits.vl_cap             = dev_lim->max_vl;	mdev->limits.mtu_cap            = dev_lim->max_mtu;	mdev->limits.gid_table_len  	= dev_lim->max_gids;	mdev->limits.pkey_table_len 	= dev_lim->max_pkeys;	mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay;	mdev->limits.max_sg             = dev_lim->max_sg;	mdev->limits.max_wqes           = dev_lim->max_qp_sz;	mdev->limits.max_qp_init_rdma   = dev_lim->max_requester_per_qp;	mdev->limits.reserved_qps       = dev_lim->reserved_qps;	mdev->limits.max_srq_wqes       = dev_lim->max_srq_sz;	mdev->limits.reserved_srqs      = dev_lim->reserved_srqs;	mdev->limits.reserved_eecs      = dev_lim->reserved_eecs;	mdev->limits.max_desc_sz        = dev_lim->max_desc_sz;	mdev->limits.max_srq_sge	= mthca_max_srq_sge(mdev);	/*	 * Subtract 1 from the limit because we need to allocate a	 * spare CQE so the HCA HW can tell the difference between an	 * empty CQ and a full CQ.	 */	mdev->limits.max_cqes           = dev_lim->max_cq_sz - 1;	mdev->limits.reserved_cqs       = dev_lim->reserved_cqs;	mdev->limits.reserved_eqs       = dev_lim->reserved_eqs;	mdev->limits.reserved_mtts      = dev_lim->reserved_mtts;	mdev->limits.reserved_mrws      = dev_lim->reserved_mrws;	mdev->limits.reserved_uars      = dev_lim->reserved_uars;	mdev->limits.reserved_pds       = dev_lim->reserved_pds;	mdev->limits.port_width_cap     = dev_lim->max_port_width;	mdev->limits.page_size_cap      = ~(u32) (dev_lim->min_page_sz - 1);	mdev->limits.flags              = dev_lim->flags;	/*	 * For old FW that doesn't return static rate support, use a	 * value of 0x3 (only static rate values of 0 or 1 are handled),	 * except on Sinai, where even old FW can handle static rate	 * values of 2 and 3.	 */	if (dev_lim->stat_rate_support)		mdev->limits.stat_rate_support = dev_lim->stat_rate_support;	else if (mdev->mthca_flags & MTHCA_FLAG_SINAI_OPT)		mdev->limits.stat_rate_support = 0xf;	else		mdev->limits.stat_rate_support = 0x3;	/* IB_DEVICE_RESIZE_MAX_WR not supported by driver.	   May be doable since hardware supports it for SRQ.	   IB_DEVICE_N_NOTIFY_CQ is supported by hardware but not by driver.	   IB_DEVICE_SRQ_RESIZE is supported by hardware but SRQ is not	   supported by driver. */	mdev->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT |		IB_DEVICE_PORT_ACTIVE_EVENT |		IB_DEVICE_SYS_IMAGE_GUID |		IB_DEVICE_RC_RNR_NAK_GEN;	if (dev_lim->flags & DEV_LIM_FLAG_BAD_PKEY_CNTR)		mdev->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;	if (dev_lim->flags & DEV_LIM_FLAG_BAD_QKEY_CNTR)		mdev->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR;	if (dev_lim->flags & DEV_LIM_FLAG_RAW_MULTI)		mdev->device_cap_flags |= IB_DEVICE_RAW_MULTI;	if (dev_lim->flags & DEV_LIM_FLAG_AUTO_PATH_MIG)		mdev->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;	if (dev_lim->flags & DEV_LIM_FLAG_UD_AV_PORT_ENFORCE)		mdev->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;	if (dev_lim->flags & DEV_LIM_FLAG_SRQ)		mdev->mthca_flags |= MTHCA_FLAG_SRQ;	return 0;}static int mthca_init_tavor(struct mthca_dev *mdev){	u8 status;	int err;	struct mthca_dev_lim        dev_lim;	struct mthca_profile        profile;	struct mthca_init_hca_param init_hca;	err = mthca_SYS_EN(mdev, &status);	if (err) {		mthca_err(mdev, "SYS_EN command failed, aborting.\n");		return err;	}	if (status) {		mthca_err(mdev, "SYS_EN returned status 0x%02x, "			  "aborting.\n", status);		return -EINVAL;	}	err = mthca_QUERY_FW(mdev, &status);	if (err) {		mthca_err(mdev, "QUERY_FW command failed, aborting.\n");		goto err_disable;	}	if (status) {		mthca_err(mdev, "QUERY_FW returned status 0x%02x, "			  "aborting.\n", status);		err = -EINVAL;		goto err_disable;	}	err = mthca_QUERY_DDR(mdev, &status);	if (err) {		mthca_err(mdev, "QUERY_DDR command failed, aborting.\n");		goto err_disable;	}	if (status) {		mthca_err(mdev, "QUERY_DDR returned status 0x%02x, "			  "aborting.\n", status);		err = -EINVAL;		goto err_disable;	}	err = mthca_dev_lim(mdev, &dev_lim);	if (err) {		mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");		goto err_disable;	}	profile = hca_profile;	profile.num_uar   = dev_lim.uar_size / PAGE_SIZE;	profile.uarc_size = 0;	if (mdev->mthca_flags & MTHCA_FLAG_SRQ)		profile.num_srq = dev_lim.max_srqs;	err = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);	if (err < 0)		goto err_disable;	err = mthca_INIT_HCA(mdev, &init_hca, &status);	if (err) {		mthca_err(mdev, "INIT_HCA command failed, aborting.\n");		goto err_disable;	}	if (status) {		mthca_err(mdev, "INIT_HCA returned status 0x%02x, "			  "aborting.\n", status);		err = -EINVAL;		goto err_disable;	}	return 0;err_disable:	mthca_SYS_DIS(mdev, &status);	return err;}static int mthca_load_fw(struct mthca_dev *mdev){	u8 status;	int err;	/* FIXME: use HCA-attached memory for FW if present */	mdev->fw.arbel.fw_icm =		mthca_alloc_icm(mdev, mdev->fw.arbel.fw_pages,				GFP_HIGHUSER | __GFP_NOWARN, 0);	if (!mdev->fw.arbel.fw_icm) {		mthca_err(mdev, "Couldn't allocate FW area, aborting.\n");		return -ENOMEM;	}	err = mthca_MAP_FA(mdev, mdev->fw.arbel.fw_icm, &status);	if (err) {		mthca_err(mdev, "MAP_FA command failed, aborting.\n");		goto err_free;	}	if (status) {		mthca_err(mdev, "MAP_FA returned status 0x%02x, aborting.\n", status);		err = -EINVAL;		goto err_free;	}	err = mthca_RUN_FW(mdev, &status);	if (err) {		mthca_err(mdev, "RUN_FW command failed, aborting.\n");		goto err_unmap_fa;	}	if (status) {		mthca_err(mdev, "RUN_FW returned status 0x%02x, aborting.\n", status);		err = -EINVAL;		goto err_unmap_fa;	}	return 0;err_unmap_fa:	mthca_UNMAP_FA(mdev, &status);err_free:	mthca_free_icm(mdev, mdev->fw.arbel.fw_icm, 0);	return err;}static int mthca_init_icm(struct mthca_dev *mdev,			  struct mthca_dev_lim *dev_lim,			  struct mthca_init_hca_param *init_hca,			  u64 icm_size){	u64 aux_pages;	u8 status;	int err;	err = mthca_SET_ICM_SIZE(mdev, icm_size, &aux_pages, &status);	if (err) {		mthca_err(mdev, "SET_ICM_SIZE command failed, aborting.\n");		return err;	}	if (status) {		mthca_err(mdev, "SET_ICM_SIZE returned status 0x%02x, "			  "aborting.\n", status);		return -EINVAL;	}	mthca_dbg(mdev, "%lld KB of HCA context requires %lld KB aux memory.\n",		  (unsigned long long) icm_size >> 10,		  (unsigned long long) aux_pages << 2);	mdev->fw.arbel.aux_icm = mthca_alloc_icm(mdev, aux_pages,						 GFP_HIGHUSER | __GFP_NOWARN, 0);	if (!mdev->fw.arbel.aux_icm) {		mthca_err(mdev, "Couldn't allocate aux memory, aborting.\n");		return -ENOMEM;	}	err = mthca_MAP_ICM_AUX(mdev, mdev->fw.arbel.aux_icm, &status);	if (err) {		mthca_err(mdev, "MAP_ICM_AUX command failed, aborting.\n");		goto err_free_aux;	}	if (status) {		mthca_err(mdev, "MAP_ICM_AUX returned status 0x%02x, aborting.\n", status);		err = -EINVAL;		goto err_free_aux;	}	err = mthca_map_eq_icm(mdev, init_hca->eqc_base);	if (err) {		mthca_err(mdev, "Failed to map EQ context memory, aborting.\n");		goto err_unmap_aux;	}	/* CPU writes to non-reserved MTTs, while HCA might DMA to reserved mtts */	mdev->limits.reserved_mtts = ALIGN(mdev->limits.reserved_mtts * MTHCA_MTT_SEG_SIZE,					   dma_get_cache_alignment()) / MTHCA_MTT_SEG_SIZE;	mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base,							 MTHCA_MTT_SEG_SIZE,							 mdev->limits.num_mtt_segs,							 mdev->limits.reserved_mtts,							 1, 0);	if (!mdev->mr_table.mtt_table) {		mthca_err(mdev, "Failed to map MTT context memory, aborting.\n");		err = -ENOMEM;		goto err_unmap_eq;	}	mdev->mr_table.mpt_table = mthca_alloc_icm_table(mdev, init_hca->mpt_base,							 dev_lim->mpt_entry_sz,							 mdev->limits.num_mpts,							 mdev->limits.reserved_mrws,							 1, 1);	if (!mdev->mr_table.mpt_table) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -