Message ID | 20210226140305.26356-14-nsaenzjulienne@suse.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Generic way of dealing with broken 64-bit buses | expand |
On Fri, Feb 26, 2021 at 3:03 PM Nicolas Saenz Julienne <nsaenzjulienne@suse.de> wrote: > unsigned long flags; > - spin_lock_irqsave(&instance->hba_lock, flags); > - writel(le32_to_cpu(req_desc->u.low), > - &instance->reg_set->inbound_low_queue_port); > - writel(le32_to_cpu(req_desc->u.high), > - &instance->reg_set->inbound_high_queue_port); > - spin_unlock_irqrestore(&instance->hba_lock, flags); > + > + if (dev_64bit_mmio_supported(&instance->pdev->dev)) { > + writeq(req_data, &instance->reg_set->inbound_low_queue_port); > + } else { > + spin_lock_irqsave(&instance->hba_lock, flags); > + lo_hi_writeq(req_data, &instance->reg_set->inbound_low_queue_port); > + spin_unlock_irqrestore(&instance->hba_lock, flags); > + } I see your patch changes the code to the lo_hi_writeq() accessor, and it also fixes the endianness bug (double byteswap on big-endian), but it does not fix the spinlock bug (writel on pci leaks out of the lock unless it's followed by a read). I'd suggest splitting the bugfix from the cleanup here, and fixing both of the bugs while you're at it. Arnd
On Fri, Feb 26, 2021 at 3:30 PM Arnd Bergmann <arnd@kernel.org> wrote: > > On Fri, Feb 26, 2021 at 3:03 PM Nicolas Saenz Julienne > <nsaenzjulienne@suse.de> wrote: > > > unsigned long flags; > > - spin_lock_irqsave(&instance->hba_lock, flags); > > - writel(le32_to_cpu(req_desc->u.low), > > - &instance->reg_set->inbound_low_queue_port); > > - writel(le32_to_cpu(req_desc->u.high), > > - &instance->reg_set->inbound_high_queue_port); > > - spin_unlock_irqrestore(&instance->hba_lock, flags); > > > + > > + if (dev_64bit_mmio_supported(&instance->pdev->dev)) { > > + writeq(req_data, &instance->reg_set->inbound_low_queue_port); > > + } else { > > + spin_lock_irqsave(&instance->hba_lock, flags); > > + lo_hi_writeq(req_data, &instance->reg_set->inbound_low_queue_port); > > + spin_unlock_irqrestore(&instance->hba_lock, flags); > > + } > > I see your patch changes the code to the lo_hi_writeq() accessor, > and it also fixes the endianness bug (double byteswap on big-endian), > but it does not fix the spinlock bug (writel on pci leaks out of the lock > unless it's followed by a read). On second look, it seems your patch breaks the byteorder logic, rather than fixing it. It would seem better to leave it unchanged then, or to send a separate rework of the endianness conversion if you think it is wrong. Arnd
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 38fc9467c625..d4933a591330 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -36,6 +36,7 @@ #include <linux/vmalloc.h> #include <linux/workqueue.h> #include <linux/irq_poll.h> +#include <linux/io-64-nonatomic-lo-hi.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -259,19 +260,17 @@ static void megasas_write_64bit_req_desc(struct megasas_instance *instance, union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc) { -#if defined(writeq) && defined(CONFIG_64BIT) - u64 req_data = (((u64)le32_to_cpu(req_desc->u.high) << 32) | - le32_to_cpu(req_desc->u.low)); - writeq(req_data, &instance->reg_set->inbound_low_queue_port); -#else + u64 req_data = ((u64)le32_to_cpu(req_desc->u.high) << 32) | + le32_to_cpu(req_desc->u.low); unsigned long flags; - spin_lock_irqsave(&instance->hba_lock, flags); - writel(le32_to_cpu(req_desc->u.low), - &instance->reg_set->inbound_low_queue_port); - writel(le32_to_cpu(req_desc->u.high), - &instance->reg_set->inbound_high_queue_port); - spin_unlock_irqrestore(&instance->hba_lock, flags); -#endif + + if (dev_64bit_mmio_supported(&instance->pdev->dev)) { + writeq(req_data, &instance->reg_set->inbound_low_queue_port); + } else { + spin_lock_irqsave(&instance->hba_lock, flags); + lo_hi_writeq(req_data, &instance->reg_set->inbound_low_queue_port); + spin_unlock_irqrestore(&instance->hba_lock, flags); + } } /**
Instead of relying on defines use dev_64bit_mmio_supported(), which provides the same functionality. On top of that convert the implementation to lo_hi_writeq(), for a cleaner end result. Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de> --- drivers/scsi/megaraid/megaraid_sas_fusion.c | 23 ++++++++++----------- 1 file changed, 11 insertions(+), 12 deletions(-)