Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: fsl: cpm1: qmc: Introduce functions to change timeslots at runtime

Introduce qmc_chan_{get,set}_ts_info() function to allow timeslots
modification at runtime.

The modification is provided using qmc_chan_set_ts_info() and will be
applied on next qmc_chan_start().
qmc_chan_set_ts_info() must be called with the channel rx and/or tx
stopped.

Signed-off-by: Herve Codina <herve.codina@bootlin.com>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Link: https://lore.kernel.org/r/20231205152116.122512-18-herve.codina@bootlin.com

+61
+51
drivers/soc/fsl/qe/qmc.c
··· 290 290 } 291 291 EXPORT_SYMBOL(qmc_chan_get_info); 292 292 293 + int qmc_chan_get_ts_info(struct qmc_chan *chan, struct qmc_chan_ts_info *ts_info) 294 + { 295 + unsigned long flags; 296 + 297 + spin_lock_irqsave(&chan->ts_lock, flags); 298 + 299 + ts_info->rx_ts_mask_avail = chan->rx_ts_mask_avail; 300 + ts_info->tx_ts_mask_avail = chan->tx_ts_mask_avail; 301 + ts_info->rx_ts_mask = chan->rx_ts_mask; 302 + ts_info->tx_ts_mask = chan->tx_ts_mask; 303 + 304 + spin_unlock_irqrestore(&chan->ts_lock, flags); 305 + 306 + return 0; 307 + } 308 + EXPORT_SYMBOL(qmc_chan_get_ts_info); 309 + 310 + int qmc_chan_set_ts_info(struct qmc_chan *chan, const struct qmc_chan_ts_info *ts_info) 311 + { 312 + unsigned long flags; 313 + int ret; 314 + 315 + /* Only a subset of available timeslots is allowed */ 316 + if ((ts_info->rx_ts_mask & chan->rx_ts_mask_avail) != ts_info->rx_ts_mask) 317 + return -EINVAL; 318 + if ((ts_info->tx_ts_mask & chan->tx_ts_mask_avail) != ts_info->tx_ts_mask) 319 + return -EINVAL; 320 + 321 + /* In case of common rx/tx table, rx/tx masks must be identical */ 322 + if (chan->qmc->is_tsa_64rxtx) { 323 + if (ts_info->rx_ts_mask != ts_info->tx_ts_mask) 324 + return -EINVAL; 325 + } 326 + 327 + spin_lock_irqsave(&chan->ts_lock, flags); 328 + 329 + if ((chan->tx_ts_mask != ts_info->tx_ts_mask && !chan->is_tx_stopped) || 330 + (chan->rx_ts_mask != ts_info->rx_ts_mask && !chan->is_rx_stopped)) { 331 + dev_err(chan->qmc->dev, "Channel rx and/or tx not stopped\n"); 332 + ret = -EBUSY; 333 + } else { 334 + chan->tx_ts_mask = ts_info->tx_ts_mask; 335 + chan->rx_ts_mask = ts_info->rx_ts_mask; 336 + ret = 0; 337 + } 338 + spin_unlock_irqrestore(&chan->ts_lock, flags); 339 + 340 + return ret; 341 + } 342 + EXPORT_SYMBOL(qmc_chan_set_ts_info); 343 + 293 344 int qmc_chan_set_param(struct qmc_chan *chan, const struct qmc_chan_param *param) 294 345 { 295 346 if (param->mode != chan->mode)
+10
include/soc/fsl/qe/qmc.h
··· 40 40 41 41 int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info); 42 42 43 + struct qmc_chan_ts_info { 44 + u64 rx_ts_mask_avail; 45 + u64 tx_ts_mask_avail; 46 + u64 rx_ts_mask; 47 + u64 tx_ts_mask; 48 + }; 49 + 50 + int qmc_chan_get_ts_info(struct qmc_chan *chan, struct qmc_chan_ts_info *ts_info); 51 + int qmc_chan_set_ts_info(struct qmc_chan *chan, const struct qmc_chan_ts_info *ts_info); 52 + 43 53 struct qmc_chan_param { 44 54 enum qmc_mode mode; 45 55 union {