Path: blob/master/drivers/infiniband/hw/amso1100/c2_ae.c
15112 views
/*1* Copyright (c) 2005 Ammasso, Inc. All rights reserved.2* Copyright (c) 2005 Open Grid Computing, 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*/32#include "c2.h"33#include <rdma/iw_cm.h>34#include "c2_status.h"35#include "c2_ae.h"3637static int c2_convert_cm_status(u32 c2_status)38{39switch (c2_status) {40case C2_CONN_STATUS_SUCCESS:41return 0;42case C2_CONN_STATUS_REJECTED:43return -ENETRESET;44case C2_CONN_STATUS_REFUSED:45return -ECONNREFUSED;46case C2_CONN_STATUS_TIMEDOUT:47return -ETIMEDOUT;48case C2_CONN_STATUS_NETUNREACH:49return -ENETUNREACH;50case C2_CONN_STATUS_HOSTUNREACH:51return -EHOSTUNREACH;52case C2_CONN_STATUS_INVALID_RNIC:53return -EINVAL;54case C2_CONN_STATUS_INVALID_QP:55return -EINVAL;56case C2_CONN_STATUS_INVALID_QP_STATE:57return -EINVAL;58case C2_CONN_STATUS_ADDR_NOT_AVAIL:59return -EADDRNOTAVAIL;60default:61printk(KERN_ERR PFX62"%s - Unable to convert CM status: %d\n",63__func__, c2_status);64return -EIO;65}66}6768static const char* to_event_str(int event)69{70static const char* event_str[] = {71"CCAE_REMOTE_SHUTDOWN",72"CCAE_ACTIVE_CONNECT_RESULTS",73"CCAE_CONNECTION_REQUEST",74"CCAE_LLP_CLOSE_COMPLETE",75"CCAE_TERMINATE_MESSAGE_RECEIVED",76"CCAE_LLP_CONNECTION_RESET",77"CCAE_LLP_CONNECTION_LOST",78"CCAE_LLP_SEGMENT_SIZE_INVALID",79"CCAE_LLP_INVALID_CRC",80"CCAE_LLP_BAD_FPDU",81"CCAE_INVALID_DDP_VERSION",82"CCAE_INVALID_RDMA_VERSION",83"CCAE_UNEXPECTED_OPCODE",84"CCAE_INVALID_DDP_QUEUE_NUMBER",85"CCAE_RDMA_READ_NOT_ENABLED",86"CCAE_RDMA_WRITE_NOT_ENABLED",87"CCAE_RDMA_READ_TOO_SMALL",88"CCAE_NO_L_BIT",89"CCAE_TAGGED_INVALID_STAG",90"CCAE_TAGGED_BASE_BOUNDS_VIOLATION",91"CCAE_TAGGED_ACCESS_RIGHTS_VIOLATION",92"CCAE_TAGGED_INVALID_PD",93"CCAE_WRAP_ERROR",94"CCAE_BAD_CLOSE",95"CCAE_BAD_LLP_CLOSE",96"CCAE_INVALID_MSN_RANGE",97"CCAE_INVALID_MSN_GAP",98"CCAE_IRRQ_OVERFLOW",99"CCAE_IRRQ_MSN_GAP",100"CCAE_IRRQ_MSN_RANGE",101"CCAE_IRRQ_INVALID_STAG",102"CCAE_IRRQ_BASE_BOUNDS_VIOLATION",103"CCAE_IRRQ_ACCESS_RIGHTS_VIOLATION",104"CCAE_IRRQ_INVALID_PD",105"CCAE_IRRQ_WRAP_ERROR",106"CCAE_CQ_SQ_COMPLETION_OVERFLOW",107"CCAE_CQ_RQ_COMPLETION_ERROR",108"CCAE_QP_SRQ_WQE_ERROR",109"CCAE_QP_LOCAL_CATASTROPHIC_ERROR",110"CCAE_CQ_OVERFLOW",111"CCAE_CQ_OPERATION_ERROR",112"CCAE_SRQ_LIMIT_REACHED",113"CCAE_QP_RQ_LIMIT_REACHED",114"CCAE_SRQ_CATASTROPHIC_ERROR",115"CCAE_RNIC_CATASTROPHIC_ERROR"116};117118if (event < CCAE_REMOTE_SHUTDOWN ||119event > CCAE_RNIC_CATASTROPHIC_ERROR)120return "<invalid event>";121122event -= CCAE_REMOTE_SHUTDOWN;123return event_str[event];124}125126static const char *to_qp_state_str(int state)127{128switch (state) {129case C2_QP_STATE_IDLE:130return "C2_QP_STATE_IDLE";131case C2_QP_STATE_CONNECTING:132return "C2_QP_STATE_CONNECTING";133case C2_QP_STATE_RTS:134return "C2_QP_STATE_RTS";135case C2_QP_STATE_CLOSING:136return "C2_QP_STATE_CLOSING";137case C2_QP_STATE_TERMINATE:138return "C2_QP_STATE_TERMINATE";139case C2_QP_STATE_ERROR:140return "C2_QP_STATE_ERROR";141default:142return "<invalid QP state>";143};144}145146void c2_ae_event(struct c2_dev *c2dev, u32 mq_index)147{148struct c2_mq *mq = c2dev->qptr_array[mq_index];149union c2wr *wr;150void *resource_user_context;151struct iw_cm_event cm_event;152struct ib_event ib_event;153enum c2_resource_indicator resource_indicator;154enum c2_event_id event_id;155unsigned long flags;156int status;157158/*159* retrieve the message160*/161wr = c2_mq_consume(mq);162if (!wr)163return;164165memset(&ib_event, 0, sizeof(ib_event));166memset(&cm_event, 0, sizeof(cm_event));167168event_id = c2_wr_get_id(wr);169resource_indicator = be32_to_cpu(wr->ae.ae_generic.resource_type);170resource_user_context =171(void *) (unsigned long) wr->ae.ae_generic.user_context;172173status = cm_event.status = c2_convert_cm_status(c2_wr_get_result(wr));174175pr_debug("event received c2_dev=%p, event_id=%d, "176"resource_indicator=%d, user_context=%p, status = %d\n",177c2dev, event_id, resource_indicator, resource_user_context,178status);179180switch (resource_indicator) {181case C2_RES_IND_QP:{182183struct c2_qp *qp = (struct c2_qp *)resource_user_context;184struct iw_cm_id *cm_id = qp->cm_id;185struct c2wr_ae_active_connect_results *res;186187if (!cm_id) {188pr_debug("event received, but cm_id is <nul>, qp=%p!\n",189qp);190goto ignore_it;191}192pr_debug("%s: event = %s, user_context=%llx, "193"resource_type=%x, "194"resource=%x, qp_state=%s\n",195__func__,196to_event_str(event_id),197(unsigned long long) wr->ae.ae_generic.user_context,198be32_to_cpu(wr->ae.ae_generic.resource_type),199be32_to_cpu(wr->ae.ae_generic.resource),200to_qp_state_str(be32_to_cpu(wr->ae.ae_generic.qp_state)));201202c2_set_qp_state(qp, be32_to_cpu(wr->ae.ae_generic.qp_state));203204switch (event_id) {205case CCAE_ACTIVE_CONNECT_RESULTS:206res = &wr->ae.ae_active_connect_results;207cm_event.event = IW_CM_EVENT_CONNECT_REPLY;208cm_event.local_addr.sin_addr.s_addr = res->laddr;209cm_event.remote_addr.sin_addr.s_addr = res->raddr;210cm_event.local_addr.sin_port = res->lport;211cm_event.remote_addr.sin_port = res->rport;212if (status == 0) {213cm_event.private_data_len =214be32_to_cpu(res->private_data_length);215cm_event.private_data = res->private_data;216} else {217spin_lock_irqsave(&qp->lock, flags);218if (qp->cm_id) {219qp->cm_id->rem_ref(qp->cm_id);220qp->cm_id = NULL;221}222spin_unlock_irqrestore(&qp->lock, flags);223cm_event.private_data_len = 0;224cm_event.private_data = NULL;225}226if (cm_id->event_handler)227cm_id->event_handler(cm_id, &cm_event);228break;229case CCAE_TERMINATE_MESSAGE_RECEIVED:230case CCAE_CQ_SQ_COMPLETION_OVERFLOW:231ib_event.device = &c2dev->ibdev;232ib_event.element.qp = &qp->ibqp;233ib_event.event = IB_EVENT_QP_REQ_ERR;234235if (qp->ibqp.event_handler)236qp->ibqp.event_handler(&ib_event,237qp->ibqp.238qp_context);239break;240case CCAE_BAD_CLOSE:241case CCAE_LLP_CLOSE_COMPLETE:242case CCAE_LLP_CONNECTION_RESET:243case CCAE_LLP_CONNECTION_LOST:244BUG_ON(cm_id->event_handler==(void*)0x6b6b6b6b);245246spin_lock_irqsave(&qp->lock, flags);247if (qp->cm_id) {248qp->cm_id->rem_ref(qp->cm_id);249qp->cm_id = NULL;250}251spin_unlock_irqrestore(&qp->lock, flags);252cm_event.event = IW_CM_EVENT_CLOSE;253cm_event.status = 0;254if (cm_id->event_handler)255cm_id->event_handler(cm_id, &cm_event);256break;257default:258BUG_ON(1);259pr_debug("%s:%d Unexpected event_id=%d on QP=%p, "260"CM_ID=%p\n",261__func__, __LINE__,262event_id, qp, cm_id);263break;264}265break;266}267268case C2_RES_IND_EP:{269270struct c2wr_ae_connection_request *req =271&wr->ae.ae_connection_request;272struct iw_cm_id *cm_id =273(struct iw_cm_id *)resource_user_context;274275pr_debug("C2_RES_IND_EP event_id=%d\n", event_id);276if (event_id != CCAE_CONNECTION_REQUEST) {277pr_debug("%s: Invalid event_id: %d\n",278__func__, event_id);279break;280}281cm_event.event = IW_CM_EVENT_CONNECT_REQUEST;282cm_event.provider_data = (void*)(unsigned long)req->cr_handle;283cm_event.local_addr.sin_addr.s_addr = req->laddr;284cm_event.remote_addr.sin_addr.s_addr = req->raddr;285cm_event.local_addr.sin_port = req->lport;286cm_event.remote_addr.sin_port = req->rport;287cm_event.private_data_len =288be32_to_cpu(req->private_data_length);289cm_event.private_data = req->private_data;290291if (cm_id->event_handler)292cm_id->event_handler(cm_id, &cm_event);293break;294}295296case C2_RES_IND_CQ:{297struct c2_cq *cq =298(struct c2_cq *) resource_user_context;299300pr_debug("IB_EVENT_CQ_ERR\n");301ib_event.device = &c2dev->ibdev;302ib_event.element.cq = &cq->ibcq;303ib_event.event = IB_EVENT_CQ_ERR;304305if (cq->ibcq.event_handler)306cq->ibcq.event_handler(&ib_event,307cq->ibcq.cq_context);308}309310default:311printk("Bad resource indicator = %d\n",312resource_indicator);313break;314}315316ignore_it:317c2_mq_free(mq);318}319320321