Loading drivers/slimbus/slim-msm-ngd.c +17 −25 Original line number Diff line number Diff line /* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2015, 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 @@ -267,16 +267,8 @@ static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn, u8 *tid, struct completion *done) { struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl); mutex_lock(&ctrl->m_ctrl); spin_lock(&ctrl->txn_lock); if (ctrl->last_tid <= 255) { ctrl->txnt = krealloc(ctrl->txnt, (ctrl->last_tid + 1) * sizeof(struct slim_msg_txn *), GFP_KERNEL); if (!ctrl->txnt) { mutex_unlock(&ctrl->m_ctrl); return -ENOMEM; } dev->msg_cnt = ctrl->last_tid; ctrl->last_tid++; } else { Loading @@ -288,7 +280,7 @@ static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn, } if (i >= 256) { dev_err(&ctrl->dev, "out of TID"); mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); return -ENOMEM; } } Loading @@ -296,7 +288,7 @@ static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn, txn->tid = dev->msg_cnt; txn->comp = done; *tid = dev->msg_cnt; mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); return 0; } static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) Loading Loading @@ -655,9 +647,9 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) SLIM_ERR(dev, "connect/disconnect:0x%x,tid:%d err:%d\n", txn->mc, txn->tid, ret); mutex_lock(&ctrl->m_ctrl); spin_lock(&ctrl->txn_lock); ctrl->txnt[txn->tid] = NULL; mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); } return ret ? ret : dev->err; } Loading Loading @@ -725,9 +717,9 @@ static int ngd_xferandwait_ack(struct slim_controller *ctrl, if (ret != -EREMOTEIO || txn->mc != SLIM_USR_MC_CHAN_CTRL) SLIM_ERR(dev, "master msg:0x%x,tid:%d ret:%d\n", txn->mc, txn->tid, ret); mutex_lock(&ctrl->m_ctrl); spin_lock(&ctrl->txn_lock); ctrl->txnt[txn->tid] = NULL; mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); } return ret; Loading Loading @@ -1014,30 +1006,30 @@ capability_retry: mt == SLIM_MSG_MT_SRC_REFERRED_USER) { struct slim_msg_txn *txn; u8 failed_ea[6] = {0, 0, 0, 0, 0, 0}; mutex_lock(&dev->ctrl.m_ctrl); spin_lock(&dev->ctrl.txn_lock); txn = dev->ctrl.txnt[buf[3]]; if (!txn) { spin_unlock(&dev->ctrl.txn_lock); SLIM_WARN(dev, "LADDR response after timeout, tid:0x%x\n", buf[3]); mutex_unlock(&dev->ctrl.m_ctrl); return; } if (memcmp(&buf[4], failed_ea, 6)) txn->la = buf[10]; dev->ctrl.txnt[buf[3]] = NULL; mutex_unlock(&dev->ctrl.m_ctrl); complete(txn->comp); spin_unlock(&dev->ctrl.txn_lock); } if (mc == SLIM_USR_MC_GENERIC_ACK && mt == SLIM_MSG_MT_SRC_REFERRED_USER) { struct slim_msg_txn *txn; mutex_lock(&dev->ctrl.m_ctrl); spin_lock(&dev->ctrl.txn_lock); txn = dev->ctrl.txnt[buf[3]]; if (!txn) { spin_unlock(&dev->ctrl.txn_lock); SLIM_WARN(dev, "ACK received after timeout, tid:0x%x\n", buf[3]); mutex_unlock(&dev->ctrl.m_ctrl); return; } dev_dbg(dev->dev, "got response:tid:%d, response:0x%x", Loading @@ -1048,8 +1040,8 @@ capability_retry: txn->ec = -EIO; } dev->ctrl.txnt[buf[3]] = NULL; mutex_unlock(&dev->ctrl.m_ctrl); complete(txn->comp); spin_unlock(&dev->ctrl.txn_lock); } } Loading Loading @@ -1191,16 +1183,16 @@ static int ngd_slim_power_down(struct msm_slim_ctrl *dev) { int i; struct slim_controller *ctrl = &dev->ctrl; mutex_lock(&ctrl->m_ctrl); spin_lock(&ctrl->txn_lock); /* Pending response for a message */ for (i = 0; i < ctrl->last_tid; i++) { if (ctrl->txnt[i]) { spin_unlock(&ctrl->txn_lock); SLIM_INFO(dev, "NGD down:txn-rsp for %d pending", i); mutex_unlock(&ctrl->m_ctrl); return -EBUSY; } } mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); return msm_slim_qmi_power_request(dev, false); } Loading drivers/slimbus/slimbus.c +119 −123 Original line number Diff line number Diff line /* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2015, 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 @@ -43,6 +43,14 @@ static DEFINE_IDR(ctrl_idr); static struct device_type slim_dev_type; static struct device_type slim_ctrl_type; #define DEFINE_SLIM_LDEST_TXN(name, mc, len, rl, rbuf, wbuf, la) \ struct slim_msg_txn name = { rl, 0, mc, SLIM_MSG_DEST_LOGICALADDR, 0,\ len, 0, la, false, rbuf, wbuf, NULL, } #define DEFINE_SLIM_BCAST_TXN(name, mc, len, rl, rbuf, wbuf, la) \ struct slim_msg_txn name = { rl, 0, mc, SLIM_MSG_DEST_BROADCAST, 0,\ len, 0, la, false, rbuf, wbuf, NULL, } static const struct slim_device_id *slim_match(const struct slim_device_id *id, const struct slim_device *slim_dev) { Loading Loading @@ -450,6 +458,7 @@ static int slim_register_controller(struct slim_controller *ctrl) ctrl->min_cg = SLIM_MIN_CLK_GEAR; if (!ctrl->max_cg) ctrl->max_cg = SLIM_MAX_CLK_GEAR; spin_lock_init(&ctrl->txn_lock); mutex_init(&ctrl->m_ctrl); mutex_init(&ctrl->sched.m_reconf); ret = device_register(&ctrl->dev); Loading Loading @@ -677,80 +686,56 @@ EXPORT_SYMBOL(slim_framer_booted); void slim_msg_response(struct slim_controller *ctrl, u8 *reply, u8 tid, u8 len) { int i; bool async; struct slim_msg_txn *txn; mutex_lock(&ctrl->m_ctrl); spin_lock(&ctrl->txn_lock); txn = ctrl->txnt[tid]; if (txn == NULL || txn->rbuf == NULL) { spin_unlock(&ctrl->txn_lock); if (txn == NULL) dev_err(&ctrl->dev, "Got response to invalid TID:%d, len:%d", tid, len); else dev_err(&ctrl->dev, "Invalid client buffer passed\n"); mutex_unlock(&ctrl->m_ctrl); return; } async = txn->async; for (i = 0; i < len; i++) txn->rbuf[i] = reply[i]; if (txn->comp) complete(txn->comp); ctrl->txnt[tid] = NULL; mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); if (async) kfree(txn); } EXPORT_SYMBOL_GPL(slim_msg_response); static int slim_processtxn(struct slim_controller *ctrl, u8 dt, u16 mc, u16 ec, u8 mt, u8 *rbuf, const u8 *wbuf, u8 len, u8 mlen, struct completion *comp, u8 la, u8 *tid) static int slim_processtxn(struct slim_controller *ctrl, struct slim_msg_txn *txn, bool need_tid) { u8 i = 0; int ret = 0; struct slim_msg_txn *txn = kmalloc(sizeof(struct slim_msg_txn), GFP_KERNEL); if (!txn) return -ENOMEM; if (tid) { mutex_lock(&ctrl->m_ctrl); if (need_tid) { spin_lock(&ctrl->txn_lock); for (i = 0; i < ctrl->last_tid; i++) { if (ctrl->txnt[i] == NULL) break; } if (i >= ctrl->last_tid) { if (ctrl->last_tid == 255) { mutex_unlock(&ctrl->m_ctrl); kfree(txn); return -ENOMEM; } ctrl->txnt = krealloc(ctrl->txnt, (i + 1) * sizeof(struct slim_msg_txn *), GFP_KERNEL); if (!ctrl->txnt) { mutex_unlock(&ctrl->m_ctrl); kfree(txn); spin_unlock(&ctrl->txn_lock); return -ENOMEM; } ctrl->last_tid++; } ctrl->txnt[i] = txn; mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); txn->tid = i; *tid = i; } txn->mc = mc; txn->mt = mt; txn->dt = dt; txn->ec = ec; txn->la = la; txn->rbuf = rbuf; txn->wbuf = wbuf; txn->rl = mlen; txn->len = len; txn->comp = comp; } ret = ctrl->xfer_msg(ctrl, txn); if (!tid) kfree(txn); return ret; } Loading Loading @@ -1035,10 +1020,23 @@ int slim_xfer_msg(struct slim_controller *ctrl, struct slim_device *sbdev, const u8 *wbuf, u8 len) { DECLARE_COMPLETION_ONSTACK(complete); DEFINE_SLIM_LDEST_TXN(txn_stack, mc, len, 6, rbuf, wbuf, sbdev->laddr); struct slim_msg_txn *txn; int ret; u16 sl, cur; u16 ec; u8 tid, mlen = 6; if (msg->comp && rbuf) { txn = kmalloc(sizeof(struct slim_msg_txn), GFP_KERNEL); if (IS_ERR_OR_NULL(txn)) return PTR_ERR(txn); *txn = txn_stack; txn->async = true; txn->comp = msg->comp; } else { txn = &txn_stack; if (rbuf) txn->comp = &complete; } ret = slim_ele_access_sanity(msg, mc, rbuf, wbuf, len); if (ret) Loading @@ -1049,50 +1047,36 @@ int slim_xfer_msg(struct slim_controller *ctrl, struct slim_device *sbdev, msg->start_offset, len, mc, sl); cur = slim_slicecodefromsize(sl); ec = ((sl | (1 << 3)) | ((msg->start_offset & 0xFFF) << 4)); txn->ec = ((sl | (1 << 3)) | ((msg->start_offset & 0xFFF) << 4)); if (wbuf) mlen += len; txn->rl += len; if (rbuf) { mlen++; if (!msg->comp) ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, ec, SLIM_MSG_MT_CORE, rbuf, wbuf, len, mlen, &complete, sbdev->laddr, &tid); else ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, ec, SLIM_MSG_MT_CORE, rbuf, wbuf, len, mlen, msg->comp, sbdev->laddr, &tid); txn->rl++; ret = slim_processtxn(ctrl, txn, true); /* sync read */ if (!ret && !msg->comp) { ret = wait_for_completion_timeout(&complete, HZ); if (!ret) { struct slim_msg_txn *txn; dev_err(&ctrl->dev, "slimbus Read timed out"); mutex_lock(&ctrl->m_ctrl); txn = ctrl->txnt[tid]; spin_lock(&ctrl->txn_lock); /* Invalidate the transaction */ ctrl->txnt[tid] = NULL; mutex_unlock(&ctrl->m_ctrl); kfree(txn); ctrl->txnt[txn->tid] = NULL; spin_unlock(&ctrl->txn_lock); ret = -ETIMEDOUT; } else ret = 0; } else if (ret < 0 && !msg->comp) { struct slim_msg_txn *txn; dev_err(&ctrl->dev, "slimbus Read error"); mutex_lock(&ctrl->m_ctrl); txn = ctrl->txnt[tid]; spin_lock(&ctrl->txn_lock); /* Invalidate the transaction */ ctrl->txnt[tid] = NULL; mutex_unlock(&ctrl->m_ctrl); kfree(txn); ctrl->txnt[txn->tid] = NULL; spin_unlock(&ctrl->txn_lock); } } else ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, ec, SLIM_MSG_MT_CORE, rbuf, wbuf, len, mlen, msg->comp, sbdev->laddr, NULL); ret = slim_processtxn(ctrl, txn, false); xfer_err: return ret; } Loading Loading @@ -1268,22 +1252,20 @@ static int connect_port_ch(struct slim_controller *ctrl, u8 ch, u32 ph, enum slim_port_flow flow) { int ret; u16 mc; u8 buf[2]; u32 la = SLIM_HDL_TO_LA(ph); u8 pn = (u8)SLIM_HDL_TO_PORT(ph); DEFINE_SLIM_LDEST_TXN(txn, 0, 2, 6, NULL, buf, la); if (flow == SLIM_SRC) mc = SLIM_MSG_MC_CONNECT_SOURCE; txn.mc = SLIM_MSG_MC_CONNECT_SOURCE; else mc = SLIM_MSG_MC_CONNECT_SINK; txn.mc = SLIM_MSG_MC_CONNECT_SINK; buf[0] = pn; buf[1] = ctrl->chans[ch].chan; if (la == SLIM_LA_MANAGER) ctrl->ports[pn].flow = flow; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, 0, SLIM_MSG_MT_CORE, NULL, buf, 2, 6, NULL, la, NULL); ret = slim_processtxn(ctrl, &txn, false); if (!ret && la == SLIM_LA_MANAGER) ctrl->ports[pn].state = SLIM_P_CFG; return ret; Loading @@ -1292,14 +1274,12 @@ static int connect_port_ch(struct slim_controller *ctrl, u8 ch, u32 ph, static int disconnect_port_ch(struct slim_controller *ctrl, u32 ph) { int ret; u16 mc; u32 la = SLIM_HDL_TO_LA(ph); u8 pn = (u8)SLIM_HDL_TO_PORT(ph); DEFINE_SLIM_LDEST_TXN(txn, 0, 1, 5, NULL, &pn, la); mc = SLIM_MSG_MC_DISCONNECT_PORT; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, 0, SLIM_MSG_MT_CORE, NULL, &pn, 1, 5, NULL, la, NULL); txn.mc = SLIM_MSG_MC_DISCONNECT_PORT; ret = slim_processtxn(ctrl, &txn, false); if (ret) return ret; if (la == SLIM_LA_MANAGER) Loading Loading @@ -2741,6 +2721,8 @@ int slim_reconfigure_now(struct slim_device *sb) u32 expshft; u32 segdist; struct slim_pending_ch *pch; DEFINE_SLIM_BCAST_TXN(txn, SLIM_MSG_MC_BEGIN_RECONFIGURATION, 0, 3, NULL, NULL, sb->laddr); mutex_lock(&ctrl->sched.m_reconf); /* Loading Loading @@ -2809,25 +2791,27 @@ int slim_reconfigure_now(struct slim_device *sb) ret = slim_allocbw(sb, &subframe, &clkgear); if (!ret) { ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_BEGIN_RECONFIGURATION, 0, SLIM_MSG_MT_CORE, NULL, NULL, 0, 3, NULL, 0, NULL); ret = slim_processtxn(ctrl, &txn, false); dev_dbg(&ctrl->dev, "sending begin_reconfig:ret:%d\n", ret); } if (!ret && subframe != ctrl->sched.subfrmcode) { wbuf[0] = (u8)(subframe & 0xFF); ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_SUBFRAME_MODE, 0, SLIM_MSG_MT_CORE, NULL, (u8 *)&subframe, 1, 4, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_SUBFRAME_MODE; txn.len = 1; txn.rl = 4; txn.wbuf = wbuf; ret = slim_processtxn(ctrl, &txn, false); dev_dbg(&ctrl->dev, "sending subframe:%d,ret:%d\n", (int)wbuf[0], ret); } if (!ret && clkgear != ctrl->clkgear) { wbuf[0] = (u8)(clkgear & 0xFF); ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_CLOCK_GEAR, 0, SLIM_MSG_MT_CORE, NULL, wbuf, 1, 4, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_CLOCK_GEAR; txn.len = 1; txn.rl = 4; txn.wbuf = wbuf; ret = slim_processtxn(ctrl, &txn, false); dev_dbg(&ctrl->dev, "sending clkgear:%d,ret:%d\n", (int)wbuf[0], ret); } Loading @@ -2843,20 +2827,21 @@ int slim_reconfigure_now(struct slim_device *sb) wbuf[1] = slc->prrate; wbuf[2] = slc->prop.dataf | (slc->prop.auxf << 4); wbuf[3] = slc->prop.sampleszbits / SLIM_CL_PER_SL; txn.mc = SLIM_MSG_MC_NEXT_DEFINE_CONTENT; txn.len = 4; txn.rl = 7; txn.wbuf = wbuf; dev_dbg(&ctrl->dev, "define content, activate:%x, %x, %x, %x\n", wbuf[0], wbuf[1], wbuf[2], wbuf[3]); /* Right now, channel link bit is not supported */ ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_DEFINE_CONTENT, 0, SLIM_MSG_MT_CORE, NULL, (u8 *)&wbuf, 4, 7, NULL, 0, NULL); ret = slim_processtxn(ctrl, &txn, false); if (ret) goto revert_reconfig; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_ACTIVATE_CHANNEL, 0, SLIM_MSG_MT_CORE, NULL, (u8 *)&wbuf, 1, 4, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_ACTIVATE_CHANNEL; txn.len = 1; txn.rl = 4; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto revert_reconfig; } Loading @@ -2865,10 +2850,11 @@ int slim_reconfigure_now(struct slim_device *sb) struct slim_ich *slc = &ctrl->chans[pch->chan]; dev_dbg(&ctrl->dev, "remove chan:%x\n", pch->chan); wbuf[0] = slc->chan; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_REMOVE_CHANNEL, 0, SLIM_MSG_MT_CORE, NULL, wbuf, 1, 4, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_REMOVE_CHANNEL; txn.len = 1; txn.rl = 4; txn.wbuf = wbuf; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto revert_reconfig; } Loading @@ -2876,10 +2862,11 @@ int slim_reconfigure_now(struct slim_device *sb) struct slim_ich *slc = &ctrl->chans[pch->chan]; dev_dbg(&ctrl->dev, "suspend chan:%x\n", pch->chan); wbuf[0] = slc->chan; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_DEACTIVATE_CHANNEL, 0, SLIM_MSG_MT_CORE, NULL, wbuf, 1, 4, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_DEACTIVATE_CHANNEL; txn.len = 1; txn.rl = 4; txn.wbuf = wbuf; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto revert_reconfig; } Loading Loading @@ -2908,10 +2895,11 @@ int slim_reconfigure_now(struct slim_device *sb) wbuf[2] = (u8)((segdist & 0xF00) >> 8) | (slc->prop.prot << 4); wbuf[3] = slc->seglen; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_DEFINE_CHANNEL, 0, SLIM_MSG_MT_CORE, NULL, (u8 *)wbuf, 4, 7, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_DEFINE_CHANNEL; txn.len = 4; txn.rl = 7; txn.wbuf = wbuf; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto revert_reconfig; } Loading Loading @@ -2941,17 +2929,20 @@ int slim_reconfigure_now(struct slim_device *sb) wbuf[2] = (u8)((segdist & 0xF00) >> 8) | (slc->prop.prot << 4); wbuf[3] = (u8)(slc->seglen); ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_DEFINE_CHANNEL, 0, SLIM_MSG_MT_CORE, NULL, (u8 *)wbuf, 4, 7, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_DEFINE_CHANNEL; txn.len = 4; txn.rl = 7; txn.wbuf = wbuf; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto revert_reconfig; } } ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_RECONFIGURE_NOW, 0, SLIM_MSG_MT_CORE, NULL, NULL, 0, 3, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_RECONFIGURE_NOW; txn.len = 0; txn.rl = 3; txn.wbuf = NULL; ret = slim_processtxn(ctrl, &txn, false); dev_dbg(&ctrl->dev, "reconfig now:ret:%d\n", ret); if (!ret) { ctrl->sched.subfrmcode = subframe; Loading Loading @@ -3128,6 +3119,9 @@ int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup, u8 restart) { int ret = 0; int i; DEFINE_SLIM_BCAST_TXN(txn, SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_BEGIN_RECONFIGURATION, 0, 3, NULL, NULL, 0); if (wakeup == false && restart > SLIM_CLK_UNSPECIFIED) return -EINVAL; Loading Loading @@ -3211,21 +3205,23 @@ int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup, u8 restart) goto clk_pause_ret; } ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_BEGIN_RECONFIGURATION, 0, SLIM_MSG_MT_CORE, NULL, NULL, 0, 3, NULL, 0, NULL); ret = slim_processtxn(ctrl, &txn, false); if (ret) goto clk_pause_ret; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_NEXT_PAUSE_CLOCK, 0, SLIM_MSG_MT_CORE, NULL, &restart, 1, 4, NULL, 0, NULL); txn.mc = SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_NEXT_PAUSE_CLOCK; txn.len = 1; txn.rl = 4; txn.wbuf = &restart; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto clk_pause_ret; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_RECONFIGURE_NOW, 0, SLIM_MSG_MT_CORE, NULL, NULL, 0, 3, NULL, 0, NULL); txn.mc = SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_RECONFIGURE_NOW; txn.len = 0; txn.rl = 3; txn.wbuf = NULL; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto clk_pause_ret; Loading include/linux/slimbus/slimbus.h +6 −2 Original line number Diff line number Diff line /* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2015, 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 @@ -24,6 +24,7 @@ extern struct bus_type slimbus_type; /* Standard values per SLIMbus spec needed by controllers and devices */ #define SLIM_CL_PER_SUPERFRAME 6144 #define SLIM_CL_PER_SUPERFRAME_DIV8 (SLIM_CL_PER_SUPERFRAME >> 3) #define SLIM_MAX_TXNS 256 #define SLIM_MAX_CLK_GEAR 10 #define SLIM_MIN_CLK_GEAR 1 #define SLIM_CL_PER_SL 4 Loading Loading @@ -171,6 +172,7 @@ struct slim_addrt { * (e.g. relevant for mc = SLIM_MSG_MC_REQUEST_INFORMATION) * @la: Logical address of the device this message is going to. * (Not used when destination type is broadcast.) * @async: If this transaction is async * @rbuf: Buffer to be populated by controller when response is received. * @wbuf: Payload of the message. (e.g. channel number for DATA channel APIs) * @comp: Completion structure. Used by controller to notify response. Loading @@ -185,6 +187,7 @@ struct slim_msg_txn { u8 len; u8 tid; u8 la; bool async; u8 *rbuf; const u8 *wbuf; struct completion *comp; Loading Loading @@ -544,8 +547,9 @@ struct slim_controller { u8 num_dev; struct list_head devs; struct workqueue_struct *wq; struct slim_msg_txn **txnt; struct slim_msg_txn *txnt[SLIM_MAX_TXNS]; u8 last_tid; spinlock_t txn_lock; struct slim_port *ports; int nports; struct slim_ich *chans; Loading Loading
drivers/slimbus/slim-msm-ngd.c +17 −25 Original line number Diff line number Diff line /* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2015, 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 @@ -267,16 +267,8 @@ static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn, u8 *tid, struct completion *done) { struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl); mutex_lock(&ctrl->m_ctrl); spin_lock(&ctrl->txn_lock); if (ctrl->last_tid <= 255) { ctrl->txnt = krealloc(ctrl->txnt, (ctrl->last_tid + 1) * sizeof(struct slim_msg_txn *), GFP_KERNEL); if (!ctrl->txnt) { mutex_unlock(&ctrl->m_ctrl); return -ENOMEM; } dev->msg_cnt = ctrl->last_tid; ctrl->last_tid++; } else { Loading @@ -288,7 +280,7 @@ static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn, } if (i >= 256) { dev_err(&ctrl->dev, "out of TID"); mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); return -ENOMEM; } } Loading @@ -296,7 +288,7 @@ static int ngd_get_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn, txn->tid = dev->msg_cnt; txn->comp = done; *tid = dev->msg_cnt; mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); return 0; } static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) Loading Loading @@ -655,9 +647,9 @@ static int ngd_xfer_msg(struct slim_controller *ctrl, struct slim_msg_txn *txn) SLIM_ERR(dev, "connect/disconnect:0x%x,tid:%d err:%d\n", txn->mc, txn->tid, ret); mutex_lock(&ctrl->m_ctrl); spin_lock(&ctrl->txn_lock); ctrl->txnt[txn->tid] = NULL; mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); } return ret ? ret : dev->err; } Loading Loading @@ -725,9 +717,9 @@ static int ngd_xferandwait_ack(struct slim_controller *ctrl, if (ret != -EREMOTEIO || txn->mc != SLIM_USR_MC_CHAN_CTRL) SLIM_ERR(dev, "master msg:0x%x,tid:%d ret:%d\n", txn->mc, txn->tid, ret); mutex_lock(&ctrl->m_ctrl); spin_lock(&ctrl->txn_lock); ctrl->txnt[txn->tid] = NULL; mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); } return ret; Loading Loading @@ -1014,30 +1006,30 @@ capability_retry: mt == SLIM_MSG_MT_SRC_REFERRED_USER) { struct slim_msg_txn *txn; u8 failed_ea[6] = {0, 0, 0, 0, 0, 0}; mutex_lock(&dev->ctrl.m_ctrl); spin_lock(&dev->ctrl.txn_lock); txn = dev->ctrl.txnt[buf[3]]; if (!txn) { spin_unlock(&dev->ctrl.txn_lock); SLIM_WARN(dev, "LADDR response after timeout, tid:0x%x\n", buf[3]); mutex_unlock(&dev->ctrl.m_ctrl); return; } if (memcmp(&buf[4], failed_ea, 6)) txn->la = buf[10]; dev->ctrl.txnt[buf[3]] = NULL; mutex_unlock(&dev->ctrl.m_ctrl); complete(txn->comp); spin_unlock(&dev->ctrl.txn_lock); } if (mc == SLIM_USR_MC_GENERIC_ACK && mt == SLIM_MSG_MT_SRC_REFERRED_USER) { struct slim_msg_txn *txn; mutex_lock(&dev->ctrl.m_ctrl); spin_lock(&dev->ctrl.txn_lock); txn = dev->ctrl.txnt[buf[3]]; if (!txn) { spin_unlock(&dev->ctrl.txn_lock); SLIM_WARN(dev, "ACK received after timeout, tid:0x%x\n", buf[3]); mutex_unlock(&dev->ctrl.m_ctrl); return; } dev_dbg(dev->dev, "got response:tid:%d, response:0x%x", Loading @@ -1048,8 +1040,8 @@ capability_retry: txn->ec = -EIO; } dev->ctrl.txnt[buf[3]] = NULL; mutex_unlock(&dev->ctrl.m_ctrl); complete(txn->comp); spin_unlock(&dev->ctrl.txn_lock); } } Loading Loading @@ -1191,16 +1183,16 @@ static int ngd_slim_power_down(struct msm_slim_ctrl *dev) { int i; struct slim_controller *ctrl = &dev->ctrl; mutex_lock(&ctrl->m_ctrl); spin_lock(&ctrl->txn_lock); /* Pending response for a message */ for (i = 0; i < ctrl->last_tid; i++) { if (ctrl->txnt[i]) { spin_unlock(&ctrl->txn_lock); SLIM_INFO(dev, "NGD down:txn-rsp for %d pending", i); mutex_unlock(&ctrl->m_ctrl); return -EBUSY; } } mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); return msm_slim_qmi_power_request(dev, false); } Loading
drivers/slimbus/slimbus.c +119 −123 Original line number Diff line number Diff line /* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2015, 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 @@ -43,6 +43,14 @@ static DEFINE_IDR(ctrl_idr); static struct device_type slim_dev_type; static struct device_type slim_ctrl_type; #define DEFINE_SLIM_LDEST_TXN(name, mc, len, rl, rbuf, wbuf, la) \ struct slim_msg_txn name = { rl, 0, mc, SLIM_MSG_DEST_LOGICALADDR, 0,\ len, 0, la, false, rbuf, wbuf, NULL, } #define DEFINE_SLIM_BCAST_TXN(name, mc, len, rl, rbuf, wbuf, la) \ struct slim_msg_txn name = { rl, 0, mc, SLIM_MSG_DEST_BROADCAST, 0,\ len, 0, la, false, rbuf, wbuf, NULL, } static const struct slim_device_id *slim_match(const struct slim_device_id *id, const struct slim_device *slim_dev) { Loading Loading @@ -450,6 +458,7 @@ static int slim_register_controller(struct slim_controller *ctrl) ctrl->min_cg = SLIM_MIN_CLK_GEAR; if (!ctrl->max_cg) ctrl->max_cg = SLIM_MAX_CLK_GEAR; spin_lock_init(&ctrl->txn_lock); mutex_init(&ctrl->m_ctrl); mutex_init(&ctrl->sched.m_reconf); ret = device_register(&ctrl->dev); Loading Loading @@ -677,80 +686,56 @@ EXPORT_SYMBOL(slim_framer_booted); void slim_msg_response(struct slim_controller *ctrl, u8 *reply, u8 tid, u8 len) { int i; bool async; struct slim_msg_txn *txn; mutex_lock(&ctrl->m_ctrl); spin_lock(&ctrl->txn_lock); txn = ctrl->txnt[tid]; if (txn == NULL || txn->rbuf == NULL) { spin_unlock(&ctrl->txn_lock); if (txn == NULL) dev_err(&ctrl->dev, "Got response to invalid TID:%d, len:%d", tid, len); else dev_err(&ctrl->dev, "Invalid client buffer passed\n"); mutex_unlock(&ctrl->m_ctrl); return; } async = txn->async; for (i = 0; i < len; i++) txn->rbuf[i] = reply[i]; if (txn->comp) complete(txn->comp); ctrl->txnt[tid] = NULL; mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); if (async) kfree(txn); } EXPORT_SYMBOL_GPL(slim_msg_response); static int slim_processtxn(struct slim_controller *ctrl, u8 dt, u16 mc, u16 ec, u8 mt, u8 *rbuf, const u8 *wbuf, u8 len, u8 mlen, struct completion *comp, u8 la, u8 *tid) static int slim_processtxn(struct slim_controller *ctrl, struct slim_msg_txn *txn, bool need_tid) { u8 i = 0; int ret = 0; struct slim_msg_txn *txn = kmalloc(sizeof(struct slim_msg_txn), GFP_KERNEL); if (!txn) return -ENOMEM; if (tid) { mutex_lock(&ctrl->m_ctrl); if (need_tid) { spin_lock(&ctrl->txn_lock); for (i = 0; i < ctrl->last_tid; i++) { if (ctrl->txnt[i] == NULL) break; } if (i >= ctrl->last_tid) { if (ctrl->last_tid == 255) { mutex_unlock(&ctrl->m_ctrl); kfree(txn); return -ENOMEM; } ctrl->txnt = krealloc(ctrl->txnt, (i + 1) * sizeof(struct slim_msg_txn *), GFP_KERNEL); if (!ctrl->txnt) { mutex_unlock(&ctrl->m_ctrl); kfree(txn); spin_unlock(&ctrl->txn_lock); return -ENOMEM; } ctrl->last_tid++; } ctrl->txnt[i] = txn; mutex_unlock(&ctrl->m_ctrl); spin_unlock(&ctrl->txn_lock); txn->tid = i; *tid = i; } txn->mc = mc; txn->mt = mt; txn->dt = dt; txn->ec = ec; txn->la = la; txn->rbuf = rbuf; txn->wbuf = wbuf; txn->rl = mlen; txn->len = len; txn->comp = comp; } ret = ctrl->xfer_msg(ctrl, txn); if (!tid) kfree(txn); return ret; } Loading Loading @@ -1035,10 +1020,23 @@ int slim_xfer_msg(struct slim_controller *ctrl, struct slim_device *sbdev, const u8 *wbuf, u8 len) { DECLARE_COMPLETION_ONSTACK(complete); DEFINE_SLIM_LDEST_TXN(txn_stack, mc, len, 6, rbuf, wbuf, sbdev->laddr); struct slim_msg_txn *txn; int ret; u16 sl, cur; u16 ec; u8 tid, mlen = 6; if (msg->comp && rbuf) { txn = kmalloc(sizeof(struct slim_msg_txn), GFP_KERNEL); if (IS_ERR_OR_NULL(txn)) return PTR_ERR(txn); *txn = txn_stack; txn->async = true; txn->comp = msg->comp; } else { txn = &txn_stack; if (rbuf) txn->comp = &complete; } ret = slim_ele_access_sanity(msg, mc, rbuf, wbuf, len); if (ret) Loading @@ -1049,50 +1047,36 @@ int slim_xfer_msg(struct slim_controller *ctrl, struct slim_device *sbdev, msg->start_offset, len, mc, sl); cur = slim_slicecodefromsize(sl); ec = ((sl | (1 << 3)) | ((msg->start_offset & 0xFFF) << 4)); txn->ec = ((sl | (1 << 3)) | ((msg->start_offset & 0xFFF) << 4)); if (wbuf) mlen += len; txn->rl += len; if (rbuf) { mlen++; if (!msg->comp) ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, ec, SLIM_MSG_MT_CORE, rbuf, wbuf, len, mlen, &complete, sbdev->laddr, &tid); else ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, ec, SLIM_MSG_MT_CORE, rbuf, wbuf, len, mlen, msg->comp, sbdev->laddr, &tid); txn->rl++; ret = slim_processtxn(ctrl, txn, true); /* sync read */ if (!ret && !msg->comp) { ret = wait_for_completion_timeout(&complete, HZ); if (!ret) { struct slim_msg_txn *txn; dev_err(&ctrl->dev, "slimbus Read timed out"); mutex_lock(&ctrl->m_ctrl); txn = ctrl->txnt[tid]; spin_lock(&ctrl->txn_lock); /* Invalidate the transaction */ ctrl->txnt[tid] = NULL; mutex_unlock(&ctrl->m_ctrl); kfree(txn); ctrl->txnt[txn->tid] = NULL; spin_unlock(&ctrl->txn_lock); ret = -ETIMEDOUT; } else ret = 0; } else if (ret < 0 && !msg->comp) { struct slim_msg_txn *txn; dev_err(&ctrl->dev, "slimbus Read error"); mutex_lock(&ctrl->m_ctrl); txn = ctrl->txnt[tid]; spin_lock(&ctrl->txn_lock); /* Invalidate the transaction */ ctrl->txnt[tid] = NULL; mutex_unlock(&ctrl->m_ctrl); kfree(txn); ctrl->txnt[txn->tid] = NULL; spin_unlock(&ctrl->txn_lock); } } else ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, ec, SLIM_MSG_MT_CORE, rbuf, wbuf, len, mlen, msg->comp, sbdev->laddr, NULL); ret = slim_processtxn(ctrl, txn, false); xfer_err: return ret; } Loading Loading @@ -1268,22 +1252,20 @@ static int connect_port_ch(struct slim_controller *ctrl, u8 ch, u32 ph, enum slim_port_flow flow) { int ret; u16 mc; u8 buf[2]; u32 la = SLIM_HDL_TO_LA(ph); u8 pn = (u8)SLIM_HDL_TO_PORT(ph); DEFINE_SLIM_LDEST_TXN(txn, 0, 2, 6, NULL, buf, la); if (flow == SLIM_SRC) mc = SLIM_MSG_MC_CONNECT_SOURCE; txn.mc = SLIM_MSG_MC_CONNECT_SOURCE; else mc = SLIM_MSG_MC_CONNECT_SINK; txn.mc = SLIM_MSG_MC_CONNECT_SINK; buf[0] = pn; buf[1] = ctrl->chans[ch].chan; if (la == SLIM_LA_MANAGER) ctrl->ports[pn].flow = flow; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, 0, SLIM_MSG_MT_CORE, NULL, buf, 2, 6, NULL, la, NULL); ret = slim_processtxn(ctrl, &txn, false); if (!ret && la == SLIM_LA_MANAGER) ctrl->ports[pn].state = SLIM_P_CFG; return ret; Loading @@ -1292,14 +1274,12 @@ static int connect_port_ch(struct slim_controller *ctrl, u8 ch, u32 ph, static int disconnect_port_ch(struct slim_controller *ctrl, u32 ph) { int ret; u16 mc; u32 la = SLIM_HDL_TO_LA(ph); u8 pn = (u8)SLIM_HDL_TO_PORT(ph); DEFINE_SLIM_LDEST_TXN(txn, 0, 1, 5, NULL, &pn, la); mc = SLIM_MSG_MC_DISCONNECT_PORT; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_LOGICALADDR, mc, 0, SLIM_MSG_MT_CORE, NULL, &pn, 1, 5, NULL, la, NULL); txn.mc = SLIM_MSG_MC_DISCONNECT_PORT; ret = slim_processtxn(ctrl, &txn, false); if (ret) return ret; if (la == SLIM_LA_MANAGER) Loading Loading @@ -2741,6 +2721,8 @@ int slim_reconfigure_now(struct slim_device *sb) u32 expshft; u32 segdist; struct slim_pending_ch *pch; DEFINE_SLIM_BCAST_TXN(txn, SLIM_MSG_MC_BEGIN_RECONFIGURATION, 0, 3, NULL, NULL, sb->laddr); mutex_lock(&ctrl->sched.m_reconf); /* Loading Loading @@ -2809,25 +2791,27 @@ int slim_reconfigure_now(struct slim_device *sb) ret = slim_allocbw(sb, &subframe, &clkgear); if (!ret) { ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_BEGIN_RECONFIGURATION, 0, SLIM_MSG_MT_CORE, NULL, NULL, 0, 3, NULL, 0, NULL); ret = slim_processtxn(ctrl, &txn, false); dev_dbg(&ctrl->dev, "sending begin_reconfig:ret:%d\n", ret); } if (!ret && subframe != ctrl->sched.subfrmcode) { wbuf[0] = (u8)(subframe & 0xFF); ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_SUBFRAME_MODE, 0, SLIM_MSG_MT_CORE, NULL, (u8 *)&subframe, 1, 4, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_SUBFRAME_MODE; txn.len = 1; txn.rl = 4; txn.wbuf = wbuf; ret = slim_processtxn(ctrl, &txn, false); dev_dbg(&ctrl->dev, "sending subframe:%d,ret:%d\n", (int)wbuf[0], ret); } if (!ret && clkgear != ctrl->clkgear) { wbuf[0] = (u8)(clkgear & 0xFF); ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_CLOCK_GEAR, 0, SLIM_MSG_MT_CORE, NULL, wbuf, 1, 4, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_CLOCK_GEAR; txn.len = 1; txn.rl = 4; txn.wbuf = wbuf; ret = slim_processtxn(ctrl, &txn, false); dev_dbg(&ctrl->dev, "sending clkgear:%d,ret:%d\n", (int)wbuf[0], ret); } Loading @@ -2843,20 +2827,21 @@ int slim_reconfigure_now(struct slim_device *sb) wbuf[1] = slc->prrate; wbuf[2] = slc->prop.dataf | (slc->prop.auxf << 4); wbuf[3] = slc->prop.sampleszbits / SLIM_CL_PER_SL; txn.mc = SLIM_MSG_MC_NEXT_DEFINE_CONTENT; txn.len = 4; txn.rl = 7; txn.wbuf = wbuf; dev_dbg(&ctrl->dev, "define content, activate:%x, %x, %x, %x\n", wbuf[0], wbuf[1], wbuf[2], wbuf[3]); /* Right now, channel link bit is not supported */ ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_DEFINE_CONTENT, 0, SLIM_MSG_MT_CORE, NULL, (u8 *)&wbuf, 4, 7, NULL, 0, NULL); ret = slim_processtxn(ctrl, &txn, false); if (ret) goto revert_reconfig; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_ACTIVATE_CHANNEL, 0, SLIM_MSG_MT_CORE, NULL, (u8 *)&wbuf, 1, 4, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_ACTIVATE_CHANNEL; txn.len = 1; txn.rl = 4; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto revert_reconfig; } Loading @@ -2865,10 +2850,11 @@ int slim_reconfigure_now(struct slim_device *sb) struct slim_ich *slc = &ctrl->chans[pch->chan]; dev_dbg(&ctrl->dev, "remove chan:%x\n", pch->chan); wbuf[0] = slc->chan; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_REMOVE_CHANNEL, 0, SLIM_MSG_MT_CORE, NULL, wbuf, 1, 4, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_REMOVE_CHANNEL; txn.len = 1; txn.rl = 4; txn.wbuf = wbuf; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto revert_reconfig; } Loading @@ -2876,10 +2862,11 @@ int slim_reconfigure_now(struct slim_device *sb) struct slim_ich *slc = &ctrl->chans[pch->chan]; dev_dbg(&ctrl->dev, "suspend chan:%x\n", pch->chan); wbuf[0] = slc->chan; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_DEACTIVATE_CHANNEL, 0, SLIM_MSG_MT_CORE, NULL, wbuf, 1, 4, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_DEACTIVATE_CHANNEL; txn.len = 1; txn.rl = 4; txn.wbuf = wbuf; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto revert_reconfig; } Loading Loading @@ -2908,10 +2895,11 @@ int slim_reconfigure_now(struct slim_device *sb) wbuf[2] = (u8)((segdist & 0xF00) >> 8) | (slc->prop.prot << 4); wbuf[3] = slc->seglen; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_DEFINE_CHANNEL, 0, SLIM_MSG_MT_CORE, NULL, (u8 *)wbuf, 4, 7, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_DEFINE_CHANNEL; txn.len = 4; txn.rl = 7; txn.wbuf = wbuf; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto revert_reconfig; } Loading Loading @@ -2941,17 +2929,20 @@ int slim_reconfigure_now(struct slim_device *sb) wbuf[2] = (u8)((segdist & 0xF00) >> 8) | (slc->prop.prot << 4); wbuf[3] = (u8)(slc->seglen); ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_NEXT_DEFINE_CHANNEL, 0, SLIM_MSG_MT_CORE, NULL, (u8 *)wbuf, 4, 7, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_NEXT_DEFINE_CHANNEL; txn.len = 4; txn.rl = 7; txn.wbuf = wbuf; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto revert_reconfig; } } ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_MC_RECONFIGURE_NOW, 0, SLIM_MSG_MT_CORE, NULL, NULL, 0, 3, NULL, 0, NULL); txn.mc = SLIM_MSG_MC_RECONFIGURE_NOW; txn.len = 0; txn.rl = 3; txn.wbuf = NULL; ret = slim_processtxn(ctrl, &txn, false); dev_dbg(&ctrl->dev, "reconfig now:ret:%d\n", ret); if (!ret) { ctrl->sched.subfrmcode = subframe; Loading Loading @@ -3128,6 +3119,9 @@ int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup, u8 restart) { int ret = 0; int i; DEFINE_SLIM_BCAST_TXN(txn, SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_BEGIN_RECONFIGURATION, 0, 3, NULL, NULL, 0); if (wakeup == false && restart > SLIM_CLK_UNSPECIFIED) return -EINVAL; Loading Loading @@ -3211,21 +3205,23 @@ int slim_ctrl_clk_pause(struct slim_controller *ctrl, bool wakeup, u8 restart) goto clk_pause_ret; } ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_BEGIN_RECONFIGURATION, 0, SLIM_MSG_MT_CORE, NULL, NULL, 0, 3, NULL, 0, NULL); ret = slim_processtxn(ctrl, &txn, false); if (ret) goto clk_pause_ret; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_NEXT_PAUSE_CLOCK, 0, SLIM_MSG_MT_CORE, NULL, &restart, 1, 4, NULL, 0, NULL); txn.mc = SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_NEXT_PAUSE_CLOCK; txn.len = 1; txn.rl = 4; txn.wbuf = &restart; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto clk_pause_ret; ret = slim_processtxn(ctrl, SLIM_MSG_DEST_BROADCAST, SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_RECONFIGURE_NOW, 0, SLIM_MSG_MT_CORE, NULL, NULL, 0, 3, NULL, 0, NULL); txn.mc = SLIM_MSG_CLK_PAUSE_SEQ_FLG | SLIM_MSG_MC_RECONFIGURE_NOW; txn.len = 0; txn.rl = 3; txn.wbuf = NULL; ret = slim_processtxn(ctrl, &txn, false); if (ret) goto clk_pause_ret; Loading
include/linux/slimbus/slimbus.h +6 −2 Original line number Diff line number Diff line /* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2015, 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 @@ -24,6 +24,7 @@ extern struct bus_type slimbus_type; /* Standard values per SLIMbus spec needed by controllers and devices */ #define SLIM_CL_PER_SUPERFRAME 6144 #define SLIM_CL_PER_SUPERFRAME_DIV8 (SLIM_CL_PER_SUPERFRAME >> 3) #define SLIM_MAX_TXNS 256 #define SLIM_MAX_CLK_GEAR 10 #define SLIM_MIN_CLK_GEAR 1 #define SLIM_CL_PER_SL 4 Loading Loading @@ -171,6 +172,7 @@ struct slim_addrt { * (e.g. relevant for mc = SLIM_MSG_MC_REQUEST_INFORMATION) * @la: Logical address of the device this message is going to. * (Not used when destination type is broadcast.) * @async: If this transaction is async * @rbuf: Buffer to be populated by controller when response is received. * @wbuf: Payload of the message. (e.g. channel number for DATA channel APIs) * @comp: Completion structure. Used by controller to notify response. Loading @@ -185,6 +187,7 @@ struct slim_msg_txn { u8 len; u8 tid; u8 la; bool async; u8 *rbuf; const u8 *wbuf; struct completion *comp; Loading Loading @@ -544,8 +547,9 @@ struct slim_controller { u8 num_dev; struct list_head devs; struct workqueue_struct *wq; struct slim_msg_txn **txnt; struct slim_msg_txn *txnt[SLIM_MAX_TXNS]; u8 last_tid; spinlock_t txn_lock; struct slim_port *ports; int nports; struct slim_ich *chans; Loading