|
@@ -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)) {
|