>From 6d5aaddbc146959eaaef7ada1760ca7fb6cd9a7d Mon Sep 17 00:00:00 2001 From: Ivo van Doorn <IvDoorn@xxxxxxxxx> Date: Sat, 21 Jul 2007 14:36:47 +0200 Subject: [PATCH 03/11] rt2x00: Cleanup allocation/initialization Allocation and initialization was not very transparent, this patch will make it more transparent by making the following changes: - Each module allocate and cleans up its own mess - eeprom array is allocated and freed by rt2x00pci/usb - Function names concerning ring & entries allocation should be changes to better reflect the actual work they do. Signed-off-by: Ivo van Doorn <IvDoorn@xxxxxxxxx> --- drivers/net/wireless/mac80211/rt2x00/rt2400pci.c | 25 +- drivers/net/wireless/mac80211/rt2x00/rt2500pci.c | 25 +- drivers/net/wireless/mac80211/rt2x00/rt2500usb.c | 25 +- drivers/net/wireless/mac80211/rt2x00/rt2x00.h | 1 + drivers/net/wireless/mac80211/rt2x00/rt2x00dev.c | 518 +++++++++++----------- drivers/net/wireless/mac80211/rt2x00/rt2x00pci.c | 58 ++- drivers/net/wireless/mac80211/rt2x00/rt2x00usb.c | 66 +++- drivers/net/wireless/mac80211/rt2x00/rt61pci.c | 25 +- drivers/net/wireless/mac80211/rt2x00/rt73usb.c | 25 +- 9 files changed, 403 insertions(+), 365 deletions(-) diff --git a/drivers/net/wireless/mac80211/rt2x00/rt2400pci.c b/drivers/net/wireless/mac80211/rt2x00/rt2400pci.c index df2221b..a6c7602 100644 --- a/drivers/net/wireless/mac80211/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/mac80211/rt2x00/rt2400pci.c @@ -1311,21 +1311,13 @@ static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) /* * Device initialization functions. */ -static int rt2400pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) { struct eeprom_93cx6 eeprom; u32 reg; u16 word; u8 *mac; - /* - * Allocate the eeprom memory, check the eeprom width - * and copy the entire eeprom into this allocated memory. - */ - rt2x00dev->eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); - if (!rt2x00dev->eeprom) - return -ENOMEM; - rt2x00pci_register_read(rt2x00dev, CSR21, ®); eeprom.data = rt2x00dev; @@ -1482,7 +1474,7 @@ static int rt2400pci_init_hw(struct rt2x00_dev *rt2x00dev) /* * Allocate eeprom data. */ - retval = rt2400pci_alloc_eeprom(rt2x00dev); + retval = rt2400pci_validate_eeprom(rt2x00dev); if (retval) return retval; @@ -1644,13 +1636,14 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { }; static const struct rt2x00_ops rt2400pci_ops = { - .name = DRV_NAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, - .lib = &rt2400pci_rt2x00_ops, - .hw = &rt2400pci_mac80211_ops, + .name = DRV_NAME, + .rxd_size = RXD_DESC_SIZE, + .txd_size = TXD_DESC_SIZE, + .eeprom_size = EEPROM_SIZE, + .lib = &rt2400pci_rt2x00_ops, + .hw = &rt2400pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2400pci_rt2x00debug, + .debugfs = &rt2400pci_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; diff --git a/drivers/net/wireless/mac80211/rt2x00/rt2500pci.c b/drivers/net/wireless/mac80211/rt2x00/rt2500pci.c index 34c2e9f..088c717 100644 --- a/drivers/net/wireless/mac80211/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/mac80211/rt2x00/rt2500pci.c @@ -1458,21 +1458,13 @@ static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) /* * Device initialization functions. */ -static int rt2500pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) { struct eeprom_93cx6 eeprom; u32 reg; u16 word; u8 *mac; - /* - * Allocate the eeprom memory, check the eeprom width - * and copy the entire eeprom into this allocated memory. - */ - rt2x00dev->eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); - if (!rt2x00dev->eeprom) - return -ENOMEM; - rt2x00pci_register_read(rt2x00dev, CSR21, ®); eeprom.data = rt2x00dev; @@ -1727,7 +1719,7 @@ static int rt2500pci_init_hw(struct rt2x00_dev *rt2x00dev) /* * Allocate eeprom data. */ - retval = rt2500pci_alloc_eeprom(rt2x00dev); + retval = rt2500pci_validate_eeprom(rt2x00dev); if (retval) return retval; @@ -1865,13 +1857,14 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { }; static const struct rt2x00_ops rt2500pci_ops = { - .name = DRV_NAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, - .lib = &rt2500pci_rt2x00_ops, - .hw = &rt2500pci_mac80211_ops, + .name = DRV_NAME, + .rxd_size = RXD_DESC_SIZE, + .txd_size = TXD_DESC_SIZE, + .eeprom_size = EEPROM_SIZE, + .lib = &rt2500pci_rt2x00_ops, + .hw = &rt2500pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2500pci_rt2x00debug, + .debugfs = &rt2500pci_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; diff --git a/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c b/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c index 0d31c6c..8967155 100644 --- a/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/mac80211/rt2x00/rt2500usb.c @@ -1135,19 +1135,11 @@ static int rt2500usb_fill_rxdone(struct data_entry *entry, /* * Device initialization functions. */ -static int rt2500usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) { u16 word; u8 *mac; - /* - * Allocate the eeprom memory, check the eeprom width - * and copy the entire eeprom into this allocated memory. - */ - rt2x00dev->eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); - if (!rt2x00dev->eeprom) - return -ENOMEM; - rt2x00usb_vendor_request( rt2x00dev, USB_EEPROM_READ, USB_VENDOR_REQUEST_IN, EEPROM_BASE, 0x00, rt2x00dev->eeprom, EEPROM_SIZE, @@ -1436,7 +1428,7 @@ static int rt2500usb_init_hw(struct rt2x00_dev *rt2x00dev) /* * Allocate eeprom data. */ - retval = rt2500usb_alloc_eeprom(rt2x00dev); + retval = rt2500usb_validate_eeprom(rt2x00dev); if (retval) return retval; @@ -1521,13 +1513,14 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { }; static const struct rt2x00_ops rt2500usb_ops = { - .name = DRV_NAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, - .lib = &rt2500usb_rt2x00_ops, - .hw = &rt2500usb_mac80211_ops, + .name = DRV_NAME, + .rxd_size = RXD_DESC_SIZE, + .txd_size = TXD_DESC_SIZE, + .eeprom_size = EEPROM_SIZE, + .lib = &rt2500usb_rt2x00_ops, + .hw = &rt2500usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2500usb_rt2x00debug, + .debugfs = &rt2500usb_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; diff --git a/drivers/net/wireless/mac80211/rt2x00/rt2x00.h b/drivers/net/wireless/mac80211/rt2x00/rt2x00.h index e6f84ac..bc4557d 100644 --- a/drivers/net/wireless/mac80211/rt2x00/rt2x00.h +++ b/drivers/net/wireless/mac80211/rt2x00/rt2x00.h @@ -720,6 +720,7 @@ struct rt2x00_ops { const char *name; const unsigned int rxd_size; const unsigned int txd_size; + const unsigned int eeprom_size; const struct rt2x00lib_ops *lib; const struct ieee80211_ops *hw; #ifdef CONFIG_RT2X00_LIB_DEBUGFS diff --git a/drivers/net/wireless/mac80211/rt2x00/rt2x00dev.c b/drivers/net/wireless/mac80211/rt2x00/rt2x00dev.c index 375645a..f4fedeb 100644 --- a/drivers/net/wireless/mac80211/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/mac80211/rt2x00/rt2x00dev.c @@ -223,6 +223,239 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, } /* + * Interrupt context handlers. + */ +void rt2x00lib_txdone(struct data_entry *entry, + const int status, const int retry) +{ + struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; + struct ieee80211_tx_status *tx_status = &entry->tx_status; + struct ieee80211_low_level_stats *stats = &rt2x00dev->low_level_stats; + + /* + * Update TX statistics. + */ + tx_status->flags = 0; + tx_status->ack_signal = 0; + tx_status->excessive_retries = (status == TX_FAIL_RETRY); + tx_status->retry_count = retry; + + if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) { + if (status == TX_SUCCESS || status == TX_SUCCESS_RETRY) + tx_status->flags |= IEEE80211_TX_STATUS_ACK; + else + stats->dot11ACKFailureCount++; + } + + tx_status->queue_length = entry->ring->stats.limit; + tx_status->queue_number = tx_status->control.queue; + + if (tx_status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) { + if (status == TX_SUCCESS || status == TX_SUCCESS_RETRY) + stats->dot11RTSSuccessCount++; + else + stats->dot11RTSFailureCount++; + } + + /* + * Send the tx_status to mac80211, + * that method also cleans up the skb structure. + */ + ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status); + + entry->skb = NULL; +} +EXPORT_SYMBOL_GPL(rt2x00lib_txdone); + +void rt2x00lib_rxdone(struct data_entry *entry, char *data, + const int size, const int signal, const int rssi, const int ofdm) +{ + struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; + struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; + struct ieee80211_hw_mode *mode; + struct ieee80211_rate *rate; + struct sk_buff *skb; + unsigned int i; + int val = 0; + + /* + * Update RX statistics. + */ + mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode]; + for (i = 0; i < mode->num_rates; i++) { + rate = &mode->rates[i]; + + /* + * When frame was received with an OFDM bitrate, + * the signal is the PLCP value. If it was received with + * a CCK bitrate the signal is the rate in 0.5kbit/s. + */ + if (!ofdm) + val = DEVICE_GET_RATE_FIELD(rate->val, RATE); + else + val = DEVICE_GET_RATE_FIELD(rate->val, PLCP); + + if (val == signal) { + /* + * Check for preamble bit. + */ + if (signal & 0x08) + val = rate->val2; + else + val = rate->val; + break; + } + } + + rx_status->rate = val; + rx_status->ssi = rssi; + rt2x00_update_link_rssi(&rt2x00dev->link, rssi); + + /* + * Let's allocate a sk_buff where we can store the received data in, + * note that if data is NULL, we still have to allocate a sk_buff + * but that we should use that to replace the sk_buff which is already + * inside the entry. + */ + skb = dev_alloc_skb(size + NET_IP_ALIGN); + if (!skb) + return; + + skb_reserve(skb, NET_IP_ALIGN); + skb_put(skb, size); + + if (data) { + memcpy(skb->data, data, size); + entry->skb = skb; + skb = NULL; + } + + ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status); + entry->skb = skb; +} +EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); + +/* + * TX descriptor initializer + */ +void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, + struct data_entry *entry, struct data_desc *txd, + struct ieee80211_hdr *ieee80211hdr, unsigned int length, + struct ieee80211_tx_control *control) +{ + struct data_entry_desc desc; + int tx_rate; + int bitrate; + int duration; + int residual; + u16 frame_control; + u16 seq_ctrl; + + /* + * Identify queue + */ + if (control->queue < rt2x00dev->hw->queues) + desc.queue = control->queue; + else + desc.queue = 15; + + /* + * Read required fields from ieee80211 header. + */ + frame_control = le16_to_cpu(ieee80211hdr->frame_control); + seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl); + + tx_rate = control->tx_rate; + + /* + * Check if this is a RTS/CTS frame + */ + if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) { + if (is_rts_frame(frame_control)) + __set_bit(ENTRY_TXD_RTS_FRAME, &entry->flags); + if (control->rts_cts_rate) + tx_rate = control->rts_cts_rate; + } + + /* + * Check for OFDM + */ + if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) + __set_bit(ENTRY_TXD_OFDM_RATE, &entry->flags); + + /* + * Check if more fragments are pending + */ + if (ieee80211_get_morefrag(ieee80211hdr)) + __set_bit(ENTRY_TXD_MORE_FRAG, &entry->flags); + + /* + * Beacons and probe responses require the tsf timestamp + * to be inserted into the frame. + */ + if (control->queue == IEEE80211_TX_QUEUE_BEACON || + is_probe_resp(frame_control)) + __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &entry->flags); + + /* + * Check if ACK is required + */ + if (!(control->flags & IEEE80211_TXCTL_NO_ACK)) + __set_bit(ENTRY_TXD_REQ_ACK, &entry->flags); + + /* + * Determine with what IFS priority this frame should be send. + * Set ifs to IFS_SIFS when the this is not the first fragment, + * or this fragment came after RTS/CTS. + */ + if ((seq_ctrl & IEEE80211_SCTL_FRAG) > 0 || + test_bit(ENTRY_TXD_RTS_FRAME, &entry->flags)) + desc.ifs = IFS_SIFS; + else + desc.ifs = IFS_BACKOFF; + + /* + * How the length should be processed depends + * on if we are working with OFDM rates or not. + */ + if (test_bit(ENTRY_TXD_OFDM_RATE, &entry->flags)) { + residual = 0; + desc.length_high = ((length + FCS_LEN) >> 6) & 0x3f; + desc.length_low = ((length + FCS_LEN) & 0x3f); + + } else { + bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE); + + /* + * Convert length to microseconds. + */ + residual = get_duration_res(length + FCS_LEN, bitrate); + duration = get_duration(length + FCS_LEN, bitrate); + + if (residual != 0) + duration++; + + desc.length_high = duration >> 8; + desc.length_low = duration & 0xff; + } + + /* + * Create the signal and service values. + */ + desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP); + if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE)) + desc.signal |= 0x08; + + desc.service = 0x04; + if (residual <= (8 % 11)) + desc.service |= 0x80; + + rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry, txd, &desc, + ieee80211hdr, length, control); +} +EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc); + +/* * Driver initialization handlers. */ static void rt2x00lib_channel(struct ieee80211_channel *entry, @@ -438,7 +671,7 @@ static int rt2x00lib_init_hw(struct rt2x00_dev *rt2x00dev) /* * Initialization/uninitialization handlers. */ -static int rt2x00lib_alloc_ring(struct data_ring *ring, +static int rt2x00lib_alloc_entries(struct data_ring *ring, const u16 max_entries, const u16 data_size, const u16 desc_size) { struct data_entry *entry; @@ -466,14 +699,14 @@ static int rt2x00lib_alloc_ring(struct data_ring *ring, return 0; } -static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev) +static int rt2x00lib_alloc_ring_entries(struct rt2x00_dev *rt2x00dev) { struct data_ring *ring; /* * Allocate the RX ring. */ - if (rt2x00lib_alloc_ring(rt2x00dev->rx, + if (rt2x00lib_alloc_entries(rt2x00dev->rx, RX_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->rxd_size)) return -ENOMEM; @@ -481,7 +714,7 @@ static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev) * First allocate the TX rings. */ txring_for_each(rt2x00dev, ring) { - if (rt2x00lib_alloc_ring(ring, + if (rt2x00lib_alloc_entries(ring, TX_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->txd_size)) return -ENOMEM; } @@ -489,23 +722,24 @@ static int rt2x00lib_allocate_rings(struct rt2x00_dev *rt2x00dev) /* * Allocate the BEACON ring. */ - if (rt2x00lib_alloc_ring(&rt2x00dev->bcn[0], + if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[0], BEACON_ENTRIES, MGMT_FRAME_SIZE, rt2x00dev->ops->txd_size)) return -ENOMEM; /* * Allocate the Atim ring. */ - if (test_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags)) { - if (rt2x00lib_alloc_ring(&rt2x00dev->bcn[1], - ATIM_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->txd_size)) - return -ENOMEM; - } + if (!test_bit(DEVICE_SUPPORT_ATIM, &rt2x00dev->flags)) + return 0; + + if (rt2x00lib_alloc_entries(&rt2x00dev->bcn[1], + ATIM_ENTRIES, DATA_FRAME_SIZE, rt2x00dev->ops->txd_size)) + return -ENOMEM; return 0; } -static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev) +static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev) { struct data_ring *ring; @@ -523,9 +757,9 @@ int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) return 0; /* - * Allocate all data rings. + * Allocate all ring entries. */ - status = rt2x00lib_allocate_rings(rt2x00dev); + status = rt2x00lib_alloc_ring_entries(rt2x00dev); if (status) { ERROR(rt2x00dev, "DMA allocation failed.\n"); return status; @@ -553,7 +787,7 @@ exit_unitialize: rt2x00lib_uninitialize(rt2x00dev); exit: - rt2x00lib_free_rings(rt2x00dev); + rt2x00lib_free_ring_entries(rt2x00dev); return status; } @@ -574,9 +808,9 @@ void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) rt2x00dev->ops->lib->uninitialize(rt2x00dev); /* - * Free allocated datarings. + * Free allocated ring entries. */ - rt2x00lib_free_rings(rt2x00dev); + rt2x00lib_free_ring_entries(rt2x00dev); } /* @@ -625,6 +859,14 @@ static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev) return 0; } +static void rt2x00lib_free_rings(struct rt2x00_dev *rt2x00dev) +{ + kfree(rt2x00dev->rx); + rt2x00dev->rx = NULL; + rt2x00dev->tx = NULL; + rt2x00dev->bcn = NULL; +} + int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) { int retval = -ENOMEM; @@ -715,16 +957,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) /* * Free ring structures. */ - kfree(rt2x00dev->rx); - rt2x00dev->rx = NULL; - rt2x00dev->tx = NULL; - rt2x00dev->bcn = NULL; - - /* - * Free EEPROM memory. - */ - kfree(rt2x00dev->eeprom); - rt2x00dev->eeprom = NULL; + rt2x00lib_free_rings(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); @@ -760,239 +993,6 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) EXPORT_SYMBOL_GPL(rt2x00lib_resume); /* - * Interrupt context handlers. - */ -void rt2x00lib_txdone(struct data_entry *entry, - const int status, const int retry) -{ - struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; - struct ieee80211_tx_status *tx_status = &entry->tx_status; - struct ieee80211_low_level_stats *stats = &rt2x00dev->low_level_stats; - - /* - * Update TX statistics. - */ - tx_status->flags = 0; - tx_status->ack_signal = 0; - tx_status->excessive_retries = (status == TX_FAIL_RETRY); - tx_status->retry_count = retry; - - if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) { - if (status == TX_SUCCESS || status == TX_SUCCESS_RETRY) - tx_status->flags |= IEEE80211_TX_STATUS_ACK; - else - stats->dot11ACKFailureCount++; - } - - tx_status->queue_length = entry->ring->stats.limit; - tx_status->queue_number = tx_status->control.queue; - - if (tx_status->control.flags & IEEE80211_TXCTL_USE_RTS_CTS) { - if (status == TX_SUCCESS || status == TX_SUCCESS_RETRY) - stats->dot11RTSSuccessCount++; - else - stats->dot11RTSFailureCount++; - } - - /* - * Send the tx_status to mac80211, - * that method also cleans up the skb structure. - */ - ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status); - - entry->skb = NULL; -} -EXPORT_SYMBOL_GPL(rt2x00lib_txdone); - -void rt2x00lib_rxdone(struct data_entry *entry, char *data, - const int size, const int signal, const int rssi, const int ofdm) -{ - struct rt2x00_dev *rt2x00dev = entry->ring->rt2x00dev; - struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; - struct ieee80211_hw_mode *mode; - struct ieee80211_rate *rate; - struct sk_buff *skb; - unsigned int i; - int val = 0; - - /* - * Update RX statistics. - */ - mode = &rt2x00dev->hwmodes[rt2x00dev->curr_hwmode]; - for (i = 0; i < mode->num_rates; i++) { - rate = &mode->rates[i]; - - /* - * When frame was received with an OFDM bitrate, - * the signal is the PLCP value. If it was received with - * a CCK bitrate the signal is the rate in 0.5kbit/s. - */ - if (!ofdm) - val = DEVICE_GET_RATE_FIELD(rate->val, RATE); - else - val = DEVICE_GET_RATE_FIELD(rate->val, PLCP); - - if (val == signal) { - /* - * Check for preamble bit. - */ - if (signal & 0x08) - val = rate->val2; - else - val = rate->val; - break; - } - } - - rx_status->rate = val; - rx_status->ssi = rssi; - rt2x00_update_link_rssi(&rt2x00dev->link, rssi); - - /* - * Let's allocate a sk_buff where we can store the received data in, - * note that if data is NULL, we still have to allocate a sk_buff - * but that we should use that to replace the sk_buff which is already - * inside the entry. - */ - skb = dev_alloc_skb(size + NET_IP_ALIGN); - if (!skb) - return; - - skb_reserve(skb, NET_IP_ALIGN); - skb_put(skb, size); - - if (data) { - memcpy(skb->data, data, size); - entry->skb = skb; - skb = NULL; - } - - ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status); - entry->skb = skb; -} -EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); - -/* - * TX descriptor initializer - */ -void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct data_entry *entry, struct data_desc *txd, - struct ieee80211_hdr *ieee80211hdr, unsigned int length, - struct ieee80211_tx_control *control) -{ - struct data_entry_desc desc; - int tx_rate; - int bitrate; - int duration; - int residual; - u16 frame_control; - u16 seq_ctrl; - - /* - * Identify queue - */ - if (control->queue < rt2x00dev->hw->queues) - desc.queue = control->queue; - else - desc.queue = 15; - - /* - * Read required fields from ieee80211 header. - */ - frame_control = le16_to_cpu(ieee80211hdr->frame_control); - seq_ctrl = le16_to_cpu(ieee80211hdr->seq_ctrl); - - tx_rate = control->tx_rate; - - /* - * Check if this is a RTS/CTS frame - */ - if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) { - if (is_rts_frame(frame_control)) - __set_bit(ENTRY_TXD_RTS_FRAME, &entry->flags); - if (control->rts_cts_rate) - tx_rate = control->rts_cts_rate; - } - - /* - * Check for OFDM - */ - if (DEVICE_GET_RATE_FIELD(tx_rate, RATEMASK) & DEV_OFDM_RATE) - __set_bit(ENTRY_TXD_OFDM_RATE, &entry->flags); - - /* - * Check if more fragments are pending - */ - if (ieee80211_get_morefrag(ieee80211hdr)) - __set_bit(ENTRY_TXD_MORE_FRAG, &entry->flags); - - /* - * Beacons and probe responses require the tsf timestamp - * to be inserted into the frame. - */ - if (control->queue == IEEE80211_TX_QUEUE_BEACON || - is_probe_resp(frame_control)) - __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &entry->flags); - - /* - * Check if ACK is required - */ - if (!(control->flags & IEEE80211_TXCTL_NO_ACK)) - __set_bit(ENTRY_TXD_REQ_ACK, &entry->flags); - - /* - * Determine with what IFS priority this frame should be send. - * Set ifs to IFS_SIFS when the this is not the first fragment, - * or this fragment came after RTS/CTS. - */ - if ((seq_ctrl & IEEE80211_SCTL_FRAG) > 0 || - test_bit(ENTRY_TXD_RTS_FRAME, &entry->flags)) - desc.ifs = IFS_SIFS; - else - desc.ifs = IFS_BACKOFF; - - /* - * How the length should be processed depends - * on if we are working with OFDM rates or not. - */ - if (test_bit(ENTRY_TXD_OFDM_RATE, &entry->flags)) { - residual = 0; - desc.length_high = ((length + FCS_LEN) >> 6) & 0x3f; - desc.length_low = ((length + FCS_LEN) & 0x3f); - - } else { - bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE); - - /* - * Convert length to microseconds. - */ - residual = get_duration_res(length + FCS_LEN, bitrate); - duration = get_duration(length + FCS_LEN, bitrate); - - if (residual != 0) - duration++; - - desc.length_high = duration >> 8; - desc.length_low = duration & 0xff; - } - - /* - * Create the signal and service values. - */ - desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP); - if (DEVICE_GET_RATE_FIELD(tx_rate, PREAMBLE)) - desc.signal |= 0x08; - - desc.service = 0x04; - if (residual <= (8 % 11)) - desc.service |= 0x80; - - rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry, txd, &desc, - ieee80211hdr, length, control); -} -EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc); - -/* * rt2x00lib module information. */ MODULE_AUTHOR(DRV_PROJECT); diff --git a/drivers/net/wireless/mac80211/rt2x00/rt2x00pci.c b/drivers/net/wireless/mac80211/rt2x00/rt2x00pci.c index 02b8744..8d7d9dc 100644 --- a/drivers/net/wireless/mac80211/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/mac80211/rt2x00/rt2x00pci.c @@ -200,7 +200,7 @@ EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); + ((__i) * (__ring)->data_size); \ }) -static int rt2x00pci_alloc_ring(struct rt2x00_dev *rt2x00dev, +static int rt2x00pci_alloc_dma(struct rt2x00_dev *rt2x00dev, struct data_ring *ring) { unsigned int i; @@ -226,6 +226,16 @@ static int rt2x00pci_alloc_ring(struct rt2x00_dev *rt2x00dev, return 0; } +static void rt2x00pci_free_dma(struct rt2x00_dev *rt2x00dev, + struct data_ring *ring) +{ + if (ring->data_addr) + pci_free_consistent(rt2x00dev_pci(rt2x00dev), + rt2x00_get_ring_size(ring), + ring->data_addr, ring->data_dma); + ring->data_addr = NULL; +} + int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) { struct pci_dev *pci_dev = rt2x00dev_pci(rt2x00dev); @@ -236,7 +246,7 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) * Allocate DMA */ ring_for_each(rt2x00dev, ring) { - status = rt2x00pci_alloc_ring(rt2x00dev, ring); + status = rt2x00pci_alloc_dma(rt2x00dev, ring); if (status) goto exit; } @@ -245,7 +255,7 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) * Register interrupt handler. */ status = request_irq(pci_dev->irq, rt2x00dev->ops->lib->irq_handler, - IRQF_SHARED, pci_dev->driver->name, rt2x00dev); + IRQF_SHARED, pci_name(pci_dev), rt2x00dev); if (status) { ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", pci_dev->irq, status); @@ -273,13 +283,8 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) /* * Free DMA */ - ring_for_each(rt2x00dev, ring) { - if (ring->data_addr) - pci_free_consistent(rt2x00dev_pci(rt2x00dev), - rt2x00_get_ring_size(ring), - ring->data_addr, ring->data_dma); - ring->data_addr = NULL; - } + ring_for_each(rt2x00dev, ring) + rt2x00pci_free_dma(rt2x00dev, ring); } EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize); @@ -307,6 +312,21 @@ static void rt2x00pci_free_csr(struct rt2x00_dev *rt2x00dev) } } +static int rt2x00pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev) +{ + rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL); + if (!rt2x00dev->eeprom) + return -ENOMEM; + + return 0; +} + +static void rt2x00pci_free_eeprom(struct rt2x00_dev *rt2x00dev) +{ + kfree(rt2x00dev->eeprom); + rt2x00dev->eeprom = NULL; +} + int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) { struct rt2x00_ops *ops = (struct rt2x00_ops*)id->driver_data; @@ -356,12 +376,19 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) if (retval) goto exit_free_device; - retval = rt2x00lib_probe_dev(rt2x00dev); + retval = rt2x00pci_alloc_eeprom(rt2x00dev); if (retval) goto exit_free_csr; + retval = rt2x00lib_probe_dev(rt2x00dev); + if (retval) + goto exit_free_eeprom; + return 0; +exit_free_eeprom: + rt2x00pci_free_eeprom(rt2x00dev); + exit_free_csr: rt2x00pci_free_csr(rt2x00dev); @@ -390,6 +417,8 @@ void rt2x00pci_remove(struct pci_dev *pci_dev) * Free all allocated data. */ rt2x00lib_remove_dev(rt2x00dev); + rt2x00pci_free_eeprom(rt2x00dev); + rt2x00pci_free_csr(rt2x00dev); ieee80211_free_hw(hw); /* @@ -412,6 +441,7 @@ int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state) if (retval) return retval; + rt2x00pci_free_eeprom(rt2x00dev); rt2x00pci_free_csr(rt2x00dev); pci_save_state(pci_dev); @@ -437,6 +467,12 @@ int rt2x00pci_resume(struct pci_dev *pci_dev) if (retval) return retval; + retval = rt2x00pci_alloc_eeprom(rt2x00dev); + if (retval) { + rt2x00pci_free_csr(rt2x00dev); + return retval; + } + return rt2x00lib_resume(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00pci_resume); diff --git a/drivers/net/wireless/mac80211/rt2x00/rt2x00usb.c b/drivers/net/wireless/mac80211/rt2x00/rt2x00usb.c index 9eee567..02f8062 100644 --- a/drivers/net/wireless/mac80211/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/mac80211/rt2x00/rt2x00usb.c @@ -410,7 +410,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); /* * Device initialization handlers. */ -static int rt2x00usb_alloc_ring(struct rt2x00_dev *rt2x00dev, +static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, struct data_ring *ring) { unsigned int i; @@ -427,6 +427,22 @@ static int rt2x00usb_alloc_ring(struct rt2x00_dev *rt2x00dev, return 0; } +static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, + struct data_ring *ring) +{ + unsigned int i; + + if (!ring->entry) + return; + + for (i = 0; i < ring->stats.limit; i++) { + usb_kill_urb(ring->entry[i].priv); + usb_free_urb(ring->entry[i].priv); + if (ring->entry[i].skb) + kfree_skb(ring->entry[i].skb); + } +} + int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) { struct data_ring *ring; @@ -439,7 +455,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) * Allocate DMA */ ring_for_each(rt2x00dev, ring) { - status = rt2x00usb_alloc_ring(rt2x00dev, ring); + status = rt2x00usb_alloc_urb(rt2x00dev, ring); if (status) goto exit; } @@ -471,25 +487,30 @@ EXPORT_SYMBOL_GPL(rt2x00usb_initialize); void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev) { struct data_ring *ring; - unsigned int i; - - ring_for_each(rt2x00dev, ring) { - if (!ring->entry) - continue; - for (i = 0; i < ring->stats.limit; i++) { - usb_kill_urb(ring->entry[i].priv); - usb_free_urb(ring->entry[i].priv); - if (ring->entry[i].skb) - kfree_skb(ring->entry[i].skb); - } - } + ring_for_each(rt2x00dev, ring) + rt2x00usb_free_urb(rt2x00dev, ring); } EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize); /* * USB driver handlers. */ +static int rt2x00usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev) +{ + rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL); + if (!rt2x00dev->eeprom) + return -ENOMEM; + + return 0; +} + +static void rt2x00usb_free_eeprom(struct rt2x00_dev *rt2x00dev) +{ + kfree(rt2x00dev->eeprom); + rt2x00dev->eeprom = NULL; +} + int rt2x00usb_probe(struct usb_interface *usb_intf, const struct usb_device_id *id) { @@ -515,12 +536,19 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, rt2x00dev->ops = ops; rt2x00dev->hw = hw; - retval = rt2x00lib_probe_dev(rt2x00dev); + retval = rt2x00usb_alloc_eeprom(rt2x00dev); if (retval) goto exit_free_device; + retval = rt2x00lib_probe_dev(rt2x00dev); + if (retval) + goto exit_free_eeprom; + return 0; +exit_free_eeprom: + rt2x00usb_free_eeprom(rt2x00dev); + exit_free_device: ieee80211_free_hw(hw); @@ -542,6 +570,7 @@ void rt2x00usb_disconnect(struct usb_interface *usb_intf) * Free all allocated data. */ rt2x00lib_remove_dev(rt2x00dev); + rt2x00usb_free_eeprom(rt2x00dev); ieee80211_free_hw(hw); /* @@ -563,6 +592,8 @@ int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state) if (retval) return retval; + rt2x00usb_free_eeprom(rt2x00dev); + /* * Decrease usbdev refcount. */ @@ -576,9 +607,14 @@ int rt2x00usb_resume(struct usb_interface *usb_intf) { struct ieee80211_hw *hw = usb_get_intfdata(usb_intf); struct rt2x00_dev *rt2x00dev = hw->priv; + int retval; usb_get_dev(interface_to_usbdev(usb_intf)); + retval = rt2x00usb_alloc_eeprom(rt2x00dev); + if (retval) + return retval; + return rt2x00lib_resume(rt2x00dev); } EXPORT_SYMBOL_GPL(rt2x00usb_resume); diff --git a/drivers/net/wireless/mac80211/rt2x00/rt61pci.c b/drivers/net/wireless/mac80211/rt2x00/rt61pci.c index 7ef847d..c935a43 100644 --- a/drivers/net/wireless/mac80211/rt2x00/rt61pci.c +++ b/drivers/net/wireless/mac80211/rt2x00/rt61pci.c @@ -1905,7 +1905,7 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) /* * Device initialization functions. */ -static int rt61pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) { struct eeprom_93cx6 eeprom; u32 reg; @@ -1913,14 +1913,6 @@ static int rt61pci_alloc_eeprom(struct rt2x00_dev *rt2x00dev) u8 *mac; char value; - /* - * Allocate the eeprom memory, check the eeprom width - * and copy the entire eeprom into this allocated memory. - */ - rt2x00dev->eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); - if (!rt2x00dev->eeprom) - return -ENOMEM; - rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); eeprom.data = rt2x00dev; @@ -2230,7 +2222,7 @@ static int rt61pci_init_hw(struct rt2x00_dev *rt2x00dev) /* * Allocate eeprom data. */ - retval = rt61pci_alloc_eeprom(rt2x00dev); + retval = rt61pci_validate_eeprom(rt2x00dev); if (retval) return retval; @@ -2360,13 +2352,14 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { }; static const struct rt2x00_ops rt61pci_ops = { - .name = DRV_NAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, - .lib = &rt61pci_rt2x00_ops, - .hw = &rt61pci_mac80211_ops, + .name = DRV_NAME, + .rxd_size = RXD_DESC_SIZE, + .txd_size = TXD_DESC_SIZE, + .eeprom_size = EEPROM_SIZE, + .lib = &rt61pci_rt2x00_ops, + .hw = &rt61pci_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt61pci_rt2x00debug, + .debugfs = &rt61pci_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; diff --git a/drivers/net/wireless/mac80211/rt2x00/rt73usb.c b/drivers/net/wireless/mac80211/rt2x00/rt73usb.c index 533067f..664cd38 100644 --- a/drivers/net/wireless/mac80211/rt2x00/rt73usb.c +++ b/drivers/net/wireless/mac80211/rt2x00/rt73usb.c @@ -1390,20 +1390,12 @@ static int rt73usb_fill_rxdone(struct data_entry *entry, /* * Device initialization functions. */ -static int rt73usb_alloc_eeprom(struct rt2x00_dev *rt2x00dev) +static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) { u16 word; u8 *mac; char value; - /* - * Allocate the eeprom memory, check the eeprom width - * and copy the entire eeprom into this allocated memory. - */ - rt2x00dev->eeprom = kzalloc(EEPROM_SIZE, GFP_KERNEL); - if (!rt2x00dev->eeprom) - return -ENOMEM; - rt2x00usb_vendor_request( rt2x00dev, USB_EEPROM_READ, USB_VENDOR_REQUEST_IN, EEPROM_BASE, 0x00, rt2x00dev->eeprom, EEPROM_SIZE, @@ -1685,7 +1677,7 @@ static int rt73usb_init_hw(struct rt2x00_dev *rt2x00dev) /* * Allocate eeprom data. */ - retval = rt73usb_alloc_eeprom(rt2x00dev); + retval = rt73usb_validate_eeprom(rt2x00dev); if (retval) return retval; @@ -1811,13 +1803,14 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { }; static const struct rt2x00_ops rt73usb_ops = { - .name = DRV_NAME, - .rxd_size = RXD_DESC_SIZE, - .txd_size = TXD_DESC_SIZE, - .lib = &rt73usb_rt2x00_ops, - .hw = &rt73usb_mac80211_ops, + .name = DRV_NAME, + .rxd_size = RXD_DESC_SIZE, + .txd_size = TXD_DESC_SIZE, + .eeprom_size = EEPROM_SIZE, + .lib = &rt73usb_rt2x00_ops, + .hw = &rt73usb_mac80211_ops, #ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt73usb_rt2x00debug, + .debugfs = &rt73usb_rt2x00debug, #endif /* CONFIG_RT2X00_LIB_DEBUGFS */ }; -- 1.5.2.2 - To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html