mlx4_en_cq.c revision 219820
1219820Sjeff/*
2219820Sjeff * Copyright (c) 2007 Mellanox Technologies. All rights reserved.
3219820Sjeff *
4219820Sjeff * This software is available to you under a choice of one of two
5219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
6219820Sjeff * General Public License (GPL) Version 2, available from the file
7219820Sjeff * COPYING in the main directory of this source tree, or the
8219820Sjeff * OpenIB.org BSD license below:
9219820Sjeff *
10219820Sjeff *     Redistribution and use in source and binary forms, with or
11219820Sjeff *     without modification, are permitted provided that the following
12219820Sjeff *     conditions are met:
13219820Sjeff *
14219820Sjeff *      - Redistributions of source code must retain the above
15219820Sjeff *        copyright notice, this list of conditions and the following
16219820Sjeff *        disclaimer.
17219820Sjeff *
18219820Sjeff *      - Redistributions in binary form must reproduce the above
19219820Sjeff *        copyright notice, this list of conditions and the following
20219820Sjeff *        disclaimer in the documentation and/or other materials
21219820Sjeff *        provided with the distribution.
22219820Sjeff *
23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30219820Sjeff * SOFTWARE.
31219820Sjeff *
32219820Sjeff */
33219820Sjeff
34219820Sjeff#include "mlx4_en.h"
35219820Sjeff
36219820Sjeff#include <linux/mlx4/cq.h>
37219820Sjeff#include <linux/mlx4/qp.h>
38219820Sjeff#include <linux/mlx4/cmd.h>
39219820Sjeff
40219820Sjeffstatic void mlx4_en_cq_event(struct mlx4_cq *cq, enum mlx4_event event)
41219820Sjeff{
42219820Sjeff	return;
43219820Sjeff}
44219820Sjeff
45219820Sjeff
46219820Sjeffint mlx4_en_create_cq(struct mlx4_en_priv *priv,
47219820Sjeff		      struct mlx4_en_cq *cq,
48219820Sjeff		      int entries, int ring, enum cq_type mode)
49219820Sjeff{
50219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
51219820Sjeff	int err;
52219820Sjeff
53219820Sjeff	cq->size = entries;
54219820Sjeff	if (mode == RX) {
55219820Sjeff		cq->buf_size = cq->size * sizeof(struct mlx4_cqe);
56219820Sjeff		cq->vector   = (ring + priv->port) %
57219820Sjeff				mdev->dev->caps.num_comp_vectors;
58219820Sjeff		TASK_INIT(&cq->cq_task, 0, mlx4_en_rx_que, cq);
59219820Sjeff	} else {
60219820Sjeff		cq->buf_size = sizeof(struct mlx4_cqe);
61219820Sjeff		cq->vector   = MLX4_LEAST_ATTACHED_VECTOR;
62219820Sjeff		TASK_INIT(&cq->cq_task, 0, mlx4_en_tx_que, cq);
63219820Sjeff	}
64219820Sjeff
65219820Sjeff	cq->tq = taskqueue_create_fast("mlx4_en_que", M_NOWAIT,
66219820Sjeff	    taskqueue_thread_enqueue, &cq->tq);
67219820Sjeff	taskqueue_start_threads(&cq->tq, 1, PI_NET, "%s cq",
68219820Sjeff	    if_name(priv->dev));
69219820Sjeff	cq->ring = ring;
70219820Sjeff	cq->is_tx = mode;
71219820Sjeff	mtx_init(&cq->lock.m, "mlx4 cq", NULL, MTX_DEF);
72219820Sjeff
73219820Sjeff	err = mlx4_alloc_hwq_res(mdev->dev, &cq->wqres,
74219820Sjeff				cq->buf_size, 2 * PAGE_SIZE);
75219820Sjeff	if (err)
76219820Sjeff		return err;
77219820Sjeff
78219820Sjeff	err = mlx4_en_map_buffer(&cq->wqres.buf);
79219820Sjeff	if (err)
80219820Sjeff		mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
81219820Sjeff	else
82219820Sjeff		cq->buf = (struct mlx4_cqe *) cq->wqres.buf.direct.buf;
83219820Sjeff
84219820Sjeff	return err;
85219820Sjeff}
86219820Sjeff
87219820Sjeffint mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
88219820Sjeff{
89219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
90219820Sjeff	int err;
91219820Sjeff
92219820Sjeff	cq->dev = mdev->pndev[priv->port];
93219820Sjeff	cq->mcq.set_ci_db  = cq->wqres.db.db;
94219820Sjeff	cq->mcq.arm_db     = cq->wqres.db.db + 1;
95219820Sjeff	*cq->mcq.set_ci_db = 0;
96219820Sjeff	*cq->mcq.arm_db    = 0;
97219820Sjeff	memset(cq->buf, 0, cq->buf_size);
98219820Sjeff
99219820Sjeff	if (!cq->is_tx)
100219820Sjeff		cq->size = priv->rx_ring[cq->ring].actual_size;
101219820Sjeff
102219820Sjeff	err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, &mdev->priv_uar,
103219820Sjeff			    cq->wqres.db.dma, &cq->mcq, cq->vector, cq->is_tx);
104219820Sjeff	if (err)
105219820Sjeff		return err;
106219820Sjeff
107219820Sjeff	cq->mcq.comp  = cq->is_tx ? mlx4_en_tx_irq : mlx4_en_rx_irq;
108219820Sjeff	cq->mcq.event = mlx4_en_cq_event;
109219820Sjeff
110219820Sjeff	if (cq->is_tx) {
111219820Sjeff		init_timer(&cq->timer);
112219820Sjeff		cq->timer.function = mlx4_en_poll_tx_cq;
113219820Sjeff		cq->timer.data = (unsigned long) cq;
114219820Sjeff	}
115219820Sjeff
116219820Sjeff	return 0;
117219820Sjeff}
118219820Sjeff
119219820Sjeffvoid mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
120219820Sjeff{
121219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
122219820Sjeff
123219820Sjeff	taskqueue_drain(cq->tq, &cq->cq_task);
124219820Sjeff	taskqueue_free(cq->tq);
125219820Sjeff	mlx4_en_unmap_buffer(&cq->wqres.buf);
126219820Sjeff	mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
127219820Sjeff	cq->buf_size = 0;
128219820Sjeff	cq->buf = NULL;
129219820Sjeff	mtx_destroy(&cq->lock.m);
130219820Sjeff}
131219820Sjeff
132219820Sjeffvoid mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
133219820Sjeff{
134219820Sjeff	struct mlx4_en_dev *mdev = priv->mdev;
135219820Sjeff
136219820Sjeff	taskqueue_drain(cq->tq, &cq->cq_task);
137219820Sjeff	if (cq->is_tx)
138219820Sjeff		del_timer(&cq->timer);
139219820Sjeff
140219820Sjeff	mlx4_cq_free(mdev->dev, &cq->mcq);
141219820Sjeff}
142219820Sjeff
143219820Sjeff/* Set rx cq moderation parameters */
144219820Sjeffint mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
145219820Sjeff{
146219820Sjeff	return mlx4_cq_modify(priv->mdev->dev, &cq->mcq,
147219820Sjeff			      cq->moder_cnt, cq->moder_time);
148219820Sjeff}
149219820Sjeff
150219820Sjeffint mlx4_en_arm_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
151219820Sjeff{
152219820Sjeff	mlx4_cq_arm(&cq->mcq, MLX4_CQ_DB_REQ_NOT, priv->mdev->uar_map,
153219820Sjeff		    &priv->mdev->uar_lock);
154219820Sjeff
155219820Sjeff	return 0;
156219820Sjeff}
157219820Sjeff
158219820Sjeff
159