Loading drivers/slimbus/slim-msm-ctrl.c +14 −12 Original line number Diff line number Diff line /* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -207,8 +207,7 @@ static irqreturn_t msm_slim_interrupt(int irq, void *d) * signalling completion/exiting ISR */ mb(); if (dev->wr_comp) complete(dev->wr_comp); msm_slim_manage_tx_msgq(dev, false, NULL); } if (stat & MGR_INT_RX_MSG_RCVD) { u32 rx_buf[10]; Loading Loading @@ -372,8 +371,7 @@ static int msm_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) } } txn->rl--; pbuf = msm_get_msg_buf(dev, txn->rl); dev->wr_comp = NULL; pbuf = msm_get_msg_buf(dev, txn->rl, &done); dev->err = 0; if (txn->dt == SLIM_MSG_DEST_ENUMADDR) { Loading Loading @@ -438,11 +436,8 @@ static int msm_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) if (txn->mt == SLIM_MSG_MT_CORE && mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION) dev->reconf_busy = true; dev->wr_comp = &done; msm_send_msg_buf(dev, pbuf, txn->rl, MGR_TX_MSG); timeout = wait_for_completion_timeout(&done, HZ); if (!timeout) dev->wr_comp = NULL; if (mc == SLIM_MSG_MC_RECONFIGURE_NOW) { if ((txn->mc == (SLIM_MSG_MC_RECONFIGURE_NOW | SLIM_MSG_CLK_PAUSE_SEQ_FLG)) && Loading Loading @@ -505,7 +500,9 @@ static int msm_set_laddr(struct slim_controller *ctrl, const u8 *ea, retry_laddr: init_completion(&done); mutex_lock(&dev->tx_lock); buf = msm_get_msg_buf(dev, 9); buf = msm_get_msg_buf(dev, 9, &done); if (buf == NULL) return -ENOMEM; buf[0] = SLIM_MSG_ASM_FIRST_WORD(9, SLIM_MSG_MT_CORE, SLIM_MSG_MC_ASSIGN_LOGICAL_ADDRESS, SLIM_MSG_DEST_LOGICALADDR, Loading @@ -513,7 +510,6 @@ retry_laddr: buf[1] = ea[3] | (ea[2] << 8) | (ea[1] << 16) | (ea[0] << 24); buf[2] = laddr; dev->wr_comp = &done; ret = msm_send_msg_buf(dev, buf, 9, MGR_TX_MSG); timeout = wait_for_completion_timeout(&done, HZ); if (!timeout) Loading @@ -521,7 +517,6 @@ retry_laddr: if (dev->err) { ret = dev->err; dev->err = 0; dev->wr_comp = NULL; } mutex_unlock(&dev->tx_lock); if (ret) { Loading Loading @@ -1183,6 +1178,10 @@ static int msm_slim_probe(struct platform_device *pdev) ret = -ENOMEM; goto err_get_res_failed; } dev->wr_comp = kzalloc(sizeof(struct completion *) * MSM_TX_BUFS, GFP_KERNEL); if (!dev->wr_comp) return -ENOMEM; dev->dev = &pdev->dev; platform_set_drvdata(pdev, dev); slim_set_ctrldata(&dev->ctrl, dev); Loading Loading @@ -1271,7 +1270,8 @@ static int msm_slim_probe(struct platform_device *pdev) dev->ctrl.dev.parent = &pdev->dev; dev->ctrl.dev.of_node = pdev->dev.of_node; ret = request_irq(dev->irq, msm_slim_interrupt, IRQF_TRIGGER_HIGH, ret = request_threaded_irq(dev->irq, NULL, msm_slim_interrupt, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "msm_slim_irq", dev); if (ret) { dev_err(&pdev->dev, "request IRQ failed\n"); Loading Loading @@ -1400,6 +1400,7 @@ err_of_init_failed: err_ioremap_bam_failed: iounmap(dev->base); err_ioremap_failed: kfree(dev->wr_comp); kfree(dev); err_get_res_failed: release_mem_region(bam_mem->start, resource_size(bam_mem)); Loading Loading @@ -1437,6 +1438,7 @@ static int msm_slim_remove(struct platform_device *pdev) kthread_stop(dev->rx_msgq_thread); iounmap(dev->bam.base); iounmap(dev->base); kfree(dev->wr_comp); kfree(dev); bam_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "slimbus_bam_physical"); Loading drivers/slimbus/slim-msm-ngd.c +33 −10 Original line number Diff line number Diff line Loading @@ -101,15 +101,13 @@ static irqreturn_t ngd_slim_interrupt(int irq, void *d) dev->err); /* Guarantee that error interrupts are cleared */ mb(); if (dev->wr_comp) complete(dev->wr_comp); msm_slim_manage_tx_msgq(dev, false, NULL); } else if (stat & NGD_INT_TX_MSG_SENT) { writel_relaxed(NGD_INT_TX_MSG_SENT, ngd + NGD_INT_CLR); /* Make sure interrupt is cleared */ mb(); if (dev->wr_comp) complete(dev->wr_comp); msm_slim_manage_tx_msgq(dev, false, NULL); } if (stat & NGD_INT_RX_MSG_RCVD) { u32 rx_buf[10]; Loading Loading @@ -286,6 +284,7 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) u16 txn_mc = txn->mc; u8 wbuf[SLIM_MSGQ_BUF_LEN]; bool report_sat = false; bool sync_wr = true; if (txn->mc == SLIM_USR_MC_REPORT_SATELLITE && txn->mt == SLIM_MSG_MT_SRC_REFERRED_USER) Loading Loading @@ -439,7 +438,25 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) txn->rl = txn->len + 4; } txn->rl--; pbuf = msm_get_msg_buf(dev, txn->rl); if (txn->mt == SLIM_MSG_MT_CORE && txn->comp && dev->use_tx_msgqs == MSM_MSGQ_ENABLED && (txn_mc != SLIM_MSG_MC_REQUEST_INFORMATION && txn_mc != SLIM_MSG_MC_REQUEST_VALUE && txn_mc != SLIM_MSG_MC_REQUEST_CHANGE_VALUE && txn_mc != SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION)) { sync_wr = false; pbuf = msm_get_msg_buf(dev, txn->rl, txn->comp); } else if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER && dev->use_tx_msgqs == MSM_MSGQ_ENABLED && txn->mc == SLIM_USR_MC_REPEAT_CHANGE_VALUE && txn->comp) { sync_wr = false; pbuf = msm_get_msg_buf(dev, txn->rl, txn->comp); } else { pbuf = msm_get_msg_buf(dev, txn->rl, &tx_sent); } if (!pbuf) { SLIM_ERR(dev, "Message buffer unavailable\n"); ret = -ENOMEM; Loading Loading @@ -510,10 +527,9 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) */ txn_mc = txn->mc; txn_mt = txn->mt; dev->wr_comp = &tx_sent; ret = msm_send_msg_buf(dev, pbuf, txn->rl, NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG); if (!ret) { if (!ret && sync_wr) { int timeout = wait_for_completion_timeout(&tx_sent, HZ); if (!timeout) { ret = -ETIMEDOUT; Loading @@ -529,7 +545,6 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) ret = dev->err; } } dev->wr_comp = NULL; if (ret) { u32 conf, stat, rx_msgq, int_stat, int_en, int_clr; void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr, Loading Loading @@ -1296,6 +1311,10 @@ static int ngd_slim_probe(struct platform_device *pdev) dev_err(&pdev->dev, "no memory for MSM slimbus controller\n"); return PTR_ERR(dev); } dev->wr_comp = kzalloc(sizeof(struct completion *) * MSM_TX_BUFS, GFP_KERNEL); if (!dev->wr_comp) return -ENOMEM; dev->dev = &pdev->dev; platform_set_drvdata(pdev, dev); slim_set_ctrldata(&dev->ctrl, dev); Loading Loading @@ -1379,6 +1398,7 @@ static int ngd_slim_probe(struct platform_device *pdev) init_completion(&dev->reconf); init_completion(&dev->ctrl_up); mutex_init(&dev->tx_lock); mutex_init(&dev->tx_buf_lock); spin_lock_init(&dev->rx_lock); dev->ee = 1; dev->irq = irq->start; Loading Loading @@ -1406,8 +1426,9 @@ static int ngd_slim_probe(struct platform_device *pdev) dev->ctrl.dev.of_node = pdev->dev.of_node; dev->state = MSM_CTRL_DOWN; ret = request_irq(dev->irq, ngd_slim_interrupt, IRQF_TRIGGER_HIGH, "ngd_slim_irq", dev); ret = request_threaded_irq(dev->irq, NULL, ngd_slim_interrupt, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "ngd_slim_irq", dev); if (ret) { dev_err(&pdev->dev, "request IRQ failed\n"); Loading Loading @@ -1470,6 +1491,7 @@ err_ioremap_failed: if (dev->sysfs_created) sysfs_remove_file(&dev->dev->kobj, &dev_attr_debug_mask.attr); kfree(dev->wr_comp); kfree(dev); return ret; } Loading @@ -1492,6 +1514,7 @@ static int ngd_slim_remove(struct platform_device *pdev) kthread_stop(dev->rx_msgq_thread); iounmap(dev->bam.base); iounmap(dev->base); kfree(dev->wr_comp); kfree(dev); return 0; } Loading drivers/slimbus/slim-msm.c +110 −22 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ */ #include <linux/pm_runtime.h> #include <linux/dma-mapping.h> #include <linux/delay.h> #include <linux/slimbus/slimbus.h> #include <linux/msm-sps.h> #include "slim-msm.h" Loading Loading @@ -390,9 +391,9 @@ static int msm_slim_post_tx_msgq(struct msm_slim_ctrl *dev, u8 *buf, int len) struct msm_slim_endp *endpoint = &dev->tx_msgq; struct sps_mem_buffer *mem = &endpoint->buf; struct sps_pipe *pipe = endpoint->sps; int ix = (buf - (u8 *)mem->base) / SLIM_MSGQ_BUF_LEN; int ix = (buf - (u8 *)mem->base); phys_addr_t phys_addr = mem->phys_base + (SLIM_MSGQ_BUF_LEN * ix); phys_addr_t phys_addr = mem->phys_base + ix; for (ret = 0; ret < ((len + 3) >> 2); ret++) pr_debug("BAM TX buf[%d]:0x%x", ret, ((u32 *)buf)[ret]); Loading @@ -405,29 +406,110 @@ static int msm_slim_post_tx_msgq(struct msm_slim_ctrl *dev, u8 *buf, int len) return ret; } static u32 *msm_slim_tx_msgq_return(struct msm_slim_ctrl *dev) void msm_slim_tx_msg_return(struct msm_slim_ctrl *dev) { struct msm_slim_endp *endpoint = &dev->tx_msgq; struct sps_mem_buffer *mem = &endpoint->buf; struct sps_pipe *pipe = endpoint->sps; struct sps_iovec iovec; int ret; /* first transaction after establishing connection */ if (dev->tx_idx == -1) { dev->tx_idx = 0; return mem->base; int idx, ret = 0; if (dev->use_tx_msgqs != MSM_MSGQ_ENABLED) { /* use 1 buffer, non-blocking writes are not possible */ if (dev->wr_comp[0]) { struct completion *comp = dev->wr_comp[0]; dev->wr_comp[0] = NULL; complete(comp); } return; } while (!ret) { ret = sps_get_iovec(pipe, &iovec); if (ret || iovec.addr == 0) { dev_err(dev->dev, "sps_get_iovec() failed 0x%x\n", ret); if (ret) pr_err("SLIM TX get IOVEC failed:%d", ret); return; } idx = (int) ((iovec.addr - mem->phys_base) / SLIM_MSGQ_BUF_LEN); if (idx < MSM_TX_BUFS && dev->wr_comp[idx]) { struct completion *comp = dev->wr_comp[idx]; dev->wr_comp[idx] = NULL; complete(comp); } /* reclaim all packets that were delivered out of order */ if (idx != dev->tx_head) pr_err("SLIM OUT OF ORDER TX:idx:%d, head:%d", idx, dev->tx_head); while (idx == dev->tx_head) { dev->tx_head = (dev->tx_head + 1) % MSM_TX_BUFS; idx++; if (dev->tx_head == dev->tx_tail || dev->wr_comp[idx] != NULL) break; } } } static u32 *msm_slim_modify_tx_buf(struct msm_slim_ctrl *dev, struct completion *comp) { struct msm_slim_endp *endpoint = &dev->tx_msgq; struct sps_mem_buffer *mem = &endpoint->buf; u32 *retbuf = NULL; if ((dev->tx_tail + 1) % MSM_TX_BUFS == dev->tx_head) return NULL; retbuf = (u32 *)((u8 *)mem->base + (dev->tx_tail * SLIM_MSGQ_BUF_LEN)); dev->wr_comp[dev->tx_tail] = comp; dev->tx_tail = (dev->tx_tail + 1) % MSM_TX_BUFS; return retbuf; } u32 *msm_slim_manage_tx_msgq(struct msm_slim_ctrl *dev, bool getbuf, struct completion *comp) { int ret = 0; int retries = 0; u32 *retbuf = NULL; /* Calculate buffer index */ dev->tx_idx = ((int)(iovec.addr - mem->phys_base)) / SLIM_MSGQ_BUF_LEN; mutex_lock(&dev->tx_buf_lock); if (!getbuf) { msm_slim_tx_msg_return(dev); mutex_unlock(&dev->tx_buf_lock); return NULL; } retbuf = msm_slim_modify_tx_buf(dev, comp); if (retbuf) { mutex_unlock(&dev->tx_buf_lock); return retbuf; } return (u32 *)((u8 *)mem->base + (dev->tx_idx * SLIM_MSGQ_BUF_LEN)); do { msm_slim_tx_msg_return(dev); retbuf = msm_slim_modify_tx_buf(dev, comp); if (!retbuf) ret = -EAGAIN; else { if (retries > 0) SLIM_INFO(dev, "SLIM TX retrieved:%d retries", retries); mutex_unlock(&dev->tx_buf_lock); return retbuf; } /* * superframe size will vary based on clock gear * 1 superframe will consume at least 1 message * if HW is in good condition. With MX_RETRIES, * make sure we wait for a [3, 10] superframes * before deciding HW couldn't process descriptors */ usleep_range(100, 250); retries++; } while (ret && (retries < INIT_MX_RETRIES)); mutex_unlock(&dev->tx_buf_lock); return NULL; } int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg) Loading @@ -445,16 +527,19 @@ int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg) return msm_slim_post_tx_msgq(dev, (u8 *)buf, len); } u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len) u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len, struct completion *comp) { /* * Currently we block a transaction until the current one completes. * In case we need multiple transactions, use message Q */ if (dev->use_tx_msgqs != MSM_MSGQ_ENABLED) if (dev->use_tx_msgqs != MSM_MSGQ_ENABLED) { dev->wr_comp[0] = comp; return dev->tx_buf; } return msm_slim_tx_msgq_return(dev); return msm_slim_manage_tx_msgq(dev, true, comp); } static void Loading Loading @@ -604,7 +689,8 @@ int msm_slim_connect_endp(struct msm_slim_ctrl *dev, } dev->use_rx_msgqs = MSM_MSGQ_ENABLED; } else { dev->tx_idx = -1; dev->tx_tail = 0; dev->tx_head = 0; dev->use_tx_msgqs = MSM_MSGQ_ENABLED; } Loading Loading @@ -711,16 +797,18 @@ static int msm_slim_init_tx_msgq(struct msm_slim_ctrl *dev, u32 pipe_reg) config->options = SPS_O_ERROR | SPS_O_NO_Q | SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE; /* Desc and TX buf are circular queues */ /* Allocate memory for the FIFO descriptors */ ret = msm_slim_sps_mem_alloc(dev, descr, MSM_TX_BUFS * sizeof(struct sps_iovec)); (MSM_TX_BUFS + 1) * sizeof(struct sps_iovec)); if (ret) { dev_err(dev->dev, "unable to allocate SPS descriptors\n"); goto alloc_descr_failed; } /* Allocate memory for the message buffer(s), N descrs, 40-byte mesg */ ret = msm_slim_sps_mem_alloc(dev, mem, MSM_TX_BUFS * SLIM_MSGQ_BUF_LEN); /* Allocate TX buffer from which descriptors are created */ ret = msm_slim_sps_mem_alloc(dev, mem, ((MSM_TX_BUFS + 1) * SLIM_MSGQ_BUF_LEN)); if (ret) { dev_err(dev->dev, "dma_alloc_coherent failed\n"); goto alloc_buffer_failed; Loading drivers/slimbus/slim-msm.h +9 −4 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ /* Per spec.max 40 bytes per received message */ #define SLIM_MSGQ_BUF_LEN 40 #define MSM_TX_BUFS 2 #define MSM_TX_BUFS 32 #define SLIM_USR_MC_GENERIC_ACK 0x25 #define SLIM_USR_MC_MASTER_CAPABILITY 0x0 Loading Loading @@ -236,14 +236,15 @@ struct msm_slim_ctrl { u8 msg_cnt; u32 tx_buf[10]; u8 rx_msgs[MSM_CONCUR_MSG][SLIM_MSGQ_BUF_LEN]; int tx_idx; int tx_tail; int tx_head; spinlock_t rx_lock; int head; int tail; int irq; int err; int ee; struct completion *wr_comp; struct completion **wr_comp; struct msm_slim_sat *satd[MSM_MAX_NSATS]; struct msm_slim_endp pipes[7]; struct msm_slim_sps_bam bam; Loading @@ -254,6 +255,7 @@ struct msm_slim_ctrl { struct clk *rclk; struct clk *hclk; struct mutex tx_lock; struct mutex tx_buf_lock; u8 pgdla; enum msm_slim_msgq use_rx_msgqs; enum msm_slim_msgq use_tx_msgqs; Loading Loading @@ -372,7 +374,10 @@ enum slim_port_err msm_slim_port_xfer_status(struct slim_controller *ctr, int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, phys_addr_t iobuf, u32 len, struct completion *comp); int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg); u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len); u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len, struct completion *comp); u32 *msm_slim_manage_tx_msgq(struct msm_slim_ctrl *dev, bool getbuf, struct completion *comp); int msm_slim_rx_msgq_get(struct msm_slim_ctrl *dev, u32 *data, int offset); int msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem, u32 pipe_reg, bool remote); Loading drivers/slimbus/slimbus.c +1 −1 Original line number Diff line number Diff line Loading @@ -1088,7 +1088,7 @@ int slim_xfer_msg(struct slim_controller *ctrl, struct slim_device *sbdev, } else ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, ec, SLIM_MSG_MT_CORE, rbuf, wbuf, len, mlen, NULL, sbdev->laddr, NULL); msg->comp, sbdev->laddr, NULL); xfer_err: return ret; } Loading Loading
drivers/slimbus/slim-msm-ctrl.c +14 −12 Original line number Diff line number Diff line /* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -207,8 +207,7 @@ static irqreturn_t msm_slim_interrupt(int irq, void *d) * signalling completion/exiting ISR */ mb(); if (dev->wr_comp) complete(dev->wr_comp); msm_slim_manage_tx_msgq(dev, false, NULL); } if (stat & MGR_INT_RX_MSG_RCVD) { u32 rx_buf[10]; Loading Loading @@ -372,8 +371,7 @@ static int msm_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) } } txn->rl--; pbuf = msm_get_msg_buf(dev, txn->rl); dev->wr_comp = NULL; pbuf = msm_get_msg_buf(dev, txn->rl, &done); dev->err = 0; if (txn->dt == SLIM_MSG_DEST_ENUMADDR) { Loading Loading @@ -438,11 +436,8 @@ static int msm_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) if (txn->mt == SLIM_MSG_MT_CORE && mc == SLIM_MSG_MC_BEGIN_RECONFIGURATION) dev->reconf_busy = true; dev->wr_comp = &done; msm_send_msg_buf(dev, pbuf, txn->rl, MGR_TX_MSG); timeout = wait_for_completion_timeout(&done, HZ); if (!timeout) dev->wr_comp = NULL; if (mc == SLIM_MSG_MC_RECONFIGURE_NOW) { if ((txn->mc == (SLIM_MSG_MC_RECONFIGURE_NOW | SLIM_MSG_CLK_PAUSE_SEQ_FLG)) && Loading Loading @@ -505,7 +500,9 @@ static int msm_set_laddr(struct slim_controller *ctrl, const u8 *ea, retry_laddr: init_completion(&done); mutex_lock(&dev->tx_lock); buf = msm_get_msg_buf(dev, 9); buf = msm_get_msg_buf(dev, 9, &done); if (buf == NULL) return -ENOMEM; buf[0] = SLIM_MSG_ASM_FIRST_WORD(9, SLIM_MSG_MT_CORE, SLIM_MSG_MC_ASSIGN_LOGICAL_ADDRESS, SLIM_MSG_DEST_LOGICALADDR, Loading @@ -513,7 +510,6 @@ retry_laddr: buf[1] = ea[3] | (ea[2] << 8) | (ea[1] << 16) | (ea[0] << 24); buf[2] = laddr; dev->wr_comp = &done; ret = msm_send_msg_buf(dev, buf, 9, MGR_TX_MSG); timeout = wait_for_completion_timeout(&done, HZ); if (!timeout) Loading @@ -521,7 +517,6 @@ retry_laddr: if (dev->err) { ret = dev->err; dev->err = 0; dev->wr_comp = NULL; } mutex_unlock(&dev->tx_lock); if (ret) { Loading Loading @@ -1183,6 +1178,10 @@ static int msm_slim_probe(struct platform_device *pdev) ret = -ENOMEM; goto err_get_res_failed; } dev->wr_comp = kzalloc(sizeof(struct completion *) * MSM_TX_BUFS, GFP_KERNEL); if (!dev->wr_comp) return -ENOMEM; dev->dev = &pdev->dev; platform_set_drvdata(pdev, dev); slim_set_ctrldata(&dev->ctrl, dev); Loading Loading @@ -1271,7 +1270,8 @@ static int msm_slim_probe(struct platform_device *pdev) dev->ctrl.dev.parent = &pdev->dev; dev->ctrl.dev.of_node = pdev->dev.of_node; ret = request_irq(dev->irq, msm_slim_interrupt, IRQF_TRIGGER_HIGH, ret = request_threaded_irq(dev->irq, NULL, msm_slim_interrupt, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "msm_slim_irq", dev); if (ret) { dev_err(&pdev->dev, "request IRQ failed\n"); Loading Loading @@ -1400,6 +1400,7 @@ err_of_init_failed: err_ioremap_bam_failed: iounmap(dev->base); err_ioremap_failed: kfree(dev->wr_comp); kfree(dev); err_get_res_failed: release_mem_region(bam_mem->start, resource_size(bam_mem)); Loading Loading @@ -1437,6 +1438,7 @@ static int msm_slim_remove(struct platform_device *pdev) kthread_stop(dev->rx_msgq_thread); iounmap(dev->bam.base); iounmap(dev->base); kfree(dev->wr_comp); kfree(dev); bam_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "slimbus_bam_physical"); Loading
drivers/slimbus/slim-msm-ngd.c +33 −10 Original line number Diff line number Diff line Loading @@ -101,15 +101,13 @@ static irqreturn_t ngd_slim_interrupt(int irq, void *d) dev->err); /* Guarantee that error interrupts are cleared */ mb(); if (dev->wr_comp) complete(dev->wr_comp); msm_slim_manage_tx_msgq(dev, false, NULL); } else if (stat & NGD_INT_TX_MSG_SENT) { writel_relaxed(NGD_INT_TX_MSG_SENT, ngd + NGD_INT_CLR); /* Make sure interrupt is cleared */ mb(); if (dev->wr_comp) complete(dev->wr_comp); msm_slim_manage_tx_msgq(dev, false, NULL); } if (stat & NGD_INT_RX_MSG_RCVD) { u32 rx_buf[10]; Loading Loading @@ -286,6 +284,7 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) u16 txn_mc = txn->mc; u8 wbuf[SLIM_MSGQ_BUF_LEN]; bool report_sat = false; bool sync_wr = true; if (txn->mc == SLIM_USR_MC_REPORT_SATELLITE && txn->mt == SLIM_MSG_MT_SRC_REFERRED_USER) Loading Loading @@ -439,7 +438,25 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) txn->rl = txn->len + 4; } txn->rl--; pbuf = msm_get_msg_buf(dev, txn->rl); if (txn->mt == SLIM_MSG_MT_CORE && txn->comp && dev->use_tx_msgqs == MSM_MSGQ_ENABLED && (txn_mc != SLIM_MSG_MC_REQUEST_INFORMATION && txn_mc != SLIM_MSG_MC_REQUEST_VALUE && txn_mc != SLIM_MSG_MC_REQUEST_CHANGE_VALUE && txn_mc != SLIM_MSG_MC_REQUEST_CLEAR_INFORMATION)) { sync_wr = false; pbuf = msm_get_msg_buf(dev, txn->rl, txn->comp); } else if (txn->mt == SLIM_MSG_MT_DEST_REFERRED_USER && dev->use_tx_msgqs == MSM_MSGQ_ENABLED && txn->mc == SLIM_USR_MC_REPEAT_CHANGE_VALUE && txn->comp) { sync_wr = false; pbuf = msm_get_msg_buf(dev, txn->rl, txn->comp); } else { pbuf = msm_get_msg_buf(dev, txn->rl, &tx_sent); } if (!pbuf) { SLIM_ERR(dev, "Message buffer unavailable\n"); ret = -ENOMEM; Loading Loading @@ -510,10 +527,9 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) */ txn_mc = txn->mc; txn_mt = txn->mt; dev->wr_comp = &tx_sent; ret = msm_send_msg_buf(dev, pbuf, txn->rl, NGD_BASE(dev->ctrl.nr, dev->ver) + NGD_TX_MSG); if (!ret) { if (!ret && sync_wr) { int timeout = wait_for_completion_timeout(&tx_sent, HZ); if (!timeout) { ret = -ETIMEDOUT; Loading @@ -529,7 +545,6 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) ret = dev->err; } } dev->wr_comp = NULL; if (ret) { u32 conf, stat, rx_msgq, int_stat, int_en, int_clr; void __iomem *ngd = dev->base + NGD_BASE(dev->ctrl.nr, Loading Loading @@ -1296,6 +1311,10 @@ static int ngd_slim_probe(struct platform_device *pdev) dev_err(&pdev->dev, "no memory for MSM slimbus controller\n"); return PTR_ERR(dev); } dev->wr_comp = kzalloc(sizeof(struct completion *) * MSM_TX_BUFS, GFP_KERNEL); if (!dev->wr_comp) return -ENOMEM; dev->dev = &pdev->dev; platform_set_drvdata(pdev, dev); slim_set_ctrldata(&dev->ctrl, dev); Loading Loading @@ -1379,6 +1398,7 @@ static int ngd_slim_probe(struct platform_device *pdev) init_completion(&dev->reconf); init_completion(&dev->ctrl_up); mutex_init(&dev->tx_lock); mutex_init(&dev->tx_buf_lock); spin_lock_init(&dev->rx_lock); dev->ee = 1; dev->irq = irq->start; Loading Loading @@ -1406,8 +1426,9 @@ static int ngd_slim_probe(struct platform_device *pdev) dev->ctrl.dev.of_node = pdev->dev.of_node; dev->state = MSM_CTRL_DOWN; ret = request_irq(dev->irq, ngd_slim_interrupt, IRQF_TRIGGER_HIGH, "ngd_slim_irq", dev); ret = request_threaded_irq(dev->irq, NULL, ngd_slim_interrupt, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "ngd_slim_irq", dev); if (ret) { dev_err(&pdev->dev, "request IRQ failed\n"); Loading Loading @@ -1470,6 +1491,7 @@ err_ioremap_failed: if (dev->sysfs_created) sysfs_remove_file(&dev->dev->kobj, &dev_attr_debug_mask.attr); kfree(dev->wr_comp); kfree(dev); return ret; } Loading @@ -1492,6 +1514,7 @@ static int ngd_slim_remove(struct platform_device *pdev) kthread_stop(dev->rx_msgq_thread); iounmap(dev->bam.base); iounmap(dev->base); kfree(dev->wr_comp); kfree(dev); return 0; } Loading
drivers/slimbus/slim-msm.c +110 −22 Original line number Diff line number Diff line Loading @@ -11,6 +11,7 @@ */ #include <linux/pm_runtime.h> #include <linux/dma-mapping.h> #include <linux/delay.h> #include <linux/slimbus/slimbus.h> #include <linux/msm-sps.h> #include "slim-msm.h" Loading Loading @@ -390,9 +391,9 @@ static int msm_slim_post_tx_msgq(struct msm_slim_ctrl *dev, u8 *buf, int len) struct msm_slim_endp *endpoint = &dev->tx_msgq; struct sps_mem_buffer *mem = &endpoint->buf; struct sps_pipe *pipe = endpoint->sps; int ix = (buf - (u8 *)mem->base) / SLIM_MSGQ_BUF_LEN; int ix = (buf - (u8 *)mem->base); phys_addr_t phys_addr = mem->phys_base + (SLIM_MSGQ_BUF_LEN * ix); phys_addr_t phys_addr = mem->phys_base + ix; for (ret = 0; ret < ((len + 3) >> 2); ret++) pr_debug("BAM TX buf[%d]:0x%x", ret, ((u32 *)buf)[ret]); Loading @@ -405,29 +406,110 @@ static int msm_slim_post_tx_msgq(struct msm_slim_ctrl *dev, u8 *buf, int len) return ret; } static u32 *msm_slim_tx_msgq_return(struct msm_slim_ctrl *dev) void msm_slim_tx_msg_return(struct msm_slim_ctrl *dev) { struct msm_slim_endp *endpoint = &dev->tx_msgq; struct sps_mem_buffer *mem = &endpoint->buf; struct sps_pipe *pipe = endpoint->sps; struct sps_iovec iovec; int ret; /* first transaction after establishing connection */ if (dev->tx_idx == -1) { dev->tx_idx = 0; return mem->base; int idx, ret = 0; if (dev->use_tx_msgqs != MSM_MSGQ_ENABLED) { /* use 1 buffer, non-blocking writes are not possible */ if (dev->wr_comp[0]) { struct completion *comp = dev->wr_comp[0]; dev->wr_comp[0] = NULL; complete(comp); } return; } while (!ret) { ret = sps_get_iovec(pipe, &iovec); if (ret || iovec.addr == 0) { dev_err(dev->dev, "sps_get_iovec() failed 0x%x\n", ret); if (ret) pr_err("SLIM TX get IOVEC failed:%d", ret); return; } idx = (int) ((iovec.addr - mem->phys_base) / SLIM_MSGQ_BUF_LEN); if (idx < MSM_TX_BUFS && dev->wr_comp[idx]) { struct completion *comp = dev->wr_comp[idx]; dev->wr_comp[idx] = NULL; complete(comp); } /* reclaim all packets that were delivered out of order */ if (idx != dev->tx_head) pr_err("SLIM OUT OF ORDER TX:idx:%d, head:%d", idx, dev->tx_head); while (idx == dev->tx_head) { dev->tx_head = (dev->tx_head + 1) % MSM_TX_BUFS; idx++; if (dev->tx_head == dev->tx_tail || dev->wr_comp[idx] != NULL) break; } } } static u32 *msm_slim_modify_tx_buf(struct msm_slim_ctrl *dev, struct completion *comp) { struct msm_slim_endp *endpoint = &dev->tx_msgq; struct sps_mem_buffer *mem = &endpoint->buf; u32 *retbuf = NULL; if ((dev->tx_tail + 1) % MSM_TX_BUFS == dev->tx_head) return NULL; retbuf = (u32 *)((u8 *)mem->base + (dev->tx_tail * SLIM_MSGQ_BUF_LEN)); dev->wr_comp[dev->tx_tail] = comp; dev->tx_tail = (dev->tx_tail + 1) % MSM_TX_BUFS; return retbuf; } u32 *msm_slim_manage_tx_msgq(struct msm_slim_ctrl *dev, bool getbuf, struct completion *comp) { int ret = 0; int retries = 0; u32 *retbuf = NULL; /* Calculate buffer index */ dev->tx_idx = ((int)(iovec.addr - mem->phys_base)) / SLIM_MSGQ_BUF_LEN; mutex_lock(&dev->tx_buf_lock); if (!getbuf) { msm_slim_tx_msg_return(dev); mutex_unlock(&dev->tx_buf_lock); return NULL; } retbuf = msm_slim_modify_tx_buf(dev, comp); if (retbuf) { mutex_unlock(&dev->tx_buf_lock); return retbuf; } return (u32 *)((u8 *)mem->base + (dev->tx_idx * SLIM_MSGQ_BUF_LEN)); do { msm_slim_tx_msg_return(dev); retbuf = msm_slim_modify_tx_buf(dev, comp); if (!retbuf) ret = -EAGAIN; else { if (retries > 0) SLIM_INFO(dev, "SLIM TX retrieved:%d retries", retries); mutex_unlock(&dev->tx_buf_lock); return retbuf; } /* * superframe size will vary based on clock gear * 1 superframe will consume at least 1 message * if HW is in good condition. With MX_RETRIES, * make sure we wait for a [3, 10] superframes * before deciding HW couldn't process descriptors */ usleep_range(100, 250); retries++; } while (ret && (retries < INIT_MX_RETRIES)); mutex_unlock(&dev->tx_buf_lock); return NULL; } int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg) Loading @@ -445,16 +527,19 @@ int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg) return msm_slim_post_tx_msgq(dev, (u8 *)buf, len); } u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len) u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len, struct completion *comp) { /* * Currently we block a transaction until the current one completes. * In case we need multiple transactions, use message Q */ if (dev->use_tx_msgqs != MSM_MSGQ_ENABLED) if (dev->use_tx_msgqs != MSM_MSGQ_ENABLED) { dev->wr_comp[0] = comp; return dev->tx_buf; } return msm_slim_tx_msgq_return(dev); return msm_slim_manage_tx_msgq(dev, true, comp); } static void Loading Loading @@ -604,7 +689,8 @@ int msm_slim_connect_endp(struct msm_slim_ctrl *dev, } dev->use_rx_msgqs = MSM_MSGQ_ENABLED; } else { dev->tx_idx = -1; dev->tx_tail = 0; dev->tx_head = 0; dev->use_tx_msgqs = MSM_MSGQ_ENABLED; } Loading Loading @@ -711,16 +797,18 @@ static int msm_slim_init_tx_msgq(struct msm_slim_ctrl *dev, u32 pipe_reg) config->options = SPS_O_ERROR | SPS_O_NO_Q | SPS_O_ACK_TRANSFERS | SPS_O_AUTO_ENABLE; /* Desc and TX buf are circular queues */ /* Allocate memory for the FIFO descriptors */ ret = msm_slim_sps_mem_alloc(dev, descr, MSM_TX_BUFS * sizeof(struct sps_iovec)); (MSM_TX_BUFS + 1) * sizeof(struct sps_iovec)); if (ret) { dev_err(dev->dev, "unable to allocate SPS descriptors\n"); goto alloc_descr_failed; } /* Allocate memory for the message buffer(s), N descrs, 40-byte mesg */ ret = msm_slim_sps_mem_alloc(dev, mem, MSM_TX_BUFS * SLIM_MSGQ_BUF_LEN); /* Allocate TX buffer from which descriptors are created */ ret = msm_slim_sps_mem_alloc(dev, mem, ((MSM_TX_BUFS + 1) * SLIM_MSGQ_BUF_LEN)); if (ret) { dev_err(dev->dev, "dma_alloc_coherent failed\n"); goto alloc_buffer_failed; Loading
drivers/slimbus/slim-msm.h +9 −4 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ /* Per spec.max 40 bytes per received message */ #define SLIM_MSGQ_BUF_LEN 40 #define MSM_TX_BUFS 2 #define MSM_TX_BUFS 32 #define SLIM_USR_MC_GENERIC_ACK 0x25 #define SLIM_USR_MC_MASTER_CAPABILITY 0x0 Loading Loading @@ -236,14 +236,15 @@ struct msm_slim_ctrl { u8 msg_cnt; u32 tx_buf[10]; u8 rx_msgs[MSM_CONCUR_MSG][SLIM_MSGQ_BUF_LEN]; int tx_idx; int tx_tail; int tx_head; spinlock_t rx_lock; int head; int tail; int irq; int err; int ee; struct completion *wr_comp; struct completion **wr_comp; struct msm_slim_sat *satd[MSM_MAX_NSATS]; struct msm_slim_endp pipes[7]; struct msm_slim_sps_bam bam; Loading @@ -254,6 +255,7 @@ struct msm_slim_ctrl { struct clk *rclk; struct clk *hclk; struct mutex tx_lock; struct mutex tx_buf_lock; u8 pgdla; enum msm_slim_msgq use_rx_msgqs; enum msm_slim_msgq use_tx_msgqs; Loading Loading @@ -372,7 +374,10 @@ enum slim_port_err msm_slim_port_xfer_status(struct slim_controller *ctr, int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, phys_addr_t iobuf, u32 len, struct completion *comp); int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg); u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len); u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len, struct completion *comp); u32 *msm_slim_manage_tx_msgq(struct msm_slim_ctrl *dev, bool getbuf, struct completion *comp); int msm_slim_rx_msgq_get(struct msm_slim_ctrl *dev, u32 *data, int offset); int msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem, u32 pipe_reg, bool remote); Loading
drivers/slimbus/slimbus.c +1 −1 Original line number Diff line number Diff line Loading @@ -1088,7 +1088,7 @@ int slim_xfer_msg(struct slim_controller *ctrl, struct slim_device *sbdev, } else ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, ec, SLIM_MSG_MT_CORE, rbuf, wbuf, len, mlen, NULL, sbdev->laddr, NULL); msg->comp, sbdev->laddr, NULL); xfer_err: return ret; } Loading