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, &reg);
        rt2x00_set_field16(&reg, 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(&reg, TXRX_CSR19_TSF_COUNT, 1);
        rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
        reg0 = reg;
        rt2x00_set_field16(&reg, 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