Skip to content

Commit

Permalink
zd1211rw: batch beacon config commands together
Browse files Browse the repository at this point in the history
Beacon config function writes beacon to hw one write per byte. This is very
slow (usually taking more than 100ms to finish) and causes high CPU usage
when in AP-mode (kworker at ~50% on Intel Atom N270). By batching commands
together zd_mac_config_beacon() runtime can be lowered to 1/5th and lower
CPU usage to saner levels (<10% on Atom).

Signed-off-by: Jussi Kivilinna <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
  • Loading branch information
jkivilin authored and linvjw committed Feb 4, 2011
1 parent 9be2325 commit 5127229
Showing 1 changed file with 25 additions and 15 deletions.
40 changes: 25 additions & 15 deletions drivers/net/wireless/zd1211rw/zd_mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -602,11 +602,18 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
{
struct zd_mac *mac = zd_hw_mac(hw);
int r, ret;
int r, ret, num_cmds, req_pos = 0;
u32 tmp, j = 0;
/* 4 more bytes for tail CRC */
u32 full_len = beacon->len + 4;
unsigned long end_jiffies, message_jiffies;
struct zd_ioreq32 *ioreqs;

/* Alloc memory for full beacon write at once. */
num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;
ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL);
if (!ioreqs)
return -ENOMEM;

mutex_lock(&mac->chip.mutex);

Expand Down Expand Up @@ -637,29 +644,31 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
msleep(20);
}

r = zd_iowrite32_locked(&mac->chip, full_len - 1, CR_BCN_FIFO);
if (r < 0)
goto release_sema;
ioreqs[req_pos].addr = CR_BCN_FIFO;
ioreqs[req_pos].value = full_len - 1;
req_pos++;
if (zd_chip_is_zd1211b(&mac->chip)) {
r = zd_iowrite32_locked(&mac->chip, full_len - 1,
CR_BCN_LENGTH);
if (r < 0)
goto release_sema;
ioreqs[req_pos].addr = CR_BCN_LENGTH;
ioreqs[req_pos].value = full_len - 1;
req_pos++;
}

for (j = 0 ; j < beacon->len; j++) {
r = zd_iowrite32_locked(&mac->chip, *((u8 *)(beacon->data + j)),
CR_BCN_FIFO);
if (r < 0)
goto release_sema;
ioreqs[req_pos].addr = CR_BCN_FIFO;
ioreqs[req_pos].value = *((u8 *)(beacon->data + j));
req_pos++;
}

for (j = 0; j < 4; j++) {
r = zd_iowrite32_locked(&mac->chip, 0x0, CR_BCN_FIFO);
if (r < 0)
goto release_sema;
ioreqs[req_pos].addr = CR_BCN_FIFO;
ioreqs[req_pos].value = 0x0;
req_pos++;
}

BUG_ON(req_pos != num_cmds);

r = zd_iowrite32a_locked(&mac->chip, ioreqs, num_cmds);

release_sema:
/*
* Try very hard to release device beacon semaphore, as otherwise
Expand Down Expand Up @@ -694,6 +703,7 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
CR_BCN_PLCP_CFG);
out:
mutex_unlock(&mac->chip.mutex);
kfree(ioreqs);
return r;
}

Expand Down

0 comments on commit 5127229

Please sign in to comment.