All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing.
@ 2007-02-26 19:04 Ron Mercer
  2007-02-26 19:06 ` [PATCH 01/13] qla3xxx: Return proper error codes when the 4022/4032 is being probed Ron Mercer
                   ` (12 more replies)
  0 siblings, 13 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:04 UTC (permalink / raw)
  To: jeff; +Cc: netdev, ron.mercer, benjamin.li

This patch series addresses a number of issues found when testing at IBM
and Redhat.  The patches were built and tested against the netdev/upstream
kernel on i386/x86_64/PPC64 platforms.

Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 01/13] qla3xxx: Return proper error codes when the 4022/4032 is being probed
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  2007-02-27  9:22   ` Jeff Garzik
  2007-02-26 19:06 ` [PATCH 02/13] qla3xxx: Remove unnecessary memset() in qla3xxx_send() Ron Mercer
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

From: Benjamin Li <benjamin.li@qlogic.com>

The return code was not properly set when when allocating memory or mapping
memory failed.  Depending on the stack, the return code would sometimes
return 0, which indicates everything was ok, when in fact there was an error.
  This would cause trouble when the module was removed.  Now, we will pass
back the proper return code when an error occurs during the PCI probe.

Signed-off-by: Benjamin Li <benjamin.li@qlogic.com>
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 2429b27..d1c90ca 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -3609,8 +3609,12 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
 	}
 
 	ndev = alloc_etherdev(sizeof(struct ql3_adapter));
-	if (!ndev)
+	if (!ndev) {
+		printk(KERN_ERR PFX "%s could not alloc etherdev\n",
+		       pci_name(pdev));
+		err = -ENOMEM;
 		goto err_out_free_regions;
+	}
 
 	SET_MODULE_OWNER(ndev);
 	SET_NETDEV_DEV(ndev, &pdev->dev);
@@ -3639,6 +3643,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
 	if (!qdev->mem_map_registers) {
 		printk(KERN_ERR PFX "%s: cannot map device registers\n",
 		       pci_name(pdev));
+		err = -EIO;
 		goto err_out_free_ndev;
 	}
 
@@ -3667,6 +3672,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
 		printk(KERN_ALERT PFX
 		       "ql3xxx_probe: Adapter #%d, Invalid NVRAM parameters.\n",
 		       qdev->index);
+		err = -EIO;
 		goto err_out_iounmap;
 	}
 
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 02/13] qla3xxx: Remove unnecessary memset() in qla3xxx_send()
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
  2007-02-26 19:06 ` [PATCH 01/13] qla3xxx: Return proper error codes when the 4022/4032 is being probed Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  2007-02-26 19:06 ` [PATCH 03/13] qla3xxx: Changed to use netdev_alloc_skb() from dev_alloc_skb Ron Mercer
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

From: Benjamin Li <benjamin.li@qlogic.com>

We do not need to zero out the 64 byte MAC request I/O control block.
  By zeroing out the control block and setting it to proper fields is
redundant work.  This is because in the qla3xxx_send() function we will
already set the proper fields in this structure.  The unused fields are
not looked at by the hardware and do not need to be zeroed out.

Signed-off-by: Benjamin Li <benjamin.li@qlogic.com>
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index d1c90ca..18a2bb5 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2188,7 +2188,6 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
 
 	}
 	mac_iocb_ptr = tx_cb->queue_entry;
-	memset((void *)mac_iocb_ptr, 0, sizeof(struct ob_mac_iocb_req));
 	mac_iocb_ptr->opcode = qdev->mac_ob_opcode;
 	mac_iocb_ptr->flags |= qdev->mb_bit_mask;
 	mac_iocb_ptr->transaction_id = qdev->req_producer_index;
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 03/13] qla3xxx: Changed to use netdev_alloc_skb() from dev_alloc_skb
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
  2007-02-26 19:06 ` [PATCH 01/13] qla3xxx: Return proper error codes when the 4022/4032 is being probed Ron Mercer
  2007-02-26 19:06 ` [PATCH 02/13] qla3xxx: Remove unnecessary memset() in qla3xxx_send() Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  2007-02-26 19:06 ` [PATCH 04/13] qla3xxx: Add ethtool functionality to report pause parameters Ron Mercer
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

From: Benjamin Li <benjamin.li@qlogic.com>

Signed-off-by: Benjamin Li <benjamin.li@qlogic.com>
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 18a2bb5..5acae02 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -287,9 +287,10 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
 	}
 
 	if (!lrg_buf_cb->skb) {
-		lrg_buf_cb->skb = dev_alloc_skb(qdev->lrg_buffer_len);
+		lrg_buf_cb->skb = netdev_alloc_skb(qdev->ndev,
+						   qdev->lrg_buffer_len);
 		if (unlikely(!lrg_buf_cb->skb)) {
-			printk(KERN_ERR PFX "%s: failed dev_alloc_skb().\n",
+			printk(KERN_ERR PFX "%s: failed netdev_alloc_skb().\n",
 			       qdev->ndev->name);
 			qdev->lrg_buf_skb_check++;
 		} else {
@@ -1619,10 +1620,11 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev)
 
 	while (lrg_buf_cb) {
 		if (!lrg_buf_cb->skb) {
-			lrg_buf_cb->skb = dev_alloc_skb(qdev->lrg_buffer_len);
+			lrg_buf_cb->skb = netdev_alloc_skb(qdev->ndev,
+							   qdev->lrg_buffer_len);
 			if (unlikely(!lrg_buf_cb->skb)) {
 				printk(KERN_DEBUG PFX
-				       "%s: Failed dev_alloc_skb().\n",
+				       "%s: Failed netdev_alloc_skb().\n",
 				       qdev->ndev->name);
 				break;
 			} else {
@@ -2514,7 +2516,8 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
 	u64 map;
 
 	for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
-		skb = dev_alloc_skb(qdev->lrg_buffer_len);
+		skb = netdev_alloc_skb(qdev->ndev,
+				       qdev->lrg_buffer_len);
 		if (unlikely(!skb)) {
 			/* Better luck next round */
 			printk(KERN_ERR PFX
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 04/13] qla3xxx: Add ethtool functionality to report pause parameters
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
                   ` (2 preceding siblings ...)
  2007-02-26 19:06 ` [PATCH 03/13] qla3xxx: Changed to use netdev_alloc_skb() from dev_alloc_skb Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  2007-02-26 19:06 ` [PATCH 05/13] qla3xxx: Fix deadlock issue on error paths Ron Mercer
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

From: Benjamin Li <benjamin.li@qlogic.com>

We have added the ability to query the receive and transmit PAUSE flow
control frames parameters, in addition to the auto-negotiated status
using ethtool.

Signed-off-by: Benjamin Li <benjamin.li@qlogic.com>
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 5acae02..b853669 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -1604,6 +1604,23 @@ static void ql_set_msglevel(struct net_device *ndev, u32 value)
 	qdev->msg_enable = value;
 }
 
+static void ql_get_pauseparam(struct net_device *ndev,
+			      struct ethtool_pauseparam *pause)
+{
+	struct ql3_adapter *qdev = netdev_priv(ndev);
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+
+	u32 reg;
+	if(qdev->mac_index == 0)
+		reg = ql_read_page0_reg(qdev, &port_regs->mac0ConfigReg);
+	else
+		reg = ql_read_page0_reg(qdev, &port_regs->mac1ConfigReg);
+
+	pause->autoneg  = ql_get_auto_cfg_status(qdev);
+	pause->rx_pause = (reg & MAC_CONFIG_REG_RF) >> 2;
+	pause->tx_pause = (reg & MAC_CONFIG_REG_TF) >> 1;
+}
+
 static const struct ethtool_ops ql3xxx_ethtool_ops = {
 	.get_settings = ql_get_settings,
 	.get_drvinfo = ql_get_drvinfo,
@@ -1611,6 +1628,7 @@ static const struct ethtool_ops ql3xxx_ethtool_ops = {
 	.get_link = ethtool_op_get_link,
 	.get_msglevel = ql_get_msglevel,
 	.set_msglevel = ql_set_msglevel,
+	.get_pauseparam = ql_get_pauseparam,
 };
 
 static int ql_populate_free_queue(struct ql3_adapter *qdev)
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 05/13] qla3xxx: Fix deadlock issue on error paths
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
                   ` (3 preceding siblings ...)
  2007-02-26 19:06 ` [PATCH 04/13] qla3xxx: Add ethtool functionality to report pause parameters Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  2007-02-26 19:06 ` [PATCH 06/13] qla3xxx: Remove API to change MTU Ron Mercer
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

From: Benjamin Li <benjamin.li@qlogic.com>

1) Fix deadlock issue when in QL_RESET_ACTIVE state and traversing
   through the Link State Machine
2) Fix deadlock issue when ethtool would call ql_get_settings()
3) Fix deadlock issue when adaptor is ifup'ed but adaptor fails to initialize

Signed-off-by: Benjamin Li <benjamin.li@qlogic.com>
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |   15 ++++++++++++---
 1 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index b853669..59cebd6 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -1388,6 +1388,8 @@ static void ql_link_state_machine(struct ql3_adapter *qdev)
 			printk(KERN_INFO PFX
 			       "%s: Reset in progress, skip processing link "
 			       "state.\n", qdev->ndev->name);
+
+		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);		
 		return;
 	}
 
@@ -1519,8 +1521,10 @@ static int ql_get_auto_cfg_status(struct ql3_adapter *qdev)
 	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
 	if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
 		(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
-			 2) << 7))
+			 2) << 7)) {
+		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
 		return 0;
+	}
 	status = ql_is_auto_cfg(qdev);
 	ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
 	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
@@ -1534,8 +1538,10 @@ static u32 ql_get_speed(struct ql3_adapter *qdev)
 	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
 	if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
 		(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
-			 2) << 7))
+			 2) << 7)) {
+		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
 		return 0;
+	}
 	status = ql_get_link_speed(qdev);
 	ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
 	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
@@ -1549,8 +1555,10 @@ static int ql_get_full_dup(struct ql3_adapter *qdev)
 	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
 	if(ql_sem_spinlock(qdev, QL_PHY_GIO_SEM_MASK,
 		(QL_RESOURCE_BITS_BASE_CODE | (qdev->mac_index) *
-			 2) << 7))
+			 2) << 7)) {
+		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
 		return 0;
+	}
 	status = ql_is_link_full_dup(qdev);
 	ql_sem_unlock(qdev, QL_PHY_GIO_SEM_MASK);
 	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
@@ -3312,6 +3320,7 @@ static int ql_adapter_up(struct ql3_adapter *qdev)
 err_init:
 	ql_sem_unlock(qdev, QL_DRVR_SEM_MASK);
 err_lock:
+	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
 	free_irq(qdev->pdev->irq, ndev);
 err_irq:
 	if (qdev->msi && test_bit(QL_MSI_ENABLED,&qdev->flags)) {
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 06/13] qla3xxx: Remove API to change MTU.
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
                   ` (4 preceding siblings ...)
  2007-02-26 19:06 ` [PATCH 05/13] qla3xxx: Fix deadlock issue on error paths Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  2007-02-26 19:06 ` [PATCH 07/13] qla3xxx: Dynamically size the rx buffer queue based on the MTU Ron Mercer
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

This network device driver shares the same hardware as the qla4xxx
iSCSI driver. Changing the MTU via the device interface will
cause qla4xxx to crash as there is no way to make notification.
Users wishing to change the MTU must do so using an iSCSI
utility such as Qlogic SanSurfer. This forces the user to
unload/reload this network device driver after the MTU
value has been changed in flash.

Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |   24 ++----------------------
 1 files changed, 2 insertions(+), 22 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 59cebd6..b86cef0 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -3372,27 +3372,6 @@ static struct net_device_stats *ql3xxx_get_stats(struct net_device *dev)
 	return &qdev->stats;
 }
 
-static int ql3xxx_change_mtu(struct net_device *ndev, int new_mtu)
-{
-	struct ql3_adapter *qdev = netdev_priv(ndev);
-	printk(KERN_ERR PFX "%s:  new mtu size = %d.\n", ndev->name, new_mtu);
-	if (new_mtu != NORMAL_MTU_SIZE && new_mtu != JUMBO_MTU_SIZE) {
-		printk(KERN_ERR PFX
-		       "%s: mtu size of %d is not valid.  Use exactly %d or "
-		       "%d.\n", ndev->name, new_mtu, NORMAL_MTU_SIZE,
-		       JUMBO_MTU_SIZE);
-		return -EINVAL;
-	}
-
-	if (!netif_running(ndev)) {
-		ndev->mtu = new_mtu;
-		return 0;
-	}
-
-	ndev->mtu = new_mtu;
-	return ql_cycle_adapter(qdev,QL_DO_RESET);
-}
-
 static void ql3xxx_set_multicast_list(struct net_device *ndev)
 {
 	/*
@@ -3684,7 +3663,6 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
 	ndev->hard_start_xmit = ql3xxx_send;
 	ndev->stop = ql3xxx_close;
 	ndev->get_stats = ql3xxx_get_stats;
-	ndev->change_mtu = ql3xxx_change_mtu;
 	ndev->set_multicast_list = ql3xxx_set_multicast_list;
 	SET_ETHTOOL_OPS(ndev, &ql3xxx_ethtool_ops);
 	ndev->set_mac_address = ql3xxx_set_mac_address;
@@ -3709,9 +3687,11 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
 
 	/* Validate and set parameters */
 	if (qdev->mac_index) {
+		ndev->mtu = qdev->nvram_data.macCfg_port1.etherMtu_mac ;
 		memcpy(ndev->dev_addr, &qdev->nvram_data.funcCfg_fn2.macAddress,
 		       ETH_ALEN);
 	} else {
+		ndev->mtu = qdev->nvram_data.macCfg_port0.etherMtu_mac ;
 		memcpy(ndev->dev_addr, &qdev->nvram_data.funcCfg_fn0.macAddress,
 		       ETH_ALEN);
 	}
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 07/13] qla3xxx: Dynamically size the rx buffer queue based on the MTU.
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
                   ` (5 preceding siblings ...)
  2007-02-26 19:06 ` [PATCH 06/13] qla3xxx: Remove API to change MTU Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  2007-02-26 19:06 ` [PATCH 08/13] qla3xxx: Clean up receive process Ron Mercer
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

This change removes use of constants for rx buffer queue size
and instead calculates the queue length based on what he MTU
is set to.

Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |   41 ++++++++++++++++++++++++++++-------------
 drivers/net/qla3xxx.h |    8 ++++++--
 2 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index b86cef0..fe494ac 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -1718,11 +1718,11 @@ static void ql_update_lrg_bufq_prod_index(struct ql3_adapter *qdev)
 
 			qdev->lrg_buf_q_producer_index++;
 
-			if (qdev->lrg_buf_q_producer_index == NUM_LBUFQ_ENTRIES)
+			if (qdev->lrg_buf_q_producer_index == qdev->num_lbufq_entries)
 				qdev->lrg_buf_q_producer_index = 0;
 
 			if (qdev->lrg_buf_q_producer_index ==
-			    (NUM_LBUFQ_ENTRIES - 1)) {
+			    (qdev->num_lbufq_entries - 1)) {
 				lrg_buf_q_ele = qdev->lrg_buf_q_virt_addr;
 			}
 		}
@@ -1803,7 +1803,7 @@ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev,
 		lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
 		lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index];
 		qdev->lrg_buf_release_cnt++;
-		if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS) {
+		if (++qdev->lrg_buf_index == qdev->num_large_buffers) {
 			qdev->lrg_buf_index = 0;
 		}
 		curr_ial_ptr++;	/* 64-bit pointers require two incs. */
@@ -1818,7 +1818,7 @@ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev,
 	 * Second buffer gets sent up the stack.
 	 */
 	qdev->lrg_buf_release_cnt++;
-	if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
+	if (++qdev->lrg_buf_index == qdev->num_large_buffers)
 		qdev->lrg_buf_index = 0;
 	skb = lrg_buf_cb2->skb;
 
@@ -1873,7 +1873,7 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
 		lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
 		lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index];
 		qdev->lrg_buf_release_cnt++;
-		if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
+		if (++qdev->lrg_buf_index == qdev->num_large_buffers)
 			qdev->lrg_buf_index = 0;
 		skb1 = lrg_buf_cb1->skb;
 		curr_ial_ptr++;	/* 64-bit pointers require two incs. */
@@ -1888,7 +1888,7 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
 	lrg_buf_cb2 = &qdev->lrg_buf[qdev->lrg_buf_index];
 	skb2 = lrg_buf_cb2->skb;
 	qdev->lrg_buf_release_cnt++;
-	if (++qdev->lrg_buf_index == NUM_LARGE_BUFFERS)
+	if (++qdev->lrg_buf_index == qdev->num_large_buffers)
 		qdev->lrg_buf_index = 0;
 
 	skb_put(skb2, length);	/* Just the second buffer length here. */
@@ -2365,12 +2365,19 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev)
 {
 	/* Create Large Buffer Queue */
 	qdev->lrg_buf_q_size =
-	    NUM_LBUFQ_ENTRIES * sizeof(struct lrg_buf_q_entry);
+	    qdev->num_lbufq_entries * sizeof(struct lrg_buf_q_entry);
 	if (qdev->lrg_buf_q_size < PAGE_SIZE)
 		qdev->lrg_buf_q_alloc_size = PAGE_SIZE;
 	else
 		qdev->lrg_buf_q_alloc_size = qdev->lrg_buf_q_size * 2;
 
+	qdev->lrg_buf = kmalloc(qdev->num_large_buffers * sizeof(struct ql_rcv_buf_cb),GFP_KERNEL);
+	if (qdev->lrg_buf == NULL) {
+		printk(KERN_ERR PFX
+		       "%s: qdev->lrg_buf alloc failed.\n", qdev->ndev->name);
+		return -ENOMEM;
+	}
+	
 	qdev->lrg_buf_q_alloc_virt_addr =
 	    pci_alloc_consistent(qdev->pdev,
 				 qdev->lrg_buf_q_alloc_size,
@@ -2420,6 +2427,7 @@ static void ql_free_buffer_queues(struct ql3_adapter *qdev)
 		       "%s: Already done.\n", qdev->ndev->name);
 		return;
 	}
+	if(qdev->lrg_buf) kfree(qdev->lrg_buf);
 
 	pci_free_consistent(qdev->pdev,
 			    qdev->lrg_buf_q_alloc_size,
@@ -2503,7 +2511,7 @@ static void ql_free_large_buffers(struct ql3_adapter *qdev)
 	int i = 0;
 	struct ql_rcv_buf_cb *lrg_buf_cb;
 
-	for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
+	for (i = 0; i < qdev->num_large_buffers; i++) {
 		lrg_buf_cb = &qdev->lrg_buf[i];
 		if (lrg_buf_cb->skb) {
 			dev_kfree_skb(lrg_buf_cb->skb);
@@ -2524,7 +2532,7 @@ static void ql_init_large_buffers(struct ql3_adapter *qdev)
 	struct ql_rcv_buf_cb *lrg_buf_cb;
 	struct bufq_addr_element *buf_addr_ele = qdev->lrg_buf_q_virt_addr;
 
-	for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
+	for (i = 0; i < qdev->num_large_buffers; i++) {
 		lrg_buf_cb = &qdev->lrg_buf[i];
 		buf_addr_ele->addr_high = lrg_buf_cb->buf_phy_addr_high;
 		buf_addr_ele->addr_low = lrg_buf_cb->buf_phy_addr_low;
@@ -2541,7 +2549,7 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
 	struct sk_buff *skb;
 	u64 map;
 
-	for (i = 0; i < NUM_LARGE_BUFFERS; i++) {
+	for (i = 0; i < qdev->num_large_buffers; i++) {
 		skb = netdev_alloc_skb(qdev->ndev,
 				       qdev->lrg_buffer_len);
 		if (unlikely(!skb)) {
@@ -2620,9 +2628,15 @@ static int ql_create_send_free_list(struct ql3_adapter *qdev)
 
 static int ql_alloc_mem_resources(struct ql3_adapter *qdev)
 {
-	if (qdev->ndev->mtu == NORMAL_MTU_SIZE)
+	if (qdev->ndev->mtu == NORMAL_MTU_SIZE) {
+		qdev->num_lbufq_entries = NUM_LBUFQ_ENTRIES;
 		qdev->lrg_buffer_len = NORMAL_MTU_SIZE;
+	}
 	else if (qdev->ndev->mtu == JUMBO_MTU_SIZE) {
+		/*
+		 * Bigger buffers, so less of them.
+		 */
+		qdev->num_lbufq_entries = JUMBO_NUM_LBUFQ_ENTRIES;
 		qdev->lrg_buffer_len = JUMBO_MTU_SIZE;
 	} else {
 		printk(KERN_ERR PFX
@@ -2630,6 +2644,7 @@ static int ql_alloc_mem_resources(struct ql3_adapter *qdev)
 		       qdev->ndev->name);
 		return -ENOMEM;
 	}
+	qdev->num_large_buffers = qdev->num_lbufq_entries * QL_ADDR_ELE_PER_BUFQ_ENTRY;
 	qdev->lrg_buffer_len += VLAN_ETH_HLEN + VLAN_ID_LEN + QL_HEADER_SPACE;
 	qdev->max_frame_size =
 	    (qdev->lrg_buffer_len - QL_HEADER_SPACE) + ETHERNET_CRC_SIZE;
@@ -2862,7 +2877,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev)
 			   &hmem_regs->rxLargeQBaseAddrLow,
 			   LS_64BITS(qdev->lrg_buf_q_phy_addr));
 
-	ql_write_page1_reg(qdev, &hmem_regs->rxLargeQLength, NUM_LBUFQ_ENTRIES);
+	ql_write_page1_reg(qdev, &hmem_regs->rxLargeQLength, qdev->num_lbufq_entries);
 
 	ql_write_page1_reg(qdev,
 			   &hmem_regs->rxLargeBufferLength,
@@ -2884,7 +2899,7 @@ static int ql_adapter_initialize(struct ql3_adapter *qdev)
 
 	qdev->small_buf_q_producer_index = NUM_SBUFQ_ENTRIES - 1;
 	qdev->small_buf_release_cnt = 8;
-	qdev->lrg_buf_q_producer_index = NUM_LBUFQ_ENTRIES - 1;
+	qdev->lrg_buf_q_producer_index = qdev->num_lbufq_entries - 1;
 	qdev->lrg_buf_release_cnt = 8;
 	qdev->lrg_buf_next_free =
 	    (struct bufq_addr_element *)qdev->lrg_buf_q_virt_addr;
diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h
index b2d76ea..51173e5 100755
--- a/drivers/net/qla3xxx.h
+++ b/drivers/net/qla3xxx.h
@@ -1014,13 +1014,15 @@ struct eeprom_data {
 
 /* Transmit and Receive Buffers */
 #define NUM_LBUFQ_ENTRIES   	128
+#define JUMBO_NUM_LBUFQ_ENTRIES   	\
+(NUM_LBUFQ_ENTRIES/(JUMBO_MTU_SIZE/NORMAL_MTU_SIZE))
 #define NUM_SBUFQ_ENTRIES   	64
 #define QL_SMALL_BUFFER_SIZE    32
 #define QL_ADDR_ELE_PER_BUFQ_ENTRY \
 (sizeof(struct lrg_buf_q_entry) / sizeof(struct bufq_addr_element))
     /* Each send has at least control block.  This is how many we keep. */
 #define NUM_SMALL_BUFFERS     	NUM_SBUFQ_ENTRIES * QL_ADDR_ELE_PER_BUFQ_ENTRY
-#define NUM_LARGE_BUFFERS     	NUM_LBUFQ_ENTRIES * QL_ADDR_ELE_PER_BUFQ_ENTRY
+
 #define QL_HEADER_SPACE 32	/* make header space at top of skb. */
 /*
  * Large & Small Buffers for Receives
@@ -1207,9 +1209,11 @@ struct ql3_adapter {
 	u32 lrg_buf_q_producer_index;
 	u32 lrg_buf_release_cnt;
 	struct bufq_addr_element *lrg_buf_next_free;
+	u32 num_large_buffers;
+	u32 num_lbufq_entries;
 
 	/* Large (Receive) Buffers */
-	struct ql_rcv_buf_cb lrg_buf[NUM_LARGE_BUFFERS];
+	struct ql_rcv_buf_cb *lrg_buf;
 	struct ql_rcv_buf_cb *lrg_buf_free_head;
 	struct ql_rcv_buf_cb *lrg_buf_free_tail;
 	u32 lrg_buf_free_count;
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 08/13] qla3xxx: Clean up receive process.
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
                   ` (6 preceding siblings ...)
  2007-02-26 19:06 ` [PATCH 07/13] qla3xxx: Dynamically size the rx buffer queue based on the MTU Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  2007-02-26 19:06 ` [PATCH 09/13] qla3xxx: bugfix: Fixed jumbo frame handling for 3032 chip Ron Mercer
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |   78 +++++++++++++++----------------------------------
 1 files changed, 24 insertions(+), 54 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index fe494ac..cb3a05e 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -1764,6 +1764,23 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
 	atomic_inc(&qdev->tx_count);
 }
 
+void ql_get_sbuf(struct ql3_adapter *qdev)
+{
+	if (++qdev->small_buf_index == NUM_SMALL_BUFFERS)
+		qdev->small_buf_index = 0;
+	qdev->small_buf_release_cnt++;
+}
+
+struct ql_rcv_buf_cb *ql_get_lbuf(struct ql3_adapter *qdev)
+{
+	struct ql_rcv_buf_cb *lrg_buf_cb = NULL;
+	lrg_buf_cb = &qdev->lrg_buf[qdev->lrg_buf_index];
+	qdev->lrg_buf_release_cnt++;
+	if (++qdev->lrg_buf_index == qdev->num_large_buffers)
+		qdev->lrg_buf_index = 0;
+	return(lrg_buf_cb);
+}
+
 /*
  * The difference between 3022 and 3032 for inbound completions:
  * 3022 uses two buffers per completion.  The first buffer contains 
@@ -1779,47 +1796,21 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
 static void ql_process_mac_rx_intr(struct ql3_adapter *qdev,
 				   struct ib_mac_iocb_rsp *ib_mac_rsp_ptr)
 {
-	long int offset;
-	u32 lrg_buf_phy_addr_low = 0;
 	struct ql_rcv_buf_cb *lrg_buf_cb1 = NULL;
 	struct ql_rcv_buf_cb *lrg_buf_cb2 = NULL;
-	u32 *curr_ial_ptr;
 	struct sk_buff *skb;
 	u16 length = le16_to_cpu(ib_mac_rsp_ptr->length);
 
 	/*
 	 * Get the inbound address list (small buffer).
 	 */
-	offset = qdev->small_buf_index * QL_SMALL_BUFFER_SIZE;
-	if (++qdev->small_buf_index == NUM_SMALL_BUFFERS)
-		qdev->small_buf_index = 0;
-
-	curr_ial_ptr = (u32 *) (qdev->small_buf_virt_addr + offset);
-	qdev->last_rsp_offset = qdev->small_buf_phy_addr_low + offset;
-	qdev->small_buf_release_cnt++;
+	ql_get_sbuf(qdev);
 
-	if (qdev->device_id == QL3022_DEVICE_ID) {
-		/* start of first buffer (3022 only) */
-		lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
-		lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index];
-		qdev->lrg_buf_release_cnt++;
-		if (++qdev->lrg_buf_index == qdev->num_large_buffers) {
-			qdev->lrg_buf_index = 0;
-		}
-		curr_ial_ptr++;	/* 64-bit pointers require two incs. */
-		curr_ial_ptr++;
-	}
+	if (qdev->device_id == QL3022_DEVICE_ID)
+		lrg_buf_cb1 = ql_get_lbuf(qdev);
 
 	/* start of second buffer */
-	lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
-	lrg_buf_cb2 = &qdev->lrg_buf[qdev->lrg_buf_index];
-
-	/*
-	 * Second buffer gets sent up the stack.
-	 */
-	qdev->lrg_buf_release_cnt++;
-	if (++qdev->lrg_buf_index == qdev->num_large_buffers)
-		qdev->lrg_buf_index = 0;
+	lrg_buf_cb2 = ql_get_lbuf(qdev);
 	skb = lrg_buf_cb2->skb;
 
 	qdev->stats.rx_packets++;
@@ -1847,11 +1838,8 @@ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev,
 static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
 				     struct ib_ip_iocb_rsp *ib_ip_rsp_ptr)
 {
-	long int offset;
-	u32 lrg_buf_phy_addr_low = 0;
 	struct ql_rcv_buf_cb *lrg_buf_cb1 = NULL;
 	struct ql_rcv_buf_cb *lrg_buf_cb2 = NULL;
-	u32 *curr_ial_ptr;
 	struct sk_buff *skb1 = NULL, *skb2;
 	struct net_device *ndev = qdev->ndev;
 	u16 length = le16_to_cpu(ib_ip_rsp_ptr->length);
@@ -1861,35 +1849,20 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
 	 * Get the inbound address list (small buffer).
 	 */
 
-	offset = qdev->small_buf_index * QL_SMALL_BUFFER_SIZE;
-	if (++qdev->small_buf_index == NUM_SMALL_BUFFERS)
-		qdev->small_buf_index = 0;
-	curr_ial_ptr = (u32 *) (qdev->small_buf_virt_addr + offset);
-	qdev->last_rsp_offset = qdev->small_buf_phy_addr_low + offset;
-	qdev->small_buf_release_cnt++;
+	ql_get_sbuf(qdev);
 
 	if (qdev->device_id == QL3022_DEVICE_ID) {
 		/* start of first buffer on 3022 */
-		lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
-		lrg_buf_cb1 = &qdev->lrg_buf[qdev->lrg_buf_index];
-		qdev->lrg_buf_release_cnt++;
-		if (++qdev->lrg_buf_index == qdev->num_large_buffers)
-			qdev->lrg_buf_index = 0;
+		lrg_buf_cb1 = ql_get_lbuf(qdev);
 		skb1 = lrg_buf_cb1->skb;
-		curr_ial_ptr++;	/* 64-bit pointers require two incs. */
-		curr_ial_ptr++;
 		size = ETH_HLEN;
 		if (*((u16 *) skb1->data) != 0xFFFF)
 			size += VLAN_ETH_HLEN - ETH_HLEN;
 	}
 
 	/* start of second buffer */
-	lrg_buf_phy_addr_low = le32_to_cpu(*curr_ial_ptr);
-	lrg_buf_cb2 = &qdev->lrg_buf[qdev->lrg_buf_index];
+	lrg_buf_cb2 = ql_get_lbuf(qdev);
 	skb2 = lrg_buf_cb2->skb;
-	qdev->lrg_buf_release_cnt++;
-	if (++qdev->lrg_buf_index == qdev->num_large_buffers)
-		qdev->lrg_buf_index = 0;
 
 	skb_put(skb2, length);	/* Just the second buffer length here. */
 	pci_unmap_single(qdev->pdev,
@@ -2428,7 +2401,6 @@ static void ql_free_buffer_queues(struct ql3_adapter *qdev)
 		return;
 	}
 	if(qdev->lrg_buf) kfree(qdev->lrg_buf);
-
 	pci_free_consistent(qdev->pdev,
 			    qdev->lrg_buf_q_alloc_size,
 			    qdev->lrg_buf_q_alloc_virt_addr,
@@ -2473,8 +2445,6 @@ static int ql_alloc_small_buffers(struct ql3_adapter *qdev)
 
 	small_buf_q_entry = qdev->small_buf_q_virt_addr;
 
-	qdev->last_rsp_offset = qdev->small_buf_phy_addr_low;
-
 	/* Initialize the small buffer queue. */
 	for (i = 0; i < (QL_ADDR_ELE_PER_BUFQ_ENTRY * NUM_SBUFQ_ENTRIES); i++) {
 		small_buf_q_entry->addr_high =
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 09/13] qla3xxx: bugfix: Fixed jumbo frame handling for 3032 chip.
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
                   ` (7 preceding siblings ...)
  2007-02-26 19:06 ` [PATCH 08/13] qla3xxx: Clean up receive process Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  2007-02-26 19:06 ` [PATCH 10/13] qla3xxx: Check return code from pci_map_single() in ql_release_to_lrg_buf_free_list(), ql_populate_free_queue(), ql_alloc_large_buffers(), and ql3xxx_send() Ron Mercer
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

The scatter/gather lists were not being build correctly.  When
large frames spanned several buffers the chip would panic.

Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |   99 +++++++++++++++++++++++++++++++-----------------
 drivers/net/qla3xxx.h |    1 -
 2 files changed, 64 insertions(+), 36 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index cb3a05e..d2f4397 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2140,11 +2140,13 @@ static void ql_hw_csum_setup(struct sk_buff *skb,
 
 	if (ip) {
 		if (ip->protocol == IPPROTO_TCP) {
-			mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC;
+			mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC | 
+			OB_3032MAC_IOCB_REQ_IC;
 			mac_iocb_ptr->ip_hdr_off = offset;
 			mac_iocb_ptr->ip_hdr_len = ip->ihl;
 		} else if (ip->protocol == IPPROTO_UDP) {
-			mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC;
+			mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC | 
+			OB_3032MAC_IOCB_REQ_IC;
 			mac_iocb_ptr->ip_hdr_off = offset;
 			mac_iocb_ptr->ip_hdr_len = ip->ihl;
 		}
@@ -2152,51 +2154,29 @@ static void ql_hw_csum_setup(struct sk_buff *skb,
 }
 
 /*
- * The difference between 3022 and 3032 sends:
- * 3022 only supports a simple single segment transmission.
- * 3032 supports checksumming and scatter/gather lists (fragments).
- * The 3032 supports sglists by using the 3 addr/len pairs (ALP) 
- * in the IOCB plus a chain of outbound address lists (OAL) that 
- * each contain 5 ALPs.  The last ALP of the IOCB (3rd) or OAL (5th) 
- * will used to point to an OAL when more ALP entries are required.  
- * The IOCB is always the top of the chain followed by one or more 
- * OALs (when necessary).
+ * Map the buffers for this transmit.  This will return
+ * NETDEV_TX_BUSY or NETDEV_TX_OK based on success.
  */
-static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
+static int ql_send_map(struct ql3_adapter *qdev,
+				struct ob_mac_iocb_req *mac_iocb_ptr,
+				struct ql_tx_buf_cb *tx_cb,
+				struct sk_buff *skb)
 {
-	struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
-	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
-	struct ql_tx_buf_cb *tx_cb;
-	u32 tot_len = skb->len;
 	struct oal *oal;
 	struct oal_entry *oal_entry;
-	int len;
-	struct ob_mac_iocb_req *mac_iocb_ptr;
+	int len = skb_headlen(skb);
 	u64 map;
 	int seg_cnt, seg = 0;
 	int frag_cnt = (int)skb_shinfo(skb)->nr_frags;
 
-	if (unlikely(atomic_read(&qdev->tx_count) < 2)) {
-		if (!netif_queue_stopped(ndev))
-			netif_stop_queue(ndev);
-		return NETDEV_TX_BUSY;
-	}
-	tx_cb = &qdev->tx_buf[qdev->req_producer_index] ;
 	seg_cnt = tx_cb->seg_count = ql_get_seg_count((skb_shinfo(skb)->nr_frags));
 	if(seg_cnt == -1) {
 		printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__);
-		return NETDEV_TX_OK;
-
+		return NETDEV_TX_BUSY;
 	}
-	mac_iocb_ptr = tx_cb->queue_entry;
-	mac_iocb_ptr->opcode = qdev->mac_ob_opcode;
-	mac_iocb_ptr->flags |= qdev->mb_bit_mask;
-	mac_iocb_ptr->transaction_id = qdev->req_producer_index;
-	mac_iocb_ptr->data_len = cpu_to_le16((u16) tot_len);
-	tx_cb->skb = skb;
-	if (skb->ip_summed == CHECKSUM_PARTIAL)
-		ql_hw_csum_setup(skb, mac_iocb_ptr);
-	len = skb_headlen(skb);
+	/*
+	 * Map the skb buffer first.
+	 */
 	map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE);
 	oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low;
 	oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
@@ -2253,6 +2233,55 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
 		oal_entry->len =
 		    cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
 	}
+	return NETDEV_TX_OK;
+}
+
+/*
+ * The difference between 3022 and 3032 sends:
+ * 3022 only supports a simple single segment transmission.
+ * 3032 supports checksumming and scatter/gather lists (fragments).
+ * The 3032 supports sglists by using the 3 addr/len pairs (ALP) 
+ * in the IOCB plus a chain of outbound address lists (OAL) that 
+ * each contain 5 ALPs.  The last ALP of the IOCB (3rd) or OAL (5th) 
+ * will used to point to an OAL when more ALP entries are required.  
+ * The IOCB is always the top of the chain followed by one or more 
+ * OALs (when necessary).
+ */
+static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
+	struct ql_tx_buf_cb *tx_cb;
+	u32 tot_len = skb->len;
+	struct ob_mac_iocb_req *mac_iocb_ptr;
+
+	if (unlikely(atomic_read(&qdev->tx_count) < 2)) {
+		if (!netif_queue_stopped(ndev))
+			netif_stop_queue(ndev);
+		return NETDEV_TX_BUSY;
+	}
+	
+	tx_cb = &qdev->tx_buf[qdev->req_producer_index] ;
+	if((tx_cb->seg_count = ql_get_seg_count((skb_shinfo(skb)->nr_frags))) == -1) {
+		printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__);
+		return NETDEV_TX_OK;
+	}
+	
+	mac_iocb_ptr = tx_cb->queue_entry;
+	mac_iocb_ptr->opcode = qdev->mac_ob_opcode;
+	mac_iocb_ptr->flags = OB_MAC_IOCB_REQ_X;
+	mac_iocb_ptr->flags |= qdev->mb_bit_mask;
+	mac_iocb_ptr->transaction_id = qdev->req_producer_index;
+	mac_iocb_ptr->data_len = cpu_to_le16((u16) tot_len);
+	tx_cb->skb = skb;
+	if (skb->ip_summed == CHECKSUM_PARTIAL)
+		ql_hw_csum_setup(skb, mac_iocb_ptr);
+	
+	if(ql_send_map(qdev,mac_iocb_ptr,tx_cb,skb) != NETDEV_TX_OK) {
+		printk(KERN_ERR PFX"%s: Could not map the segments!\n",__func__);
+		return NETDEV_TX_BUSY;
+	}
+	
 	wmb();
 	qdev->req_producer_index++;
 	if (qdev->req_producer_index == NUM_REQ_Q_ENTRIES)
diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h
index 51173e5..40913d2 100755
--- a/drivers/net/qla3xxx.h
+++ b/drivers/net/qla3xxx.h
@@ -1094,7 +1094,6 @@ struct oal_entry {
 	u32 len;
 #define OAL_LAST_ENTRY   0x80000000	/* Last valid buffer in list. */
 #define OAL_CONT_ENTRY   0x40000000	/* points to an OAL. (continuation) */
-	u32 reserved;
 };
 
 struct oal {
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 10/13] qla3xxx: Check return code from pci_map_single() in ql_release_to_lrg_buf_free_list(), ql_populate_free_queue(), ql_alloc_large_buffers(), and ql3xxx_send()
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
                   ` (8 preceding siblings ...)
  2007-02-26 19:06 ` [PATCH 09/13] qla3xxx: bugfix: Fixed jumbo frame handling for 3032 chip Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  2007-02-26 19:06 ` [PATCH 11/13] qla3xxx: bugfix tx reset after stress conditions Ron Mercer
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

From: Benjamin Li <benjamin.li@qlogic.com>

pci_map_single() could fail.  We need to properly check the return
code from pci_map_single().  If we can not properly map this address,
then we should cleanup and return the proper return code.

Signed-off-by: Benjamin Li <benjamin.li@qlogic.com>
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |  114 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 107 insertions(+), 7 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index d2f4397..63522ea 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -276,7 +276,8 @@ static void ql_enable_interrupts(struct ql3_adapter *qdev)
 static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
 					    struct ql_rcv_buf_cb *lrg_buf_cb)
 {
-	u64 map;
+	dma_addr_t map;
+	int err;
 	lrg_buf_cb->next = NULL;
 
 	if (qdev->lrg_buf_free_tail == NULL) {	/* The list is empty  */
@@ -304,6 +305,17 @@ static void ql_release_to_lrg_buf_free_list(struct ql3_adapter *qdev,
 					     qdev->lrg_buffer_len -
 					     QL_HEADER_SPACE,
 					     PCI_DMA_FROMDEVICE);
+			err = pci_dma_mapping_error(map);
+			if(err) {
+				printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", 
+				       qdev->ndev->name, err);
+				dev_kfree_skb(lrg_buf_cb->skb);
+				lrg_buf_cb->skb = NULL;
+
+				qdev->lrg_buf_skb_check++;
+				return;
+			}
+
 			lrg_buf_cb->buf_phy_addr_low =
 			    cpu_to_le32(LS_64BITS(map));
 			lrg_buf_cb->buf_phy_addr_high =
@@ -1642,7 +1654,8 @@ static const struct ethtool_ops ql3xxx_ethtool_ops = {
 static int ql_populate_free_queue(struct ql3_adapter *qdev)
 {
 	struct ql_rcv_buf_cb *lrg_buf_cb = qdev->lrg_buf_free_head;
-	u64 map;
+	dma_addr_t map;
+	int err;
 
 	while (lrg_buf_cb) {
 		if (!lrg_buf_cb->skb) {
@@ -1664,6 +1677,17 @@ static int ql_populate_free_queue(struct ql3_adapter *qdev)
 						     qdev->lrg_buffer_len -
 						     QL_HEADER_SPACE,
 						     PCI_DMA_FROMDEVICE);
+
+				err = pci_dma_mapping_error(map);
+				if(err) {
+					printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", 
+					       qdev->ndev->name, err);
+					dev_kfree_skb(lrg_buf_cb->skb);
+					lrg_buf_cb->skb = NULL;
+					break;
+				}
+
+
 				lrg_buf_cb->buf_phy_addr_low =
 				    cpu_to_le32(LS_64BITS(map));
 				lrg_buf_cb->buf_phy_addr_high =
@@ -2165,7 +2189,9 @@ static int ql_send_map(struct ql3_adapter *qdev,
 	struct oal *oal;
 	struct oal_entry *oal_entry;
 	int len = skb_headlen(skb);
-	u64 map;
+	dma_addr_t map;
+	int err;
+	int completed_segs, i;
 	int seg_cnt, seg = 0;
 	int frag_cnt = (int)skb_shinfo(skb)->nr_frags;
 
@@ -2178,6 +2204,15 @@ static int ql_send_map(struct ql3_adapter *qdev,
 	 * Map the skb buffer first.
 	 */
 	map = pci_map_single(qdev->pdev, skb->data, len, PCI_DMA_TODEVICE);
+
+	err = pci_dma_mapping_error(map);
+	if(err) {
+		printk(KERN_ERR "%s: PCI mapping failed with error: %d\n", 
+		       qdev->ndev->name, err);
+
+		return NETDEV_TX_BUSY;
+	}
+	
 	oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low;
 	oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
 	oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map));
@@ -2191,10 +2226,9 @@ static int ql_send_map(struct ql3_adapter *qdev,
 		oal_entry->len =
 		    cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
 	} else {
-		int i;
 		oal = tx_cb->oal;
-		for (i=0; i<frag_cnt; i++,seg++) {
-			skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+		for (completed_segs=0; completed_segs<frag_cnt; completed_segs++,seg++) {
+			skb_frag_t *frag = &skb_shinfo(skb)->frags[completed_segs];
 			oal_entry++;
 			if ((seg == 2 && seg_cnt > 3) ||	/* Check for continuation */
 			    (seg == 7 && seg_cnt > 8) ||	/* requirements. It's strange */
@@ -2204,6 +2238,15 @@ static int ql_send_map(struct ql3_adapter *qdev,
 				map = pci_map_single(qdev->pdev, oal,
 						     sizeof(struct oal),
 						     PCI_DMA_TODEVICE);
+
+				err = pci_dma_mapping_error(map);
+				if(err) {
+
+					printk(KERN_ERR "%s: PCI mapping outbound address list with error: %d\n", 
+					       qdev->ndev->name, err);
+					goto map_error;
+				}
+
 				oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
 				oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map));
 				oal_entry->len =
@@ -2222,6 +2265,14 @@ static int ql_send_map(struct ql3_adapter *qdev,
 			    pci_map_page(qdev->pdev, frag->page,
 					 frag->page_offset, frag->size,
 					 PCI_DMA_TODEVICE);
+
+			err = pci_dma_mapping_error(map);
+			if(err) {
+				printk(KERN_ERR "%s: PCI mapping frags failed with error: %d\n", 
+				       qdev->ndev->name, err);
+				goto map_error;
+			}
+
 			oal_entry->dma_lo = cpu_to_le32(LS_64BITS(map));
 			oal_entry->dma_hi = cpu_to_le32(MS_64BITS(map));
 			oal_entry->len = cpu_to_le32(frag->size);
@@ -2233,7 +2284,46 @@ static int ql_send_map(struct ql3_adapter *qdev,
 		oal_entry->len =
 		    cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
 	}
+
 	return NETDEV_TX_OK;
+
+map_error:
+	/* A PCI mapping failed and now we will need to back out
+	 * We need to traverse through the oal's and associated pages which 
+	 * have been mapped and now we must unmap them to clean up properly
+	 */
+	
+	seg = 1;
+	oal_entry = (struct oal_entry *)&mac_iocb_ptr->buf_addr0_low;
+	oal = tx_cb->oal;
+	for (i=0; i<completed_segs; i++,seg++) {
+		oal_entry++;
+
+		if((seg == 2 && seg_cnt > 3) ||        /* Check for continuation */
+		   (seg == 7 && seg_cnt > 8) ||        /* requirements. It's strange */
+		   (seg == 12 && seg_cnt > 13) ||      /* but necessary. */
+		   (seg == 17 && seg_cnt > 18)) {
+			pci_unmap_single(qdev->pdev,
+				pci_unmap_addr(&tx_cb->map[seg], mapaddr),
+				pci_unmap_len(&tx_cb->map[seg], maplen),
+				 PCI_DMA_TODEVICE);
+			oal++;
+			seg++;
+		}
+
+		pci_unmap_page(qdev->pdev,
+			       pci_unmap_addr(&tx_cb->map[seg], mapaddr),
+			       pci_unmap_len(&tx_cb->map[seg], maplen),
+			       PCI_DMA_TODEVICE);
+	}
+
+	pci_unmap_single(qdev->pdev,
+			 pci_unmap_addr(&tx_cb->map[0], mapaddr),
+			 pci_unmap_addr(&tx_cb->map[0], maplen),
+			 PCI_DMA_TODEVICE);
+
+	return NETDEV_TX_BUSY;
+
 }
 
 /*
@@ -2546,7 +2636,8 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
 	int i;
 	struct ql_rcv_buf_cb *lrg_buf_cb;
 	struct sk_buff *skb;
-	u64 map;
+	dma_addr_t map;
+	int err;
 
 	for (i = 0; i < qdev->num_large_buffers; i++) {
 		skb = netdev_alloc_skb(qdev->ndev,
@@ -2576,6 +2667,15 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
 					     qdev->lrg_buffer_len -
 					     QL_HEADER_SPACE,
 					     PCI_DMA_FROMDEVICE);
+
+			err = pci_dma_mapping_error(map);
+			if(err) {
+				printk(KERN_ERR "%s: PCI mapping failed with error: %d\n",
+				       qdev->ndev->name, err);
+				ql_free_large_buffers(qdev);
+				return -ENOMEM;
+			}
+
 			pci_unmap_addr_set(lrg_buf_cb, mapaddr, map);
 			pci_unmap_len_set(lrg_buf_cb, maplen,
 					  qdev->lrg_buffer_len -
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 11/13] qla3xxx: bugfix tx reset after stress conditions.
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
                   ` (9 preceding siblings ...)
  2007-02-26 19:06 ` [PATCH 10/13] qla3xxx: Check return code from pci_map_single() in ql_release_to_lrg_buf_free_list(), ql_populate_free_queue(), ql_alloc_large_buffers(), and ql3xxx_send() Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  2007-02-26 19:06 ` [PATCH 12/13] qla3xxx: Kernic Panic on pSeries under " Ron Mercer
  2007-02-26 19:06 ` [PATCH 13/13] qla3xxx: Bumping driver version number Ron Mercer
  12 siblings, 0 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

To Reproduce the Problem:
To reproduce this panic consistently, we run an intensive network
application like 'netperf' and then switch to a different console.
After waiting for a couple of seconds, you will see a tx reset has occured.

Reason:
We enable interrupts even if we were not running.

Solution:
Now we will enable interrupts only after we are ready to give up the poll
routine.

Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |   69 +++++++++++++++++++++++++++++--------------------
 1 files changed, 41 insertions(+), 28 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 63522ea..bc9109a 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -1939,10 +1939,11 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev,
 	struct net_rsp_iocb *net_rsp;
 	struct net_device *ndev = qdev->ndev;
 	unsigned long hw_flags;
+	int work_done = 0;
 
 	/* While there are entries in the completion queue. */
 	while ((cpu_to_le32(*(qdev->prsp_producer_index)) !=
-		qdev->rsp_consumer_index) && (*rx_cleaned < work_to_do)) {
+		qdev->rsp_consumer_index) && (work_done < work_to_do)) {
 
 		net_rsp = qdev->rsp_current;
 		switch (net_rsp->opcode) {
@@ -1993,37 +1994,41 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev,
 		} else {
 			qdev->rsp_current++;
 		}
+
+		work_done = *tx_cleaned + *rx_cleaned;
 	}
 
-	spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+	if(work_done) {
+		spin_lock_irqsave(&qdev->hw_lock, hw_flags);
 
-	ql_update_lrg_bufq_prod_index(qdev);
+		ql_update_lrg_bufq_prod_index(qdev);
 
-	if (qdev->small_buf_release_cnt >= 16) {
-		while (qdev->small_buf_release_cnt >= 16) {
-			qdev->small_buf_q_producer_index++;
+		if (qdev->small_buf_release_cnt >= 16) {
+			while (qdev->small_buf_release_cnt >= 16) {
+				qdev->small_buf_q_producer_index++;
 
-			if (qdev->small_buf_q_producer_index ==
-			    NUM_SBUFQ_ENTRIES)
-				qdev->small_buf_q_producer_index = 0;
-			qdev->small_buf_release_cnt -= 8;
-		}
+				if (qdev->small_buf_q_producer_index ==
+				    NUM_SBUFQ_ENTRIES)
+					qdev->small_buf_q_producer_index = 0;
+				qdev->small_buf_release_cnt -= 8;
+			}
 
-		ql_write_common_reg(qdev,
-				    &port_regs->CommonRegs.
-				    rxSmallQProducerIndex,
-				    qdev->small_buf_q_producer_index);
-	}
+			wmb();
+			ql_write_common_reg(qdev,
+					    &port_regs->CommonRegs.
+					    rxSmallQProducerIndex,
+					    qdev->small_buf_q_producer_index);
 
-	ql_write_common_reg(qdev,
-			    &port_regs->CommonRegs.rspQConsumerIndex,
-			    qdev->rsp_consumer_index);
-	spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+		}
 
-	if (unlikely(netif_queue_stopped(qdev->ndev))) {
-		if (netif_queue_stopped(qdev->ndev) &&
-		    (atomic_read(&qdev->tx_count) > (NUM_REQ_Q_ENTRIES / 4)))
-			netif_wake_queue(qdev->ndev);
+		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
+		if (unlikely(netif_queue_stopped(qdev->ndev))) {
+			if (netif_queue_stopped(qdev->ndev) &&
+			    (atomic_read(&qdev->tx_count) > 
+			     (NUM_REQ_Q_ENTRIES / 4)))
+				netif_wake_queue(qdev->ndev);
+		}
 	}
 
 	return *tx_cleaned + *rx_cleaned;
@@ -2034,6 +2039,8 @@ static int ql_poll(struct net_device *ndev, int *budget)
 	struct ql3_adapter *qdev = netdev_priv(ndev);
 	int work_to_do = min(*budget, ndev->quota);
 	int rx_cleaned = 0, tx_cleaned = 0;
+	unsigned long hw_flags;
+	struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
 
 	if (!netif_carrier_ok(ndev))
 		goto quit_polling;
@@ -2045,6 +2052,13 @@ static int ql_poll(struct net_device *ndev, int *budget)
 	if ((!tx_cleaned && !rx_cleaned) || !netif_running(ndev)) {
 quit_polling:
 		netif_rx_complete(ndev);
+
+		spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+		ql_write_common_reg(qdev,
+				    &port_regs->CommonRegs.rspQConsumerIndex,
+				    qdev->rsp_consumer_index);
+		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
+
 		ql_enable_interrupts(qdev);
 		return 0;
 	}
@@ -2097,11 +2111,10 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id)
 		queue_delayed_work(qdev->workqueue, &qdev->reset_work, 0);
 		spin_unlock(&qdev->adapter_lock);
 	} else if (value & ISP_IMR_DISABLE_CMPL_INT) {
-		ql_disable_interrupts(qdev);
-		if (likely(netif_rx_schedule_prep(ndev)))
+		if (likely(netif_rx_schedule_prep(ndev))) {
+			ql_disable_interrupts(qdev);
 			__netif_rx_schedule(ndev);
-		else
-			ql_enable_interrupts(qdev);
+		}
 	} else {
 		return IRQ_NONE;
 	}
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 12/13] qla3xxx: Kernic Panic on pSeries under stress conditions
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
                   ` (10 preceding siblings ...)
  2007-02-26 19:06 ` [PATCH 11/13] qla3xxx: bugfix tx reset after stress conditions Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  2007-02-26 19:06 ` [PATCH 13/13] qla3xxx: Bumping driver version number Ron Mercer
  12 siblings, 0 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

From: Benjamin Li <benjamin.li@qlogic.com>

To reproduce this panic consistently, we run an intensive network
application like 'netperf'. After waiting for a couple of seconds,
you will see a stack trace and a kernel panic where we are calling
pci_unmap_single() in ql_poll().

Changes:
1)  Check the flags on the Response MAC IO Control block to check for
errors
2)  Ensure that if we are on the 4022 we only use one segment
3)  Before, we were reading the memory mapped producer index register
everytime we iterated in the loop when clearing the queue.  We should
only be iterating to a known point, not as the producer index
is being updated.

Signed-off-by: Benjamin Li <benjamin.li@qlogic.com>
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |   64 +++++++++++++++++++++++++++++++++++-------------
 drivers/net/qla3xxx.h |    2 +-
 2 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 524a9a6..f446232 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -1765,8 +1765,31 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
 {
 	struct ql_tx_buf_cb *tx_cb;
 	int i;
+	int retval = 0;
 
+	if(mac_rsp->flags & OB_MAC_IOCB_RSP_S) {
+		printk(KERN_WARNING "Frame short but, frame was padded and sent.\n");
+	}
+	
 	tx_cb = &qdev->tx_buf[mac_rsp->transaction_id];
+
+	/*  Check the transmit response flags for any errors */
+	if(mac_rsp->flags & OB_MAC_IOCB_RSP_S) {
+		printk(KERN_ERR "Frame too short to be legal, frame not sent.\n");
+
+		qdev->stats.tx_errors++;
+		retval = -EIO;
+		goto frame_not_sent;
+	}
+
+	if(tx_cb->seg_count == 0) {
+		printk(KERN_ERR "tx_cb->seg_count == 0: %d\n", mac_rsp->transaction_id);
+
+		qdev->stats.tx_errors++;
+		retval = -EIO;
+		goto invalid_seg_count;
+	}
+
 	pci_unmap_single(qdev->pdev,
 			 pci_unmap_addr(&tx_cb->map[0], mapaddr),
 			 pci_unmap_len(&tx_cb->map[0], maplen),
@@ -1783,8 +1806,12 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
 	}
 	qdev->stats.tx_packets++;
 	qdev->stats.tx_bytes += tx_cb->skb->len;
+
+frame_not_sent:
 	dev_kfree_skb_irq(tx_cb->skb);
 	tx_cb->skb = NULL;
+
+invalid_seg_count:
 	atomic_inc(&qdev->tx_count);
 }
 
@@ -1941,8 +1968,10 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev,
 	unsigned long hw_flags;
 	int work_done = 0;
 
+	u32 rsp_producer_index = le32_to_cpu(*(qdev->prsp_producer_index));
+
 	/* While there are entries in the completion queue. */
-	while ((cpu_to_le32(*(qdev->prsp_producer_index)) !=
+	while ((rsp_producer_index !=
 		qdev->rsp_consumer_index) && (work_done < work_to_do)) {
 
 		net_rsp = qdev->rsp_current;
@@ -2022,13 +2051,6 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev,
 		}
 
 		spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
-
-		if (unlikely(netif_queue_stopped(qdev->ndev))) {
-			if (netif_queue_stopped(qdev->ndev) &&
-			    (atomic_read(&qdev->tx_count) > 
-			     (NUM_REQ_Q_ENTRIES / 4)))
-				netif_wake_queue(qdev->ndev);
-		}
 	}
 
 	return *tx_cleaned + *rx_cleaned;
@@ -2049,7 +2071,8 @@ static int ql_poll(struct net_device *ndev, int *budget)
 	*budget -= rx_cleaned;
 	ndev->quota -= rx_cleaned;
 
-	if ((!tx_cleaned && !rx_cleaned) || !netif_running(ndev)) {
+	if( tx_cleaned + rx_cleaned != work_to_do ||
+	    !netif_running(ndev)) {
 quit_polling:
 		netif_rx_complete(ndev);
 
@@ -2111,8 +2134,8 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id)
 		queue_delayed_work(qdev->workqueue, &qdev->reset_work, 0);
 		spin_unlock(&qdev->adapter_lock);
 	} else if (value & ISP_IMR_DISABLE_CMPL_INT) {
+		ql_disable_interrupts(qdev);
 		if (likely(netif_rx_schedule_prep(ndev))) {
-			ql_disable_interrupts(qdev);
 			__netif_rx_schedule(ndev);
 		}
 	} else {
@@ -2131,8 +2154,12 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id)
  * the next AOL if more frags are coming.  
  * That is why the frags:segment count  ratio is not linear.
  */
-static int ql_get_seg_count(unsigned short frags)
+static int ql_get_seg_count(struct ql3_adapter *qdev,
+			    unsigned short frags)
 {
+	if (qdev->device_id == QL3022_DEVICE_ID)
+		return 1;
+
 	switch(frags) {
 	case 0:	return 1;	/* just the skb->data seg */
 	case 1:	return 2;	/* skb->data + 1 frag */
@@ -2201,14 +2228,15 @@ static int ql_send_map(struct ql3_adapter *qdev,
 {
 	struct oal *oal;
 	struct oal_entry *oal_entry;
-	int len = skb_headlen(skb);
+	int len = skb->len;
 	dma_addr_t map;
 	int err;
 	int completed_segs, i;
 	int seg_cnt, seg = 0;
 	int frag_cnt = (int)skb_shinfo(skb)->nr_frags;
 
-	seg_cnt = tx_cb->seg_count = ql_get_seg_count((skb_shinfo(skb)->nr_frags));
+	seg_cnt = tx_cb->seg_count = ql_get_seg_count(qdev,
+						      (skb_shinfo(skb)->nr_frags));
 	if(seg_cnt == -1) {
 		printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__);
 		return NETDEV_TX_BUSY;
@@ -2234,7 +2262,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
 	pci_unmap_len_set(&tx_cb->map[seg], maplen, len);
 	seg++;
 
-	if (!skb_shinfo(skb)->nr_frags) {
+	if (seg_cnt == 1) {
 		/* Terminate the last segment. */
 		oal_entry->len =
 		    cpu_to_le32(le32_to_cpu(oal_entry->len) | OAL_LAST_ENTRY);
@@ -2359,13 +2387,12 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
 	struct ob_mac_iocb_req *mac_iocb_ptr;
 
 	if (unlikely(atomic_read(&qdev->tx_count) < 2)) {
-		if (!netif_queue_stopped(ndev))
-			netif_stop_queue(ndev);
 		return NETDEV_TX_BUSY;
 	}
 	
 	tx_cb = &qdev->tx_buf[qdev->req_producer_index] ;
-	if((tx_cb->seg_count = ql_get_seg_count((skb_shinfo(skb)->nr_frags))) == -1) {
+	if((tx_cb->seg_count = ql_get_seg_count(qdev,
+						(skb_shinfo(skb)->nr_frags))) == -1) {
 		printk(KERN_ERR PFX"%s: invalid segment count!\n",__func__);
 		return NETDEV_TX_OK;
 	}
@@ -2377,7 +2404,8 @@ static int ql3xxx_send(struct sk_buff *skb, struct net_device *ndev)
 	mac_iocb_ptr->transaction_id = qdev->req_producer_index;
 	mac_iocb_ptr->data_len = cpu_to_le16((u16) tot_len);
 	tx_cb->skb = skb;
-	if (skb->ip_summed == CHECKSUM_PARTIAL)
+	if (qdev->device_id == QL3032_DEVICE_ID &&
+	    skb->ip_summed == CHECKSUM_PARTIAL)
 		ql_hw_csum_setup(skb, mac_iocb_ptr);
 	
 	if(ql_send_map(qdev,mac_iocb_ptr,tx_cb,skb) != NETDEV_TX_OK) {
diff --git a/drivers/net/qla3xxx.h b/drivers/net/qla3xxx.h
index 40913d2..34cd658 100755
--- a/drivers/net/qla3xxx.h
+++ b/drivers/net/qla3xxx.h
@@ -1194,7 +1194,7 @@ struct ql3_adapter {
 	struct net_rsp_iocb *rsp_current;
 	u16 rsp_consumer_index;
 	u16 reserved_06;
-	u32 *prsp_producer_index;
+	volatile u32 *prsp_producer_index;
 	u32 rsp_producer_index_phy_addr_high;
 	u32 rsp_producer_index_phy_addr_low;
 
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 13/13] qla3xxx: Bumping driver version number
  2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
                   ` (11 preceding siblings ...)
  2007-02-26 19:06 ` [PATCH 12/13] qla3xxx: Kernic Panic on pSeries under " Ron Mercer
@ 2007-02-26 19:06 ` Ron Mercer
  12 siblings, 0 replies; 17+ messages in thread
From: Ron Mercer @ 2007-02-26 19:06 UTC (permalink / raw)
  To: jeff; +Cc: ron.mercer, romieu, benjamin.li, netdev

From: Benjamin Li <benjamin.li@qlogic.com>

Signed-off-by: Benjamin Li <benjamin.li@qlogic.com>
Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index f446232..15f1371 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -39,7 +39,7 @@
 
 #define DRV_NAME  	"qla3xxx"
 #define DRV_STRING 	"QLogic ISP3XXX Network Driver"
-#define DRV_VERSION	"v2.02.00-k36"
+#define DRV_VERSION	"v2.03.00-k3"
 #define PFX		DRV_NAME " "
 
 static const char ql3xxx_driver_name[] = DRV_NAME;
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH 01/13] qla3xxx: Return proper error codes when the 4022/4032 is being probed
  2007-02-26 19:06 ` [PATCH 01/13] qla3xxx: Return proper error codes when the 4022/4032 is being probed Ron Mercer
@ 2007-02-27  9:22   ` Jeff Garzik
  2007-03-01  0:48     ` [PATCH] qla3xxx: bugfix for line omitted in previous patch Ron Mercer
  0 siblings, 1 reply; 17+ messages in thread
From: Jeff Garzik @ 2007-02-27  9:22 UTC (permalink / raw)
  To: Ron Mercer; +Cc: romieu, benjamin.li, netdev

Ron Mercer wrote:
> From: Benjamin Li <benjamin.li@qlogic.com>
> 
> The return code was not properly set when when allocating memory or mapping
> memory failed.  Depending on the stack, the return code would sometimes
> return 0, which indicates everything was ok, when in fact there was an error.
>   This would cause trouble when the module was removed.  Now, we will pass
> back the proper return code when an error occurs during the PCI probe.
> 
> Signed-off-by: Benjamin Li <benjamin.li@qlogic.com>
> Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
> ---
>  drivers/net/qla3xxx.c |    8 +++++++-
>  1 files changed, 7 insertions(+), 1 deletions(-)

applied 1-13



^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH] qla3xxx: bugfix for line omitted in previous patch.
  2007-02-27  9:22   ` Jeff Garzik
@ 2007-03-01  0:48     ` Ron Mercer
  2007-03-03  1:17       ` Jeff Garzik
  0 siblings, 1 reply; 17+ messages in thread
From: Ron Mercer @ 2007-03-01  0:48 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: netdev, ron.mercer, benjamin.li


>From 01751a39d7327acc28dabf4f68930b7e20b279d1 Mon Sep 17 00:00:00 2001
From: Ron Mercer <ron.mercer@qlogic.com>
Date: Wed, 28 Feb 2007 16:42:17 -0800
Subject: [PATCH] [PATCH] qla3xxx: bugfix for line omitted in previous patch.

This missing line caused transmit errors on the Qlogic 4032 chip.

Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>
---
 drivers/net/qla3xxx.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 3a14d19..d3f65da 100755
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2210,7 +2210,7 @@ static int ql_send_map(struct ql3_adapter *qdev,
 {
 	struct oal *oal;
 	struct oal_entry *oal_entry;
-	int len = skb->len;
+	int len = skb_headlen(skb);
 	dma_addr_t map;
 	int err;
 	int completed_segs, i;
-- 
1.5.0.rc4.16.g9e258


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH] qla3xxx: bugfix for line omitted in previous patch.
  2007-03-01  0:48     ` [PATCH] qla3xxx: bugfix for line omitted in previous patch Ron Mercer
@ 2007-03-03  1:17       ` Jeff Garzik
  0 siblings, 0 replies; 17+ messages in thread
From: Jeff Garzik @ 2007-03-03  1:17 UTC (permalink / raw)
  To: Jeff Garzik, netdev, benjamin.li

Ron Mercer wrote:
>>From 01751a39d7327acc28dabf4f68930b7e20b279d1 Mon Sep 17 00:00:00 2001
> From: Ron Mercer <ron.mercer@qlogic.com>
> Date: Wed, 28 Feb 2007 16:42:17 -0800
> Subject: [PATCH] [PATCH] qla3xxx: bugfix for line omitted in previous patch.
> 
> This missing line caused transmit errors on the Qlogic 4032 chip.
> 
> Signed-off-by: Ron Mercer <ron.mercer@qlogic.com>

applied



^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2007-03-03  1:17 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-26 19:04 [PATCH 0/13] qla3xxx: bugfixes and cleanup after IBM/Redhat testing Ron Mercer
2007-02-26 19:06 ` [PATCH 01/13] qla3xxx: Return proper error codes when the 4022/4032 is being probed Ron Mercer
2007-02-27  9:22   ` Jeff Garzik
2007-03-01  0:48     ` [PATCH] qla3xxx: bugfix for line omitted in previous patch Ron Mercer
2007-03-03  1:17       ` Jeff Garzik
2007-02-26 19:06 ` [PATCH 02/13] qla3xxx: Remove unnecessary memset() in qla3xxx_send() Ron Mercer
2007-02-26 19:06 ` [PATCH 03/13] qla3xxx: Changed to use netdev_alloc_skb() from dev_alloc_skb Ron Mercer
2007-02-26 19:06 ` [PATCH 04/13] qla3xxx: Add ethtool functionality to report pause parameters Ron Mercer
2007-02-26 19:06 ` [PATCH 05/13] qla3xxx: Fix deadlock issue on error paths Ron Mercer
2007-02-26 19:06 ` [PATCH 06/13] qla3xxx: Remove API to change MTU Ron Mercer
2007-02-26 19:06 ` [PATCH 07/13] qla3xxx: Dynamically size the rx buffer queue based on the MTU Ron Mercer
2007-02-26 19:06 ` [PATCH 08/13] qla3xxx: Clean up receive process Ron Mercer
2007-02-26 19:06 ` [PATCH 09/13] qla3xxx: bugfix: Fixed jumbo frame handling for 3032 chip Ron Mercer
2007-02-26 19:06 ` [PATCH 10/13] qla3xxx: Check return code from pci_map_single() in ql_release_to_lrg_buf_free_list(), ql_populate_free_queue(), ql_alloc_large_buffers(), and ql3xxx_send() Ron Mercer
2007-02-26 19:06 ` [PATCH 11/13] qla3xxx: bugfix tx reset after stress conditions Ron Mercer
2007-02-26 19:06 ` [PATCH 12/13] qla3xxx: Kernic Panic on pSeries under " Ron Mercer
2007-02-26 19:06 ` [PATCH 13/13] qla3xxx: Bumping driver version number Ron Mercer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.