en_cq.c revision 272407
154359Sroberto/* 2182007Sroberto * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved. 354359Sroberto * 4182007Sroberto * This software is available to you under a choice of one of two 554359Sroberto * licenses. You may choose to be licensed under the terms of the GNU 6182007Sroberto * General Public License (GPL) Version 2, available from the file 7285612Sdelphij * COPYING in the main directory of this source tree, or the 854359Sroberto * OpenIB.org BSD license below: 9182007Sroberto * 10182007Sroberto * Redistribution and use in source and binary forms, with or 11182007Sroberto * without modification, are permitted provided that the following 12182007Sroberto * conditions are met: 13182007Sroberto * 14182007Sroberto * - Redistributions of source code must retain the above 15182007Sroberto * copyright notice, this list of conditions and the following 16182007Sroberto * disclaimer. 17182007Sroberto * 18182007Sroberto * - Redistributions in binary form must reproduce the above 19182007Sroberto * copyright notice, this list of conditions and the following 20182007Sroberto * disclaimer in the documentation and/or other materials 21182007Sroberto * provided with the distribution. 22182007Sroberto * 23182007Sroberto * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24182007Sroberto * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25182007Sroberto * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26182007Sroberto * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27182007Sroberto * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28182007Sroberto * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29182007Sroberto * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30182007Sroberto * SOFTWARE. 31182007Sroberto * 32182007Sroberto */ 3354359Sroberto 3454359Sroberto#include <linux/mlx4/cq.h> 3554359Sroberto#include <linux/mlx4/qp.h> 3654359Sroberto#include <linux/mlx4/cmd.h> 3754359Sroberto 38182007Sroberto#include "mlx4_en.h" 3954359Sroberto 4054359Sroberto 4154359Srobertostatic void mlx4_en_cq_event(struct mlx4_cq *cq, enum mlx4_event event) 4254359Sroberto{ 4354359Sroberto return; 44285612Sdelphij} 4554359Sroberto 46285612Sdelphij 47285612Sdelphijint mlx4_en_create_cq(struct mlx4_en_priv *priv, 48285612Sdelphij struct mlx4_en_cq **pcq, 49285612Sdelphij int entries, int ring, enum cq_type mode, 50285612Sdelphij int node) 5154359Sroberto{ 5254359Sroberto struct mlx4_en_dev *mdev = priv->mdev; 5354359Sroberto struct mlx4_en_cq *cq; 5454359Sroberto int err; 5554359Sroberto 5654359Sroberto cq = kzalloc_node(sizeof(struct mlx4_en_cq), GFP_KERNEL, node); 5754359Sroberto if (!cq) { 5854359Sroberto cq = kzalloc(sizeof(struct mlx4_en_cq), GFP_KERNEL); 5954359Sroberto if (!cq) { 6054359Sroberto en_err(priv, "Failed to allocate CW struture\n"); 6154359Sroberto return -ENOMEM; 6254359Sroberto } 6354359Sroberto } 6454359Sroberto 6554359Sroberto cq->size = entries; 6654359Sroberto cq->buf_size = cq->size * mdev->dev->caps.cqe_size; 6754359Sroberto 6854359Sroberto cq->tq = taskqueue_create_fast("mlx4_en_que", M_NOWAIT, 6954359Sroberto taskqueue_thread_enqueue, &cq->tq); 7054359Sroberto if (mode == RX) { 7154359Sroberto TASK_INIT(&cq->cq_task, 0, mlx4_en_rx_que, cq); 7254359Sroberto taskqueue_start_threads(&cq->tq, 1, PI_NET, "%s rx cq", 7354359Sroberto if_name(priv->dev)); 7454359Sroberto 75182007Sroberto } else { 76182007Sroberto TASK_INIT(&cq->cq_task, 0, mlx4_en_tx_que, cq); 77182007Sroberto taskqueue_start_threads(&cq->tq, 1, PI_NET, "%s tx cq", 78182007Sroberto if_name(priv->dev)); 79182007Sroberto } 80182007Sroberto 81182007Sroberto cq->ring = ring; 82182007Sroberto cq->is_tx = mode; 83182007Sroberto spin_lock_init(&cq->lock); 84 85 err = mlx4_alloc_hwq_res(mdev->dev, &cq->wqres, 86 cq->buf_size, 2 * PAGE_SIZE); 87 if (err) 88 goto err_cq; 89 90 err = mlx4_en_map_buffer(&cq->wqres.buf); 91 if (err) 92 goto err_res; 93 94 cq->buf = (struct mlx4_cqe *) cq->wqres.buf.direct.buf; 95 *pcq = cq; 96 97 return 0; 98 99err_res: 100 mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size); 101err_cq: 102 kfree(cq); 103 return err; 104} 105 106 107int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq, 108 int cq_idx) 109{ 110 struct mlx4_en_dev *mdev = priv->mdev; 111 int err = 0; 112 char name[25]; 113 int timestamp_en = 0; 114 115 cq->dev = mdev->pndev[priv->port]; 116 cq->mcq.set_ci_db = cq->wqres.db.db; 117 cq->mcq.arm_db = cq->wqres.db.db + 1; 118 *cq->mcq.set_ci_db = 0; 119 *cq->mcq.arm_db = 0; 120 memset(cq->buf, 0, cq->buf_size); 121 122 if (cq->is_tx == RX) { 123 if (mdev->dev->caps.comp_pool) { 124 if (!cq->vector) { 125 sprintf(name, "%s-%d", if_name(priv->dev), 126 cq->ring); 127 /* Set IRQ for specific name (per ring) */ 128 if (mlx4_assign_eq(mdev->dev, name, &cq->vector)) { 129 cq->vector = (cq->ring + 1 + priv->port) 130 % mdev->dev->caps.num_comp_vectors; 131 mlx4_warn(mdev, "Failed Assigning an EQ to " 132 "%s ,Falling back to legacy EQ's\n", 133 name); 134 } 135 } 136 } else { 137 cq->vector = (cq->ring + 1 + priv->port) % 138 mdev->dev->caps.num_comp_vectors; 139 } 140 } else { 141 struct mlx4_en_cq *rx_cq; 142 /* 143 * For TX we use the same irq per 144 * ring we assigned for the RX 145 */ 146 cq_idx = cq_idx % priv->rx_ring_num; 147 rx_cq = priv->rx_cq[cq_idx]; 148 cq->vector = rx_cq->vector; 149 } 150 151 if (!cq->is_tx) 152 cq->size = priv->rx_ring[cq->ring]->actual_size; 153 err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, 154 &mdev->priv_uar, cq->wqres.db.dma, &cq->mcq, 155 cq->vector, 0, timestamp_en); 156 if (err) 157 return err; 158 159 cq->mcq.comp = cq->is_tx ? mlx4_en_tx_irq : mlx4_en_rx_irq; 160 cq->mcq.event = mlx4_en_cq_event; 161 162 if (cq->is_tx) { 163 init_timer(&cq->timer); 164 cq->timer.function = mlx4_en_poll_tx_cq; 165 cq->timer.data = (unsigned long) cq; 166 } 167 168 169 return 0; 170} 171 172void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq **pcq) 173{ 174 struct mlx4_en_dev *mdev = priv->mdev; 175 struct mlx4_en_cq *cq = *pcq; 176 177 taskqueue_drain(cq->tq, &cq->cq_task); 178 taskqueue_free(cq->tq); 179 mlx4_en_unmap_buffer(&cq->wqres.buf); 180 mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size); 181 if (priv->mdev->dev->caps.comp_pool && cq->vector) 182 mlx4_release_eq(priv->mdev->dev, cq->vector); 183 kfree(cq); 184 *pcq = NULL; 185} 186 187void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) 188{ 189 struct mlx4_en_dev *mdev = priv->mdev; 190 191 taskqueue_drain(cq->tq, &cq->cq_task); 192 if (cq->is_tx) 193 del_timer(&cq->timer); 194 195 mlx4_cq_free(mdev->dev, &cq->mcq); 196} 197 198 199/* Set rx cq moderation parameters */ 200int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) 201{ 202 return mlx4_cq_modify(priv->mdev->dev, &cq->mcq, 203 cq->moder_cnt, cq->moder_time); 204} 205 206int mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq) 207{ 208 mlx4_cq_arm(&cq->mcq, MLX4_CQ_DB_REQ_NOT, priv->mdev->uar_map, 209 &priv->mdev->uar_lock); 210 211 return 0; 212} 213 214 215