/*
  * Initialization functions.
  */
-static void rt2400pci_init_rxring(struct rt2x00_dev *rt2x00dev)
+static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+                                  struct data_entry *entry)
 {
-       struct data_ring *ring = rt2x00dev->rx;
-       __le32 *rxd;
-       unsigned int i;
+       __le32 *rxd = entry->priv;
        u32 word;
 
-       memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
-       for (i = 0; i < ring->stats.limit; i++) {
-               rxd = ring->entry[i].priv;
+       rt2x00_desc_read(rxd, 2, &word);
+       rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->ring->data_size);
+       rt2x00_desc_write(rxd, 2, word);
 
-               rt2x00_desc_read(rxd, 2, &word);
-               rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH,
-                                  ring->data_size);
-               rt2x00_desc_write(rxd, 2, word);
-
-               rt2x00_desc_read(rxd, 1, &word);
-               rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS,
-                                  ring->entry[i].data_dma);
-               rt2x00_desc_write(rxd, 1, word);
-
-               rt2x00_desc_read(rxd, 0, &word);
-               rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
-               rt2x00_desc_write(rxd, 0, word);
-       }
+       rt2x00_desc_read(rxd, 1, &word);
+       rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
+       rt2x00_desc_write(rxd, 1, word);
 
-       rt2x00_ring_index_clear(rt2x00dev->rx);
+       rt2x00_desc_read(rxd, 0, &word);
+       rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+       rt2x00_desc_write(rxd, 0, word);
 }
 
-static void rt2400pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue)
+static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+                                  struct data_entry *entry)
 {
-       struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
-       __le32 *txd;
-       unsigned int i;
+       __le32 *txd = entry->priv;
        u32 word;
 
-       memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
-       for (i = 0; i < ring->stats.limit; i++) {
-               txd = ring->entry[i].priv;
-
-               rt2x00_desc_read(txd, 1, &word);
-               rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS,
-                                  ring->entry[i].data_dma);
-               rt2x00_desc_write(txd, 1, word);
+       rt2x00_desc_read(txd, 1, &word);
+       rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
+       rt2x00_desc_write(txd, 1, word);
 
-               rt2x00_desc_read(txd, 2, &word);
-               rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH,
-                                  ring->data_size);
-               rt2x00_desc_write(txd, 2, word);
-
-               rt2x00_desc_read(txd, 0, &word);
-               rt2x00_set_field32(&word, TXD_W0_VALID, 0);
-               rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
-               rt2x00_desc_write(txd, 0, word);
-       }
+       rt2x00_desc_read(txd, 2, &word);
+       rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, entry->ring->data_size);
+       rt2x00_desc_write(txd, 2, word);
 
-       rt2x00_ring_index_clear(ring);
+       rt2x00_desc_read(txd, 0, &word);
+       rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+       rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+       rt2x00_desc_write(txd, 0, word);
 }
 
 static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       /*
-        * Initialize rings.
-        */
-       rt2400pci_init_rxring(rt2x00dev);
-       rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
-       rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
-       rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
-       rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-
        /*
         * Initialize registers.
         */
        .probe_hw               = rt2400pci_probe_hw,
        .initialize             = rt2x00pci_initialize,
        .uninitialize           = rt2x00pci_uninitialize,
+       .init_rxentry           = rt2400pci_init_rxentry,
+       .init_txentry           = rt2400pci_init_txentry,
        .set_device_state       = rt2400pci_set_device_state,
        .rfkill_poll            = rt2400pci_rfkill_poll,
        .link_stats             = rt2400pci_link_stats,
 
 /*
  * Initialization functions.
  */
-static void rt2500pci_init_rxring(struct rt2x00_dev *rt2x00dev)
+static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+                                  struct data_entry *entry)
 {
-       struct data_ring *ring = rt2x00dev->rx;
-       __le32 *rxd;
-       unsigned int i;
+       __le32 *rxd = entry->priv;
        u32 word;
 
-       memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
-       for (i = 0; i < ring->stats.limit; i++) {
-               rxd = ring->entry[i].priv;
-
-               rt2x00_desc_read(rxd, 1, &word);
-               rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS,
-                                  ring->entry[i].data_dma);
-               rt2x00_desc_write(rxd, 1, word);
-
-               rt2x00_desc_read(rxd, 0, &word);
-               rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
-               rt2x00_desc_write(rxd, 0, word);
-       }
+       rt2x00_desc_read(rxd, 1, &word);
+       rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
+       rt2x00_desc_write(rxd, 1, word);
 
-       rt2x00_ring_index_clear(rt2x00dev->rx);
+       rt2x00_desc_read(rxd, 0, &word);
+       rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+       rt2x00_desc_write(rxd, 0, word);
 }
 
-static void rt2500pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue)
+static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+                                  struct data_entry *entry)
 {
-       struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
-       __le32 *txd;
-       unsigned int i;
+       __le32 *txd = entry->priv;
        u32 word;
 
-       memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
-       for (i = 0; i < ring->stats.limit; i++) {
-               txd = ring->entry[i].priv;
+       rt2x00_desc_read(txd, 1, &word);
+       rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
+       rt2x00_desc_write(txd, 1, word);
 
-               rt2x00_desc_read(txd, 1, &word);
-               rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS,
-                                  ring->entry[i].data_dma);
-               rt2x00_desc_write(txd, 1, word);
-
-               rt2x00_desc_read(txd, 0, &word);
-               rt2x00_set_field32(&word, TXD_W0_VALID, 0);
-               rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
-               rt2x00_desc_write(txd, 0, word);
-       }
-
-       rt2x00_ring_index_clear(ring);
+       rt2x00_desc_read(txd, 0, &word);
+       rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+       rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+       rt2x00_desc_write(txd, 0, word);
 }
 
 static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       /*
-        * Initialize rings.
-        */
-       rt2500pci_init_rxring(rt2x00dev);
-       rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
-       rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
-       rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
-       rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-
        /*
         * Initialize registers.
         */
        .probe_hw               = rt2500pci_probe_hw,
        .initialize             = rt2x00pci_initialize,
        .uninitialize           = rt2x00pci_uninitialize,
+       .init_rxentry           = rt2500pci_init_rxentry,
+       .init_txentry           = rt2500pci_init_txentry,
        .set_device_state       = rt2500pci_set_device_state,
        .rfkill_poll            = rt2500pci_rfkill_poll,
        .link_stats             = rt2500pci_link_stats,
 
                return -EIO;
        }
 
-       rt2x00usb_enable_radio(rt2x00dev);
-
        /*
         * Enable LED
         */
        .probe_hw               = rt2500usb_probe_hw,
        .initialize             = rt2x00usb_initialize,
        .uninitialize           = rt2x00usb_uninitialize,
+       .init_rxentry           = rt2x00usb_init_rxentry,
+       .init_txentry           = rt2x00usb_init_txentry,
        .set_device_state       = rt2500usb_set_device_state,
        .link_stats             = rt2500usb_link_stats,
        .reset_tuner            = rt2500usb_reset_tuner,
 
        int (*initialize) (struct rt2x00_dev *rt2x00dev);
        void (*uninitialize) (struct rt2x00_dev *rt2x00dev);
 
+       /*
+        * Ring initialization handlers
+        */
+       void (*init_rxentry) (struct rt2x00_dev *rt2x00dev,
+                             struct data_entry *entry);
+       void (*init_txentry) (struct rt2x00_dev *rt2x00dev,
+                             struct data_entry *entry);
+
        /*
         * Radio control handlers.
         */
 
        rt2x00lib_start_link_tuner(rt2x00dev);
 }
 
+/*
+ * Ring initialization
+ */
+static void rt2x00lib_init_rxrings(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_ring *ring = rt2x00dev->rx;
+       unsigned int i;
+
+       if (!rt2x00dev->ops->lib->init_rxentry)
+               return;
+
+       if (ring->data_addr)
+               memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
+
+       for (i = 0; i < ring->stats.limit; i++)
+               rt2x00dev->ops->lib->init_rxentry(rt2x00dev, &ring->entry[i]);
+
+       rt2x00_ring_index_clear(ring);
+}
+
+static void rt2x00lib_init_txrings(struct rt2x00_dev *rt2x00dev)
+{
+       struct data_ring *ring;
+       unsigned int i;
+
+       if (!rt2x00dev->ops->lib->init_txentry)
+               return;
+
+       txringall_for_each(rt2x00dev, ring) {
+               if (ring->data_addr)
+                       memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
+
+               for (i = 0; i < ring->stats.limit; i++)
+                       rt2x00dev->ops->lib->init_txentry(rt2x00dev,
+                                                         &ring->entry[i]);
+
+               rt2x00_ring_index_clear(ring);
+       }
+}
+
 /*
  * Radio control handlers.
  */
            test_bit(DEVICE_DISABLED_RADIO_HW, &rt2x00dev->flags))
                return 0;
 
+       /*
+        * Initialize all data rings.
+        */
+       rt2x00lib_init_rxrings(rt2x00dev);
+       rt2x00lib_init_txrings(rt2x00dev);
+
        /*
         * Enable radio.
         */
 
 /*
  * Radio handlers
  */
-void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
-       struct usb_device *usb_dev =
-           interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
-       struct data_ring *ring;
-       struct data_entry *entry;
-       unsigned int i;
-
-       /*
-        * Initialize the TX rings
-        */
-       txringall_for_each(rt2x00dev, ring) {
-               for (i = 0; i < ring->stats.limit; i++)
-                       ring->entry[i].flags = 0;
-
-               rt2x00_ring_index_clear(ring);
-       }
-
-       /*
-        * Initialize and start the RX ring.
-        */
-       rt2x00_ring_index_clear(rt2x00dev->rx);
-
-       for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
-               entry = &rt2x00dev->rx->entry[i];
-
-               usb_fill_bulk_urb(entry->priv, usb_dev,
-                                 usb_rcvbulkpipe(usb_dev, 1),
-                                 entry->skb->data, entry->skb->len,
-                                 rt2x00usb_interrupt_rxdone, entry);
-
-               __set_bit(ENTRY_OWNER_NIC, &entry->flags);
-               usb_submit_urb(entry->priv, GFP_ATOMIC);
-       }
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_enable_radio);
-
 void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
        struct data_ring *ring;
 /*
  * Device initialization handlers.
  */
+void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
+                           struct data_entry *entry)
+{
+       struct usb_device *usb_dev =
+            interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
+
+       usb_fill_bulk_urb(entry->priv, usb_dev,
+                         usb_rcvbulkpipe(usb_dev, 1),
+                         entry->skb->data, entry->skb->len,
+                         rt2x00usb_interrupt_rxdone, entry);
+
+       __set_bit(ENTRY_OWNER_NIC, &entry->flags);
+       usb_submit_urb(entry->priv, GFP_ATOMIC);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry);
+
+void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
+                           struct data_entry *entry)
+{
+       entry->flags = 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry);
+
 static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
                               struct data_ring *ring)
 {
 
 /*
  * Radio handlers
  */
-void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev);
 void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
 
 /*
 /*
  * Device initialization handlers.
  */
+void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
+                           struct data_entry *entry);
+void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
+                           struct data_entry *entry);
 int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev);
 void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
 
 
        return 0;
 }
 
-static void rt61pci_init_rxring(struct rt2x00_dev *rt2x00dev)
+static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+                                struct data_entry *entry)
 {
-       struct data_ring *ring = rt2x00dev->rx;
-       __le32 *rxd;
-       unsigned int i;
+       __le32 *rxd = entry->priv;
        u32 word;
 
-       memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
-       for (i = 0; i < ring->stats.limit; i++) {
-               rxd = ring->entry[i].priv;
-
-               rt2x00_desc_read(rxd, 5, &word);
-               rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
-                                  ring->entry[i].data_dma);
-               rt2x00_desc_write(rxd, 5, word);
-
-               rt2x00_desc_read(rxd, 0, &word);
-               rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
-               rt2x00_desc_write(rxd, 0, word);
-       }
+       rt2x00_desc_read(rxd, 5, &word);
+       rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
+                          entry->data_dma);
+       rt2x00_desc_write(rxd, 5, word);
 
-       rt2x00_ring_index_clear(rt2x00dev->rx);
+       rt2x00_desc_read(rxd, 0, &word);
+       rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+       rt2x00_desc_write(rxd, 0, word);
 }
 
-static void rt61pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue)
+static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+                                struct data_entry *entry)
 {
-       struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
-       __le32 *txd;
-       unsigned int i;
+       __le32 *txd = entry->priv;
        u32 word;
 
-       memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
-       for (i = 0; i < ring->stats.limit; i++) {
-               txd = ring->entry[i].priv;
-
-               rt2x00_desc_read(txd, 1, &word);
-               rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
-               rt2x00_desc_write(txd, 1, word);
-
-               rt2x00_desc_read(txd, 5, &word);
-               rt2x00_set_field32(&word, TXD_W5_PID_TYPE,
-                                  ring->queue_idx);
-               rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE,
-                                  ring->entry[i].entry_idx);
-               rt2x00_desc_write(txd, 5, word);
+       rt2x00_desc_read(txd, 1, &word);
+       rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
+       rt2x00_desc_write(txd, 1, word);
 
-               rt2x00_desc_read(txd, 6, &word);
-               rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
-                                  ring->entry[i].data_dma);
-               rt2x00_desc_write(txd, 6, word);
+       rt2x00_desc_read(txd, 5, &word);
+       rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->ring->queue_idx);
+       rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
+       rt2x00_desc_write(txd, 5, word);
 
-               rt2x00_desc_read(txd, 0, &word);
-               rt2x00_set_field32(&word, TXD_W0_VALID, 0);
-               rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
-               rt2x00_desc_write(txd, 0, word);
-       }
+       rt2x00_desc_read(txd, 6, &word);
+       rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
+                          entry->data_dma);
+       rt2x00_desc_write(txd, 6, word);
 
-       rt2x00_ring_index_clear(ring);
+       rt2x00_desc_read(txd, 0, &word);
+       rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+       rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+       rt2x00_desc_write(txd, 0, word);
 }
 
 static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
 {
        u32 reg;
 
-       /*
-        * Initialize rings.
-        */
-       rt61pci_init_rxring(rt2x00dev);
-       rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
-       rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
-       rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA2);
-       rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA3);
-       rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA4);
-
        /*
         * Initialize registers.
         */
        .load_firmware          = rt61pci_load_firmware,
        .initialize             = rt2x00pci_initialize,
        .uninitialize           = rt2x00pci_uninitialize,
+       .init_rxentry           = rt61pci_init_rxentry,
+       .init_txentry           = rt61pci_init_txentry,
        .set_device_state       = rt61pci_set_device_state,
        .rfkill_poll            = rt61pci_rfkill_poll,
        .link_stats             = rt61pci_link_stats,
 
                return -EIO;
        }
 
-       rt2x00usb_enable_radio(rt2x00dev);
-
        /*
         * Enable LED
         */
        .load_firmware          = rt73usb_load_firmware,
        .initialize             = rt2x00usb_initialize,
        .uninitialize           = rt2x00usb_uninitialize,
+       .init_rxentry           = rt2x00usb_init_rxentry,
+       .init_txentry           = rt2x00usb_init_txentry,
        .set_device_state       = rt73usb_set_device_state,
        .link_stats             = rt73usb_link_stats,
        .reset_tuner            = rt73usb_reset_tuner,