Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/qdio: add helpers to manage qdio buffers

Users of qdio buffers employ different strategies to manage these
buffers. The qeth driver uses huge contiguous buffers which leads
to high order allocations with all their downsides.

This patch provides helpers to allocate, free, and reset arrays of
qdio buffers using non contiguous pages.

Reviewed-by: Martin Peschke <mpeschke@linux.vnet.ibm.com>
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

authored by

Sebastian Ott and committed by
Martin Schwidefsky
5245c924 15ba2236

+57
+4
arch/s390/include/asm/qdio.h
··· 415 415 #define QDIO_FLAG_SYNC_OUTPUT 0x02 416 416 #define QDIO_FLAG_PCI_OUT 0x10 417 417 418 + int qdio_alloc_buffers(struct qdio_buffer **buf, unsigned int count); 419 + void qdio_free_buffers(struct qdio_buffer **buf, unsigned int count); 420 + void qdio_reset_buffers(struct qdio_buffer **buf, unsigned int count); 421 + 418 422 extern int qdio_allocate(struct qdio_initialize *); 419 423 extern int qdio_establish(struct qdio_initialize *); 420 424 extern int qdio_activate(struct ccw_device *);
+53
drivers/s390/cio/qdio_setup.c
··· 17 17 #include "qdio.h" 18 18 #include "qdio_debug.h" 19 19 20 + #define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer)) 21 + 20 22 static struct kmem_cache *qdio_q_cache; 21 23 static struct kmem_cache *qdio_aob_cache; 22 24 ··· 33 31 kmem_cache_free(qdio_aob_cache, aob); 34 32 } 35 33 EXPORT_SYMBOL_GPL(qdio_release_aob); 34 + 35 + /** 36 + * qdio_free_buffers() - free qdio buffers 37 + * @buf: array of pointers to qdio buffers 38 + * @count: number of qdio buffers to free 39 + */ 40 + void qdio_free_buffers(struct qdio_buffer **buf, unsigned int count) 41 + { 42 + int pos; 43 + 44 + for (pos = 0; pos < count; pos += QBUFF_PER_PAGE) 45 + free_page((unsigned long) buf[pos]); 46 + } 47 + EXPORT_SYMBOL_GPL(qdio_free_buffers); 48 + 49 + /** 50 + * qdio_alloc_buffers() - allocate qdio buffers 51 + * @buf: array of pointers to qdio buffers 52 + * @count: number of qdio buffers to allocate 53 + */ 54 + int qdio_alloc_buffers(struct qdio_buffer **buf, unsigned int count) 55 + { 56 + int pos; 57 + 58 + for (pos = 0; pos < count; pos += QBUFF_PER_PAGE) { 59 + buf[pos] = (void *) get_zeroed_page(GFP_KERNEL); 60 + if (!buf[pos]) { 61 + qdio_free_buffers(buf, count); 62 + return -ENOMEM; 63 + } 64 + } 65 + for (pos = 0; pos < count; pos++) 66 + if (pos % QBUFF_PER_PAGE) 67 + buf[pos] = buf[pos - 1] + 1; 68 + return 0; 69 + } 70 + EXPORT_SYMBOL_GPL(qdio_alloc_buffers); 71 + 72 + /** 73 + * qdio_reset_buffers() - reset qdio buffers 74 + * @buf: array of pointers to qdio buffers 75 + * @count: number of qdio buffers that will be zeroed 76 + */ 77 + void qdio_reset_buffers(struct qdio_buffer **buf, unsigned int count) 78 + { 79 + int pos; 80 + 81 + for (pos = 0; pos < count; pos++) 82 + memset(buf[pos], 0, sizeof(struct qdio_buffer)); 83 + } 84 + EXPORT_SYMBOL_GPL(qdio_reset_buffers); 36 85 37 86 /* 38 87 * qebsm is only available under 64bit but the adapter sets the feature