Out of the three callers once insists on the scratch buffer, and the others are fine with a new allocation. Switch those two to juse use pci_alloc_consistent directly, and open code the scratch buffer allocation in the remaining one. This avoids a case where we might be doing a memory allocation under a spinlock with irqs disabled. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- drivers/scsi/gdth.c | 7 ++-- drivers/scsi/gdth_proc.c | 71 ++++++++++++---------------------------- drivers/scsi/gdth_proc.h | 3 -- 3 files changed, 25 insertions(+), 56 deletions(-) diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 2bec840018ad..7274d09b2a6c 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -4232,7 +4232,7 @@ static int ioc_general(void __user *arg, char *cmnd) gdth_ioctl_general gen; gdth_ha_str *ha; char *buf = NULL; - u64 paddr; + dma_addr_t paddr; int rval; if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general))) @@ -4251,7 +4251,8 @@ static int ioc_general(void __user *arg, char *cmnd) if (gen.data_len + gen.sense_len == 0) goto execute; - buf = gdth_ioctl_alloc(ha, gen.data_len + gen.sense_len, FALSE, &paddr); + buf = pci_alloc_consistent(ha->pdev, gen.data_len + gen.sense_len, + &paddr); if (!buf) return -EFAULT; @@ -4291,7 +4292,7 @@ static int ioc_general(void __user *arg, char *cmnd) rval = 0; out_free_buf: - gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr); + pci_free_consistent(ha->pdev, gen.data_len + gen.sense_len, buf, paddr); return 0; } diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c index 63d851398e38..6a6bdab748df 100644 --- a/drivers/scsi/gdth_proc.c +++ b/drivers/scsi/gdth_proc.c @@ -31,7 +31,6 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, int i, found; gdth_cmd_str gdtcmd; gdth_cpar_str *pcpar; - u64 paddr; char cmnd[MAX_COMMAND_SIZE]; memset(cmnd, 0xff, 12); @@ -113,13 +112,23 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, } if (wb_mode) { - if (!gdth_ioctl_alloc(ha, sizeof(gdth_cpar_str), TRUE, &paddr)) - return(-EBUSY); + unsigned long flags; + + BUILD_BUG_ON(sizeof(gdth_cpar_str) > GDTH_SCRATCH); + + spin_lock_irqsave(&ha->smp_lock, flags); + if (ha->scratch_busy) { + spin_unlock_irqrestore(&ha->smp_lock, flags); + return -EBUSY; + } + ha->scratch_busy = TRUE; + spin_unlock_irqrestore(&ha->smp_lock, flags); + pcpar = (gdth_cpar_str *)ha->pscratch; memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) ); gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_IOCTL; - gdtcmd.u.ioctl.p_param = paddr; + gdtcmd.u.ioctl.p_param = ha->scratch_phys; gdtcmd.u.ioctl.param_size = sizeof(gdth_cpar_str); gdtcmd.u.ioctl.subfunc = CACHE_CONFIG; gdtcmd.u.ioctl.channel = INVALID_CHANNEL; @@ -127,7 +136,10 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, gdth_execute(host, &gdtcmd, cmnd, 30, NULL); - gdth_ioctl_free(ha, GDTH_SCRATCH, ha->pscratch, paddr); + spin_lock_irqsave(&ha->smp_lock, flags); + ha->scratch_busy = FALSE; + spin_unlock_irqrestore(&ha->smp_lock, flags); + printk("Done.\n"); return(orig_length); } @@ -143,7 +155,7 @@ int gdth_show_info(struct seq_file *m, struct Scsi_Host *host) int id, i, j, k, sec, flag; int no_mdrv = 0, drv_no, is_mirr; u32 cnt; - u64 paddr; + dma_addr_t paddr; int rc = -ENOMEM; gdth_cmd_str *gdtcmd; @@ -232,7 +244,7 @@ int gdth_show_info(struct seq_file *m, struct Scsi_Host *host) seq_puts(m, "\nPhysical Devices:"); flag = FALSE; - buf = gdth_ioctl_alloc(ha, size, FALSE, &paddr); + buf = pci_alloc_consistent(ha->pdev, size, &paddr); if (!buf) goto stop_output; for (i = 0; i < ha->bus_cnt; ++i) { @@ -408,7 +420,7 @@ int gdth_show_info(struct seq_file *m, struct Scsi_Host *host) seq_printf(m, " To Array Drv.:\t%s\n", hrec); } - + if (!flag) seq_puts(m, "\n --\n"); @@ -502,7 +514,7 @@ int gdth_show_info(struct seq_file *m, struct Scsi_Host *host) } } } - gdth_ioctl_free(ha, size, buf, paddr); + pci_free_consistent(ha->pdev, size, buf, paddr); for (i = 0; i < MAX_HDRIVES; ++i) { if (!(ha->hdr[i].present)) @@ -555,47 +567,6 @@ int gdth_show_info(struct seq_file *m, struct Scsi_Host *host) return rc; } -static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch, - u64 *paddr) -{ - unsigned long flags; - char *ret_val; - - if (size == 0) - return NULL; - - spin_lock_irqsave(&ha->smp_lock, flags); - - if (!ha->scratch_busy && size <= GDTH_SCRATCH) { - ha->scratch_busy = TRUE; - ret_val = ha->pscratch; - *paddr = ha->scratch_phys; - } else if (scratch) { - ret_val = NULL; - } else { - dma_addr_t dma_addr; - - ret_val = pci_alloc_consistent(ha->pdev, size, &dma_addr); - *paddr = dma_addr; - } - - spin_unlock_irqrestore(&ha->smp_lock, flags); - return ret_val; -} - -static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, u64 paddr) -{ - unsigned long flags; - - if (buf == ha->pscratch) { - spin_lock_irqsave(&ha->smp_lock, flags); - ha->scratch_busy = FALSE; - spin_unlock_irqrestore(&ha->smp_lock, flags); - } else { - pci_free_consistent(ha->pdev, size, buf, paddr); - } -} - #ifdef GDTH_IOCTL_PROC static int gdth_ioctl_check_bin(gdth_ha_str *ha, u16 size) { diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h index d7d0aa283695..4cc5377cb92e 100644 --- a/drivers/scsi/gdth_proc.h +++ b/drivers/scsi/gdth_proc.h @@ -12,9 +12,6 @@ int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd, static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, int length, gdth_ha_str *ha); -static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch, - u64 *paddr); -static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, u64 paddr); static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id); #endif -- 2.19.1