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

📄 mthca_cmd.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved. * Copyright (c) 2005 Mellanox Technologies. All rights reserved. * Copyright (c) 2005 Cisco Systems. 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_cmd.c 1349 2004-12-16 21:09:43Z roland $ */#include <linux/sched.h>#include <linux/pci.h>#include <linux/errno.h>#include <asm/io.h>#include <rdma/ib_mad.h>#include "mthca_dev.h"#include "mthca_config_reg.h"#include "mthca_cmd.h"#include "mthca_memfree.h"#define CMD_POLL_TOKEN 0xffffenum {	HCR_IN_PARAM_OFFSET    = 0x00,	HCR_IN_MODIFIER_OFFSET = 0x08,	HCR_OUT_PARAM_OFFSET   = 0x0c,	HCR_TOKEN_OFFSET       = 0x14,	HCR_STATUS_OFFSET      = 0x18,	HCR_OPMOD_SHIFT        = 12,	HCA_E_BIT              = 22,	HCR_GO_BIT             = 23};enum {	/* initialization and general commands */	CMD_SYS_EN          = 0x1,	CMD_SYS_DIS         = 0x2,	CMD_MAP_FA          = 0xfff,	CMD_UNMAP_FA        = 0xffe,	CMD_RUN_FW          = 0xff6,	CMD_MOD_STAT_CFG    = 0x34,	CMD_QUERY_DEV_LIM   = 0x3,	CMD_QUERY_FW        = 0x4,	CMD_ENABLE_LAM      = 0xff8,	CMD_DISABLE_LAM     = 0xff7,	CMD_QUERY_DDR       = 0x5,	CMD_QUERY_ADAPTER   = 0x6,	CMD_INIT_HCA        = 0x7,	CMD_CLOSE_HCA       = 0x8,	CMD_INIT_IB         = 0x9,	CMD_CLOSE_IB        = 0xa,	CMD_QUERY_HCA       = 0xb,	CMD_SET_IB          = 0xc,	CMD_ACCESS_DDR      = 0x2e,	CMD_MAP_ICM         = 0xffa,	CMD_UNMAP_ICM       = 0xff9,	CMD_MAP_ICM_AUX     = 0xffc,	CMD_UNMAP_ICM_AUX   = 0xffb,	CMD_SET_ICM_SIZE    = 0xffd,	/* TPT commands */	CMD_SW2HW_MPT 	    = 0xd,	CMD_QUERY_MPT 	    = 0xe,	CMD_HW2SW_MPT 	    = 0xf,	CMD_READ_MTT        = 0x10,	CMD_WRITE_MTT       = 0x11,	CMD_SYNC_TPT        = 0x2f,	/* EQ commands */	CMD_MAP_EQ          = 0x12,	CMD_SW2HW_EQ 	    = 0x13,	CMD_HW2SW_EQ 	    = 0x14,	CMD_QUERY_EQ        = 0x15,	/* CQ commands */	CMD_SW2HW_CQ 	    = 0x16,	CMD_HW2SW_CQ 	    = 0x17,	CMD_QUERY_CQ 	    = 0x18,	CMD_RESIZE_CQ       = 0x2c,	/* SRQ commands */	CMD_SW2HW_SRQ 	    = 0x35,	CMD_HW2SW_SRQ 	    = 0x36,	CMD_QUERY_SRQ       = 0x37,	CMD_ARM_SRQ         = 0x40,	/* QP/EE commands */	CMD_RST2INIT_QPEE   = 0x19,	CMD_INIT2RTR_QPEE   = 0x1a,	CMD_RTR2RTS_QPEE    = 0x1b,	CMD_RTS2RTS_QPEE    = 0x1c,	CMD_SQERR2RTS_QPEE  = 0x1d,	CMD_2ERR_QPEE       = 0x1e,	CMD_RTS2SQD_QPEE    = 0x1f,	CMD_SQD2SQD_QPEE    = 0x38,	CMD_SQD2RTS_QPEE    = 0x20,	CMD_ERR2RST_QPEE    = 0x21,	CMD_QUERY_QPEE      = 0x22,	CMD_INIT2INIT_QPEE  = 0x2d,	CMD_SUSPEND_QPEE    = 0x32,	CMD_UNSUSPEND_QPEE  = 0x33,	/* special QPs and management commands */	CMD_CONF_SPECIAL_QP = 0x23,	CMD_MAD_IFC         = 0x24,	/* multicast commands */	CMD_READ_MGM        = 0x25,	CMD_WRITE_MGM       = 0x26,	CMD_MGID_HASH       = 0x27,	/* miscellaneous commands */	CMD_DIAG_RPRT       = 0x30,	CMD_NOP             = 0x31,	/* debug commands */	CMD_QUERY_DEBUG_MSG = 0x2a,	CMD_SET_DEBUG_MSG   = 0x2b,};/* * According to Mellanox code, FW may be starved and never complete * commands.  So we can't use strict timeouts described in PRM -- we * just arbitrarily select 60 seconds for now. */#if 0/* * Round up and add 1 to make sure we get the full wait time (since we * will be starting in the middle of a jiffy) */enum {	CMD_TIME_CLASS_A = (HZ + 999) / 1000 + 1,	CMD_TIME_CLASS_B = (HZ +  99) /  100 + 1,	CMD_TIME_CLASS_C = (HZ +   9) /   10 + 1};#elseenum {	CMD_TIME_CLASS_A = 60 * HZ,	CMD_TIME_CLASS_B = 60 * HZ,	CMD_TIME_CLASS_C = 60 * HZ};#endifenum {	GO_BIT_TIMEOUT = HZ * 10};struct mthca_cmd_context {	struct completion done;	struct timer_list timer;	int               result;	int               next;	u64               out_param;	u16               token;	u8                status;};static inline int go_bit(struct mthca_dev *dev){	return readl(dev->hcr + HCR_STATUS_OFFSET) &		swab32(1 << HCR_GO_BIT);}static int mthca_cmd_post(struct mthca_dev *dev,			  u64 in_param,			  u64 out_param,			  u32 in_modifier,			  u8 op_modifier,			  u16 op,			  u16 token,			  int event){	int err = 0;	if (down_interruptible(&dev->cmd.hcr_sem))		return -EINTR;	if (event) {		unsigned long end = jiffies + GO_BIT_TIMEOUT;		while (go_bit(dev) && time_before(jiffies, end)) {			set_current_state(TASK_RUNNING);			schedule();		}	}	if (go_bit(dev)) {		err = -EAGAIN;		goto out;	}	/*	 * We use writel (instead of something like memcpy_toio)	 * because writes of less than 32 bits to the HCR don't work	 * (and some architectures such as ia64 implement memcpy_toio	 * in terms of writeb).	 */	__raw_writel((__force u32) cpu_to_be32(in_param >> 32),           dev->hcr + 0 * 4);	__raw_writel((__force u32) cpu_to_be32(in_param & 0xfffffffful),  dev->hcr + 1 * 4);	__raw_writel((__force u32) cpu_to_be32(in_modifier),              dev->hcr + 2 * 4);	__raw_writel((__force u32) cpu_to_be32(out_param >> 32),          dev->hcr + 3 * 4);	__raw_writel((__force u32) cpu_to_be32(out_param & 0xfffffffful), dev->hcr + 4 * 4);	__raw_writel((__force u32) cpu_to_be32(token << 16),              dev->hcr + 5 * 4);	/* __raw_writel may not order writes. */	wmb();	__raw_writel((__force u32) cpu_to_be32((1 << HCR_GO_BIT)                |					       (event ? (1 << HCA_E_BIT) : 0)   |					       (op_modifier << HCR_OPMOD_SHIFT) |					       op),                       dev->hcr + 6 * 4);out:	up(&dev->cmd.hcr_sem);	return err;}static int mthca_cmd_poll(struct mthca_dev *dev,			  u64 in_param,			  u64 *out_param,			  int out_is_imm,			  u32 in_modifier,			  u8 op_modifier,			  u16 op,			  unsigned long timeout,			  u8 *status){	int err = 0;	unsigned long end;	if (down_interruptible(&dev->cmd.poll_sem))		return -EINTR;	err = mthca_cmd_post(dev, in_param,			     out_param ? *out_param : 0,			     in_modifier, op_modifier,			     op, CMD_POLL_TOKEN, 0);	if (err)		goto out;	end = timeout + jiffies;	while (go_bit(dev) && time_before(jiffies, end)) {		set_current_state(TASK_RUNNING);		schedule();	}	if (go_bit(dev)) {		err = -EBUSY;		goto out;	}	if (out_is_imm)		*out_param = 			(u64) be32_to_cpu((__force __be32)					  __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET)) << 32 |			(u64) be32_to_cpu((__force __be32)					  __raw_readl(dev->hcr + HCR_OUT_PARAM_OFFSET + 4));	*status = be32_to_cpu((__force __be32) __raw_readl(dev->hcr + HCR_STATUS_OFFSET)) >> 24;out:	up(&dev->cmd.poll_sem);	return err;}void mthca_cmd_event(struct mthca_dev *dev,		     u16 token,		     u8  status,		     u64 out_param){	struct mthca_cmd_context *context =		&dev->cmd.context[token & dev->cmd.token_mask];	/* previously timed out command completing at long last */	if (token != context->token)		return;	context->result    = 0;	context->status    = status;	context->out_param = out_param;	context->token += dev->cmd.token_mask + 1;	complete(&context->done);}static void event_timeout(unsigned long context_ptr){	struct mthca_cmd_context *context =		(struct mthca_cmd_context *) context_ptr;	context->result = -EBUSY;	complete(&context->done);}static int mthca_cmd_wait(struct mthca_dev *dev,			  u64 in_param,			  u64 *out_param,			  int out_is_imm,			  u32 in_modifier,			  u8 op_modifier,			  u16 op,			  unsigned long timeout,			  u8 *status){	int err = 0;	struct mthca_cmd_context *context;	if (down_interruptible(&dev->cmd.event_sem))		return -EINTR;	spin_lock(&dev->cmd.context_lock);	BUG_ON(dev->cmd.free_head < 0);	context = &dev->cmd.context[dev->cmd.free_head];	dev->cmd.free_head = context->next;	spin_unlock(&dev->cmd.context_lock);	init_completion(&context->done);	err = mthca_cmd_post(dev, in_param,			     out_param ? *out_param : 0,			     in_modifier, op_modifier,			     op, context->token, 1);	if (err)		goto out;	context->timer.expires  = jiffies + timeout;	add_timer(&context->timer);	wait_for_completion(&context->done);	del_timer_sync(&context->timer);	err = context->result;	if (err)		goto out;	*status = context->status;	if (*status)		mthca_dbg(dev, "Command %02x completed with status %02x\n",			  op, *status);	if (out_is_imm)		*out_param = context->out_param;out:	spin_lock(&dev->cmd.context_lock);	context->next = dev->cmd.free_head;	dev->cmd.free_head = context - dev->cmd.context;	spin_unlock(&dev->cmd.context_lock);	up(&dev->cmd.event_sem);	return err;}/* Invoke a command with an output mailbox */static int mthca_cmd_box(struct mthca_dev *dev,			 u64 in_param,			 u64 out_param,			 u32 in_modifier,			 u8 op_modifier,			 u16 op,			 unsigned long timeout,			 u8 *status){	if (dev->cmd.use_events)		return mthca_cmd_wait(dev, in_param, &out_param, 0,				      in_modifier, op_modifier, op,				      timeout, status);	else		return mthca_cmd_poll(dev, in_param, &out_param, 0,				      in_modifier, op_modifier, op,				      timeout, status);}/* Invoke a command with no output parameter */static int mthca_cmd(struct mthca_dev *dev,		     u64 in_param,		     u32 in_modifier,		     u8 op_modifier,		     u16 op,		     unsigned long timeout,		     u8 *status){	return mthca_cmd_box(dev, in_param, 0, in_modifier,			     op_modifier, op, timeout, status);}/* * Invoke a command with an immediate output parameter (and copy the * output into the caller's out_param pointer after the command * executes). */static int mthca_cmd_imm(struct mthca_dev *dev,			 u64 in_param,			 u64 *out_param,			 u32 in_modifier,			 u8 op_modifier,			 u16 op,			 unsigned long timeout,			 u8 *status){	if (dev->cmd.use_events)		return mthca_cmd_wait(dev, in_param, out_param, 1,				      in_modifier, op_modifier, op,				      timeout, status);	else		return mthca_cmd_poll(dev, in_param, out_param, 1,				      in_modifier, op_modifier, op,				      timeout, status);}int mthca_cmd_init(struct mthca_dev *dev){

⌨️ 快捷键说明

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