2 * Copyright (c) 2005 SilverStorm Technologies. All rights reserved.
\r
4 * This software is available to you under the OpenIB.org BSD license
\r
7 * Redistribution and use in source and binary forms, with or
\r
8 * without modification, are permitted provided that the following
\r
9 * conditions are met:
\r
11 * - Redistributions of source code must retain the above
\r
12 * copyright notice, this list of conditions and the following
\r
15 * - Redistributions in binary form must reproduce the above
\r
16 * copyright notice, this list of conditions and the following
\r
17 * disclaimer in the documentation and/or other materials
\r
18 * provided with the distribution.
\r
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
32 #include "iba/ib_al.h"
\r
33 #include "vnic_util.h"
\r
34 #include "vnic_driver.h"
\r
35 #include "vnic_viport.h"
\r
36 #include "vnic_control.h"
\r
37 #include "vnic_data.h"
\r
38 #include "vnic_config.h"
\r
39 #include "vnic_controlpkt.h"
\r
41 extern vnic_globals_t g_vnic;
\r
43 static void viport_timeout( void *context );
\r
44 static ib_api_status_t viport_initMacAddresses( viport_t *p_viport );
\r
45 static void viport_statemachine( void *context );
\r
48 viport_get_adapter_name(
\r
49 IN viport_t *p_viport )
\r
51 cl_memcpy(p_viport->p_adapter->name, DEFAULT_VNIC_NAME, sizeof(DEFAULT_VNIC_NAME) );
\r
52 return ( sizeof(DEFAULT_VNIC_NAME) );
\r
56 viport_config_defaults(
\r
57 IN viport_t *p_viport )
\r
60 vnic_adapter_t *p_adapter = p_viport->p_adapter;
\r
61 ViportConfig_t *pConfig = &p_viport->port_config;
\r
62 ControlConfig_t *pControlConfig = &p_viport->port_config.controlConfig;
\r
63 DataConfig_t *pDataConfig = &p_viport->port_config.dataConfig;
\r
65 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
67 p_viport->state = VIPORT_DISCONNECTED;
\r
68 p_viport->linkState = LINK_RETRYWAIT;
\r
69 p_viport->newMtu = 1500;
\r
70 p_viport->newFlags = 0;
\r
72 cl_timer_init( &p_viport->timer, viport_timeout, p_viport );
\r
74 pConfig->statsInterval = p_adapter->params.ViportStatsInterval;
\r
75 pConfig->hbInterval = p_adapter->params.ViportHbInterval;
\r
76 pConfig->hbTimeout = p_adapter->params.ViportHbTimeout;
\r
78 cl_memcpy ( pConfig->ioc_string,
\r
79 p_adapter->ioc_info.profile.id_string,
\r
80 min( sizeof( p_adapter->ioc_info.profile.id_string ),
\r
81 sizeof( pConfig->ioc_string )) );
\r
83 pControlConfig->ibConfig.sid =
\r
91 ( (uint8_t)( p_adapter->ioc_info.profile.ioc_guid >> 24 ) & 0xFF );
\r
93 pControlConfig->ibConfig.connData.pathId = 0;
\r
94 pControlConfig->ibConfig.connData.inicInstance = 0;
\r
95 pControlConfig->ibConfig.connData.pathNum = 0;
\r
97 pControlConfig->ibConfig.retryCount = p_adapter->params.RetryCount;
\r
98 pControlConfig->ibConfig.rnrRetryCount = p_adapter->params.RetryCount;
\r
99 pControlConfig->ibConfig.minRnrTimer = (uint8_t)p_adapter->params.MinRnrTimer;
\r
100 pControlConfig->ibConfig.numRecvs = 5; /* Not configurable */
\r
101 pControlConfig->ibConfig.numSends = 1; /* Not configurable */
\r
102 pControlConfig->ibConfig.recvScatter = 1; /* Not configurable */
\r
103 pControlConfig->ibConfig.sendGather = 1; /* Not configurable */
\r
105 /* indicate new features support capabilities */
\r
106 pControlConfig->ibConfig.connData.featuresSupported =
\r
107 hton32((uint32_t)(INIC_FEAT_IGNORE_VLAN | INIC_FEAT_RDMA_IMMED ));
\r
109 cl_memcpy ( pControlConfig->ibConfig.connData.nodename,
\r
111 min( sizeof( g_vnic.host_name ),
\r
112 sizeof( pControlConfig->ibConfig.connData.nodename )) );
\r
114 pControlConfig->numRecvs = pControlConfig->ibConfig.numRecvs;
\r
116 pControlConfig->inicInstance = pControlConfig->ibConfig.connData.inicInstance;
\r
117 pControlConfig->maxAddressEntries = (uint16_t)p_adapter->params.MaxAddressEntries;
\r
118 pControlConfig->minAddressEntries = (uint16_t)p_adapter->params.MinAddressEntries;
\r
119 pControlConfig->reqRetryCount = (uint8_t)p_adapter->params.ControlReqRetryCount;
\r
120 pControlConfig->rspTimeout = p_adapter->params.ControlRspTimeout;
\r
122 pDataConfig->ibConfig.sid =
\r
130 ( (uint8_t)( p_adapter->ioc_info.profile.ioc_guid >> 24 ) & 0xFF );
\r
132 pDataConfig->ibConfig.connData.pathId = get_time_stamp_ms();
\r
133 pDataConfig->ibConfig.connData.inicInstance = pControlConfig->inicInstance;
\r
134 pDataConfig->ibConfig.connData.pathNum = 0;
\r
136 pDataConfig->ibConfig.retryCount = p_adapter->params.RetryCount;
\r
137 pDataConfig->ibConfig.rnrRetryCount = p_adapter->params.RetryCount;
\r
138 pDataConfig->ibConfig.minRnrTimer = (uint8_t)p_adapter->params.MinRnrTimer;
\r
141 * NOTE: The numRecvs size assumes that the EIOC could
\r
142 * RDMA enough packets to fill all of the host recv
\r
143 * pool entries, plus send a kick message after each
\r
144 * packet, plus RDMA new buffers for the size of
\r
145 * the EIOC recv buffer pool, plus send kick messages
\r
146 * after each MinHostUpdateSz of new buffers all
\r
147 * before the Host can even pull off the first completed
\r
148 * receive off the completion queue, and repost the
\r
149 * receive. NOT LIKELY!
\r
151 pDataConfig->ibConfig.numRecvs = p_adapter->params.HostRecvPoolEntries +
\r
152 ( p_adapter->params.MaxEiocPoolSz / p_adapter->params.MinHostUpdateSz );
\r
154 #if TRUE //defined(LIMIT_OUTSTANDING_SENDS)
\r
156 pDataConfig->ibConfig.numSends = (2 * p_adapter->params.NotifyBundleSz ) +
\r
157 ( p_adapter->params.HostRecvPoolEntries / p_adapter->params.MinEiocUpdateSz ) + 1;
\r
159 #else /* !defined(LIMIT_OUTSTANDING_SENDS) */
\r
161 * NOTE: The numSends size assumes that the HOST could
\r
162 * post RDMA sends for every single buffer in the EIOCs
\r
163 * receive pool, and allocate a full complement of
\r
164 * receive buffers on the host, and RDMA free buffers
\r
165 * every MinEiocUpdateSz entries all before the HCA
\r
166 * can complete a single RDMA transfer. VERY UNLIKELY,
\r
167 * BUT NOT COMPLETELY IMPOSSIBLE IF THERE IS AN IB
\r
170 pDataConfig->ibConfig.numSends = p_adapter->params.MaxEiocPoolSz +
\r
171 ( p_adapter->params.HostRecvPoolEntries / p_adapter->params.MinEiocUpdateSz ) + 1;
\r
173 #endif /* !defined(LIMIT_OUTSTANDING_SENDS) */
\r
175 pDataConfig->ibConfig.recvScatter = 1; /* Not configurable */
\r
176 pDataConfig->ibConfig.sendGather = MAX_NUM_SGE; /* Not configurable */
\r
178 pDataConfig->numRecvs = pDataConfig->ibConfig.numRecvs;
\r
179 pDataConfig->pathId = pDataConfig->ibConfig.connData.pathId;
\r
181 pDataConfig->hostMin.sizeRecvPoolEntry =
\r
182 (uint32_t)BUFFER_SIZE(ETH_VLAN_HLEN + p_adapter->params.MinMtu);
\r
183 pDataConfig->hostMax.sizeRecvPoolEntry =
\r
184 (uint32_t)BUFFER_SIZE(ETH_VLAN_HLEN + p_adapter->params.MaxMtu);
\r
185 pDataConfig->eiocMin.sizeRecvPoolEntry =
\r
186 (uint32_t)BUFFER_SIZE(ETH_VLAN_HLEN + p_adapter->params.MinMtu);
\r
187 pDataConfig->eiocMax.sizeRecvPoolEntry = MAX_PARAM_VALUE;
\r
189 pDataConfig->hostRecvPoolEntries = p_adapter->params.HostRecvPoolEntries;
\r
190 pDataConfig->notifyBundle = p_adapter->params.NotifyBundleSz;
\r
192 pDataConfig->hostMin.numRecvPoolEntries = p_adapter->params.MinHostPoolSz;
\r
193 pDataConfig->hostMax.numRecvPoolEntries = MAX_PARAM_VALUE;
\r
194 pDataConfig->eiocMin.numRecvPoolEntries = p_adapter->params.MinEiocPoolSz;
\r
195 pDataConfig->eiocMax.numRecvPoolEntries = p_adapter->params.MaxEiocPoolSz;
\r
197 pDataConfig->hostMin.timeoutBeforeKick = p_adapter->params.MinHostKickTimeout;
\r
198 pDataConfig->hostMax.timeoutBeforeKick = p_adapter->params.MaxHostKickTimeout;
\r
199 pDataConfig->eiocMin.timeoutBeforeKick = 0;
\r
200 pDataConfig->eiocMax.timeoutBeforeKick = MAX_PARAM_VALUE;
\r
202 pDataConfig->hostMin.numRecvPoolEntriesBeforeKick = p_adapter->params.MinHostKickEntries;
\r
203 pDataConfig->hostMax.numRecvPoolEntriesBeforeKick = p_adapter->params.MaxHostKickEntries;
\r
204 pDataConfig->eiocMin.numRecvPoolEntriesBeforeKick = 0;
\r
205 pDataConfig->eiocMax.numRecvPoolEntriesBeforeKick = MAX_PARAM_VALUE;
\r
207 pDataConfig->hostMin.numRecvPoolBytesBeforeKick = p_adapter->params.MinHostKickBytes;
\r
208 pDataConfig->hostMax.numRecvPoolBytesBeforeKick = p_adapter->params.MaxHostKickBytes;
\r
209 pDataConfig->eiocMin.numRecvPoolBytesBeforeKick = 0;
\r
210 pDataConfig->eiocMax.numRecvPoolBytesBeforeKick = MAX_PARAM_VALUE;
\r
212 pDataConfig->hostMin.freeRecvPoolEntriesPerUpdate = p_adapter->params.MinHostUpdateSz;
\r
213 pDataConfig->hostMax.freeRecvPoolEntriesPerUpdate = p_adapter->params.MaxHostUpdateSz;
\r
214 pDataConfig->eiocMin.freeRecvPoolEntriesPerUpdate = p_adapter->params.MinEiocUpdateSz;
\r
215 pDataConfig->eiocMax.freeRecvPoolEntriesPerUpdate = p_adapter->params.MaxEiocUpdateSz;
\r
217 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
221 static BOOLEAN config_isValid(ViportConfig_t *pConfig)
\r
223 UNREFERENCED_PARAMETER( pConfig );
\r
230 viport_t *p_viport )
\r
232 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
236 InterlockedExchange( &p_viport->p_adapter->carrier, FALSE );
\r
237 InterlockedExchange( &p_viport->p_netpath->carrier, FALSE );
\r
238 viport_timerStop( p_viport );
\r
240 data_disconnect( &p_viport->data );
\r
242 control_cleanup( &p_viport->control );
\r
244 data_cleanup( &p_viport->data );
\r
246 if( p_viport->macAddresses != NULL )
\r
248 NdisFreeMemory( p_viport->macAddresses,
\r
249 p_viport->numMacAddresses * sizeof(Inic_AddressOp_t), 0 );
\r
252 cl_timer_destroy( &p_viport->timer );
\r
254 NdisFreeMemory ( p_viport, sizeof(viport_t), 0 );
\r
256 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
263 IN viport_t *p_viport,
\r
264 IN ib_path_rec_t *p_path,
\r
265 IN uint64_t *p_guid )
\r
268 UNUSED_PARAM( p_guid );
\r
270 VNIC_ENTER( VNIC_DBG_FUNC );
\r
272 VNIC_TRACE( VNIC_DBG_INFO,
\r
273 ("Using SLID=%d DLID=%d Target:%s\n",
\r
274 cl_ntoh16( p_path->slid ),
\r
275 cl_ntoh16( p_path->dlid ),
\r
276 p_viport->p_adapter->ioc_info.profile.id_string) );
\r
278 p_viport->portGuid = p_path->sgid.unicast.interface_id;
\r
279 p_viport->iocGuid = *p_guid;
\r
280 p_viport->port_config.dataConfig.ibConfig.pathInfo = *p_path;
\r
281 p_viport->port_config.controlConfig.ibConfig.pathInfo = *p_path;
\r
282 p_viport->port_config.controlConfig.ibConfig.sid =
\r
283 p_viport->p_adapter->p_svc_entries[0].id;
\r
284 p_viport->port_config.dataConfig.ibConfig.sid =
\r
285 p_viport->p_adapter->p_svc_entries[1].id;
\r
287 VNIC_EXIT( VNIC_DBG_FUNC );
\r
292 IN viport_t *p_viport,
\r
293 IN Netpath_t *pNetpath )
\r
295 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
298 if(p_viport->p_netpath != NULL)
\r
303 p_viport->p_netpath = pNetpath;
\r
305 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
310 viport_unsetParent(
\r
311 IN viport_t *p_viport,
\r
312 IN Netpath_t *pNetpath )
\r
314 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
315 if( pNetpath->pViport == p_viport )
\r
316 viport_free( p_viport );
\r
317 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
323 IN viport_t *p_viport )
\r
325 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
327 viport_timerStop( p_viport );
\r
328 viport_disconnect(p_viport);
\r
329 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
335 IN viport_t *p_viport )
\r
337 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
339 InterlockedExchange( (volatile LONG *)&p_viport->disconnect, TRUE );
\r
340 viport_failure( p_viport );
\r
342 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
349 IN viport_t *p_viport,
\r
354 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
\r
356 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
358 if(mtu > data_maxMtu(&p_viport->data))
\r
360 viport_failure(p_viport);
\r
361 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,
\r
362 ("Configuration error. Mtu of %d unsupported by %s\n", mtu, p_viport->p_adapter->name ) );
\r
363 return NDIS_STATUS_FAILURE;
\r
366 KeAcquireSpinLock( &p_viport->lock, &irql );
\r
368 flags &= ( INIC_FLAG_ENABLE_NIC |
\r
369 INIC_FLAG_ENABLE_MCAST_ALL |
\r
370 INIC_FLAG_ENABLE_PROMISC );
\r
372 if( (p_viport->newFlags != flags) ||
\r
373 (p_viport->newMtu != mtu))
\r
375 p_viport->newFlags = flags;
\r
376 p_viport->newMtu = mtu;
\r
377 InterlockedOr( &p_viport->updates, NEED_LINK_CONFIG );
\r
379 KeReleaseSpinLock( &p_viport->lock, irql );
\r
381 status = _viport_process_query( p_viport, TRUE );
\r
382 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
388 IN viport_t *p_viport,
\r
389 IN uint8_t *p_address )
\r
393 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
398 KeAcquireSpinLock( &p_viport->lock, &flags );
\r
399 if( p_viport->macAddresses == NULL )
\r
401 KeReleaseSpinLock( &p_viport->lock, flags );
\r
404 if( cl_memcmp(p_viport->macAddresses[UNICAST_ADDR].address,
\r
405 p_address, MAC_ADDR_LEN ) )
\r
407 cl_memcpy( p_viport->macAddresses[UNICAST_ADDR].address,
\r
408 p_address, MAC_ADDR_LEN );
\r
409 p_viport->macAddresses[UNICAST_ADDR].operation
\r
410 = INIC_OP_SET_ENTRY;
\r
411 InterlockedOr( &p_viport->updates, NEED_ADDRESS_CONFIG );
\r
413 KeReleaseSpinLock( &p_viport->lock, flags );
\r
415 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
420 /* Returns flags for state machine operations. */
\r
422 viport_setMulticast(
\r
423 IN viport_t *p_viport )
\r
425 vnic_adapter_t *p_adapter = p_viport->p_adapter;
\r
426 uint32_t updates = 0;
\r
429 NDIS_STATUS status;
\r
431 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
433 KeAcquireSpinLock( &p_viport->lock, &flags );
\r
435 if( p_viport->macAddresses == NULL )
\r
437 KeReleaseSpinLock( &p_viport->lock, flags );
\r
438 return NDIS_STATUS_NOT_ACCEPTED;
\r
441 ASSERT( (p_viport->updates & ~MCAST_OVERFLOW) == 0 );
\r
443 if( p_adapter->mc_count > p_viport->numMacAddresses - MCAST_ADDR_START )
\r
445 updates |= NEED_LINK_CONFIG | MCAST_OVERFLOW;
\r
447 else if( p_adapter->mc_count == 0 )
\r
449 /* NDIS can send us a NULL array to clear all entries */
\r
450 if( InterlockedAnd(
\r
451 &p_viport->updates, ~MCAST_OVERFLOW ) & MCAST_OVERFLOW )
\r
453 updates |= NEED_LINK_CONFIG;
\r
455 /* invalidate all entries for the remote */
\r
456 for (i = MCAST_ADDR_START;
\r
457 i < min( MAX_ADDR_ARRAY, p_viport->numMacAddresses ); i++ )
\r
459 p_viport->macAddresses[i].valid = 0;
\r
460 p_viport->macAddresses[i].operation = INIC_OP_SET_ENTRY;
\r
462 updates |= NEED_ADDRESS_CONFIG;
\r
466 if( InterlockedAnd(
\r
467 &p_viport->updates, ~MCAST_OVERFLOW ) & MCAST_OVERFLOW )
\r
469 updates |= NEED_LINK_CONFIG;
\r
471 /* Brute force algorithm */
\r
472 for (i = MCAST_ADDR_START;
\r
473 i < min( MAX_ADDR_ARRAY, p_adapter->mc_count + MCAST_ADDR_START );
\r
476 if( p_viport->macAddresses[i].valid &&
\r
477 NdisEqualMemory( p_viport->macAddresses[i].address,
\r
478 p_adapter->mcast_array[i - MCAST_ADDR_START].addr,
\r
484 NdisMoveMemory( &p_viport->macAddresses[i].address,
\r
485 p_adapter->mcast_array[i - MCAST_ADDR_START].addr,
\r
488 p_viport->macAddresses[i].valid = 1;
\r
489 p_viport->macAddresses[i].operation = INIC_OP_SET_ENTRY;
\r
491 updates |= NEED_ADDRESS_CONFIG;
\r
493 for (; i < min( MAX_ADDR_ARRAY, p_viport->numMacAddresses ); i++ )
\r
495 if( !p_viport->macAddresses[i].valid )
\r
498 updates |= NEED_ADDRESS_CONFIG;
\r
500 p_viport->macAddresses[i].valid = 0;
\r
501 p_viport->macAddresses[i].operation = INIC_OP_SET_ENTRY;
\r
506 * Now that the mac array is setup, we can set the update bits
\r
507 * to send the request.
\r
509 InterlockedOr( &p_viport->updates, updates );
\r
510 KeReleaseSpinLock( &p_viport->lock, flags );
\r
512 status = _viport_process_query( p_viport, FALSE );
\r
514 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
521 IN viport_t *p_viport )
\r
523 uint64_t stats_update_ms;
\r
524 NDIS_STATUS status = STATUS_SUCCESS;
\r
526 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
528 stats_update_ms = get_time_stamp_ms();
\r
530 if( stats_update_ms > p_viport->lastStatsTime + p_viport->port_config.statsInterval )
\r
532 p_viport->lastStatsTime = (uint32_t)stats_update_ms;
\r
534 InterlockedOr( &p_viport->updates, NEED_STATS );
\r
535 // TODO: Should the following call be synchronous?
\r
536 status = _viport_process_query( p_viport, TRUE );
\r
537 if ( status != NDIS_STATUS_SUCCESS )
\r
539 VNIC_TRACE( VNIC_DBG_ERROR,
\r
540 ("Query NEED_STATS Failed\n") );
\r
544 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
551 IN viport_t* const p_viport,
\r
552 IN NDIS_PACKET* const p_packet )
\r
554 BOOLEAN status = FALSE;
\r
556 cl_list_item_t *p_list_item;
\r
558 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
560 KeAcquireSpinLock( &p_viport->lock, &flags );
\r
562 if( p_viport->p_adapter->xmitStarted )
\r
564 for( p_list_item = cl_qlist_remove_head( &p_viport->send_pending_list );
\r
565 p_list_item != cl_qlist_end( &p_viport->send_pending_list );
\r
566 p_list_item = cl_qlist_remove_head( &p_viport->send_pending_list ) )
\r
568 status = data_xmitPacket( &p_viport->data,
\r
569 VNIC_PACKET_FROM_LIST_ITEM( p_list_item ));
\r
571 status = data_xmitPacket( &p_viport->data, p_packet );
\r
575 cl_qlist_insert_tail( &p_viport->send_pending_list,
\r
576 VNIC_LIST_ITEM_FROM_PACKET( p_packet ) );
\r
579 KeReleaseSpinLock( &p_viport->lock, flags );
\r
581 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
585 void viport_linkUp(viport_t *p_viport)
\r
587 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
588 InterlockedExchange( &p_viport->p_adapter->carrier, TRUE );
\r
589 NdisMIndicateStatus( p_viport->p_adapter->h_handle,
\r
590 NDIS_STATUS_MEDIA_CONNECT, NULL, 0 );
\r
591 NdisMIndicateStatusComplete( p_viport->p_adapter->h_handle );
\r
592 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
596 void viport_linkDown(viport_t *p_viport)
\r
598 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
599 InterlockedExchange( &p_viport->p_adapter->carrier, FALSE );
\r
600 NdisMIndicateStatus( p_viport->p_adapter->h_handle,
\r
601 NDIS_STATUS_MEDIA_DISCONNECT, NULL, 0 );
\r
602 NdisMIndicateStatusComplete( p_viport->p_adapter->h_handle );
\r
603 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
607 void viport_stopXmit(viport_t *p_viport)
\r
609 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
610 netpath_stopXmit( p_viport->p_netpath );
\r
611 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
615 void viport_restartXmit(viport_t *p_viport)
\r
617 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
618 netpath_restartXmit( p_viport->p_netpath );
\r
619 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
625 IN viport_t *p_viport,
\r
626 IN NDIS_PACKET *p_packet )
\r
628 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
629 netpath_recvPacket(p_viport->p_netpath, p_packet );
\r
630 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
637 IN viport_t *p_viport )
\r
639 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
641 InterlockedExchange( (volatile LONG*)&p_viport->errored, 1 );
\r
643 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
651 viport_t *p_viport = (viport_t *)context;
\r
653 InterlockedExchange( &p_viport->timerActive, FALSE );
\r
654 if( p_viport && p_viport->data.connected )
\r
656 // TODO: What about send failure?
\r
657 control_heartbeatReq( &p_viport->control,
\r
658 p_viport->port_config.hbTimeout );
\r
665 IN viport_t *p_viport,
\r
668 VNIC_ENTER( VNIC_DBG_VIPORT );;
\r
670 InterlockedExchange( &p_viport->timerActive, TRUE );
\r
671 cl_timer_start( &p_viport->timer, (uint32_t)timeout );
\r
673 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
679 IN viport_t *p_viport )
\r
681 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
685 if( InterlockedExchange( &p_viport->timerActive, FALSE ) == TRUE )
\r
687 cl_timer_stop( &p_viport->timer );
\r
691 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
695 static ib_api_status_t
\r
696 viport_initMacAddresses(
\r
697 IN viport_t *p_viport )
\r
701 NDIS_STATUS status;
\r
702 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
704 size = p_viport->numMacAddresses * sizeof(Inic_AddressOp_t);
\r
705 status = NdisAllocateMemoryWithTag( &p_viport->macAddresses, size , 'acam' );
\r
707 if ( status != NDIS_STATUS_SUCCESS )
\r
709 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,
\r
710 ("Failed allocating MAC address table size %d\n", size) );
\r
711 return IB_INSUFFICIENT_MEMORY;
\r
714 NdisZeroMemory( p_viport->macAddresses, size );
\r
716 KeAcquireSpinLock( &p_viport->lock, &flags );
\r
717 for( i = 0; i < p_viport->numMacAddresses; i++ )
\r
719 p_viport->macAddresses[i].index = (uint16_t)i;
\r
720 p_viport->macAddresses[i].vlan = p_viport->defaultVlan;
\r
723 NdisFillMemory( p_viport->macAddresses[BROADCAST_ADDR].address,
\r
724 MAC_ADDR_LEN, 0xFF );
\r
725 p_viport->macAddresses[BROADCAST_ADDR].valid = TRUE;
\r
727 NdisMoveMemory( p_viport->macAddresses[UNICAST_ADDR].address,
\r
728 p_viport->hwMacAddress, MAC_ADDR_LEN );
\r
730 p_viport->macAddresses[UNICAST_ADDR].valid = TRUE;
\r
731 p_viport->p_adapter->macSet = TRUE;
\r
733 KeReleaseSpinLock( &p_viport->lock, flags );
\r
735 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
741 viport_control_connect(
\r
742 IN viport_t* const p_viport )
\r
744 ib_api_status_t ib_status;
\r
746 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
748 ib_status = control_init( &p_viport->control, p_viport,
\r
749 &p_viport->port_config.controlConfig, p_viport->portGuid );
\r
750 if( ib_status != IB_SUCCESS )
\r
752 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
756 ib_status = ibqp_connect( &p_viport->control.qp );
\r
757 if( ib_status != IB_SUCCESS )
\r
759 VNIC_TRACE( VNIC_DBG_INFO,
\r
760 ("control QP connect failed\n"));
\r
764 InterlockedExchange( (volatile LONG*)&p_viport->linkState,
\r
765 (LONG)LINK_INITINICREQ );
\r
767 ib_status = control_initInicReq( &p_viport->control );
\r
768 if( ib_status != IB_SUCCESS )
\r
770 VNIC_TRACE( VNIC_DBG_INFO, ("CMD_INIT_INIC REQ failed\n") );
\r
773 cl_event_wait_on( &p_viport->conn_event,
\r
774 (p_viport->control.p_conf->rspTimeout << 11), TRUE );
\r
776 if( p_viport->linkState != LINK_INITINICRSP )
\r
778 VNIC_TRACE( VNIC_DBG_INFO,
\r
779 ("CMD_INIT_INIC RSP failed\n"));
\r
780 ib_status = IB_INSUFFICIENT_RESOURCES;
\r
784 vnic_resume_oids( p_viport->p_adapter );
\r
786 ib_status = viport_initMacAddresses( p_viport );
\r
787 if( ib_status != IB_SUCCESS )
\r
789 VNIC_TRACE( VNIC_DBG_INFO,
\r
790 ("Init MAC Addresses failed\n"));
\r
792 control_resetReq( &p_viport->control );
\r
794 control_cleanup( &p_viport->control );
\r
797 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
802 viport_data_connect(
\r
803 IN viport_t* const p_viport )
\r
805 NDIS_STATUS status;
\r
806 ib_api_status_t ib_status;
\r
808 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
810 ib_status = data_init( &p_viport->data,
\r
811 &p_viport->port_config.dataConfig,
\r
812 p_viport->portGuid );
\r
813 if( ib_status != IB_SUCCESS )
\r
815 VNIC_TRACE( VNIC_DBG_ERROR, ("Data init returned %s\n",
\r
816 p_viport->p_adapter->ifc.get_err_str( ib_status )) );
\r
819 InterlockedExchange( (volatile LONG*)&p_viport->linkState,
\r
820 (LONG)LINK_CONFIGDATAPATHREQ );
\r
822 ib_status = control_configDataPathReq( &p_viport->control,
\r
823 data_pathId(&p_viport->data ), data_hostPoolMax( &p_viport->data ),
\r
824 data_eiocPoolMax( &p_viport->data ) );
\r
825 if( ib_status != IB_SUCCESS )
\r
827 VNIC_TRACE( VNIC_DBG_ERROR,
\r
828 ("command CONFIGDATAPATH REQ failed\n"));
\r
831 cl_event_wait_on( &p_viport->conn_event,
\r
832 (p_viport->control.p_conf->rspTimeout << 11), TRUE );
\r
834 if( p_viport->linkState != LINK_CONFIGDATAPATHRSP )
\r
836 VNIC_TRACE( VNIC_DBG_ERROR,
\r
837 ("failed to get CONFIGDATAPATH RSP\n"));
\r
838 return IB_INSUFFICIENT_RESOURCES;
\r
841 ib_status = data_connect( &p_viport->data );
\r
842 if( ib_status != IB_SUCCESS )
\r
844 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
847 cl_event_wait_on( &p_viport->conn_event,
\r
848 (p_viport->control.p_conf->rspTimeout << 11), TRUE );
\r
849 if( p_viport->data.qp.qpState != IB_ATTACHED )
\r
851 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
854 InterlockedExchange( (volatile LONG*)&p_viport->linkState,
\r
855 (LONG)LINK_XCHGPOOLREQ );
\r
856 ib_status = control_exchangePoolsReq( &p_viport->control,
\r
857 data_localPoolAddr(&p_viport->data),
\r
858 data_localPoolRkey(&p_viport->data) );
\r
859 if( ib_status != IB_SUCCESS )
\r
861 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,
\r
862 ("command XCHGPOOL REQ failed\n"));
\r
865 cl_event_wait_on( &p_viport->conn_event,
\r
866 (p_viport->control.p_conf->rspTimeout << 11), TRUE );
\r
868 if( p_viport->linkState != LINK_XCHGPOOLRSP )
\r
870 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,
\r
871 ("failed to get LINK_XCHGPOOL RSP\n"));
\r
875 InterlockedExchange( (volatile LONG*)&p_viport->linkState,
\r
876 (LONG)LINK_INITIALIZED );
\r
877 p_viport->state = VIPORT_CONNECTED;
\r
879 data_connected(&p_viport->data);
\r
881 InterlockedExchange( (volatile LONG *)&p_viport->mtu, 1500 );
\r
882 InterlockedExchange( (volatile LONG *)&p_viport->flags, 0 );
\r
883 status = viport_setLink( p_viport, INIC_FLAG_ENABLE_NIC, 1500 );
\r
884 if( status != NDIS_STATUS_SUCCESS )
\r
886 VNIC_TRACE_EXIT( VNIC_DBG_ERROR,
\r
887 ("failed to set Link flags\n"));
\r
891 /* now we have to start periodic heartbeat timer */
\r
892 if( p_viport->port_config.hbInterval )
\r
894 viport_timer( p_viport, p_viport->port_config.hbInterval );
\r
897 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
903 _viport_process_query(
\r
904 IN viport_t* const p_viport,
\r
907 NDIS_STATUS status;
\r
908 ib_api_status_t ib_status;
\r
910 LinkState_t expected_state = 0;
\r
912 VNIC_ENTER( VNIC_DBG_VIPORT );
\r
914 if ( p_viport->state != VIPORT_CONNECTED ||
\r
915 p_viport->errored != 0 )
\r
917 VNIC_TRACE_EXIT( VNIC_DBG_WARN, ("Invalid state or error.\n") );
\r
918 return NDIS_STATUS_NOT_ACCEPTED;
\r
921 // Check for updates. Note that unless sync is set to TRUE, this
\r
922 // is the only way for this function to return success.
\r
923 if( !InterlockedCompareExchange( &p_viport->updates, 0, 0 ) )
\r
925 VNIC_TRACE_EXIT( VNIC_DBG_VIPORT, ("No updates.\n") );
\r
926 return NDIS_STATUS_SUCCESS;
\r
931 status = NDIS_STATUS_SUCCESS;
\r
932 InterlockedOr( &p_viport->updates, SYNC_QUERY );
\r
936 status = NDIS_STATUS_PENDING;
\r
939 // Handle update bits one at a time.
\r
940 if( p_viport->updates & NEED_ADDRESS_CONFIG )
\r
942 VNIC_TRACE( VNIC_DBG_INFO,
\r
943 ("QUERY NEED_ADDRESS_CONFIG\n"));
\r
944 KeAcquireSpinLock(&p_viport->lock, &irql );
\r
945 p_viport->linkState = LINK_CONFIGADDRSREQ;
\r
946 ib_status = control_configAddrsReq(
\r
947 &p_viport->control, p_viport->macAddresses,
\r
948 p_viport->numMacAddresses, &p_viport->addrs_query_done );
\r
949 KeReleaseSpinLock( &p_viport->lock, irql );
\r
950 if ( ib_status != IB_SUCCESS )
\r
952 InterlockedAnd( &p_viport->updates, ~NEED_ADDRESS_CONFIG );
\r
953 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
954 return NDIS_STATUS_FAILURE;
\r
956 expected_state = LINK_CONFIGADDRSRSP;
\r
958 else if( p_viport->updates & NEED_LINK_CONFIG )
\r
960 VNIC_TRACE( VNIC_DBG_INFO,
\r
961 ("QUERY NEED_LINK_CONFIG\n"));
\r
963 KeAcquireSpinLock(&p_viport->lock, &irql );
\r
964 p_viport->linkState = LINK_CONFIGLINKREQ;
\r
966 if( (InterlockedAnd(
\r
967 &p_viport->updates, ~MCAST_OVERFLOW ) & MCAST_OVERFLOW) )
\r
969 p_viport->newFlags |= INIC_FLAG_ENABLE_MCAST_ALL;
\r
973 p_viport->newFlags &= ~INIC_FLAG_ENABLE_MCAST_ALL;
\r
976 if ( p_viport->mtu != p_viport->newMtu )
\r
977 p_viport->mtu = p_viport->newMtu;
\r
979 ib_status = control_configLinkReq( &p_viport->control,
\r
980 p_viport->newFlags, p_viport->mtu );
\r
981 KeReleaseSpinLock( &p_viport->lock, irql );
\r
982 if( ib_status != IB_SUCCESS )
\r
984 InterlockedAnd( &p_viport->updates, ~NEED_LINK_CONFIG );
\r
985 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
986 return NDIS_STATUS_FAILURE;
\r
988 expected_state = LINK_CONFIGLINKRSP;
\r
990 else if( p_viport->updates & NEED_STATS )
\r
992 // TODO: This is dead code.
\r
993 VNIC_TRACE( VNIC_DBG_INFO,
\r
994 ("QUERY NEED_STATS\n"));
\r
996 KeAcquireSpinLock( &p_viport->lock, &irql );
\r
997 p_viport->linkState = LINK_REPORTSTATREQ;
\r
999 ib_status = control_reportStatisticsReq( &p_viport->control );
\r
1000 KeReleaseSpinLock( &p_viport->lock, irql );
\r
1001 if( ib_status != IB_SUCCESS )
\r
1003 InterlockedAnd( &p_viport->updates, ~NEED_STATS );
\r
1004 VNIC_EXIT( VNIC_DBG_VIPORT );
\r
1005 return NDIS_STATUS_FAILURE;
\r
1007 expected_state = LINK_REPORTSTATRSP;
\r
1012 cl_event_wait_on( &p_viport->conn_event, EVENT_NO_TIMEOUT, FALSE );
\r
1014 if( p_viport->linkState != expected_state )
\r
1016 status = NDIS_STATUS_FAILURE;
\r
1017 VNIC_TRACE( VNIC_DBG_ERROR,
\r
1018 ("Link state error: expected %d but got %d\n",
\r
1019 expected_state, p_viport->linkState));
\r
1022 VNIC_EXIT( VNIC_DBG_VIPORT );
\r