[go: nahoru, domu]

11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.
32a1d9b7f09aaaacf235656cb32a40ba2c79590b3Roland Dreier * Copyright (c) 2005 Mellanox Technologies. All rights reserved.
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software is available to you under a choice of one of two
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * licenses.  You may choose to be licensed under the terms of the GNU
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * General Public License (GPL) Version 2, available from the file
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * COPYING in the main directory of this source tree, or the
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OpenIB.org BSD license below:
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     Redistribution and use in source and binary forms, with or
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     without modification, are permitted provided that the following
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *     conditions are met:
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      - Redistributions of source code must retain the above
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *        copyright notice, this list of conditions and the following
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *        disclaimer.
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      - Redistributions in binary form must reproduce the above
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *        copyright notice, this list of conditions and the following
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *        disclaimer in the documentation and/or other materials
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *        provided with the distribution.
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * SOFTWARE.
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
375a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "mthca_dev.h"
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "mthca_cmd.h"
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "mthca_config_reg.h"
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum {
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_NUM_ASYNC_EQE = 0x80,
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_NUM_CMD_EQE   = 0x80,
4692898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin	MTHCA_NUM_SPARE_EQE = 0x80,
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EQ_ENTRY_SIZE = 0x20
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Must be packed because start is 64 bits but only aligned to 32 bits.
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mthca_eq_context {
5497f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__be32 flags;
5597f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__be64 start;
5697f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__be32 logsize_usrpage;
5797f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__be32 tavor_pd;	/* reserved for Arbel */
5897f52eb438be7caebe026421545619d8a0c1398aSean Hefty	u8     reserved1[3];
5997f52eb438be7caebe026421545619d8a0c1398aSean Hefty	u8     intr;
6097f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__be32 arbel_pd;	/* lost_count for Tavor */
6197f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__be32 lkey;
6297f52eb438be7caebe026421545619d8a0c1398aSean Hefty	u32    reserved2[2];
6397f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__be32 consumer_index;
6497f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__be32 producer_index;
6597f52eb438be7caebe026421545619d8a0c1398aSean Hefty	u32    reserved3[4];
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} __attribute__((packed));
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_STATUS_OK          ( 0 << 28)
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_STATUS_OVERFLOW    ( 9 << 28)
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_STATUS_WRITE_FAIL  (10 << 28)
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_OWNER_SW           ( 0 << 24)
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_OWNER_HW           ( 1 << 24)
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_FLAG_TR            ( 1 << 18)
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_FLAG_OI            ( 1 << 17)
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_STATE_ARMED        ( 1 <<  8)
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_STATE_FIRED        ( 2 <<  8)
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_STATE_ALWAYS_ARMED ( 3 <<  8)
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_STATE_ARBEL        ( 8 <<  8)
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsenum {
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_COMP       	    = 0x00,
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_PATH_MIG   	    = 0x01,
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_COMM_EST   	    = 0x02,
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_SQ_DRAINED 	    = 0x03,
8590f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier	MTHCA_EVENT_TYPE_SRQ_QP_LAST_WQE    = 0x13,
8690f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier	MTHCA_EVENT_TYPE_SRQ_LIMIT	    = 0x14,
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_CQ_ERROR   	    = 0x04,
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_WQ_CATAS_ERROR     = 0x05,
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_EEC_CATAS_ERROR    = 0x06,
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_PATH_MIG_FAILED    = 0x07,
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_WQ_INVAL_REQ_ERROR = 0x10,
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_WQ_ACCESS_ERROR    = 0x11,
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_SRQ_CATAS_ERROR    = 0x12,
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_LOCAL_CATAS_ERROR  = 0x08,
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_PORT_CHANGE        = 0x09,
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_EQ_OVERFLOW        = 0x0f,
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_ECC_DETECT         = 0x0e,
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MTHCA_EVENT_TYPE_CMD                = 0x0a
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_ASYNC_EVENT_MASK ((1ULL << MTHCA_EVENT_TYPE_PATH_MIG)           | \
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(1ULL << MTHCA_EVENT_TYPE_COMM_EST)           | \
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(1ULL << MTHCA_EVENT_TYPE_SQ_DRAINED)         | \
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(1ULL << MTHCA_EVENT_TYPE_CQ_ERROR)           | \
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(1ULL << MTHCA_EVENT_TYPE_WQ_CATAS_ERROR)     | \
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(1ULL << MTHCA_EVENT_TYPE_EEC_CATAS_ERROR)    | \
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(1ULL << MTHCA_EVENT_TYPE_PATH_MIG_FAILED)    | \
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(1ULL << MTHCA_EVENT_TYPE_WQ_INVAL_REQ_ERROR) | \
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(1ULL << MTHCA_EVENT_TYPE_WQ_ACCESS_ERROR)    | \
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(1ULL << MTHCA_EVENT_TYPE_LOCAL_CATAS_ERROR)  | \
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(1ULL << MTHCA_EVENT_TYPE_PORT_CHANGE)        | \
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				(1ULL << MTHCA_EVENT_TYPE_ECC_DETECT))
11390f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier#define MTHCA_SRQ_EVENT_MASK   ((1ULL << MTHCA_EVENT_TYPE_SRQ_CATAS_ERROR)    | \
11490f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier				(1ULL << MTHCA_EVENT_TYPE_SRQ_QP_LAST_WQE)    | \
11590f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier				(1ULL << MTHCA_EVENT_TYPE_SRQ_LIMIT))
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_CMD_EVENT_MASK    (1ULL << MTHCA_EVENT_TYPE_CMD)
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_DB_INC_CI     (1 << 24)
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_DB_REQ_NOT    (2 << 24)
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_DB_DISARM_CQ  (3 << 24)
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_DB_SET_CI     (4 << 24)
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define MTHCA_EQ_DB_ALWAYS_ARM (5 << 24)
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct mthca_eqe {
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 reserved1;
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 type;
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 reserved2;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 subtype;
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	union {
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u32 raw[6];
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct {
13297f52eb438be7caebe026421545619d8a0c1398aSean Hefty			__be32 cqn;
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} __attribute__((packed)) comp;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct {
13597f52eb438be7caebe026421545619d8a0c1398aSean Hefty			u16    reserved1;
13697f52eb438be7caebe026421545619d8a0c1398aSean Hefty			__be16 token;
13797f52eb438be7caebe026421545619d8a0c1398aSean Hefty			u32    reserved2;
13897f52eb438be7caebe026421545619d8a0c1398aSean Hefty			u8     reserved3[3];
13997f52eb438be7caebe026421545619d8a0c1398aSean Hefty			u8     status;
14097f52eb438be7caebe026421545619d8a0c1398aSean Hefty			__be64 out_param;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} __attribute__((packed)) cmd;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct {
14397f52eb438be7caebe026421545619d8a0c1398aSean Hefty			__be32 qpn;
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} __attribute__((packed)) qp;
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct {
14690f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier			__be32 srqn;
14790f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier		} __attribute__((packed)) srq;
14890f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier		struct {
14997f52eb438be7caebe026421545619d8a0c1398aSean Hefty			__be32 cqn;
15097f52eb438be7caebe026421545619d8a0c1398aSean Hefty			u32    reserved1;
15197f52eb438be7caebe026421545619d8a0c1398aSean Hefty			u8     reserved2[3];
15297f52eb438be7caebe026421545619d8a0c1398aSean Hefty			u8     syndrome;
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} __attribute__((packed)) cq_err;
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct {
15597f52eb438be7caebe026421545619d8a0c1398aSean Hefty			u32    reserved1[2];
15697f52eb438be7caebe026421545619d8a0c1398aSean Hefty			__be32 port;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} __attribute__((packed)) port_change;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} event;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 reserved3[3];
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 owner;
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} __attribute__((packed));
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define  MTHCA_EQ_ENTRY_OWNER_SW      (0 << 7)
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define  MTHCA_EQ_ENTRY_OWNER_HW      (1 << 7)
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline u64 async_mask(struct mthca_dev *dev)
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return dev->mthca_flags & MTHCA_FLAG_SRQ ?
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MTHCA_ASYNC_EVENT_MASK | MTHCA_SRQ_EVENT_MASK :
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		MTHCA_ASYNC_EVENT_MASK;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void tavor_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * This barrier makes sure that all updates to ownership bits
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * done by set_eqe_hw() hit memory before the consumer index
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * is updated.  set_eq_ci() allows the HCA to possibly write
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * more EQ entries, and we want to avoid the exceedingly
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * unlikely possibility of the HCA writing an entry and then
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * having set_eqe_hw() overwrite the owner field.
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
184ab8403c424a35364a3a2c753f7c5917fcbb4d809Roland Dreier	mthca_write64(MTHCA_EQ_DB_SET_CI | eq->eqn, ci & (eq->nent - 1),
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      dev->kar + MTHCA_EQ_DOORBELL,
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void arbel_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* See comment in tavor_set_eq_ci() above. */
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	wmb();
19397f52eb438be7caebe026421545619d8a0c1398aSean Hefty	__raw_writel((__force u32) cpu_to_be32(ci),
19497f52eb438be7caebe026421545619d8a0c1398aSean Hefty		     dev->eq_regs.arbel.eq_set_ci_base + eq->eqn * 8);
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* We still want ordering, just not swabbing, so add a barrier */
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mb();
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
201d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier	if (mthca_is_memfree(dev))
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		arbel_set_eq_ci(dev, eq, ci);
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tavor_set_eq_ci(dev, eq, ci);
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void tavor_eq_req_not(struct mthca_dev *dev, int eqn)
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
209ab8403c424a35364a3a2c753f7c5917fcbb4d809Roland Dreier	mthca_write64(MTHCA_EQ_DB_REQ_NOT | eqn, 0,
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      dev->kar + MTHCA_EQ_DOORBELL,
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void arbel_eq_req_not(struct mthca_dev *dev, u32 eqn_mask)
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(eqn_mask, dev->eq_regs.arbel.eq_arm);
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void disarm_cq(struct mthca_dev *dev, int eqn, int cqn)
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
221d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier	if (!mthca_is_memfree(dev)) {
222ab8403c424a35364a3a2c753f7c5917fcbb4d809Roland Dreier		mthca_write64(MTHCA_EQ_DB_DISARM_CQ | eqn, cqn,
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      dev->kar + MTHCA_EQ_DOORBELL,
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline struct mthca_eqe *get_eqe(struct mthca_eq *eq, u32 entry)
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long off = (entry & (eq->nent - 1)) * MTHCA_EQ_ENTRY_SIZE;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return eq->page_list[off / PAGE_SIZE].buf + off % PAGE_SIZE;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
234b39993936d3b192ea088995f7ba882a49e4bf09cRoland Dreierstatic inline struct mthca_eqe *next_eqe_sw(struct mthca_eq *eq)
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
236b39993936d3b192ea088995f7ba882a49e4bf09cRoland Dreier	struct mthca_eqe *eqe;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eqe = get_eqe(eq, eq->cons_index);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (MTHCA_EQ_ENTRY_OWNER_HW & eqe->owner) ? NULL : eqe;
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void set_eqe_hw(struct mthca_eqe *eqe)
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eqe->owner =  MTHCA_EQ_ENTRY_OWNER_HW;
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void port_change(struct mthca_dev *dev, int port, int active)
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct ib_event record;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_dbg(dev, "Port change to %s for port %d\n",
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		  active ? "active" : "down", port);
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	record.device = &dev->ib_dev;
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	record.event  = active ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	record.element.port_num = port;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ib_dispatch_event(&record);
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mthca_eqe *eqe;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int disarm_cqn;
26492898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin	int eqes_found = 0;
26592898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin	int set_ci = 0;
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while ((eqe = next_eqe_sw(eq))) {
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Make sure we read EQ entry contents after we've
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * checked the ownership bit.
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rmb();
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		switch (eqe->type) {
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_COMP:
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			disarm_cqn = be32_to_cpu(eqe->event.comp.cqn) & 0xffffff;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			disarm_cq(dev, eq->eqn, disarm_cqn);
278affcd50546d4788b7849e2b2e2ec7bc50d64c5f8Michael S. Tsirkin			mthca_cq_completion(dev, disarm_cqn);
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_PATH_MIG:
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       IB_EVENT_PATH_MIG);
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_COMM_EST:
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       IB_EVENT_COMM_EST);
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_SQ_DRAINED:
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       IB_EVENT_SQ_DRAINED);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29690f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier		case MTHCA_EVENT_TYPE_SRQ_QP_LAST_WQE:
29790f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier			mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
29890f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier				       IB_EVENT_QP_LAST_WQE_REACHED);
29990f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier			break;
30090f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier
30190f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier		case MTHCA_EVENT_TYPE_SRQ_LIMIT:
30290f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier			mthca_srq_event(dev, be32_to_cpu(eqe->event.srq.srqn) & 0xffffff,
30390f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier					IB_EVENT_SRQ_LIMIT_REACHED);
30490f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier			break;
30590f104da22bbf2e2b8a2136c12fb4e013fccf504Roland Dreier
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_WQ_CATAS_ERROR:
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       IB_EVENT_QP_FATAL);
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_PATH_MIG_FAILED:
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       IB_EVENT_PATH_MIG_ERR);
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_WQ_INVAL_REQ_ERROR:
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       IB_EVENT_QP_REQ_ERR);
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_WQ_ACCESS_ERROR:
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_qp_event(dev, be32_to_cpu(eqe->event.qp.qpn) & 0xffffff,
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				       IB_EVENT_QP_ACCESS_ERR);
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_CMD:
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_cmd_event(dev,
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					be16_to_cpu(eqe->event.cmd.token),
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					eqe->event.cmd.status,
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					be64_to_cpu(eqe->event.cmd.out_param));
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_PORT_CHANGE:
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			port_change(dev,
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    (be32_to_cpu(eqe->event.port_change.port) >> 28) & 3,
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    eqe->subtype == 0x4);
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_CQ_ERROR:
340b87dcfbacee9c57b39738f43f32834f02ec302d5Roland Dreier			mthca_warn(dev, "CQ %s on CQN %06x\n",
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   eqe->event.cq_err.syndrome == 1 ?
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   "overrun" : "access violation",
343b87dcfbacee9c57b39738f43f32834f02ec302d5Roland Dreier				   be32_to_cpu(eqe->event.cq_err.cqn) & 0xffffff);
344affcd50546d4788b7849e2b2e2ec7bc50d64c5f8Michael S. Tsirkin			mthca_cq_event(dev, be32_to_cpu(eqe->event.cq_err.cqn),
345affcd50546d4788b7849e2b2e2ec7bc50d64c5f8Michael S. Tsirkin				       IB_EVENT_CQ_ERR);
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_EQ_OVERFLOW:
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_warn(dev, "EQ overrun on EQN %d\n", eq->eqn);
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_EEC_CATAS_ERROR:
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_SRQ_CATAS_ERROR:
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_LOCAL_CATAS_ERROR:
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case MTHCA_EVENT_TYPE_ECC_DETECT:
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_warn(dev, "Unhandled event %02x(%02x) on EQ %d\n",
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				   eqe->type, eqe->subtype, eq->eqn);
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
3602b50176d11866e59208a4ed1623b3fc0ca322690Joe Perches		}
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_eqe_hw(eqe);
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		++eq->cons_index;
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eqes_found = 1;
36592898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin		++set_ci;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36792898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin		/*
36892898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin		 * The HCA will think the queue has overflowed if we
36992898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin		 * don't tell it we've been processing events.  We
37092898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin		 * create our EQs with MTHCA_NUM_SPARE_EQE extra
37192898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin		 * entries, so we must update our consumer index at
37292898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin		 * least that often.
37392898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin		 */
37492898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin		if (unlikely(set_ci >= MTHCA_NUM_SPARE_EQE)) {
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/*
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * Conditional on hca_type is OK here because
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 * this is a rare case, not the fast path.
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 */
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			set_eq_ci(dev, eq, eq->cons_index);
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			set_ci = 0;
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Rely on caller to set consumer index so that we don't have
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * to test hca_type in our interrupt handling fast path.
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return eqes_found;
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3917d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mthca_tavor_interrupt(int irq, void *dev_ptr)
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mthca_dev *dev = dev_ptr;
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 ecr;
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->eq_table.clr_mask)
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(dev->eq_table.clr_mask, dev->eq_table.clr_int);
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ecr = readl(dev->eq_regs.tavor.ecr_base + 4);
401c8e0ca683dfea7242ff29814561dfe761945e5b3Roland Dreier	if (!ecr)
402c8e0ca683dfea7242ff29814561dfe761945e5b3Roland Dreier		return IRQ_NONE;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
404c8e0ca683dfea7242ff29814561dfe761945e5b3Roland Dreier	writel(ecr, dev->eq_regs.tavor.ecr_base +
405c8e0ca683dfea7242ff29814561dfe761945e5b3Roland Dreier	       MTHCA_ECR_CLR_BASE - MTHCA_ECR_BASE + 4);
406c8e0ca683dfea7242ff29814561dfe761945e5b3Roland Dreier
407c8e0ca683dfea7242ff29814561dfe761945e5b3Roland Dreier	for (i = 0; i < MTHCA_NUM_EQ; ++i)
408c8e0ca683dfea7242ff29814561dfe761945e5b3Roland Dreier		if (ecr & dev->eq_table.eq[i].eqn_mask) {
409c8e0ca683dfea7242ff29814561dfe761945e5b3Roland Dreier			if (mthca_eq_int(dev, &dev->eq_table.eq[i]))
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				tavor_set_eq_ci(dev, &dev->eq_table.eq[i],
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						dev->eq_table.eq[i].cons_index);
412c8e0ca683dfea7242ff29814561dfe761945e5b3Roland Dreier			tavor_eq_req_not(dev, dev->eq_table.eq[i].eqn);
413c8e0ca683dfea7242ff29814561dfe761945e5b3Roland Dreier		}
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
415c8e0ca683dfea7242ff29814561dfe761945e5b3Roland Dreier	return IRQ_HANDLED;
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4187d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mthca_tavor_msi_x_interrupt(int irq, void *eq_ptr)
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mthca_eq  *eq  = eq_ptr;
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mthca_dev *dev = eq->dev;
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_eq_int(dev, eq);
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tavor_set_eq_ci(dev, eq, eq->cons_index);
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tavor_eq_req_not(dev, eq->eqn);
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* MSI-X vectors always belong to us */
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_HANDLED;
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4317d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mthca_arbel_interrupt(int irq, void *dev_ptr)
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mthca_dev *dev = dev_ptr;
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int work = 0;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->eq_table.clr_mask)
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(dev->eq_table.clr_mask, dev->eq_table.clr_int);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MTHCA_NUM_EQ; ++i)
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mthca_eq_int(dev, &dev->eq_table.eq[i])) {
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			work = 1;
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			arbel_set_eq_ci(dev, &dev->eq_table.eq[i],
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev->eq_table.eq[i].cons_index);
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	arbel_eq_req_not(dev, dev->eq_table.arm_mask);
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_RETVAL(work);
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4527d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mthca_arbel_msi_x_interrupt(int irq, void *eq_ptr)
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mthca_eq  *eq  = eq_ptr;
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mthca_dev *dev = eq->dev;
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_eq_int(dev, eq);
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	arbel_set_eq_ci(dev, eq, eq->cons_index);
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	arbel_eq_req_not(dev, eq->eqn_mask);
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* MSI-X vectors always belong to us */
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_HANDLED;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
465f4f3d0f0ece2527184b6c91afa1196a27a5bfaf5Roland Dreierstatic int mthca_create_eq(struct mthca_dev *dev,
466f4f3d0f0ece2527184b6c91afa1196a27a5bfaf5Roland Dreier			   int nent,
467f4f3d0f0ece2527184b6c91afa1196a27a5bfaf5Roland Dreier			   u8 intr,
468f4f3d0f0ece2527184b6c91afa1196a27a5bfaf5Roland Dreier			   struct mthca_eq *eq)
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
470466200562ccd80f728f7ef602d2b97b4fdedd566Michael S. Tsirkin	int npages;
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u64 *dma_list = NULL;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dma_addr_t t;
473ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier	struct mthca_mailbox *mailbox;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mthca_eq_context *eq_context;
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = -ENOMEM;
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
478c915033fc62d7186d243d89f88782d6be33fd8f6Roland Dreier	eq->dev  = dev;
479c915033fc62d7186d243d89f88782d6be33fd8f6Roland Dreier	eq->nent = roundup_pow_of_two(max(nent, 2));
4802fa5e2ebbe2d81f741ba7bed9e07dc38cc734625Roland Dreier	npages = ALIGN(eq->nent * MTHCA_EQ_ENTRY_SIZE, PAGE_SIZE) / PAGE_SIZE;
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eq->page_list = kmalloc(npages * sizeof *eq->page_list,
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				GFP_KERNEL);
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!eq->page_list)
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out;
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < npages; ++i)
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eq->page_list[i].buf = NULL;
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dma_list)
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_free;
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
494ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
495ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier	if (IS_ERR(mailbox))
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_free;
497ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier	eq_context = mailbox->buf;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < npages; ++i) {
50064dc81fca7f6d5c51e50ffa850640ad8358acd1fRoland Dreier		eq->page_list[i].buf = dma_alloc_coherent(&dev->pdev->dev,
50164dc81fca7f6d5c51e50ffa850640ad8358acd1fRoland Dreier							  PAGE_SIZE, &t, GFP_KERNEL);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!eq->page_list[i].buf)
503ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier			goto err_out_free_pages;
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dma_list[i] = t;
5063a2baff783497321e8322ce29f3a33a21c0d88f5FUJITA Tomonori		dma_unmap_addr_set(&eq->page_list[i], mapping, t);
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5088909c571fa1e62e254c4045394e6eaccfadec6f4Shani Moideen		clear_page(eq->page_list[i].buf);
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511c915033fc62d7186d243d89f88782d6be33fd8f6Roland Dreier	for (i = 0; i < eq->nent; ++i)
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		set_eqe_hw(get_eqe(eq, i));
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eq->eqn = mthca_alloc(&dev->eq_table.alloc);
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (eq->eqn == -1)
516ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier		goto err_out_free_pages;
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = mthca_mr_alloc_phys(dev, dev->driver_pd.pd_num,
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  dma_list, PAGE_SHIFT, npages,
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  0, npages * PAGE_SIZE,
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  MTHCA_MPT_FLAG_LOCAL_WRITE |
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  MTHCA_MPT_FLAG_LOCAL_READ,
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  &eq->mr);
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_free_eq;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memset(eq_context, 0, sizeof *eq_context);
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eq_context->flags           = cpu_to_be32(MTHCA_EQ_STATUS_OK   |
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  MTHCA_EQ_OWNER_HW    |
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  MTHCA_EQ_STATE_ARMED |
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						  MTHCA_EQ_FLAG_TR);
532d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier	if (mthca_is_memfree(dev))
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eq_context->flags  |= cpu_to_be32(MTHCA_EQ_STATE_ARBEL);
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
535c915033fc62d7186d243d89f88782d6be33fd8f6Roland Dreier	eq_context->logsize_usrpage = cpu_to_be32((ffs(eq->nent) - 1) << 24);
536d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier	if (mthca_is_memfree(dev)) {
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eq_context->arbel_pd = cpu_to_be32(dev->driver_pd.pd_num);
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eq_context->logsize_usrpage |= cpu_to_be32(dev->driver_uar.index);
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		eq_context->tavor_pd         = cpu_to_be32(dev->driver_pd.pd_num);
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eq_context->intr            = intr;
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eq_context->lkey            = cpu_to_be32(eq->mr.ibmr.lkey);
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
545cdb73db0b6bf7a1bcf5c788f0c8f803facb6e517Goldwyn Rodrigues	err = mthca_SW2HW_EQ(dev, mailbox, eq->eqn);
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err) {
547cdb73db0b6bf7a1bcf5c788f0c8f803facb6e517Goldwyn Rodrigues		mthca_warn(dev, "SW2HW_EQ returned %d\n", err);
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_free_mr;
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(dma_list);
552ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier	mthca_free_mailbox(dev, mailbox);
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eq->eqn_mask   = swab32(1 << eq->eqn);
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	eq->cons_index = 0;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->eq_table.arm_mask |= eq->eqn_mask;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_dbg(dev, "Allocated EQ %d with %d entries\n",
560c915033fc62d7186d243d89f88782d6be33fd8f6Roland Dreier		  eq->eqn, eq->nent);
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err_out_free_mr:
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_free_mr(dev, &eq->mr);
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err_out_free_eq:
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_free(&dev->eq_table.alloc, eq->eqn);
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
570ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier err_out_free_pages:
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < npages; ++i)
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (eq->page_list[i].buf)
57364dc81fca7f6d5c51e50ffa850640ad8358acd1fRoland Dreier			dma_free_coherent(&dev->pdev->dev, PAGE_SIZE,
57464dc81fca7f6d5c51e50ffa850640ad8358acd1fRoland Dreier					  eq->page_list[i].buf,
5753a2baff783497321e8322ce29f3a33a21c0d88f5FUJITA Tomonori					  dma_unmap_addr(&eq->page_list[i],
57664dc81fca7f6d5c51e50ffa850640ad8358acd1fRoland Dreier							 mapping));
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
578ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier	mthca_free_mailbox(dev, mailbox);
579ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier
580ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier err_out_free:
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(eq->page_list);
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(dma_list);
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err_out:
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mthca_free_eq(struct mthca_dev *dev,
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			  struct mthca_eq *eq)
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
591ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier	struct mthca_mailbox *mailbox;
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int npages = (eq->nent * MTHCA_EQ_ENTRY_SIZE + PAGE_SIZE - 1) /
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		PAGE_SIZE;
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
597ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier	mailbox = mthca_alloc_mailbox(dev, GFP_KERNEL);
598ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier	if (IS_ERR(mailbox))
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601cdb73db0b6bf7a1bcf5c788f0c8f803facb6e517Goldwyn Rodrigues	err = mthca_HW2SW_EQ(dev, mailbox, eq->eqn);
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
603cdb73db0b6bf7a1bcf5c788f0c8f803facb6e517Goldwyn Rodrigues		mthca_warn(dev, "HW2SW_EQ returned %d\n", err);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->eq_table.arm_mask &= ~eq->eqn_mask;
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (0) {
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mthca_dbg(dev, "Dumping EQ context %02x:\n", eq->eqn);
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < sizeof (struct mthca_eq_context) / 4; ++i) {
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (i % 4 == 0)
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk("[%02x] ", i * 4);
612ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier			printk(" %08x", be32_to_cpup(mailbox->buf + i * 4));
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((i + 1) % 4 == 0)
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk("\n");
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_free_mr(dev, &eq->mr);
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < npages; ++i)
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_free_consistent(dev->pdev, PAGE_SIZE,
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				    eq->page_list[i].buf,
6223a2baff783497321e8322ce29f3a33a21c0d88f5FUJITA Tomonori				    dma_unmap_addr(&eq->page_list[i], mapping));
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	kfree(eq->page_list);
625ed878458eeff9754d66f1b0325df6ebbfcdce668Roland Dreier	mthca_free_mailbox(dev, mailbox);
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mthca_free_irqs(struct mthca_dev *dev)
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->eq_table.have_irq)
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		free_irq(dev->pdev->irq, dev);
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MTHCA_NUM_EQ; ++i)
6359aa0a489d909af0cc36c41d3061ef956c7442ce2Roland Dreier		if (dev->eq_table.eq[i].have_irq) {
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			free_irq(dev->eq_table.eq[i].msi_x_vector,
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				 dev->eq_table.eq + i);
6389aa0a489d909af0cc36c41d3061ef956c7442ce2Roland Dreier			dev->eq_table.eq[i].have_irq = 0;
6399aa0a489d909af0cc36c41d3061ef956c7442ce2Roland Dreier		}
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
642f4f3d0f0ece2527184b6c91afa1196a27a5bfaf5Roland Dreierstatic int mthca_map_reg(struct mthca_dev *dev,
643f4f3d0f0ece2527184b6c91afa1196a27a5bfaf5Roland Dreier			 unsigned long offset, unsigned long size,
644f4f3d0f0ece2527184b6c91afa1196a27a5bfaf5Roland Dreier			 void __iomem **map)
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
646eb4a7cbf27082bea34764bab3bc85595683f967bJohn L. Burr	phys_addr_t base = pci_resource_start(dev->pdev, 0);
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*map = ioremap(base + offset, size);
649208dde28b0f73c0e2dc6be74040fa562e129a6e8Roland Dreier	if (!*map)
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
655f4f3d0f0ece2527184b6c91afa1196a27a5bfaf5Roland Dreierstatic int mthca_map_eq_regs(struct mthca_dev *dev)
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
657d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier	if (mthca_is_memfree(dev)) {
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * We assume that the EQ arm and EQ set CI registers
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * fall within the first BAR.  We can't trust the
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * values firmware gives us, since those addresses are
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * valid on the HCA's side of the PCI bus but not
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * necessarily the host side.
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mthca_map_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  &dev->clr_base)) {
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_err(dev, "Couldn't map interrupt clear register, "
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  "aborting.\n");
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENOMEM;
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Add 4 because we limit ourselves to EQs 0 ... 31,
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * so we only need the low word of the register.
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mthca_map_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) &
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev->fw.arbel.eq_arm_base) + 4, 4,
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  &dev->eq_regs.arbel.eq_arm)) {
680177214af2946e86ce89324f379720ec0dc8d4a9eBernhard Fischer			mthca_err(dev, "Couldn't map EQ arm register, aborting.\n");
681208dde28b0f73c0e2dc6be74040fa562e129a6e8Roland Dreier			iounmap(dev->clr_base);
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENOMEM;
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mthca_map_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  dev->fw.arbel.eq_set_ci_base,
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  MTHCA_EQ_SET_CI_SIZE,
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  &dev->eq_regs.arbel.eq_set_ci_base)) {
689177214af2946e86ce89324f379720ec0dc8d4a9eBernhard Fischer			mthca_err(dev, "Couldn't map EQ CI register, aborting.\n");
690208dde28b0f73c0e2dc6be74040fa562e129a6e8Roland Dreier			iounmap(dev->eq_regs.arbel.eq_arm);
691208dde28b0f73c0e2dc6be74040fa562e129a6e8Roland Dreier			iounmap(dev->clr_base);
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENOMEM;
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mthca_map_reg(dev, MTHCA_CLR_INT_BASE, MTHCA_CLR_INT_SIZE,
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  &dev->clr_base)) {
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_err(dev, "Couldn't map interrupt clear register, "
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  "aborting.\n");
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENOMEM;
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mthca_map_reg(dev, MTHCA_ECR_BASE,
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  MTHCA_ECR_SIZE + MTHCA_ECR_CLR_SIZE,
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  &dev->eq_regs.tavor.ecr_base)) {
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mthca_err(dev, "Couldn't map ecr register, "
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  "aborting.\n");
707208dde28b0f73c0e2dc6be74040fa562e129a6e8Roland Dreier			iounmap(dev->clr_base);
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENOMEM;
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
716e1f7868c80947d40ef8e1fd37323d939a9bf311cRoland Dreierstatic void mthca_unmap_eq_regs(struct mthca_dev *dev)
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
718d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier	if (mthca_is_memfree(dev)) {
719208dde28b0f73c0e2dc6be74040fa562e129a6e8Roland Dreier		iounmap(dev->eq_regs.arbel.eq_set_ci_base);
720208dde28b0f73c0e2dc6be74040fa562e129a6e8Roland Dreier		iounmap(dev->eq_regs.arbel.eq_arm);
721208dde28b0f73c0e2dc6be74040fa562e129a6e8Roland Dreier		iounmap(dev->clr_base);
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
723208dde28b0f73c0e2dc6be74040fa562e129a6e8Roland Dreier		iounmap(dev->eq_regs.tavor.ecr_base);
724208dde28b0f73c0e2dc6be74040fa562e129a6e8Roland Dreier		iounmap(dev->clr_base);
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
728f4f3d0f0ece2527184b6c91afa1196a27a5bfaf5Roland Dreierint mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We assume that mapping one page is enough for the whole EQ
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * context table.  This is fine with all current HCAs, because
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * we only use 32 EQs and each EQ uses 32 bytes of context
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * memory, or 1 KB total.
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->eq_table.icm_virt = icm_virt;
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->eq_table.icm_page = alloc_page(GFP_HIGHUSER);
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev->eq_table.icm_page)
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->eq_table.icm_dma  = pci_map_page(dev->pdev, dev->eq_table.icm_page, 0,
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					      PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
7448d8bb39b9eba32dd70e87fd5ad5c5dd4ba118e06FUJITA Tomonori	if (pci_dma_mapping_error(dev->pdev, dev->eq_table.icm_dma)) {
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__free_page(dev->eq_table.icm_page);
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
749cdb73db0b6bf7a1bcf5c788f0c8f803facb6e517Goldwyn Rodrigues	ret = mthca_MAP_ICM_page(dev, dev->eq_table.icm_dma, icm_virt);
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret) {
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pci_unmap_page(dev->pdev, dev->eq_table.icm_dma, PAGE_SIZE,
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       PCI_DMA_BIDIRECTIONAL);
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		__free_page(dev->eq_table.icm_page);
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
759e1f7868c80947d40ef8e1fd37323d939a9bf311cRoland Dreiervoid mthca_unmap_eq_icm(struct mthca_dev *dev)
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
761cdb73db0b6bf7a1bcf5c788f0c8f803facb6e517Goldwyn Rodrigues	mthca_UNMAP_ICM(dev, dev->eq_table.icm_virt, 1);
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_unmap_page(dev->pdev, dev->eq_table.icm_dma, PAGE_SIZE,
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		       PCI_DMA_BIDIRECTIONAL);
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__free_page(dev->eq_table.icm_page);
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
767f4f3d0f0ece2527184b6c91afa1196a27a5bfaf5Roland Dreierint mthca_init_eq_table(struct mthca_dev *dev)
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u8 intr;
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = mthca_alloc_init(&dev->eq_table.alloc,
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       dev->limits.num_eqs,
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       dev->limits.num_eqs - 1,
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       dev->limits.reserved_eqs);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return err;
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = mthca_map_eq_regs(dev);
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_free;
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
784e57895d38991036f9ccf193b70fc5ebd5f6e6dc9Adrian Bunk	if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->eq_table.clr_mask = 0;
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->eq_table.clr_mask =
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			swab32(1 << (dev->eq_table.inta_pin & 31));
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->eq_table.clr_int  = dev->clr_base +
790f7ed3a5971da98acdc506bdbdef25cfe51c334a2Michael S. Tsirkin			(dev->eq_table.inta_pin < 32 ? 4 : 0);
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->eq_table.arm_mask = 0;
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
795e57895d38991036f9ccf193b70fc5ebd5f6e6dc9Adrian Bunk	intr = dev->eq_table.inta_pin;
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
79792898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin	err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE,
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr,
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      &dev->eq_table.eq[MTHCA_EQ_COMP]);
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_unmap;
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
80392898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin	err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE + MTHCA_NUM_SPARE_EQE,
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr,
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      &dev->eq_table.eq[MTHCA_EQ_ASYNC]);
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_comp;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
80992898522e3ee1a0ba54140aad1974d9e868f74aeMichael S. Tsirkin	err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE + MTHCA_NUM_SPARE_EQE,
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr,
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      &dev->eq_table.eq[MTHCA_EQ_CMD]);
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto err_out_async;
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (dev->mthca_flags & MTHCA_FLAG_MSI_X) {
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		static const char *eq_name[] = {
817d94a86890137fabcc97eaa324bfef3f1827744c8Arputham Benjamin			[MTHCA_EQ_COMP]  = DRV_NAME "-comp",
818d94a86890137fabcc97eaa324bfef3f1827744c8Arputham Benjamin			[MTHCA_EQ_ASYNC] = DRV_NAME "-async",
819d94a86890137fabcc97eaa324bfef3f1827744c8Arputham Benjamin			[MTHCA_EQ_CMD]   = DRV_NAME "-cmd"
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		};
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (i = 0; i < MTHCA_NUM_EQ; ++i) {
823d94a86890137fabcc97eaa324bfef3f1827744c8Arputham Benjamin			snprintf(dev->eq_table.eq[i].irq_name,
824d94a86890137fabcc97eaa324bfef3f1827744c8Arputham Benjamin				 IB_DEVICE_NAME_MAX,
825d94a86890137fabcc97eaa324bfef3f1827744c8Arputham Benjamin				 "%s@pci:%s", eq_name[i],
826d94a86890137fabcc97eaa324bfef3f1827744c8Arputham Benjamin				 pci_name(dev->pdev));
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = request_irq(dev->eq_table.eq[i].msi_x_vector,
828d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier					  mthca_is_memfree(dev) ?
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					  mthca_arbel_msi_x_interrupt :
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					  mthca_tavor_msi_x_interrupt,
831d94a86890137fabcc97eaa324bfef3f1827744c8Arputham Benjamin					  0, dev->eq_table.eq[i].irq_name,
832d94a86890137fabcc97eaa324bfef3f1827744c8Arputham Benjamin					  dev->eq_table.eq + i);
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (err)
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				goto err_out_cmd;
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev->eq_table.eq[i].have_irq = 1;
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
838d94a86890137fabcc97eaa324bfef3f1827744c8Arputham Benjamin		snprintf(dev->eq_table.eq[0].irq_name, IB_DEVICE_NAME_MAX,
839d94a86890137fabcc97eaa324bfef3f1827744c8Arputham Benjamin			 DRV_NAME "@pci:%s", pci_name(dev->pdev));
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = request_irq(dev->pdev->irq,
841d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier				  mthca_is_memfree(dev) ?
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  mthca_arbel_interrupt :
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  mthca_tavor_interrupt,
844d94a86890137fabcc97eaa324bfef3f1827744c8Arputham Benjamin				  IRQF_SHARED, dev->eq_table.eq[0].irq_name, dev);
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (err)
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto err_out_cmd;
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev->eq_table.have_irq = 1;
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = mthca_MAP_EQ(dev, async_mask(dev),
851cdb73db0b6bf7a1bcf5c788f0c8f803facb6e517Goldwyn Rodrigues			   0, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mthca_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n",
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn, err);
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = mthca_MAP_EQ(dev, MTHCA_CMD_EVENT_MASK,
857cdb73db0b6bf7a1bcf5c788f0c8f803facb6e517Goldwyn Rodrigues			   0, dev->eq_table.eq[MTHCA_EQ_CMD].eqn);
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mthca_warn(dev, "MAP_EQ for cmd EQ %d failed (%d)\n",
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   dev->eq_table.eq[MTHCA_EQ_CMD].eqn, err);
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8626b63e3015a69dd8aa5534e23af9f132a021da02eRoland Dreier	for (i = 0; i < MTHCA_NUM_EQ; ++i)
863d10ddbf6d7f6699c386d1f41bf542189de32b6beRoland Dreier		if (mthca_is_memfree(dev))
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			arbel_eq_req_not(dev, dev->eq_table.eq[i].eqn_mask);
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tavor_eq_req_not(dev, dev->eq_table.eq[i].eqn);
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_cmd:
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_free_irqs(dev);
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_free_eq(dev, &dev->eq_table.eq[MTHCA_EQ_CMD]);
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_async:
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_free_eq(dev, &dev->eq_table.eq[MTHCA_EQ_ASYNC]);
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_comp:
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_free_eq(dev, &dev->eq_table.eq[MTHCA_EQ_COMP]);
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_unmap:
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_unmap_eq_regs(dev);
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldserr_out_free:
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_alloc_cleanup(&dev->eq_table.alloc);
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
888e1f7868c80947d40ef8e1fd37323d939a9bf311cRoland Dreiervoid mthca_cleanup_eq_table(struct mthca_dev *dev)
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_free_irqs(dev);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_MAP_EQ(dev, async_mask(dev),
895cdb73db0b6bf7a1bcf5c788f0c8f803facb6e517Goldwyn Rodrigues		     1, dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_MAP_EQ(dev, MTHCA_CMD_EVENT_MASK,
897cdb73db0b6bf7a1bcf5c788f0c8f803facb6e517Goldwyn Rodrigues		     1, dev->eq_table.eq[MTHCA_EQ_CMD].eqn);
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < MTHCA_NUM_EQ; ++i)
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mthca_free_eq(dev, &dev->eq_table.eq[i]);
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_unmap_eq_regs(dev);
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mthca_alloc_cleanup(&dev->eq_table.alloc);
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
906