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

Commit 69cf36a4 authored by Helmut Schaa's avatar Helmut Schaa Committed by John W. Linville
Browse files

rt2x00: Refactor beacon code to make use of start- and stop_queue



This patch allows to dynamically remove beaconing interfaces without
shutting beaconing down on all interfaces.

The only place to start and stop beaconing are now the start- and
stop_queue callbacks. Hence, we can remove some register writes during
interface bring up (config_intf) and only write the correct sync mode
to the register there.

When multiple beaconing interfaces are present we should enable
beaconing as soon as mac80211 enables beaconing on at least one of
them. The beacon queue gets stopped when the last beaconing
interface was stopped by mac80211. Therefore, introduce another
interface counter to keep track ot the number of enabled beaconing
interfaces and start or stop the beacon queue accordingly.

To allow single interfaces to stop beaconing, add a new driver
callback clear_beacon to clear a single interface's beacon without
affecting the other interfaces. Don't overload the clear_entry callback
for clearing beacons as that would introduce additional overhead
(check for each TX queue) into the clear_entry callback which is used
on the drivers TX/RX hotpaths.

Furthermore, the write beacon callback doesn't need to enable beaconing
anymore but since beaconing should be disabled while a new beacon is
written or cleared we still disable beacon generation and enable it
afterwards again in the driver specific callbacks. However, beacon
related interrupts should not be disabled/enabled here, that's solely
done from the start- and stop queue callbacks. It would be nice to stop
the beacon queue just before the beacon update and enable it afterwards
in rt2x00queue itself instead of the current implementation that relies
on the driver doing the right thing. However, since start- and
stop_queue are mutex protected we cannot use them for atomic beacon
updates.

Signed-off-by: default avatarHelmut Schaa <helmut.schaa@googlemail.com>
Acked-by: default avatarGertjan van Wingerde <gwingerde@gmail.com>
Signed-off-by: default avatarIvo van Doorn <IvDoorn@gmail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent d828cd5a
Loading
Loading
Loading
Loading
+0 −4
Original line number Diff line number Diff line
@@ -305,9 +305,7 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
		 * Enable synchronisation.
		 */
		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
		rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
	}

@@ -1183,8 +1181,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry,
	/*
	 * Enable beaconing again.
	 */
	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
	rt2x00_set_field32(&reg, CSR14_TBCN, 1);
	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}
+0 −4
Original line number Diff line number Diff line
@@ -311,9 +311,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
		 * Enable synchronisation.
		 */
		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
		rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
	}

@@ -1337,8 +1335,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry,
	/*
	 * Enable beaconing again.
	 */
	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
	rt2x00_set_field32(&reg, CSR14_TBCN, 1);
	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
}
+0 −2
Original line number Diff line number Diff line
@@ -478,9 +478,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
		rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);

		rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, conf->sync);
		rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
		rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
	}

+37 −30
Original line number Diff line number Diff line
@@ -818,8 +818,6 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
	/*
	 * Enable beaconing again.
	 */
	rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
	rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);

@@ -831,7 +829,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
}
EXPORT_SYMBOL_GPL(rt2800_write_beacon);

static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
						unsigned int beacon_base)
{
	int i;
@@ -845,6 +843,33 @@ static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
}

void rt2800_clear_beacon(struct queue_entry *entry)
{
	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
	u32 reg;

	/*
	 * Disable beaconing while we are reloading the beacon data,
	 * otherwise we might be sending out invalid data.
	 */
	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);

	/*
	 * Clear beacon.
	 */
	rt2800_clear_beacon_register(rt2x00dev,
				     HW_BEACON_OFFSET(entry->entry_idx));

	/*
	 * Enabled beaconing again.
	 */
	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
}
EXPORT_SYMBOL_GPL(rt2800_clear_beacon);

#ifdef CONFIG_RT2X00_LIB_DEBUGFS
const struct rt2x00debug rt2800_rt2x00debug = {
	.owner	= THIS_MODULE,
@@ -1154,30 +1179,12 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
	bool update_bssid = false;

	if (flags & CONFIG_UPDATE_TYPE) {
		/*
		 * Clear current synchronisation setup.
		 */
		rt2800_clear_beacon(rt2x00dev,
				    HW_BEACON_OFFSET(intf->beacon->entry_idx));
		/*
		 * Enable synchronisation.
		 */
		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE,
				   (conf->sync == TSF_SYNC_ADHOC ||
				    conf->sync == TSF_SYNC_AP_NONE));
		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);

		/*
		 * Enable pre tbtt interrupt for beaconing modes
		 */
		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER,
				   (conf->sync == TSF_SYNC_AP_NONE));
		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);

	}

	if (flags & CONFIG_UPDATE_MAC) {
@@ -2187,14 +2194,14 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
	/*
	 * Clear all beacons
	 */
	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE0);
	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE1);
	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE2);
	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE3);
	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE4);
	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE5);
	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE6);
	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE7);
	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE0);
	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE1);
	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE2);
	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE3);
	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE4);
	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE5);
	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE6);
	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE7);

	if (rt2x00_is_usb(rt2x00dev)) {
		rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
+1 −0
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev);
void rt2800_txdone_entry(struct queue_entry *entry, u32 status);

void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
void rt2800_clear_beacon(struct queue_entry *entry);

extern const struct rt2x00debug rt2800_rt2x00debug;

Loading