Path: blob/master/drivers/infiniband/hw/ipath/ipath_uc.c
15112 views
/*1* Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved.2* Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.3*4* This software is available to you under a choice of one of two5* licenses. You may choose to be licensed under the terms of the GNU6* General Public License (GPL) Version 2, available from the file7* COPYING in the main directory of this source tree, or the8* OpenIB.org BSD license below:9*10* Redistribution and use in source and binary forms, with or11* without modification, are permitted provided that the following12* conditions are met:13*14* - Redistributions of source code must retain the above15* copyright notice, this list of conditions and the following16* disclaimer.17*18* - Redistributions in binary form must reproduce the above19* copyright notice, this list of conditions and the following20* disclaimer in the documentation and/or other materials21* provided with the distribution.22*23* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,24* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF25* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND26* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS27* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN28* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN29* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE30* SOFTWARE.31*/3233#include "ipath_verbs.h"34#include "ipath_kernel.h"3536/* cut down ridiculously long IB macro names */37#define OP(x) IB_OPCODE_UC_##x3839/**40* ipath_make_uc_req - construct a request packet (SEND, RDMA write)41* @qp: a pointer to the QP42*43* Return 1 if constructed; otherwise, return 0.44*/45int ipath_make_uc_req(struct ipath_qp *qp)46{47struct ipath_other_headers *ohdr;48struct ipath_swqe *wqe;49unsigned long flags;50u32 hwords;51u32 bth0;52u32 len;53u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);54int ret = 0;5556spin_lock_irqsave(&qp->s_lock, flags);5758if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK)) {59if (!(ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND))60goto bail;61/* We are in the error state, flush the work request. */62if (qp->s_last == qp->s_head)63goto bail;64/* If DMAs are in progress, we can't flush immediately. */65if (atomic_read(&qp->s_dma_busy)) {66qp->s_flags |= IPATH_S_WAIT_DMA;67goto bail;68}69wqe = get_swqe_ptr(qp, qp->s_last);70ipath_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR);71goto done;72}7374ohdr = &qp->s_hdr.u.oth;75if (qp->remote_ah_attr.ah_flags & IB_AH_GRH)76ohdr = &qp->s_hdr.u.l.oth;7778/* header size in 32-bit words LRH+BTH = (8+12)/4. */79hwords = 5;80bth0 = 1 << 22; /* Set M bit */8182/* Get the next send request. */83wqe = get_swqe_ptr(qp, qp->s_cur);84qp->s_wqe = NULL;85switch (qp->s_state) {86default:87if (!(ib_ipath_state_ops[qp->state] &88IPATH_PROCESS_NEXT_SEND_OK))89goto bail;90/* Check if send work queue is empty. */91if (qp->s_cur == qp->s_head)92goto bail;93/*94* Start a new request.95*/96qp->s_psn = wqe->psn = qp->s_next_psn;97qp->s_sge.sge = wqe->sg_list[0];98qp->s_sge.sg_list = wqe->sg_list + 1;99qp->s_sge.num_sge = wqe->wr.num_sge;100qp->s_len = len = wqe->length;101switch (wqe->wr.opcode) {102case IB_WR_SEND:103case IB_WR_SEND_WITH_IMM:104if (len > pmtu) {105qp->s_state = OP(SEND_FIRST);106len = pmtu;107break;108}109if (wqe->wr.opcode == IB_WR_SEND)110qp->s_state = OP(SEND_ONLY);111else {112qp->s_state =113OP(SEND_ONLY_WITH_IMMEDIATE);114/* Immediate data comes after the BTH */115ohdr->u.imm_data = wqe->wr.ex.imm_data;116hwords += 1;117}118if (wqe->wr.send_flags & IB_SEND_SOLICITED)119bth0 |= 1 << 23;120qp->s_wqe = wqe;121if (++qp->s_cur >= qp->s_size)122qp->s_cur = 0;123break;124125case IB_WR_RDMA_WRITE:126case IB_WR_RDMA_WRITE_WITH_IMM:127ohdr->u.rc.reth.vaddr =128cpu_to_be64(wqe->wr.wr.rdma.remote_addr);129ohdr->u.rc.reth.rkey =130cpu_to_be32(wqe->wr.wr.rdma.rkey);131ohdr->u.rc.reth.length = cpu_to_be32(len);132hwords += sizeof(struct ib_reth) / 4;133if (len > pmtu) {134qp->s_state = OP(RDMA_WRITE_FIRST);135len = pmtu;136break;137}138if (wqe->wr.opcode == IB_WR_RDMA_WRITE)139qp->s_state = OP(RDMA_WRITE_ONLY);140else {141qp->s_state =142OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE);143/* Immediate data comes after the RETH */144ohdr->u.rc.imm_data = wqe->wr.ex.imm_data;145hwords += 1;146if (wqe->wr.send_flags & IB_SEND_SOLICITED)147bth0 |= 1 << 23;148}149qp->s_wqe = wqe;150if (++qp->s_cur >= qp->s_size)151qp->s_cur = 0;152break;153154default:155goto bail;156}157break;158159case OP(SEND_FIRST):160qp->s_state = OP(SEND_MIDDLE);161/* FALLTHROUGH */162case OP(SEND_MIDDLE):163len = qp->s_len;164if (len > pmtu) {165len = pmtu;166break;167}168if (wqe->wr.opcode == IB_WR_SEND)169qp->s_state = OP(SEND_LAST);170else {171qp->s_state = OP(SEND_LAST_WITH_IMMEDIATE);172/* Immediate data comes after the BTH */173ohdr->u.imm_data = wqe->wr.ex.imm_data;174hwords += 1;175}176if (wqe->wr.send_flags & IB_SEND_SOLICITED)177bth0 |= 1 << 23;178qp->s_wqe = wqe;179if (++qp->s_cur >= qp->s_size)180qp->s_cur = 0;181break;182183case OP(RDMA_WRITE_FIRST):184qp->s_state = OP(RDMA_WRITE_MIDDLE);185/* FALLTHROUGH */186case OP(RDMA_WRITE_MIDDLE):187len = qp->s_len;188if (len > pmtu) {189len = pmtu;190break;191}192if (wqe->wr.opcode == IB_WR_RDMA_WRITE)193qp->s_state = OP(RDMA_WRITE_LAST);194else {195qp->s_state =196OP(RDMA_WRITE_LAST_WITH_IMMEDIATE);197/* Immediate data comes after the BTH */198ohdr->u.imm_data = wqe->wr.ex.imm_data;199hwords += 1;200if (wqe->wr.send_flags & IB_SEND_SOLICITED)201bth0 |= 1 << 23;202}203qp->s_wqe = wqe;204if (++qp->s_cur >= qp->s_size)205qp->s_cur = 0;206break;207}208qp->s_len -= len;209qp->s_hdrwords = hwords;210qp->s_cur_sge = &qp->s_sge;211qp->s_cur_size = len;212ipath_make_ruc_header(to_idev(qp->ibqp.device),213qp, ohdr, bth0 | (qp->s_state << 24),214qp->s_next_psn++ & IPATH_PSN_MASK);215done:216ret = 1;217goto unlock;218219bail:220qp->s_flags &= ~IPATH_S_BUSY;221unlock:222spin_unlock_irqrestore(&qp->s_lock, flags);223return ret;224}225226/**227* ipath_uc_rcv - handle an incoming UC packet228* @dev: the device the packet came in on229* @hdr: the header of the packet230* @has_grh: true if the packet has a GRH231* @data: the packet data232* @tlen: the length of the packet233* @qp: the QP for this packet.234*235* This is called from ipath_qp_rcv() to process an incoming UC packet236* for the given QP.237* Called at interrupt level.238*/239void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,240int has_grh, void *data, u32 tlen, struct ipath_qp *qp)241{242struct ipath_other_headers *ohdr;243int opcode;244u32 hdrsize;245u32 psn;246u32 pad;247struct ib_wc wc;248u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu);249struct ib_reth *reth;250int header_in_data;251252/* Validate the SLID. See Ch. 9.6.1.5 */253if (unlikely(be16_to_cpu(hdr->lrh[3]) != qp->remote_ah_attr.dlid))254goto done;255256/* Check for GRH */257if (!has_grh) {258ohdr = &hdr->u.oth;259hdrsize = 8 + 12; /* LRH + BTH */260psn = be32_to_cpu(ohdr->bth[2]);261header_in_data = 0;262} else {263ohdr = &hdr->u.l.oth;264hdrsize = 8 + 40 + 12; /* LRH + GRH + BTH */265/*266* The header with GRH is 60 bytes and the267* core driver sets the eager header buffer268* size to 56 bytes so the last 4 bytes of269* the BTH header (PSN) is in the data buffer.270*/271header_in_data = dev->dd->ipath_rcvhdrentsize == 16;272if (header_in_data) {273psn = be32_to_cpu(((__be32 *) data)[0]);274data += sizeof(__be32);275} else276psn = be32_to_cpu(ohdr->bth[2]);277}278/*279* The opcode is in the low byte when its in network order280* (top byte when in host order).281*/282opcode = be32_to_cpu(ohdr->bth[0]) >> 24;283284memset(&wc, 0, sizeof wc);285286/* Compare the PSN verses the expected PSN. */287if (unlikely(ipath_cmp24(psn, qp->r_psn) != 0)) {288/*289* Handle a sequence error.290* Silently drop any current message.291*/292qp->r_psn = psn;293inv:294qp->r_state = OP(SEND_LAST);295switch (opcode) {296case OP(SEND_FIRST):297case OP(SEND_ONLY):298case OP(SEND_ONLY_WITH_IMMEDIATE):299goto send_first;300301case OP(RDMA_WRITE_FIRST):302case OP(RDMA_WRITE_ONLY):303case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE):304goto rdma_first;305306default:307dev->n_pkt_drops++;308goto done;309}310}311312/* Check for opcode sequence errors. */313switch (qp->r_state) {314case OP(SEND_FIRST):315case OP(SEND_MIDDLE):316if (opcode == OP(SEND_MIDDLE) ||317opcode == OP(SEND_LAST) ||318opcode == OP(SEND_LAST_WITH_IMMEDIATE))319break;320goto inv;321322case OP(RDMA_WRITE_FIRST):323case OP(RDMA_WRITE_MIDDLE):324if (opcode == OP(RDMA_WRITE_MIDDLE) ||325opcode == OP(RDMA_WRITE_LAST) ||326opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE))327break;328goto inv;329330default:331if (opcode == OP(SEND_FIRST) ||332opcode == OP(SEND_ONLY) ||333opcode == OP(SEND_ONLY_WITH_IMMEDIATE) ||334opcode == OP(RDMA_WRITE_FIRST) ||335opcode == OP(RDMA_WRITE_ONLY) ||336opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE))337break;338goto inv;339}340341/* OK, process the packet. */342switch (opcode) {343case OP(SEND_FIRST):344case OP(SEND_ONLY):345case OP(SEND_ONLY_WITH_IMMEDIATE):346send_first:347if (qp->r_flags & IPATH_R_REUSE_SGE) {348qp->r_flags &= ~IPATH_R_REUSE_SGE;349qp->r_sge = qp->s_rdma_read_sge;350} else if (!ipath_get_rwqe(qp, 0)) {351dev->n_pkt_drops++;352goto done;353}354/* Save the WQE so we can reuse it in case of an error. */355qp->s_rdma_read_sge = qp->r_sge;356qp->r_rcv_len = 0;357if (opcode == OP(SEND_ONLY))358goto send_last;359else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE))360goto send_last_imm;361/* FALLTHROUGH */362case OP(SEND_MIDDLE):363/* Check for invalid length PMTU or posted rwqe len. */364if (unlikely(tlen != (hdrsize + pmtu + 4))) {365qp->r_flags |= IPATH_R_REUSE_SGE;366dev->n_pkt_drops++;367goto done;368}369qp->r_rcv_len += pmtu;370if (unlikely(qp->r_rcv_len > qp->r_len)) {371qp->r_flags |= IPATH_R_REUSE_SGE;372dev->n_pkt_drops++;373goto done;374}375ipath_copy_sge(&qp->r_sge, data, pmtu);376break;377378case OP(SEND_LAST_WITH_IMMEDIATE):379send_last_imm:380if (header_in_data) {381wc.ex.imm_data = *(__be32 *) data;382data += sizeof(__be32);383} else {384/* Immediate data comes after BTH */385wc.ex.imm_data = ohdr->u.imm_data;386}387hdrsize += 4;388wc.wc_flags = IB_WC_WITH_IMM;389/* FALLTHROUGH */390case OP(SEND_LAST):391send_last:392/* Get the number of bytes the message was padded by. */393pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;394/* Check for invalid length. */395/* XXX LAST len should be >= 1 */396if (unlikely(tlen < (hdrsize + pad + 4))) {397qp->r_flags |= IPATH_R_REUSE_SGE;398dev->n_pkt_drops++;399goto done;400}401/* Don't count the CRC. */402tlen -= (hdrsize + pad + 4);403wc.byte_len = tlen + qp->r_rcv_len;404if (unlikely(wc.byte_len > qp->r_len)) {405qp->r_flags |= IPATH_R_REUSE_SGE;406dev->n_pkt_drops++;407goto done;408}409wc.opcode = IB_WC_RECV;410last_imm:411ipath_copy_sge(&qp->r_sge, data, tlen);412wc.wr_id = qp->r_wr_id;413wc.status = IB_WC_SUCCESS;414wc.qp = &qp->ibqp;415wc.src_qp = qp->remote_qpn;416wc.slid = qp->remote_ah_attr.dlid;417wc.sl = qp->remote_ah_attr.sl;418/* Signal completion event if the solicited bit is set. */419ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc,420(ohdr->bth[0] &421cpu_to_be32(1 << 23)) != 0);422break;423424case OP(RDMA_WRITE_FIRST):425case OP(RDMA_WRITE_ONLY):426case OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE): /* consume RWQE */427rdma_first:428/* RETH comes after BTH */429if (!header_in_data)430reth = &ohdr->u.rc.reth;431else {432reth = (struct ib_reth *)data;433data += sizeof(*reth);434}435hdrsize += sizeof(*reth);436qp->r_len = be32_to_cpu(reth->length);437qp->r_rcv_len = 0;438if (qp->r_len != 0) {439u32 rkey = be32_to_cpu(reth->rkey);440u64 vaddr = be64_to_cpu(reth->vaddr);441int ok;442443/* Check rkey */444ok = ipath_rkey_ok(qp, &qp->r_sge, qp->r_len,445vaddr, rkey,446IB_ACCESS_REMOTE_WRITE);447if (unlikely(!ok)) {448dev->n_pkt_drops++;449goto done;450}451} else {452qp->r_sge.sg_list = NULL;453qp->r_sge.sge.mr = NULL;454qp->r_sge.sge.vaddr = NULL;455qp->r_sge.sge.length = 0;456qp->r_sge.sge.sge_length = 0;457}458if (unlikely(!(qp->qp_access_flags &459IB_ACCESS_REMOTE_WRITE))) {460dev->n_pkt_drops++;461goto done;462}463if (opcode == OP(RDMA_WRITE_ONLY))464goto rdma_last;465else if (opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE))466goto rdma_last_imm;467/* FALLTHROUGH */468case OP(RDMA_WRITE_MIDDLE):469/* Check for invalid length PMTU or posted rwqe len. */470if (unlikely(tlen != (hdrsize + pmtu + 4))) {471dev->n_pkt_drops++;472goto done;473}474qp->r_rcv_len += pmtu;475if (unlikely(qp->r_rcv_len > qp->r_len)) {476dev->n_pkt_drops++;477goto done;478}479ipath_copy_sge(&qp->r_sge, data, pmtu);480break;481482case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE):483rdma_last_imm:484if (header_in_data) {485wc.ex.imm_data = *(__be32 *) data;486data += sizeof(__be32);487} else {488/* Immediate data comes after BTH */489wc.ex.imm_data = ohdr->u.imm_data;490}491hdrsize += 4;492wc.wc_flags = IB_WC_WITH_IMM;493494/* Get the number of bytes the message was padded by. */495pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;496/* Check for invalid length. */497/* XXX LAST len should be >= 1 */498if (unlikely(tlen < (hdrsize + pad + 4))) {499dev->n_pkt_drops++;500goto done;501}502/* Don't count the CRC. */503tlen -= (hdrsize + pad + 4);504if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) {505dev->n_pkt_drops++;506goto done;507}508if (qp->r_flags & IPATH_R_REUSE_SGE)509qp->r_flags &= ~IPATH_R_REUSE_SGE;510else if (!ipath_get_rwqe(qp, 1)) {511dev->n_pkt_drops++;512goto done;513}514wc.byte_len = qp->r_len;515wc.opcode = IB_WC_RECV_RDMA_WITH_IMM;516goto last_imm;517518case OP(RDMA_WRITE_LAST):519rdma_last:520/* Get the number of bytes the message was padded by. */521pad = (be32_to_cpu(ohdr->bth[0]) >> 20) & 3;522/* Check for invalid length. */523/* XXX LAST len should be >= 1 */524if (unlikely(tlen < (hdrsize + pad + 4))) {525dev->n_pkt_drops++;526goto done;527}528/* Don't count the CRC. */529tlen -= (hdrsize + pad + 4);530if (unlikely(tlen + qp->r_rcv_len != qp->r_len)) {531dev->n_pkt_drops++;532goto done;533}534ipath_copy_sge(&qp->r_sge, data, tlen);535break;536537default:538/* Drop packet for unknown opcodes. */539dev->n_pkt_drops++;540goto done;541}542qp->r_psn++;543qp->r_state = opcode;544done:545return;546}547548549