drivers/net/{e1000|igc}: fix link status crash
netdev_lower_carrier_xxx API can't be used in interrupt context Signed-off-by: p-szafonimateusz <p-szafonimateusz@xiaomi.com>
This commit is contained in:
parent
5e48f2a3d8
commit
ada47439bd
2 changed files with 85 additions and 28 deletions
|
@ -140,6 +140,7 @@ struct e1000_driver_s
|
|||
/* This holds the information visible to the NuttX network */
|
||||
|
||||
struct netdev_lowerhalf_s dev;
|
||||
struct work_s work;
|
||||
|
||||
/* Driver state */
|
||||
|
||||
|
@ -657,6 +658,39 @@ static void e1000_txdone(FAR struct netdev_lowerhalf_s *dev)
|
|||
netdev_lower_txdone(dev);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Name: e1000_link_work
|
||||
*
|
||||
* Description:
|
||||
* Handle link status change.
|
||||
*
|
||||
* Input Parameters:
|
||||
* arg - Reference to the lover half driver structure (cast to void *)
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static void e1000_link_work(FAR void *arg)
|
||||
{
|
||||
FAR struct e1000_driver_s *priv = arg;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = e1000_getreg_mem(priv, E1000_STATUS);
|
||||
if (tmp & E1000_STATUS_LU)
|
||||
{
|
||||
ninfo("Link up, status = 0x%x\n", tmp);
|
||||
|
||||
netdev_lower_carrier_on(&priv->dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
ninfo("Link down\n");
|
||||
netdev_lower_carrier_off(&priv->dev);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Name: e1000_msi_interupt
|
||||
*
|
||||
|
@ -677,7 +711,6 @@ static void e1000_txdone(FAR struct netdev_lowerhalf_s *dev)
|
|||
static void e1000_msi_interrupt(FAR struct e1000_driver_s *priv)
|
||||
{
|
||||
uint32_t status;
|
||||
uint32_t tmp;
|
||||
|
||||
status = e1000_getreg_mem(priv, E1000_ICR);
|
||||
ninfo("irq status = 0x%" PRIx32 "\n", status);
|
||||
|
@ -701,16 +734,13 @@ static void e1000_msi_interrupt(FAR struct e1000_driver_s *priv)
|
|||
|
||||
if (status & E1000_IC_LSC)
|
||||
{
|
||||
tmp = e1000_getreg_mem(priv, E1000_STATUS);
|
||||
if (tmp & E1000_STATUS_LU)
|
||||
if (work_available(&priv->work))
|
||||
{
|
||||
ninfo("Link up, status = 0x%x\n", tmp);
|
||||
netdev_lower_carrier_on(&priv->dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
ninfo("Link down\n");
|
||||
netdev_lower_carrier_off(&priv->dev);
|
||||
/* Schedule to work queue because netdev_lower_carrier_xxx API
|
||||
* can't be used in interrupt context
|
||||
*/
|
||||
|
||||
work_queue(LPWORK, &priv->work, e1000_link_work, priv, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -773,15 +803,13 @@ static void e1000_msix_interrupt(FAR struct e1000_driver_s *priv)
|
|||
|
||||
if (status & E1000_IC_LSC)
|
||||
{
|
||||
if (e1000_getreg_mem(priv, E1000_STATUS) & E1000_STATUS_LU)
|
||||
if (work_available(&priv->work))
|
||||
{
|
||||
ninfo("Link up\n");
|
||||
netdev_lower_carrier_on(&priv->dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
ninfo("Link down\n");
|
||||
netdev_lower_carrier_off(&priv->dev);
|
||||
/* Schedule to work queue because netdev_lower_carrier_xxx API
|
||||
* can't be used in interrupt context
|
||||
*/
|
||||
|
||||
work_queue(LPWORK, &priv->work, e1000_link_work, priv, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,6 +121,7 @@ struct igc_driver_s
|
|||
/* This holds the information visible to the NuttX network */
|
||||
|
||||
struct netdev_lowerhalf_s dev;
|
||||
struct work_s work;
|
||||
|
||||
/* Driver state */
|
||||
|
||||
|
@ -613,6 +614,38 @@ static void igc_txdone(FAR struct netdev_lowerhalf_s *dev)
|
|||
netdev_lower_txdone(dev);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Name: igc_link_work
|
||||
*
|
||||
* Description:
|
||||
* Handle link status change.
|
||||
*
|
||||
* Input Parameters:
|
||||
* arg - Reference to the lover half driver structure (cast to void *)
|
||||
*
|
||||
* Returned Value:
|
||||
* None
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
static void igc_link_work(FAR void *arg)
|
||||
{
|
||||
FAR struct igc_driver_s *priv = arg;
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = igc_getreg_mem(priv, IGC_STATUS);
|
||||
if (tmp & IGC_STATUS_LU)
|
||||
{
|
||||
ninfo("Link up, status = 0x%x\n", tmp);
|
||||
netdev_lower_carrier_on(&priv->dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
ninfo("Link down\n");
|
||||
netdev_lower_carrier_off(&priv->dev);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Name: igc_misx_interrupt
|
||||
*
|
||||
|
@ -634,7 +667,6 @@ static void igc_msix_interrupt(FAR struct igc_driver_s *priv)
|
|||
{
|
||||
uint32_t icr = 0;
|
||||
uint32_t eicr = 0;
|
||||
uint32_t tmp = 0;
|
||||
|
||||
/* Get interrupts */
|
||||
|
||||
|
@ -661,16 +693,13 @@ static void igc_msix_interrupt(FAR struct igc_driver_s *priv)
|
|||
|
||||
if (icr & IGC_IC_LSC)
|
||||
{
|
||||
tmp = igc_getreg_mem(priv, IGC_STATUS);
|
||||
if (tmp & IGC_STATUS_LU)
|
||||
if (work_available(&priv->work))
|
||||
{
|
||||
ninfo("Link up, status = 0x%x\n", tmp);
|
||||
netdev_lower_carrier_on(&priv->dev);
|
||||
}
|
||||
else
|
||||
{
|
||||
ninfo("Link down\n");
|
||||
netdev_lower_carrier_off(&priv->dev);
|
||||
/* Schedule to work queue because netdev_lower_carrier_xxx API
|
||||
* can't be used in interrupt context
|
||||
*/
|
||||
|
||||
work_queue(LPWORK, &priv->work, igc_link_work, priv, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue