aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax/i2400m/i2400m.h
diff options
context:
space:
mode:
authorPrasanna S. Panchamukhi <prasannax.s.panchamukhi@intel.com>2010-04-13 19:35:58 -0400
committerInaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>2010-05-11 17:08:23 -0400
commitd11a6e4495ee1fbb38b59bc88d49d050d3736929 (patch)
tree08afc7d7909dc451878f2ec04747071e2999e6e4 /drivers/net/wimax/i2400m/i2400m.h
parentded0fd62a8a7cb3b12bb007079bff2b858a12d2b (diff)
wimax i2400m: fix race condition while accessing rx_roq by using kref count
This patch fixes the race condition when one thread tries to destroy the memory allocated for rx_roq, while another thread still happen to access rx_roq. Such a race condition occurs when i2400m-sdio kernel module gets unloaded, destroying the memory allocated for rx_roq while rx_roq is accessed by i2400m_rx_edata(), as explained below: $thread1 $thread2 $ void i2400m_rx_edata() $ $Access rx_roq[] $ $roq = &i2400m->rx_roq[ro_cin] $ $ i2400m_roq_[reset/queue/update_ws] $ $ $ void i2400m_rx_release(); $ $kfree(rx->roq); $ $rx->roq = NULL; $Oops! rx_roq is NULL This patch fixes the race condition using refcount approach. Signed-off-by: Prasanna S. Panchamukhi <prasannax.s.panchamukhi@intel.com>
Diffstat (limited to 'drivers/net/wimax/i2400m/i2400m.h')
-rw-r--r--drivers/net/wimax/i2400m/i2400m.h12
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h
index 7a9c2c5b25cb..b8c7dbfead49 100644
--- a/drivers/net/wimax/i2400m/i2400m.h
+++ b/drivers/net/wimax/i2400m/i2400m.h
@@ -412,7 +412,7 @@ struct i2400m_barker_db;
412 * 412 *
413 * @tx_size_max: biggest TX message sent. 413 * @tx_size_max: biggest TX message sent.
414 * 414 *
415 * @rx_lock: spinlock to protect RX members 415 * @rx_lock: spinlock to protect RX members and rx_roq_refcount.
416 * 416 *
417 * @rx_pl_num: total number of payloads received 417 * @rx_pl_num: total number of payloads received
418 * 418 *
@@ -436,6 +436,10 @@ struct i2400m_barker_db;
436 * delivered. Then the driver can release them to the host. See 436 * delivered. Then the driver can release them to the host. See
437 * drivers/net/i2400m/rx.c for details. 437 * drivers/net/i2400m/rx.c for details.
438 * 438 *
439 * @rx_roq_refcount: refcount rx_roq. This refcounts any access to
440 * rx_roq thus preventing rx_roq being destroyed when rx_roq
441 * is being accessed. rx_roq_refcount is protected by rx_lock.
442 *
439 * @rx_reports: reports received from the device that couldn't be 443 * @rx_reports: reports received from the device that couldn't be
440 * processed because the driver wasn't still ready; when ready, 444 * processed because the driver wasn't still ready; when ready,
441 * they are pulled from here and chewed. 445 * they are pulled from here and chewed.
@@ -597,10 +601,12 @@ struct i2400m {
597 tx_num, tx_size_acc, tx_size_min, tx_size_max; 601 tx_num, tx_size_acc, tx_size_min, tx_size_max;
598 602
599 /* RX stuff */ 603 /* RX stuff */
600 spinlock_t rx_lock; /* protect RX state */ 604 /* protect RX state and rx_roq_refcount */
605 spinlock_t rx_lock;
601 unsigned rx_pl_num, rx_pl_max, rx_pl_min, 606 unsigned rx_pl_num, rx_pl_max, rx_pl_min,
602 rx_num, rx_size_acc, rx_size_min, rx_size_max; 607 rx_num, rx_size_acc, rx_size_min, rx_size_max;
603 struct i2400m_roq *rx_roq; /* not under rx_lock! */ 608 struct i2400m_roq *rx_roq; /* access is refcounted */
609 struct kref rx_roq_refcount; /* refcount access to rx_roq */
604 u8 src_mac_addr[ETH_HLEN]; 610 u8 src_mac_addr[ETH_HLEN];
605 struct list_head rx_reports; /* under rx_lock! */ 611 struct list_head rx_reports; /* under rx_lock! */
606 struct work_struct rx_report_ws; 612 struct work_struct rx_report_ws;