linux/drivers/infiniband/hw/ehca/ehca_qes.h
Alexander Schmidt 6773f079b7 IB/ehca: Discard double CQE for one WR
Under rare circumstances, the ehca hardware might erroneously generate
two CQEs for the same WQE, which is not compliant to the IB spec and
will cause unpredictable errors like memory being freed twice. To
avoid this problem, the driver needs to detect the second CQE and
discard it.

For this purpose, introduce an array holding as many elements as the
SQ of the QP, called sq_map. Each sq_map entry stores a "reported"
flag for one WQE in the SQ. When a work request is posted to the SQ,
the respective "reported" flag is set to zero. After the arrival of a
CQE, the flag is set to 1, which allows to detect the occurence of a
second CQE.

The mapping between WQE / CQE and the corresponding sq_map element is
implemented by replacing the lowest 16 Bits of the wr_id with the
index in the queue map. The original 16 Bits are stored in the sq_map
entry and are restored when the CQE is passed to the application.

Signed-off-by: Alexander Schmidt <alexs@linux.vnet.ibm.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
2008-08-12 11:34:59 -07:00

260 lines
6.1 KiB
C

/*
* IBM eServer eHCA Infiniband device driver for Linux on POWER
*
* Hardware request structures
*
* Authors: Waleri Fomin <fomin@de.ibm.com>
* Reinhard Ernst <rernst@de.ibm.com>
* Christoph Raisch <raisch@de.ibm.com>
*
* Copyright (c) 2005 IBM Corporation
*
* All rights reserved.
*
* This source code is distributed under a dual license of GPL v2.0 and OpenIB
* BSD.
*
* OpenIB BSD License
*
* 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.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _EHCA_QES_H_
#define _EHCA_QES_H_
#include "ehca_tools.h"
/* virtual scatter gather entry to specify remote adresses with length */
struct ehca_vsgentry {
u64 vaddr;
u32 lkey;
u32 length;
};
#define GRH_FLAG_MASK EHCA_BMASK_IBM( 7, 7)
#define GRH_IPVERSION_MASK EHCA_BMASK_IBM( 0, 3)
#define GRH_TCLASS_MASK EHCA_BMASK_IBM( 4, 12)
#define GRH_FLOWLABEL_MASK EHCA_BMASK_IBM(13, 31)
#define GRH_PAYLEN_MASK EHCA_BMASK_IBM(32, 47)
#define GRH_NEXTHEADER_MASK EHCA_BMASK_IBM(48, 55)
#define GRH_HOPLIMIT_MASK EHCA_BMASK_IBM(56, 63)
/*
* Unreliable Datagram Address Vector Format
* see IBTA Vol1 chapter 8.3 Global Routing Header
*/
struct ehca_ud_av {
u8 sl;
u8 lnh;
u16 dlid;
u8 reserved1;
u8 reserved2;
u8 reserved3;
u8 slid_path_bits;
u8 reserved4;
u8 ipd;
u8 reserved5;
u8 pmtu;
u32 reserved6;
u64 reserved7;
union {
struct {
u64 word_0; /* always set to 6 */
/*should be 0x1B for IB transport */
u64 word_1;
u64 word_2;
u64 word_3;
u64 word_4;
} grh;
struct {
u32 wd_0;
u32 wd_1;
/* DWord_1 --> SGID */
u32 sgid_wd3;
u32 sgid_wd2;
u32 sgid_wd1;
u32 sgid_wd0;
/* DWord_3 --> DGID */
u32 dgid_wd3;
u32 dgid_wd2;
u32 dgid_wd1;
u32 dgid_wd0;
} grh_l;
};
};
/* maximum number of sg entries allowed in a WQE */
#define MAX_WQE_SG_ENTRIES 252
#define WQE_OPTYPE_SEND 0x80
#define WQE_OPTYPE_RDMAREAD 0x40
#define WQE_OPTYPE_RDMAWRITE 0x20
#define WQE_OPTYPE_CMPSWAP 0x10
#define WQE_OPTYPE_FETCHADD 0x08
#define WQE_OPTYPE_BIND 0x04
#define WQE_WRFLAG_REQ_SIGNAL_COM 0x80
#define WQE_WRFLAG_FENCE 0x40
#define WQE_WRFLAG_IMM_DATA_PRESENT 0x20
#define WQE_WRFLAG_SOLIC_EVENT 0x10
#define WQEF_CACHE_HINT 0x80
#define WQEF_CACHE_HINT_RD_WR 0x40
#define WQEF_TIMED_WQE 0x20
#define WQEF_PURGE 0x08
#define WQEF_HIGH_NIBBLE 0xF0
#define MW_BIND_ACCESSCTRL_R_WRITE 0x40
#define MW_BIND_ACCESSCTRL_R_READ 0x20
#define MW_BIND_ACCESSCTRL_R_ATOMIC 0x10
struct ehca_wqe {
u64 work_request_id;
u8 optype;
u8 wr_flag;
u16 pkeyi;
u8 wqef;
u8 nr_of_data_seg;
u16 wqe_provided_slid;
u32 destination_qp_number;
u32 resync_psn_sqp;
u32 local_ee_context_qkey;
u32 immediate_data;
union {
struct {
u64 remote_virtual_adress;
u32 rkey;
u32 reserved;
u64 atomic_1st_op_dma_len;
u64 atomic_2nd_op;
struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES];
} nud;
struct {
u64 ehca_ud_av_ptr;
u64 reserved1;
u64 reserved2;
u64 reserved3;
struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES];
} ud_avp;
struct {
struct ehca_ud_av ud_av;
struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES -
2];
} ud_av;
struct {
u64 reserved0;
u64 reserved1;
u64 reserved2;
u64 reserved3;
struct ehca_vsgentry sg_list[MAX_WQE_SG_ENTRIES];
} all_rcv;
struct {
u64 reserved;
u32 rkey;
u32 old_rkey;
u64 reserved1;
u64 reserved2;
u64 virtual_address;
u32 reserved3;
u32 length;
u32 reserved4;
u16 reserved5;
u8 reserved6;
u8 lr_ctl;
u32 lkey;
u32 reserved7;
u64 reserved8;
u64 reserved9;
u64 reserved10;
u64 reserved11;
} bind;
struct {
u64 reserved12;
u64 reserved13;
u32 size;
u32 start;
} inline_data;
} u;
};
#define WC_SEND_RECEIVE EHCA_BMASK_IBM(0, 0)
#define WC_IMM_DATA EHCA_BMASK_IBM(1, 1)
#define WC_GRH_PRESENT EHCA_BMASK_IBM(2, 2)
#define WC_SE_BIT EHCA_BMASK_IBM(3, 3)
#define WC_STATUS_ERROR_BIT 0x80000000
#define WC_STATUS_REMOTE_ERROR_FLAGS 0x0000F800
#define WC_STATUS_PURGE_BIT 0x10
#define WC_SEND_RECEIVE_BIT 0x80
struct ehca_cqe {
u64 work_request_id;
u8 optype;
u8 w_completion_flags;
u16 reserved1;
u32 nr_bytes_transferred;
u32 immediate_data;
u32 local_qp_number;
u8 freed_resource_count;
u8 service_level;
u16 wqe_count;
u32 qp_token;
u32 qkey_ee_token;
u32 remote_qp_number;
u16 dlid;
u16 rlid;
u16 reserved2;
u16 pkey_index;
u32 cqe_timestamp;
u32 wqe_timestamp;
u8 wqe_timestamp_valid;
u8 reserved3;
u8 reserved4;
u8 cqe_flags;
u32 status;
};
struct ehca_eqe {
u64 entry;
};
struct ehca_mrte {
u64 starting_va;
u64 length; /* length of memory region in bytes*/
u32 pd;
u8 key_instance;
u8 pagesize;
u8 mr_control;
u8 local_remote_access_ctrl;
u8 reserved[0x20 - 0x18];
u64 at_pointer[4];
};
#endif /*_EHCA_QES_H_*/