Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd88a781 authored by Ivo van Doorn's avatar Ivo van Doorn Committed by John W. Linville
Browse files

rt2x00: Reorganize beacon handling



With the new beacon handling from mac80211 we can
reorganize the beacon handling in rt2x00 as well.
This patch will move the function to the TX handlers,
and move all duplicate code into rt2x00queue.c.

After this change the descriptor helper functions
from rt2x00queue.c no longer need to be exported
outside of rt2x00lib and can be declared static.

Signed-off-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e360c4cb
Loading
Loading
Loading
Loading
+35 −54
Original line number Diff line number Diff line
@@ -1058,6 +1058,40 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
/*
 * TX data initialization
 */
static void rt2400pci_write_beacon(struct queue_entry *entry)
{
	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
	u32 word;
	u32 reg;

	/*
	 * Disable beaconing while we are reloading the beacon data,
	 * otherwise we might be sending out invalid data.
	 */
	rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
	rt2x00_set_field32(&reg, CSR14_TBCN, 0);
	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
	rt2x00pci_register_write(rt2x00dev, CSR14, reg);

	/*
	 * Replace rt2x00lib allocated descriptor with the
	 * pointer to the _real_ hardware descriptor.
	 * After that, map the beacon to DMA and update the
	 * descriptor.
	 */
	memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len);
	skbdesc->desc = entry_priv->desc;

	rt2x00queue_map_txskb(rt2x00dev, entry->skb);

	rt2x00_desc_read(entry_priv->desc, 1, &word);
	rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
	rt2x00_desc_write(entry_priv->desc, 1, word);
}

static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
				    const enum data_queue_qid queue)
{
@@ -1504,59 +1538,6 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw)
	return tsf;
}

static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
	struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
	struct queue_entry_priv_pci *entry_priv;
	struct skb_frame_desc *skbdesc;
	struct txentry_desc txdesc;
	u32 reg;

	if (unlikely(!intf->beacon))
		return -ENOBUFS;
	entry_priv = intf->beacon->priv_data;

	/*
	 * Copy all TX descriptor information into txdesc,
	 * after that we are free to use the skb->cb array
	 * for our information.
	 */
	intf->beacon->skb = skb;
	rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);

	/*
	 * Fill in skb descriptor
	 */
	skbdesc = get_skb_frame_desc(skb);
	memset(skbdesc, 0, sizeof(*skbdesc));
	skbdesc->desc = entry_priv->desc;
	skbdesc->desc_len = intf->beacon->queue->desc_size;
	skbdesc->entry = intf->beacon;

	/*
	 * Disable beaconing while we are reloading the beacon data,
	 * otherwise we might be sending out invalid data.
	 */
	rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
	rt2x00_set_field32(&reg, CSR14_TBCN, 0);
	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
	rt2x00pci_register_write(rt2x00dev, CSR14, reg);

	/*
	 * Enable beacon generation.
	 * Write entire beacon with descriptor to register,
	 * and kick the beacon generator.
	 */
	rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb);
	rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
	rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);

	return 0;
}

static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -1598,9 +1579,9 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
	.link_tuner		= rt2400pci_link_tuner,
	.write_tx_desc		= rt2400pci_write_tx_desc,
	.write_tx_data		= rt2x00pci_write_tx_data,
	.write_beacon		= rt2400pci_write_beacon,
	.kick_tx_queue		= rt2400pci_kick_tx_queue,
	.fill_rxdone		= rt2400pci_fill_rxdone,
	.beacon_update		= rt2400pci_beacon_update,
	.config_filter		= rt2400pci_config_filter,
	.config_intf		= rt2400pci_config_intf,
	.config_erp		= rt2400pci_config_erp,
+35 −55
Original line number Diff line number Diff line
@@ -1216,6 +1216,40 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
/*
 * TX data initialization
 */
static void rt2500pci_write_beacon(struct queue_entry *entry)
{
	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
	u32 word;
	u32 reg;

	/*
	 * Disable beaconing while we are reloading the beacon data,
	 * otherwise we might be sending out invalid data.
	 */
	rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
	rt2x00_set_field32(&reg, CSR14_TBCN, 0);
	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
	rt2x00pci_register_write(rt2x00dev, CSR14, reg);

	/*
	 * Replace rt2x00lib allocated descriptor with the
	 * pointer to the _real_ hardware descriptor.
	 * After that, map the beacon to DMA and update the
	 * descriptor.
	 */
	memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len);
	skbdesc->desc = entry_priv->desc;

	rt2x00queue_map_txskb(rt2x00dev, entry->skb);

	rt2x00_desc_read(entry_priv->desc, 1, &word);
	rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
	rt2x00_desc_write(entry_priv->desc, 1, word);
}

static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
				    const enum data_queue_qid queue)
{
@@ -1797,60 +1831,6 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw)
	return tsf;
}

static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
	struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
	struct queue_entry_priv_pci *entry_priv;
	struct skb_frame_desc *skbdesc;
	struct txentry_desc txdesc;
	u32 reg;

	if (unlikely(!intf->beacon))
		return -ENOBUFS;

	entry_priv = intf->beacon->priv_data;

	/*
	 * Copy all TX descriptor information into txdesc,
	 * after that we are free to use the skb->cb array
	 * for our information.
	 */
	intf->beacon->skb = skb;
	rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);

	/*
	 * Fill in skb descriptor
	 */
	skbdesc = get_skb_frame_desc(skb);
	memset(skbdesc, 0, sizeof(*skbdesc));
	skbdesc->desc = entry_priv->desc;
	skbdesc->desc_len = intf->beacon->queue->desc_size;
	skbdesc->entry = intf->beacon;

	/*
	 * Disable beaconing while we are reloading the beacon data,
	 * otherwise we might be sending out invalid data.
	 */
	rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
	rt2x00_set_field32(&reg, CSR14_TBCN, 0);
	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
	rt2x00pci_register_write(rt2x00dev, CSR14, reg);

	/*
	 * Enable beacon generation.
	 * Write entire beacon with descriptor to register,
	 * and kick the beacon generator.
	 */
	rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb);
	rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
	rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);

	return 0;
}

static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -1892,9 +1872,9 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
	.link_tuner		= rt2500pci_link_tuner,
	.write_tx_desc		= rt2500pci_write_tx_desc,
	.write_tx_data		= rt2x00pci_write_tx_data,
	.write_beacon		= rt2500pci_write_beacon,
	.kick_tx_queue		= rt2500pci_kick_tx_queue,
	.fill_rxdone		= rt2500pci_fill_rxdone,
	.beacon_update		= rt2500pci_beacon_update,
	.config_filter		= rt2500pci_config_filter,
	.config_intf		= rt2500pci_config_intf,
	.config_erp		= rt2500pci_config_erp,
+60 −94
Original line number Diff line number Diff line
@@ -1100,6 +1100,65 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
	rt2x00_desc_write(txd, 0, word);
}

/*
 * TX data initialization
 */
static void rt2500usb_beacondone(struct urb *urb);

static void rt2500usb_write_beacon(struct queue_entry *entry)
{
	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
	struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
	int pipe = usb_sndbulkpipe(usb_dev, 1);
	int length;
	u16 reg;

	/*
	 * Add the descriptor in front of the skb.
	 */
	skb_push(entry->skb, entry->queue->desc_size);
	memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len);
	skbdesc->desc = entry->skb->data;

	/*
	 * Disable beaconing while we are reloading the beacon data,
	 * otherwise we might be sending out invalid data.
	 */
	rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
	rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
	rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
	rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);

	/*
	 * USB devices cannot blindly pass the skb->len as the
	 * length of the data to usb_fill_bulk_urb. Pass the skb
	 * to the driver to determine what the length should be.
	 */
	length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb);

	usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe,
			  entry->skb->data, length, rt2500usb_beacondone,
			  entry);

	/*
	 * Second we need to create the guardian byte.
	 * We only need a single byte, so lets recycle
	 * the 'flags' field we are not using for beacons.
	 */
	bcn_priv->guardian_data = 0;
	usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe,
			  &bcn_priv->guardian_data, 1, rt2500usb_beacondone,
			  entry);

	/*
	 * Send out the guardian byte.
	 */
	usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC);
}

static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
				     struct sk_buff *skb)
{
@@ -1115,9 +1174,6 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
	return length;
}

/*
 * TX data initialization
 */
static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
				    const enum data_queue_qid queue)
{
@@ -1672,96 +1728,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
	return 0;
}

/*
 * IEEE80211 stack callback functions.
 */
static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
{
	struct rt2x00_dev *rt2x00dev = hw->priv;
	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
	struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
	struct queue_entry_priv_usb_bcn *bcn_priv;
	struct skb_frame_desc *skbdesc;
	struct txentry_desc txdesc;
	int pipe = usb_sndbulkpipe(usb_dev, 1);
	int length;
	u16 reg;

	if (unlikely(!intf->beacon))
		return -ENOBUFS;

	bcn_priv = intf->beacon->priv_data;

	/*
	 * Copy all TX descriptor information into txdesc,
	 * after that we are free to use the skb->cb array
	 * for our information.
	 */
	intf->beacon->skb = skb;
	rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);

	/*
	 * Add the descriptor in front of the skb.
	 */
	skb_push(skb, intf->beacon->queue->desc_size);
	memset(skb->data, 0, intf->beacon->queue->desc_size);

	/*
	 * Fill in skb descriptor
	 */
	skbdesc = get_skb_frame_desc(skb);
	memset(skbdesc, 0, sizeof(*skbdesc));
	skbdesc->desc = skb->data;
	skbdesc->desc_len = intf->beacon->queue->desc_size;
	skbdesc->entry = intf->beacon;

	/*
	 * Disable beaconing while we are reloading the beacon data,
	 * otherwise we might be sending out invalid data.
	 */
	rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
	rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
	rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
	rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
	rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);

	rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);

	/*
	 * USB devices cannot blindly pass the skb->len as the
	 * length of the data to usb_fill_bulk_urb. Pass the skb
	 * to the driver to determine what the length should be.
	 */
	length = rt2500usb_get_tx_data_len(rt2x00dev, skb);

	usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe,
			  skb->data, length, rt2500usb_beacondone,
			  intf->beacon);

	/*
	 * Second we need to create the guardian byte.
	 * We only need a single byte, so lets recycle
	 * the 'flags' field we are not using for beacons.
	 */
	bcn_priv->guardian_data = 0;
	usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe,
			  &bcn_priv->guardian_data, 1, rt2500usb_beacondone,
			  intf->beacon);

	/*
	 * Send out the guardian byte.
	 */
	usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC);

	/*
	 * Enable beacon generation.
	 */
	rt2500usb_kick_tx_queue(rt2x00dev, QID_BEACON);

	return 0;
}

static const struct ieee80211_ops rt2500usb_mac80211_ops = {
	.tx			= rt2x00mac_tx,
	.start			= rt2x00mac_start,
@@ -1789,10 +1755,10 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
	.link_tuner		= rt2500usb_link_tuner,
	.write_tx_desc		= rt2500usb_write_tx_desc,
	.write_tx_data		= rt2x00usb_write_tx_data,
	.write_beacon		= rt2500usb_write_beacon,
	.get_tx_data_len	= rt2500usb_get_tx_data_len,
	.kick_tx_queue		= rt2500usb_kick_tx_queue,
	.fill_rxdone		= rt2500usb_fill_rxdone,
	.beacon_update		= rt2500usb_beacon_update,
	.config_filter		= rt2500usb_config_filter,
	.config_intf		= rt2500usb_config_intf,
	.config_erp		= rt2500usb_config_erp,
+1 −35
Original line number Diff line number Diff line
@@ -521,6 +521,7 @@ struct rt2x00lib_ops {
			       struct sk_buff *skb,
			       struct txentry_desc *txdesc);
	int (*write_tx_data) (struct queue_entry *entry);
	void (*write_beacon) (struct queue_entry *entry);
	int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
				struct sk_buff *skb);
	void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
@@ -535,8 +536,6 @@ struct rt2x00lib_ops {
	/*
	 * Configuration handlers.
	 */
	int (*beacon_update) (struct ieee80211_hw *hw, struct sk_buff *bcn);

	void (*config_filter) (struct rt2x00_dev *rt2x00dev,
			       const unsigned int filter_flags);
	void (*config_intf) (struct rt2x00_dev *rt2x00dev,
@@ -912,39 +911,6 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate)
 */
void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);

/**
 * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input
 * @entry: The entry which will be used to transfer the TX frame.
 * @txdesc: rt2x00 TX descriptor which will be initialized by this function.
 *
 * This function will initialize the &struct txentry_desc based on information
 * from mac80211. This descriptor can then be used by rt2x00lib and the drivers
 * to correctly initialize the hardware descriptor.
 * Note that before calling this function the skb->cb array must be untouched
 * by rt2x00lib. Only after this function completes will it be save to
 * overwrite the skb->cb information.
 * The reason for this is that mac80211 writes its own tx information into
 * the skb->cb array, and this function will use that information to initialize
 * the &struct txentry_desc structure.
 */
void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
				      struct txentry_desc *txdesc);

/**
 * rt2x00queue_write_tx_descriptor - Write TX descriptor to hardware
 * @entry: The entry which will be used to transfer the TX frame.
 * @txdesc: TX descriptor which will be used to write hardware descriptor
 *
 * This function will write a TX descriptor initialized by
 * &rt2x00queue_create_tx_descriptor to the hardware. After this call
 * has completed the frame is now owned by the hardware, the hardware
 * queue will have automatically be kicked unless this frame was generated
 * by rt2x00lib, in which case the frame is "special" and must be kicked
 * by the caller.
 */
void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
				     struct txentry_desc *txdesc);

/**
 * rt2x00queue_get_queue - Convert queue index to queue pointer
 * @rt2x00dev: Pointer to &struct rt2x00_dev.
+2 −7
Original line number Diff line number Diff line
@@ -434,13 +434,8 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
	if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
		return;

	if (delayed_flags & DELAYED_UPDATE_BEACON) {
		struct ieee80211_if_conf conf;
		conf.bssid = conf.ssid = NULL;
		conf.ssid_len = 0;
		conf.changed = IEEE80211_IFCC_BEACON;
		rt2x00dev->ops->hw->config_interface(rt2x00dev->hw, vif, &conf);
	}
	if (delayed_flags & DELAYED_UPDATE_BEACON)
		rt2x00queue_update_beacon(rt2x00dev, vif);

	if (delayed_flags & DELAYED_CONFIG_ERP)
		rt2x00lib_config_erp(rt2x00dev, intf, &conf);
Loading