Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 360801
b: refs/heads/master
c: 8a964f4
h: refs/heads/master
i:
  360799: 4fa25a5
v: v3
  • Loading branch information
Johannes Berg committed Feb 26, 2013
1 parent 280f9b8 commit bbabe92
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 86 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: cb601ffa326bc5c74a6ecd8e72ae9631e5f12f75
refs/heads/master: 8a964f44e01ad3bbc208c3e80d931ba91b9ea786
10 changes: 4 additions & 6 deletions trunk/drivers/net/wireless/iwlwifi/iwl-devtrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -349,25 +349,23 @@ TRACE_EVENT(iwlwifi_dev_rx_data,
TRACE_EVENT(iwlwifi_dev_hcmd,
TP_PROTO(const struct device *dev,
struct iwl_host_cmd *cmd, u16 total_size,
const void *hdr, size_t hdr_len),
TP_ARGS(dev, cmd, total_size, hdr, hdr_len),
struct iwl_cmd_header *hdr),
TP_ARGS(dev, cmd, total_size, hdr),
TP_STRUCT__entry(
DEV_ENTRY
__dynamic_array(u8, hcmd, total_size)
__field(u32, flags)
),
TP_fast_assign(
int i, offset = hdr_len;
int i, offset = sizeof(*hdr);

DEV_ASSIGN;
__entry->flags = cmd->flags;
memcpy(__get_dynamic_array(hcmd), hdr, hdr_len);
memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr));

for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
if (!cmd->len[i])
continue;
if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY))
continue;
memcpy((u8 *)__get_dynamic_array(hcmd) + offset,
cmd->data[i], cmd->len[i]);
offset += cmd->len[i];
Expand Down
9 changes: 9 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/pcie/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ struct iwl_queue {
#define TFD_TX_CMD_SLOTS 256
#define TFD_CMD_SLOTS 32

/*
* The FH will write back to the first TB only, so we need
* to copy some data into the buffer regardless of whether
* it should be mapped or not. This indicates how much to
* copy, even for HCMDs it must be big enough to fit the
* DRAM scratch from the TX cmd, at least 16 bytes.
*/
#define IWL_HCMD_MIN_COPY_SIZE 16

struct iwl_pcie_txq_entry {
struct iwl_device_cmd *cmd;
struct iwl_device_cmd *copy_cmd;
Expand Down
75 changes: 58 additions & 17 deletions trunk/drivers/net/wireless/iwlwifi/pcie/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1152,10 +1152,12 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
void *dup_buf = NULL;
dma_addr_t phys_addr;
int idx;
u16 copy_size, cmd_size;
u16 copy_size, cmd_size, dma_size;
bool had_nocopy = false;
int i;
u32 cmd_pos;
const u8 *cmddata[IWL_MAX_CMD_TFDS];
u16 cmdlen[IWL_MAX_CMD_TFDS];

copy_size = sizeof(out_cmd->hdr);
cmd_size = sizeof(out_cmd->hdr);
Expand All @@ -1164,8 +1166,23 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);

for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
cmddata[i] = cmd->data[i];
cmdlen[i] = cmd->len[i];

if (!cmd->len[i])
continue;

/* need at least IWL_HCMD_MIN_COPY_SIZE copied */
if (copy_size < IWL_HCMD_MIN_COPY_SIZE) {
int copy = IWL_HCMD_MIN_COPY_SIZE - copy_size;

if (copy > cmdlen[i])
copy = cmdlen[i];
cmdlen[i] -= copy;
cmddata[i] += copy;
copy_size += copy;
}

if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) {
had_nocopy = true;
if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) {
Expand All @@ -1185,7 +1202,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
goto free_dup_buf;
}

dup_buf = kmemdup(cmd->data[i], cmd->len[i],
dup_buf = kmemdup(cmddata[i], cmdlen[i],
GFP_ATOMIC);
if (!dup_buf)
return -ENOMEM;
Expand All @@ -1195,7 +1212,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
idx = -EINVAL;
goto free_dup_buf;
}
copy_size += cmd->len[i];
copy_size += cmdlen[i];
}
cmd_size += cmd->len[i];
}
Expand Down Expand Up @@ -1242,14 +1259,31 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,

/* and copy the data that needs to be copied */
cmd_pos = offsetof(struct iwl_device_cmd, payload);
copy_size = sizeof(out_cmd->hdr);
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
if (!cmd->len[i])
int copy = 0;

if (!cmd->len)
continue;
if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
IWL_HCMD_DFL_DUP))
break;
memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]);
cmd_pos += cmd->len[i];

/* need at least IWL_HCMD_MIN_COPY_SIZE copied */
if (copy_size < IWL_HCMD_MIN_COPY_SIZE) {
copy = IWL_HCMD_MIN_COPY_SIZE - copy_size;

if (copy > cmd->len[i])
copy = cmd->len[i];
}

/* copy everything if not nocopy/dup */
if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
IWL_HCMD_DFL_DUP)))
copy = cmd->len[i];

if (copy) {
memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
cmd_pos += copy;
copy_size += copy;
}
}

WARN_ON_ONCE(txq->entries[idx].copy_cmd);
Expand All @@ -1275,30 +1309,38 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue);

phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size,
/*
* If the entire command is smaller than IWL_HCMD_MIN_COPY_SIZE, we must
* still map at least that many bytes for the hardware to write back to.
* We have enough space, so that's not a problem.
*/
dma_size = max_t(u16, copy_size, IWL_HCMD_MIN_COPY_SIZE);

phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, dma_size,
DMA_BIDIRECTIONAL);
if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
idx = -ENOMEM;
goto out;
}

dma_unmap_addr_set(out_meta, mapping, phys_addr);
dma_unmap_len_set(out_meta, len, copy_size);
dma_unmap_len_set(out_meta, len, dma_size);

iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1);

/* map the remaining (adjusted) nocopy/dup fragments */
for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
const void *data = cmd->data[i];
const void *data = cmddata[i];

if (!cmd->len[i])
if (!cmdlen[i])
continue;
if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
IWL_HCMD_DFL_DUP)))
continue;
if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP)
data = dup_buf;
phys_addr = dma_map_single(trans->dev, (void *)data,
cmd->len[i], DMA_BIDIRECTIONAL);
cmdlen[i], DMA_BIDIRECTIONAL);
if (dma_mapping_error(trans->dev, phys_addr)) {
iwl_pcie_tfd_unmap(trans, out_meta,
&txq->tfds[q->write_ptr],
Expand All @@ -1307,7 +1349,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
goto out;
}

iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0);
iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0);
}

out_meta->flags = cmd->flags;
Expand All @@ -1317,8 +1359,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,

txq->need_update = 1;

trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size,
&out_cmd->hdr, copy_size);
trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr);

/* start timer if queue currently empty */
if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout)
Expand Down
12 changes: 3 additions & 9 deletions trunk/net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -3285,19 +3285,13 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_chanctx_conf *chanctx_conf;
int ret = -ENODATA;

rcu_read_lock();
if (local->use_chanctx) {
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (chanctx_conf) {
*chandef = chanctx_conf->def;
ret = 0;
}
} else if (local->open_count == local->monitors) {
*chandef = local->monitor_chandef;
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (chanctx_conf) {
*chandef = chanctx_conf->def;
ret = 0;
}
rcu_read_unlock();
Expand Down
2 changes: 1 addition & 1 deletion trunk/net/mac80211/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ void ieee80211_recalc_idle(struct ieee80211_local *local)

lockdep_assert_held(&local->mtx);

active = !list_empty(&local->chanctx_list) || local->monitors;
active = !list_empty(&local->chanctx_list);

if (!local->ops->remain_on_channel) {
list_for_each_entry(roc, &local->roc_list, list) {
Expand Down
77 changes: 28 additions & 49 deletions trunk/net/mac80211/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1231,40 +1231,34 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
if (local->queue_stop_reasons[q] ||
(!txpending && !skb_queue_empty(&local->pending[q]))) {
if (unlikely(info->flags &
IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) {
if (local->queue_stop_reasons[q] &
~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) {
/*
* Drop off-channel frames if queues
* are stopped for any reason other
* than off-channel operation. Never
* queue them.
*/
spin_unlock_irqrestore(
&local->queue_stop_reason_lock,
flags);
ieee80211_purge_tx_queue(&local->hw,
skbs);
return true;
}
} else {

IEEE80211_TX_INTFL_OFFCHAN_TX_OK &&
local->queue_stop_reasons[q] &
~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) {
/*
* Since queue is stopped, queue up frames for
* later transmission from the tx-pending
* tasklet when the queue is woken again.
* Drop off-channel frames if queues are stopped
* for any reason other than off-channel
* operation. Never queue them.
*/
if (txpending)
skb_queue_splice_init(skbs,
&local->pending[q]);
else
skb_queue_splice_tail_init(skbs,
&local->pending[q]);

spin_unlock_irqrestore(&local->queue_stop_reason_lock,
flags);
return false;
spin_unlock_irqrestore(
&local->queue_stop_reason_lock, flags);
ieee80211_purge_tx_queue(&local->hw, skbs);
return true;
}

/*
* Since queue is stopped, queue up frames for later
* transmission from the tx-pending tasklet when the
* queue is woken again.
*/
if (txpending)
skb_queue_splice_init(skbs, &local->pending[q]);
else
skb_queue_splice_tail_init(skbs,
&local->pending[q]);

spin_unlock_irqrestore(&local->queue_stop_reason_lock,
flags);
return false;
}
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);

Expand Down Expand Up @@ -1850,24 +1844,9 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
}

if (!is_multicast_ether_addr(skb->data)) {
struct sta_info *next_hop;
bool mpp_lookup = true;

mpath = mesh_path_lookup(sdata, skb->data);
if (mpath) {
mpp_lookup = false;
next_hop = rcu_dereference(mpath->next_hop);
if (!next_hop ||
!(mpath->flags & (MESH_PATH_ACTIVE |
MESH_PATH_RESOLVING)))
mpp_lookup = true;
}

if (mpp_lookup)
if (!mpath)
mppath = mpp_path_lookup(sdata, skb->data);

if (mppath && mpath)
mesh_path_del(mpath->sdata, mpath->dst);
}

/*
Expand Down Expand Up @@ -2381,9 +2360,9 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
if (local->tim_in_locked_section) {
__ieee80211_beacon_add_tim(sdata, ps, skb);
} else {
spin_lock_bh(&local->tim_lock);
spin_lock(&local->tim_lock);
__ieee80211_beacon_add_tim(sdata, ps, skb);
spin_unlock_bh(&local->tim_lock);
spin_unlock(&local->tim_lock);
}

return 0;
Expand Down
Loading

0 comments on commit bbabe92

Please sign in to comment.