Commit 2b72c784 authored by Ron Mercer's avatar Ron Mercer Committed by David S. Miller

qlge: bugfix: Fix shadow register endian issue.

Shadow registers are consistent memory locations to which the chip
echos ring indexes in little endian format.  These values need to
be endian swapped before referencing.

Note:
The register pointer declaration uses the volatile modifier which
causes warnings in checkpatch.
Per Documentation/volatile-considered-harmful.txt:
  - Pointers to data structures in coherent memory which might be modified
    by I/O devices can, sometimes, legitimately be volatile.  A ring buffer
    used by a network adapter, where that adapter changes pointers to
    indicate which descriptors have been processed, is an example of this
    type of situation.
Signed-off-by: default avatarRon Mercer <ron.mercer@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4055c7d4
...@@ -1189,7 +1189,7 @@ struct rx_ring { ...@@ -1189,7 +1189,7 @@ struct rx_ring {
u32 cq_size; u32 cq_size;
u32 cq_len; u32 cq_len;
u16 cq_id; u16 cq_id;
u32 *prod_idx_sh_reg; /* Shadowed producer register. */ volatile __le32 *prod_idx_sh_reg; /* Shadowed producer register. */
dma_addr_t prod_idx_sh_reg_dma; dma_addr_t prod_idx_sh_reg_dma;
void __iomem *cnsmr_idx_db_reg; /* PCI doorbell mem area + 0 */ void __iomem *cnsmr_idx_db_reg; /* PCI doorbell mem area + 0 */
u32 cnsmr_idx; /* current sw idx */ u32 cnsmr_idx; /* current sw idx */
...@@ -1467,21 +1467,6 @@ static inline void ql_write_db_reg(u32 val, void __iomem *addr) ...@@ -1467,21 +1467,6 @@ static inline void ql_write_db_reg(u32 val, void __iomem *addr)
mmiowb(); mmiowb();
} }
/*
* Shadow Registers:
* Outbound queues have a consumer index that is maintained by the chip.
* Inbound queues have a producer index that is maintained by the chip.
* For lower overhead, these registers are "shadowed" to host memory
* which allows the device driver to track the queue progress without
* PCI reads. When an entry is placed on an inbound queue, the chip will
* update the relevant index register and then copy the value to the
* shadow register in host memory.
*/
static inline unsigned int ql_read_sh_reg(const volatile void *addr)
{
return *(volatile unsigned int __force *)addr;
}
extern char qlge_driver_name[]; extern char qlge_driver_name[];
extern const char qlge_driver_version[]; extern const char qlge_driver_version[];
extern const struct ethtool_ops qlge_ethtool_ops; extern const struct ethtool_ops qlge_ethtool_ops;
......
...@@ -1559,7 +1559,7 @@ static void ql_process_chip_ae_intr(struct ql_adapter *qdev, ...@@ -1559,7 +1559,7 @@ static void ql_process_chip_ae_intr(struct ql_adapter *qdev,
static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
{ {
struct ql_adapter *qdev = rx_ring->qdev; struct ql_adapter *qdev = rx_ring->qdev;
u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); u32 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
struct ob_mac_iocb_rsp *net_rsp = NULL; struct ob_mac_iocb_rsp *net_rsp = NULL;
int count = 0; int count = 0;
...@@ -1585,7 +1585,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) ...@@ -1585,7 +1585,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
} }
count++; count++;
ql_update_cq(rx_ring); ql_update_cq(rx_ring);
prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
} }
ql_write_cq_idx(rx_ring); ql_write_cq_idx(rx_ring);
if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) { if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) {
...@@ -1605,7 +1605,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) ...@@ -1605,7 +1605,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget) static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget)
{ {
struct ql_adapter *qdev = rx_ring->qdev; struct ql_adapter *qdev = rx_ring->qdev;
u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); u32 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
struct ql_net_rsp_iocb *net_rsp; struct ql_net_rsp_iocb *net_rsp;
int count = 0; int count = 0;
...@@ -1638,7 +1638,7 @@ static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget) ...@@ -1638,7 +1638,7 @@ static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget)
} }
count++; count++;
ql_update_cq(rx_ring); ql_update_cq(rx_ring);
prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
if (count == budget) if (count == budget)
break; break;
} }
...@@ -1801,7 +1801,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) ...@@ -1801,7 +1801,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
* Check the default queue and wake handler if active. * Check the default queue and wake handler if active.
*/ */
rx_ring = &qdev->rx_ring[0]; rx_ring = &qdev->rx_ring[0];
if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) { if (le32_to_cpu(*rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) {
QPRINTK(qdev, INTR, INFO, "Waking handler for rx_ring[0].\n"); QPRINTK(qdev, INTR, INFO, "Waking handler for rx_ring[0].\n");
ql_disable_completion_interrupt(qdev, intr_context->intr); ql_disable_completion_interrupt(qdev, intr_context->intr);
queue_delayed_work_on(smp_processor_id(), qdev->q_workqueue, queue_delayed_work_on(smp_processor_id(), qdev->q_workqueue,
...@@ -1815,7 +1815,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) ...@@ -1815,7 +1815,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
*/ */
for (i = 1; i < qdev->rx_ring_count; i++) { for (i = 1; i < qdev->rx_ring_count; i++) {
rx_ring = &qdev->rx_ring[i]; rx_ring = &qdev->rx_ring[i];
if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != if (le32_to_cpu(*rx_ring->prod_idx_sh_reg) !=
rx_ring->cnsmr_idx) { rx_ring->cnsmr_idx) {
QPRINTK(qdev, INTR, INFO, QPRINTK(qdev, INTR, INFO,
"Waking handler for rx_ring[%d].\n", i); "Waking handler for rx_ring[%d].\n", i);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment