提交 4545a3f2 编写于 作者: R Ron Mercer 提交者: David S. Miller

qlge: Use one path to (re)fill rx buffers.

Currently there are two paths for filling rx buffer queues. One is
used during initialization and the other during runtime.  This patch
removes ql_alloc_sbq_buffers() and ql_alloc_lbq_buffers() and replaces
them with a call to the runtime functions ql_update_lbq() and
ql_update_sbq().
Signed-off-by: NRon Mercer <ron.mercer@qlogic.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 49f2186d
......@@ -2105,47 +2105,6 @@ static void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring
}
}
/*
* Allocate and map a page for each element of the lbq.
*/
static int ql_alloc_lbq_buffers(struct ql_adapter *qdev,
struct rx_ring *rx_ring)
{
int i;
struct bq_desc *lbq_desc;
u64 map;
__le64 *bq = rx_ring->lbq_base;
for (i = 0; i < rx_ring->lbq_len; i++) {
lbq_desc = &rx_ring->lbq[i];
memset(lbq_desc, 0, sizeof(lbq_desc));
lbq_desc->addr = bq;
lbq_desc->index = i;
lbq_desc->p.lbq_page = alloc_page(GFP_ATOMIC);
if (unlikely(!lbq_desc->p.lbq_page)) {
QPRINTK(qdev, IFUP, ERR, "failed alloc_page().\n");
goto mem_error;
} else {
map = pci_map_page(qdev->pdev,
lbq_desc->p.lbq_page,
0, PAGE_SIZE, PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(qdev->pdev, map)) {
QPRINTK(qdev, IFUP, ERR,
"PCI mapping failed.\n");
goto mem_error;
}
pci_unmap_addr_set(lbq_desc, mapaddr, map);
pci_unmap_len_set(lbq_desc, maplen, PAGE_SIZE);
*lbq_desc->addr = cpu_to_le64(map);
}
bq++;
}
return 0;
mem_error:
ql_free_lbq_buffers(qdev, rx_ring);
return -ENOMEM;
}
static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
{
int i;
......@@ -2168,63 +2127,72 @@ static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring
}
}
/* Allocate and map an skb for each element of the sbq. */
static int ql_alloc_sbq_buffers(struct ql_adapter *qdev,
/* Free all large and small rx buffers associated
* with the completion queues for this device.
*/
static void ql_free_rx_buffers(struct ql_adapter *qdev)
{
int i;
struct rx_ring *rx_ring;
for (i = 0; i < qdev->rx_ring_count; i++) {
rx_ring = &qdev->rx_ring[i];
if (rx_ring->lbq)
ql_free_lbq_buffers(qdev, rx_ring);
if (rx_ring->sbq)
ql_free_sbq_buffers(qdev, rx_ring);
}
}
static void ql_alloc_rx_buffers(struct ql_adapter *qdev)
{
struct rx_ring *rx_ring;
int i;
for (i = 0; i < qdev->rx_ring_count; i++) {
rx_ring = &qdev->rx_ring[i];
if (rx_ring->type != TX_Q)
ql_update_buffer_queues(qdev, rx_ring);
}
}
static void ql_init_lbq_ring(struct ql_adapter *qdev,
struct rx_ring *rx_ring)
{
int i;
struct bq_desc *lbq_desc;
__le64 *bq = rx_ring->lbq_base;
memset(rx_ring->lbq, 0, rx_ring->lbq_len * sizeof(struct bq_desc));
for (i = 0; i < rx_ring->lbq_len; i++) {
lbq_desc = &rx_ring->lbq[i];
memset(lbq_desc, 0, sizeof(*lbq_desc));
lbq_desc->index = i;
lbq_desc->addr = bq;
bq++;
}
}
static void ql_init_sbq_ring(struct ql_adapter *qdev,
struct rx_ring *rx_ring)
{
int i;
struct bq_desc *sbq_desc;
struct sk_buff *skb;
u64 map;
__le64 *bq = rx_ring->sbq_base;
memset(rx_ring->sbq, 0, rx_ring->sbq_len * sizeof(struct bq_desc));
for (i = 0; i < rx_ring->sbq_len; i++) {
sbq_desc = &rx_ring->sbq[i];
memset(sbq_desc, 0, sizeof(sbq_desc));
memset(sbq_desc, 0, sizeof(*sbq_desc));
sbq_desc->index = i;
sbq_desc->addr = bq;
skb = netdev_alloc_skb(qdev->ndev, rx_ring->sbq_buf_size);
if (unlikely(!skb)) {
/* Better luck next round */
QPRINTK(qdev, IFUP, ERR,
"small buff alloc failed for %d bytes at index %d.\n",
rx_ring->sbq_buf_size, i);
goto mem_err;
}
skb_reserve(skb, QLGE_SB_PAD);
sbq_desc->p.skb = skb;
/*
* Map only half the buffer. Because the
* other half may get some data copied to it
* when the completion arrives.
*/
map = pci_map_single(qdev->pdev,
skb->data,
rx_ring->sbq_buf_size / 2,
PCI_DMA_FROMDEVICE);
if (pci_dma_mapping_error(qdev->pdev, map)) {
QPRINTK(qdev, IFUP, ERR, "PCI mapping failed.\n");
goto mem_err;
}
pci_unmap_addr_set(sbq_desc, mapaddr, map);
pci_unmap_len_set(sbq_desc, maplen, rx_ring->sbq_buf_size / 2);
*sbq_desc->addr = cpu_to_le64(map);
bq++;
}
return 0;
mem_err:
ql_free_sbq_buffers(qdev, rx_ring);
return -ENOMEM;
}
static void ql_free_rx_resources(struct ql_adapter *qdev,
struct rx_ring *rx_ring)
{
if (rx_ring->sbq_len)
ql_free_sbq_buffers(qdev, rx_ring);
if (rx_ring->lbq_len)
ql_free_lbq_buffers(qdev, rx_ring);
/* Free the small buffer queue. */
if (rx_ring->sbq_base) {
pci_free_consistent(qdev->pdev,
......@@ -2302,11 +2270,7 @@ static int ql_alloc_rx_resources(struct ql_adapter *qdev,
goto err_mem;
}
if (ql_alloc_sbq_buffers(qdev, rx_ring)) {
QPRINTK(qdev, IFUP, ERR,
"Small buffer allocation failed.\n");
goto err_mem;
}
ql_init_sbq_ring(qdev, rx_ring);
}
if (rx_ring->lbq_len) {
......@@ -2334,14 +2298,7 @@ static int ql_alloc_rx_resources(struct ql_adapter *qdev,
goto err_mem;
}
/*
* Allocate the buffers.
*/
if (ql_alloc_lbq_buffers(qdev, rx_ring)) {
QPRINTK(qdev, IFUP, ERR,
"Large buffer allocation failed.\n");
goto err_mem;
}
ql_init_lbq_ring(qdev, rx_ring);
}
return 0;
......@@ -2489,10 +2446,10 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
bq_len = (rx_ring->lbq_len == 65536) ? 0 :
(u16) rx_ring->lbq_len;
cqicb->lbq_len = cpu_to_le16(bq_len);
rx_ring->lbq_prod_idx = rx_ring->lbq_len - 16;
rx_ring->lbq_prod_idx = 0;
rx_ring->lbq_curr_idx = 0;
rx_ring->lbq_clean_idx = rx_ring->lbq_prod_idx;
rx_ring->lbq_free_cnt = 16;
rx_ring->lbq_clean_idx = 0;
rx_ring->lbq_free_cnt = rx_ring->lbq_len;
}
if (rx_ring->sbq_len) {
cqicb->flags |= FLAGS_LS; /* Load sbq values */
......@@ -2504,10 +2461,10 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
bq_len = (rx_ring->sbq_len == 65536) ? 0 :
(u16) rx_ring->sbq_len;
cqicb->sbq_len = cpu_to_le16(bq_len);
rx_ring->sbq_prod_idx = rx_ring->sbq_len - 16;
rx_ring->sbq_prod_idx = 0;
rx_ring->sbq_curr_idx = 0;
rx_ring->sbq_clean_idx = rx_ring->sbq_prod_idx;
rx_ring->sbq_free_cnt = 16;
rx_ring->sbq_clean_idx = 0;
rx_ring->sbq_free_cnt = rx_ring->sbq_len;
}
switch (rx_ring->type) {
case TX_Q:
......@@ -2560,17 +2517,6 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
QPRINTK(qdev, IFUP, ERR, "Failed to load CQICB.\n");
return err;
}
QPRINTK(qdev, IFUP, INFO, "Successfully loaded CQICB.\n");
/*
* Advance the producer index for the buffer queues.
*/
wmb();
if (rx_ring->lbq_len)
ql_write_db_reg(rx_ring->lbq_prod_idx,
rx_ring->lbq_prod_idx_db_reg);
if (rx_ring->sbq_len)
ql_write_db_reg(rx_ring->sbq_prod_idx,
rx_ring->sbq_prod_idx_db_reg);
return err;
}
......@@ -3171,6 +3117,7 @@ static int ql_adapter_down(struct ql_adapter *qdev)
ql_tx_ring_clean(qdev);
ql_free_rx_buffers(qdev);
spin_lock(&qdev->hw_lock);
status = ql_adapter_reset(qdev);
if (status)
......@@ -3193,6 +3140,7 @@ static int ql_adapter_up(struct ql_adapter *qdev)
}
spin_unlock(&qdev->hw_lock);
set_bit(QL_ADAPTER_UP, &qdev->flags);
ql_alloc_rx_buffers(qdev);
ql_enable_interrupts(qdev);
ql_enable_all_completion_interrupts(qdev);
if ((ql_read32(qdev, STS) & qdev->port_init)) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册