Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 195117
b: refs/heads/master
c: d11a6e4
h: refs/heads/master
i:
  195115: 91d4ae0
v: v3
  • Loading branch information
Prasanna S. Panchamukhi authored and Inaky Perez-Gonzalez committed May 11, 2010
1 parent 20850e7 commit a129546
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ded0fd62a8a7cb3b12bb007079bff2b858a12d2b
refs/heads/master: d11a6e4495ee1fbb38b59bc88d49d050d3736929
12 changes: 9 additions & 3 deletions trunk/drivers/net/wimax/i2400m/i2400m.h
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ struct i2400m_barker_db;
*
* @tx_size_max: biggest TX message sent.
*
* @rx_lock: spinlock to protect RX members
* @rx_lock: spinlock to protect RX members and rx_roq_refcount.
*
* @rx_pl_num: total number of payloads received
*
Expand All @@ -436,6 +436,10 @@ struct i2400m_barker_db;
* delivered. Then the driver can release them to the host. See
* drivers/net/i2400m/rx.c for details.
*
* @rx_roq_refcount: refcount rx_roq. This refcounts any access to
* rx_roq thus preventing rx_roq being destroyed when rx_roq
* is being accessed. rx_roq_refcount is protected by rx_lock.
*
* @rx_reports: reports received from the device that couldn't be
* processed because the driver wasn't still ready; when ready,
* they are pulled from here and chewed.
Expand Down Expand Up @@ -597,10 +601,12 @@ struct i2400m {
tx_num, tx_size_acc, tx_size_min, tx_size_max;

/* RX stuff */
spinlock_t rx_lock; /* protect RX state */
/* protect RX state and rx_roq_refcount */
spinlock_t rx_lock;
unsigned rx_pl_num, rx_pl_max, rx_pl_min,
rx_num, rx_size_acc, rx_size_min, rx_size_max;
struct i2400m_roq *rx_roq; /* not under rx_lock! */
struct i2400m_roq *rx_roq; /* access is refcounted */
struct kref rx_roq_refcount; /* refcount access to rx_roq */
u8 src_mac_addr[ETH_HLEN];
struct list_head rx_reports; /* under rx_lock! */
struct work_struct rx_report_ws;
Expand Down
44 changes: 39 additions & 5 deletions trunk/drivers/net/wimax/i2400m/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,25 @@ void i2400m_roq_queue_update_ws(struct i2400m *i2400m, struct i2400m_roq *roq,
}


/*
* This routine destroys the memory allocated for rx_roq, when no
* other thread is accessing it. Access to rx_roq is refcounted by
* rx_roq_refcount, hence memory allocated must be destroyed when
* rx_roq_refcount becomes zero. This routine gets executed when
* rx_roq_refcount becomes zero.
*/
void i2400m_rx_roq_destroy(struct kref *ref)
{
unsigned itr;
struct i2400m *i2400m
= container_of(ref, struct i2400m, rx_roq_refcount);
for (itr = 0; itr < I2400M_RO_CIN + 1; itr++)
__skb_queue_purge(&i2400m->rx_roq[itr].queue);
kfree(i2400m->rx_roq[0].log);
kfree(i2400m->rx_roq);
i2400m->rx_roq = NULL;
}

/*
* Receive and send up an extended data packet
*
Expand Down Expand Up @@ -969,6 +988,7 @@ void i2400m_rx_edata(struct i2400m *i2400m, struct sk_buff *skb_rx,
unsigned ro_needed, ro_type, ro_cin, ro_sn;
struct i2400m_roq *roq;
struct i2400m_roq_data *roq_data;
unsigned long flags;

BUILD_BUG_ON(ETH_HLEN > sizeof(*hdr));

Expand Down Expand Up @@ -1007,7 +1027,16 @@ void i2400m_rx_edata(struct i2400m *i2400m, struct sk_buff *skb_rx,
ro_cin = (reorder >> I2400M_RO_CIN_SHIFT) & I2400M_RO_CIN;
ro_sn = (reorder >> I2400M_RO_SN_SHIFT) & I2400M_RO_SN;

spin_lock_irqsave(&i2400m->rx_lock, flags);
roq = &i2400m->rx_roq[ro_cin];
if (roq == NULL) {
kfree_skb(skb); /* rx_roq is already destroyed */
spin_unlock_irqrestore(&i2400m->rx_lock, flags);
goto error;
}
kref_get(&i2400m->rx_roq_refcount);
spin_unlock_irqrestore(&i2400m->rx_lock, flags);

roq_data = (struct i2400m_roq_data *) &skb->cb;
roq_data->sn = ro_sn;
roq_data->cs = cs;
Expand All @@ -1034,6 +1063,10 @@ void i2400m_rx_edata(struct i2400m *i2400m, struct sk_buff *skb_rx,
default:
dev_err(dev, "HW BUG? unknown reorder type %u\n", ro_type);
}

spin_lock_irqsave(&i2400m->rx_lock, flags);
kref_put(&i2400m->rx_roq_refcount, i2400m_rx_roq_destroy);
spin_unlock_irqrestore(&i2400m->rx_lock, flags);
}
else
i2400m_net_erx(i2400m, skb, cs);
Expand Down Expand Up @@ -1344,6 +1377,7 @@ int i2400m_rx_setup(struct i2400m *i2400m)
__i2400m_roq_init(&i2400m->rx_roq[itr]);
i2400m->rx_roq[itr].log = &rd[itr];
}
kref_init(&i2400m->rx_roq_refcount);
}
return 0;

Expand All @@ -1357,12 +1391,12 @@ int i2400m_rx_setup(struct i2400m *i2400m)
/* Tear down the RX queue and infrastructure */
void i2400m_rx_release(struct i2400m *i2400m)
{
unsigned long flags;

if (i2400m->rx_reorder) {
unsigned itr;
for(itr = 0; itr < I2400M_RO_CIN + 1; itr++)
__skb_queue_purge(&i2400m->rx_roq[itr].queue);
kfree(i2400m->rx_roq[0].log);
kfree(i2400m->rx_roq);
spin_lock_irqsave(&i2400m->rx_lock, flags);
kref_put(&i2400m->rx_roq_refcount, i2400m_rx_roq_destroy);
spin_unlock_irqrestore(&i2400m->rx_lock, flags);
}
/* at this point, nothing can be received... */
i2400m_report_hook_flush(i2400m);
Expand Down

0 comments on commit a129546

Please sign in to comment.