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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
0bbed88af5
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user