lm_l4tx.c revision d14abf155341d55053c76eeec58b787a456b753b
#include "lm5710.h"
#include "bd_chain.h"
#include "command.h"
#include "context.h"
#include "lm_l4fp.h"
#include "lm_l4sp.h"
#include "mm_l4if.h"
/* TODO: remove this temporary solution for solaris / linux compilation conflict, linux needs the
* first option, solaris the latter */
#if defined(__LINUX)
#define TOE_TX_INIT_ZERO {{0}}
#else
#define TOE_TX_INIT_ZERO {0}
#endif
} while(0)
static __inline void _lm_tcp_tx_write_db(
lm_device_t * pdev,
{
if(fin) {
}
"ringing tx doorbell: cid=%d, (nbytes+=%d, nbds+=%d, fin=%d)\n",
}
}
static __inline void lm_tcp_tx_write_db(
{
/* define a policy for ringing the doorbell */
#define MAX_BYTES_PER_TX_DB 0xffff
#define MAX_BDS_PER_TX_DB 64
if (post_end ||
/* assert if the new addition will make the cyclic counter post_cnt smaller than comp_cnt */
} else {
}
}
/** Description:
* Post a single tcp buffer to the Tx bd chain
* Assumptions:
* - caller initiated tcp_buf->flags field with BUFFER_START/BUFFER_END appropriately
* Returns:
* - SUCCESS - tcp buf was successfully attached to the bd chain
* - RESOURCE - not enough available BDs on bd chain for given tcp buf
* - CONNECTION_CLOSED - whenever connection's flag are marked as 'POST BLOCKED' */
struct _lm_device_t *pdev,
{
u32_t i, dbg_buf_size = 0;
/* check if tx con is already closed */
return LM_STATUS_CONNECTION_CLOSED;
}
/* check bd chain availability (including additional bd that should
* be kept available for future fin request) */
DbgMessage(pdev, INFORMl4tx, "post tx buf failed, tx chain is full (cid=%d, avail bds=%d, buf nfrags=%d)\n",
if (tx_con->db_more_bds) {
/* if doorbell ringing was deferred (e.g. until an end of
* application buffer), it can no longer be deferred since
* the place in the bd chain is now required */
}
return LM_STATUS_RESOURCE;
}
/* "attach" the frags to the bd chain */
DbgBreakIf(frag->size > 0xffff || frag->size == 0); /* hw limit: each bd can point to a buffer with max size of 64KB */
/* Support for FW Nagle Algorithm:
* This bit, is to be set for every bd which is part of a tcp buffer which is equal to or larger than an mss.
*/
}
}
tx_con->app_buf_bytes_acc_post == 0 :
tx_con->app_buf_bytes_acc_post > 0));
tx_con->db_more_bufs++;
/* Support for FW Nagle Algorithm:
* This bit, is to be set for every bd which is part of a tcp buffer which is equal to or larger than an mss.
*/
}
/* special care in case of last tcp buffer of an application buffer */
tx_con->app_buf_bytes_acc_post = 0;
/* special care for the last bd: */
} else {
/* make sure there aren't 'too many' bds without completion flag */
}
}
/* network reachability (NOT IMPLEMENTED):
if(lm_neigh_is_cache_entry_staled(tcp->path->neigh))
lm_neigh_indicate_staled_cache_entry(tcp->path->neigh);
*/
DbgMessage(pdev, VERBOSEl4tx, "posted tx buf for cid=%d, buf size=%d, bd used=%d, buf flags=%x, app_buf_size=%d\n",
return LM_STATUS_SUCCESS;
} /* lm_tcp_tx_post_buf */
/** Description
* indicates graceful disconnect completion to client.
* Assumtpions:
* tx-lock is taken by caller
*/
static __inline void lm_tcp_tx_graceful_disconnect_complete(lm_device_t * pdev, lm_tcp_state_t * tcp)
{
ip_version = (tcp->path->path_const.ip_version == IP_VERSION_IPV4)? STATS_IP_4_IDX : STATS_IP_6_IDX;
}
}
void lm_tcp_tx_cmp_process(
struct _lm_device_t *pdev,
)
{
u32_t actual_completed; /* number of bytes actually completed (could be different than completed in case of fin) */
}
if (actual_completed != completed_bytes) {
/* fin completed */
}
/* network reachability (NOT IMPLEMENTED):
lm_neigh_update_nic_reachability_time(tcp->path->neigh)
*/
}
} /* lm_tcp_tx_app_cmp_process */
{
if ( scq->hw_con_idx_ptr &&
{
}
DbgMessage(pdev, INFORMl4int, "lm_toe_is_tx_completion(): result is:%s\n", result? "TRUE" : "FALSE");
return result;
}
struct _lm_device_t *pdev,
)
{
}
}
} /* lm_tcp_tx_inc_aborted_count */
/** Description
* completes the fast-path operations for a certain connection
* Assumption:
* fp-tx lock is taken
*/
{
/**** Client completing : may result in lock-release *****/
/* during lock-release, due to this function being called from service_deferred, more
* cqes can be processed. We don't want to mix. This function is mutually exclusive, so
* any processing makes it's way to being completed by calling this function.
* the following define a "fast-path completion"
* (i) RQ buffers to be completed
* defined by dpc_completed_tail and are collected during lm_tcp_complete_bufs BEFORE lock
* is released, so no more buffer processing can make it's way into this buffer completion.
* (ii) Fin to be completed
* determined by the flags, since dpc_flags CAN be modified during processing we copy
* them to a snapshot_flags parameter, which is initialized in this function only, so no fin
* can can make its way in while we release the lock.
* (iv) Remainders for sp
* all sp operations are logged in dpc_flags. for the same reason as (iii) no sp commands can
* make their way in during this fp-completion, all sp-processing after will relate to this point in time.
*/
/* complete buffers to client */
}
/* Graceful Disconnect */
}
}
void lm_tcp_tx_process_cqe(
lm_device_t * pdev,
struct toe_tx_cqe * cqe,
)
{
enum toe_sq_opcode_type cmd;
/* get the cmd from cqe */
/* Check that the cqe len make sense, we could have got here by chance... */
DbgBreakIfAll(cqe->len & 0xc0000000); /* two upper bits on show a completion larger than 1GB - a bit odd...*/
/* Three types of completios: fast-path, reset-recv, ramrod-cmp. All completions may have a
* fast-path part (nbytes completed) which will be handled in any case that cqe->len > 0 */
/* complete data if anything needs to be complete */
((tcp->tx_con->dpc_info.dpc_flags & LM_TCP_DPC_RESET_RECV /* RST recv on this DPC on a previous CQE */ ) ||
{
/* 10/28/08 - Since in exterme cases current FW may not complete all sent+acked bytes
on RST recv cqe and do so only later on one of the following ramrod completions,
we need to ignore this too late completed bytes thus we nullify cqe->len */
(cmd != RAMROD_OPCODE_TOE_INVALIDATE) &&
(cmd != RAMROD_OPCODE_TOE_EMPTY_RAMROD) &&
(cmd != RAMROD_OPCODE_TOE_TERMINATE));
}
}
switch(cmd) {
case CMP_OPCODE_TOE_TX_CMP:
break;
case CMP_OPCODE_TOE_RST_RCV:
break;
break;
break;
break;
break;
default:
}
}
/** Description
*
* Assumptions
* connections is initialzed with a dummy head.
*/
{
u16_t num_to_reproduce = 0;
/* save statistics */
}
/* we don't want to wrap around...*/
scq->avg_dpc_cnt = 0;
scq->sum_cqes_last_x_dpcs = 0;
}
scq->avg_dpc_cnt++;
if (avg_dpc_cnt) {
} else {
scq->sum_cqes_last_x_dpcs = 0;
}
}
while(cq_old_idx != cq_new_idx) {
/* get next consumed cqe */
DbgBreakIf(!cqe);
/* get tcp state from cqe */
DbgBreakIf(!tcp);
/* save cqe in history_cqes */
if (defer_cqe) {
/* if we're deferring completions - just store the cqe and continue to the next one */
/* Return if we are still deferred (may have changed since initial check was w/o a lock */
/* check again under lock if we're deferred */
if (defer_cqe) {
}
}
if (!defer_cqe) {
/* connections will always be initialized to a dummy, so once a tcp connection is added to the
* list, it's link will be initialized to point to another link other than NULL */
}
}
/* GilR 5/12/2006 - TODO - decide with Alon if reading the hw_con again is required */
//cq_new_idx = *(scq->hw_con_idx_ptr);
}
/* The fact that we post the producer here before we've handled any slow-path completions assures that
* the sp-ring will always be updated AFTER the producer was. */
if (num_to_reproduce) {
/* GilR 5/13/2006 - TBA - save some stats? */
/* notify the fw of the prod of the SCQ */
LM_INTMEM_WRITE16(pdev, CSTORM_TOE_CQ_PROD_OFFSET(LM_TOE_FW_RSS_ID(pdev,drv_toe_rss_id) , PORT_ID(pdev)),
}
}
{
lm_tcp_con_t * con;
/* process the cqes and initialize connections with all the connections that appeared
* in the DPC */
}
/* SP : traverse the connections. remember to ignore the last one */
while (s_list_entry_cnt(&connections) > 0) {
/* we access snapshot and not dpc, since once the dpc_flags were copied
* to snapshot they were zeroized */
}
}
}
)
{
return LM_STATUS_CONNECTION_CLOSED;
}
(tcp_con->db_more_bytes != 0) ||
(tcp_con->db_more_bds != 0) ||
);
/* Post FIN BD on Tx chain */
line - there is an assignment to flags, NOT bitwise OR */
/* For a safety */
/* Update fin request time, if not already set by the caller */
}
}
/* Doorbell FIN */
/* assert if the new addition will make the cyclic counter post_cnt smaller than comp_cnt */
return LM_STATUS_SUCCESS;
}