Merged in masayuki2009/nuttx.nuttx/lc823450_smp_improvement (pull request #554)
lc823450 smp improvement
* arch/arm/src/common: Apply irq_spin APIs to modifyregXX
Replace enter_critical_section with spin_lock_irqsave.
Replace leave_critical_section with spin_unlock_irqrestore.
Please see 6150299f54
as well.
Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
* arch/arm/src/lc823450: Do not use modifyreg32() to enable Mutex.
Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
* arch/arm/src/lc823450: Modify IRQ control for i2s
Interrupt will be handled on CPU0 with this change.
Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
* arch/arm/src/lc823450: Apply irq_spin APIs to dma/syscontrol/usbdev.
Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
* configs/lc823450-xgevk: Assign CPU1 to lpwork
This change will improve load balancing for networking with RNDIS.
Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
* drivers/audio/wm8776.c: Improve stability in SMP mode
Apply irq_spin APIs to improbe performance.
Repeat to process a message to avoid deadlock.
Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
* configs/lc823450-xgevk: Enable SPINLOCK_IRQ and NXPLAYER in rndis
Signed-off-by: Masayuki Ishikawa <Masayuki.Ishikawa@jp.sony.com>
Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
parent
87291e0064
commit
ab96e3fdc7
@ -64,10 +64,10 @@ void modifyreg16(unsigned int addr, uint16_t clearbits, uint16_t setbits)
|
||||
irqstate_t flags;
|
||||
uint16_t regval;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
regval = getreg16(addr);
|
||||
regval &= ~clearbits;
|
||||
regval |= setbits;
|
||||
putreg16(regval, addr);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
}
|
||||
|
@ -64,10 +64,10 @@ void modifyreg32(unsigned int addr, uint32_t clearbits, uint32_t setbits)
|
||||
irqstate_t flags;
|
||||
uint32_t regval;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
regval = getreg32(addr);
|
||||
regval &= ~clearbits;
|
||||
regval |= setbits;
|
||||
putreg32(regval, addr);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
}
|
||||
|
@ -64,10 +64,10 @@ void modifyreg8(unsigned int addr, uint8_t clearbits, uint8_t setbits)
|
||||
irqstate_t flags;
|
||||
uint8_t regval;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
regval = getreg8(addr);
|
||||
regval &= ~clearbits;
|
||||
regval |= setbits;
|
||||
putreg8(regval, addr);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
}
|
||||
|
@ -218,14 +218,14 @@ static int phydmastart(struct lc823450_phydmach_s *pdmach)
|
||||
struct lc823450_dmach_s *dmach;
|
||||
sq_entry_t *q_ent;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
|
||||
q_ent = pdmach->req_q.tail;
|
||||
|
||||
if (!q_ent)
|
||||
{
|
||||
pdmach->inprogress = 0;
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -288,7 +288,7 @@ static int phydmastart(struct lc823450_phydmach_s *pdmach)
|
||||
|
||||
modifyreg32(DMACCFG(dmach->chn), 0, DMACCFG_ITC | DMACCFG_E);
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -614,7 +614,7 @@ int lc823450_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
|
||||
|
||||
/* select physical channel */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
|
||||
sq_addfirst(&dmach->q_ent, &g_dma.phydmach[dmach->chn].req_q);
|
||||
|
||||
@ -628,7 +628,7 @@ int lc823450_dmastart(DMA_HANDLE handle, dma_callback_t callback, void *arg)
|
||||
phydmastart(&g_dma.phydmach[dmach->chn]);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
|
||||
return OK;
|
||||
}
|
||||
@ -645,7 +645,7 @@ void lc823450_dmastop(DMA_HANDLE handle)
|
||||
|
||||
DEBUGASSERT(dmach);
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
|
||||
modifyreg32(DMACCFG(dmach->chn), DMACCFG_ITC | DMACCFG_E, 0);
|
||||
|
||||
@ -660,6 +660,6 @@ void lc823450_dmastop(DMA_HANDLE handle)
|
||||
sq_rem(&dmach->q_ent, &pdmach->req_q);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
return;
|
||||
}
|
||||
|
@ -280,9 +280,9 @@ static uint32_t lc823450_i2s_txdatawidth(struct i2s_dev_s *dev, int bits)
|
||||
|
||||
static int _i2s_isr(int irq, FAR void *context, FAR void *arg)
|
||||
{
|
||||
/* disable interrupt */
|
||||
/* Disable Buffer F Under Level IRQ */
|
||||
|
||||
up_disable_irq(LC823450_IRQ_AUDIOBUF0);
|
||||
putreg32(0, ABUFIRQEN0);
|
||||
|
||||
/* post semaphore for the waiter */
|
||||
|
||||
@ -298,9 +298,9 @@ static int lc823450_i2s_send(struct i2s_dev_s *dev, struct ap_buffer_s *apb,
|
||||
i2s_callback_t callback, void *arg,
|
||||
uint32_t timeout)
|
||||
{
|
||||
/* Enable IRQ for Audio Buffer */
|
||||
/* Enable Buffer F Under Level IRQ */
|
||||
|
||||
up_enable_irq(LC823450_IRQ_AUDIOBUF0);
|
||||
putreg32(ABUFIRQEN0_BFULIRQEN, ABUFIRQEN0);
|
||||
|
||||
/* Wait for Audio Buffer */
|
||||
|
||||
@ -374,10 +374,6 @@ static int lc823450_i2s_configure(void)
|
||||
|
||||
putreg32(1024, BUF_F_ULVL);
|
||||
|
||||
/* Enable Buffer F Under Level IRQ */
|
||||
|
||||
putreg32(ABUFIRQEN0_BFULIRQEN, ABUFIRQEN0);
|
||||
|
||||
/* Clear Audio Buffer */
|
||||
|
||||
putreg32(0xffff, ABUFCLR);
|
||||
@ -466,6 +462,10 @@ FAR struct i2s_dev_s *lc823450_i2sdev_initialize(void)
|
||||
|
||||
irq_attach(LC823450_IRQ_AUDIOBUF0, _i2s_isr, NULL);
|
||||
|
||||
/* Enable IRQ for Audio Buffer */
|
||||
|
||||
up_enable_irq(LC823450_IRQ_AUDIOBUF0);
|
||||
|
||||
/* Success exit */
|
||||
|
||||
return &priv->dev;
|
||||
|
@ -259,9 +259,12 @@ void __start(void)
|
||||
#endif /* CONFIG_LC823450_IPL2 */
|
||||
#endif /* CONFIG_LC823450_SPIFLASH_BOOT */
|
||||
|
||||
/* Mutex enable */
|
||||
/* Enable Mutex */
|
||||
/* NOTE: modyfyreg32() can not be used because it might use spin_lock */
|
||||
|
||||
modifyreg32(MRSTCNTBASIC, 0, MRSTCNTBASIC_MUTEX_RSTB);
|
||||
uint32_t val = getreg32(MRSTCNTBASIC);
|
||||
val |= MRSTCNTBASIC_MUTEX_RSTB;
|
||||
putreg32(val, MRSTCNTBASIC);
|
||||
|
||||
/* Configure the uart so that we can get debug output as soon as possible */
|
||||
|
||||
|
@ -144,7 +144,7 @@ void mod_stby_regs(uint32_t enabits, uint32_t disbits)
|
||||
void up_enable_clk(enum clock_e clk)
|
||||
{
|
||||
irqstate_t flags;
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
|
||||
ASSERT(clk < LC823450_CLOCK_NUM);
|
||||
|
||||
@ -154,7 +154,7 @@ void up_enable_clk(enum clock_e clk)
|
||||
0, lc823450_clocks[clk].regmask);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -164,7 +164,7 @@ void up_enable_clk(enum clock_e clk)
|
||||
void up_disable_clk(enum clock_e clk)
|
||||
{
|
||||
irqstate_t flags;
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
|
||||
ASSERT(clk < LC823450_CLOCK_NUM);
|
||||
|
||||
@ -181,7 +181,7 @@ void up_disable_clk(enum clock_e clk)
|
||||
lc823450_clocks[clk].count = 0;
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -487,7 +487,7 @@ static int lc823450_epclearreq(struct usbdev_ep_s *ep)
|
||||
struct lc823450_ep_s *privep = (struct lc823450_ep_s *)ep;
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
while (privep->req_q.tail)
|
||||
{
|
||||
struct usbdev_req_s *req;
|
||||
@ -504,7 +504,7 @@ static int lc823450_epclearreq(struct usbdev_ep_s *ep)
|
||||
req->callback(ep, req);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -666,27 +666,27 @@ static int lc823450_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
|
||||
|
||||
if (privep->epphy == 0)
|
||||
{
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
req->xfrd = epbuf_write(privep->epphy, req->buf, req->len);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
req->callback(ep, req);
|
||||
}
|
||||
else if (privep->in)
|
||||
{
|
||||
/* Send packet requst from function driver */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
|
||||
if ((getreg32(USB_EPCOUNT(privep->epphy * 2)) &
|
||||
USB_EPCOUNT_PHYCNT_MASK) >> USB_EPCOUNT_PHYCNT_SHIFT ||
|
||||
privep->req_q.tail)
|
||||
{
|
||||
sq_addfirst(&privreq->q_ent, &privep->req_q); /* non block */
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
req->xfrd = epbuf_write(privep->epphy, req->buf, req->len);
|
||||
req->callback(ep, req);
|
||||
}
|
||||
@ -695,9 +695,9 @@ static int lc823450_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
|
||||
{
|
||||
/* receive packet buffer from function driver */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
sq_addfirst(&privreq->q_ent, &privep->req_q); /* non block */
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
lc823450_epack(privep->epphy, 1);
|
||||
}
|
||||
|
||||
@ -738,7 +738,7 @@ static int lc823450_epstall(struct usbdev_ep_s *ep, bool resume)
|
||||
|
||||
/* STALL or RESUME the endpoint */
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
usbtrace(resume ? TRACE_EPRESUME : TRACE_EPSTALL, privep->epphy);
|
||||
|
||||
if (resume)
|
||||
@ -752,7 +752,7 @@ static int lc823450_epstall(struct usbdev_ep_s *ep, bool resume)
|
||||
epcmd_write(privep->epphy, USB_EPCMD_STALL_SET | USB_EPCMD_TGL_SET);
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -761,11 +761,11 @@ void up_epignore_clear_stall(struct usbdev_ep_s *ep, bool ignore)
|
||||
{
|
||||
struct lc823450_ep_s *privep = (struct lc823450_ep_s *)ep;
|
||||
irqstate_t flags;
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
|
||||
privep->ignore_clear_stall = ignore;
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
}
|
||||
#endif /* CONFIG_USBMSC_IGNORE_CLEAR_STALL */
|
||||
|
||||
@ -922,7 +922,7 @@ static void usb_suspend_work_func(void *arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
if (getreg32(USB_DEVS) & USB_DEVS_SUSPEND)
|
||||
{
|
||||
uinfo("USB BUS SUSPEND\n");
|
||||
@ -936,7 +936,7 @@ static void usb_suspend_work_func(void *arg)
|
||||
g_usbsuspend = 1;
|
||||
wake_unlock(&priv->wlock);
|
||||
}
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1630,7 +1630,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
|
||||
* canceled while the class driver is still bound.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
|
||||
#ifdef CONFIG_WAKELOCK
|
||||
/* cancel USB suspend work */
|
||||
@ -1666,7 +1666,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
|
||||
pm_unregister(&pm_cb);
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
|
||||
#ifdef CONFIG_LC823450_LSISTBY
|
||||
/* disable USB */
|
||||
@ -1915,7 +1915,7 @@ static void usbdev_pmnotify(struct pm_callback_s *cb, enum pm_state_e pmstate)
|
||||
{
|
||||
irqstate_t flags;
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
|
||||
switch (pmstate)
|
||||
{
|
||||
@ -1936,6 +1936,6 @@ static void usbdev_pmnotify(struct pm_callback_s *cb, enum pm_state_e pmstate)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
}
|
||||
#endif
|
||||
|
@ -122,6 +122,7 @@ CONFIG_NSH_WGET_USERAGENT="NuttX/7.2x.x (; http://www.nuttx.org/)"
|
||||
CONFIG_NX_BLOCKING=y
|
||||
# CONFIG_NX_DISABLE_1BPP is not set
|
||||
CONFIG_NXFONT_MONO5X8=y
|
||||
CONFIG_NXPLAYER_DEFAULT_MEDIADIR="/mnt/sd1"
|
||||
CONFIG_NX=y
|
||||
CONFIG_PIPES=y
|
||||
CONFIG_POSIX_SPAWN_PROXY_STACKSIZE=2048
|
||||
@ -154,11 +155,13 @@ CONFIG_SERIAL_TERMIOS=y
|
||||
CONFIG_SMP_NCPUS=2
|
||||
CONFIG_SMP=y
|
||||
# CONFIG_SPI_EXCHANGE is not set
|
||||
CONFIG_SPINLOCK_IRQ=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_START_DAY=3
|
||||
CONFIG_START_MONTH=10
|
||||
CONFIG_START_YEAR=2013
|
||||
CONFIG_SYSTEM_I2CTOOL=y
|
||||
CONFIG_SYSTEM_NXPLAYER=y
|
||||
CONFIG_SYSTEM_PING=y
|
||||
CONFIG_TASK_NAME_SIZE=24
|
||||
CONFIG_UART0_RXBUFSIZE=512
|
||||
|
@ -45,6 +45,10 @@
|
||||
#include <stdbool.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
# include <sched.h>
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_RNDIS
|
||||
# include <nuttx/usb/rndis.h>
|
||||
#endif
|
||||
@ -112,6 +116,16 @@ int lc823450_bringup(void)
|
||||
usbdev_rndis_initialize(mac);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SMP) && defined (CONFIG_RNDIS)
|
||||
cpu_set_t cpuset;
|
||||
CPU_ZERO(&cpuset);
|
||||
CPU_SET(1, &cpuset); /* assigned to CPU1 */
|
||||
|
||||
/* NOTE: pid=4 is assumed to be lpwork */
|
||||
|
||||
sched_setaffinity(4, sizeof(cpu_set_t), &cpuset);
|
||||
#endif
|
||||
|
||||
/* If we got here then perhaps not all initialization was successful, but
|
||||
* at least enough succeeded to bring-up NSH with perhaps reduced
|
||||
* capabilities.
|
||||
|
@ -538,7 +538,7 @@ static void wm8776_senddone(FAR struct i2s_dev_s *i2s,
|
||||
* against that possibility.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
|
||||
/* Add the completed buffer to the end of our doneq. We do not yet
|
||||
* decrement the reference count.
|
||||
@ -555,7 +555,7 @@ static void wm8776_senddone(FAR struct i2s_dev_s *i2s,
|
||||
/* REVISIT: This can be overwritten */
|
||||
|
||||
priv->result = result;
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
|
||||
/* Now send a message to the worker thread, informing it that there are
|
||||
* buffers in the done queue that need to be cleaned up.
|
||||
@ -590,13 +590,13 @@ static void wm8776_returnbuffers(FAR struct wm8776_dev_s *priv)
|
||||
* use interrupt controls to protect against that possibility.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
while (dq_peek(&priv->doneq) != NULL)
|
||||
{
|
||||
/* Take the next buffer from the queue of completed transfers */
|
||||
|
||||
apb = (FAR struct ap_buffer_s *)dq_remfirst(&priv->doneq);
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
|
||||
audinfo("Returning: apb=%p curbyte=%d nbytes=%d flags=%04x\n",
|
||||
apb, apb->curbyte, apb->nbytes, apb->flags);
|
||||
@ -631,10 +631,10 @@ static void wm8776_returnbuffers(FAR struct wm8776_dev_s *priv)
|
||||
#else
|
||||
priv->dev.upper(priv->dev.priv, AUDIO_CALLBACK_DEQUEUE, apb, OK);
|
||||
#endif
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
}
|
||||
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -682,9 +682,9 @@ static int wm8776_sendbuffer(FAR struct wm8776_dev_s *priv)
|
||||
* to avoid a possible race condition.
|
||||
*/
|
||||
|
||||
flags = enter_critical_section();
|
||||
flags = spin_lock_irqsave();
|
||||
priv->inflight++;
|
||||
leave_critical_section(flags);
|
||||
spin_unlock_irqrestore(flags);
|
||||
|
||||
shift = (priv->bpsamp == 8) ? 14 - 3 : 14 - 4;
|
||||
shift -= (priv->nchannels > 1) ? 1 : 0;
|
||||
@ -1153,6 +1153,7 @@ static void *wm8776_workerthread(pthread_addr_t pvarg)
|
||||
FAR struct ap_buffer_s *apb;
|
||||
int msglen;
|
||||
int prio;
|
||||
struct mq_attr attr;
|
||||
|
||||
audinfo("Entry\n");
|
||||
|
||||
@ -1187,6 +1188,8 @@ static void *wm8776_workerthread(pthread_addr_t pvarg)
|
||||
wm8776_sendbuffer(priv);
|
||||
}
|
||||
|
||||
repeat:
|
||||
|
||||
/* Wait for messages from our message queue */
|
||||
|
||||
msglen = mq_receive(priv->mq, (FAR char *)&msg, sizeof(msg), &prio);
|
||||
@ -1241,6 +1244,16 @@ static void *wm8776_workerthread(pthread_addr_t pvarg)
|
||||
auderr("ERROR: Ignoring message ID %d\n", msg.msgId);
|
||||
break;
|
||||
}
|
||||
|
||||
(void)mq_getattr(priv->mq, &attr);
|
||||
|
||||
/* If there is a message in the queue, process it */
|
||||
|
||||
if (0 < attr.mq_curmsgs)
|
||||
{
|
||||
goto repeat;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Reset the WM8776 hardware */
|
||||
|
Loading…
Reference in New Issue
Block a user