[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