diff options
Diffstat (limited to 'drivers/net/dsa/sja1105/sja1105_main.c')
-rw-r--r-- | drivers/net/dsa/sja1105/sja1105_main.c | 231 |
1 files changed, 2 insertions, 229 deletions
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 586974687ba2..2ffe642cf54b 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -506,39 +506,6 @@ static int sja1105_init_l2_policing(struct sja1105_private *priv) return 0; } -static int sja1105_init_avb_params(struct sja1105_private *priv, - bool on) -{ - struct sja1105_avb_params_entry *avb; - struct sja1105_table *table; - - table = &priv->static_config.tables[BLK_IDX_AVB_PARAMS]; - - /* Discard previous AVB Parameters Table */ - if (table->entry_count) { - kfree(table->entries); - table->entry_count = 0; - } - - /* Configure the reception of meta frames only if requested */ - if (!on) - return 0; - - table->entries = kcalloc(SJA1105_MAX_AVB_PARAMS_COUNT, - table->ops->unpacked_entry_size, GFP_KERNEL); - if (!table->entries) - return -ENOMEM; - - table->entry_count = SJA1105_MAX_AVB_PARAMS_COUNT; - - avb = table->entries; - - avb->destmeta = SJA1105_META_DMAC; - avb->srcmeta = SJA1105_META_SMAC; - - return 0; -} - static int sja1105_static_config_load(struct sja1105_private *priv, struct sja1105_dt_port *ports) { @@ -579,9 +546,6 @@ static int sja1105_static_config_load(struct sja1105_private *priv, rc = sja1105_init_general_params(priv); if (rc < 0) return rc; - rc = sja1105_init_avb_params(priv, false); - if (rc < 0) - return rc; /* Send initial configuration to hardware via SPI */ return sja1105_static_config_upload(priv); @@ -1728,8 +1692,6 @@ static void sja1105_teardown(struct dsa_switch *ds) struct sja1105_private *priv = ds->priv; sja1105_tas_teardown(ds); - cancel_work_sync(&priv->tagger_data.rxtstamp_work); - skb_queue_purge(&priv->tagger_data.skb_rxtstamp_queue); sja1105_ptp_clock_unregister(ds); sja1105_static_config_free(&priv->static_config); } @@ -1816,11 +1778,8 @@ static netdev_tx_t sja1105_port_deferred_xmit(struct dsa_switch *ds, int port, { struct sja1105_private *priv = ds->priv; struct sja1105_port *sp = &priv->ports[port]; - struct skb_shared_hwtstamps shwt = {0}; int slot = sp->mgmt_slot; struct sk_buff *clone; - u64 now, ts; - int rc; /* The tragic fact about the switch having 4x2 slots for installing * management routes is that all of them except one are actually @@ -1846,27 +1805,8 @@ static netdev_tx_t sja1105_port_deferred_xmit(struct dsa_switch *ds, int port, if (!clone) goto out; - skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS; - - mutex_lock(&priv->ptp_lock); - - now = priv->tstamp_cc.read(&priv->tstamp_cc); - - rc = sja1105_ptpegr_ts_poll(ds, slot, &ts); - if (rc < 0) { - dev_err(ds->dev, "xmit: timed out polling for tstamp\n"); - kfree_skb(clone); - goto out_unlock_ptp; - } - - ts = sja1105_tstamp_reconstruct(ds, now, ts); - ts = timecounter_cyc2time(&priv->tstamp_tc, ts); - - shwt.hwtstamp = ns_to_ktime(ts); - skb_complete_tx_timestamp(clone, &shwt); + sja1105_ptp_txtstamp_skb(ds, slot, clone); -out_unlock_ptp: - mutex_unlock(&priv->ptp_lock); out: mutex_unlock(&priv->mgmt_lock); return NETDEV_TX_OK; @@ -1896,171 +1836,6 @@ static int sja1105_set_ageing_time(struct dsa_switch *ds, return sja1105_static_config_reload(priv); } -/* Must be called only with priv->tagger_data.state bit - * SJA1105_HWTS_RX_EN cleared - */ -static int sja1105_change_rxtstamping(struct sja1105_private *priv, - bool on) -{ - struct sja1105_general_params_entry *general_params; - struct sja1105_table *table; - int rc; - - table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS]; - general_params = table->entries; - general_params->send_meta1 = on; - general_params->send_meta0 = on; - - rc = sja1105_init_avb_params(priv, on); - if (rc < 0) - return rc; - - /* Initialize the meta state machine to a known state */ - if (priv->tagger_data.stampable_skb) { - kfree_skb(priv->tagger_data.stampable_skb); - priv->tagger_data.stampable_skb = NULL; - } - - return sja1105_static_config_reload(priv); -} - -static int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, - struct ifreq *ifr) -{ - struct sja1105_private *priv = ds->priv; - struct hwtstamp_config config; - bool rx_on; - int rc; - - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - switch (config.tx_type) { - case HWTSTAMP_TX_OFF: - priv->ports[port].hwts_tx_en = false; - break; - case HWTSTAMP_TX_ON: - priv->ports[port].hwts_tx_en = true; - break; - default: - return -ERANGE; - } - - switch (config.rx_filter) { - case HWTSTAMP_FILTER_NONE: - rx_on = false; - break; - default: - rx_on = true; - break; - } - - if (rx_on != test_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state)) { - clear_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state); - - rc = sja1105_change_rxtstamping(priv, rx_on); - if (rc < 0) { - dev_err(ds->dev, - "Failed to change RX timestamping: %d\n", rc); - return rc; - } - if (rx_on) - set_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state); - } - - if (copy_to_user(ifr->ifr_data, &config, sizeof(config))) - return -EFAULT; - return 0; -} - -static int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, - struct ifreq *ifr) -{ - struct sja1105_private *priv = ds->priv; - struct hwtstamp_config config; - - config.flags = 0; - if (priv->ports[port].hwts_tx_en) - config.tx_type = HWTSTAMP_TX_ON; - else - config.tx_type = HWTSTAMP_TX_OFF; - if (test_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state)) - config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; - else - config.rx_filter = HWTSTAMP_FILTER_NONE; - - return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? - -EFAULT : 0; -} - -#define to_tagger(d) \ - container_of((d), struct sja1105_tagger_data, rxtstamp_work) -#define to_sja1105(d) \ - container_of((d), struct sja1105_private, tagger_data) - -static void sja1105_rxtstamp_work(struct work_struct *work) -{ - struct sja1105_tagger_data *data = to_tagger(work); - struct sja1105_private *priv = to_sja1105(data); - struct dsa_switch *ds = priv->ds; - struct sk_buff *skb; - u64 now; - - mutex_lock(&priv->ptp_lock); - - while ((skb = skb_dequeue(&data->skb_rxtstamp_queue)) != NULL) { - struct skb_shared_hwtstamps *shwt = skb_hwtstamps(skb); - u64 ts; - - now = priv->tstamp_cc.read(&priv->tstamp_cc); - - *shwt = (struct skb_shared_hwtstamps) {0}; - - ts = SJA1105_SKB_CB(skb)->meta_tstamp; - ts = sja1105_tstamp_reconstruct(ds, now, ts); - ts = timecounter_cyc2time(&priv->tstamp_tc, ts); - - shwt->hwtstamp = ns_to_ktime(ts); - netif_rx_ni(skb); - } - - mutex_unlock(&priv->ptp_lock); -} - -/* Called from dsa_skb_defer_rx_timestamp */ -static bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port, - struct sk_buff *skb, unsigned int type) -{ - struct sja1105_private *priv = ds->priv; - struct sja1105_tagger_data *data = &priv->tagger_data; - - if (!test_bit(SJA1105_HWTS_RX_EN, &data->state)) - return false; - - /* We need to read the full PTP clock to reconstruct the Rx - * timestamp. For that we need a sleepable context. - */ - skb_queue_tail(&data->skb_rxtstamp_queue, skb); - schedule_work(&data->rxtstamp_work); - return true; -} - -/* Called from dsa_skb_tx_timestamp. This callback is just to make DSA clone - * the skb and have it available in DSA_SKB_CB in the .port_deferred_xmit - * callback, where we will timestamp it synchronously. - */ -static bool sja1105_port_txtstamp(struct dsa_switch *ds, int port, - struct sk_buff *skb, unsigned int type) -{ - struct sja1105_private *priv = ds->priv; - struct sja1105_port *sp = &priv->ports[port]; - - if (!sp->hwts_tx_en) - return false; - - return true; -} - static int sja1105_port_setup_tc(struct dsa_switch *ds, int port, enum tc_setup_type type, void *type_data) @@ -2281,9 +2056,6 @@ static int sja1105_probe(struct spi_device *spi) priv->ds = ds; tagger_data = &priv->tagger_data; - skb_queue_head_init(&tagger_data->skb_rxtstamp_queue); - INIT_WORK(&tagger_data->rxtstamp_work, sja1105_rxtstamp_work); - spin_lock_init(&tagger_data->meta_lock); /* Connections between dsa_port and sja1105_port */ for (i = 0; i < SJA1105_NUM_PORTS; i++) { @@ -2293,6 +2065,7 @@ static int sja1105_probe(struct spi_device *spi) sp->dp = &ds->ports[i]; sp->data = tagger_data; } + mutex_init(&priv->ptp_data.lock); mutex_init(&priv->mgmt_lock); sja1105_tas_setup(ds); |