static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, struct data_ring *ring, struct sk_buff *frag_skb, struct ieee80211_tx_control *control) { struct sk_buff *skb; int size; if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) size = sizeof(struct ieee80211_cts); else size = sizeof(struct ieee80211_rts); skb = dev_alloc_skb(size + rt2x00dev->hw->extra_tx_headroom); if (!skb) { WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n"); return NETDEV_TX_BUSY; } skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom); skb_put(skb, size); if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) ieee80211_ctstoself_get(rt2x00dev->hw, rt2x00dev->interface.id, frag_skb->data, frag_skb->len, control, (struct ieee80211_cts *)(skb->data)); else ieee80211_rts_get(rt2x00dev->hw, rt2x00dev->interface.id, frag_skb->data, frag_skb->len, control, (struct ieee80211_rts *)(skb->data)); if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) { WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); return NETDEV_TX_BUSY; } return NETDEV_TX_OK; }
static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, struct data_queue *queue, struct sk_buff *frag_skb) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb); struct ieee80211_tx_info *rts_info; struct sk_buff *skb; unsigned int data_length; int retval = 0; if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) data_length = sizeof(struct ieee80211_cts); else data_length = sizeof(struct ieee80211_rts); skb = dev_alloc_skb(data_length + rt2x00dev->hw->extra_tx_headroom); if (unlikely(!skb)) { rt2x00_warn(rt2x00dev, "Failed to create RTS/CTS frame\n"); return -ENOMEM; } skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom); skb_put(skb, data_length); /* * Copy TX information over from original frame to * RTS/CTS frame. Note that we set the no encryption flag * since we don't want this frame to be encrypted. * RTS frames should be acked, while CTS-to-self frames * should not. The ready for TX flag is cleared to prevent * it being automatically send when the descriptor is * written to the hardware. */ memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb)); rts_info = IEEE80211_SKB_CB(skb); rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS; rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT; if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) rts_info->flags |= IEEE80211_TX_CTL_NO_ACK; else rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK; /* Disable hardware encryption */ rts_info->control.hw_key = NULL; /* * RTS/CTS frame should use the length of the frame plus any * encryption overhead that will be added by the hardware. */ data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb); if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif, frag_skb->data, data_length, tx_info, (struct ieee80211_cts *)(skb->data)); else ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif, frag_skb->data, data_length, tx_info, (struct ieee80211_rts *)(skb->data)); retval = rt2x00queue_write_tx_frame(queue, skb, NULL, true); if (retval) { dev_kfree_skb_any(skb); rt2x00_warn(rt2x00dev, "Failed to send RTS/CTS frame\n"); } return retval; }
static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, struct data_queue *queue, struct sk_buff *frag_skb) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb); struct ieee80211_tx_info *rts_info; struct sk_buff *skb; int size; if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) size = sizeof(struct ieee80211_cts); else size = sizeof(struct ieee80211_rts); skb = dev_alloc_skb(size + rt2x00dev->hw->extra_tx_headroom); if (!skb) { WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n"); return NETDEV_TX_BUSY; } skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom); skb_put(skb, size); /* * Copy TX information over from original frame to * RTS/CTS frame. Note that we set the no encryption flag * since we don't want this frame to be encrypted. * RTS frames should be acked, while CTS-to-self frames * should not. The ready for TX flag is cleared to prevent * it being automatically send when the descriptor is * written to the hardware. */ memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb)); rts_info = IEEE80211_SKB_CB(skb); rts_info->control.hw_key = NULL; rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS; rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT; rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS; if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) rts_info->flags |= IEEE80211_TX_CTL_NO_ACK; else rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK; if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif, frag_skb->data, size, tx_info, (struct ieee80211_cts *)(skb->data)); else ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif, frag_skb->data, size, tx_info, (struct ieee80211_rts *)(skb->data)); if (rt2x00queue_write_tx_frame(queue, skb)) { dev_kfree_skb_any(skb); WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); return NETDEV_TX_BUSY; } return NETDEV_TX_OK; }