Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 171454
b: refs/heads/master
c: 54bc3a0
h: refs/heads/master
v: v3
  • Loading branch information
Lennert Buytenhek authored and John W. Linville committed Nov 6, 2009
1 parent c3c051a commit 07f3b9a
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 62 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 788838ebe8a4caca93a91982c7bbf393edf24c08
refs/heads/master: 54bc3a0d7a0c9a13da31183609c42cf7786138e1
180 changes: 119 additions & 61 deletions trunk/drivers/net/wireless/mwl8k.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,18 @@
#define MWL8K_RX_QUEUES 1
#define MWL8K_TX_QUEUES 4

struct rxd_ops {
int rxd_size;
void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr);
void (*rxd_refill)(void *rxd, dma_addr_t addr, int len);
int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status);
};

struct mwl8k_device_info {
char *part_name;
char *helper_image;
char *fw_image;
struct rxd_ops *rxd_ops;
};

struct mwl8k_rx_queue {
Expand All @@ -95,7 +103,7 @@ struct mwl8k_rx_queue {
/* refill descs here */
int tail;

struct mwl8k_rx_desc *rxd;
void *rxd;
dma_addr_t rxd_dma;
struct {
struct sk_buff *skb;
Expand Down Expand Up @@ -134,6 +142,7 @@ struct mwl8k_priv {

struct mwl8k_device_info *device_info;
bool ap_fw;
struct rxd_ops *rxd_ops;

/* firmware files and meta data */
struct mwl8k_firmware fw;
Expand Down Expand Up @@ -744,9 +753,7 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb)
/*
* Packet reception.
*/
#define MWL8K_RX_CTRL_OWNED_BY_HOST 0x02

struct mwl8k_rx_desc {
struct mwl8k_rxd_8687 {
__le16 pkt_len;
__u8 link_quality;
__u8 noise_level;
Expand All @@ -763,16 +770,79 @@ struct mwl8k_rx_desc {
__u8 pad2[2];
} __attribute__((packed));

#define MWL8K_8687_RATE_INFO_SHORTPRE 0x8000
#define MWL8K_8687_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3)
#define MWL8K_8687_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f)
#define MWL8K_8687_RATE_INFO_40MHZ 0x0004
#define MWL8K_8687_RATE_INFO_SHORTGI 0x0002
#define MWL8K_8687_RATE_INFO_MCS_FORMAT 0x0001

#define MWL8K_8687_RX_CTRL_OWNED_BY_HOST 0x02

static void mwl8k_rxd_8687_init(void *_rxd, dma_addr_t next_dma_addr)
{
struct mwl8k_rxd_8687 *rxd = _rxd;

rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr);
rxd->rx_ctrl = MWL8K_8687_RX_CTRL_OWNED_BY_HOST;
}

static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len)
{
struct mwl8k_rxd_8687 *rxd = _rxd;

rxd->pkt_len = cpu_to_le16(len);
rxd->pkt_phys_addr = cpu_to_le32(addr);
wmb();
rxd->rx_ctrl = 0;
}

static int
mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status)
{
struct mwl8k_rxd_8687 *rxd = _rxd;
u16 rate_info;

if (!(rxd->rx_ctrl & MWL8K_8687_RX_CTRL_OWNED_BY_HOST))
return -1;
rmb();

rate_info = le16_to_cpu(rxd->rate_info);

memset(status, 0, sizeof(*status));

status->signal = -rxd->rssi;
status->noise = -rxd->noise_level;
status->qual = rxd->link_quality;
status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info);
status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info);

if (rate_info & MWL8K_8687_RATE_INFO_SHORTPRE)
status->flag |= RX_FLAG_SHORTPRE;
if (rate_info & MWL8K_8687_RATE_INFO_40MHZ)
status->flag |= RX_FLAG_40MHZ;
if (rate_info & MWL8K_8687_RATE_INFO_SHORTGI)
status->flag |= RX_FLAG_SHORT_GI;
if (rate_info & MWL8K_8687_RATE_INFO_MCS_FORMAT)
status->flag |= RX_FLAG_HT;

status->band = IEEE80211_BAND_2GHZ;
status->freq = ieee80211_channel_to_frequency(rxd->channel);

return le16_to_cpu(rxd->pkt_len);
}

static struct rxd_ops rxd_8687_ops = {
.rxd_size = sizeof(struct mwl8k_rxd_8687),
.rxd_init = mwl8k_rxd_8687_init,
.rxd_refill = mwl8k_rxd_8687_refill,
.rxd_process = mwl8k_rxd_8687_process,
};


#define MWL8K_RX_DESCS 256
#define MWL8K_RX_MAXSZ 3800

#define RATE_INFO_SHORTPRE 0x8000
#define RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3)
#define RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f)
#define RATE_INFO_40MHZ 0x0004
#define RATE_INFO_SHORTGI 0x0002
#define RATE_INFO_MCS_FORMAT 0x0001

static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
{
struct mwl8k_priv *priv = hw->priv;
Expand All @@ -784,7 +854,7 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
rxq->head = 0;
rxq->tail = 0;

size = MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc);
size = MWL8K_RX_DESCS * priv->rxd_ops->rxd_size;

rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma);
if (rxq->rxd == NULL) {
Expand All @@ -804,15 +874,20 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
memset(rxq->buf, 0, MWL8K_RX_DESCS * sizeof(*rxq->buf));

for (i = 0; i < MWL8K_RX_DESCS; i++) {
struct mwl8k_rx_desc *rx_desc;
int desc_size;
void *rxd;
int nexti;
dma_addr_t next_dma_addr;

desc_size = priv->rxd_ops->rxd_size;
rxd = rxq->rxd + (i * priv->rxd_ops->rxd_size);

rx_desc = rxq->rxd + i;
nexti = (i + 1) % MWL8K_RX_DESCS;
nexti = i + 1;
if (nexti == MWL8K_RX_DESCS)
nexti = 0;
next_dma_addr = rxq->rxd_dma + (nexti * desc_size);

rx_desc->next_rxd_phys_addr =
cpu_to_le32(rxq->rxd_dma + nexti * sizeof(*rx_desc));
rx_desc->rx_ctrl = MWL8K_RX_CTRL_OWNED_BY_HOST;
priv->rxd_ops->rxd_init(rxd, next_dma_addr);
}

return 0;
Expand All @@ -829,25 +904,24 @@ static int rxq_refill(struct ieee80211_hw *hw, int index, int limit)
struct sk_buff *skb;
dma_addr_t addr;
int rx;
void *rxd;

skb = dev_alloc_skb(MWL8K_RX_MAXSZ);
if (skb == NULL)
break;

rxq->rxd_count++;

rx = rxq->tail;
rxq->tail = (rx + 1) % MWL8K_RX_DESCS;

addr = pci_map_single(priv->pdev, skb->data,
MWL8K_RX_MAXSZ, DMA_FROM_DEVICE);

rxq->rxd[rx].pkt_len = cpu_to_le16(MWL8K_RX_MAXSZ);
rxq->rxd[rx].pkt_phys_addr = cpu_to_le32(addr);
rxq->rxd_count++;
rx = rxq->tail++;
if (rxq->tail == MWL8K_RX_DESCS)
rxq->tail = 0;
rxq->buf[rx].skb = skb;
pci_unmap_addr_set(&rxq->buf[rx], dma, addr);
wmb();
rxq->rxd[rx].rx_ctrl = 0;

rxd = rxq->rxd + (rx * priv->rxd_ops->rxd_size);
priv->rxd_ops->rxd_refill(rxd, addr, MWL8K_RX_MAXSZ);

refilled++;
}
Expand Down Expand Up @@ -878,7 +952,7 @@ static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index)
rxq->buf = NULL;

pci_free_consistent(priv->pdev,
MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc),
MWL8K_RX_DESCS * priv->rxd_ops->rxd_size,
rxq->rxd, rxq->rxd_dma);
rxq->rxd = NULL;
}
Expand Down Expand Up @@ -922,63 +996,45 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)

processed = 0;
while (rxq->rxd_count && limit--) {
struct mwl8k_rx_desc *rx_desc;
struct sk_buff *skb;
void *rxd;
int pkt_len;
struct ieee80211_rx_status status;
struct ieee80211_hdr *wh;
u16 rate_info;

rx_desc = rxq->rxd + rxq->head;
if (!(rx_desc->rx_ctrl & MWL8K_RX_CTRL_OWNED_BY_HOST))
break;
rmb();

skb = rxq->buf[rxq->head].skb;
if (skb == NULL)
break;

rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size);

pkt_len = priv->rxd_ops->rxd_process(rxd, &status);
if (pkt_len < 0)
break;

rxq->buf[rxq->head].skb = NULL;

pci_unmap_single(priv->pdev,
pci_unmap_addr(&rxq->buf[rxq->head], dma),
MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
pci_unmap_addr_set(&rxq->buf[rxq->head], dma, 0);

rxq->head = (rxq->head + 1) % MWL8K_RX_DESCS;
rxq->head++;
if (rxq->head == MWL8K_RX_DESCS)
rxq->head = 0;

rxq->rxd_count--;

skb_put(skb, le16_to_cpu(rx_desc->pkt_len));
skb_put(skb, pkt_len);
mwl8k_remove_dma_header(skb);

wh = (struct ieee80211_hdr *)skb->data;

/*
* Check for a pending join operation. Save a
* copy of the beacon and schedule a tasklet to
* send a FINALIZE_JOIN command to the firmware.
*/
if (mwl8k_capture_bssid(priv, wh))
if (mwl8k_capture_bssid(priv, (void *)skb->data))
mwl8k_save_beacon(hw, skb);

rate_info = le16_to_cpu(rx_desc->rate_info);

memset(&status, 0, sizeof(status));
status.mactime = 0;
status.signal = -rx_desc->rssi;
status.noise = -rx_desc->noise_level;
status.qual = rx_desc->link_quality;
status.antenna = RATE_INFO_ANTSELECT(rate_info);
status.rate_idx = RATE_INFO_RATEID(rate_info);
status.flag = 0;
if (rate_info & RATE_INFO_SHORTPRE)
status.flag |= RX_FLAG_SHORTPRE;
if (rate_info & RATE_INFO_40MHZ)
status.flag |= RX_FLAG_40MHZ;
if (rate_info & RATE_INFO_SHORTGI)
status.flag |= RX_FLAG_SHORT_GI;
if (rate_info & RATE_INFO_MCS_FORMAT)
status.flag |= RX_FLAG_HT;
status.band = IEEE80211_BAND_2GHZ;
status.freq = ieee80211_channel_to_frequency(rx_desc->channel);
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
ieee80211_rx_irqsafe(hw, skb);

Expand Down Expand Up @@ -2959,6 +3015,7 @@ static struct mwl8k_device_info di_8687 = {
.part_name = "88w8687",
.helper_image = "mwl8k/helper_8687.fw",
.fw_image = "mwl8k/fmimage_8687.fw",
.rxd_ops = &rxd_8687_ops,
};

static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
Expand Down Expand Up @@ -3014,6 +3071,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
priv->hw = hw;
priv->pdev = pdev;
priv->device_info = (void *)id->driver_data;
priv->rxd_ops = priv->device_info->rxd_ops;
priv->sniffer_enabled = false;
priv->wmm_enabled = false;
priv->pending_tx_pkts = 0;
Expand Down

0 comments on commit 07f3b9a

Please sign in to comment.