diff options
author | Julian Wiedmann <jwi@linux.ibm.com> | 2021-08-24 09:37:06 +0300 |
---|---|---|
committer | Heiko Carstens <hca@linux.ibm.com> | 2021-12-06 14:42:24 +0100 |
commit | 718ce9e10171f70f2d00c3c89ceb7e406a892bb6 (patch) | |
tree | c27de76c28b592d4e758e840addb1459e195510e /drivers/s390 | |
parent | bd3a025dd22c500d33960b0a1fcf92e27514332c (diff) | |
download | linux-718ce9e10171f70f2d00c3c89ceb7e406a892bb6.tar.gz linux-718ce9e10171f70f2d00c3c89ceb7e406a892bb6.tar.bz2 linux-718ce9e10171f70f2d00c3c89ceb7e406a892bb6.zip |
s390/qdio: avoid allocating the qdio_irq with GFP_DMA
The qdio_irq contains only two fields that are directly exposed to the
HW (ccw and qib). And only the ccw needs to reside in 31-bit memory. So
allocate it separately, and remove the GFP_DMA constraint from the
qdio_irq allocation.
Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/qdio.h | 2 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_main.c | 34 | ||||
-rw-r--r-- | drivers/s390/cio/qdio_setup.c | 1 |
3 files changed, 23 insertions, 14 deletions
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 5f43e2b0c855..152c032e74d4 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -236,7 +236,7 @@ struct qdio_irq { int nr_input_qs; int nr_output_qs; - struct ccw1 ccw; + struct ccw1 *ccw; struct qdio_ssqd_desc ssqd_desc; void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *); diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index c42ce1933b2e..9b48573db93d 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -10,6 +10,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/kmemleak.h> #include <linux/delay.h> #include <linux/gfp.h> #include <linux/io.h> @@ -874,6 +875,7 @@ int qdio_free(struct ccw_device *cdev) qdio_free_queues(irq_ptr); free_page((unsigned long) irq_ptr->qdr); free_page(irq_ptr->chsc_page); + kfree(irq_ptr->ccw); free_page((unsigned long) irq_ptr); return 0; } @@ -899,11 +901,17 @@ int qdio_allocate(struct ccw_device *cdev, unsigned int no_input_qs, no_output_qs > QDIO_MAX_QUEUES_PER_IRQ) return -EINVAL; - /* irq_ptr must be in GFP_DMA since it contains ccw1.cda */ - irq_ptr = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); + irq_ptr = (void *) get_zeroed_page(GFP_KERNEL); if (!irq_ptr) return -ENOMEM; + irq_ptr->ccw = kmalloc(sizeof(*irq_ptr->ccw), GFP_KERNEL | GFP_DMA); + if (!irq_ptr->ccw) + goto err_ccw; + + /* kmemleak doesn't scan the page-allocated irq_ptr: */ + kmemleak_not_leak(irq_ptr->ccw); + irq_ptr->cdev = cdev; mutex_init(&irq_ptr->setup_mutex); if (qdio_allocate_dbf(irq_ptr)) @@ -941,6 +949,8 @@ err_qdr: free_page(irq_ptr->chsc_page); err_chsc: err_dbf: + kfree(irq_ptr->ccw); +err_ccw: free_page((unsigned long) irq_ptr); return rc; } @@ -1012,15 +1022,15 @@ int qdio_establish(struct ccw_device *cdev, goto err_thinint; /* establish q */ - irq_ptr->ccw.cmd_code = ciw->cmd; - irq_ptr->ccw.flags = CCW_FLAG_SLI; - irq_ptr->ccw.count = ciw->count; - irq_ptr->ccw.cda = (u32) virt_to_phys(irq_ptr->qdr); + irq_ptr->ccw->cmd_code = ciw->cmd; + irq_ptr->ccw->flags = CCW_FLAG_SLI; + irq_ptr->ccw->count = ciw->count; + irq_ptr->ccw->cda = (u32) virt_to_phys(irq_ptr->qdr); spin_lock_irq(get_ccwdev_lock(cdev)); ccw_device_set_options_mask(cdev, 0); - rc = ccw_device_start(cdev, &irq_ptr->ccw, QDIO_DOING_ESTABLISH, 0, 0); + rc = ccw_device_start(cdev, irq_ptr->ccw, QDIO_DOING_ESTABLISH, 0, 0); spin_unlock_irq(get_ccwdev_lock(cdev)); if (rc) { DBF_ERROR("%4x est IO ERR", irq_ptr->schid.sch_no); @@ -1093,15 +1103,15 @@ int qdio_activate(struct ccw_device *cdev) goto out; } - irq_ptr->ccw.cmd_code = ciw->cmd; - irq_ptr->ccw.flags = CCW_FLAG_SLI; - irq_ptr->ccw.count = ciw->count; - irq_ptr->ccw.cda = 0; + irq_ptr->ccw->cmd_code = ciw->cmd; + irq_ptr->ccw->flags = CCW_FLAG_SLI; + irq_ptr->ccw->count = ciw->count; + irq_ptr->ccw->cda = 0; spin_lock_irq(get_ccwdev_lock(cdev)); ccw_device_set_options(cdev, CCWDEV_REPORT_ALL); - rc = ccw_device_start(cdev, &irq_ptr->ccw, QDIO_DOING_ACTIVATE, + rc = ccw_device_start(cdev, irq_ptr->ccw, QDIO_DOING_ACTIVATE, 0, DOIO_DENY_PREFETCH); spin_unlock_irq(get_ccwdev_lock(cdev)); if (rc) { diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 766f1e849fae..fd663922d7d5 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -356,7 +356,6 @@ void qdio_setup_irq(struct qdio_irq *irq_ptr, struct qdio_initialize *init_data) struct ccw_device *cdev = irq_ptr->cdev; irq_ptr->qdioac1 = 0; - memset(&irq_ptr->ccw, 0, sizeof(irq_ptr->ccw)); memset(&irq_ptr->ssqd_desc, 0, sizeof(irq_ptr->ssqd_desc)); memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat)); |