aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorRon Mercer <ron.mercer@qlogic.com>2009-01-04 20:07:50 -0500
committerDavid S. Miller <davem@davemloft.net>2009-01-04 20:07:50 -0500
commit2b72c7849f9a091c1e5d7255732faf14ac7d5123 (patch)
tree50abd7531683f201cb45a650d9128c3afefa8216 /drivers/net
parent4055c7d495f2502718bbbea871e6504ae95add14 (diff)
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: Ron Mercer <ron.mercer@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/qlge/qlge.h17
-rw-r--r--drivers/net/qlge/qlge_main.c12
2 files changed, 7 insertions, 22 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index ba2e1c5b6bcf..97321bb9600e 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -1189,7 +1189,7 @@ struct rx_ring {
1189 u32 cq_size; 1189 u32 cq_size;
1190 u32 cq_len; 1190 u32 cq_len;
1191 u16 cq_id; 1191 u16 cq_id;
1192 u32 *prod_idx_sh_reg; /* Shadowed producer register. */ 1192 volatile __le32 *prod_idx_sh_reg; /* Shadowed producer register. */
1193 dma_addr_t prod_idx_sh_reg_dma; 1193 dma_addr_t prod_idx_sh_reg_dma;
1194 void __iomem *cnsmr_idx_db_reg; /* PCI doorbell mem area + 0 */ 1194 void __iomem *cnsmr_idx_db_reg; /* PCI doorbell mem area + 0 */
1195 u32 cnsmr_idx; /* current sw idx */ 1195 u32 cnsmr_idx; /* current sw idx */
@@ -1467,21 +1467,6 @@ static inline void ql_write_db_reg(u32 val, void __iomem *addr)
1467 mmiowb(); 1467 mmiowb();
1468} 1468}
1469 1469
1470/*
1471 * Shadow Registers:
1472 * Outbound queues have a consumer index that is maintained by the chip.
1473 * Inbound queues have a producer index that is maintained by the chip.
1474 * For lower overhead, these registers are "shadowed" to host memory
1475 * which allows the device driver to track the queue progress without
1476 * PCI reads. When an entry is placed on an inbound queue, the chip will
1477 * update the relevant index register and then copy the value to the
1478 * shadow register in host memory.
1479 */
1480static inline unsigned int ql_read_sh_reg(const volatile void *addr)
1481{
1482 return *(volatile unsigned int __force *)addr;
1483}
1484
1485extern char qlge_driver_name[]; 1470extern char qlge_driver_name[];
1486extern const char qlge_driver_version[]; 1471extern const char qlge_driver_version[];
1487extern const struct ethtool_ops qlge_ethtool_ops; 1472extern const struct ethtool_ops qlge_ethtool_ops;
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 9ceedfc4b56a..c0e43c552d1f 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -1559,7 +1559,7 @@ static void ql_process_chip_ae_intr(struct ql_adapter *qdev,
1559static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) 1559static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
1560{ 1560{
1561 struct ql_adapter *qdev = rx_ring->qdev; 1561 struct ql_adapter *qdev = rx_ring->qdev;
1562 u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); 1562 u32 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
1563 struct ob_mac_iocb_rsp *net_rsp = NULL; 1563 struct ob_mac_iocb_rsp *net_rsp = NULL;
1564 int count = 0; 1564 int count = 0;
1565 1565
@@ -1585,7 +1585,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring)
1585 } 1585 }
1586 count++; 1586 count++;
1587 ql_update_cq(rx_ring); 1587 ql_update_cq(rx_ring);
1588 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); 1588 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
1589 } 1589 }
1590 ql_write_cq_idx(rx_ring); 1590 ql_write_cq_idx(rx_ring);
1591 if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) { 1591 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)
1605static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget) 1605static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget)
1606{ 1606{
1607 struct ql_adapter *qdev = rx_ring->qdev; 1607 struct ql_adapter *qdev = rx_ring->qdev;
1608 u32 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); 1608 u32 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
1609 struct ql_net_rsp_iocb *net_rsp; 1609 struct ql_net_rsp_iocb *net_rsp;
1610 int count = 0; 1610 int count = 0;
1611 1611
@@ -1638,7 +1638,7 @@ static int ql_clean_inbound_rx_ring(struct rx_ring *rx_ring, int budget)
1638 } 1638 }
1639 count++; 1639 count++;
1640 ql_update_cq(rx_ring); 1640 ql_update_cq(rx_ring);
1641 prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); 1641 prod = le32_to_cpu(*rx_ring->prod_idx_sh_reg);
1642 if (count == budget) 1642 if (count == budget)
1643 break; 1643 break;
1644 } 1644 }
@@ -1801,7 +1801,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
1801 * Check the default queue and wake handler if active. 1801 * Check the default queue and wake handler if active.
1802 */ 1802 */
1803 rx_ring = &qdev->rx_ring[0]; 1803 rx_ring = &qdev->rx_ring[0];
1804 if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) { 1804 if (le32_to_cpu(*rx_ring->prod_idx_sh_reg) != rx_ring->cnsmr_idx) {
1805 QPRINTK(qdev, INTR, INFO, "Waking handler for rx_ring[0].\n"); 1805 QPRINTK(qdev, INTR, INFO, "Waking handler for rx_ring[0].\n");
1806 ql_disable_completion_interrupt(qdev, intr_context->intr); 1806 ql_disable_completion_interrupt(qdev, intr_context->intr);
1807 queue_delayed_work_on(smp_processor_id(), qdev->q_workqueue, 1807 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 */ 1815 */
1816 for (i = 1; i < qdev->rx_ring_count; i++) { 1816 for (i = 1; i < qdev->rx_ring_count; i++) {
1817 rx_ring = &qdev->rx_ring[i]; 1817 rx_ring = &qdev->rx_ring[i];
1818 if (ql_read_sh_reg(rx_ring->prod_idx_sh_reg) != 1818 if (le32_to_cpu(*rx_ring->prod_idx_sh_reg) !=
1819 rx_ring->cnsmr_idx) { 1819 rx_ring->cnsmr_idx) {
1820 QPRINTK(qdev, INTR, INFO, 1820 QPRINTK(qdev, INTR, INFO,
1821 "Waking handler for rx_ring[%d].\n", i); 1821 "Waking handler for rx_ring[%d].\n", i);