Commit 76d67494 authored by David S. Miller's avatar David S. Miller

Merge branch 'SJA1105-DSA-locking-fixes-for-PTP'

Vladimir Oltean says:

====================
SJA1105 DSA locking fixes for PTP

This series fixes the locking API usage problems spotted when compiling
the kernel with CONFIG_DEBUG_ATOMIC_SLEEP=y and CONFIG_DEBUG_SPINLOCK=y.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d64bf89a 3e8db7e5
...@@ -1897,7 +1897,9 @@ static int sja1105_set_ageing_time(struct dsa_switch *ds, ...@@ -1897,7 +1897,9 @@ static int sja1105_set_ageing_time(struct dsa_switch *ds,
return sja1105_static_config_reload(priv); return sja1105_static_config_reload(priv);
} }
/* Caller must hold priv->tagger_data.meta_lock */ /* Must be called only with priv->tagger_data.state bit
* SJA1105_HWTS_RX_EN cleared
*/
static int sja1105_change_rxtstamping(struct sja1105_private *priv, static int sja1105_change_rxtstamping(struct sja1105_private *priv,
bool on) bool on)
{ {
...@@ -1954,16 +1956,17 @@ static int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, ...@@ -1954,16 +1956,17 @@ static int sja1105_hwtstamp_set(struct dsa_switch *ds, int port,
break; break;
} }
if (rx_on != priv->tagger_data.hwts_rx_en) { if (rx_on != test_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state)) {
spin_lock(&priv->tagger_data.meta_lock); clear_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state);
rc = sja1105_change_rxtstamping(priv, rx_on); rc = sja1105_change_rxtstamping(priv, rx_on);
spin_unlock(&priv->tagger_data.meta_lock);
if (rc < 0) { if (rc < 0) {
dev_err(ds->dev, dev_err(ds->dev,
"Failed to change RX timestamping: %d\n", rc); "Failed to change RX timestamping: %d\n", rc);
return -EFAULT; return rc;
} }
priv->tagger_data.hwts_rx_en = rx_on; if (rx_on)
set_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state);
} }
if (copy_to_user(ifr->ifr_data, &config, sizeof(config))) if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
...@@ -1982,7 +1985,7 @@ static int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, ...@@ -1982,7 +1985,7 @@ static int sja1105_hwtstamp_get(struct dsa_switch *ds, int port,
config.tx_type = HWTSTAMP_TX_ON; config.tx_type = HWTSTAMP_TX_ON;
else else
config.tx_type = HWTSTAMP_TX_OFF; config.tx_type = HWTSTAMP_TX_OFF;
if (priv->tagger_data.hwts_rx_en) if (test_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state))
config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
else else
config.rx_filter = HWTSTAMP_FILTER_NONE; config.rx_filter = HWTSTAMP_FILTER_NONE;
...@@ -2031,7 +2034,7 @@ static bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port, ...@@ -2031,7 +2034,7 @@ static bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
struct sja1105_private *priv = ds->priv; struct sja1105_private *priv = ds->priv;
struct sja1105_tagger_data *data = &priv->tagger_data; struct sja1105_tagger_data *data = &priv->tagger_data;
if (!data->hwts_rx_en) if (!test_bit(SJA1105_HWTS_RX_EN, &data->state))
return false; return false;
/* We need to read the full PTP clock to reconstruct the Rx /* We need to read the full PTP clock to reconstruct the Rx
...@@ -2201,6 +2204,7 @@ static int sja1105_probe(struct spi_device *spi) ...@@ -2201,6 +2204,7 @@ static int sja1105_probe(struct spi_device *spi)
tagger_data = &priv->tagger_data; tagger_data = &priv->tagger_data;
skb_queue_head_init(&tagger_data->skb_rxtstamp_queue); skb_queue_head_init(&tagger_data->skb_rxtstamp_queue);
INIT_WORK(&tagger_data->rxtstamp_work, sja1105_rxtstamp_work); INIT_WORK(&tagger_data->rxtstamp_work, sja1105_rxtstamp_work);
spin_lock_init(&tagger_data->meta_lock);
/* Connections between dsa_port and sja1105_port */ /* Connections between dsa_port and sja1105_port */
for (i = 0; i < SJA1105_NUM_PORTS; i++) { for (i = 0; i < SJA1105_NUM_PORTS; i++) {
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#define SJA1105_META_SMAC 0x222222222222ull #define SJA1105_META_SMAC 0x222222222222ull
#define SJA1105_META_DMAC 0x0180C200000Eull #define SJA1105_META_DMAC 0x0180C200000Eull
#define SJA1105_HWTS_RX_EN 0
/* Global tagger data: each struct sja1105_port has a reference to /* Global tagger data: each struct sja1105_port has a reference to
* the structure defined in struct sja1105_private. * the structure defined in struct sja1105_private.
*/ */
...@@ -42,7 +44,7 @@ struct sja1105_tagger_data { ...@@ -42,7 +44,7 @@ struct sja1105_tagger_data {
* from taggers running on multiple ports on SMP systems * from taggers running on multiple ports on SMP systems
*/ */
spinlock_t meta_lock; spinlock_t meta_lock;
bool hwts_rx_en; unsigned long state;
}; };
struct sja1105_skb_cb { struct sja1105_skb_cb {
......
...@@ -156,7 +156,11 @@ static struct sk_buff ...@@ -156,7 +156,11 @@ static struct sk_buff
/* Step 1: A timestampable frame was received. /* Step 1: A timestampable frame was received.
* Buffer it until we get its meta frame. * Buffer it until we get its meta frame.
*/ */
if (is_link_local && sp->data->hwts_rx_en) { if (is_link_local) {
if (!test_bit(SJA1105_HWTS_RX_EN, &sp->data->state))
/* Do normal processing. */
return skb;
spin_lock(&sp->data->meta_lock); spin_lock(&sp->data->meta_lock);
/* Was this a link-local frame instead of the meta /* Was this a link-local frame instead of the meta
* that we were expecting? * that we were expecting?
...@@ -187,6 +191,12 @@ static struct sk_buff ...@@ -187,6 +191,12 @@ static struct sk_buff
} else if (is_meta) { } else if (is_meta) {
struct sk_buff *stampable_skb; struct sk_buff *stampable_skb;
/* Drop the meta frame if we're not in the right state
* to process it.
*/
if (!test_bit(SJA1105_HWTS_RX_EN, &sp->data->state))
return NULL;
spin_lock(&sp->data->meta_lock); spin_lock(&sp->data->meta_lock);
stampable_skb = sp->data->stampable_skb; stampable_skb = sp->data->stampable_skb;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment