Commit 65b5b0e1 authored by Mikhail Karpenko's avatar Mikhail Karpenko

Update locking for queue pointers

parent 0564ebaf
......@@ -1185,22 +1185,31 @@ static void finish_rec(struct elphel_ahci_priv *dpriv)
/** Move a pointer to free command slot one step forward. This function holds spin lock #elphel_ahci_priv::flags_lock */
static int move_tail(struct elphel_ahci_priv *dpriv)
{
int ret;
unsigned long irq_flags;
size_t slot = (dpriv->tail_ptr + 1) % MAX_CMD_SLOTS;
spin_lock_irqsave(&dpriv->flags_lock, irq_flags);
if (slot != dpriv->head_ptr) {
set_flag(dpriv, LOCK_TAIL);
dpriv->flags |= LOCK_TAIL;
dpriv->tail_ptr = slot;
dev_dbg(dpriv->dev, "move tail pointer to slot: %u\n", slot);
return 0;
ret = 0;
} else {
/* no more free command slots */
return -1;
ret = -1;
}
spin_unlock_irqrestore(&dpriv->flags_lock, irq_flags);
if (ret == 0)
dev_dbg(dpriv->dev, "move tail pointer to slot: %u\n", slot);
return ret;
}
/** Move a pointer to next ready command. This function holds spin lock #elphel_ahci_priv::flags_lock*/
static int move_head(struct elphel_ahci_priv *dpriv)
{
int ret;
size_t use_tail;
unsigned long irq_flags;
size_t slot = (dpriv->head_ptr + 1) % MAX_CMD_SLOTS;
......@@ -1212,17 +1221,19 @@ static int move_head(struct elphel_ahci_priv *dpriv)
} else {
use_tail = dpriv->tail_ptr;
}
spin_unlock_irqrestore(&dpriv->flags_lock, irq_flags);
if (dpriv->head_ptr != use_tail) {
dpriv->head_ptr = slot;
dev_dbg(dpriv->dev, "move head pointer to slot: %u\n", slot);
return 0;
ret = 0;
} else {
/* no more commands in queue */
return -1;
ret = -1;
}
spin_unlock_irqrestore(&dpriv->flags_lock, irq_flags);
if (ret == 0)
dev_dbg(dpriv->dev, "move head pointer to slot: %u\n", slot);
return ret;
}
/** Check if command queue is empty */
......@@ -1382,6 +1393,7 @@ static ssize_t rawdev_write(struct device *dev, ///< device structure associate
} else {
dpriv->flags |= DELAYED_FINISH;
}
dpriv->datascope.reg_stat[CMD_RCVD] = dpriv->datascope.reg_stat[CMD_RCVD] + 1;
return buff_sz;
}
......@@ -1440,6 +1452,8 @@ static ssize_t rawdev_write(struct device *dev, ///< device structure associate
/* new command slot is ready now and can be unlocked */
reset_flag(dpriv, LOCK_TAIL);
dpriv->datascope.reg_stat[CMD_RCVD] = dpriv->datascope.reg_stat[CMD_RCVD] + 1;
if (!proceed) {
/* disk may be free by the moment, try to grab it */
spin_lock_irqsave(&dpriv->flags_lock, irq_flags);
......
......@@ -83,7 +83,8 @@ enum {
REG_PxSERR, ///< value of PxSERR in data buffer
IRQ_COUNTER, ///< interrupts counter for internal commands
IRQ_COUNTER_SYS, ///< interrupts counter for system commands
CMD_SENT ///< number of commands sent
CMD_SENT, ///< number of commands sent
CMD_RCVD ///< number of commands received
};
struct datascope {
void __iomem *timestamp_reg; ///< register in vendor specific address range (PxVS) where timestamp can be written
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment