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

Merge branch 'ipa-fixes'



Alex Elder says:

====================
net: ipa: fix two replenish bugs

This series contains two fixes for bugs in the IPA receive buffer
replenishing code.  The (new) second patch defines a bitmap to
represent endpoint the replenish enabled flag.  Its purpose is to
prepare for the third patch, which adds an additional flag.

Version 2 of this series uses bitmap operations in the second bug
fix rather than an atomic variable, as suggested by Jakub.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c12837d1 998c0bd2
Loading
Loading
Loading
Loading
+20 −8
Original line number Diff line number Diff line
@@ -1080,27 +1080,38 @@ static void ipa_endpoint_replenish(struct ipa_endpoint *endpoint, bool add_one)
{
	struct gsi *gsi;
	u32 backlog;
	int delta;

	if (!endpoint->replenish_enabled) {
	if (!test_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags)) {
		if (add_one)
			atomic_inc(&endpoint->replenish_saved);
		return;
	}

	/* If already active, just update the backlog */
	if (test_and_set_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags)) {
		if (add_one)
			atomic_inc(&endpoint->replenish_backlog);
		return;
	}

	while (atomic_dec_not_zero(&endpoint->replenish_backlog))
		if (ipa_endpoint_replenish_one(endpoint))
			goto try_again_later;

	clear_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags);

	if (add_one)
		atomic_inc(&endpoint->replenish_backlog);

	return;

try_again_later:
	/* The last one didn't succeed, so fix the backlog */
	backlog = atomic_inc_return(&endpoint->replenish_backlog);
	clear_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags);

	if (add_one)
		atomic_inc(&endpoint->replenish_backlog);
	/* The last one didn't succeed, so fix the backlog */
	delta = add_one ? 2 : 1;
	backlog = atomic_add_return(delta, &endpoint->replenish_backlog);

	/* Whenever a receive buffer transaction completes we'll try to
	 * replenish again.  It's unlikely, but if we fail to supply even
@@ -1120,7 +1131,7 @@ static void ipa_endpoint_replenish_enable(struct ipa_endpoint *endpoint)
	u32 max_backlog;
	u32 saved;

	endpoint->replenish_enabled = true;
	set_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags);
	while ((saved = atomic_xchg(&endpoint->replenish_saved, 0)))
		atomic_add(saved, &endpoint->replenish_backlog);

@@ -1134,7 +1145,7 @@ static void ipa_endpoint_replenish_disable(struct ipa_endpoint *endpoint)
{
	u32 backlog;

	endpoint->replenish_enabled = false;
	clear_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags);
	while ((backlog = atomic_xchg(&endpoint->replenish_backlog, 0)))
		atomic_add(backlog, &endpoint->replenish_saved);
}
@@ -1691,7 +1702,8 @@ static void ipa_endpoint_setup_one(struct ipa_endpoint *endpoint)
		/* RX transactions require a single TRE, so the maximum
		 * backlog is the same as the maximum outstanding TREs.
		 */
		endpoint->replenish_enabled = false;
		clear_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags);
		clear_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags);
		atomic_set(&endpoint->replenish_saved,
			   gsi_channel_tre_max(gsi, endpoint->channel_id));
		atomic_set(&endpoint->replenish_backlog, 0);
+15 −2
Original line number Diff line number Diff line
@@ -40,6 +40,19 @@ enum ipa_endpoint_name {

#define IPA_ENDPOINT_MAX		32	/* Max supported by driver */

/**
 * enum ipa_replenish_flag:	RX buffer replenish flags
 *
 * @IPA_REPLENISH_ENABLED:	Whether receive buffer replenishing is enabled
 * @IPA_REPLENISH_ACTIVE:	Whether replenishing is underway
 * @IPA_REPLENISH_COUNT:	Number of defined replenish flags
 */
enum ipa_replenish_flag {
	IPA_REPLENISH_ENABLED,
	IPA_REPLENISH_ACTIVE,
	IPA_REPLENISH_COUNT,	/* Number of flags (must be last) */
};

/**
 * struct ipa_endpoint - IPA endpoint information
 * @ipa:		IPA pointer
@@ -51,7 +64,7 @@ enum ipa_endpoint_name {
 * @trans_tre_max:	Maximum number of TRE descriptors per transaction
 * @evt_ring_id:	GSI event ring used by the endpoint
 * @netdev:		Network device pointer, if endpoint uses one
 * @replenish_enabled:	Whether receive buffer replenishing is enabled
 * @replenish_flags:	Replenishing state flags
 * @replenish_ready:	Number of replenish transactions without doorbell
 * @replenish_saved:	Replenish requests held while disabled
 * @replenish_backlog:	Number of buffers needed to fill hardware queue
@@ -72,7 +85,7 @@ struct ipa_endpoint {
	struct net_device *netdev;

	/* Receive buffer replenishing for RX endpoints */
	bool replenish_enabled;
	DECLARE_BITMAP(replenish_flags, IPA_REPLENISH_COUNT);
	u32 replenish_ready;
	atomic_t replenish_saved;
	atomic_t replenish_backlog;