提交 0bbed88a 编写于 作者: D David S. Miller

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: NDavid S. Miller <davem@davemloft.net>
...@@ -1080,27 +1080,38 @@ static void ipa_endpoint_replenish(struct ipa_endpoint *endpoint, bool add_one) ...@@ -1080,27 +1080,38 @@ static void ipa_endpoint_replenish(struct ipa_endpoint *endpoint, bool add_one)
{ {
struct gsi *gsi; struct gsi *gsi;
u32 backlog; u32 backlog;
int delta;
if (!endpoint->replenish_enabled) { if (!test_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags)) {
if (add_one) if (add_one)
atomic_inc(&endpoint->replenish_saved); atomic_inc(&endpoint->replenish_saved);
return; 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)) while (atomic_dec_not_zero(&endpoint->replenish_backlog))
if (ipa_endpoint_replenish_one(endpoint)) if (ipa_endpoint_replenish_one(endpoint))
goto try_again_later; goto try_again_later;
clear_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags);
if (add_one) if (add_one)
atomic_inc(&endpoint->replenish_backlog); atomic_inc(&endpoint->replenish_backlog);
return; return;
try_again_later: try_again_later:
/* The last one didn't succeed, so fix the backlog */ clear_bit(IPA_REPLENISH_ACTIVE, endpoint->replenish_flags);
backlog = atomic_inc_return(&endpoint->replenish_backlog);
if (add_one) /* The last one didn't succeed, so fix the backlog */
atomic_inc(&endpoint->replenish_backlog); delta = add_one ? 2 : 1;
backlog = atomic_add_return(delta, &endpoint->replenish_backlog);
/* Whenever a receive buffer transaction completes we'll try to /* Whenever a receive buffer transaction completes we'll try to
* replenish again. It's unlikely, but if we fail to supply even * 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) ...@@ -1120,7 +1131,7 @@ static void ipa_endpoint_replenish_enable(struct ipa_endpoint *endpoint)
u32 max_backlog; u32 max_backlog;
u32 saved; u32 saved;
endpoint->replenish_enabled = true; set_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags);
while ((saved = atomic_xchg(&endpoint->replenish_saved, 0))) while ((saved = atomic_xchg(&endpoint->replenish_saved, 0)))
atomic_add(saved, &endpoint->replenish_backlog); atomic_add(saved, &endpoint->replenish_backlog);
...@@ -1134,7 +1145,7 @@ static void ipa_endpoint_replenish_disable(struct ipa_endpoint *endpoint) ...@@ -1134,7 +1145,7 @@ static void ipa_endpoint_replenish_disable(struct ipa_endpoint *endpoint)
{ {
u32 backlog; u32 backlog;
endpoint->replenish_enabled = false; clear_bit(IPA_REPLENISH_ENABLED, endpoint->replenish_flags);
while ((backlog = atomic_xchg(&endpoint->replenish_backlog, 0))) while ((backlog = atomic_xchg(&endpoint->replenish_backlog, 0)))
atomic_add(backlog, &endpoint->replenish_saved); atomic_add(backlog, &endpoint->replenish_saved);
} }
...@@ -1691,7 +1702,8 @@ static void ipa_endpoint_setup_one(struct ipa_endpoint *endpoint) ...@@ -1691,7 +1702,8 @@ static void ipa_endpoint_setup_one(struct ipa_endpoint *endpoint)
/* RX transactions require a single TRE, so the maximum /* RX transactions require a single TRE, so the maximum
* backlog is the same as the maximum outstanding TREs. * 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, atomic_set(&endpoint->replenish_saved,
gsi_channel_tre_max(gsi, endpoint->channel_id)); gsi_channel_tre_max(gsi, endpoint->channel_id));
atomic_set(&endpoint->replenish_backlog, 0); atomic_set(&endpoint->replenish_backlog, 0);
......
...@@ -40,6 +40,19 @@ enum ipa_endpoint_name { ...@@ -40,6 +40,19 @@ enum ipa_endpoint_name {
#define IPA_ENDPOINT_MAX 32 /* Max supported by driver */ #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 * struct ipa_endpoint - IPA endpoint information
* @ipa: IPA pointer * @ipa: IPA pointer
...@@ -51,7 +64,7 @@ enum ipa_endpoint_name { ...@@ -51,7 +64,7 @@ enum ipa_endpoint_name {
* @trans_tre_max: Maximum number of TRE descriptors per transaction * @trans_tre_max: Maximum number of TRE descriptors per transaction
* @evt_ring_id: GSI event ring used by the endpoint * @evt_ring_id: GSI event ring used by the endpoint
* @netdev: Network device pointer, if endpoint uses one * @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_ready: Number of replenish transactions without doorbell
* @replenish_saved: Replenish requests held while disabled * @replenish_saved: Replenish requests held while disabled
* @replenish_backlog: Number of buffers needed to fill hardware queue * @replenish_backlog: Number of buffers needed to fill hardware queue
...@@ -72,7 +85,7 @@ struct ipa_endpoint { ...@@ -72,7 +85,7 @@ struct ipa_endpoint {
struct net_device *netdev; struct net_device *netdev;
/* Receive buffer replenishing for RX endpoints */ /* Receive buffer replenishing for RX endpoints */
bool replenish_enabled; DECLARE_BITMAP(replenish_flags, IPA_REPLENISH_COUNT);
u32 replenish_ready; u32 replenish_ready;
atomic_t replenish_saved; atomic_t replenish_saved;
atomic_t replenish_backlog; atomic_t replenish_backlog;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册