2008-10-22 15:47:49 -07:00
/*
* Copyright ( c ) 2007 Mellanox Technologies . All rights reserved .
*
* This software is available to you under a choice of one of two
* licenses . You may choose to be licensed under the terms of the GNU
* General Public License ( GPL ) Version 2 , available from the file
* COPYING in the main directory of this source tree , or the
* OpenIB . org BSD license below :
*
* Redistribution and use in source and binary forms , with or
* without modification , are permitted provided that the following
* conditions are met :
*
* - Redistributions of source code must retain the above
* copyright notice , this list of conditions and the following
* disclaimer .
*
* - Redistributions in binary form must reproduce the above
* copyright notice , this list of conditions and the following
* disclaimer in the documentation and / or other materials
* provided with the distribution .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND ,
* EXPRESS OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY , FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER IN AN
* ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE .
*
*/
# include <linux/mlx4/cq.h>
# include <linux/mlx4/qp.h>
# include <linux/mlx4/cmd.h>
# include "mlx4_en.h"
static void mlx4_en_cq_event ( struct mlx4_cq * cq , enum mlx4_event event )
{
return ;
}
int mlx4_en_create_cq ( struct mlx4_en_priv * priv ,
struct mlx4_en_cq * cq ,
int entries , int ring , enum cq_type mode )
{
struct mlx4_en_dev * mdev = priv - > mdev ;
int err ;
cq - > size = entries ;
2011-03-22 22:37:52 +00:00
if ( mode = = RX )
2008-10-22 15:47:49 -07:00
cq - > buf_size = cq - > size * sizeof ( struct mlx4_cqe ) ;
2011-03-22 22:37:52 +00:00
else
2008-10-22 15:47:49 -07:00
cq - > buf_size = sizeof ( struct mlx4_cqe ) ;
cq - > ring = ring ;
cq - > is_tx = mode ;
spin_lock_init ( & cq - > lock ) ;
err = mlx4_alloc_hwq_res ( mdev - > dev , & cq - > wqres ,
cq - > buf_size , 2 * PAGE_SIZE ) ;
if ( err )
return err ;
err = mlx4_en_map_buffer ( & cq - > wqres . buf ) ;
if ( err )
mlx4_free_hwq_res ( mdev - > dev , & cq - > wqres , cq - > buf_size ) ;
2008-12-25 18:13:20 -08:00
else
cq - > buf = ( struct mlx4_cqe * ) cq - > wqres . buf . direct . buf ;
2008-10-22 15:47:49 -07:00
return err ;
}
int mlx4_en_activate_cq ( struct mlx4_en_priv * priv , struct mlx4_en_cq * cq )
{
struct mlx4_en_dev * mdev = priv - > mdev ;
2011-03-22 22:37:52 +00:00
int err = 0 ;
char name [ 25 ] ;
2008-10-22 15:47:49 -07:00
cq - > dev = mdev - > pndev [ priv - > port ] ;
cq - > mcq . set_ci_db = cq - > wqres . db . db ;
cq - > mcq . arm_db = cq - > wqres . db . db + 1 ;
* cq - > mcq . set_ci_db = 0 ;
* cq - > mcq . arm_db = 0 ;
memset ( cq - > buf , 0 , cq - > buf_size ) ;
2011-03-22 22:37:52 +00:00
if ( cq - > is_tx = = RX ) {
if ( mdev - > dev - > caps . comp_pool ) {
if ( ! cq - > vector ) {
sprintf ( name , " %s-rx-%d " , priv - > dev - > name , cq - > ring ) ;
if ( mlx4_assign_eq ( mdev - > dev , name , & cq - > vector ) ) {
cq - > vector = ( cq - > ring + 1 + priv - > port ) %
mdev - > dev - > caps . num_comp_vectors ;
mlx4_warn ( mdev , " Failed Assigning an EQ to "
" %s_rx-%d ,Falling back to legacy EQ's \n " ,
priv - > dev - > name , cq - > ring ) ;
}
}
} else {
cq - > vector = ( cq - > ring + 1 + priv - > port ) %
mdev - > dev - > caps . num_comp_vectors ;
}
} else {
if ( ! cq - > vector | | ! mdev - > dev - > caps . comp_pool ) {
/*Fallback to legacy pool in case of error*/
cq - > vector = 0 ;
}
}
2009-05-24 03:17:11 +00:00
if ( ! cq - > is_tx )
cq - > size = priv - > rx_ring [ cq - > ring ] . actual_size ;
2008-10-22 15:47:49 -07:00
err = mlx4_cq_alloc ( mdev - > dev , cq - > size , & cq - > wqres . mtt , & mdev - > priv_uar ,
2008-12-22 07:15:03 -08:00
cq - > wqres . db . dma , & cq - > mcq , cq - > vector , cq - > is_tx ) ;
2008-10-22 15:47:49 -07:00
if ( err )
return err ;
cq - > mcq . comp = cq - > is_tx ? mlx4_en_tx_irq : mlx4_en_rx_irq ;
cq - > mcq . event = mlx4_en_cq_event ;
if ( cq - > is_tx ) {
init_timer ( & cq - > timer ) ;
cq - > timer . function = mlx4_en_poll_tx_cq ;
cq - > timer . data = ( unsigned long ) cq ;
} else {
netif_napi_add ( cq - > dev , & cq - > napi , mlx4_en_poll_rx_cq , 64 ) ;
napi_enable ( & cq - > napi ) ;
}
return 0 ;
}
2011-03-22 22:37:52 +00:00
void mlx4_en_destroy_cq ( struct mlx4_en_priv * priv , struct mlx4_en_cq * cq ,
bool reserve_vectors )
2008-10-22 15:47:49 -07:00
{
struct mlx4_en_dev * mdev = priv - > mdev ;
mlx4_en_unmap_buffer ( & cq - > wqres . buf ) ;
mlx4_free_hwq_res ( mdev - > dev , & cq - > wqres , cq - > buf_size ) ;
2011-03-22 22:37:52 +00:00
if ( priv - > mdev - > dev - > caps . comp_pool & & cq - > vector & & ! reserve_vectors )
mlx4_release_eq ( priv - > mdev - > dev , cq - > vector ) ;
2008-10-22 15:47:49 -07:00
cq - > buf_size = 0 ;
cq - > buf = NULL ;
}
void mlx4_en_deactivate_cq ( struct mlx4_en_priv * priv , struct mlx4_en_cq * cq )
{
struct mlx4_en_dev * mdev = priv - > mdev ;
if ( cq - > is_tx )
del_timer ( & cq - > timer ) ;
2009-05-17 20:48:59 -07:00
else {
2008-10-22 15:47:49 -07:00
napi_disable ( & cq - > napi ) ;
2009-05-17 20:48:59 -07:00
netif_napi_del ( & cq - > napi ) ;
}
2008-10-22 15:47:49 -07:00
mlx4_cq_free ( mdev - > dev , & cq - > mcq ) ;
}
/* Set rx cq moderation parameters */
int mlx4_en_set_cq_moder ( struct mlx4_en_priv * priv , struct mlx4_en_cq * cq )
{
return mlx4_cq_modify ( priv - > mdev - > dev , & cq - > mcq ,
cq - > moder_cnt , cq - > moder_time ) ;
}
int mlx4_en_arm_cq ( struct mlx4_en_priv * priv , struct mlx4_en_cq * cq )
{
mlx4_cq_arm ( & cq - > mcq , MLX4_CQ_DB_REQ_NOT , priv - > mdev - > uar_map ,
& priv - > mdev - > uar_lock ) ;
return 0 ;
}