From 288379f050284087578b77e04f040b57db3db3f8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 19 Jan 2009 16:43:59 -0800 Subject: net: Remove redundant NAPI functions Following the removal of the unused struct net_device * parameter from the NAPI functions named *netif_rx_* in commit 908a7a1, they are exactly equivalent to the corresponding *napi_* functions and are therefore redundant. Signed-off-by: Ben Hutchings Acked-by: Neil Horman Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 45421c8b601..16eb9dd8528 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1642,7 +1642,7 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget) rx_ring->cq_id); if (work_done < budget) { - __netif_rx_complete(napi); + __napi_complete(napi); ql_enable_completion_interrupt(qdev, rx_ring->irq); } return work_done; @@ -1727,7 +1727,7 @@ static irqreturn_t qlge_msix_tx_isr(int irq, void *dev_id) static irqreturn_t qlge_msix_rx_isr(int irq, void *dev_id) { struct rx_ring *rx_ring = dev_id; - netif_rx_schedule(&rx_ring->napi); + napi_schedule(&rx_ring->napi); return IRQ_HANDLED; } @@ -1813,7 +1813,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) &rx_ring->rx_work, 0); else - netif_rx_schedule(&rx_ring->napi); + napi_schedule(&rx_ring->napi); work_done++; } } -- cgit v1.2.3 From 0c8dfc830aadd978e461dad66c33741b71c6a0be Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 27 Jan 2009 16:22:32 -0800 Subject: net: Add skb_record_rx_queue() calls to multiqueue capable drivers. Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 16eb9dd8528..4ab6e72ea95 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1436,6 +1436,7 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, qdev->stats.rx_packets++; qdev->stats.rx_bytes += skb->len; skb->protocol = eth_type_trans(skb, ndev); + skb_record_rx_queue(skb, rx_ring - &qdev->rx_ring[0]); if (qdev->vlgrp && (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V)) { QPRINTK(qdev, RX_STATUS, DEBUG, "Passing a VLAN packet upstream.\n"); -- cgit v1.2.3 From bb58b5b67c08b5fde08090917a040a07ac9d43de Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 23 Feb 2009 10:42:13 +0000 Subject: qlge: Clean up mac address and frame route settings. Setting MAC addresses and routing frames to various queues will need to be done in response to firmware events as well as during initialization. This change encapsulates the facilities into a single call that can later me made from other places. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index fd515afb1aa..3a041b6d9fe 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2958,6 +2958,24 @@ static int ql_route_initialize(struct ql_adapter *qdev) return status; } +static int ql_cam_route_initialize(struct ql_adapter *qdev) +{ + int status; + + status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr, + MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n"); + return status; + } + + status = ql_route_initialize(qdev); + if (status) + QPRINTK(qdev, IFUP, ERR, "Failed to init routing table.\n"); + + return status; +} + static int ql_adapter_initialize(struct ql_adapter *qdev) { u32 value, mask; @@ -3028,16 +3046,11 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) return status; } - status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr, - MAC_ADDR_TYPE_CAM_MAC, qdev->func); - if (status) { - QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n"); - return status; - } - - status = ql_route_initialize(qdev); + /* Set up the MAC address and frame routing filter. */ + status = ql_cam_route_initialize(qdev); if (status) { - QPRINTK(qdev, IFUP, ERR, "Failed to init routing table.\n"); + QPRINTK(qdev, IFUP, ERR, + "Failed to init CAM/Routing tables.\n"); return status; } -- cgit v1.2.3 From cc288f54bbace136c08742da84712add54e4acfa Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 23 Feb 2009 10:42:14 +0000 Subject: qlge: Increase MAC addr hw sem granularity. Instead of taking/giving the semaphore repeatedly when iterating over several adderesses, we have the caller hold it until all are done. This reduces PCI bus chatter and possible waits. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 51 +++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 3a041b6d9fe..d316e508d06 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -247,9 +247,6 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, u32 offset = 0; int status; - status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); - if (status) - return status; switch (type) { case MAC_ADDR_TYPE_MULTI_MAC: case MAC_ADDR_TYPE_CAM_MAC: @@ -308,7 +305,6 @@ int ql_get_mac_addr_reg(struct ql_adapter *qdev, u32 type, u16 index, status = -EPERM; } exit: - ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); return status; } @@ -321,9 +317,6 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, u32 offset = 0; int status = 0; - status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); - if (status) - return status; switch (type) { case MAC_ADDR_TYPE_MULTI_MAC: case MAC_ADDR_TYPE_CAM_MAC: @@ -415,7 +408,6 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, status = -EPERM; } exit: - ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); return status; } @@ -1690,19 +1682,29 @@ static void ql_vlan_rx_add_vid(struct net_device *ndev, u16 vid) { struct ql_adapter *qdev = netdev_priv(ndev); u32 enable_bit = MAC_ADDR_E; + int status; + status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); + if (status) + return; spin_lock(&qdev->hw_lock); if (ql_set_mac_addr_reg (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) { QPRINTK(qdev, IFUP, ERR, "Failed to init vlan address.\n"); } spin_unlock(&qdev->hw_lock); + ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); } static void ql_vlan_rx_kill_vid(struct net_device *ndev, u16 vid) { struct ql_adapter *qdev = netdev_priv(ndev); u32 enable_bit = 0; + int status; + + status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); + if (status) + return; spin_lock(&qdev->hw_lock); if (ql_set_mac_addr_reg @@ -1710,6 +1712,7 @@ static void ql_vlan_rx_kill_vid(struct net_device *ndev, u16 vid) QPRINTK(qdev, IFUP, ERR, "Failed to clear vlan address.\n"); } spin_unlock(&qdev->hw_lock); + ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); } @@ -2962,8 +2965,12 @@ static int ql_cam_route_initialize(struct ql_adapter *qdev) { int status; + status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); + if (status) + return status; status = ql_set_mac_addr_reg(qdev, (u8 *) qdev->ndev->perm_addr, MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); + ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); if (status) { QPRINTK(qdev, IFUP, ERR, "Failed to init mac address.\n"); return status; @@ -3428,8 +3435,11 @@ static void qlge_set_multicast_list(struct net_device *ndev) { struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); struct dev_mc_list *mc_ptr; - int i; + int i, status; + status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); + if (status) + return; spin_lock(&qdev->hw_lock); /* * Set or clear promiscuous mode if a @@ -3485,14 +3495,19 @@ static void qlge_set_multicast_list(struct net_device *ndev) } if (ndev->mc_count) { + status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); + if (status) + goto exit; for (i = 0, mc_ptr = ndev->mc_list; mc_ptr; i++, mc_ptr = mc_ptr->next) if (ql_set_mac_addr_reg(qdev, (u8 *) mc_ptr->dmi_addr, MAC_ADDR_TYPE_MULTI_MAC, i)) { QPRINTK(qdev, HW, ERR, "Failed to loadmulticast address.\n"); + ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); goto exit; } + ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); if (ql_set_routing_reg (qdev, RT_IDX_MCAST_MATCH_SLOT, RT_IDX_MCAST_MATCH, 1)) { QPRINTK(qdev, HW, ERR, @@ -3509,7 +3524,7 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p) { struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev); struct sockaddr *addr = p; - int ret = 0; + int status; if (netif_running(ndev)) return -EBUSY; @@ -3518,15 +3533,17 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p) return -EADDRNOTAVAIL; memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len); + status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); + if (status) + return status; spin_lock(&qdev->hw_lock); - if (ql_set_mac_addr_reg(qdev, (u8 *) ndev->dev_addr, - MAC_ADDR_TYPE_CAM_MAC, qdev->func)) {/* Unicast */ - QPRINTK(qdev, HW, ERR, "Failed to load MAC address.\n"); - ret = -1; - } + status = ql_set_mac_addr_reg(qdev, (u8 *) ndev->dev_addr, + MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); spin_unlock(&qdev->hw_lock); - - return ret; + if (status) + QPRINTK(qdev, HW, ERR, "Failed to load MAC address.\n"); + ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); + return status; } static void qlge_tx_timeout(struct net_device *ndev) -- cgit v1.2.3 From 8587ea35ca6b4add4353b8a18b67d358aed0389e Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 23 Feb 2009 10:42:15 +0000 Subject: qlge: Change frame route hw semaphore granularity. Instead of taking/giving the hw semaphore repeatedly when iterating over several frame to queue route settings, we have the caller hold it until all are done. This reduces PCI bus chatter and possible waits. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index d316e508d06..16c056a62fc 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -418,10 +418,6 @@ int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value) { int status = 0; - status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); - if (status) - goto exit; - status = ql_wait_reg_rdy(qdev, RT_IDX, RT_IDX_MW, 0); if (status) goto exit; @@ -433,7 +429,6 @@ int ql_get_routing_reg(struct ql_adapter *qdev, u32 index, u32 *value) goto exit; *value = ql_read32(qdev, RT_DATA); exit: - ql_sem_unlock(qdev, SEM_RT_IDX_MASK); return status; } @@ -445,13 +440,9 @@ exit: static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask, int enable) { - int status; + int status = -EINVAL; /* Return error if no mask match. */ u32 value = 0; - status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); - if (status) - return status; - QPRINTK(qdev, IFUP, DEBUG, "%s %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s mask %s the routing reg.\n", (enable ? "Adding" : "Removing"), @@ -547,7 +538,6 @@ static int ql_set_routing_reg(struct ql_adapter *qdev, u32 index, u32 mask, ql_write32(qdev, RT_DATA, enable ? mask : 0); } exit: - ql_sem_unlock(qdev, SEM_RT_IDX_MASK); return status; } @@ -2916,13 +2906,17 @@ static int ql_route_initialize(struct ql_adapter *qdev) int status = 0; int i; + status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); + if (status) + return status; + /* Clear all the entries in the routing table. */ for (i = 0; i < 16; i++) { status = ql_set_routing_reg(qdev, i, 0, 0); if (status) { QPRINTK(qdev, IFUP, ERR, "Failed to init routing register for CAM packets.\n"); - return status; + goto exit; } } @@ -2930,13 +2924,13 @@ static int ql_route_initialize(struct ql_adapter *qdev) if (status) { QPRINTK(qdev, IFUP, ERR, "Failed to init routing register for error packets.\n"); - return status; + goto exit; } status = ql_set_routing_reg(qdev, RT_IDX_BCAST_SLOT, RT_IDX_BCAST, 1); if (status) { QPRINTK(qdev, IFUP, ERR, "Failed to init routing register for broadcast packets.\n"); - return status; + goto exit; } /* If we have more than one inbound queue, then turn on RSS in the * routing block. @@ -2947,17 +2941,17 @@ static int ql_route_initialize(struct ql_adapter *qdev) if (status) { QPRINTK(qdev, IFUP, ERR, "Failed to init routing register for MATCH RSS packets.\n"); - return status; + goto exit; } } status = ql_set_routing_reg(qdev, RT_IDX_CAM_HIT_SLOT, RT_IDX_CAM_HIT, 1); - if (status) { + if (status) QPRINTK(qdev, IFUP, ERR, "Failed to init routing register for CAM packets.\n"); - return status; - } +exit: + ql_sem_unlock(qdev, SEM_RT_IDX_MASK); return status; } @@ -3518,6 +3512,7 @@ static void qlge_set_multicast_list(struct net_device *ndev) } exit: spin_unlock(&qdev->hw_lock); + ql_sem_unlock(qdev, SEM_RT_IDX_MASK); } static int qlge_set_mac_address(struct net_device *ndev, void *p) -- cgit v1.2.3 From 49f2186d36a88ae6f7dd8261aff2cf80409af28d Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 23 Feb 2009 10:42:16 +0000 Subject: qlge: Optimize rx buffer refill process. RX Buffers are refilled in chunks of 16 at a time before notifying the hardware with a register write. This can cause several writes to take place in a given napi poll call. This change causes the write to take place only once at the end of the call. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 16c056a62fc..17198459918 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -863,7 +863,8 @@ static void ql_write_cq_idx(struct rx_ring *rx_ring) /* Process (refill) a large buffer queue. */ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) { - int clean_idx = rx_ring->lbq_clean_idx; + u32 clean_idx = rx_ring->lbq_clean_idx; + u32 start_idx = clean_idx; struct bq_desc *lbq_desc; u64 map; int i; @@ -910,19 +911,23 @@ static void ql_update_lbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) rx_ring->lbq_prod_idx += 16; if (rx_ring->lbq_prod_idx == rx_ring->lbq_len) rx_ring->lbq_prod_idx = 0; + rx_ring->lbq_free_cnt -= 16; + } + + if (start_idx != clean_idx) { QPRINTK(qdev, RX_STATUS, DEBUG, "lbq: updating prod idx = %d.\n", rx_ring->lbq_prod_idx); ql_write_db_reg(rx_ring->lbq_prod_idx, rx_ring->lbq_prod_idx_db_reg); - rx_ring->lbq_free_cnt -= 16; } } /* Process (refill) a small buffer queue. */ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) { - int clean_idx = rx_ring->sbq_clean_idx; + u32 clean_idx = rx_ring->sbq_clean_idx; + u32 start_idx = clean_idx; struct bq_desc *sbq_desc; u64 map; int i; @@ -972,13 +977,15 @@ static void ql_update_sbq(struct ql_adapter *qdev, struct rx_ring *rx_ring) rx_ring->sbq_prod_idx += 16; if (rx_ring->sbq_prod_idx == rx_ring->sbq_len) rx_ring->sbq_prod_idx = 0; + rx_ring->sbq_free_cnt -= 16; + } + + if (start_idx != clean_idx) { QPRINTK(qdev, RX_STATUS, DEBUG, "sbq: updating prod idx = %d.\n", rx_ring->sbq_prod_idx); ql_write_db_reg(rx_ring->sbq_prod_idx, rx_ring->sbq_prod_idx_db_reg); - - rx_ring->sbq_free_cnt -= 16; } } -- cgit v1.2.3 From 4545a3f2765bb7d2d93468a8ffa578ac87a2c5c7 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 23 Feb 2009 10:42:17 +0000 Subject: 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: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 170 +++++++++++++++---------------------------- 1 file changed, 59 insertions(+), 111 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 17198459918..655f3c4322e 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -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)) { -- cgit v1.2.3 From 125844eaff0e9600c92a753995564fd93c807f3c Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Thu, 26 Feb 2009 10:08:34 +0000 Subject: qlge: Move firmware event handler. This is not a logical change but rather a move of the inbound firmware event handler into it's own function as it will later be called by the outbound path. The addition of the mutex is to create exclusive access to the mailbox commands between inbound and outbound handling. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 655f3c4322e..b144b6becfe 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3659,6 +3659,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, INIT_DELAYED_WORK(&qdev->asic_reset_work, ql_asic_reset_work); INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work); INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work); + mutex_init(&qdev->mpi_mutex); if (!cards_found) { dev_info(&pdev->dev, "%s\n", DRV_STRING); -- cgit v1.2.3 From b0c2aadfa4d2194615ba8f5630be7ae686b9ed01 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Thu, 26 Feb 2009 10:08:35 +0000 Subject: qlge: Prepare to add new device. This organizes a few calls into a function table to enable adding new devices. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 80 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 16 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index b144b6becfe..d1d8f05d5a1 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -75,7 +75,7 @@ module_param(irq_type, int, MSIX_IRQ); MODULE_PARM_DESC(irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); static struct pci_device_id qlge_pci_tbl[] __devinitdata = { - {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID)}, + {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)}, /* required last entry */ {0,} }; @@ -623,6 +623,28 @@ static void ql_enable_all_completion_interrupts(struct ql_adapter *qdev) } +static int ql_validate_flash(struct ql_adapter *qdev, u32 size, const char *str) +{ + int status, i; + u16 csum = 0; + __le16 *flash = (__le16 *)&qdev->flash; + + status = strncmp((char *)&qdev->flash, str, 4); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Invalid flash signature.\n"); + return status; + } + + for (i = 0; i < size; i++) + csum += le16_to_cpu(*flash++); + + if (csum) + QPRINTK(qdev, IFUP, ERR, + "Invalid flash checksum, csum = 0x%.04x.\n", csum); + + return csum; +} + static int ql_read_flash_word(struct ql_adapter *qdev, int offset, __le32 *data) { int status = 0; @@ -647,23 +669,24 @@ exit: return status; } -static int ql_get_flash_params(struct ql_adapter *qdev) +static int ql_get_8012_flash_params(struct ql_adapter *qdev) { int i; int status; __le32 *p = (__le32 *)&qdev->flash; u32 offset = 0; + u32 size = sizeof(struct flash_params_8012) / sizeof(u32); /* Second function's parameters follow the first * function's. */ if (qdev->func) - offset = sizeof(qdev->flash) / sizeof(u32); + offset = size; if (ql_sem_spinlock(qdev, SEM_FLASH_MASK)) return -ETIMEDOUT; - for (i = 0; i < sizeof(qdev->flash) / sizeof(u32); i++, p++) { + for (i = 0; i < size; i++, p++) { status = ql_read_flash_word(qdev, i+offset, p); if (status) { QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n"); @@ -671,6 +694,25 @@ static int ql_get_flash_params(struct ql_adapter *qdev) } } + + status = ql_validate_flash(qdev, + sizeof(struct flash_params_8012) / sizeof(u16), + "8012"); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Invalid flash.\n"); + status = -EINVAL; + goto exit; + } + + if (!is_valid_ether_addr(qdev->flash.flash_params_8012.mac_addr)) { + status = -EINVAL; + goto exit; + } + + memcpy(qdev->ndev->dev_addr, + qdev->flash.flash_params_8012.mac_addr, + qdev->ndev->addr_len); + exit: ql_sem_unlock(qdev, SEM_FLASH_MASK); return status; @@ -747,7 +789,7 @@ exit: * This functionality may be done in the MPI firmware at a * later date. */ -static int ql_port_initialize(struct ql_adapter *qdev) +static int ql_8012_port_initialize(struct ql_adapter *qdev) { int status = 0; u32 data; @@ -2994,11 +3036,12 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) } } - status = ql_port_initialize(qdev); - if (status) { - QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n"); - return status; - } + /* Initialize the port and set the max framesize. */ + status = qdev->nic_ops->port_initialize(qdev); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Failed to start port.\n"); + return status; + } /* Set up the MAC address and frame routing filter. */ status = ql_cam_route_initialize(qdev); @@ -3509,6 +3552,12 @@ static void ql_asic_reset_work(struct work_struct *work) ql_cycle_adapter(qdev); } +static struct nic_operations qla8012_nic_ops = { + .get_flash = ql_get_8012_flash_params, + .port_initialize = ql_8012_port_initialize, +}; + + static void ql_get_board_info(struct ql_adapter *qdev) { qdev->func = @@ -3527,6 +3576,9 @@ static void ql_get_board_info(struct ql_adapter *qdev) qdev->mailbox_out = PROC_ADDR_MPI_RISC | PROC_ADDR_FUNC0_MBO; } qdev->chip_rev_id = ql_read32(qdev, REV_ID); + qdev->device_id = qdev->pdev->device; + if (qdev->device_id == QLGE_DEVICE_ID_8012) + qdev->nic_ops = &qla8012_nic_ops; } static void ql_release_all(struct pci_dev *pdev) @@ -3619,24 +3671,20 @@ static int __devinit ql_init_device(struct pci_dev *pdev, goto err_out; } - ql_get_board_info(qdev); qdev->ndev = ndev; qdev->pdev = pdev; + ql_get_board_info(qdev); qdev->msg_enable = netif_msg_init(debug, default_msg); spin_lock_init(&qdev->hw_lock); spin_lock_init(&qdev->stats_lock); /* make sure the EEPROM is good */ - err = ql_get_flash_params(qdev); + err = qdev->nic_ops->get_flash(qdev); if (err) { dev_err(&pdev->dev, "Invalid FLASH.\n"); goto err_out; } - if (!is_valid_ether_addr(qdev->flash.mac_addr)) - goto err_out; - - memcpy(ndev->dev_addr, qdev->flash.mac_addr, ndev->addr_len); memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); /* Set up the default ring sizes. */ -- cgit v1.2.3 From 4974097a97c6c11c22c2242f70821e2af65ef8e7 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Thu, 26 Feb 2009 10:08:36 +0000 Subject: qlge: Reduce debug print output. Get rid of some noise that is for debug only. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index d1d8f05d5a1..b4c6fd7a761 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -58,8 +58,8 @@ static const u32 default_msg = NETIF_MSG_IFUP | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR | - NETIF_MSG_TX_QUEUED | - NETIF_MSG_INTR | NETIF_MSG_TX_DONE | NETIF_MSG_RX_STATUS | +/* NETIF_MSG_TX_QUEUED | */ +/* NETIF_MSG_INTR | NETIF_MSG_TX_DONE | NETIF_MSG_RX_STATUS | */ /* NETIF_MSG_PKTDATA | */ NETIF_MSG_HW | NETIF_MSG_WOL | 0; @@ -327,7 +327,7 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type, (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | (addr[5]); - QPRINTK(qdev, IFUP, INFO, + QPRINTK(qdev, IFUP, DEBUG, "Adding %s address %pM" " at index %d in the CAM.\n", ((type == @@ -2552,7 +2552,7 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) QPRINTK(qdev, IFUP, DEBUG, "Invalid rx_ring->type = %d.\n", rx_ring->type); } - QPRINTK(qdev, IFUP, INFO, "Initializing rx work queue.\n"); + QPRINTK(qdev, IFUP, DEBUG, "Initializing rx work queue.\n"); err = ql_write_cfg(qdev, cqicb, sizeof(struct cqicb), CFG_LCQ, rx_ring->cq_id); if (err) { @@ -2605,7 +2605,7 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring) QPRINTK(qdev, IFUP, ERR, "Failed to load tx_ring.\n"); return err; } - QPRINTK(qdev, IFUP, INFO, "Successfully loaded WQICB.\n"); + QPRINTK(qdev, IFUP, DEBUG, "Successfully loaded WQICB.\n"); return err; } @@ -2647,7 +2647,7 @@ static void ql_enable_msix(struct ql_adapter *qdev) (qdev->pdev, qdev->msi_x_entry, qdev->rx_ring_count)) { set_bit(QL_MSIX_ENABLED, &qdev->flags); qdev->intr_count = qdev->rx_ring_count; - QPRINTK(qdev, IFUP, INFO, + QPRINTK(qdev, IFUP, DEBUG, "MSI-X Enabled, got %d vectors.\n", qdev->intr_count); return; @@ -2774,11 +2774,11 @@ static void ql_free_irq(struct ql_adapter *qdev) if (test_bit(QL_MSIX_ENABLED, &qdev->flags)) { free_irq(qdev->msi_x_entry[i].vector, &qdev->rx_ring[i]); - QPRINTK(qdev, IFDOWN, ERR, + QPRINTK(qdev, IFDOWN, DEBUG, "freeing msix interrupt %d.\n", i); } else { free_irq(qdev->pdev->irq, &qdev->rx_ring[0]); - QPRINTK(qdev, IFDOWN, ERR, + QPRINTK(qdev, IFDOWN, DEBUG, "freeing msi interrupt %d.\n", i); } } @@ -2809,7 +2809,7 @@ static int ql_request_irq(struct ql_adapter *qdev) i); goto err_irq; } else { - QPRINTK(qdev, IFUP, INFO, + QPRINTK(qdev, IFUP, DEBUG, "Hooked intr %d, queue type %s%s%s, with name %s.\n", i, qdev->rx_ring[i].type == @@ -2884,14 +2884,14 @@ static int ql_start_rss(struct ql_adapter *qdev) get_random_bytes((void *)&ricb->ipv6_hash_key[0], 40); get_random_bytes((void *)&ricb->ipv4_hash_key[0], 16); - QPRINTK(qdev, IFUP, INFO, "Initializing RSS.\n"); + QPRINTK(qdev, IFUP, DEBUG, "Initializing RSS.\n"); status = ql_write_cfg(qdev, ricb, sizeof(ricb), CFG_LR, 0); if (status) { QPRINTK(qdev, IFUP, ERR, "Failed to load RICB.\n"); return status; } - QPRINTK(qdev, IFUP, INFO, "Successfully loaded RICB.\n"); + QPRINTK(qdev, IFUP, DEBUG, "Successfully loaded RICB.\n"); return status; } @@ -3053,7 +3053,7 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) /* Start NAPI for the RSS queues. */ for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) { - QPRINTK(qdev, IFUP, INFO, "Enabling NAPI for rx_ring[%d].\n", + QPRINTK(qdev, IFUP, DEBUG, "Enabling NAPI for rx_ring[%d].\n", i); napi_enable(&qdev->rx_ring[i].napi); } -- cgit v1.2.3 From cdca8d02ea4229c2ccf3c27fb537b150843f67c9 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 2 Mar 2009 08:07:31 +0000 Subject: qlge: Add support for device ID 8000. This device has more firmware support for link management, setting TX and RX maximum frame sizes. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index b4c6fd7a761..29334d99b43 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -76,6 +76,7 @@ MODULE_PARM_DESC(irq_type, "0 = MSI-X, 1 = MSI, 2 = Legacy."); static struct pci_device_id qlge_pci_tbl[] __devinitdata = { {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8012)}, + {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, QLGE_DEVICE_ID_8000)}, /* required last entry */ {0,} }; @@ -669,6 +670,57 @@ exit: return status; } +static int ql_get_8000_flash_params(struct ql_adapter *qdev) +{ + u32 i, size; + int status; + __le32 *p = (__le32 *)&qdev->flash; + u32 offset; + + /* Get flash offset for function and adjust + * for dword access. + */ + if (!qdev->func) + offset = FUNC0_FLASH_OFFSET / sizeof(u32); + else + offset = FUNC1_FLASH_OFFSET / sizeof(u32); + + if (ql_sem_spinlock(qdev, SEM_FLASH_MASK)) + return -ETIMEDOUT; + + size = sizeof(struct flash_params_8000) / sizeof(u32); + for (i = 0; i < size; i++, p++) { + status = ql_read_flash_word(qdev, i+offset, p); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Error reading flash.\n"); + goto exit; + } + } + + status = ql_validate_flash(qdev, + sizeof(struct flash_params_8000) / sizeof(u16), + "8000"); + if (status) { + QPRINTK(qdev, IFUP, ERR, "Invalid flash.\n"); + status = -EINVAL; + goto exit; + } + + if (!is_valid_ether_addr(qdev->flash.flash_params_8000.mac_addr)) { + QPRINTK(qdev, IFUP, ERR, "Invalid MAC address.\n"); + status = -EINVAL; + goto exit; + } + + memcpy(qdev->ndev->dev_addr, + qdev->flash.flash_params_8000.mac_addr, + qdev->ndev->addr_len); + +exit: + ql_sem_unlock(qdev, SEM_FLASH_MASK); + return status; +} + static int ql_get_8012_flash_params(struct ql_adapter *qdev) { int i; @@ -783,6 +835,11 @@ exit: return status; } +static int ql_8000_port_initialize(struct ql_adapter *qdev) +{ + return ql_mb_get_fw_state(qdev); +} + /* Take the MAC Core out of reset. * Enable statistics counting. * Take the transmitter/receiver out of reset. @@ -3557,6 +3614,11 @@ static struct nic_operations qla8012_nic_ops = { .port_initialize = ql_8012_port_initialize, }; +static struct nic_operations qla8000_nic_ops = { + .get_flash = ql_get_8000_flash_params, + .port_initialize = ql_8000_port_initialize, +}; + static void ql_get_board_info(struct ql_adapter *qdev) { @@ -3579,6 +3641,8 @@ static void ql_get_board_info(struct ql_adapter *qdev) qdev->device_id = qdev->pdev->device; if (qdev->device_id == QLGE_DEVICE_ID_8012) qdev->nic_ops = &qla8012_nic_ops; + else if (qdev->device_id == QLGE_DEVICE_ID_8000) + qdev->nic_ops = &qla8000_nic_ops; } static void ql_release_all(struct pci_dev *pdev) -- cgit v1.2.3 From bcc2cb3b97e37317c301309d7052bb61e6cce2c4 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 2 Mar 2009 08:07:32 +0000 Subject: qlge: Add support for getting/setting port config. This patch adds functionality to get and set port parameters. Currently it is used to set maximum TX/RX frame sizes. This process is also capable of setting: 1) Pause type: Standard or Priority based. 2) Loop back mode. 3) Enable Jumbo frame mode (included here...) Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 29334d99b43..7c1ce576575 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -837,7 +837,14 @@ exit: static int ql_8000_port_initialize(struct ql_adapter *qdev) { - return ql_mb_get_fw_state(qdev); + int status; + status = ql_mb_get_fw_state(qdev); + if (status) + goto exit; + /* Wake up a worker to get/set the TX/RX frame sizes. */ + queue_delayed_work(qdev->workqueue, &qdev->mpi_port_cfg_work, 0); +exit: + return status; } /* Take the MAC Core out of reset. @@ -3188,6 +3195,7 @@ static int ql_adapter_down(struct ql_adapter *qdev) cancel_delayed_work_sync(&qdev->asic_reset_work); cancel_delayed_work_sync(&qdev->mpi_reset_work); cancel_delayed_work_sync(&qdev->mpi_work); + cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); /* The default queue at index 0 is always processed in * a workqueue. @@ -3462,6 +3470,8 @@ static int qlge_change_mtu(struct net_device *ndev, int new_mtu) if (ndev->mtu == 1500 && new_mtu == 9000) { QPRINTK(qdev, IFUP, ERR, "Changing to jumbo MTU.\n"); + queue_delayed_work(qdev->workqueue, + &qdev->mpi_port_cfg_work, 0); } else if (ndev->mtu == 9000 && new_mtu == 1500) { QPRINTK(qdev, IFUP, ERR, "Changing to normal MTU.\n"); } else if ((ndev->mtu == 1500 && new_mtu == 1500) || @@ -3771,7 +3781,9 @@ static int __devinit ql_init_device(struct pci_dev *pdev, INIT_DELAYED_WORK(&qdev->asic_reset_work, ql_asic_reset_work); INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work); INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work); + INIT_DELAYED_WORK(&qdev->mpi_port_cfg_work, ql_mpi_port_cfg_work); mutex_init(&qdev->mpi_mutex); + init_completion(&qdev->ide_completion); if (!cards_found) { dev_info(&pdev->dev, "%s\n", DRV_STRING); -- cgit v1.2.3 From 2ee1e272d1661d7846da753248a4141ad5f16d69 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Tue, 3 Mar 2009 12:10:33 +0000 Subject: qlge: Add worker-handler for firmware events. This worker and it's supporting routines are used for IDC 'inter-device-communication' events that require an ACK mailbox command be sent to allow completion of the request. These requests are originated by another function wanting to change some common port paramters. Typical example would be: 1) Change max TX/RX frame size allowed. 2) Change pause parameters. 3) Change loopback mode. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 7c1ce576575..d800ff40b32 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3014,7 +3014,7 @@ exit: return status; } -static int ql_cam_route_initialize(struct ql_adapter *qdev) +int ql_cam_route_initialize(struct ql_adapter *qdev) { int status; @@ -3195,6 +3195,7 @@ static int ql_adapter_down(struct ql_adapter *qdev) cancel_delayed_work_sync(&qdev->asic_reset_work); cancel_delayed_work_sync(&qdev->mpi_reset_work); cancel_delayed_work_sync(&qdev->mpi_work); + cancel_delayed_work_sync(&qdev->mpi_idc_work); cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); /* The default queue at index 0 is always processed in @@ -3782,6 +3783,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, INIT_DELAYED_WORK(&qdev->mpi_reset_work, ql_mpi_reset_work); INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work); INIT_DELAYED_WORK(&qdev->mpi_port_cfg_work, ql_mpi_port_cfg_work); + INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work); mutex_init(&qdev->mpi_mutex); init_completion(&qdev->ide_completion); -- cgit v1.2.3 From db98812f6bbe17c5994d6290a68f8de8aa5ff8b9 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:17 +0000 Subject: qlge: Move reset logic into asic_reset_worker func. Get rid of extraneous ql_cycle_adapter. It's only called from the one place. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index d800ff40b32..ed7138d07ba 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3263,28 +3263,6 @@ err_init: return err; } -static int ql_cycle_adapter(struct ql_adapter *qdev) -{ - int status; - - status = ql_adapter_down(qdev); - if (status) - goto error; - - status = ql_adapter_up(qdev); - if (status) - goto error; - - return status; -error: - QPRINTK(qdev, IFUP, ALERT, - "Driver up/down cycle failed, closing device\n"); - rtnl_lock(); - dev_close(qdev->ndev); - rtnl_unlock(); - return status; -} - static void ql_release_adapter_resources(struct ql_adapter *qdev) { ql_free_mem_resources(qdev); @@ -3617,7 +3595,24 @@ static void ql_asic_reset_work(struct work_struct *work) { struct ql_adapter *qdev = container_of(work, struct ql_adapter, asic_reset_work.work); - ql_cycle_adapter(qdev); + int status; + + status = ql_adapter_down(qdev); + if (status) + goto error; + + status = ql_adapter_up(qdev); + if (status) + goto error; + + return; +error: + QPRINTK(qdev, IFUP, ALERT, + "Driver up/down cycle failed, closing device\n"); + rtnl_lock(); + set_bit(QL_ADAPTER_UP, &qdev->flags); + dev_close(qdev->ndev); + rtnl_unlock(); } static struct nic_operations qla8012_nic_ops = { -- cgit v1.2.3 From a75ee7f1ccace560642e5dc6b1c0e22c73da5a8c Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:18 +0000 Subject: qlge: Remove debug junk from asic reset logic. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index ed7138d07ba..bc04aebc928 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3129,36 +3129,23 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) static int ql_adapter_reset(struct ql_adapter *qdev) { u32 value; - int max_wait_time; int status = 0; - int resetCnt = 0; + unsigned long end_jiffies = jiffies + + max((unsigned long)1, usecs_to_jiffies(30)); -#define MAX_RESET_CNT 1 -issueReset: - resetCnt++; - QPRINTK(qdev, IFDOWN, DEBUG, "Issue soft reset to chip.\n"); ql_write32(qdev, RST_FO, (RST_FO_FR << 16) | RST_FO_FR); - /* Wait for reset to complete. */ - max_wait_time = 3; - QPRINTK(qdev, IFDOWN, DEBUG, "Wait %d seconds for reset to complete.\n", - max_wait_time); + do { value = ql_read32(qdev, RST_FO); if ((value & RST_FO_FR) == 0) break; + cpu_relax(); + } while (time_before(jiffies, end_jiffies)); - ssleep(1); - } while ((--max_wait_time)); if (value & RST_FO_FR) { - QPRINTK(qdev, IFDOWN, ERR, - "Stuck in SoftReset: FSC_SR:0x%08x\n", value); - if (resetCnt < MAX_RESET_CNT) - goto issueReset; - } - if (max_wait_time == 0) { - status = -ETIMEDOUT; QPRINTK(qdev, IFDOWN, ERR, "ETIMEOUT!!! errored out of resetting the chip!\n"); + status = -ETIMEDOUT; } return status; -- cgit v1.2.3 From d555f5921f2b0d9f65b547dd0be67c870ff5a56f Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:19 +0000 Subject: qlge: Increase filtering for inbound csum settings. Chip does not do UDP checksum when fragmentation occurs. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index bc04aebc928..498d4bf5211 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1531,22 +1531,37 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) { QPRINTK(qdev, RX_STATUS, DEBUG, "Promiscuous Packet.\n"); } - if (ib_mac_rsp->flags1 & (IB_MAC_IOCB_RSP_IE | IB_MAC_IOCB_RSP_TE)) { - QPRINTK(qdev, RX_STATUS, ERR, - "Bad checksum for this %s packet.\n", - ((ib_mac_rsp-> - flags2 & IB_MAC_IOCB_RSP_T) ? "TCP" : "UDP")); - skb->ip_summed = CHECKSUM_NONE; - } else if (qdev->rx_csum && - ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) || - ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && - !(ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_NU)))) { - QPRINTK(qdev, RX_STATUS, DEBUG, "RX checksum done!\n"); - skb->ip_summed = CHECKSUM_UNNECESSARY; + + + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_NONE; + + /* If rx checksum is on, and there are no + * csum or frame errors. + */ + if (qdev->rx_csum && + !(ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) && + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { + /* TCP frame. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && + (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { + /* Unfragmented ipv4 UDP frame. */ + struct iphdr *iph = (struct iphdr *) skb->data; + if (!(iph->frag_off & + cpu_to_be16(IP_MF|IP_OFFSET))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + } + } } + qdev->stats.rx_packets++; qdev->stats.rx_bytes += skb->len; - skb->protocol = eth_type_trans(skb, ndev); skb_record_rx_queue(skb, rx_ring - &qdev->rx_ring[0]); if (qdev->vlgrp && (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V)) { QPRINTK(qdev, RX_STATUS, DEBUG, -- cgit v1.2.3 From 22bdd4f599b87734b7fc8137f47e62c13ab27e93 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:20 +0000 Subject: qlge: Add support for GRO. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 498d4bf5211..339e1da77e6 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1507,6 +1507,8 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, { struct net_device *ndev = qdev->ndev; struct sk_buff *skb = NULL; + u16 vlan_id = (le16_to_cpu(ib_mac_rsp->vlan_id) & + IB_MAC_IOCB_RSP_VLAN_MASK) QL_DUMP_IB_MAC_RSP(ib_mac_rsp); @@ -1562,16 +1564,23 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, qdev->stats.rx_packets++; qdev->stats.rx_bytes += skb->len; - skb_record_rx_queue(skb, rx_ring - &qdev->rx_ring[0]); - if (qdev->vlgrp && (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V)) { - QPRINTK(qdev, RX_STATUS, DEBUG, - "Passing a VLAN packet upstream.\n"); - vlan_hwaccel_receive_skb(skb, qdev->vlgrp, - le16_to_cpu(ib_mac_rsp->vlan_id)); + skb_record_rx_queue(skb, + rx_ring->cq_id - qdev->rss_ring_first_cq_id); + if (skb->ip_summed == CHECKSUM_UNNECESSARY) { + if (qdev->vlgrp && + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) && + (vlan_id != 0)) + vlan_gro_receive(&rx_ring->napi, qdev->vlgrp, + vlan_id, skb); + else + napi_gro_receive(&rx_ring->napi, skb); } else { - QPRINTK(qdev, RX_STATUS, DEBUG, - "Passing a normal packet upstream.\n"); - netif_receive_skb(skb); + if (qdev->vlgrp && + (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_V) && + (vlan_id != 0)) + vlan_hwaccel_receive_skb(skb, qdev->vlgrp, vlan_id); + else + netif_receive_skb(skb); } } @@ -1774,7 +1783,7 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget) rx_ring->cq_id); if (work_done < budget) { - __napi_complete(napi); + napi_complete(napi); ql_enable_completion_interrupt(qdev, rx_ring->irq); } return work_done; @@ -3840,6 +3849,7 @@ static int __devinit qlge_probe(struct pci_dev *pdev, | NETIF_F_TSO_ECN | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER); + ndev->features |= NETIF_F_GRO; if (test_bit(QL_DMA64, &qdev->flags)) ndev->features |= NETIF_F_HIGHDMA; -- cgit v1.2.3 From 1e213303d8ef2a5d43fb64d2b373858ef70cc79b Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:21 +0000 Subject: qlge: Add tx multiqueue support. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 339e1da77e6..6da8901b0cc 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1627,14 +1627,12 @@ static void ql_process_mac_tx_intr(struct ql_adapter *qdev, /* Fire up a handler to reset the MPI processor. */ void ql_queue_fw_error(struct ql_adapter *qdev) { - netif_stop_queue(qdev->ndev); netif_carrier_off(qdev->ndev); queue_delayed_work(qdev->workqueue, &qdev->mpi_reset_work, 0); } void ql_queue_asic_error(struct ql_adapter *qdev) { - netif_stop_queue(qdev->ndev); netif_carrier_off(qdev->ndev); ql_disable_interrupts(qdev); /* Clear adapter up bit to signal the recovery @@ -1689,6 +1687,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) struct ob_mac_iocb_rsp *net_rsp = NULL; int count = 0; + struct tx_ring *tx_ring; /* While there are entries in the completion queue. */ while (prod != rx_ring->cnsmr_idx) { @@ -1714,15 +1713,16 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) prod = ql_read_sh_reg(rx_ring->prod_idx_sh_reg); } ql_write_cq_idx(rx_ring); - if (netif_queue_stopped(qdev->ndev) && net_rsp != NULL) { - struct tx_ring *tx_ring = &qdev->tx_ring[net_rsp->txq_idx]; + tx_ring = &qdev->tx_ring[net_rsp->txq_idx]; + if (__netif_subqueue_stopped(qdev->ndev, tx_ring->wq_id) && + net_rsp != NULL) { if (atomic_read(&tx_ring->queue_stopped) && (atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4))) /* * The queue got stopped because the tx_ring was full. * Wake it up, because it's now at least 25% empty. */ - netif_wake_queue(qdev->ndev); + netif_wake_subqueue(qdev->ndev, tx_ring->wq_id); } return count; @@ -2054,7 +2054,7 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) struct ql_adapter *qdev = netdev_priv(ndev); int tso; struct tx_ring *tx_ring; - u32 tx_ring_idx = (u32) QL_TXQ_IDX(qdev, skb); + u32 tx_ring_idx = (u32) skb->queue_mapping; tx_ring = &qdev->tx_ring[tx_ring_idx]; @@ -2062,7 +2062,7 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) QPRINTK(qdev, TX_QUEUED, INFO, "%s: shutting down tx queue %d du to lack of resources.\n", __func__, tx_ring_idx); - netif_stop_queue(ndev); + netif_stop_subqueue(ndev, tx_ring->wq_id); atomic_inc(&tx_ring->queue_stopped); return NETDEV_TX_BUSY; } @@ -3192,12 +3192,10 @@ static void ql_display_dev_info(struct net_device *ndev) static int ql_adapter_down(struct ql_adapter *qdev) { - struct net_device *ndev = qdev->ndev; int i, status = 0; struct rx_ring *rx_ring; - netif_stop_queue(ndev); - netif_carrier_off(ndev); + netif_carrier_off(qdev->ndev); /* Don't kill the reset worker thread if we * are in the process of recovery. @@ -3261,12 +3259,11 @@ 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); + if ((ql_read32(qdev, STS) & qdev->port_init)) + netif_carrier_on(qdev->ndev); ql_enable_interrupts(qdev); ql_enable_all_completion_interrupts(qdev); - if ((ql_read32(qdev, STS) & qdev->port_init)) { - netif_carrier_on(qdev->ndev); - netif_start_queue(qdev->ndev); - } + netif_tx_start_all_queues(qdev->ndev); return 0; err_init: @@ -3354,6 +3351,7 @@ static int ql_configure_rings(struct ql_adapter *qdev) * completion handler rx_rings. */ qdev->rx_ring_count = qdev->tx_ring_count + qdev->rss_ring_count + 1; + netif_set_gso_max_size(qdev->ndev, 65536); for (i = 0; i < qdev->tx_ring_count; i++) { tx_ring = &qdev->tx_ring[i]; @@ -3829,7 +3827,8 @@ static int __devinit qlge_probe(struct pci_dev *pdev, static int cards_found = 0; int err = 0; - ndev = alloc_etherdev(sizeof(struct ql_adapter)); + ndev = alloc_etherdev_mq(sizeof(struct ql_adapter), + min(MAX_CPUS, (int)num_online_cpus())); if (!ndev) return -ENOMEM; @@ -3872,7 +3871,6 @@ static int __devinit qlge_probe(struct pci_dev *pdev, return err; } netif_carrier_off(ndev); - netif_stop_queue(ndev); ql_display_dev_info(ndev); cards_found++; return 0; @@ -3926,7 +3924,6 @@ static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev) pci_set_master(pdev); netif_carrier_off(ndev); - netif_stop_queue(ndev); ql_adapter_reset(qdev); /* Make sure the EEPROM is good */ -- cgit v1.2.3 From c9cf0a04a0c20c26388c51052296d774ec92e2bd Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:22 +0000 Subject: qlge: bugfix: Tell hw to strip vlan header. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 6da8901b0cc..8b6128e7f5c 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3073,9 +3073,9 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) mask = value << 16; ql_write32(qdev, SYS, mask | value); - /* Set the default queue. */ - value = NIC_RCV_CFG_DFQ; - mask = NIC_RCV_CFG_DFQ_MASK; + /* Set the default queue, and VLAN behavior. */ + value = NIC_RCV_CFG_DFQ | NIC_RCV_CFG_RV; + mask = NIC_RCV_CFG_DFQ_MASK | (NIC_RCV_CFG_RV << 16); ql_write32(qdev, NIC_RCV_CFG, (mask | value)); /* Set the MPI interrupt to enabled. */ -- cgit v1.2.3 From 08b1bc8f4aba4ddbc4ccef7ebc899e6faae81bbf Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:23 +0000 Subject: qlge: Get rid of irqsave/restore in intr disable. The completion interrupt disable routine is only called from the ISR, so there is no need for irqsave/restore. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 8b6128e7f5c..45ad4cc298b 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -587,7 +587,6 @@ u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr) static u32 ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr) { u32 var = 0; - unsigned long hw_flags; struct intr_context *ctx; /* HW disables for us if we're MSIX multi interrupts and @@ -597,14 +596,14 @@ static u32 ql_disable_completion_interrupt(struct ql_adapter *qdev, u32 intr) return 0; ctx = qdev->intr_context + intr; - spin_lock_irqsave(&qdev->hw_lock, hw_flags); + spin_lock(&qdev->hw_lock); if (!atomic_read(&ctx->irq_cnt)) { ql_write32(qdev, INTR_EN, ctx->intr_dis_mask); var = ql_read32(qdev, STS); } atomic_inc(&ctx->irq_cnt); - spin_unlock_irqrestore(&qdev->hw_lock, hw_flags); + spin_unlock(&qdev->hw_lock); return var; } -- cgit v1.2.3 From b25215d0433f6c71b68eede3548815196a2ed5d5 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:24 +0000 Subject: qlge: Clear shadow registers before use. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 45ad4cc298b..75ad4dbb5cb 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2142,6 +2142,7 @@ static int ql_alloc_shadow_space(struct ql_adapter *qdev) "Allocation of RX shadow space failed.\n"); return -ENOMEM; } + memset(qdev->rx_ring_shadow_reg_area, 0, PAGE_SIZE); qdev->tx_ring_shadow_reg_area = pci_alloc_consistent(qdev->pdev, PAGE_SIZE, &qdev->tx_ring_shadow_reg_dma); @@ -2150,6 +2151,7 @@ static int ql_alloc_shadow_space(struct ql_adapter *qdev) "Allocation of TX shadow space failed.\n"); goto err_wqp_sh_area; } + memset(qdev->tx_ring_shadow_reg_area, 0, PAGE_SIZE); return 0; err_wqp_sh_area: -- cgit v1.2.3 From 39a28bc480bff0f778d043877aff2fd16ad5f769 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:25 +0000 Subject: qlge: Remove spinlock from asic init path. There is nothing to contend with it. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 75ad4dbb5cb..f7f104ab5ff 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3250,14 +3250,12 @@ static int ql_adapter_up(struct ql_adapter *qdev) { int err = 0; - spin_lock(&qdev->hw_lock); err = ql_adapter_initialize(qdev); if (err) { QPRINTK(qdev, IFUP, INFO, "Unable to initialize adapter.\n"); spin_unlock(&qdev->hw_lock); goto err_init; } - spin_unlock(&qdev->hw_lock); set_bit(QL_ADAPTER_UP, &qdev->flags); ql_alloc_rx_buffers(qdev); if ((ql_read32(qdev, STS) & qdev->port_init)) -- cgit v1.2.3 From 6b318cb36813d03dd20f80e63c37176a55edae30 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:26 +0000 Subject: qlge: bugfix: Move netif_napi_del() to common call point. Moving netif_napi_del() up the call chain so it will get called from all exit points. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index f7f104ab5ff..ce826da6f16 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3236,6 +3236,11 @@ static int ql_adapter_down(struct ql_adapter *qdev) ql_tx_ring_clean(qdev); + /* Call netif_napi_del() from common point. + */ + for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) + netif_napi_del(&qdev->rx_ring[i].napi); + ql_free_rx_buffers(qdev); spin_lock(&qdev->hw_lock); status = ql_adapter_reset(qdev); @@ -3964,7 +3969,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *ndev = pci_get_drvdata(pdev); struct ql_adapter *qdev = netdev_priv(ndev); - int err, i; + int err; netif_device_detach(ndev); @@ -3974,9 +3979,6 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) return err; } - for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) - netif_napi_del(&qdev->rx_ring[i].napi); - err = pci_save_state(pdev); if (err) return err; -- cgit v1.2.3 From 74c50b4bae225b8e5aff9a1ceca256ba46c665c6 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:27 +0000 Subject: qlge: bugfix: Pad outbound frames smaller than 60 bytes. With some asic configurations xmit of frames smaller than 60 bytes may fail. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index ce826da6f16..189584684aa 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2057,6 +2057,9 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) tx_ring = &qdev->tx_ring[tx_ring_idx]; + if (skb_padto(skb, ETH_ZLEN)) + return NETDEV_TX_OK; + if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) { QPRINTK(qdev, TX_QUEUED, INFO, "%s: shutting down tx queue %d du to lack of resources.\n", -- cgit v1.2.3 From d4a4aba61731ce6d102a6a93e22b8fa26511c9d5 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Mon, 9 Mar 2009 10:59:28 +0000 Subject: qlge: bugfix: Fix endian issue related to rx buffers. This was introduced in an earlier net-next patch. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/net/qlge/qlge_main.c') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 189584684aa..b91b700a081 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2526,6 +2526,7 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) qdev->doorbell_area + (DB_PAGE_SIZE * (128 + rx_ring->cq_id)); int err = 0; u16 bq_len; + u64 tmp; /* Set up the shadow registers for this ring. */ rx_ring->prod_idx_sh_reg = shadow_reg; @@ -2571,7 +2572,8 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) FLAGS_LI; /* Load irq delay values */ if (rx_ring->lbq_len) { cqicb->flags |= FLAGS_LL; /* Load lbq values */ - *((u64 *) rx_ring->lbq_base_indirect) = rx_ring->lbq_base_dma; + tmp = (u64)rx_ring->lbq_base_dma;; + *((__le64 *) rx_ring->lbq_base_indirect) = cpu_to_le64(tmp); cqicb->lbq_addr = cpu_to_le64(rx_ring->lbq_base_indirect_dma); bq_len = (rx_ring->lbq_buf_size == 65536) ? 0 : @@ -2587,11 +2589,12 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring) } if (rx_ring->sbq_len) { cqicb->flags |= FLAGS_LS; /* Load sbq values */ - *((u64 *) rx_ring->sbq_base_indirect) = rx_ring->sbq_base_dma; + tmp = (u64)rx_ring->sbq_base_dma;; + *((__le64 *) rx_ring->sbq_base_indirect) = cpu_to_le64(tmp); cqicb->sbq_addr = cpu_to_le64(rx_ring->sbq_base_indirect_dma); cqicb->sbq_buf_size = - cpu_to_le16(((rx_ring->sbq_buf_size / 2) + 8) & 0xfffffff8); + cpu_to_le16((u16)(rx_ring->sbq_buf_size/2)); bq_len = (rx_ring->sbq_len == 65536) ? 0 : (u16) rx_ring->sbq_len; cqicb->sbq_len = cpu_to_le16(bq_len); -- cgit v1.2.3