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:
Masayuki Ishikawa 2017-12-08 12:31:34 +00:00 committed by Gregory Nutt
parent 87291e0064
commit ab96e3fdc7
11 changed files with 87 additions and 54 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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 */

View File

@ -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);
}
/****************************************************************************

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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 */