aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNishanth Menon <nm@ti.com>2018-07-16 14:06:03 -0400
committerJassi Brar <jaswinder.singh@linaro.org>2018-08-03 09:27:41 -0400
commit5ab935e1942bdf8cab192478ac668b1589c47059 (patch)
tree70d0fb04461bf92901dd4eb7c8b6212109745818
parente7474ca1005768bddde2aad6fdd920245357377e (diff)
mailbox: ti-msgmgr: Allocate Rx channel resources only on request
In a much bigger system SoCs, the number of Rx channels can be many and mostly unused based on the system of choice, and not all Rx channels need IRQs and allocating all memory at probe will be inefficient. Some SoCs could have total threads in the 100s and usage would be just 1 Rx thread. Thus, request and map the IRQs and allocate memory only when needed. Since these channels are requested by client drivers on need, our utilization will be optimal. Signed-off-by: Nishanth Menon <nm@ti.com> Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
-rw-r--r--drivers/mailbox/ti-msgmgr.c91
1 files changed, 61 insertions, 30 deletions
diff --git a/drivers/mailbox/ti-msgmgr.c b/drivers/mailbox/ti-msgmgr.c
index 5fe6ce200264..91c955979008 100644
--- a/drivers/mailbox/ti-msgmgr.c
+++ b/drivers/mailbox/ti-msgmgr.c
@@ -311,6 +311,51 @@ static int ti_msgmgr_send_data(struct mbox_chan *chan, void *data)
311} 311}
312 312
313/** 313/**
314 * ti_msgmgr_queue_rx_irq_req() - RX IRQ request
315 * @dev: device pointer
316 * @qinst: Queue instance
317 * @chan: Channel pointer
318 */
319static int ti_msgmgr_queue_rx_irq_req(struct device *dev,
320 struct ti_queue_inst *qinst,
321 struct mbox_chan *chan)
322{
323 int ret = 0;
324 char of_rx_irq_name[7];
325 struct device_node *np;
326
327 snprintf(of_rx_irq_name, sizeof(of_rx_irq_name),
328 "rx_%03d", qinst->queue_id);
329
330 /* Get the IRQ if not found */
331 if (qinst->irq < 0) {
332 np = of_node_get(dev->of_node);
333 if (!np)
334 return -ENODATA;
335 qinst->irq = of_irq_get_byname(np, of_rx_irq_name);
336 of_node_put(np);
337
338 if (qinst->irq < 0) {
339 dev_err(dev,
340 "QID %d PID %d:No IRQ[%s]: %d\n",
341 qinst->queue_id, qinst->proxy_id,
342 of_rx_irq_name, qinst->irq);
343 return qinst->irq;
344 }
345 }
346
347 /* With the expectation that the IRQ might be shared in SoC */
348 ret = request_irq(qinst->irq, ti_msgmgr_queue_rx_interrupt,
349 IRQF_SHARED, qinst->name, chan);
350 if (ret) {
351 dev_err(dev, "Unable to get IRQ %d on %s(res=%d)\n",
352 qinst->irq, qinst->name, ret);
353 }
354
355 return ret;
356}
357
358/**
314 * ti_msgmgr_queue_startup() - Startup queue 359 * ti_msgmgr_queue_startup() - Startup queue
315 * @chan: Channel pointer 360 * @chan: Channel pointer
316 * 361 *
@@ -318,19 +363,21 @@ static int ti_msgmgr_send_data(struct mbox_chan *chan, void *data)
318 */ 363 */
319static int ti_msgmgr_queue_startup(struct mbox_chan *chan) 364static int ti_msgmgr_queue_startup(struct mbox_chan *chan)
320{ 365{
321 struct ti_queue_inst *qinst = chan->con_priv;
322 struct device *dev = chan->mbox->dev; 366 struct device *dev = chan->mbox->dev;
367 struct ti_msgmgr_inst *inst = dev_get_drvdata(dev);
368 struct ti_queue_inst *qinst = chan->con_priv;
369 const struct ti_msgmgr_desc *d = inst->desc;
323 int ret; 370 int ret;
324 371
325 if (!qinst->is_tx) { 372 if (!qinst->is_tx) {
326 /* 373 /* Allocate usage buffer for rx */
327 * With the expectation that the IRQ might be shared in SoC 374 qinst->rx_buff = kzalloc(d->max_message_size, GFP_KERNEL);
328 */ 375 if (!qinst->rx_buff)
329 ret = request_irq(qinst->irq, ti_msgmgr_queue_rx_interrupt, 376 return -ENOMEM;
330 IRQF_SHARED, qinst->name, chan); 377 /* Request IRQ */
378 ret = ti_msgmgr_queue_rx_irq_req(dev, qinst, chan);
331 if (ret) { 379 if (ret) {
332 dev_err(dev, "Unable to get IRQ %d on %s(res=%d)\n", 380 kfree(qinst->rx_buff);
333 qinst->irq, qinst->name, ret);
334 return ret; 381 return ret;
335 } 382 }
336 } 383 }
@@ -346,8 +393,10 @@ static void ti_msgmgr_queue_shutdown(struct mbox_chan *chan)
346{ 393{
347 struct ti_queue_inst *qinst = chan->con_priv; 394 struct ti_queue_inst *qinst = chan->con_priv;
348 395
349 if (!qinst->is_tx) 396 if (!qinst->is_tx) {
350 free_irq(qinst->irq, chan); 397 free_irq(qinst->irq, chan);
398 kfree(qinst->rx_buff);
399 }
351} 400}
352 401
353/** 402/**
@@ -425,27 +474,6 @@ static int ti_msgmgr_queue_setup(int idx, struct device *dev,
425 dev_name(dev), qinst->is_tx ? "tx" : "rx", qinst->queue_id, 474 dev_name(dev), qinst->is_tx ? "tx" : "rx", qinst->queue_id,
426 qinst->proxy_id); 475 qinst->proxy_id);
427 476
428 if (!qinst->is_tx) {
429 char of_rx_irq_name[7];
430
431 snprintf(of_rx_irq_name, sizeof(of_rx_irq_name),
432 "rx_%03d", qinst->queue_id);
433
434 qinst->irq = of_irq_get_byname(np, of_rx_irq_name);
435 if (qinst->irq < 0) {
436 dev_crit(dev,
437 "[%d]QID %d PID %d:No IRQ[%s]: %d\n",
438 idx, qinst->queue_id, qinst->proxy_id,
439 of_rx_irq_name, qinst->irq);
440 return qinst->irq;
441 }
442 /* Allocate usage buffer for rx */
443 qinst->rx_buff = devm_kzalloc(dev,
444 d->max_message_size, GFP_KERNEL);
445 if (!qinst->rx_buff)
446 return -ENOMEM;
447 }
448
449 qinst->queue_buff_start = inst->queue_proxy_region + 477 qinst->queue_buff_start = inst->queue_proxy_region +
450 Q_DATA_OFFSET(qinst->proxy_id, qinst->queue_id, d->data_first_reg); 478 Q_DATA_OFFSET(qinst->proxy_id, qinst->queue_id, d->data_first_reg);
451 qinst->queue_buff_end = inst->queue_proxy_region + 479 qinst->queue_buff_end = inst->queue_proxy_region +
@@ -454,6 +482,9 @@ static int ti_msgmgr_queue_setup(int idx, struct device *dev,
454 Q_STATE_OFFSET(qinst->queue_id); 482 Q_STATE_OFFSET(qinst->queue_id);
455 qinst->chan = chan; 483 qinst->chan = chan;
456 484
485 /* Setup an error value for IRQ - Lazy allocation */
486 qinst->irq = -EINVAL;
487
457 chan->con_priv = qinst; 488 chan->con_priv = qinst;
458 489
459 dev_dbg(dev, "[%d] qidx=%d pidx=%d irq=%d q_s=%p q_e = %p\n", 490 dev_dbg(dev, "[%d] qidx=%d pidx=%d irq=%d q_s=%p q_e = %p\n",