diff options
author | merge <null@invalid> | 2008-11-26 21:18:18 +0000 |
---|---|---|
committer | Andy Green <agreen@pads.home.warmcat.com> | 2008-11-26 21:18:18 +0000 |
commit | e21ce7019cc3b9495be8678ef2c41569cc03021e (patch) | |
tree | 34311d5cda8c87664ca3e368c8c82a9640d14dca /drivers/ar6000 | |
parent | bcc54765697f64a6270e5e2373d41153e5f1871a (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.c | 46 | ||||
-rw-r--r-- | drivers/ar6000/ar6000/ar6000_drv.h | 4 | ||||
-rw-r--r-- | drivers/ar6000/ar6000/ar6000_raw_if.c | 10 |
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; } |