Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 134188
b: refs/heads/master
c: 7aaa1d7
h: refs/heads/master
v: v3
  • Loading branch information
Samuel Ortiz authored and John W. Linville committed Jan 29, 2009
1 parent fba38de commit d068f7f
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 164 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: 4f3602c8a3cf8d31e8b08b82d7ea9b0c30f28965
refs/heads/master: 7aaa1d79e3a2d573ac469744506f17b1c9386840
28 changes: 18 additions & 10 deletions trunk/drivers/net/wireless/iwlwifi/iwl-3945.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
tx_info = &txq->txb[txq->q.read_ptr];
ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]);
tx_info->skb[0] = NULL;
iwl3945_hw_txq_free_tfd(priv, txq);
priv->cfg->ops->lib->txq_free_tfd(priv, txq);
}

if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
Expand Down Expand Up @@ -724,15 +724,21 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
}

int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
dma_addr_t addr, u16 len)
int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
dma_addr_t addr, u16 len, u8 reset, u8 pad)
{
int count;
u32 pad;
struct iwl3945_tfd *tfd = (struct iwl3945_tfd *)ptr;
struct iwl_queue *q;
struct iwl3945_tfd *tfd;

q = &txq->q;
tfd = &txq->tfds39[q->write_ptr];

if (reset)
memset(tfd, 0, sizeof(*tfd));

count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
pad = TFD_CTL_PAD_GET(le32_to_cpu(tfd->control_flags));

if ((count >= NUM_TFD_CHUNKS) || (count < 0)) {
IWL_ERR(priv, "Error can not send more than %d chunks\n",
Expand All @@ -756,7 +762,7 @@ int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
*
* Does NOT advance any indexes
*/
int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
{
struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)&txq->tfds39[0];
struct iwl3945_tfd *tfd = &tfd_tmp[txq->q.read_ptr];
Expand All @@ -767,14 +773,14 @@ int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
/* classify bd */
if (txq->q.id == IWL_CMD_QUEUE_NUM)
/* nothing to cleanup after for host commands */
return 0;
return;

/* sanity check */
counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
if (counter > NUM_TFD_CHUNKS) {
IWL_ERR(priv, "Too many chunks: %i\n", counter);
/* @todo issue fatal error, it is quite serious situation */
return 0;
return;
}

/* unmap chunks if any */
Expand All @@ -791,7 +797,7 @@ int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
}
}
}
return 0;
return ;
}

u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *addr)
Expand Down Expand Up @@ -2697,6 +2703,8 @@ static int iwl3945_load_bsm(struct iwl_priv *priv)
}

static struct iwl_lib_ops iwl3945_lib = {
.txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
.txq_free_tfd = iwl3945_hw_txq_free_tfd,
.load_ucode = iwl3945_load_bsm,
.apm_ops = {
.init = iwl3945_apm_init,
Expand Down
9 changes: 6 additions & 3 deletions trunk/drivers/net/wireless/iwlwifi/iwl-3945.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,9 +260,12 @@ extern int iwl3945_hw_nic_stop_master(struct iwl_priv *priv);
extern void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv);
extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv);
extern int iwl3945_hw_nic_reset(struct iwl_priv *priv);
extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd,
dma_addr_t addr, u16 len);
extern int iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
dma_addr_t addr, u16 len,
u8 reset, u8 pad);
extern void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv,
struct iwl_tx_queue *txq);
extern int iwl3945_hw_get_temperature(struct iwl_priv *priv);
extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv,
struct iwl_tx_queue *txq);
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-4965.c
Original file line number Diff line number Diff line change
Expand Up @@ -2295,6 +2295,8 @@ static struct iwl_lib_ops iwl4965_lib = {
.txq_set_sched = iwl4965_txq_set_sched,
.txq_agg_enable = iwl4965_txq_agg_enable,
.txq_agg_disable = iwl4965_txq_agg_disable,
.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
.txq_free_tfd = iwl_hw_txq_free_tfd,
.rx_handler_setup = iwl4965_rx_handler_setup,
.setup_deferred_work = iwl4965_setup_deferred_work,
.cancel_deferred_work = iwl4965_cancel_deferred_work,
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-5000.c
Original file line number Diff line number Diff line change
Expand Up @@ -1492,6 +1492,8 @@ static struct iwl_lib_ops iwl5000_lib = {
.txq_set_sched = iwl5000_txq_set_sched,
.txq_agg_enable = iwl5000_txq_agg_enable,
.txq_agg_disable = iwl5000_txq_agg_disable,
.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
.txq_free_tfd = iwl_hw_txq_free_tfd,
.rx_handler_setup = iwl5000_rx_handler_setup,
.setup_deferred_work = iwl5000_setup_deferred_work,
.is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
Expand Down
120 changes: 120 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-agn.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,126 @@ static int iwl_send_beacon_cmd(struct iwl_priv *priv)
return rc;
}

static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
{
struct iwl_tfd_tb *tb = &tfd->tbs[idx];

dma_addr_t addr = get_unaligned_le32(&tb->lo);
if (sizeof(dma_addr_t) > sizeof(u32))
addr |=
((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;

return addr;
}

static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
{
struct iwl_tfd_tb *tb = &tfd->tbs[idx];

return le16_to_cpu(tb->hi_n_len) >> 4;
}

static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
dma_addr_t addr, u16 len)
{
struct iwl_tfd_tb *tb = &tfd->tbs[idx];
u16 hi_n_len = len << 4;

put_unaligned_le32(addr, &tb->lo);
if (sizeof(dma_addr_t) > sizeof(u32))
hi_n_len |= ((addr >> 16) >> 16) & 0xF;

tb->hi_n_len = cpu_to_le16(hi_n_len);

tfd->num_tbs = idx + 1;
}

static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
{
return tfd->num_tbs & 0x1f;
}

/**
* iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
* @priv - driver private data
* @txq - tx queue
*
* Does NOT advance any TFD circular buffer read/write indexes
* Does NOT free the TFD itself (which is within circular buffer)
*/
void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
{
struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)&txq->tfds[0];
struct iwl_tfd *tfd;
struct pci_dev *dev = priv->pci_dev;
int index = txq->q.read_ptr;
int i;
int num_tbs;

tfd = &tfd_tmp[index];

/* Sanity check on number of chunks */
num_tbs = iwl_tfd_get_num_tbs(tfd);

if (num_tbs >= IWL_NUM_OF_TBS) {
IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
/* @todo issue fatal error, it is quite serious situation */
return;
}

/* Unmap tx_cmd */
if (num_tbs)
pci_unmap_single(dev,
pci_unmap_addr(&txq->cmd[index]->meta, mapping),
pci_unmap_len(&txq->cmd[index]->meta, len),
PCI_DMA_TODEVICE);

/* Unmap chunks, if any. */
for (i = 1; i < num_tbs; i++) {
pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE);

if (txq->txb) {
dev_kfree_skb(txq->txb[txq->q.read_ptr].skb[i - 1]);
txq->txb[txq->q.read_ptr].skb[i - 1] = NULL;
}
}
}

int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
dma_addr_t addr, u16 len,
u8 reset, u8 pad)
{
struct iwl_queue *q;
struct iwl_tfd *tfd;
u32 num_tbs;

q = &txq->q;
tfd = &txq->tfds[q->write_ptr];

if (reset)
memset(tfd, 0, sizeof(*tfd));

num_tbs = iwl_tfd_get_num_tbs(tfd);

/* Each TFD can point to a maximum 20 Tx buffers */
if (num_tbs >= IWL_NUM_OF_TBS) {
IWL_ERR(priv, "Error can not send more than %d chunks\n",
IWL_NUM_OF_TBS);
return -EINVAL;
}

BUG_ON(addr & ~DMA_BIT_MASK(36));
if (unlikely(addr & ~IWL_TX_DMA_MASK))
IWL_ERR(priv, "Unaligned address = %llx\n",
(unsigned long long)addr);

iwl_tfd_set_tb(tfd, num_tbs, addr, len);

return 0;
}

/******************************************************************************
*
* Misc. internal state and helper functions
Expand Down
10 changes: 10 additions & 0 deletions trunk/drivers/net/wireless/iwlwifi/iwl-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ struct iwl_lib_ops {
void (*txq_inval_byte_cnt_tbl)(struct iwl_priv *priv,
struct iwl_tx_queue *txq);
void (*txq_set_sched)(struct iwl_priv *priv, u32 mask);
int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
dma_addr_t addr,
u16 len, u8 reset, u8 pad);
void (*txq_free_tfd)(struct iwl_priv *priv,
struct iwl_tx_queue *txq);
/* aggregations */
int (*txq_agg_enable)(struct iwl_priv *priv, int txq_id, int tx_fifo,
int sta_id, int tid, u16 ssn_idx);
Expand Down Expand Up @@ -252,6 +258,10 @@ void iwl_rx_statistics(struct iwl_priv *priv,
* TX
******************************************************/
int iwl_txq_ctx_reset(struct iwl_priv *priv);
void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
dma_addr_t addr, u16 len, u8 reset, u8 pad);
int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
Expand Down
Loading

0 comments on commit d068f7f

Please sign in to comment.