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>
This commit is contained in:
Родитель
bd3a025dd2
Коммит
718ce9e101
|
@ -236,7 +236,7 @@ struct qdio_irq {
|
||||||
int nr_input_qs;
|
int nr_input_qs;
|
||||||
int nr_output_qs;
|
int nr_output_qs;
|
||||||
|
|
||||||
struct ccw1 ccw;
|
struct ccw1 *ccw;
|
||||||
|
|
||||||
struct qdio_ssqd_desc ssqd_desc;
|
struct qdio_ssqd_desc ssqd_desc;
|
||||||
void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *);
|
void (*orig_handler) (struct ccw_device *, unsigned long, struct irb *);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/kmemleak.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/gfp.h>
|
#include <linux/gfp.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
@ -874,6 +875,7 @@ int qdio_free(struct ccw_device *cdev)
|
||||||
qdio_free_queues(irq_ptr);
|
qdio_free_queues(irq_ptr);
|
||||||
free_page((unsigned long) irq_ptr->qdr);
|
free_page((unsigned long) irq_ptr->qdr);
|
||||||
free_page(irq_ptr->chsc_page);
|
free_page(irq_ptr->chsc_page);
|
||||||
|
kfree(irq_ptr->ccw);
|
||||||
free_page((unsigned long) irq_ptr);
|
free_page((unsigned long) irq_ptr);
|
||||||
return 0;
|
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)
|
no_output_qs > QDIO_MAX_QUEUES_PER_IRQ)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* irq_ptr must be in GFP_DMA since it contains ccw1.cda */
|
irq_ptr = (void *) get_zeroed_page(GFP_KERNEL);
|
||||||
irq_ptr = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
|
|
||||||
if (!irq_ptr)
|
if (!irq_ptr)
|
||||||
return -ENOMEM;
|
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;
|
irq_ptr->cdev = cdev;
|
||||||
mutex_init(&irq_ptr->setup_mutex);
|
mutex_init(&irq_ptr->setup_mutex);
|
||||||
if (qdio_allocate_dbf(irq_ptr))
|
if (qdio_allocate_dbf(irq_ptr))
|
||||||
|
@ -941,6 +949,8 @@ err_qdr:
|
||||||
free_page(irq_ptr->chsc_page);
|
free_page(irq_ptr->chsc_page);
|
||||||
err_chsc:
|
err_chsc:
|
||||||
err_dbf:
|
err_dbf:
|
||||||
|
kfree(irq_ptr->ccw);
|
||||||
|
err_ccw:
|
||||||
free_page((unsigned long) irq_ptr);
|
free_page((unsigned long) irq_ptr);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -1012,15 +1022,15 @@ int qdio_establish(struct ccw_device *cdev,
|
||||||
goto err_thinint;
|
goto err_thinint;
|
||||||
|
|
||||||
/* establish q */
|
/* establish q */
|
||||||
irq_ptr->ccw.cmd_code = ciw->cmd;
|
irq_ptr->ccw->cmd_code = ciw->cmd;
|
||||||
irq_ptr->ccw.flags = CCW_FLAG_SLI;
|
irq_ptr->ccw->flags = CCW_FLAG_SLI;
|
||||||
irq_ptr->ccw.count = ciw->count;
|
irq_ptr->ccw->count = ciw->count;
|
||||||
irq_ptr->ccw.cda = (u32) virt_to_phys(irq_ptr->qdr);
|
irq_ptr->ccw->cda = (u32) virt_to_phys(irq_ptr->qdr);
|
||||||
|
|
||||||
spin_lock_irq(get_ccwdev_lock(cdev));
|
spin_lock_irq(get_ccwdev_lock(cdev));
|
||||||
ccw_device_set_options_mask(cdev, 0);
|
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));
|
spin_unlock_irq(get_ccwdev_lock(cdev));
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DBF_ERROR("%4x est IO ERR", irq_ptr->schid.sch_no);
|
DBF_ERROR("%4x est IO ERR", irq_ptr->schid.sch_no);
|
||||||
|
@ -1093,15 +1103,15 @@ int qdio_activate(struct ccw_device *cdev)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
irq_ptr->ccw.cmd_code = ciw->cmd;
|
irq_ptr->ccw->cmd_code = ciw->cmd;
|
||||||
irq_ptr->ccw.flags = CCW_FLAG_SLI;
|
irq_ptr->ccw->flags = CCW_FLAG_SLI;
|
||||||
irq_ptr->ccw.count = ciw->count;
|
irq_ptr->ccw->count = ciw->count;
|
||||||
irq_ptr->ccw.cda = 0;
|
irq_ptr->ccw->cda = 0;
|
||||||
|
|
||||||
spin_lock_irq(get_ccwdev_lock(cdev));
|
spin_lock_irq(get_ccwdev_lock(cdev));
|
||||||
ccw_device_set_options(cdev, CCWDEV_REPORT_ALL);
|
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);
|
0, DOIO_DENY_PREFETCH);
|
||||||
spin_unlock_irq(get_ccwdev_lock(cdev));
|
spin_unlock_irq(get_ccwdev_lock(cdev));
|
||||||
if (rc) {
|
if (rc) {
|
||||||
|
|
|
@ -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;
|
struct ccw_device *cdev = irq_ptr->cdev;
|
||||||
|
|
||||||
irq_ptr->qdioac1 = 0;
|
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->ssqd_desc, 0, sizeof(irq_ptr->ssqd_desc));
|
||||||
memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
|
memset(&irq_ptr->perf_stat, 0, sizeof(irq_ptr->perf_stat));
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче