[PATCH] ar6k-break-down-insane-allocation.patch
Werner Almesberger
werner at openmoko.org
Tue Nov 25 16:18:35 CET 2008
The Atheros WLAN stack kmallocs almost 64kB of contiguous kernel
memory for a structure containing almost entirely buffers.
As is commonly known , this kind of large allocation has a very
high risk of failing as kernel memory fragments during the life of
a system.
This patch allocates the buffers indiviudually, thus shrinking the
structure to a size below 4kB.
Note: this is untested. These buffers are only used with Atheros'
raw interface, which none of the code we have, including wmiconfig,
even seems to know about.
This may fix bug #2133. Code follows Atheros' style, so checkpatch
hates it.
Signed-off-by: Werner Almesberger <werner at openmoko.org>
---
Index: ktrack/drivers/ar6000/ar6000/ar6000_drv.c
===================================================================
--- ktrack.orig/drivers/ar6000/ar6000/ar6000_drv.c 2008-11-25 12:58:07.000000000 -0200
+++ ktrack/drivers/ar6000/ar6000/ar6000_drv.c 2008-11-25 13:15:49.000000000 -0200
@@ -659,6 +659,40 @@
return status;
}
+static void free_raw_buffers(AR_SOFTC_T *ar)
+{
+ int i, j;
+
+ for (i = 0; i != HTC_RAW_STREAM_NUM_MAX; i++) {
+ for (j = 0; j != RAW_HTC_READ_BUFFERS_NUM; j++)
+ kfree(ar->raw_htc_read_buffer[i][j]);
+ for (j = 0; j != RAW_HTC_WRITE_BUFFERS_NUM; j++)
+ kfree(ar->raw_htc_write_buffer[i][j]);
+ }
+}
+
+static int alloc_raw_buffers(AR_SOFTC_T *ar)
+{
+ int i, j;
+ raw_htc_buffer *b;
+
+ for (i = 0; i != HTC_RAW_STREAM_NUM_MAX; i++) {
+ for (j = 0; j != RAW_HTC_READ_BUFFERS_NUM; j++) {
+ b = kzalloc(sizeof(*b), GFP_KERNEL);
+ if (!b)
+ return -ENOMEM;
+ ar->raw_htc_read_buffer[i][j] = b;
+ }
+ for (j = 0; j != RAW_HTC_WRITE_BUFFERS_NUM; j++) {
+ b = kzalloc(sizeof(*b), GFP_KERNEL);
+ if (!b)
+ return -ENOMEM;
+ ar->raw_htc_write_buffer[i][j] = b;
+ }
+ }
+ return 0;
+}
+
/*
* HTC Event handlers
*/
@@ -723,6 +757,15 @@
init_waitqueue_head(&arEvent);
sema_init(&ar->arSem, 1);
+ if (alloc_raw_buffers(ar)) {
+ free_raw_buffers(ar);
+ /*
+ * @@@ Clean up our own mess, but for anything else, cheerfully mimick
+ * the beautiful error non-handling of the rest of this function.
+ */
+ return;
+ }
+
#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
A_INIT_TIMER(&aptcTimer, aptcTimerHandler, ar);
#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
@@ -1004,6 +1047,9 @@
/* Free up the device data structure */
if (unregister)
unregister_netdev(dev);
+
+ free_raw_buffers(ar);
+
#ifndef free_netdev
kfree(dev);
#else
Index: ktrack/drivers/ar6000/ar6000/ar6000_drv.h
===================================================================
--- ktrack.orig/drivers/ar6000/ar6000/ar6000_drv.h 2008-11-25 12:58:07.000000000 -0200
+++ ktrack/drivers/ar6000/ar6000/ar6000_drv.h 2008-11-25 13:15:19.000000000 -0200
@@ -268,8 +268,8 @@
struct semaphore raw_htc_write_sem[HTC_RAW_STREAM_NUM_MAX];
wait_queue_head_t raw_htc_read_queue[HTC_RAW_STREAM_NUM_MAX];
wait_queue_head_t raw_htc_write_queue[HTC_RAW_STREAM_NUM_MAX];
- raw_htc_buffer raw_htc_read_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_READ_BUFFERS_NUM];
- raw_htc_buffer raw_htc_write_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_WRITE_BUFFERS_NUM];
+ raw_htc_buffer *raw_htc_read_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_READ_BUFFERS_NUM];
+ raw_htc_buffer *raw_htc_write_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_WRITE_BUFFERS_NUM];
A_BOOL write_buffer_available[HTC_RAW_STREAM_NUM_MAX];
A_BOOL read_buffer_available[HTC_RAW_STREAM_NUM_MAX];
#endif
Index: ktrack/drivers/ar6000/ar6000/ar6000_raw_if.c
===================================================================
--- ktrack.orig/drivers/ar6000/ar6000/ar6000_raw_if.c 2008-11-25 12:58:07.000000000 -0200
+++ ktrack/drivers/ar6000/ar6000/ar6000_raw_if.c 2008-11-25 13:15:19.000000000 -0200
@@ -201,9 +201,9 @@
for (count2 = 0; count2 < RAW_HTC_READ_BUFFERS_NUM; count2 ++) {
/* Initialize the receive buffers */
- buffer = &ar->raw_htc_write_buffer[streamID][count2];
+ buffer = ar->raw_htc_write_buffer[streamID][count2];
memset(buffer, 0, sizeof(raw_htc_buffer));
- buffer = &ar->raw_htc_read_buffer[streamID][count2];
+ buffer = ar->raw_htc_read_buffer[streamID][count2];
memset(buffer, 0, sizeof(raw_htc_buffer));
SET_HTC_PACKET_INFO_RX_REFILL(&buffer->HTCPacket,
@@ -222,7 +222,7 @@
for (count2 = 0; count2 < RAW_HTC_WRITE_BUFFERS_NUM; count2 ++) {
/* Initialize the receive buffers */
- buffer = &ar->raw_htc_write_buffer[streamID][count2];
+ buffer = ar->raw_htc_write_buffer[streamID][count2];
memset(buffer, 0, sizeof(raw_htc_buffer));
}
@@ -278,7 +278,7 @@
/* Check for data */
for (count = 0; count < RAW_HTC_READ_BUFFERS_NUM; count ++) {
- busy = &ar->raw_htc_read_buffer[StreamID][count];
+ busy = ar->raw_htc_read_buffer[StreamID][count];
if (busy->length) {
break;
}
@@ -360,7 +360,7 @@
free = NULL;
for (count = 0; count < RAW_HTC_WRITE_BUFFERS_NUM; count ++) {
- free = &ar->raw_htc_write_buffer[StreamID][count];
+ free = ar->raw_htc_write_buffer[StreamID][count];
if (free->length == 0) {
break;
}
More information about the openmoko-kernel
mailing list