libipw: split ieee->networks into small pieces
authorZhu Yi <yi.zhu@intel.com>
Mon, 8 Mar 2010 05:18:03 +0000 (13:18 +0800)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 10 Mar 2010 21:16:55 +0000 (16:16 -0500)
The ieee->networks consists of 128 struct libipw_network entries. If
we allocate this chunk of memory altogether, it ends up with an
order 4 page allocation. High order page allocation is likely to fail
on system high load. This patch splits the big chunk memory allocation
into small pieces, each is 344 bytes, allocates them with 128 times.

The patch fixed bug http://bugzilla.kernel.org/show_bug.cgi?id=14989

Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ipw2x00/libipw.h
drivers/net/wireless/ipw2x00/libipw_module.c

index bf45391172f3a3a6b739826e8e7816176ba29d0d..a6d5e42647e4c2f0aae15dfd1ba1a598ffba633f 100644 (file)
@@ -797,7 +797,7 @@ struct libipw_device {
        /* Probe / Beacon management */
        struct list_head network_free_list;
        struct list_head network_list;
-       struct libipw_network *networks;
+       struct libipw_network *networks[MAX_NETWORK_COUNT];
        int scans;
        int scan_age;
 
index 1ae0b2b02c38cc7590638bb7cb3426964dc62c02..2fa55867bd8bb66a931738c50d58f89aee30dda2 100644 (file)
@@ -67,16 +67,17 @@ void *libipw_wiphy_privid = &libipw_wiphy_privid;
 
 static int libipw_networks_allocate(struct libipw_device *ieee)
 {
-       if (ieee->networks)
-               return 0;
-
-       ieee->networks =
-           kzalloc(MAX_NETWORK_COUNT * sizeof(struct libipw_network),
-                   GFP_KERNEL);
-       if (!ieee->networks) {
-               printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
-                      ieee->dev->name);
-               return -ENOMEM;
+       int i, j;
+
+       for (i = 0; i < MAX_NETWORK_COUNT; i++) {
+               ieee->networks[i] = kzalloc(sizeof(struct libipw_network),
+                                           GFP_KERNEL);
+               if (!ieee->networks[i]) {
+                       LIBIPW_ERROR("Out of memory allocating beacons\n");
+                       for (j = 0; j < i; j++)
+                               kfree(ieee->networks[j]);
+                       return -ENOMEM;
+               }
        }
 
        return 0;
@@ -97,15 +98,11 @@ static inline void libipw_networks_free(struct libipw_device *ieee)
 {
        int i;
 
-       if (!ieee->networks)
-               return;
-
-       for (i = 0; i < MAX_NETWORK_COUNT; i++)
-               if (ieee->networks[i].ibss_dfs)
-                       kfree(ieee->networks[i].ibss_dfs);
-
-       kfree(ieee->networks);
-       ieee->networks = NULL;
+       for (i = 0; i < MAX_NETWORK_COUNT; i++) {
+               if (ieee->networks[i]->ibss_dfs)
+                       kfree(ieee->networks[i]->ibss_dfs);
+               kfree(ieee->networks[i]);
+       }
 }
 
 void libipw_networks_age(struct libipw_device *ieee,
@@ -130,7 +127,7 @@ static void libipw_networks_initialize(struct libipw_device *ieee)
        INIT_LIST_HEAD(&ieee->network_free_list);
        INIT_LIST_HEAD(&ieee->network_list);
        for (i = 0; i < MAX_NETWORK_COUNT; i++)
-               list_add_tail(&ieee->networks[i].list,
+               list_add_tail(&ieee->networks[i]->list,
                              &ieee->network_free_list);
 }