kern/149643: [rum] device not sending proper beacon frames in
ap mode
Adrian Chadd
adrian at freebsd.org
Sun Oct 16 16:46:49 UTC 2011
I don't think it's the mbuf. It looks like the mbuf allocation is fine.
The linux code in compat-wireless:
* seems to handle endian-ness a bit better;
* does a bunch of different stuff - look at
drivers/net/wireless/rt2x00/rt2500usb.c:
static void rt2500usb_write_beacon(struct queue_entry *entry,
struct txentry_desc *txdesc)
...
/*
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®);
rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
(assembles beacon here)
/*
* 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(entry);
.. which does some fruit:
static int rt2500usb_get_tx_data_len(struct queue_entry *entry)
{
int length;
/*
* The length _must_ be a multiple of 2,
* but it must _not_ be a multiple of the USB packet size.
*/
length = roundup(entry->skb->len, 2);
length += (2 * !(length % entry->queue->usb_maxpacket));
return length;
}
.. and then it does something with a guard byte, and fiddles with some
more registers:
/*
* 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);
/*
* Enable beaconing again.
*/
rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1);
rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1);
reg0 = reg;
rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1);
/*
* Beacon generation will fail initially.
* To prevent this we need to change the TXRX_CSR19
* register several times (reg0 is the same as reg
* except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0
* and 1 in reg).
*/
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
In terms of the setup of the PLCP frame information, that's done in
rt2x00queue.c, in rt2x00queue_create_tx_descriptor_plcp().
It is likely worthwhile comparing the two drivers to see what's
missing/different.
Good luck. :)
Adrian
More information about the freebsd-net
mailing list