+++ /dev/null
-/*\r
- * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.\r
- * Copyright (c) 2006 Voltaire Corporation. All rights reserved.
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- * $Id$\r
- */\r
-\r
-\r
-/*\r
- * SMP handling of IB Access Layer VPD for Mellanox MT23108 HCA\r
- */\r
-\r
-\r
-#include "hca_driver.h"\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "hca_smp.tmh"\r
-#endif\r
-#include "mthca_dev.h"\r
-#include "ib_mad.h"\r
-\r
-\r
-boolean_t\r
-mlnx_cachable_guid_info(\r
- IN const mlnx_cache_t* const p_cache,\r
- IN const ib_mad_t *p_mad_in,\r
- OUT ib_mad_t *p_mad_out )\r
-{\r
- uint32_t idx;\r
-\r
- /* Get the table selector from the attribute */\r
- idx = cl_ntoh32( p_mad_in->attr_mod );\r
-\r
- /*\r
- * TODO: Setup the response to fail the MAD instead of sending\r
- * it down to the HCA.\r
- */\r
- if( idx > 31 )\r
- return FALSE;\r
-\r
- if( !p_cache->guid_block[idx].valid )\r
- return FALSE;\r
-\r
- /*\r
- * If a SET, see if the set is identical to the cache,\r
- * in which case it's a no-op.\r
- */\r
- if( p_mad_in->method == IB_MAD_METHOD_SET )\r
- {\r
- if( cl_memcmp( ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_in ),\r
- &p_cache->guid_block[idx].tbl, sizeof(ib_guid_info_t) ) )\r
- {\r
- /* The set is requesting a change. */\r
- return FALSE;\r
- }\r
- }\r
-\r
- /* Setup the response mad. */\r
- cl_memcpy( p_mad_out, p_mad_in, MAD_BLOCK_SIZE );\r
- p_mad_out->method = (IB_MAD_METHOD_RESP_MASK | IB_MAD_METHOD_GET);\r
- if( p_mad_out->mgmt_class == IB_MCLASS_SUBN_DIR )\r
- p_mad_out->status = IB_SMP_DIRECTION;\r
- else\r
- p_mad_out->status = 0;\r
-\r
- /* Copy the cached data. */\r
- cl_memcpy( ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_out ),\r
- &p_cache->guid_block[idx].tbl, sizeof(ib_guid_info_t) );\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-boolean_t\r
-mlnx_cachable_pkey_table(\r
- IN const mlnx_cache_t* const p_cache,\r
- IN const ib_mad_t *p_mad_in,\r
- OUT ib_mad_t *p_mad_out )\r
-{\r
- uint16_t idx;\r
-\r
- /* Get the table selector from the attribute */\r
- idx = ((uint16_t)cl_ntoh32( p_mad_in->attr_mod ));\r
-\r
- /*\r
- * TODO: Setup the response to fail the MAD instead of sending\r
- * it down to the HCA.\r
- */\r
- if( idx > 2047 )\r
- return FALSE;\r
-\r
- if( !p_cache->pkey_tbl[idx].valid )\r
- return FALSE;\r
-\r
- /*\r
- * If a SET, see if the set is identical to the cache,\r
- * in which case it's a no-op.\r
- */\r
- if( p_mad_in->method == IB_MAD_METHOD_SET )\r
- {\r
- if( cl_memcmp( ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_in ),\r
- &p_cache->pkey_tbl[idx].tbl, sizeof(ib_pkey_table_info_t) ) )\r
- {\r
- /* The set is requesting a change. */\r
- return FALSE;\r
- }\r
- }\r
-\r
- /* Setup the response mad. */\r
- cl_memcpy( p_mad_out, p_mad_in, MAD_BLOCK_SIZE );\r
- p_mad_out->method = (IB_MAD_METHOD_RESP_MASK | IB_MAD_METHOD_GET);\r
- if( p_mad_out->mgmt_class == IB_MCLASS_SUBN_DIR )\r
- p_mad_out->status = IB_SMP_DIRECTION;\r
- else\r
- p_mad_out->status = 0;\r
-\r
- /* Copy the cached data. */\r
- cl_memcpy( ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_out ),\r
- &p_cache->pkey_tbl[idx].tbl, sizeof(ib_pkey_table_info_t) );\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-boolean_t\r
-mlnx_cachable_sl_vl_table(\r
- IN const mlnx_cache_t* const p_cache,\r
- IN const ib_mad_t *p_mad_in,\r
- OUT ib_mad_t *p_mad_out )\r
-{\r
- if( !p_cache->sl_vl.valid )\r
- return FALSE;\r
-\r
- /*\r
- * If a SET, see if the set is identical to the cache,\r
- * in which case it's a no-op.\r
- */\r
- if( p_mad_in->method == IB_MAD_METHOD_SET )\r
- {\r
- if( cl_memcmp( ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_in ),\r
- &p_cache->sl_vl.tbl, sizeof(ib_slvl_table_t) ) )\r
- {\r
- /* The set is requesting a change. */\r
- return FALSE;\r
- }\r
- }\r
-\r
- /* Setup the response mad. */\r
- cl_memcpy( p_mad_out, p_mad_in, MAD_BLOCK_SIZE );\r
- p_mad_out->method = (IB_MAD_METHOD_RESP_MASK | IB_MAD_METHOD_GET);\r
- if( p_mad_out->mgmt_class == IB_MCLASS_SUBN_DIR )\r
- p_mad_out->status = IB_SMP_DIRECTION;\r
- else\r
- p_mad_out->status = 0;\r
-\r
- /* Copy the cached data. */\r
- cl_memcpy( ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_out ),\r
- &p_cache->sl_vl.tbl, sizeof(ib_slvl_table_t) );\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-boolean_t\r
-mlnx_cachable_vl_arb_table(\r
- IN const mlnx_cache_t* const p_cache,\r
- IN const ib_mad_t *p_mad_in,\r
- OUT ib_mad_t *p_mad_out )\r
-{\r
- uint16_t idx;\r
-\r
- /* Get the table selector from the attribute */\r
- idx = ((uint16_t)(cl_ntoh32( p_mad_in->attr_mod ) >> 16)) - 1;\r
-\r
- /*\r
- * TODO: Setup the response to fail the MAD instead of sending\r
- * it down to the HCA.\r
- */\r
- if( idx > 3 )\r
- return FALSE;\r
-\r
- if( !p_cache->vl_arb[idx].valid )\r
- return FALSE;\r
-\r
- /*\r
- * If a SET, see if the set is identical to the cache,\r
- * in which case it's a no-op.\r
- */\r
- if( p_mad_in->method == IB_MAD_METHOD_SET )\r
- {\r
- if( cl_memcmp( ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_in ),\r
- &p_cache->vl_arb[idx].tbl, sizeof(ib_vl_arb_table_t) ) )\r
- {\r
- /* The set is requesting a change. */\r
- return FALSE;\r
- }\r
- }\r
-\r
- /* Setup the response mad. */\r
- cl_memcpy( p_mad_out, p_mad_in, MAD_BLOCK_SIZE );\r
- p_mad_out->method = (IB_MAD_METHOD_RESP_MASK | IB_MAD_METHOD_GET);\r
- if( p_mad_out->mgmt_class == IB_MCLASS_SUBN_DIR )\r
- p_mad_out->status = IB_SMP_DIRECTION;\r
- else\r
- p_mad_out->status = 0;\r
-\r
- /* Copy the cached data. */\r
- cl_memcpy( ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_out ),\r
- &p_cache->vl_arb[idx].tbl, sizeof(ib_vl_arb_table_t) );\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-boolean_t\r
-mlnx_cachable_port_info(\r
- IN const mlnx_cache_t* const p_cache,\r
- IN const uint8_t port_num,\r
- IN const ib_mad_t *p_mad_in,\r
- OUT ib_mad_t *p_mad_out )\r
-{\r
- ib_port_info_t *p_port_info;\r
-\r
- UNUSED_PARAM( p_mad_out );\r
-\r
- if( !p_cache->port_info.valid )\r
- return FALSE;\r
-\r
- if( p_mad_in->method == IB_MAD_METHOD_GET )\r
- return FALSE;\r
-\r
- /*\r
- * NOTE: Even though the input MAD is const, we modify it to change\r
- * some parameters to no-ops to compensate for problems in the HCA chip.\r
- */\r
- p_port_info =\r
- (ib_port_info_t*)ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_in );\r
-\r
- /* We can only cache requests for the same port that the SMP came in on. */\r
- if( p_mad_in->attr_mod != 0 &&\r
- cl_ntoh32( p_mad_in->attr_mod ) != port_num )\r
- {\r
- return FALSE;\r
- }\r
-\r
- /*\r
- * to avoid unnecessary glitches in port state, we translate these\r
- * fields to NOP when there is no change. Note these fields cannot\r
- * change within the hardware without a Set going through here.\r
- */\r
- if( p_port_info->link_width_enabled ==\r
- p_cache->port_info.info.link_width_enabled )\r
- {\r
- p_port_info->link_width_enabled = 0;\r
- }\r
- if( (p_port_info->state_info2 & 0x0F) ==\r
- (p_cache->port_info.info.state_info2 & 0x0F) )\r
- {\r
- p_port_info->state_info2 &= 0xF0;\r
- }\r
- if( (p_port_info->link_speed & 0x0F) ==\r
- (p_cache->port_info.info.link_speed & 0x0F) )\r
- {\r
- p_port_info->link_speed &= 0xF0;\r
- }\r
- if( (p_port_info->vl_enforce & 0xF0) ==\r
- (p_cache->port_info.info.vl_enforce & 0xF0) )\r
- {\r
- p_port_info->vl_enforce &= 0x0F;\r
- }\r
-\r
- /*\r
- * We modified the input MAD to change things to no-ops, but\r
- * we can't actually fulfill the MAD with cached data.\r
- */\r
- return FALSE;\r
-}\r
-\r
-\r
-boolean_t\r
-mlnx_cachable_mad(\r
- IN const ib_ca_handle_t h_ca,\r
- IN const uint8_t port_num,\r
- IN const ib_mad_t *p_mad_in,\r
- OUT ib_mad_t *p_mad_out )\r
-{\r
- if( p_mad_in->mgmt_class!= IB_MCLASS_SUBN_DIR &&\r
- p_mad_in->mgmt_class != IB_MCLASS_SUBN_LID )\r
- {\r
- return FALSE;\r
- }\r
-\r
- switch( p_mad_in->attr_id )\r
- {\r
- case IB_MAD_ATTR_GUID_INFO:\r
- return mlnx_cachable_guid_info(\r
- &h_ca->cache[port_num-1], p_mad_in, p_mad_out );\r
-\r
- case IB_MAD_ATTR_P_KEY_TABLE:\r
- return mlnx_cachable_pkey_table(\r
- &h_ca->cache[port_num-1], p_mad_in, p_mad_out );\r
-\r
- case IB_MAD_ATTR_SLVL_TABLE:\r
- return mlnx_cachable_sl_vl_table(\r
- &h_ca->cache[port_num-1], p_mad_in, p_mad_out );\r
-\r
- case IB_MAD_ATTR_VL_ARBITRATION:\r
- return mlnx_cachable_vl_arb_table(\r
- &h_ca->cache[port_num-1], p_mad_in, p_mad_out );\r
-\r
- case IB_MAD_ATTR_PORT_INFO:\r
- return mlnx_cachable_port_info(\r
- &h_ca->cache[port_num-1], port_num, p_mad_in, p_mad_out );\r
-\r
- default:\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-\r
-void\r
-mlnx_update_guid_info(\r
- IN mlnx_cache_t* const p_cache,\r
- IN const ib_mad_t* const p_mad_out )\r
-{\r
- uint32_t idx;\r
-\r
- /* Get the table selector from the attribute */\r
- idx = cl_ntoh32( p_mad_out->attr_mod );\r
-\r
- /*\r
- * We only get successful MADs here, so invalid settings\r
- * shouldn't happen.\r
- */\r
- CL_ASSERT( idx <= 31 );\r
-\r
- cl_memcpy( &p_cache->guid_block[idx].tbl,\r
- ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_out ),\r
- sizeof(ib_guid_info_t) );\r
- p_cache->guid_block[idx].valid = TRUE;\r
-}\r
-\r
-\r
-void\r
-mlnx_update_pkey_table(\r
- IN mlnx_cache_t* const p_cache,\r
- IN const ib_mad_t* const p_mad_out )\r
-{\r
- uint16_t idx;\r
-\r
- /* Get the table selector from the attribute */\r
- idx = ((uint16_t)cl_ntoh32( p_mad_out->attr_mod ));\r
-\r
- ASSERT( idx <= 2047 );\r
-\r
- cl_memcpy( &p_cache->pkey_tbl[idx].tbl,\r
- ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_out ),\r
- sizeof(ib_pkey_table_info_t) );\r
- p_cache->pkey_tbl[idx].valid = TRUE;\r
-}\r
-\r
-\r
-void\r
-mlnx_update_sl_vl_table(\r
- IN mlnx_cache_t* const p_cache,\r
- IN const ib_mad_t* const p_mad_out )\r
-{\r
- cl_memcpy( &p_cache->sl_vl.tbl,\r
- ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_out ),\r
- sizeof(ib_slvl_table_t) );\r
- p_cache->sl_vl.valid = TRUE;\r
-}\r
-\r
-\r
-void\r
-mlnx_update_vl_arb_table(\r
- IN mlnx_cache_t* const p_cache,\r
- IN const ib_mad_t* const p_mad_out )\r
-{\r
- uint16_t idx;\r
-\r
- /* Get the table selector from the attribute */\r
- idx = ((uint16_t)(cl_ntoh32( p_mad_out->attr_mod ) >> 16)) - 1;\r
-\r
- CL_ASSERT( idx <= 3 );\r
-\r
- cl_memcpy( &p_cache->vl_arb[idx].tbl,\r
- ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_out ),\r
- sizeof(ib_vl_arb_table_t) );\r
- p_cache->vl_arb[idx].valid = TRUE;\r
-}\r
-\r
-\r
-void\r
-mlnx_update_port_info(\r
- IN const mlnx_cache_t* const p_cache,\r
- IN const uint8_t port_num,\r
- IN const ib_mad_t* const p_mad_out )\r
-{\r
- UNUSED_PARAM( p_cache );\r
-\r
- /* We can only cache requests for the same port that the SMP came in on. */\r
- /* TODO: Add synchronization to support getting data from other ports. */\r
- if( p_mad_out->attr_mod != 0 &&\r
- cl_ntoh32( p_mad_out->attr_mod ) != port_num )\r
- {\r
- return;\r
- }\r
-\r
- /* TODO: Setup the capabilites mask properly. */\r
-}\r
-\r
-\r
-void\r
-mlnx_update_cache(\r
- IN const ib_ca_handle_t h_ca,\r
- IN const uint8_t port_num,\r
- IN const ib_mad_t *p_mad_out )\r
-{\r
- if( p_mad_out->mgmt_class != IB_MCLASS_SUBN_DIR &&\r
- p_mad_out->mgmt_class != IB_MCLASS_SUBN_LID )\r
- {\r
- return;\r
- }\r
-\r
- /* Any successful response updates the cache. */\r
- if( p_mad_out->status )\r
- return;\r
-\r
-\r
- switch( p_mad_out->attr_id )\r
- {\r
- case IB_MAD_ATTR_GUID_INFO:\r
- mlnx_update_guid_info(\r
- &h_ca->cache[port_num-1], p_mad_out );\r
- break;\r
-\r
- case IB_MAD_ATTR_P_KEY_TABLE:\r
- mlnx_update_pkey_table(\r
- &h_ca->cache[port_num-1], p_mad_out );\r
- break;\r
-\r
- case IB_MAD_ATTR_SLVL_TABLE:\r
- mlnx_update_sl_vl_table(\r
- &h_ca->cache[port_num-1], p_mad_out );\r
- break;\r
-\r
- case IB_MAD_ATTR_VL_ARBITRATION:\r
- mlnx_update_vl_arb_table(\r
- &h_ca->cache[port_num-1], p_mad_out );\r
- break;\r
-\r
- case IB_MAD_ATTR_PORT_INFO:\r
- mlnx_update_port_info(\r
- &h_ca->cache[port_num-1], port_num, p_mad_out );\r
- break;\r
-\r
- default:\r
- break;\r
- }\r
-\r
-}\r
-\r
-\r
-/*\r
- * Local MAD Support Verbs. For CAs that do not support\r
- * agents in HW.\r
- */\r
-\r
-#ifdef WIN_TO_BE_REMOVED\r
-//TODO: seems like non need in that\r
-static void build_smp_wc(u64 wr_id, u16 slid, u16 pkey_index, \r
- u8 port_num, struct _ib_wc *wc)\r
-{\r
- RtlZeroMemory(wc, sizeof *wc);\r
- wc->wr_id = wr_id;\r
- wc->status = IB_WC_SUCCESS;\r
- wc->wc_type = IB_WC_RECV;\r
- wc->length = sizeof(struct ib_mad) + sizeof(struct ib_grh);\r
- wc->qp_num = IB_QP0;\r
- wc->port_num = port_num;\r
- wc->recv.ud.pkey_index = pkey_index;\r
- wc->recv.ud.remote_qp = IB_QP0;\r
- wc->recv.ud.remote_lid = slid;\r
- wc->recv.ud.remote_sl = 0;\r
- wc->recv.ud.path_bits = 0;\r
-}\r
-#endif\r
-\r
-ib_api_status_t\r
-mlnx_local_mad (\r
- IN const ib_ca_handle_t h_ca,\r
- IN const uint8_t port_num,\r
- IN const ib_av_attr_t* p_av_attr,\r
- IN const ib_mad_t *p_mad_in,\r
- OUT ib_mad_t *p_mad_out )\r
-{\r
- int err;\r
- ib_api_status_t status = IB_SUCCESS;\r
- mlnx_hob_t *hob_p = (mlnx_hob_t *)h_ca;\r
- struct ib_device *ib_dev = IBDEV_FROM_HOB( hob_p );\r
- //TODO: do we need use flags (IB_MAD_IGNORE_MKEY, IB_MAD_IGNORE_BKEY) ?\r
- int mad_flags = 0; \r
- struct _ib_wc *wc_p = NULL;\r
- //TODO: do we need use grh ?\r
- struct _ib_grh *grh_p = NULL;\r
-\r
- HCA_ENTER(HCA_DBG_MAD);\r
-\r
- // sanity checks\r
- if (port_num > 2) {\r
- status = IB_INVALID_PARAMETER;\r
- goto err_port_num;\r
- }\r
-\r
- if (p_av_attr){\r
- wc_p = cl_zalloc(sizeof(struct _ib_wc));\r
- if(!wc_p){\r
- status = IB_INSUFFICIENT_MEMORY ;\r
- goto err_wc_alloc;\r
- }\r
- //Copy part of the attributes need to fill the mad extended fields in mellanox devices\r
- wc_p->recv.ud.remote_lid = p_av_attr->dlid;\r
- wc_p->recv.ud.remote_sl = p_av_attr->sl;\r
- wc_p->recv.ud.path_bits = p_av_attr->path_bits;\r
- wc_p->recv.ud.recv_opt = p_av_attr->grh_valid?IB_RECV_OPT_GRH_VALID:0;\r
-\r
- if(wc_p->recv.ud.recv_opt &IB_RECV_OPT_GRH_VALID){\r
- grh_p = cl_zalloc(sizeof(struct _ib_grh));\r
- if(!grh_p){\r
- status = IB_INSUFFICIENT_MEMORY ;\r
- goto err_grh_alloc;\r
- }\r
- cl_memcpy(grh_p, &p_av_attr->grh, sizeof(ib_grh_t));\r
- }\r
- \r
-\r
- }\r
-\r
- HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_MAD, \r
- ("MAD: Class %02x, Method %02x, Attr %02x, HopPtr %d, HopCnt %d, \n",\r
- (uint32_t)((ib_smp_t *)p_mad_in)->mgmt_class, \r
- (uint32_t)((ib_smp_t *)p_mad_in)->method, \r
- (uint32_t)((ib_smp_t *)p_mad_in)->attr_id, \r
- (uint32_t)((ib_smp_t *)p_mad_in)->hop_ptr,\r
- (uint32_t)((ib_smp_t *)p_mad_in)->hop_count));\r
-\r
- \r
- // process mad\r
- if( !mlnx_cachable_mad( h_ca, port_num, p_mad_in, p_mad_out ) )\r
- {\r
- err = mthca_process_mad(ib_dev, mad_flags, (uint8_t)port_num, \r
- wc_p, grh_p, (struct ib_mad*)p_mad_in, (struct ib_mad*)p_mad_out);\r
- if (!err) {\r
- HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_MAD, \r
- ("MAD failed:\n\tClass 0x%x\n\tMethod 0x%x\n\tAttr 0x%x",\r
- p_mad_in->mgmt_class, p_mad_in->method, p_mad_in->attr_id ));\r
- status = IB_ERROR;\r
- goto err_process_mad;\r
- }\r
- \r
- if( (p_mad_in->mgmt_class == IB_MCLASS_SUBN_DIR ||\r
- p_mad_in->mgmt_class == IB_MCLASS_SUBN_LID) &&\r
- p_mad_in->attr_id == IB_MAD_ATTR_PORT_INFO )\r
- {\r
- ib_port_info_t *p_pi_in, *p_pi_out;\r
-\r
- if( p_mad_in->mgmt_class == IB_MCLASS_SUBN_DIR )\r
- {\r
- p_pi_in = (ib_port_info_t*)\r
- ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_in );\r
- p_pi_out = (ib_port_info_t*)\r
- ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_out );\r
- }\r
- else\r
- {\r
- p_pi_in = (ib_port_info_t*)(p_mad_in + 1);\r
- p_pi_out = (ib_port_info_t*)(p_mad_out + 1);\r
- }\r
-\r
- /* Work around FW bug 33958 */\r
- p_pi_out->subnet_timeout &= 0x7F;\r
- if( p_mad_in->method == IB_MAD_METHOD_SET )\r
- p_pi_out->subnet_timeout |= (p_pi_in->subnet_timeout & 0x80);\r
- }\r
-\r
- mlnx_update_cache( h_ca, port_num, p_mad_out );\r
- }\r
-\r
- /* Modify direction for Direct MAD */\r
- if ( p_mad_in->mgmt_class == IB_MCLASS_SUBN_DIR )\r
- p_mad_out->status |= IB_SMP_DIRECTION;\r
-\r
-\r
-err_process_mad:\r
- if(grh_p)\r
- cl_free(grh_p);\r
-err_grh_alloc:\r
- if(wc_p)\r
- cl_free(wc_p);\r
-err_wc_alloc:\r
-err_port_num: \r
- HCA_PRINT_EXIT(TRACE_LEVEL_ERROR , HCA_DBG_MAD,\r
- ("completes with ERROR status %s\n", IB_GET_ERR_STR(status)));\r
- return status;\r
-}\r
- \r
{\r
mlnx_hca_t *p_hca;\r
ib_api_status_t status = IB_NOT_FOUND;\r
- mlnx_cache_t *p_cache;\r
struct ib_device *ib_dev;\r
\r
HCA_ENTER(HCA_DBG_SHIM);\r
goto err_set_cb;\r
}\r
\r
- // MAD cache\r
- p_cache = (mlnx_cache_t*)cl_pzalloc( sizeof(mlnx_cache_t) * 2 );\r
- if( !p_cache ) {\r
- status = IB_INSUFFICIENT_MEMORY;\r
- goto err_mad_cache;\r
- }\r
- p_hca->hob.cache = p_cache;\r
-\r
\r
//TODO: do we need something for kernel users ?\r
\r
if (ph_ca) *ph_ca = &p_hca->hob;\r
status = IB_SUCCESS;\r
\r
-err_mad_cache:\r
+//err_mad_cache:\r
err_set_cb:\r
HCA_PRINT_EXIT(TRACE_LEVEL_ERROR , HCA_DBG_SHIM,\r
("completes with ERROR status %s\n", IB_GET_ERR_STR(status)));\r
}\r
\r
\r
+ib_api_status_t\r
+mlnx_local_mad (\r
+ IN const ib_ca_handle_t h_ca,\r
+ IN const uint8_t port_num,\r
+ IN const ib_av_attr_t* p_av_attr,\r
+ IN const ib_mad_t *p_mad_in,\r
+ OUT ib_mad_t *p_mad_out )\r
+{\r
+ int err;\r
+ ib_api_status_t status = IB_SUCCESS;\r
+ mlnx_hob_t *hob_p = (mlnx_hob_t *)h_ca;\r
+ struct ib_device *ib_dev = IBDEV_FROM_HOB( hob_p );\r
+ //TODO: do we need use flags (IB_MAD_IGNORE_MKEY, IB_MAD_IGNORE_BKEY) ?\r
+ int mad_flags = 0; \r
+ struct _ib_wc *wc_p = NULL;\r
+ //TODO: do we need use grh ?\r
+ struct _ib_grh *grh_p = NULL;\r
+\r
+ HCA_ENTER(HCA_DBG_MAD);\r
+\r
+ // sanity checks\r
+ if (port_num > 2) {\r
+ status = IB_INVALID_PARAMETER;\r
+ goto err_port_num;\r
+ }\r
+\r
+ if (p_av_attr){\r
+ wc_p = cl_zalloc(sizeof(struct _ib_wc));\r
+ if(!wc_p){\r
+ status = IB_INSUFFICIENT_MEMORY ;\r
+ goto err_wc_alloc;\r
+ }\r
+ //Copy part of the attributes need to fill the mad extended fields in mellanox devices\r
+ wc_p->recv.ud.remote_lid = p_av_attr->dlid;\r
+ wc_p->recv.ud.remote_sl = p_av_attr->sl;\r
+ wc_p->recv.ud.path_bits = p_av_attr->path_bits;\r
+ wc_p->recv.ud.recv_opt = p_av_attr->grh_valid?IB_RECV_OPT_GRH_VALID:0;\r
+\r
+ if(wc_p->recv.ud.recv_opt &IB_RECV_OPT_GRH_VALID){\r
+ grh_p = cl_zalloc(sizeof(struct _ib_grh));\r
+ if(!grh_p){\r
+ status = IB_INSUFFICIENT_MEMORY ;\r
+ goto err_grh_alloc;\r
+ }\r
+ cl_memcpy(grh_p, &p_av_attr->grh, sizeof(ib_grh_t));\r
+ }\r
+ \r
+\r
+ }\r
+\r
+ HCA_PRINT( TRACE_LEVEL_INFORMATION, HCA_DBG_MAD, \r
+ ("MAD: Class %02x, Method %02x, Attr %02x, HopPtr %d, HopCnt %d, \n",\r
+ (uint32_t)((ib_smp_t *)p_mad_in)->mgmt_class, \r
+ (uint32_t)((ib_smp_t *)p_mad_in)->method, \r
+ (uint32_t)((ib_smp_t *)p_mad_in)->attr_id, \r
+ (uint32_t)((ib_smp_t *)p_mad_in)->hop_ptr,\r
+ (uint32_t)((ib_smp_t *)p_mad_in)->hop_count));\r
+\r
+ \r
+ // process mad\r
+ \r
+ err = mthca_process_mad(ib_dev, mad_flags, (uint8_t)port_num, \r
+ wc_p, grh_p, (struct ib_mad*)p_mad_in, (struct ib_mad*)p_mad_out);\r
+ if (!err) {\r
+ HCA_PRINT( TRACE_LEVEL_ERROR, HCA_DBG_MAD, \r
+ ("MAD failed:\n\tClass 0x%x\n\tMethod 0x%x\n\tAttr 0x%x",\r
+ p_mad_in->mgmt_class, p_mad_in->method, p_mad_in->attr_id ));\r
+ status = IB_ERROR;\r
+ goto err_process_mad;\r
+ }\r
+ \r
+ if( (p_mad_in->mgmt_class == IB_MCLASS_SUBN_DIR ||\r
+ p_mad_in->mgmt_class == IB_MCLASS_SUBN_LID) &&\r
+ p_mad_in->attr_id == IB_MAD_ATTR_PORT_INFO )\r
+ {\r
+ ib_port_info_t *p_pi_in, *p_pi_out;\r
+\r
+ if( p_mad_in->mgmt_class == IB_MCLASS_SUBN_DIR )\r
+ {\r
+ p_pi_in = (ib_port_info_t*)\r
+ ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_in );\r
+ p_pi_out = (ib_port_info_t*)\r
+ ib_smp_get_payload_ptr( (ib_smp_t*)p_mad_out );\r
+ }\r
+ else\r
+ {\r
+ p_pi_in = (ib_port_info_t*)(p_mad_in + 1);\r
+ p_pi_out = (ib_port_info_t*)(p_mad_out + 1);\r
+ }\r
+\r
+ /* Work around FW bug 33958 */\r
+ p_pi_out->subnet_timeout &= 0x7F;\r
+ if( p_mad_in->method == IB_MAD_METHOD_SET )\r
+ p_pi_out->subnet_timeout |= (p_pi_in->subnet_timeout & 0x80);\r
+ }\r
+\r
+ /* Modify direction for Direct MAD */\r
+ if ( p_mad_in->mgmt_class == IB_MCLASS_SUBN_DIR )\r
+ p_mad_out->status |= IB_SMP_DIRECTION;\r
+\r
+\r
+err_process_mad:\r
+ if(grh_p)\r
+ cl_free(grh_p);\r
+err_grh_alloc:\r
+ if(wc_p)\r
+ cl_free(wc_p);\r
+err_wc_alloc:\r
+err_port_num: \r
+ HCA_PRINT_EXIT(TRACE_LEVEL_ERROR , HCA_DBG_MAD,\r
+ ("completes with ERROR status %s\n", IB_GET_ERR_STR(status)));\r
+ return status;\r
+}\r
+ \r
+\r
void\r
setup_ci_interface(\r
IN const ib_net64_t ca_guid,\r