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

📄 mthca_main.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2004, 2005 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. * * $Id: mthca_main.c 1396 2004-12-28 04:10:27Z roland $ */#include <linux/config.h>#include <linux/version.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 =	"ib_mthca: 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 */	.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->hca_type == TAVOR)		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->hca_type == ARBEL_NATIVE ||		   mdev->hca_type == ARBEL_COMPAT)		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.reserved_qps       = dev_lim->reserved_qps;	mdev->limits.reserved_srqs      = dev_lim->reserved_srqs;	mdev->limits.reserved_eecs      = dev_lim->reserved_eecs;	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;	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;	struct mthca_adapter        adapter;	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;	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;	}	err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);	if (err) {		mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");		goto err_close;	}	if (status) {		mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "			  "aborting.\n", status);		err = -EINVAL;		goto err_close;	}	mdev->eq_table.inta_pin = adapter.inta_pin;	mdev->rev_id            = adapter.revision_id;	return 0;err_close:	mthca_CLOSE_HCA(mdev, 0, &status);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,							 mdev->limits.num_mtt_segs *							 init_hca->mtt_seg_sz,							 mdev->limits.reserved_mtts *							 init_hca->mtt_seg_sz, 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,							 mdev->limits.num_mpts *							 dev_lim->mpt_entry_sz,							 mdev->limits.reserved_mrws *							 dev_lim->mpt_entry_sz, 1);	if (!mdev->mr_table.mpt_table) {		mthca_err(mdev, "Failed to map MPT context memory, aborting.\n");		err = -ENOMEM;		goto err_unmap_mtt;	}	mdev->qp_table.qp_table = mthca_alloc_icm_table(mdev, init_hca->qpc_base,							mdev->limits.num_qps *							dev_lim->qpc_entry_sz,							mdev->limits.reserved_qps *							dev_lim->qpc_entry_sz, 1);	if (!mdev->qp_table.qp_table) {		mthca_err(mdev, "Failed to map QP context memory, aborting.\n");		err = -ENOMEM;		goto err_unmap_mpt;	}	mdev->qp_table.eqp_table = mthca_alloc_icm_table(mdev, init_hca->eqpc_base,							 mdev->limits.num_qps *							 dev_lim->eqpc_entry_sz,							 mdev->limits.reserved_qps *							 dev_lim->eqpc_entry_sz, 1);	if (!mdev->qp_table.eqp_table) {		mthca_err(mdev, "Failed to map EQP context memory, aborting.\n");		err = -ENOMEM;		goto err_unmap_qp;	}	mdev->cq_table.table = mthca_alloc_icm_table(mdev, init_hca->cqc_base,						     mdev->limits.num_cqs *						     dev_lim->cqc_entry_sz,						     mdev->limits.reserved_cqs *						     dev_lim->cqc_entry_sz, 1);	if (!mdev->cq_table.table) {		mthca_err(mdev, "Failed to map CQ context memory, aborting.\n");		err = -ENOMEM;		goto err_unmap_eqp;	}	return 0;err_unmap_eqp:	mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);err_unmap_qp:	mthca_free_icm_table(mdev, mdev->qp_table.qp_table);err_unmap_mpt:	mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);err_unmap_mtt:	mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);err_unmap_eq:	mthca_unmap_eq_icm(mdev);err_unmap_aux:	mthca_UNMAP_ICM_AUX(mdev, &status);err_free_aux:	mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);	return err;}static int __devinit mthca_init_arbel(struct mthca_dev *mdev){	struct mthca_dev_lim        dev_lim;	struct mthca_profile        profile;	struct mthca_init_hca_param init_hca;	struct mthca_adapter        adapter;	u64 icm_size;	u8 status;	int err;	err = mthca_QUERY_FW(mdev, &status);	if (err) {		mthca_err(mdev, "QUERY_FW command failed, aborting.\n");		return err;	}	if (status) {		mthca_err(mdev, "QUERY_FW returned status 0x%02x, "			  "aborting.\n", status);		return -EINVAL;	}	err = mthca_ENABLE_LAM(mdev, &status);	if (err) {		mthca_err(mdev, "ENABLE_LAM command failed, aborting.\n");		return err;	}	if (status == MTHCA_CMD_STAT_LAM_NOT_PRE) {		mthca_dbg(mdev, "No HCA-attached memory (running in MemFree mode)\n");		mdev->mthca_flags |= MTHCA_FLAG_NO_LAM;	} else if (status) {		mthca_err(mdev, "ENABLE_LAM returned status 0x%02x, "			  "aborting.\n", status);		return -EINVAL;	}	err = mthca_load_fw(mdev);	if (err) {		mthca_err(mdev, "Failed to start FW, aborting.\n");		goto err_disable;	}	err = mthca_dev_lim(mdev, &dev_lim);	if (err) {		mthca_err(mdev, "QUERY_DEV_LIM command failed, aborting.\n");		goto err_stop_fw;	}	profile = default_profile;	profile.num_uar  = dev_lim.uar_size / PAGE_SIZE;	profile.num_udav = 0;	icm_size = mthca_make_profile(mdev, &profile, &dev_lim, &init_hca);	if ((int) icm_size < 0) {		err = icm_size;		goto err_stop_fw;	}	err = mthca_init_icm(mdev, &dev_lim, &init_hca, icm_size);	if (err)		goto err_stop_fw;	err = mthca_INIT_HCA(mdev, &init_hca, &status);	if (err) {		mthca_err(mdev, "INIT_HCA command failed, aborting.\n");		goto err_free_icm;	}	if (status) {		mthca_err(mdev, "INIT_HCA returned status 0x%02x, "			  "aborting.\n", status);		err = -EINVAL;		goto err_free_icm;	}	err = mthca_QUERY_ADAPTER(mdev, &adapter, &status);	if (err) {		mthca_err(mdev, "QUERY_ADAPTER command failed, aborting.\n");		goto err_free_icm;	}	if (status) {		mthca_err(mdev, "QUERY_ADAPTER returned status 0x%02x, "			  "aborting.\n", status);		err = -EINVAL;		goto err_free_icm;	}	mdev->eq_table.inta_pin = adapter.inta_pin;	mdev->rev_id            = adapter.revision_id;	return 0;err_free_icm:	mthca_free_icm_table(mdev, mdev->cq_table.table);	mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);	mthca_free_icm_table(mdev, mdev->qp_table.qp_table);	mthca_free_icm_table(mdev, mdev->mr_table.mpt_table);	mthca_free_icm_table(mdev, mdev->mr_table.mtt_table);	mthca_unmap_eq_icm(mdev);	mthca_UNMAP_ICM_AUX(mdev, &status);	mthca_free_icm(mdev, mdev->fw.arbel.aux_icm);err_stop_fw:	mthca_UNMAP_FA(mdev, &status);	mthca_free_icm(mdev, mdev->fw.arbel.fw_icm);err_disable:	if (!(mdev->mthca_flags & MTHCA_FLAG_NO_LAM))		mthca_DISABLE_LAM(mdev, &status);	return err;}static int __devinit mthca_init_hca(struct mthca_dev *mdev){	if (mdev->hca_type == ARBEL_NATIVE)		return mthca_init_arbel(mdev);	else		return mthca_init_tavor(mdev);}

⌨️ 快捷键说明

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