diff options
author | Abhijeet Kolekar <abhijeet.kolekar@intel.com> | 2009-06-03 14:44:08 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-06-04 10:57:36 -0400 |
commit | d14d44407b9f06e3cf967fcef28ccb780caf0583 (patch) | |
tree | 56f5541554cd094c08caf4bc2420d7f77563bbec | |
parent | c587de0b8d6e194f7a1719fc6af8a81b4e8916d2 (diff) |
iwl3945: port allow skb allocation in tasklet patch
Port "iwlcore: Allow skb allocation from tasklet." to 3945
If RX queue becomes empty then we need to restock the queue from
tasklet to prevent ucode from starving. A caller to iwl_rx_allocate
will decide if allocated buffer should come from GFP_ATOMIC or
GFP_KERNEL.
Signed-off-by: Abhijeet Kolekar <abhijeet.kolekar@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 745eaaec5954..92fa1a39c446 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1176,7 +1176,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) | |||
1176 | 1176 | ||
1177 | /* If we've added more space for the firmware to place data, tell it. | 1177 | /* If we've added more space for the firmware to place data, tell it. |
1178 | * Increment device's write pointer in multiples of 8. */ | 1178 | * Increment device's write pointer in multiples of 8. */ |
1179 | if ((write != (rxq->write & ~0x7)) | 1179 | if ((rxq->write_actual != (rxq->write & ~0x7)) |
1180 | || (abs(rxq->write - rxq->read) > 7)) { | 1180 | || (abs(rxq->write - rxq->read) > 7)) { |
1181 | spin_lock_irqsave(&rxq->lock, flags); | 1181 | spin_lock_irqsave(&rxq->lock, flags); |
1182 | rxq->need_update = 1; | 1182 | rxq->need_update = 1; |
@@ -1197,7 +1197,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv) | |||
1197 | * Also restock the Rx queue via iwl3945_rx_queue_restock. | 1197 | * Also restock the Rx queue via iwl3945_rx_queue_restock. |
1198 | * This is called as a scheduled work item (except for during initialization) | 1198 | * This is called as a scheduled work item (except for during initialization) |
1199 | */ | 1199 | */ |
1200 | static void iwl3945_rx_allocate(struct iwl_priv *priv) | 1200 | static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) |
1201 | { | 1201 | { |
1202 | struct iwl_rx_queue *rxq = &priv->rxq; | 1202 | struct iwl_rx_queue *rxq = &priv->rxq; |
1203 | struct list_head *element; | 1203 | struct list_head *element; |
@@ -1220,7 +1220,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv) | |||
1220 | /* Alloc a new receive buffer */ | 1220 | /* Alloc a new receive buffer */ |
1221 | rxb->skb = | 1221 | rxb->skb = |
1222 | alloc_skb(priv->hw_params.rx_buf_size, | 1222 | alloc_skb(priv->hw_params.rx_buf_size, |
1223 | GFP_KERNEL); | 1223 | priority); |
1224 | if (!rxb->skb) { | 1224 | if (!rxb->skb) { |
1225 | if (net_ratelimit()) | 1225 | if (net_ratelimit()) |
1226 | IWL_CRIT(priv, ": Can not allocate SKB buffers\n"); | 1226 | IWL_CRIT(priv, ": Can not allocate SKB buffers\n"); |
@@ -1279,6 +1279,7 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
1279 | * not restocked the Rx queue with fresh buffers */ | 1279 | * not restocked the Rx queue with fresh buffers */ |
1280 | rxq->read = rxq->write = 0; | 1280 | rxq->read = rxq->write = 0; |
1281 | rxq->free_count = 0; | 1281 | rxq->free_count = 0; |
1282 | rxq->write_actual = 0; | ||
1282 | spin_unlock_irqrestore(&rxq->lock, flags); | 1283 | spin_unlock_irqrestore(&rxq->lock, flags); |
1283 | } | 1284 | } |
1284 | 1285 | ||
@@ -1287,13 +1288,21 @@ void iwl3945_rx_replenish(void *data) | |||
1287 | struct iwl_priv *priv = data; | 1288 | struct iwl_priv *priv = data; |
1288 | unsigned long flags; | 1289 | unsigned long flags; |
1289 | 1290 | ||
1290 | iwl3945_rx_allocate(priv); | 1291 | iwl3945_rx_allocate(priv, GFP_KERNEL); |
1291 | 1292 | ||
1292 | spin_lock_irqsave(&priv->lock, flags); | 1293 | spin_lock_irqsave(&priv->lock, flags); |
1293 | iwl3945_rx_queue_restock(priv); | 1294 | iwl3945_rx_queue_restock(priv); |
1294 | spin_unlock_irqrestore(&priv->lock, flags); | 1295 | spin_unlock_irqrestore(&priv->lock, flags); |
1295 | } | 1296 | } |
1296 | 1297 | ||
1298 | static void iwl3945_rx_replenish_now(struct iwl_priv *priv) | ||
1299 | { | ||
1300 | iwl3945_rx_allocate(priv, GFP_ATOMIC); | ||
1301 | |||
1302 | iwl3945_rx_queue_restock(priv); | ||
1303 | } | ||
1304 | |||
1305 | |||
1297 | /* Assumes that the skb field of the buffers in 'pool' is kept accurate. | 1306 | /* Assumes that the skb field of the buffers in 'pool' is kept accurate. |
1298 | * If an SKB has been detached, the POOL needs to have its SKB set to NULL | 1307 | * If an SKB has been detached, the POOL needs to have its SKB set to NULL |
1299 | * This free routine walks the list of POOL entries and if SKB is set to | 1308 | * This free routine walks the list of POOL entries and if SKB is set to |
@@ -1416,13 +1425,19 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1416 | unsigned long flags; | 1425 | unsigned long flags; |
1417 | u8 fill_rx = 0; | 1426 | u8 fill_rx = 0; |
1418 | u32 count = 8; | 1427 | u32 count = 8; |
1428 | int total_empty = 0; | ||
1419 | 1429 | ||
1420 | /* uCode's read index (stored in shared DRAM) indicates the last Rx | 1430 | /* uCode's read index (stored in shared DRAM) indicates the last Rx |
1421 | * buffer that the driver may process (last buffer filled by ucode). */ | 1431 | * buffer that the driver may process (last buffer filled by ucode). */ |
1422 | r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; | 1432 | r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; |
1423 | i = rxq->read; | 1433 | i = rxq->read; |
1424 | 1434 | ||
1425 | if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2)) | 1435 | /* calculate total frames need to be restock after handling RX */ |
1436 | total_empty = r - priv->rxq.write_actual; | ||
1437 | if (total_empty < 0) | ||
1438 | total_empty += RX_QUEUE_SIZE; | ||
1439 | |||
1440 | if (total_empty > (RX_QUEUE_SIZE / 2)) | ||
1426 | fill_rx = 1; | 1441 | fill_rx = 1; |
1427 | /* Rx interrupt, but nothing sent from uCode */ | 1442 | /* Rx interrupt, but nothing sent from uCode */ |
1428 | if (i == r) | 1443 | if (i == r) |
@@ -1499,7 +1514,7 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1499 | count++; | 1514 | count++; |
1500 | if (count >= 8) { | 1515 | if (count >= 8) { |
1501 | priv->rxq.read = i; | 1516 | priv->rxq.read = i; |
1502 | iwl3945_rx_queue_restock(priv); | 1517 | iwl3945_rx_replenish_now(priv); |
1503 | count = 0; | 1518 | count = 0; |
1504 | } | 1519 | } |
1505 | } | 1520 | } |
@@ -1507,7 +1522,10 @@ static void iwl3945_rx_handle(struct iwl_priv *priv) | |||
1507 | 1522 | ||
1508 | /* Backtrack one entry */ | 1523 | /* Backtrack one entry */ |
1509 | priv->rxq.read = i; | 1524 | priv->rxq.read = i; |
1510 | iwl3945_rx_queue_restock(priv); | 1525 | if (fill_rx) |
1526 | iwl3945_rx_replenish_now(priv); | ||
1527 | else | ||
1528 | iwl3945_rx_queue_restock(priv); | ||
1511 | } | 1529 | } |
1512 | 1530 | ||
1513 | /* call this function to flush any scheduled tasklet */ | 1531 | /* call this function to flush any scheduled tasklet */ |