scsi: Eliminate duplicate barriers on weakly-ordered archs
Subsystems (7)
v4 cover scsi: Eliminate duplicate barriers on weakly-ordered archs
Code includes wmb() followed by writel() in multiple places. writel() already has a barrier on some architectures like arm64.
This ends up CPU observing two barriers back to back before executing the register write.
Since code already has an explicit barrier call, changing writel() to writel_relaxed().
I did a regex search for wmb() followed by writel() in each drivers directory.
I scrubbed the ones I care about in this series.
I considered "ease of change", "popular usage" and "performance critical path" as the determining criteria for my filtering.
We used relaxed API heavily on ARM for a long time but
it did not exist on other architectures. For this reason, relaxed architectures have been paying double penalty in order to use the common drivers.
Now that relaxed API is present on all architectures, we can go and scrub all drivers to see what needs to change and what can remain.
We start with mostly used ones and hope to increase the coverage over time. It will take a while to cover all drivers.
Feel free to apply patches individually.
Changes since v3:
- https://www.spinics.net/lists/arm-kernel/msg641851.html
- group patches together into subsystems scsi:...
- collect reviewed and tested bys
- scrub barrier()
Sinan Kaya (7):
scsi: hpsa: Eliminate duplicate barriers on weakly-ordered archs
scsi: megaraid: eliminate duplicate barriers on weakly-ordered archs
scsi: dpt_i2o: eliminate duplicate barriers on weakly-ordered archs
scsi: lpfc: Eliminate duplicate barriers on weakly-ordered archs
scsi: ipr: Eliminate duplicate barriers on weakly-ordered archs
scsi: bnx2i: Eliminate duplicate barriers on weakly-ordered archs
scsi: csiostor: Eliminate duplicate barriers on weakly-ordered archs
drivers/scsi/bnx2i/bnx2i_hwi.c | 2 +- drivers/scsi/csiostor/csio_hw.h | 4 ++++ drivers/scsi/csiostor/csio_wr.c | 2 +- drivers/scsi/dpt_i2o.c | 6 +++--- drivers/scsi/hpsa.h | 2 +- drivers/scsi/ipr.c | 7 ++++--- drivers/scsi/lpfc/lpfc_sli.c | 4 ++-- drivers/scsi/megaraid/megaraid_mbox.c | 8 ++++---- drivers/scsi/megaraid/megaraid_mbox.h | 2 ++ drivers/scsi/megaraid/megaraid_sas_fusion.c | 4 ++-- 10 files changed, 24 insertions(+), 17 deletions(-)
Signature · 1 line
2.7.4
PATCH v4 1/7 scsi: hpsa: Eliminate duplicate barriers on weakly-ordered archs
Code includes wmb() followed by writel(). writel() already has a barrier on some architectures like arm64.
This ends up CPU observing two barriers back to back before executing the register write.
Since code already has an explicit barrier call, changing writel() to writel_relaxed().
--- drivers/scsi/hpsa.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/hpsa.h +1 -1
@@ -599,7 +599,7 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q)* but with current driver design this is easiest. */ wmb (); -writel ((q <<24 ) | rq->current_entry, h->vaddr + +writel_relaxed ((q <<24 ) | rq->current_entry, h->vaddr +IOACCEL_MODE1_CONSUMER_INDEX );atomic_dec (&h->commands_outstanding); }
Signature · 1 line
2.7.4
PATCH v4 1/7 scsi: hpsa: Eliminate duplicate barriers on weakly-ordered archs
Quoted 18 lines
-----Original Message-----
From: Sinan Kaya [mailto:okaya at codeaurora.org]
Sent: Monday, March 19, 2018 9:50 PM
To: linux-scsi at vger.kernel.org; timur at codeaurora.org; sulrich at codeaurora.org
Cc: linux-arm-msm at vger.kernel.org; linux-arm-kernel at lists.infradead.org; Sinan Kaya <[email protected]>; Don Brace <[email protected]>; James E.J. Bottomley <[email protected]>; Martin K. Petersen <[email protected]>; esc.storagedev <[email protected]>; linux-kernel at vger.kernel.org
Subject: [PATCH v4 1/7] scsi: hpsa: Eliminate duplicate barriers on weakly- ordered archsEXTERNAL EMAIL
Code includes
wmb()followed bywritel().writel()already has a barrier on some architectures like arm64.
Quoted 7 lines
This ends up CPU observing two barriers back to back before executing the register write.
Since code already has an explicit barrier call, changing
writel()towritel_relaxed().Signed-off-by Sinan Kaya <[email protected]>
Quoted 20 lines
--- drivers/scsi/hpsa.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/scsi/hpsa.h +1
-1@@ -599,7 +599,7 @@ static unsigned longSA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q) * but with current driver design this is easiest. */ wmb (); -writel ((q <<24 ) | rq->current_entry, h->vaddr + +writel_relaxed ((q <<24 ) | rq->current_entry, h->vaddr +IOACCEL_MODE1_CONSUMER_INDEX );atomic_dec (&h->commands_outstanding);}--
2.7.4
Re: [PATCH v4 1/7] scsi: hpsa: Eliminate duplicate barriers on weakly-ordered archs
In reply to Sinan KayaQuoted 26 lines · Sinan Kaya
Code includes
wmb()followed bywritel().writel()already has a barrier on some architectures like arm64.This ends up CPU observing two barriers back to back before executing the register write.
Since code already has an explicit barrier call, changing
writel()towritel_relaxed().Signed-off-by Sinan Kaya <[email protected]>---
?drivers/scsi/hpsa.h | 2 +-
?1 file changed, 1 insertion(+), 1 deletion(-)drivers/scsi/hpsa.h +0
-0@@ -599,7 +599,7 @@ static unsigned long SA5_ioaccel_mode1_completed(struct ctlr_info *h, u8 q)? ?* but with current driver design this is easiest.
? ?*/
?wmb();drivers/scsi/hpsa.h +1
-1- writel((q << 24) | rq->current_entry, h->vaddr + + writel_relaxed((q << 24) | rq->current_entry, h-Quoted 1 line
vaddr +
Quoted 3 lines
?
IOACCEL_MODE1_CONSUMER_INDEX);
?atomic_dec(&h->commands_outstanding);
? }
This looks like it would work for the x86_64 and arm because of how its defined architecture specific for the x86_64 and the arm64
I guess its up to Don and the driver folks and if its worth the change. I am generally not a fan of messing with these barrier things though.
PATCH v4 2/7 scsi: megaraid: eliminate duplicate barriers on weakly-ordered archs
In reply to Sinan KayaCode includes barrier() followed by writel(). writel() already has a barrier
on some architectures like arm64.
This ends up CPU observing two barriers back to back before executing the register write.
Create a new wrapper function with relaxed write operator. Use the new wrapper when a write is following a barrier().
Since code already has an explicit barrier call, changing writel() to writel_relaxed().
--- drivers/scsi/megaraid/megaraid_mbox.c | 8 ++++---- drivers/scsi/megaraid/megaraid_mbox.h | 2 ++ drivers/scsi/megaraid/megaraid_sas_fusion.c | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-)
drivers/scsi/megaraid/megaraid_mbox.c +4 -4
@@ -1439,7 +1439,7 @@ mbox_post_cmd(adapter_t *adapter, scb_t *scb) mbox->ack =0 ;wmb (); -WRINDOOR (raid_dev, raid_dev->mbox_dma |0x1 ); +WRINDOOR_RELAXED (raid_dev, raid_dev->mbox_dma |0x1 );spin_unlock_irqrestore (MAILBOX_LOCK (raid_dev), flags);
@@ -2752,7 +2752,7 @@ mbox_post_sync_cmd(adapter_t *adapter, uint8_t raw_mbox[]) mbox->status =0xFF ;wmb (); -WRINDOOR (raid_dev, raid_dev->mbox_dma |0x1 ); +WRINDOOR_RELAXED (raid_dev, raid_dev->mbox_dma |0x1 );// wait for maximum 1 second for status to post. If the status is not // available within 1 second, assume FW is initializing and wait
@@ -2877,7 +2877,7 @@ mbox_post_sync_cmd_fast(adapter_t *adapter, uint8_t raw_mbox[]) mbox->status =0xFF ;wmb (); -WRINDOOR (raid_dev, raid_dev->mbox_dma |0x1 ); +WRINDOOR_RELAXED (raid_dev, raid_dev->mbox_dma |0x1 );for (i =0 ; i <MBOX_SYNC_WAIT_CNT ; i++) {if (mbox->numstatus !=0xFF )break ;
@@ -3329,7 +3329,7 @@ megaraid_mbox_fire_sync_cmd(adapter_t *adapter) mbox->status =0 ;wmb (); -WRINDOOR (raid_dev, raid_dev->mbox_dma |0x1 ); +WRINDOOR_RELAXED (raid_dev, raid_dev->mbox_dma |0x1 );/* Wait for maximum 1 min for status to post. * If the Firmware SUPPORTS the ABOVE COMMAND,
drivers/scsi/megaraid/megaraid_mbox.h +2 -0
@@ -230,6 +230,8 @@ typedef struct {#define RDINDOOR (rdev) readl((rdev)->baseaddr + 0x20)#define RDOUTDOOR (rdev) readl((rdev)->baseaddr + 0x2C) +#define WRINDOOR_RELAXED (rdev, value) \ + writel_relaxed(value, (rdev)->baseaddr + 0x20)#define WRINDOOR (rdev, value) writel(value, (rdev)->baseaddr + 0x20)#define WROUTDOOR (rdev, value) writel(value, (rdev)->baseaddr + 0x2C)
drivers/scsi/megaraid/megaraid_sas_fusion.c +2 -2
@@ -3479,11 +3479,11 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex)wmb ();if (instance->msix_combined) -writel (((MSIxIndex &0x7 ) <<24 ) | +writel_relaxed (((MSIxIndex &0x7 ) <<24 ) | fusion->last_reply_idx[MSIxIndex], instance->reply_post_host_index_addr[MSIxIndex/8 ]);else -writel ((MSIxIndex <<24 ) | +writel_relaxed ((MSIxIndex <<24 ) | fusion->last_reply_idx[MSIxIndex], instance->reply_post_host_index_addr[0 ]);megasas_check_and_restore_queue_depth (instance);
Signature · 1 line
2.7.4
PATCH v4 3/7 scsi: dpt_i2o: eliminate duplicate barriers on weakly-ordered archs
In reply to Sinan KayaCode includes barrier() followed by writel(). writel() already has a barrier
on some architectures like arm64.
This ends up CPU observing two barriers back to back before executing the register write.
Since code already has an explicit barrier call, changing writel() to writel_relaxed().
--- drivers/scsi/dpt_i2o.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/scsi/dpt_i2o.c +3 -3
@@ -1300,7 +1300,7 @@ static s32 adpt_i2o_post_this(adpt_hba* pHba, u32* data, int len)wmb ();//post message -writel (m, pHba->post_port); +writel_relaxed (m, pHba->post_port);wmb ();return 0 ;
@@ -1390,7 +1390,7 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba)memcpy_toio (pHba->msg_addr_virt+m, msg,sizeof (msg));wmb (); -writel (m, pHba->post_port); +writel_relaxed (m, pHba->post_port);wmb ();while (*status ==0 ){
@@ -2797,7 +2797,7 @@ static s32 adpt_send_nop(adpt_hba*pHba,u32 m)writel (0 ,&msg[2 ]);wmb (); -writel (m, pHba->post_port); +writel_relaxed (m, pHba->post_port);wmb ();return 0 ; }
Signature · 1 line
2.7.4
Re: [PATCH v4 3/7] scsi: dpt_i2o: eliminate duplicate barriers on weakly-ordered archs
This is a basically unmaintained driver for historic hardware, and not the right place for micro-optimizations.
Re: [PATCH v4 3/7] scsi: dpt_i2o: eliminate duplicate barriers on weakly-ordered archs
Quoted 3 lines · Christoph Hellwig
This is a basically unmaintained driver for historic hardware, and not the
right place for micro-optimizations.
Sure, I can drop this on the next version.
PATCH v4 4/7 scsi: lpfc: Eliminate duplicate barriers on weakly-ordered archs
In reply to Sinan KayaCode includes barrier() followed by writel(). writel() already has a barrier
on some architectures like arm64.
This ends up CPU observing two barriers back to back before executing the register write.
Since code already has an explicit barrier call, changing writel() to writel_relaxed().
--- drivers/scsi/lpfc/lpfc_sli.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/lpfc/lpfc_sli.c +2 -2
@@ -1647,7 +1647,7 @@ lpfc_sli_update_full_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)* Set ring 'ringno' to SET R0CE_REQ in Chip Att register. * The HBA will tell us when an IOCB entry is available. */ -writel ((CA_R0ATT |CA_R0CE_REQ ) << (ringno*4 ), phba->CAregaddr); +writel_relaxed ((CA_R0ATT |CA_R0CE_REQ ) << (ringno*4 ), phba->CAregaddr);readl (phba->CAregaddr);/* flush */ pring->stats.iocb_cmd_full++;
@@ -1672,7 +1672,7 @@ lpfc_sli_update_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)*/ if (!(phba->sli3_options &LPFC_SLI3_CRP_ENABLED )) {wmb (); -writel (CA_R0ATT << (ringno *4 ), phba->CAregaddr); +writel_relaxed (CA_R0ATT << (ringno *4 ), phba->CAregaddr);readl (phba->CAregaddr);/* flush */ } }
Signature · 1 line
2.7.4
PATCH v4 5/7 scsi: ipr: Eliminate duplicate barriers on weakly-ordered archs
In reply to Sinan KayaCode includes barrier() followed by writel(). writel() already has a barrier
on some architectures like arm64.
This ends up CPU observing two barriers back to back before executing the register write.
Since code already has an explicit barrier call, changing writeX() to writeX_relaxed().
--- drivers/scsi/ipr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/scsi/ipr.c +4 -3
@@ -762,9 +762,9 @@ static void ipr_mask_and_clear_interrupts(struct ipr_ioa_cfg *ioa_cfg,/* Set interrupt mask to stop all new interrupts */ if (ioa_cfg->sis64) -writeq (~0 , ioa_cfg->regs.set_interrupt_mask_reg); +writeq_relaxed (~0 , ioa_cfg->regs.set_interrupt_mask_reg);else -writel (~0 , ioa_cfg->regs.set_interrupt_mask_reg); +writel_relaxed (~0 , ioa_cfg->regs.set_interrupt_mask_reg);/* Clear any pending interrupts */ if (ioa_cfg->sis64)
@@ -8435,7 +8435,8 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd)wmb ();if (ioa_cfg->sis64) {/* Set the adapter to the correct endian mode. */ -writel (IPR_ENDIAN_SWAP_KEY , ioa_cfg->regs.endian_swap_reg); +writel_relaxed (IPR_ENDIAN_SWAP_KEY , + ioa_cfg->regs.endian_swap_reg); int_reg =readl (ioa_cfg->regs.endian_swap_reg); }
Signature · 1 line
2.7.4
Re: [PATCH v4 5/7] scsi: ipr: Eliminate duplicate barriers on weakly-ordered archs
Quoted 32 lines · Sinan Kaya
Code includes
barrier()followed bywritel().writel()already has a barrier
on some architectures like arm64.This ends up CPU observing two barriers back to back before executing the register write.
Since code already has an explicit barrier call, changing
writeX()towriteX_relaxed().Signed-off-by Sinan Kaya <[email protected]>--- drivers/scsi/ipr.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)drivers/scsi/ipr.c +2
-2@@ -762,9 +762,9 @@ static void ipr_mask_and_clear_interrupts(struct ipr_ioa_cfg *ioa_cfg,/* Set interrupt mask to stop all new interrupts */ if (ioa_cfg->sis64) -writeq (~0 , ioa_cfg->regs.set_interrupt_mask_reg); +writeq_relaxed (~0 , ioa_cfg->regs.set_interrupt_mask_reg);else -writel (~0 , ioa_cfg->regs.set_interrupt_mask_reg); +writel_relaxed (~0 , ioa_cfg->regs.set_interrupt_mask_reg);/* Clear any pending interrupts */ if (ioa_cfg->sis64)
drivers/scsi/ipr.c static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd) · line 8442
Quoted 9 lines
drivers/scsi/ipr.c +2
-1@@ -8435,7 +8435,8 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd)wmb ();if (ioa_cfg->sis64) {/* Set the adapter to the correct endian mode. */ -writel (IPR_ENDIAN_SWAP_KEY , ioa_cfg->regs.endian_swap_reg); +writel_relaxed (IPR_ENDIAN_SWAP_KEY , + ioa_cfg->regs.endian_swap_reg); int_reg =readl (ioa_cfg->regs.endian_swap_reg); }
Looks fine to me. Thanks.
Signature · 3 lines
Brian King Power Linux I/O IBM Linux Technology Center
PATCH v4 6/7 scsi: bnx2i: Eliminate duplicate barriers on weakly-ordered archs
In reply to Sinan KayaCode includes barrier() followed by writel(). writel() already has a barrier
on some architectures like arm64.
This ends up CPU observing two barriers back to back before executing the register write.
Since code already has an explicit barrier call, changing writel() to writel_relaxed().
--- drivers/scsi/bnx2i/bnx2i_hwi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/bnx2i/bnx2i_hwi.c +1 -1
@@ -278,7 +278,7 @@ static void bnx2i_ring_sq_dbell(struct bnx2i_conn *bnx2i_conn, int count) sq_db->prod_idx = ep->qp.sq_prod_idx;bnx2i_ring_577xx_doorbell (bnx2i_conn); }else -writew (count, ep->qp.ctx_base +CNIC_SEND_DOORBELL ); +writew_relaxed (count, ep->qp.ctx_base +CNIC_SEND_DOORBELL );mmiowb ();/* flush posted PCI writes */ }
Signature · 1 line
2.7.4
PATCH v4 7/7 scsi: csiostor: Eliminate duplicate barriers on weakly-ordered archs
In reply to Sinan KayaCode includes barrier() followed by writel(). writel() already has a barrier
on some architectures like arm64.
This ends up CPU observing two barriers back to back before executing the register write.
Create a new wrapper function with relaxed write operator. Use the new wrapper when a write is following a barrier().
--- drivers/scsi/csiostor/csio_hw.h | 4 ++++ drivers/scsi/csiostor/csio_wr.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-)
drivers/scsi/csiostor/csio_hw.h +4 -0
@@ -512,6 +512,10 @@ struct csio_hw { csio_reg((_h)->regstart, (_r)))#define csio_wr_reg16 (_h, _v, _r) writew((_v), \ csio_reg((_h)->regstart, (_r))) + +#define csio_wr_reg32_relaxed (_h, _v, _r) \ + writel_relaxed((_v), csio_reg((_h)->regstart, (_r))) +#define csio_wr_reg32 (_h, _v, _r) writel((_v), \ csio_reg((_h)->regstart, (_r)))#define csio_wr_reg64 (_h, _v, _r) writeq((_v), \
drivers/scsi/csiostor/csio_wr.c +1 -1
@@ -984,7 +984,7 @@ csio_wr_issue(struct csio_hw *hw, int qidx, bool prio)wmb ();/* Ring SGE Doorbell writing q->pidx into it */ -csio_wr_reg32 (hw,DBPRIO_V (prio) |QID_V (q->un.eq.physeqid) | +csio_wr_reg32_relaxed (hw,DBPRIO_V (prio) |QID_V (q->un.eq.physeqid) |PIDX_T5_V (q->inc_idx) |DBTYPE_F ,MYPF_REG (SGE_PF_KDOORBELL_A )); q->inc_idx =0 ;
Signature · 1 line
2.7.4