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

📄 mthca_main.c

📁 linux-2.6.15.6
💻 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/config.h>#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_PCI_MSIstatic int msi_x = 0;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");#else /* CONFIG_PCI_MSI */#define msi_x (0)#define msi   (0)#endif /* CONFIG_PCI_MSI */static const char mthca_version[] __devinitdata =	DRV_NAME ": Mellanox InfiniBand HCA driver v"	DRV_VERSION " (" DRV_RELDATE ")\n";static struct mthca_profile default_profile = {	.num_qp		   = 1 << 16,	.rdb_per_qp	   = 4,	.num_cq		   = 1 << 16,	.num_mcg	   = 1 << 13,	.num_mpt	   = 1 << 17,	.num_mtt	   = 1 << 20,	.num_udav	   = 1 << 15,	/* Tavor only */	.fmr_reserved_mtts = 1 << 18,	/* Tavor only */	.uarc_size	   = 1 << 18,	/* Arbel only */};static int __devinit mthca_tune_pci(struct mthca_dev *mdev){	int cap;	u16 val;	/* First try to max out Read Byte Count */	cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_PCIX);	if (cap) {		if (pci_read_config_word(mdev->pdev, cap + PCI_X_CMD, &val)) {			mthca_err(mdev, "Couldn't read PCI-X command register, "				  "aborting.\n");			return -ENODEV;		}		val = (val & ~PCI_X_CMD_MAX_READ) | (3 << 2);		if (pci_write_config_word(mdev->pdev, cap + PCI_X_CMD, val)) {			mthca_err(mdev, "Couldn't write PCI-X command register, "				  "aborting.\n");			return -ENODEV;		}	} else if (!(mdev->mthca_flags & MTHCA_FLAG_PCIE))		mthca_info(mdev, "No PCI-X capability, not setting RBC.\n");	cap = pci_find_capability(mdev->pdev, PCI_CAP_ID_EXP);	if (cap) {		if (pci_read_config_word(mdev->pdev, cap + PCI_EXP_DEVCTL, &val)) {			mthca_err(mdev, "Couldn't read PCI Express device control "				  "register, aborting.\n");			return -ENODEV;		}		val = (val & ~PCI_EXP_DEVCTL_READRQ) | (5 << 12);		if (pci_write_config_word(mdev->pdev, cap + PCI_EXP_DEVCTL, val)) {			mthca_err(mdev, "Couldn't write PCI Express device control "				  "register, 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 __devinit 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;	}	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;	/*	 * 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;	/* 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 __devinit 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);	profile = default_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 __devinit 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);	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);	return err;}static int __devinit 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);	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;	}	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);	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);	if (!mdev->mr_table.mpt_table) {		mthca_err(mdev, "Failed to map MPT context memory, aborting.\n");		err = -ENOMEM;		goto err_unmap_mtt;	}

⌨️ 快捷键说明

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