18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * This file is part of the Chelsio T6 Ethernet driver for Linux. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (c) 2017-2018 Chelsio Communications, Inc. All rights reserved. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 78c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 88c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 98c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 108c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 138c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 148c2ecf20Sopenharmony_ci * conditions are met: 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 178c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 188c2ecf20Sopenharmony_ci * disclaimer. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 218c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 228c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 238c2ecf20Sopenharmony_ci * provided with the distribution. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 268c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 278c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 288c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 298c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 308c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 318c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 328c2ecf20Sopenharmony_ci * SOFTWARE. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include "cxgb4.h" 368c2ecf20Sopenharmony_ci#include "t4_msg.h" 378c2ecf20Sopenharmony_ci#include "srq.h" 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistruct srq_data *t4_init_srq(int srq_size) 408c2ecf20Sopenharmony_ci{ 418c2ecf20Sopenharmony_ci struct srq_data *s; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci s = kvzalloc(sizeof(*s), GFP_KERNEL); 448c2ecf20Sopenharmony_ci if (!s) 458c2ecf20Sopenharmony_ci return NULL; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci s->srq_size = srq_size; 488c2ecf20Sopenharmony_ci init_completion(&s->comp); 498c2ecf20Sopenharmony_ci mutex_init(&s->lock); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci return s; 528c2ecf20Sopenharmony_ci} 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/* cxgb4_get_srq_entry: read the SRQ table entry 558c2ecf20Sopenharmony_ci * @dev: Pointer to the net_device 568c2ecf20Sopenharmony_ci * @idx: Index to the srq 578c2ecf20Sopenharmony_ci * @entryp: pointer to the srq entry 588c2ecf20Sopenharmony_ci * 598c2ecf20Sopenharmony_ci * Sends CPL_SRQ_TABLE_REQ message for the given index. 608c2ecf20Sopenharmony_ci * Contents will be returned in CPL_SRQ_TABLE_RPL message. 618c2ecf20Sopenharmony_ci * 628c2ecf20Sopenharmony_ci * Returns zero if the read is successful, else a error 638c2ecf20Sopenharmony_ci * number will be returned. Caller should not use the srq 648c2ecf20Sopenharmony_ci * entry if the return value is non-zero. 658c2ecf20Sopenharmony_ci * 668c2ecf20Sopenharmony_ci * 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ciint cxgb4_get_srq_entry(struct net_device *dev, 698c2ecf20Sopenharmony_ci int srq_idx, struct srq_entry *entryp) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci struct cpl_srq_table_req *req; 728c2ecf20Sopenharmony_ci struct adapter *adap; 738c2ecf20Sopenharmony_ci struct sk_buff *skb; 748c2ecf20Sopenharmony_ci struct srq_data *s; 758c2ecf20Sopenharmony_ci int rc = -ENODEV; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci adap = netdev2adap(dev); 788c2ecf20Sopenharmony_ci s = adap->srq; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci if (!(adap->flags & CXGB4_FULL_INIT_DONE) || !s) 818c2ecf20Sopenharmony_ci goto out; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci skb = alloc_skb(sizeof(*req), GFP_KERNEL); 848c2ecf20Sopenharmony_ci if (!skb) 858c2ecf20Sopenharmony_ci return -ENOMEM; 868c2ecf20Sopenharmony_ci req = (struct cpl_srq_table_req *) 878c2ecf20Sopenharmony_ci __skb_put_zero(skb, sizeof(*req)); 888c2ecf20Sopenharmony_ci INIT_TP_WR(req, 0); 898c2ecf20Sopenharmony_ci OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SRQ_TABLE_REQ, 908c2ecf20Sopenharmony_ci TID_TID_V(srq_idx) | 918c2ecf20Sopenharmony_ci TID_QID_V(adap->sge.fw_evtq.abs_id))); 928c2ecf20Sopenharmony_ci req->idx = srq_idx; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci mutex_lock(&s->lock); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci s->entryp = entryp; 978c2ecf20Sopenharmony_ci t4_mgmt_tx(adap, skb); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci rc = wait_for_completion_timeout(&s->comp, SRQ_WAIT_TO); 1008c2ecf20Sopenharmony_ci if (rc) 1018c2ecf20Sopenharmony_ci rc = 0; 1028c2ecf20Sopenharmony_ci else /* !rc means we timed out */ 1038c2ecf20Sopenharmony_ci rc = -ETIMEDOUT; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci WARN_ON_ONCE(entryp->idx != srq_idx); 1068c2ecf20Sopenharmony_ci mutex_unlock(&s->lock); 1078c2ecf20Sopenharmony_ciout: 1088c2ecf20Sopenharmony_ci return rc; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ciEXPORT_SYMBOL(cxgb4_get_srq_entry); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_civoid do_srq_table_rpl(struct adapter *adap, 1138c2ecf20Sopenharmony_ci const struct cpl_srq_table_rpl *rpl) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci unsigned int idx = TID_TID_G(GET_TID(rpl)); 1168c2ecf20Sopenharmony_ci struct srq_data *s = adap->srq; 1178c2ecf20Sopenharmony_ci struct srq_entry *e; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci if (unlikely(rpl->status != CPL_CONTAINS_READ_RPL)) { 1208c2ecf20Sopenharmony_ci dev_err(adap->pdev_dev, 1218c2ecf20Sopenharmony_ci "Unexpected SRQ_TABLE_RPL status %u for entry %u\n", 1228c2ecf20Sopenharmony_ci rpl->status, idx); 1238c2ecf20Sopenharmony_ci goto out; 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci /* Store the read entry */ 1278c2ecf20Sopenharmony_ci e = s->entryp; 1288c2ecf20Sopenharmony_ci e->valid = 1; 1298c2ecf20Sopenharmony_ci e->idx = idx; 1308c2ecf20Sopenharmony_ci e->pdid = SRQT_PDID_G(be64_to_cpu(rpl->rsvd_pdid)); 1318c2ecf20Sopenharmony_ci e->qlen = SRQT_QLEN_G(be32_to_cpu(rpl->qlen_qbase)); 1328c2ecf20Sopenharmony_ci e->qbase = SRQT_QBASE_G(be32_to_cpu(rpl->qlen_qbase)); 1338c2ecf20Sopenharmony_ci e->cur_msn = be16_to_cpu(rpl->cur_msn); 1348c2ecf20Sopenharmony_ci e->max_msn = be16_to_cpu(rpl->max_msn); 1358c2ecf20Sopenharmony_ciout: 1368c2ecf20Sopenharmony_ci complete(&s->comp); 1378c2ecf20Sopenharmony_ci} 138