Merge "slim_msm: Optimize RX path for slimbus"

This commit is contained in:
Linux Build Service Account 2015-07-06 21:52:00 -07:00 committed by Gerrit - the friendly Code Review server
commit 369dfc05f2
3 changed files with 112 additions and 123 deletions

View File

@ -81,6 +81,7 @@ enum ngd_status {
NGD_LADDR = 1 << 1,
};
static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf);
static int ngd_slim_runtime_resume(struct device *device);
static int ngd_slim_power_up(struct msm_slim_ctrl *dev, bool mdm_restart);
@ -124,7 +125,7 @@ static irqreturn_t ngd_slim_interrupt(int irq, void *d)
(4 * i));
SLIM_DBG(dev, "REG-RX data: %x\n", rx_buf[i]);
}
msm_slim_rx_enqueue(dev, rx_buf, len);
ngd_slim_rx(dev, (u8 *)rx_buf);
writel_relaxed(NGD_INT_RX_MSG_RCVD,
ngd + NGD_INT_CLR);
/*
@ -134,8 +135,6 @@ static irqreturn_t ngd_slim_interrupt(int irq, void *d)
mb();
if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
SLIM_WARN(dev, "direct msg rcvd with RX MSGQs\n");
else
complete(&dev->rx_msgq_notify);
}
if (stat & NGD_INT_RECFG_DONE) {
writel_relaxed(NGD_INT_RECFG_DONE, ngd + NGD_INT_CLR);
@ -590,7 +589,7 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn)
SPS_BAM_PIPE(4), 0, 2);
msm_slim_disconnect_endp(dev, &dev->tx_msgq,
&dev->use_tx_msgqs);
msm_slim_connect_endp(dev, &dev->tx_msgq, NULL);
msm_slim_connect_endp(dev, &dev->tx_msgq);
}
} else if (!timeout) {
ret = -ETIMEDOUT;
@ -1044,8 +1043,7 @@ static void ngd_slim_setup_msg_path(struct msm_slim_ctrl *dev)
SLIM_WARN(dev, "pipe setup when RX msgq enabled?");
goto setup_tx_msg_path;
}
msm_slim_connect_endp(dev, &dev->rx_msgq,
&dev->rx_msgq_notify);
msm_slim_connect_endp(dev, &dev->rx_msgq);
setup_tx_msg_path:
if (dev->use_tx_msgqs == MSM_MSGQ_DISABLED)
@ -1054,74 +1052,21 @@ setup_tx_msg_path:
SLIM_WARN(dev, "pipe setup when TX msgq enabled?");
return;
}
msm_slim_connect_endp(dev, &dev->tx_msgq,
NULL);
msm_slim_connect_endp(dev, &dev->tx_msgq);
}
}
static void ngd_slim_rx(struct msm_slim_ctrl *dev, u8 *buf)
{
u8 mc, mt, len;
int ret;
u32 msgq_en = 1;
len = buf[0] & 0x1F;
mt = (buf[0] >> 5) & 0x7;
mc = buf[1];
if (mc == SLIM_USR_MC_MASTER_CAPABILITY &&
mt == SLIM_MSG_MT_SRC_REFERRED_USER) {
struct slim_msg_txn txn;
int retries = 0;
u8 wbuf[8];
txn.dt = SLIM_MSG_DEST_LOGICALADDR;
txn.ec = 0;
txn.rbuf = NULL;
txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
txn.la = SLIM_LA_MGR;
wbuf[0] = SAT_MAGIC_LSB;
wbuf[1] = SAT_MAGIC_MSB;
wbuf[2] = SAT_MSG_VER;
wbuf[3] = SAT_MSG_PROT;
txn.wbuf = wbuf;
txn.len = 4;
SLIM_INFO(dev, "SLIM SAT: Rcvd master capability\n");
if (dev->state >= MSM_CTRL_ASLEEP) {
ngd_slim_setup_msg_path(dev);
if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
msgq_en |= NGD_CFG_RX_MSGQ_EN;
if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
msgq_en |= NGD_CFG_TX_MSGQ_EN;
writel_relaxed(msgq_en, dev->base +
NGD_BASE(dev->ctrl.nr, dev->ver));
/* make sure NGD MSG-Q config goes through */
mb();
}
capability_retry:
txn.rl = 8;
ret = ngd_xfer_msg(&dev->ctrl, &txn);
if (!ret) {
enum msm_ctrl_state prev_state = dev->state;
SLIM_INFO(dev,
"SLIM SAT: capability exchange successful\n");
if (prev_state >= MSM_CTRL_ASLEEP)
complete(&dev->reconf);
else
SLIM_ERR(dev,
"SLIM: unexpected capability, state:%d\n",
prev_state);
/* ADSP SSR, send device_up notifications */
if (prev_state == MSM_CTRL_DOWN)
complete(&dev->qmi.slave_notify);
} else if (ret == -EIO) {
SLIM_WARN(dev, "capability message NACKed, retrying\n");
if (retries < INIT_MX_RETRIES) {
msleep(DEF_RETRY_MS);
retries++;
goto capability_retry;
}
}
}
mt == SLIM_MSG_MT_SRC_REFERRED_USER)
complete(&dev->rx_msgq_notify);
if (mc == SLIM_MSG_MC_REPLY_INFORMATION ||
mc == SLIM_MSG_MC_REPLY_VALUE) {
u8 tid = buf[3];
@ -1328,43 +1273,66 @@ static int ngd_slim_rx_msgq_thread(void *data)
{
struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)data;
struct completion *notify = &dev->rx_msgq_notify;
int ret = 0, index = 0;
u32 mc = 0;
u32 mt = 0;
u32 buffer[10];
u8 msg_len = 0;
int ret = 0;
u32 msgq_en = 1;
while (!kthread_should_stop()) {
struct slim_msg_txn txn;
int retries = 0;
u8 wbuf[8];
set_current_state(TASK_INTERRUPTIBLE);
wait_for_completion(notify);
/* 1 irq notification per message */
if (dev->use_rx_msgqs != MSM_MSGQ_ENABLED) {
msm_slim_rx_dequeue(dev, (u8 *)buffer);
ngd_slim_rx(dev, (u8 *)buffer);
continue;
}
do {
ret = msm_slim_rx_msgq_get(dev, buffer, index);
if (ret) {
SLIM_ERR(dev, "rx_msgq_get() failed 0x%x\n",
ret);
break;
}
/* Traverse first byte of message for message length */
if (index++ == 0) {
msg_len = *buffer & 0x1F;
mt = (buffer[0] >> 5) & 0x7;
mc = (buffer[0] >> 8) & 0xff;
dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
}
msg_len = (msg_len < 4) ? 0 : (msg_len - 4);
} while (msg_len);
if (!msg_len) {
index = 0;
ngd_slim_rx(dev, (u8 *)buffer);
txn.dt = SLIM_MSG_DEST_LOGICALADDR;
txn.ec = 0;
txn.rbuf = NULL;
txn.mc = SLIM_USR_MC_REPORT_SATELLITE;
txn.mt = SLIM_MSG_MT_SRC_REFERRED_USER;
txn.la = SLIM_LA_MGR;
wbuf[0] = SAT_MAGIC_LSB;
wbuf[1] = SAT_MAGIC_MSB;
wbuf[2] = SAT_MSG_VER;
wbuf[3] = SAT_MSG_PROT;
txn.wbuf = wbuf;
txn.len = 4;
SLIM_INFO(dev, "SLIM SAT: Rcvd master capability\n");
if (dev->state >= MSM_CTRL_ASLEEP) {
ngd_slim_setup_msg_path(dev);
if (dev->use_rx_msgqs == MSM_MSGQ_ENABLED)
msgq_en |= NGD_CFG_RX_MSGQ_EN;
if (dev->use_tx_msgqs == MSM_MSGQ_ENABLED)
msgq_en |= NGD_CFG_TX_MSGQ_EN;
writel_relaxed(msgq_en, dev->base +
NGD_BASE(dev->ctrl.nr, dev->ver));
/* make sure NGD MSG-Q config goes through */
mb();
}
capability_retry:
txn.rl = 8;
ret = ngd_xfer_msg(&dev->ctrl, &txn);
if (!ret) {
enum msm_ctrl_state prev_state = dev->state;
SLIM_INFO(dev,
"SLIM SAT: capability exchange successful\n");
if (prev_state >= MSM_CTRL_ASLEEP)
complete(&dev->reconf);
else
SLIM_ERR(dev,
"SLIM: unexpected capability, state:%d\n",
prev_state);
/* ADSP SSR, send device_up notifications */
if (prev_state == MSM_CTRL_DOWN)
complete(&dev->qmi.slave_notify);
} else if (ret == -EIO) {
SLIM_WARN(dev, "capability message NACKed, retrying\n");
if (retries < INIT_MX_RETRIES) {
msleep(DEF_RETRY_MS);
retries++;
goto capability_retry;
}
}
continue;
}
return 0;
}
@ -1595,6 +1563,7 @@ static int ngd_slim_probe(struct platform_device *pdev)
dev->ctrl.port_xfer = msm_slim_port_xfer;
dev->ctrl.port_xfer_status = msm_slim_port_xfer_status;
dev->bam_mem = bam_mem;
dev->rx_slim = ngd_slim_rx;
init_completion(&dev->reconf);
init_completion(&dev->ctrl_up);

View File

@ -672,33 +672,55 @@ u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len,
static void
msm_slim_rx_msgq_event(struct msm_slim_ctrl *dev, struct sps_event_notify *ev)
{
u32 *buf = ev->data.transfer.user;
struct sps_iovec *iovec = &ev->data.transfer.iovec;
/*
* Note the virtual address needs to be offset by the same index
* as the physical address or just pass in the actual virtual address
* if the sps_mem_buffer is not needed. Note that if completion is
* used, the virtual address won't be available and will need to be
* calculated based on the offset of the physical address
*/
if (ev->event_id == SPS_EVENT_DESC_DONE) {
pr_debug("buf = 0x%p, data = 0x%x\n", buf, *buf);
pr_debug("iovec = (0x%x 0x%x 0x%x)\n",
iovec->addr, iovec->size, iovec->flags);
} else {
if (ev->event_id == SPS_EVENT_DESC_DONE)
complete(&dev->rx_msgq_notify);
else
dev_err(dev->dev, "%s: unknown event %d\n",
__func__, ev->event_id);
}
static void
msm_slim_handle_rx(struct msm_slim_ctrl *dev, struct sps_event_notify *ev)
{
int ret = 0, index = 0;
u32 mc = 0;
u32 mt = 0;
u32 buffer[10];
u8 msg_len = 0;
if (ev->event_id != SPS_EVENT_EOT) {
dev_err(dev->dev, "%s: unknown event %d\n",
__func__, ev->event_id);
return;
}
do {
ret = msm_slim_rx_msgq_get(dev, buffer, index);
if (ret) {
SLIM_ERR(dev, "rx_msgq_get() failed 0x%x\n",
ret);
return;
}
/* Traverse first byte of message for message length */
if (index++ == 0) {
msg_len = *buffer & 0x1F;
mt = (buffer[0] >> 5) & 0x7;
mc = (buffer[0] >> 8) & 0xff;
dev_dbg(dev->dev, "MC: %x, MT: %x\n", mc, mt);
}
msg_len = (msg_len < 4) ? 0 : (msg_len - 4);
} while (msg_len);
dev->rx_slim(dev, (u8 *)buffer);
}
static void msm_slim_rx_msgq_cb(struct sps_event_notify *notify)
{
struct msm_slim_ctrl *dev = (struct msm_slim_ctrl *)notify->user;
msm_slim_rx_msgq_event(dev, notify);
/* is this manager controller or NGD controller? */
if (dev->ctrl.wakeup)
msm_slim_rx_msgq_event(dev, notify);
else
msm_slim_handle_rx(dev, notify);
}
/* Queue up Rx message buffer */
@ -713,8 +735,6 @@ static int msm_slim_post_rx_msgq(struct msm_slim_ctrl *dev, int ix)
u8 *virt_addr = mem->base + (4 * ix);
phys_addr_t phys_addr = mem->phys_base + (4 * ix);
pr_debug("index:%d, virt:0x%p\n", ix, virt_addr);
ret = sps_transfer_one(pipe, phys_addr, 4, virt_addr, 0);
if (ret)
dev_err(dev->dev, "transfer_one() failed 0x%x, %d\n", ret, ix);
@ -758,8 +778,7 @@ err_exit:
}
int msm_slim_connect_endp(struct msm_slim_ctrl *dev,
struct msm_slim_endp *endpoint,
struct completion *notify)
struct msm_slim_endp *endpoint)
{
int i, ret;
struct sps_register_event sps_error_event; /* SPS_ERROR */
@ -775,11 +794,12 @@ int msm_slim_connect_endp(struct msm_slim_ctrl *dev,
memset(&sps_descr_event, 0x00, sizeof(sps_descr_event));
if (notify) {
if (endpoint == &dev->rx_msgq) {
sps_descr_event.mode = SPS_TRIGGER_CALLBACK;
sps_descr_event.options = SPS_O_EOT;
sps_descr_event.user = (void *)dev;
sps_descr_event.xfer_done = notify;
sps_descr_event.callback = msm_slim_rx_msgq_cb;
sps_descr_event.xfer_done = NULL;
ret = sps_register_event(endpoint->sps, &sps_descr_event);
if (ret) {
@ -883,7 +903,7 @@ static int msm_slim_init_rx_msgq(struct msm_slim_ctrl *dev, u32 pipe_reg)
goto alloc_buffer_failed;
}
ret = msm_slim_connect_endp(dev, endpoint, notify);
ret = msm_slim_connect_endp(dev, endpoint);
if (!ret)
return 0;
@ -946,7 +966,7 @@ static int msm_slim_init_tx_msgq(struct msm_slim_ctrl *dev, u32 pipe_reg)
dev_err(dev->dev, "dma_alloc_coherent failed\n");
goto alloc_buffer_failed;
}
ret = msm_slim_connect_endp(dev, endpoint, NULL);
ret = msm_slim_connect_endp(dev, endpoint);
if (!ret)
return 0;

View File

@ -301,6 +301,7 @@ struct msm_slim_ctrl {
int ipc_log_mask;
bool sysfs_created;
void *ipc_slimbus_log;
void (*rx_slim)(struct msm_slim_ctrl *dev, u8 *buf);
};
struct msm_sat_chan {
@ -411,8 +412,7 @@ int msm_slim_sps_init(struct msm_slim_ctrl *dev, struct resource *bam_mem,
void msm_slim_sps_exit(struct msm_slim_ctrl *dev, bool dereg);
int msm_slim_connect_endp(struct msm_slim_ctrl *dev,
struct msm_slim_endp *endpoint,
struct completion *notify);
struct msm_slim_endp *endpoint);
void msm_slim_disconnect_endp(struct msm_slim_ctrl *dev,
struct msm_slim_endp *endpoint,
enum msm_slim_msgq *msgq_flag);