aboutsummaryrefslogtreecommitdiff
path: root/drivers/ar6000
diff options
context:
space:
mode:
authormerge <null@invalid>2008-11-26 21:18:18 +0000
committerAndy Green <agreen@pads.home.warmcat.com>2008-11-26 21:18:18 +0000
commite21ce7019cc3b9495be8678ef2c41569cc03021e (patch)
tree34311d5cda8c87664ca3e368c8c82a9640d14dca /drivers/ar6000
parentbcc54765697f64a6270e5e2373d41153e5f1871a (diff)
MERGE-via-balaji-tracking-hist-MERGE-via-stable-tracking-hist-ar6k-break-down-insane-allocat
balaji-tracking-hist top was MERGE-via-stable-tracking-hist-ar6k-break-down-insane-allocat / 6a9c6db399ca60d371ec6b42986608e8bc4a636f ... parent commitmessage: From: merge <null@invalid> MERGE-via-stable-tracking-hist-ar6k-break-down-insane-allocat stable-tracking-hist top was ar6k-break-down-insane-allocat / ac6b4c5fae9b497401eeb3e47cc21932839c18a2 ... parent commitmessage: From: Werner Almesberger <werner@openmoko.org> ar6k-break-down-insane-allocation.patch 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@openmoko.org>
Diffstat (limited to 'drivers/ar6000')
-rw-r--r--drivers/ar6000/ar6000/ar6000_drv.c46
-rw-r--r--drivers/ar6000/ar6000/ar6000_drv.h4
-rw-r--r--drivers/ar6000/ar6000/ar6000_raw_if.c10
3 files changed, 53 insertions, 7 deletions
diff --git a/drivers/ar6000/ar6000/ar6000_drv.c b/drivers/ar6000/ar6000/ar6000_drv.c
index 5dd16517f1e..77730b2a3ac 100644
--- a/drivers/ar6000/ar6000/ar6000_drv.c
+++ b/drivers/ar6000/ar6000/ar6000_drv.c
@@ -659,6 +659,40 @@ A_STATUS ar6000_SetHTCBlockSize(AR_SOFTC_T *ar)
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 @@ ar6000_avail_ev(HTC_HANDLE HTCHandle)
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 @@ ar6000_destroy(struct net_device *dev, unsigned int unregister)
/* Free up the device data structure */
if (unregister)
unregister_netdev(dev);
+
+ free_raw_buffers(ar);
+
#ifndef free_netdev
kfree(dev);
#else
diff --git a/drivers/ar6000/ar6000/ar6000_drv.h b/drivers/ar6000/ar6000/ar6000_drv.h
index 9e8ce0216a4..d5ff7774885 100644
--- a/drivers/ar6000/ar6000/ar6000_drv.h
+++ b/drivers/ar6000/ar6000/ar6000_drv.h
@@ -268,8 +268,8 @@ typedef struct ar6_softc {
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
diff --git a/drivers/ar6000/ar6000/ar6000_raw_if.c b/drivers/ar6000/ar6000/ar6000_raw_if.c
index 746cb2b023e..65402b9c8d5 100644
--- a/drivers/ar6000/ar6000/ar6000_raw_if.c
+++ b/drivers/ar6000/ar6000/ar6000_raw_if.c
@@ -201,9 +201,9 @@ int ar6000_htc_raw_open(AR_SOFTC_T *ar)
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 @@ int ar6000_htc_raw_open(AR_SOFTC_T *ar)
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 @@ get_filled_buffer(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID)
/* 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 @@ get_free_buffer(AR_SOFTC_T *ar, HTC_ENDPOINT_ID StreamID)
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;
}