dp83640: Delay scheduled work.

Currently rx_timestamp_work reschedules itself as a regular workqueue item,
effectively causing it run constantly as long as there are packets left in
the queue. Fix by using delayed workqueue items, limiting it to run only
every two jiffies.

Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Stefan Sørensen 2015-11-03 09:34:05 +01:00 committed by David S. Miller
parent 539e44d268
commit 4b063258ab

View File

@ -69,6 +69,8 @@
/* phyter seems to miss the mark by 16 ns */ /* phyter seems to miss the mark by 16 ns */
#define ADJTIME_FIX 16 #define ADJTIME_FIX 16
#define SKB_TIMESTAMP_TIMEOUT 2 /* jiffies */
#if defined(__BIG_ENDIAN) #if defined(__BIG_ENDIAN)
#define ENDIAN_FLAG 0 #define ENDIAN_FLAG 0
#elif defined(__LITTLE_ENDIAN) #elif defined(__LITTLE_ENDIAN)
@ -111,7 +113,7 @@ struct dp83640_private {
struct list_head list; struct list_head list;
struct dp83640_clock *clock; struct dp83640_clock *clock;
struct phy_device *phydev; struct phy_device *phydev;
struct work_struct ts_work; struct delayed_work ts_work;
int hwts_tx_en; int hwts_tx_en;
int hwts_rx_en; int hwts_rx_en;
int layer; int layer;
@ -285,7 +287,7 @@ static void phy2rxts(struct phy_rxts *p, struct rxts *rxts)
rxts->seqid = p->seqid; rxts->seqid = p->seqid;
rxts->msgtype = (p->msgtype >> 12) & 0xf; rxts->msgtype = (p->msgtype >> 12) & 0xf;
rxts->hash = p->msgtype & 0x0fff; rxts->hash = p->msgtype & 0x0fff;
rxts->tmo = jiffies + 2; rxts->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
} }
static u64 phy2txts(struct phy_txts *p) static u64 phy2txts(struct phy_txts *p)
@ -1115,7 +1117,7 @@ static int dp83640_probe(struct phy_device *phydev)
goto no_memory; goto no_memory;
dp83640->phydev = phydev; dp83640->phydev = phydev;
INIT_WORK(&dp83640->ts_work, rx_timestamp_work); INIT_DELAYED_WORK(&dp83640->ts_work, rx_timestamp_work);
INIT_LIST_HEAD(&dp83640->rxts); INIT_LIST_HEAD(&dp83640->rxts);
INIT_LIST_HEAD(&dp83640->rxpool); INIT_LIST_HEAD(&dp83640->rxpool);
@ -1162,7 +1164,7 @@ static void dp83640_remove(struct phy_device *phydev)
return; return;
enable_status_frames(phydev, false); enable_status_frames(phydev, false);
cancel_work_sync(&dp83640->ts_work); cancel_delayed_work_sync(&dp83640->ts_work);
skb_queue_purge(&dp83640->rx_queue); skb_queue_purge(&dp83640->rx_queue);
skb_queue_purge(&dp83640->tx_queue); skb_queue_purge(&dp83640->tx_queue);
@ -1356,7 +1358,7 @@ static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
static void rx_timestamp_work(struct work_struct *work) static void rx_timestamp_work(struct work_struct *work)
{ {
struct dp83640_private *dp83640 = struct dp83640_private *dp83640 =
container_of(work, struct dp83640_private, ts_work); container_of(work, struct dp83640_private, ts_work.work);
struct sk_buff *skb; struct sk_buff *skb;
/* Deliver expired packets. */ /* Deliver expired packets. */
@ -1373,7 +1375,7 @@ static void rx_timestamp_work(struct work_struct *work)
} }
if (!skb_queue_empty(&dp83640->rx_queue)) if (!skb_queue_empty(&dp83640->rx_queue))
schedule_work(&dp83640->ts_work); schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT);
} }
static bool dp83640_rxtstamp(struct phy_device *phydev, static bool dp83640_rxtstamp(struct phy_device *phydev,
@ -1412,9 +1414,11 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
if (!shhwtstamps) { if (!shhwtstamps) {
skb_info->ptp_type = type; skb_info->ptp_type = type;
skb_info->tmo = jiffies + 2; skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
skb_queue_tail(&dp83640->rx_queue, skb); skb_queue_tail(&dp83640->rx_queue, skb);
schedule_work(&dp83640->ts_work); schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT);
} else {
netif_rx_ni(skb);
} }
return true; return true;