Commit 0e0704bb authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'ch_tlss-fixes'



Vinay Kumar Yadav says:

====================
chelsio/ch_ktls: chelsio inline tls driver bug fixes

This series of patches fix following bugs in Chelsio inline tls driver.
Patch1: kernel panic.
Patch2: connection close issue.
Patch3: tcb close call issue.
Patch4: unnecessary snd_una update.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 61d77358 e8a41555
Loading
Loading
Loading
Loading
+11 −91
Original line number Diff line number Diff line
@@ -349,18 +349,6 @@ static int chcr_set_tcb_field(struct chcr_ktls_info *tx_info, u16 word,
	return cxgb4_ofld_send(tx_info->netdev, skb);
}

/*
 * chcr_ktls_mark_tcb_close: mark tcb state to CLOSE
 * @tx_info - driver specific tls info.
 * return: NET_TX_OK/NET_XMIT_DROP.
 */
static int chcr_ktls_mark_tcb_close(struct chcr_ktls_info *tx_info)
{
	return chcr_set_tcb_field(tx_info, TCB_T_STATE_W,
				  TCB_T_STATE_V(TCB_T_STATE_M),
				  CHCR_TCB_STATE_CLOSED, 1);
}

/*
 * chcr_ktls_dev_del:  call back for tls_dev_del.
 * Remove the tid and l2t entry and close the connection.
@@ -395,8 +383,6 @@ static void chcr_ktls_dev_del(struct net_device *netdev,

	/* clear tid */
	if (tx_info->tid != -1) {
		/* clear tcb state and then release tid */
		chcr_ktls_mark_tcb_close(tx_info);
		cxgb4_remove_tid(&tx_info->adap->tids, tx_info->tx_chan,
				 tx_info->tid, tx_info->ip_family);
	}
@@ -574,7 +560,6 @@ static int chcr_ktls_dev_add(struct net_device *netdev, struct sock *sk,
	return 0;

free_tid:
	chcr_ktls_mark_tcb_close(tx_info);
#if IS_ENABLED(CONFIG_IPV6)
	/* clear clip entry */
	if (tx_info->ip_family == AF_INET6)
@@ -672,10 +657,6 @@ static int chcr_ktls_cpl_act_open_rpl(struct adapter *adap,
	if (tx_info->pending_close) {
		spin_unlock(&tx_info->lock);
		if (!status) {
			/* it's a late success, tcb status is established,
			 * mark it close.
			 */
			chcr_ktls_mark_tcb_close(tx_info);
			cxgb4_remove_tid(&tx_info->adap->tids, tx_info->tx_chan,
					 tid, tx_info->ip_family);
		}
@@ -1663,54 +1644,6 @@ static void chcr_ktls_copy_record_in_skb(struct sk_buff *nskb,
	refcount_add(nskb->truesize, &nskb->sk->sk_wmem_alloc);
}

/*
 * chcr_ktls_update_snd_una:  Reset the SEND_UNA. It will be done to avoid
 * sending the same segment again. It will discard the segment which is before
 * the current tx max.
 * @tx_info - driver specific tls info.
 * @q - TX queue.
 * return: NET_TX_OK/NET_XMIT_DROP.
 */
static int chcr_ktls_update_snd_una(struct chcr_ktls_info *tx_info,
				    struct sge_eth_txq *q)
{
	struct fw_ulptx_wr *wr;
	unsigned int ndesc;
	int credits;
	void *pos;
	u32 len;

	len = sizeof(*wr) + roundup(CHCR_SET_TCB_FIELD_LEN, 16);
	ndesc = DIV_ROUND_UP(len, 64);

	credits = chcr_txq_avail(&q->q) - ndesc;
	if (unlikely(credits < 0)) {
		chcr_eth_txq_stop(q);
		return NETDEV_TX_BUSY;
	}

	pos = &q->q.desc[q->q.pidx];

	wr = pos;
	/* ULPTX wr */
	wr->op_to_compl = htonl(FW_WR_OP_V(FW_ULPTX_WR));
	wr->cookie = 0;
	/* fill len in wr field */
	wr->flowid_len16 = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(len, 16)));

	pos += sizeof(*wr);

	pos = chcr_write_cpl_set_tcb_ulp(tx_info, q, tx_info->tid, pos,
					 TCB_SND_UNA_RAW_W,
					 TCB_SND_UNA_RAW_V(TCB_SND_UNA_RAW_M),
					 TCB_SND_UNA_RAW_V(0), 0);

	chcr_txq_advance(&q->q, ndesc);
	cxgb4_ring_tx_db(tx_info->adap, &q->q, ndesc);

	return 0;
}

/*
 * chcr_end_part_handler: This handler will handle the record which
 * is complete or if record's end part is received. T6 adapter has a issue that
@@ -1735,7 +1668,9 @@ static int chcr_end_part_handler(struct chcr_ktls_info *tx_info,
				 struct sge_eth_txq *q, u32 skb_offset,
				 u32 tls_end_offset, bool last_wr)
{
	bool free_skb_if_tx_fails = false;
	struct sk_buff *nskb = NULL;

	/* check if it is a complete record */
	if (tls_end_offset == record->len) {
		nskb = skb;
@@ -1758,6 +1693,8 @@ static int chcr_end_part_handler(struct chcr_ktls_info *tx_info,

		if (last_wr)
			dev_kfree_skb_any(skb);
		else
			free_skb_if_tx_fails = true;

		last_wr = true;

@@ -1769,6 +1706,8 @@ static int chcr_end_part_handler(struct chcr_ktls_info *tx_info,
				       record->num_frags,
				       (last_wr && tcp_push_no_fin),
				       mss)) {
		if (free_skb_if_tx_fails)
			dev_kfree_skb_any(skb);
		goto out;
	}
	tx_info->prev_seq = record->end_seq;
@@ -1905,11 +1844,6 @@ static int chcr_short_record_handler(struct chcr_ktls_info *tx_info,
			/* reset tcp_seq as per the prior_data_required len */
			tcp_seq -= prior_data_len;
		}
		/* reset snd una, so the middle record won't send the already
		 * sent part.
		 */
		if (chcr_ktls_update_snd_una(tx_info, q))
			goto out;
		atomic64_inc(&tx_info->adap->ch_ktls_stats.ktls_tx_middle_pkts);
	} else {
		atomic64_inc(&tx_info->adap->ch_ktls_stats.ktls_tx_start_pkts);
@@ -2010,12 +1944,11 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
	 * we will send the complete record again.
	 */

	spin_lock_irqsave(&tx_ctx->base.lock, flags);

	do {
		int i;

		cxgb4_reclaim_completed_tx(adap, &q->q, true);
		/* lock taken */
		spin_lock_irqsave(&tx_ctx->base.lock, flags);
		/* fetch the tls record */
		record = tls_get_record(&tx_ctx->base, tcp_seq,
					&tx_info->record_no);
@@ -2074,11 +2007,11 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
						    tls_end_offset, skb_offset,
						    0);

			spin_unlock_irqrestore(&tx_ctx->base.lock, flags);
			if (ret) {
				/* free the refcount taken earlier */
				if (tls_end_offset < data_len)
					dev_kfree_skb_any(skb);
				spin_unlock_irqrestore(&tx_ctx->base.lock, flags);
				goto out;
			}

@@ -2088,16 +2021,6 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
			continue;
		}

		/* increase page reference count of the record, so that there
		 * won't be any chance of page free in middle if in case stack
		 * receives ACK and try to delete the record.
		 */
		for (i = 0; i < record->num_frags; i++)
			__skb_frag_ref(&record->frags[i]);
		/* lock cleared */
		spin_unlock_irqrestore(&tx_ctx->base.lock, flags);


		/* if a tls record is finishing in this SKB */
		if (tls_end_offset <= data_len) {
			ret = chcr_end_part_handler(tx_info, skb, record,
@@ -2122,13 +2045,9 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)
			data_len = 0;
		}

		/* clear the frag ref count which increased locally before */
		for (i = 0; i < record->num_frags; i++) {
			/* clear the frag ref count */
			__skb_frag_unref(&record->frags[i]);
		}
		/* if any failure, come out from the loop. */
		if (ret) {
			spin_unlock_irqrestore(&tx_ctx->base.lock, flags);
			if (th->fin)
				dev_kfree_skb_any(skb);

@@ -2143,6 +2062,7 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev)

	} while (data_len > 0);

	spin_unlock_irqrestore(&tx_ctx->base.lock, flags);
	atomic64_inc(&port_stats->ktls_tx_encrypted_packets);
	atomic64_add(skb_data_len, &port_stats->ktls_tx_encrypted_bytes);