Loading src/drivers/ata/ahci_elphel.c +23 −9 Original line number Original line Diff line number Diff line Loading @@ -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 */ /** 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) 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; size_t slot = (dpriv->tail_ptr + 1) % MAX_CMD_SLOTS; spin_lock_irqsave(&dpriv->flags_lock, irq_flags); if (slot != dpriv->head_ptr) { if (slot != dpriv->head_ptr) { set_flag(dpriv, LOCK_TAIL); dpriv->flags |= LOCK_TAIL; dpriv->tail_ptr = slot; dpriv->tail_ptr = slot; dev_dbg(dpriv->dev, "move tail pointer to slot: %u\n", slot); ret = 0; return 0; } else { } else { /* no more free command slots */ /* 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*/ /** 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) static int move_head(struct elphel_ahci_priv *dpriv) { { int ret; size_t use_tail; size_t use_tail; unsigned long irq_flags; unsigned long irq_flags; size_t slot = (dpriv->head_ptr + 1) % MAX_CMD_SLOTS; size_t slot = (dpriv->head_ptr + 1) % MAX_CMD_SLOTS; Loading @@ -1212,17 +1221,19 @@ static int move_head(struct elphel_ahci_priv *dpriv) } else { } else { use_tail = dpriv->tail_ptr; use_tail = dpriv->tail_ptr; } } spin_unlock_irqrestore(&dpriv->flags_lock, irq_flags); if (dpriv->head_ptr != use_tail) { if (dpriv->head_ptr != use_tail) { dpriv->head_ptr = slot; dpriv->head_ptr = slot; dev_dbg(dpriv->dev, "move head pointer to slot: %u\n", slot); ret = 0; return 0; } else { } else { /* no more commands in queue */ /* 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 */ /** Check if command queue is empty */ Loading Loading @@ -1382,6 +1393,7 @@ static ssize_t rawdev_write(struct device *dev, ///< device structure associate } else { } else { dpriv->flags |= DELAYED_FINISH; dpriv->flags |= DELAYED_FINISH; } } dpriv->datascope.reg_stat[CMD_RCVD] = dpriv->datascope.reg_stat[CMD_RCVD] + 1; return buff_sz; return buff_sz; } } Loading Loading @@ -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 */ /* new command slot is ready now and can be unlocked */ reset_flag(dpriv, LOCK_TAIL); reset_flag(dpriv, LOCK_TAIL); dpriv->datascope.reg_stat[CMD_RCVD] = dpriv->datascope.reg_stat[CMD_RCVD] + 1; if (!proceed) { if (!proceed) { /* disk may be free by the moment, try to grab it */ /* disk may be free by the moment, try to grab it */ spin_lock_irqsave(&dpriv->flags_lock, irq_flags); spin_lock_irqsave(&dpriv->flags_lock, irq_flags); Loading src/drivers/ata/ahci_elphel.h +2 −1 Original line number Original line Diff line number Diff line Loading @@ -83,7 +83,8 @@ enum { REG_PxSERR, ///< value of PxSERR in data buffer REG_PxSERR, ///< value of PxSERR in data buffer IRQ_COUNTER, ///< interrupts counter for internal commands IRQ_COUNTER, ///< interrupts counter for internal commands IRQ_COUNTER_SYS, ///< interrupts counter for system 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 { struct datascope { void __iomem *timestamp_reg; ///< register in vendor specific address range (PxVS) where timestamp can be written void __iomem *timestamp_reg; ///< register in vendor specific address range (PxVS) where timestamp can be written Loading Loading
src/drivers/ata/ahci_elphel.c +23 −9 Original line number Original line Diff line number Diff line Loading @@ -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 */ /** 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) 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; size_t slot = (dpriv->tail_ptr + 1) % MAX_CMD_SLOTS; spin_lock_irqsave(&dpriv->flags_lock, irq_flags); if (slot != dpriv->head_ptr) { if (slot != dpriv->head_ptr) { set_flag(dpriv, LOCK_TAIL); dpriv->flags |= LOCK_TAIL; dpriv->tail_ptr = slot; dpriv->tail_ptr = slot; dev_dbg(dpriv->dev, "move tail pointer to slot: %u\n", slot); ret = 0; return 0; } else { } else { /* no more free command slots */ /* 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*/ /** 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) static int move_head(struct elphel_ahci_priv *dpriv) { { int ret; size_t use_tail; size_t use_tail; unsigned long irq_flags; unsigned long irq_flags; size_t slot = (dpriv->head_ptr + 1) % MAX_CMD_SLOTS; size_t slot = (dpriv->head_ptr + 1) % MAX_CMD_SLOTS; Loading @@ -1212,17 +1221,19 @@ static int move_head(struct elphel_ahci_priv *dpriv) } else { } else { use_tail = dpriv->tail_ptr; use_tail = dpriv->tail_ptr; } } spin_unlock_irqrestore(&dpriv->flags_lock, irq_flags); if (dpriv->head_ptr != use_tail) { if (dpriv->head_ptr != use_tail) { dpriv->head_ptr = slot; dpriv->head_ptr = slot; dev_dbg(dpriv->dev, "move head pointer to slot: %u\n", slot); ret = 0; return 0; } else { } else { /* no more commands in queue */ /* 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 */ /** Check if command queue is empty */ Loading Loading @@ -1382,6 +1393,7 @@ static ssize_t rawdev_write(struct device *dev, ///< device structure associate } else { } else { dpriv->flags |= DELAYED_FINISH; dpriv->flags |= DELAYED_FINISH; } } dpriv->datascope.reg_stat[CMD_RCVD] = dpriv->datascope.reg_stat[CMD_RCVD] + 1; return buff_sz; return buff_sz; } } Loading Loading @@ -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 */ /* new command slot is ready now and can be unlocked */ reset_flag(dpriv, LOCK_TAIL); reset_flag(dpriv, LOCK_TAIL); dpriv->datascope.reg_stat[CMD_RCVD] = dpriv->datascope.reg_stat[CMD_RCVD] + 1; if (!proceed) { if (!proceed) { /* disk may be free by the moment, try to grab it */ /* disk may be free by the moment, try to grab it */ spin_lock_irqsave(&dpriv->flags_lock, irq_flags); spin_lock_irqsave(&dpriv->flags_lock, irq_flags); Loading
src/drivers/ata/ahci_elphel.h +2 −1 Original line number Original line Diff line number Diff line Loading @@ -83,7 +83,8 @@ enum { REG_PxSERR, ///< value of PxSERR in data buffer REG_PxSERR, ///< value of PxSERR in data buffer IRQ_COUNTER, ///< interrupts counter for internal commands IRQ_COUNTER, ///< interrupts counter for internal commands IRQ_COUNTER_SYS, ///< interrupts counter for system 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 { struct datascope { void __iomem *timestamp_reg; ///< register in vendor specific address range (PxVS) where timestamp can be written void __iomem *timestamp_reg; ///< register in vendor specific address range (PxVS) where timestamp can be written Loading