iPXE
mlx_port.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2015 Mellanox Technologies Ltd.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  */
00019 
00020 FILE_LICENCE ( GPL2_OR_LATER );
00021 
00022 #include "../include/mlx_port.h"
00023 #include "../include/mlx_cmd.h"
00024 #include "../../mlx_utils/include/public/mlx_memory.h"
00025 #include "../../mlx_utils/include/public/mlx_pci.h"
00026 #include "../../mlx_utils/include/public/mlx_bail.h"
00027 
00028 #define PortDataEntry( _option, _offset, _align, _mask) { \
00029   .option = _option,                     \
00030   .offset = _offset,                   \
00031   .align = _align,                  \
00032   .mask = _mask,                    \
00033   }
00034 
00035 #define QpDataEntry( _type, _send_offset, _recv_offset) { \
00036   .type = _type,                     \
00037   .send_offset = _send_offset,                   \
00038   .recv_offset = _recv_offset,                  \
00039   }
00040 
00041 
00042 struct nodnic_port_data_entry nodnic_port_data_table[] = {
00043                 PortDataEntry(nodnic_port_option_link_type, 0x0, 4, 0x1),
00044                 PortDataEntry(nodnic_port_option_mac_low, 0xc, 0, 0xFFFFFFFF),
00045                 PortDataEntry(nodnic_port_option_mac_high, 0x8, 0, 0xFFFF),
00046                 PortDataEntry(nodnic_port_option_log_cq_size, 0x6c, 0, 0x3F),
00047                 PortDataEntry(nodnic_port_option_reset_needed, 0x0, 31, 0x1),
00048                 PortDataEntry(nodnic_port_option_mac_filters_en, 0x4, 0, 0x1F),
00049                 PortDataEntry(nodnic_port_option_port_state, 0x0, 0, 0xF),
00050                 PortDataEntry(nodnic_port_option_network_en, 0x4, 31, 0x1),
00051                 PortDataEntry(nodnic_port_option_dma_en, 0x4, 30, 0x1),
00052                 PortDataEntry(nodnic_port_option_eq_addr_low, 0x74, 0, 0xFFFFFFFF),
00053                 PortDataEntry(nodnic_port_option_eq_addr_high, 0x70, 0, 0xFFFFFFFF),
00054                 PortDataEntry(nodnic_port_option_cq_addr_low, 0x6c, 12, 0xFFFFF),
00055                 PortDataEntry(nodnic_port_option_cq_addr_high, 0x68, 0, 0xFFFFFFFF),
00056                 PortDataEntry(nodnic_port_option_port_management_change_event, 0x0, 30, 0x1),
00057                 PortDataEntry(nodnic_port_option_port_promisc_en, 0x4, 29, 0x1),
00058 #ifndef DEVICE_CX3
00059                 PortDataEntry(nodnic_port_option_arm_cq, 0x78, 8, 0xffffff),
00060 #else
00061                 PortDataEntry(nodnic_port_option_arm_cq, 0x78, 8, 0xffff),
00062 #endif
00063                 PortDataEntry(nodnic_port_option_port_promisc_multicast_en, 0x4, 28, 0x1),
00064 #ifdef DEVICE_CX3
00065                 PortDataEntry(nodnic_port_option_crspace_en, 0x4, 27, 0x1),
00066 #endif
00067                 PortDataEntry(nodnic_port_option_send_ring0_uar_index, 0x108, 0, 0xFFFFFFFF),
00068                 PortDataEntry(nodnic_port_option_send_ring1_uar_index, 0x10c, 0, 0xFFFFFFFF),
00069                 PortDataEntry(nodnic_port_option_cq_n_index, 0x118, 0, 0xFFFFFF),
00070 };
00071 
00072 #define MAX_QP_DATA_ENTRIES 5
00073 struct nodnic_qp_data_entry nodnic_qp_data_teable[MAX_QP_DATA_ENTRIES] = {
00074                 QpDataEntry(NODNIC_QPT_SMI, 0, 0),
00075                 QpDataEntry(NODNIC_QPT_GSI, 0, 0),
00076                 QpDataEntry(NODNIC_QPT_UD, 0, 0),
00077                 QpDataEntry(NODNIC_QPT_RC, 0, 0),
00078                 QpDataEntry(NODNIC_QPT_ETH, 0x80, 0xC0),
00079 };
00080 
00081 #define MAX_NODNIC_PORTS 2
00082 int nodnic_port_offset_table[MAX_NODNIC_PORTS] = {
00083         0x100, //port 1 offset
00084         0x280, //port 1 offset
00085 };
00086 
00087 mlx_status
00088 nodnic_port_get_state(
00089                                         IN  nodnic_port_priv    *port_priv,
00090                                         OUT nodnic_port_state                   *state
00091                                         )
00092 {
00093         mlx_status status = MLX_SUCCESS;
00094         mlx_uint32 out = 0;
00095 
00096         status = nodnic_port_query(port_priv,
00097                         nodnic_port_option_port_state, &out);
00098         MLX_CHECK_STATUS(port_priv->device, status, query_err,
00099                         "nodnic_port_query failed");
00100         *state = (nodnic_port_state)out;
00101 query_err:
00102         return status;
00103 }
00104 mlx_status
00105 nodnic_port_get_type(
00106                                         IN  nodnic_port_priv    *port_priv,
00107                                         OUT nodnic_port_type    *type
00108                                         )
00109 {
00110         mlx_status status = MLX_SUCCESS;
00111         mlx_uint32 out = 0;
00112 
00113         if ( port_priv->port_type == NODNIC_PORT_TYPE_UNKNOWN){
00114                 status = nodnic_port_query(port_priv,
00115                                 nodnic_port_option_link_type, &out);
00116                 MLX_FATAL_CHECK_STATUS(status, query_err,
00117                                 "nodnic_port_query failed");
00118                 port_priv->port_type = (nodnic_port_type)out;
00119         }
00120         *type = port_priv->port_type;
00121 query_err:
00122         return status;
00123 }
00124 
00125 mlx_status
00126 nodnic_port_query(
00127                                         IN  nodnic_port_priv    *port_priv,
00128                                         IN  nodnic_port_option          option,
00129                                         OUT     mlx_uint32                              *out
00130                                         )
00131 {
00132         mlx_status                              status = MLX_SUCCESS;
00133         nodnic_device_priv              *device_priv = NULL;
00134         struct nodnic_port_data_entry *data_entry;
00135         mlx_uint32                              buffer = 0;
00136         if( port_priv == NULL || out == NULL){
00137                 status = MLX_INVALID_PARAMETER;
00138                 goto invalid_parm;
00139         }
00140         device_priv = port_priv->device;
00141 
00142         data_entry = &nodnic_port_data_table[option];
00143 
00144         status = nodnic_cmd_read(device_priv,
00145                         port_priv->port_offset + data_entry->offset , &buffer);
00146         MLX_CHECK_STATUS(device_priv, status, read_err,
00147                         "nodnic_cmd_read failed");
00148         *out = (buffer >> data_entry->align) & data_entry->mask;
00149 read_err:
00150 invalid_parm:
00151         return status;
00152 }
00153 
00154 mlx_status
00155 nodnic_port_set(
00156                                         IN  nodnic_port_priv    *port_priv,
00157                                         IN  nodnic_port_option          option,
00158                                         IN      mlx_uint32                              in
00159                                         )
00160 {
00161         mlx_status                              status = MLX_SUCCESS;
00162         nodnic_device_priv              *device_priv = NULL;
00163         struct nodnic_port_data_entry *data_entry;
00164         mlx_uint32                              buffer = 0;
00165 
00166         if( port_priv == NULL ){
00167                 MLX_DEBUG_FATAL_ERROR("port_priv is NULL\n");
00168                 status = MLX_INVALID_PARAMETER;
00169                 goto invalid_parm;
00170         }
00171         device_priv = port_priv->device;
00172         data_entry = &nodnic_port_data_table[option];
00173 
00174         if( in > data_entry->mask ){
00175                 MLX_DEBUG_FATAL_ERROR("in > data_entry->mask (%d > %d)\n",
00176                                 in, data_entry->mask);
00177                 status = MLX_INVALID_PARAMETER;
00178                 goto invalid_parm;
00179         }
00180         status = nodnic_cmd_read(device_priv,
00181                         port_priv->port_offset + data_entry->offset, &buffer);
00182         MLX_FATAL_CHECK_STATUS(status, read_err,
00183                         "nodnic_cmd_read failed");
00184         buffer = buffer & ~(data_entry->mask << data_entry->align);
00185         buffer = buffer | (in << data_entry->align);
00186         status = nodnic_cmd_write(device_priv,
00187                         port_priv->port_offset + data_entry->offset, buffer);
00188         MLX_FATAL_CHECK_STATUS(status, write_err,
00189                         "nodnic_cmd_write failed");
00190 write_err:
00191 read_err:
00192 invalid_parm:
00193         return status;
00194 }
00195 
00196 mlx_status
00197 nodnic_port_set_send_uar_offset(
00198                 IN  nodnic_port_priv    *port_priv
00199                 )
00200 {
00201         mlx_status status = MLX_SUCCESS;
00202         mlx_uint32 out = 0;
00203 
00204         if  ( ! port_priv->device->device_cap.support_uar_tx_db ) {
00205                 MLX_DEBUG_INFO1 ( port_priv, "nodnic_port_set_send_uar_offset: tx db using uar is not supported \n");
00206                 status = MLX_UNSUPPORTED;
00207                 goto uar_not_supported;
00208    }
00209 
00210         status = nodnic_port_query(port_priv,
00211                         nodnic_port_option_send_ring0_uar_index, &out);
00212         MLX_CHECK_STATUS(port_priv->device, status, query_err,
00213                         "nodnic_port_query failed");
00214         port_priv->device->uar.offset = out << port_priv->device->device_cap.log_uar_page_size;
00215 uar_not_supported:
00216 query_err:
00217         return status;
00218 }
00219 
00220 mlx_status
00221 nodnic_port_read_reset_needed(
00222                                                 IN nodnic_port_priv             *port_priv,
00223                                                 OUT mlx_boolean                 *reset_needed
00224                                                 )
00225 {
00226         mlx_status status = MLX_SUCCESS;
00227         mlx_uint32 out = 0;
00228         status = nodnic_port_query(port_priv,
00229                         nodnic_port_option_reset_needed, &out);
00230         MLX_CHECK_STATUS(port_priv->device, status, query_err,
00231                         "nodnic_port_query failed");
00232         *reset_needed = (mlx_boolean)out;
00233 query_err:
00234         return status;
00235 }
00236 
00237 mlx_status
00238 nodnic_port_read_port_management_change_event(
00239                                                 IN nodnic_port_priv             *port_priv,
00240                                                 OUT mlx_boolean                 *change_event
00241                                                 )
00242 {
00243         mlx_status status = MLX_SUCCESS;
00244         mlx_uint32 out = 0;
00245         status = nodnic_port_query(port_priv,
00246                         nodnic_port_option_port_management_change_event, &out);
00247         MLX_CHECK_STATUS(port_priv->device, status, query_err,
00248                         "nodnic_port_query failed");
00249         *change_event = (mlx_boolean)out;
00250 query_err:
00251         return status;
00252 }
00253 
00254 static
00255 mlx_status
00256 nodnic_port_allocate_dbr_dma (
00257                 IN nodnic_port_priv     *port_priv,
00258                 IN struct nodnic_doorbell       *nodnic_db,
00259                 IN mlx_uint32   dbr_addr_low_ofst,
00260                 IN mlx_uint32   dbr_addr_high_ofst,
00261                 IN void **dbr_addr,
00262                 IN mlx_size     size,
00263                 IN void **map
00264                 )
00265 {
00266         mlx_status status = MLX_SUCCESS;
00267         mlx_uint64 address = 0;
00268         nodnic_device_priv *device_priv = NULL;
00269 
00270         if( port_priv == NULL || nodnic_db == NULL ){
00271                         status = MLX_INVALID_PARAMETER;
00272                         goto invalid_parm;
00273         }
00274 
00275         device_priv = port_priv->device;
00276         status = mlx_memory_alloc_dma(device_priv->utils,
00277                                         size,
00278                                         NODNIC_MEMORY_ALIGN,
00279                                         (void **)dbr_addr
00280                                         );
00281         MLX_FATAL_CHECK_STATUS(status, alloc_db_record_err,
00282                                 "doorbell record dma allocation error");
00283 
00284         status = mlx_memory_map_dma(device_priv->utils,
00285                                         (void *)(*dbr_addr),
00286                                         size,
00287                                         &nodnic_db->doorbell_physical,
00288                                         map//nodnic_ring->map
00289                                         );
00290         MLX_FATAL_CHECK_STATUS(status, map_db_record_err,
00291                                 "doorbell record map dma error");
00292 
00293         address = (mlx_uint64)nodnic_db->doorbell_physical;
00294         status = nodnic_cmd_write(device_priv,
00295                                 dbr_addr_low_ofst,
00296                                 (mlx_uint32)address);
00297         MLX_FATAL_CHECK_STATUS(status, set_err,
00298                         "failed to set doorbell addr low");
00299 
00300         address = address >> 32;
00301         status = nodnic_cmd_write(device_priv,
00302                                 dbr_addr_high_ofst,
00303                                 (mlx_uint32)address);
00304         MLX_FATAL_CHECK_STATUS(status, set_err,
00305                         "failed to set doorbell addr high");
00306 
00307         return status;
00308 
00309 set_err:
00310         mlx_memory_ummap_dma(device_priv->utils, *map);
00311 map_db_record_err:
00312         mlx_memory_free_dma(device_priv->utils, size,
00313                 (void **)dbr_addr);
00314 alloc_db_record_err:
00315 invalid_parm:
00316         return status;
00317 }
00318 
00319 static
00320 mlx_status
00321 nodnic_port_cq_dbr_dma_init(
00322                 IN nodnic_port_priv     *port_priv,
00323                 OUT nodnic_cq   **cq
00324                 )
00325 {
00326         mlx_status status = MLX_SUCCESS;
00327         nodnic_device_priv *device_priv = NULL;
00328 
00329         if( port_priv == NULL ){
00330                 status = MLX_INVALID_PARAMETER;
00331                 goto invalid_parm;
00332         }
00333 
00334         device_priv =  port_priv->device;
00335         if ( ! device_priv->device_cap.support_bar_cq_ctrl ) {
00336                 status = MLX_UNSUPPORTED;
00337                 goto uar_arm_cq_db_unsupported;
00338         }
00339 
00340 #define NODNIC_PORT_ARM_CQ_DBR_ADDR_LOW_OFFSET 0x114
00341 #define NODNIC_PORT_ARM_CQ_DBR_ADDR_HIGH_OFFSET 0x110
00342 
00343         status = nodnic_port_allocate_dbr_dma ( port_priv,&(*cq)->arm_cq_doorbell,
00344                         port_priv->port_offset + NODNIC_PORT_ARM_CQ_DBR_ADDR_LOW_OFFSET,
00345                         port_priv->port_offset + NODNIC_PORT_ARM_CQ_DBR_ADDR_HIGH_OFFSET,
00346                         (void **)&port_priv->arm_cq_doorbell_record ,
00347                         sizeof(nodnic_arm_cq_db),
00348                         (void **)&((*cq)->arm_cq_doorbell.map));
00349         MLX_FATAL_CHECK_STATUS(status, alloc_dbr_dma_err,
00350                                 "failed to allocate doorbell record dma");
00351         return status;
00352 
00353 alloc_dbr_dma_err:
00354 uar_arm_cq_db_unsupported:
00355 invalid_parm:
00356         return status;
00357 }
00358 
00359 mlx_status
00360 nodnic_port_create_cq(
00361                                         IN nodnic_port_priv     *port_priv,
00362                                         IN mlx_size     cq_size,
00363                                         OUT nodnic_cq   **cq
00364                                         )
00365 {
00366         mlx_status status = MLX_SUCCESS;
00367         nodnic_device_priv *device_priv = NULL;
00368         mlx_uint64 address = 0;
00369         if( port_priv == NULL || cq == NULL){
00370                 status = MLX_INVALID_PARAMETER;
00371                 goto invalid_parm;
00372         }
00373 
00374         device_priv =  port_priv->device;
00375 
00376         status = mlx_memory_zalloc(device_priv->utils,
00377                                 sizeof(nodnic_cq),(mlx_void **)cq);
00378         MLX_FATAL_CHECK_STATUS(status, alloc_err,
00379                         "cq priv allocation error");
00380 
00381         (*cq)->cq_size = cq_size;
00382         status = mlx_memory_alloc_dma(device_priv->utils,
00383                         (*cq)->cq_size, NODNIC_MEMORY_ALIGN,
00384                                 &(*cq)->cq_virt);
00385         MLX_FATAL_CHECK_STATUS(status, dma_alloc_err,
00386                                 "cq allocation error");
00387 
00388         status = mlx_memory_map_dma(device_priv->utils,
00389                                                 (*cq)->cq_virt,
00390                                                 (*cq)->cq_size,
00391                                                 &(*cq)->cq_physical,
00392                                                 &(*cq)->map);
00393         MLX_FATAL_CHECK_STATUS(status, cq_map_err,
00394                                 "cq map error");
00395 
00396         status = nodnic_port_cq_dbr_dma_init(port_priv,cq);
00397 
00398         /* update cq address */
00399 #define NODIC_CQ_ADDR_HIGH 0x68
00400 #define NODIC_CQ_ADDR_LOW 0x6c
00401         address = (mlx_uint64)(*cq)->cq_physical;
00402         status = nodnic_port_set(port_priv, nodnic_port_option_cq_addr_low,
00403                         (mlx_uint32)(address) >> 12);
00404         MLX_FATAL_CHECK_STATUS(status, dma_set_addr_low_err,
00405                                         "cq set addr low error");
00406         address = address >> 32;
00407         status = nodnic_port_set(port_priv, nodnic_port_option_cq_addr_high,
00408                                 (mlx_uint32)address);
00409         MLX_FATAL_CHECK_STATUS(status, dma_set_addr_high_err,
00410                                                 "cq set addr high error");
00411         return status;
00412 dma_set_addr_high_err:
00413 dma_set_addr_low_err:
00414         mlx_memory_ummap_dma(device_priv->utils, (*cq)->map);
00415 cq_map_err:
00416         mlx_memory_free_dma(device_priv->utils, (*cq)->cq_size,
00417                         (void **)&((*cq)->cq_virt));
00418 dma_alloc_err:
00419         mlx_memory_free(device_priv->utils, (void **)cq);
00420 alloc_err:
00421 invalid_parm:
00422         return status;
00423 }
00424 
00425 mlx_status
00426 nodnic_port_destroy_cq(
00427                                         IN nodnic_port_priv     *port_priv,
00428                                         IN nodnic_cq    *cq
00429                                         )
00430 {
00431         mlx_status status = MLX_SUCCESS;
00432         nodnic_device_priv *device_priv = NULL;
00433 
00434         if( port_priv == NULL || cq == NULL){
00435                 status = MLX_INVALID_PARAMETER;
00436                 goto invalid_parm;
00437         }
00438         device_priv =  port_priv->device;
00439 
00440         if ( device_priv->device_cap.support_bar_cq_ctrl ){
00441                         status = mlx_memory_ummap_dma(device_priv->utils,
00442                                         cq->arm_cq_doorbell.map);
00443                         if( status != MLX_SUCCESS){
00444                                 MLX_DEBUG_ERROR(device_priv, "mlx_memory_ummap_dma failed (Status = %d)\n", status);
00445                         }
00446 
00447                         status = mlx_memory_free_dma(device_priv->utils,
00448                                         sizeof(nodnic_arm_cq_db),
00449                                         (void **)&(port_priv->arm_cq_doorbell_record));
00450                         if( status != MLX_SUCCESS){
00451                                 MLX_DEBUG_ERROR(device_priv, "mlx_memory_free_dma failed (Status = %d)\n", status);
00452                         }
00453                 }
00454 
00455         mlx_memory_ummap_dma(device_priv->utils, cq->map);
00456 
00457         mlx_memory_free_dma(device_priv->utils, cq->cq_size,
00458                         (void **)&(cq->cq_virt));
00459 
00460         mlx_memory_free(device_priv->utils, (void **)&cq);
00461 invalid_parm:
00462         return status;
00463 }
00464 
00465 static
00466 mlx_status
00467 nodnic_port_allocate_ring_db_dma (
00468                 IN nodnic_port_priv     *port_priv,
00469                 IN struct nodnic_ring *nodnic_ring,
00470                 IN struct nodnic_doorbell *nodnic_db
00471                 )
00472 {
00473         mlx_status status = MLX_SUCCESS;
00474 
00475         if( port_priv == NULL || nodnic_ring == NULL || nodnic_db == NULL ){
00476                         status = MLX_INVALID_PARAMETER;
00477                         goto invalid_parm;
00478         }
00479 #define NODNIC_RING_DBR_ADDR_LOW_OFFSET 0x1C
00480 #define NODNIC_RING_DBR_ADDR_HIGH_OFFSET 0x18
00481         status = nodnic_port_allocate_dbr_dma ( port_priv,nodnic_db,
00482                         nodnic_ring->offset + NODNIC_RING_DBR_ADDR_LOW_OFFSET,
00483                         nodnic_ring->offset + NODNIC_RING_DBR_ADDR_HIGH_OFFSET,
00484                         (void **)&nodnic_db->qp_doorbell_record,
00485                         sizeof(nodnic_qp_db),
00486                         (void **)&nodnic_ring->map );
00487         MLX_FATAL_CHECK_STATUS(status, alloc_dbr_dma_err,
00488                         "failed to allocate doorbell record dma");
00489 
00490         return status;
00491 alloc_dbr_dma_err:
00492 invalid_parm:
00493         return status;
00494 }
00495 
00496 static
00497 mlx_status
00498 nodnic_port_rx_pi_dma_alloc(
00499                 IN nodnic_port_priv     *port_priv,
00500                 OUT nodnic_qp   **qp
00501                 )
00502 {
00503         mlx_status status = MLX_SUCCESS;
00504         nodnic_device_priv *device_priv = NULL;
00505 
00506         if( port_priv == NULL || qp == NULL){
00507                 status = MLX_INVALID_PARAMETER;
00508                 goto invalid_parm;
00509         }
00510 
00511         device_priv =  port_priv->device;
00512 
00513         if ( ! device_priv->device_cap.support_rx_pi_dma ) {
00514                 goto rx_pi_dma_unsupported;
00515         }
00516 
00517         if ( device_priv->device_cap.support_rx_pi_dma ) {
00518                 status = nodnic_port_allocate_ring_db_dma(port_priv,
00519                                 &(*qp)->receive.nodnic_ring,&(*qp)->receive.nodnic_ring.recv_doorbell);
00520                 MLX_FATAL_CHECK_STATUS(status, dma_alloc_err,
00521                                 "rx doorbell dma allocation error");
00522         }
00523 
00524         return status;
00525 
00526 dma_alloc_err:
00527 rx_pi_dma_unsupported:
00528 invalid_parm:
00529         return status;
00530 }
00531 
00532 static
00533 mlx_status
00534 nodnic_port_send_db_dma(
00535                 IN nodnic_port_priv     *port_priv,
00536                 IN struct nodnic_ring *ring,
00537                 IN mlx_uint16 index
00538                 )
00539 {
00540         mlx_uint32 swapped = 0;
00541         mlx_uint32 index32 = index;
00542         mlx_memory_cpu_to_be32(port_priv->device->utils, index32, &swapped);
00543         ring->send_doorbell.qp_doorbell_record->send_db =  swapped;
00544 
00545         return MLX_SUCCESS;
00546 }
00547 
00548 static
00549 mlx_status
00550 nodnic_port_tx_dbr_dma_init(
00551                 IN nodnic_port_priv     *port_priv,
00552                 OUT nodnic_qp   **qp
00553                 )
00554 {
00555         mlx_status status = MLX_SUCCESS;
00556         nodnic_device_priv *device_priv = NULL;
00557 
00558         if( port_priv == NULL || qp == NULL){
00559                 status = MLX_INVALID_PARAMETER;
00560                 goto invalid_parm;
00561         }
00562 
00563         device_priv =  port_priv->device;
00564 
00565         if ( ! device_priv->device_cap.support_uar_tx_db || ! device_priv->uar.offset ) {
00566                 status = MLX_UNSUPPORTED;
00567                 goto uar_tx_db_unsupported;
00568         }
00569         status = nodnic_port_allocate_ring_db_dma(port_priv,
00570                         &(*qp)->send.nodnic_ring,&(*qp)->send.nodnic_ring.send_doorbell);
00571         MLX_FATAL_CHECK_STATUS(status, dma_alloc_err,
00572                         "tx doorbell dma allocation error");
00573         port_priv->send_doorbell = nodnic_port_send_db_dma;
00574 
00575         return status;
00576 
00577 dma_alloc_err:
00578 uar_tx_db_unsupported:
00579 invalid_parm:
00580 
00581         return status;
00582 }
00583 
00584 mlx_status
00585 nodnic_port_create_qp(
00586                                         IN nodnic_port_priv     *port_priv,
00587                                         IN nodnic_queue_pair_type       type,
00588                                         IN mlx_size     send_wq_size,
00589                                         IN mlx_uint32 send_wqe_num,
00590                                         IN mlx_size     receive_wq_size,
00591                                         IN mlx_uint32 recv_wqe_num,
00592                                         OUT nodnic_qp   **qp
00593                                         )
00594 {
00595         mlx_status status = MLX_SUCCESS;
00596         nodnic_device_priv *device_priv = NULL;
00597         mlx_uint32 max_ring_size = 0;
00598         mlx_uint64 address = 0;
00599         mlx_uint32 log_size = 0;
00600         if( port_priv == NULL || qp == NULL){
00601                 status = MLX_INVALID_PARAMETER;
00602                 goto invalid_parm;
00603         }
00604 
00605         device_priv =  port_priv->device;
00606         max_ring_size = (1 << device_priv->device_cap.log_max_ring_size);
00607         if( send_wq_size > max_ring_size ||
00608                         receive_wq_size > max_ring_size ){
00609                 status = MLX_INVALID_PARAMETER;
00610                 goto invalid_parm;
00611         }
00612 
00613         status = mlx_memory_zalloc(device_priv->utils,
00614                         sizeof(nodnic_qp),(mlx_void **)qp);
00615         MLX_FATAL_CHECK_STATUS(status, alloc_err,
00616                         "qp allocation error");
00617 
00618         if( nodnic_qp_data_teable[type].send_offset == 0 ||
00619                         nodnic_qp_data_teable[type].recv_offset == 0){
00620                 status = MLX_INVALID_PARAMETER;
00621                 goto invalid_type;
00622         }
00623 
00624         (*qp)->send.nodnic_ring.offset = port_priv->port_offset +
00625                                 nodnic_qp_data_teable[type].send_offset;
00626         (*qp)->receive.nodnic_ring.offset = port_priv->port_offset +
00627                         nodnic_qp_data_teable[type].recv_offset;
00628 
00629         status = mlx_memory_alloc_dma(device_priv->utils,
00630                         send_wq_size, NODNIC_MEMORY_ALIGN,
00631                         (void*)&(*qp)->send.wqe_virt);
00632         MLX_FATAL_CHECK_STATUS(status, send_alloc_err,
00633                                 "send wq allocation error");
00634 
00635         status = mlx_memory_alloc_dma(device_priv->utils,
00636                                 receive_wq_size, NODNIC_MEMORY_ALIGN,
00637                                 &(*qp)->receive.wqe_virt);
00638         MLX_FATAL_CHECK_STATUS(status, receive_alloc_err,
00639                                 "receive wq allocation error");
00640 
00641         status = mlx_memory_map_dma(device_priv->utils,
00642                                                 (*qp)->send.wqe_virt,
00643                                                 send_wq_size,
00644                                                 &(*qp)->send.nodnic_ring.wqe_physical,
00645                                                 &(*qp)->send.nodnic_ring.map);
00646         MLX_FATAL_CHECK_STATUS(status, send_map_err,
00647                                 "send wq map error");
00648 
00649         status = mlx_memory_map_dma(device_priv->utils,
00650                                                 (*qp)->receive.wqe_virt,
00651                                                 receive_wq_size,
00652                                                 &(*qp)->receive.nodnic_ring.wqe_physical,
00653                                                 &(*qp)->receive.nodnic_ring.map);
00654         MLX_FATAL_CHECK_STATUS(status, receive_map_err,
00655                                 "receive wq map error");
00656 
00657         status = nodnic_port_rx_pi_dma_alloc(port_priv,qp);
00658         MLX_FATAL_CHECK_STATUS(status, rx_pi_dma_alloc_err,
00659                                 "receive db dma error");
00660 
00661         status = nodnic_port_tx_dbr_dma_init(port_priv,qp);
00662 
00663 
00664         (*qp)->send.nodnic_ring.wq_size = send_wq_size;
00665         (*qp)->send.nodnic_ring.num_wqes = send_wqe_num;
00666         (*qp)->receive.nodnic_ring.wq_size = receive_wq_size;
00667         (*qp)->receive.nodnic_ring.num_wqes = recv_wqe_num;
00668 
00669         /* Set Ownership bit in Send/receive queue (0 - recv ; 1 - send) */
00670         mlx_memory_set(device_priv->utils, (*qp)->send.wqe_virt, 0xff, send_wq_size );
00671         mlx_memory_set(device_priv->utils, (*qp)->receive.wqe_virt, 0, recv_wqe_num );
00672 
00673         /* update send ring */
00674 #define NODIC_RING_QP_ADDR_HIGH 0x0
00675 #define NODIC_RING_QP_ADDR_LOW 0x4
00676         address = (mlx_uint64)(*qp)->send.nodnic_ring.wqe_physical;
00677         status = nodnic_cmd_write(device_priv, (*qp)->send.nodnic_ring.offset +
00678                         NODIC_RING_QP_ADDR_HIGH,
00679                         (mlx_uint32)(address >> 32));
00680         MLX_FATAL_CHECK_STATUS(status, write_send_addr_err,
00681                                         "send address write error 1");
00682         mlx_utils_ilog2((*qp)->send.nodnic_ring.wq_size, &log_size);
00683         address = address | log_size;
00684         status = nodnic_cmd_write(device_priv, (*qp)->send.nodnic_ring.offset +
00685                         NODIC_RING_QP_ADDR_LOW,
00686                                 (mlx_uint32)address);
00687         MLX_FATAL_CHECK_STATUS(status, write_send_addr_err,
00688                                                 "send address write error 2");
00689         /* update receive ring */
00690         address = (mlx_uint64)(*qp)->receive.nodnic_ring.wqe_physical;
00691         status = nodnic_cmd_write(device_priv, (*qp)->receive.nodnic_ring.offset +
00692                         NODIC_RING_QP_ADDR_HIGH,
00693                         (mlx_uint32)(address >> 32));
00694         MLX_FATAL_CHECK_STATUS(status, write_recv_addr_err,
00695                                                 "receive address write error 1");
00696         mlx_utils_ilog2((*qp)->receive.nodnic_ring.wq_size, &log_size);
00697         address = address | log_size;
00698         status = nodnic_cmd_write(device_priv, (*qp)->receive.nodnic_ring.offset +
00699                         NODIC_RING_QP_ADDR_LOW,
00700                                 (mlx_uint32)address);
00701         MLX_FATAL_CHECK_STATUS(status, write_recv_addr_err,
00702                                                 "receive address write error 2");
00703 
00704         return status;
00705 write_recv_addr_err:
00706 write_send_addr_err:
00707         mlx_memory_ummap_dma(device_priv->utils, (*qp)->receive.nodnic_ring.map);
00708 rx_pi_dma_alloc_err:
00709 receive_map_err:
00710         mlx_memory_ummap_dma(device_priv->utils, (*qp)->send.nodnic_ring.map);
00711 send_map_err:
00712         mlx_memory_free_dma(device_priv->utils, receive_wq_size,
00713                         &((*qp)->receive.wqe_virt));
00714 receive_alloc_err:
00715         mlx_memory_free_dma(device_priv->utils, send_wq_size,
00716                         (void **)&((*qp)->send.wqe_virt));
00717 send_alloc_err:
00718 invalid_type:
00719         mlx_memory_free(device_priv->utils, (void **)qp);
00720 alloc_err:
00721 invalid_parm:
00722         return status;
00723 }
00724 
00725 mlx_status
00726 nodnic_port_destroy_qp(
00727                                         IN nodnic_port_priv     *port_priv,
00728                                         IN nodnic_queue_pair_type       type __attribute__((unused)),
00729                                         IN nodnic_qp    *qp
00730                                         )
00731 {
00732         mlx_status status = MLX_SUCCESS;
00733         nodnic_device_priv *device_priv = port_priv->device;
00734 
00735         status = mlx_memory_ummap_dma(device_priv->utils,
00736                         qp->receive.nodnic_ring.map);
00737         if( status != MLX_SUCCESS){
00738                 MLX_DEBUG_ERROR(device_priv, "mlx_memory_ummap_dma failed (Status = %d)\n", status);
00739         }
00740 
00741         status = mlx_memory_ummap_dma(device_priv->utils, qp->send.nodnic_ring.map);
00742         if( status != MLX_SUCCESS){
00743                 MLX_DEBUG_ERROR(device_priv, "mlx_memory_ummap_dma failed (Status = %d)\n", status);
00744         }
00745 
00746         if ( device_priv->device_cap.support_rx_pi_dma ){
00747                 status = mlx_memory_ummap_dma(device_priv->utils,
00748                                         qp->receive.nodnic_ring.recv_doorbell.map);
00749                 if( status != MLX_SUCCESS){
00750                         MLX_DEBUG_ERROR(device_priv, "mlx_memory_ummap_dma failed (Status = %d)\n", status);
00751                 }
00752 
00753                 status = mlx_memory_free_dma(device_priv->utils,
00754                                 sizeof(nodnic_qp_db),
00755                                 (void **)&(qp->receive.nodnic_ring.recv_doorbell.qp_doorbell_record));
00756                 if( status != MLX_SUCCESS){
00757                         MLX_DEBUG_ERROR(device_priv, "mlx_memory_free_dma failed (Status = %d)\n", status);
00758                 }
00759         }
00760 
00761         if ( device_priv->device_cap.support_uar_tx_db || ! device_priv->uar.offset){
00762                 status = mlx_memory_ummap_dma(device_priv->utils,
00763                                         qp->send.nodnic_ring.send_doorbell.map);
00764                 if( status != MLX_SUCCESS){
00765                         MLX_DEBUG_ERROR(device_priv, "mlx_memory_ummap_dma failed (Status = %d)\n", status);
00766                 }
00767 
00768                 status = mlx_memory_free_dma(device_priv->utils,
00769                                 sizeof(nodnic_qp_db),
00770                                 (void **)&(qp->send.nodnic_ring.send_doorbell.qp_doorbell_record));
00771                 if( status != MLX_SUCCESS){
00772                         MLX_DEBUG_ERROR(device_priv, "mlx_memory_free_dma failed (Status = %d)\n", status);
00773                 }
00774         }
00775 
00776         status = mlx_memory_free_dma(device_priv->utils,
00777                         qp->receive.nodnic_ring.wq_size,
00778                         (void **)&(qp->receive.wqe_virt));
00779         if( status != MLX_SUCCESS){
00780                 MLX_DEBUG_ERROR(device_priv, "mlx_memory_free_dma failed (Status = %d)\n", status);
00781         }
00782         status = mlx_memory_free_dma(device_priv->utils,
00783                         qp->send.nodnic_ring.wq_size,
00784                         (void **)&(qp->send.wqe_virt));
00785         if( status != MLX_SUCCESS){
00786                 MLX_DEBUG_ERROR(device_priv, "mlx_memory_free_dma failed (Status = %d)\n", status);
00787         }
00788         status = mlx_memory_free(device_priv->utils, (void **)&qp);
00789         if( status != MLX_SUCCESS){
00790                 MLX_DEBUG_ERROR(device_priv, "mlx_memory_free failed (Status = %d)\n", status);
00791         }
00792         return status;
00793 }
00794 
00795 mlx_status
00796 nodnic_port_get_qpn(
00797                         IN nodnic_port_priv     *port_priv,
00798                         IN struct nodnic_ring  *ring,
00799                         OUT mlx_uint32 *qpn
00800                         )
00801 {
00802         mlx_status status = MLX_SUCCESS;
00803         mlx_uint32 buffer = 0;
00804         if( ring == NULL || qpn == NULL){
00805                 status = MLX_INVALID_PARAMETER;
00806                 goto bad_param;
00807         }
00808         if( ring->qpn != 0 ){
00809                 *qpn = ring->qpn;
00810                 goto success;
00811         }
00812 #define NODNIC_RING_QPN_OFFSET 0xc
00813 #define NODNIC_RING_QPN_MASK 0xFFFFFF
00814         status = nodnic_cmd_read(port_priv->device,
00815                         ring->offset + NODNIC_RING_QPN_OFFSET,
00816                         &buffer);
00817         MLX_FATAL_CHECK_STATUS(status, read_err,
00818                         "nodnic_cmd_read failed");
00819         ring->qpn = buffer & NODNIC_RING_QPN_MASK;
00820         *qpn = ring->qpn;
00821 read_err:
00822 success:
00823 bad_param:
00824         return status;
00825 }
00826 
00827 #ifdef DEVICE_CX3
00828 static
00829 mlx_status
00830 nodnic_port_send_db_connectx3(
00831                 IN nodnic_port_priv     *port_priv,
00832                 IN struct nodnic_ring *ring __attribute__((unused)),
00833                 IN mlx_uint16 index
00834                 )
00835 {
00836         nodnic_port_data_flow_gw *ptr = port_priv->data_flow_gw;
00837         mlx_uint32 index32 = index;
00838         mlx_pci_mem_write(port_priv->device->utils, MlxPciWidthUint32, 0,
00839                         (mlx_uintn)&(ptr->send_doorbell), 1, &index32);
00840         return MLX_SUCCESS;
00841 }
00842 
00843 static
00844 mlx_status
00845 nodnic_port_recv_db_connectx3(
00846                 IN nodnic_port_priv     *port_priv,
00847                 IN struct nodnic_ring *ring __attribute__((unused)),
00848                 IN mlx_uint16 index
00849                 )
00850 {
00851         nodnic_port_data_flow_gw *ptr = port_priv->data_flow_gw;
00852         mlx_uint32 index32 = index;
00853         mlx_pci_mem_write(port_priv->device->utils, MlxPciWidthUint32, 0,
00854                         (mlx_uintn)&(ptr->recv_doorbell), 1, &index32);
00855         return MLX_SUCCESS;
00856 }
00857 #endif
00858 static
00859 mlx_status
00860 nodnic_port_recv_db_dma(
00861                 IN nodnic_port_priv     *port_priv __attribute__((unused)),
00862                 IN struct nodnic_ring *ring,
00863                 IN mlx_uint16 index
00864                 )
00865 {
00866         mlx_uint32 swapped = 0;
00867         mlx_uint32 index32 = index;
00868         mlx_memory_cpu_to_be32(port_priv->device->utils, index32, &swapped);
00869         ring->recv_doorbell.qp_doorbell_record->recv_db =  swapped;
00870         return MLX_SUCCESS;
00871 }
00872 
00873 mlx_status
00874 nodnic_port_update_ring_doorbell(
00875                                         IN nodnic_port_priv     *port_priv,
00876                                         IN struct nodnic_ring *ring,
00877                                         IN mlx_uint16 index
00878                                         )
00879 {
00880         mlx_status status = MLX_SUCCESS;
00881         mlx_uint32 buffer = 0;
00882         if( ring == NULL ){
00883                 status = MLX_INVALID_PARAMETER;
00884                 goto bad_param;
00885         }
00886 #define NODNIC_RING_RING_OFFSET 0x8
00887         buffer = (mlx_uint32)((index & 0xFFFF)<< 8);
00888         status = nodnic_cmd_write(port_priv->device,
00889                                 ring->offset + NODNIC_RING_RING_OFFSET,
00890                                 buffer);
00891         MLX_CHECK_STATUS(port_priv->device, status, write_err,
00892                                 "nodnic_cmd_write failed");
00893 write_err:
00894 bad_param:
00895         return status;
00896 }
00897 
00898 mlx_status
00899 nodnic_port_get_cq_size(
00900                 IN nodnic_port_priv     *port_priv,
00901                 OUT mlx_uint64 *cq_size
00902                 )
00903 {
00904         mlx_status status = MLX_SUCCESS;
00905         mlx_uint32 out = 0;
00906         status = nodnic_port_query(port_priv, nodnic_port_option_log_cq_size, &out);
00907         MLX_FATAL_CHECK_STATUS(status, query_err,
00908                         "nodnic_port_query failed");
00909         *cq_size = 1 << out;
00910 query_err:
00911         return status;
00912 }
00913 
00914 mlx_status
00915 nodnic_port_allocate_eq(
00916                                         IN  nodnic_port_priv    *port_priv,
00917                                         IN  mlx_uint8                   log_eq_size
00918                                         )
00919 {
00920         mlx_status status = MLX_SUCCESS;
00921         nodnic_device_priv *device_priv = NULL;
00922         mlx_uint64 address = 0;
00923 
00924         if( port_priv == NULL ){
00925                 status = MLX_INVALID_PARAMETER;
00926                 goto bad_param;
00927         }
00928 
00929         device_priv = port_priv->device;
00930         port_priv->eq.eq_size = ( ( 1 << log_eq_size ) * 1024 ); /* Size is in KB */
00931         status = mlx_memory_alloc_dma(device_priv->utils,
00932                                                                 port_priv->eq.eq_size,
00933                                                                 NODNIC_MEMORY_ALIGN,
00934                                                                 &port_priv->eq.eq_virt);
00935         MLX_FATAL_CHECK_STATUS(status, alloc_err,
00936                                                         "eq allocation error");
00937 
00938         status = mlx_memory_map_dma(device_priv->utils,
00939                                                         port_priv->eq.eq_virt,
00940                                                         port_priv->eq.eq_size,
00941                                                         &port_priv->eq.eq_physical,
00942                                                         &port_priv->eq.map);
00943         MLX_FATAL_CHECK_STATUS(status, map_err,
00944                                                                 "eq map error");
00945 
00946         address = port_priv->eq.eq_physical;
00947         status = nodnic_port_set(port_priv, nodnic_port_option_eq_addr_low,
00948                                                 (mlx_uint32)address);
00949         MLX_FATAL_CHECK_STATUS(status, set_err,
00950                         "failed to set eq addr low");
00951         address = (address >> 32);
00952         status = nodnic_port_set(port_priv, nodnic_port_option_eq_addr_high,
00953                                                 (mlx_uint32)address);
00954         MLX_FATAL_CHECK_STATUS(status, set_err,
00955                                 "failed to set eq addr high");
00956         return status;
00957 set_err:
00958         mlx_memory_ummap_dma(device_priv->utils, port_priv->eq.map);
00959 map_err:
00960         mlx_memory_free_dma(device_priv->utils,
00961                         port_priv->eq.eq_size,
00962                         (void **)&(port_priv->eq.eq_virt));
00963 alloc_err:
00964 bad_param:
00965         return status;
00966 }
00967 mlx_status
00968 nodnic_port_free_eq(
00969                                         IN  nodnic_port_priv    *port_priv
00970                                         )
00971 {
00972         mlx_status status = MLX_SUCCESS;
00973         nodnic_device_priv *device_priv = NULL;
00974 
00975         if( port_priv == NULL ){
00976                 status = MLX_INVALID_PARAMETER;
00977                 goto bad_param;
00978         }
00979 
00980         device_priv = port_priv->device;
00981         mlx_memory_ummap_dma(device_priv->utils, port_priv->eq.map);
00982 
00983         mlx_memory_free_dma(device_priv->utils,
00984                         port_priv->eq.eq_size,
00985                         (void **)&(port_priv->eq.eq_virt));
00986 
00987 bad_param:
00988         return status;
00989 }
00990 
00991 mlx_status
00992 nodnic_port_add_mac_filter(
00993                                         IN  nodnic_port_priv    *port_priv,
00994                                         IN  mlx_mac_address     mac
00995                                         )
00996 {
00997         mlx_status status = MLX_SUCCESS;
00998         nodnic_device_priv *device= NULL;;
00999         mlx_uint8 index = 0;
01000         mlx_uint32 out = 0;
01001         mlx_uint32 mac_filters_en = 0;
01002         mlx_uint32 address = 0;
01003         mlx_mac_address zero_mac;
01004         mlx_utils *utils = NULL;
01005 
01006         if( port_priv == NULL){
01007                 status = MLX_INVALID_PARAMETER;
01008                 goto bad_param;
01009         }
01010 
01011         device = port_priv->device;
01012         utils = device->utils;
01013 
01014         mlx_memory_set(utils, &zero_mac, 0, sizeof(zero_mac));
01015         /* check if mac already exists */
01016         for( ; index < NODNIC_MAX_MAC_FILTERS ; index ++) {
01017                 mlx_memory_cmp(utils, &port_priv->mac_filters[index], &mac,
01018                                 sizeof(mac), &out);
01019                 if ( out == 0 ){
01020                         status = MLX_FAILED;
01021                         goto already_exists;
01022                 }
01023         }
01024 
01025         /* serch for available mac filter slot */
01026         for (index = 0 ; index < NODNIC_MAX_MAC_FILTERS ; index ++) {
01027                 mlx_memory_cmp(utils, &port_priv->mac_filters[index], &zero_mac,
01028                                 sizeof(zero_mac), &out);
01029                 if ( out == 0 ){
01030                         break;
01031                 }
01032         }
01033         if ( index >= NODNIC_MAX_MAC_FILTERS ){
01034                 status = MLX_FAILED;
01035                 goto mac_list_full;
01036         }
01037 
01038         status = nodnic_port_query(port_priv, nodnic_port_option_mac_filters_en,
01039                         &mac_filters_en);
01040         MLX_CHECK_STATUS(device, status , query_err,
01041                         "nodnic_port_query failed");
01042         if(mac_filters_en & (1 << index)){
01043                 status = MLX_FAILED;
01044                 goto mac_list_full;
01045         }
01046         port_priv->mac_filters[index] = mac;
01047 
01048         // set mac filter
01049         address = port_priv->port_offset + NODNIC_PORT_MAC_FILTERS_OFFSET +
01050                                 (0x8 * index);
01051 
01052         status = nodnic_cmd_write(device, address, mac.high );
01053         MLX_CHECK_STATUS(device, status, write_err,     "set mac high failed");
01054         status = nodnic_cmd_write(device, address + 0x4, mac.low );
01055         MLX_CHECK_STATUS(device, status, write_err, "set mac low failed");
01056 
01057         // enable mac filter
01058         mac_filters_en = mac_filters_en | (1 << index);
01059         status = nodnic_port_set(port_priv, nodnic_port_option_mac_filters_en,
01060                                 mac_filters_en);
01061         MLX_CHECK_STATUS(device, status , set_err,
01062                         "nodnic_port_set failed");
01063 set_err:
01064 write_err:
01065 query_err:
01066 mac_list_full:
01067 already_exists:
01068 bad_param:
01069         return status;
01070 }
01071 
01072 mlx_status
01073 nodnic_port_remove_mac_filter(
01074                                         IN  nodnic_port_priv    *port_priv,
01075                                         IN  mlx_mac_address     mac
01076                                         )
01077 {
01078         mlx_status status = MLX_SUCCESS;
01079         nodnic_device_priv *device= NULL;;
01080         mlx_uint8 index = 0;
01081         mlx_uint32 out = 0;
01082         mlx_uint32 mac_filters_en = 0;
01083         mlx_mac_address zero_mac;
01084         mlx_utils *utils = NULL;
01085 
01086         if( port_priv == NULL){
01087                 status = MLX_INVALID_PARAMETER;
01088                 goto bad_param;
01089         }
01090 
01091         device = port_priv->device;
01092         utils = device->utils;
01093 
01094         mlx_memory_set(utils, &zero_mac, 0, sizeof(zero_mac));
01095         /* serch for mac filter */
01096         for( ; index < NODNIC_MAX_MAC_FILTERS ; index ++) {
01097                 mlx_memory_cmp(utils, &port_priv->mac_filters[index], &mac,
01098                                 sizeof(mac), &out);
01099                 if ( out == 0 ){
01100                         break;
01101                 }
01102         }
01103         if ( index == NODNIC_MAX_MAC_FILTERS ){
01104                 status = MLX_FAILED;
01105                 goto mac_not_found;
01106         }
01107 
01108         status = nodnic_port_query(port_priv, nodnic_port_option_mac_filters_en,
01109                         &mac_filters_en);
01110         MLX_CHECK_STATUS(device, status , query_err,
01111                         "nodnic_port_query failed");
01112         if((mac_filters_en & (1 << index)) == 0){
01113                 status = MLX_FAILED;
01114                 goto mac_not_en;
01115         }
01116         port_priv->mac_filters[index] = zero_mac;
01117 
01118         // disable mac filter
01119         mac_filters_en = mac_filters_en & ~(1 << index);
01120         status = nodnic_port_set(port_priv, nodnic_port_option_mac_filters_en,
01121                                 mac_filters_en);
01122         MLX_CHECK_STATUS(device, status , set_err,
01123                         "nodnic_port_set failed");
01124 set_err:
01125 query_err:
01126 mac_not_en:
01127 mac_not_found:
01128 bad_param:
01129         return status;
01130 }
01131 
01132 static
01133 mlx_status
01134 nodnic_port_set_network(
01135                 IN nodnic_port_priv             *port_priv,
01136                 IN mlx_boolean                  value
01137                 )
01138 {
01139         mlx_status status = MLX_SUCCESS;
01140         /*mlx_uint32 network_valid = 0;
01141         mlx_uint8 try = 0;*/
01142 
01143         status = nodnic_port_set(port_priv, nodnic_port_option_network_en, value);
01144         MLX_CHECK_STATUS(port_priv->device, status, set_err,
01145                         "nodnic_port_set failed");
01146         port_priv->network_state = value;
01147 set_err:
01148         return status;
01149 }
01150 
01151 #ifdef DEVICE_CX3
01152 static
01153 mlx_status
01154 nodnic_port_set_dma_connectx3(
01155                 IN nodnic_port_priv             *port_priv,
01156                 IN mlx_boolean                  value
01157                 )
01158 {
01159         mlx_utils *utils = port_priv->device->utils;
01160         nodnic_port_data_flow_gw *ptr = port_priv->data_flow_gw;
01161         mlx_uint32 data = (value ? 0xffffffff : 0x0);
01162         mlx_pci_mem_write(utils, MlxPciWidthUint32, 0,
01163                         (mlx_uintn)&(ptr->dma_en), 1, &data);
01164         return MLX_SUCCESS;
01165 }
01166 #endif
01167 
01168 static
01169 mlx_status
01170 nodnic_port_set_dma(
01171                 IN nodnic_port_priv             *port_priv,
01172                 IN mlx_boolean                  value
01173                 )
01174 {
01175         return nodnic_port_set(port_priv, nodnic_port_option_dma_en, value);
01176 }
01177 
01178 static
01179 mlx_status
01180 nodnic_port_check_and_set_dma(
01181                 IN nodnic_port_priv             *port_priv,
01182                 IN mlx_boolean                  value
01183                 )
01184 {
01185         mlx_status status = MLX_SUCCESS;
01186         if ( port_priv->dma_state == value ) {
01187                 MLX_DEBUG_WARN(port_priv->device,
01188                                 "nodnic_port_check_and_set_dma: already %s\n",
01189                                 (value ? "enabled" : "disabled"));
01190                 status = MLX_SUCCESS;
01191                 goto set_out;
01192         }
01193 
01194         status = port_priv->set_dma(port_priv, value);
01195         MLX_CHECK_STATUS(port_priv->device, status, set_err,
01196                         "nodnic_port_set failed");
01197         port_priv->dma_state = value;
01198 set_err:
01199 set_out:
01200         return status;
01201 }
01202 
01203 
01204 mlx_status
01205 nodnic_port_set_promisc(
01206                 IN nodnic_port_priv             *port_priv,
01207                 IN mlx_boolean                  value
01208                 ){
01209         mlx_status status = MLX_SUCCESS;
01210         mlx_uint32      buffer = value;
01211 
01212         status = nodnic_port_set(port_priv, nodnic_port_option_port_promisc_en, buffer);
01213         MLX_CHECK_STATUS(port_priv->device, status, set_err,
01214                         "nodnic_port_set failed");
01215 set_err:
01216         return status;
01217 }
01218 
01219 mlx_status
01220 nodnic_port_set_promisc_multicast(
01221                 IN nodnic_port_priv             *port_priv,
01222                 IN mlx_boolean                  value
01223                 ){
01224         mlx_status status = MLX_SUCCESS;
01225         mlx_uint32      buffer = value;
01226 
01227         status = nodnic_port_set(port_priv, nodnic_port_option_port_promisc_multicast_en, buffer);
01228         MLX_CHECK_STATUS(port_priv->device, status, set_err,
01229                         "nodnic_port_set failed");
01230 set_err:
01231         return status;
01232 }
01233 
01234 mlx_status
01235 nodnic_port_init(
01236                 IN nodnic_port_priv             *port_priv
01237                 )
01238 {
01239         mlx_status status = MLX_SUCCESS;
01240 
01241         if( port_priv == NULL ){
01242                 status = MLX_INVALID_PARAMETER;
01243                 goto bad_param;
01244         }
01245 
01246         status = nodnic_port_set_network(port_priv, TRUE);
01247         MLX_FATAL_CHECK_STATUS(status, set_err,
01248                                         "nodnic_port_set_network failed");
01249 set_err:
01250 bad_param:
01251         return status;
01252 }
01253 
01254 mlx_status
01255 nodnic_port_close(
01256                 IN nodnic_port_priv             *port_priv
01257                 )
01258 {
01259         mlx_status status = MLX_SUCCESS;
01260 
01261         if( port_priv == NULL ){
01262                 status = MLX_INVALID_PARAMETER;
01263                 goto bad_param;
01264         }
01265 
01266         status = nodnic_port_set_network(port_priv, FALSE);
01267         MLX_FATAL_CHECK_STATUS(status, set_err,
01268                                         "nodnic_port_set_network failed");
01269 set_err:
01270 bad_param:
01271         return status;
01272 }
01273 
01274 mlx_status
01275 nodnic_port_enable_dma(
01276                 IN nodnic_port_priv             *port_priv
01277                 )
01278 {
01279         mlx_status status = MLX_SUCCESS;
01280 
01281         if( port_priv == NULL ){
01282                 status = MLX_INVALID_PARAMETER;
01283                 goto bad_param;
01284         }
01285 
01286         status = nodnic_port_check_and_set_dma(port_priv, TRUE);
01287         MLX_CHECK_STATUS(port_priv->device, status, set_err,
01288                                         "nodnic_port_check_and_set_dma failed");
01289 set_err:
01290 bad_param:
01291         return status;
01292 }
01293 
01294 mlx_status
01295 nodnic_port_disable_dma(
01296                 IN nodnic_port_priv             *port_priv
01297                 )
01298 {
01299         mlx_status status = MLX_SUCCESS;
01300 
01301         if( port_priv == NULL ){
01302                 status = MLX_INVALID_PARAMETER;
01303                 goto bad_param;
01304         }
01305 
01306         status = nodnic_port_check_and_set_dma(port_priv, FALSE);
01307         MLX_CHECK_STATUS(port_priv->device, status, set_err,
01308                                         "nodnic_port_check_and_set_dma failed");
01309 set_err:
01310 bad_param:
01311         return status;
01312 }
01313 
01314 mlx_status
01315 nodnic_port_thin_init(
01316                 IN nodnic_device_priv   *device_priv,
01317                 IN nodnic_port_priv             *port_priv,
01318                 IN mlx_uint8                    port_index
01319                 )
01320 {
01321         mlx_status status = MLX_SUCCESS;
01322         mlx_boolean     reset_needed = 0;
01323 #ifdef DEVICE_CX3
01324         mlx_uint32 offset;
01325 #endif
01326 
01327         if( device_priv == NULL || port_priv == NULL || port_index > 1){
01328                 status = MLX_INVALID_PARAMETER;
01329                 goto invalid_parm;
01330         }
01331 
01332         port_priv->device = device_priv;
01333 
01334         port_priv->port_offset = device_priv->device_offset +
01335                         nodnic_port_offset_table[port_index];
01336 
01337         port_priv->port_num = port_index + 1;
01338 
01339         port_priv->send_doorbell = nodnic_port_update_ring_doorbell;
01340         port_priv->recv_doorbell = nodnic_port_update_ring_doorbell;
01341         port_priv->set_dma = nodnic_port_set_dma;
01342 #ifdef DEVICE_CX3
01343         if (device_priv->device_cap.crspace_doorbells) {
01344                 status = nodnic_cmd_read(device_priv, (port_priv->port_offset + 0x100),
01345                                 &offset);
01346                 if (status != MLX_SUCCESS) {
01347                         return status;
01348                 } else {
01349                         port_priv->data_flow_gw = (nodnic_port_data_flow_gw *)
01350                                         (device_priv->utils->config + offset);
01351                 }
01352                 if ( nodnic_port_set ( port_priv, nodnic_port_option_crspace_en, 1 ) ) {
01353                         return MLX_FAILED;
01354                 }
01355                 port_priv->send_doorbell = nodnic_port_send_db_connectx3;
01356                 port_priv->recv_doorbell = nodnic_port_recv_db_connectx3;
01357                 port_priv->set_dma = nodnic_port_set_dma_connectx3;
01358         }
01359 #endif
01360         if ( device_priv->device_cap.support_rx_pi_dma ) {
01361                 port_priv->recv_doorbell = nodnic_port_recv_db_dma;
01362         }
01363 
01364         /* clear reset_needed */
01365         nodnic_port_read_reset_needed(port_priv, &reset_needed);
01366 
01367         port_priv->port_type = NODNIC_PORT_TYPE_UNKNOWN;
01368 invalid_parm:
01369         return status;
01370 }