Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2623

kernel-2.6.18-238.el5.src.rpm

From: Andy Gospodarek <gospo@redhat.com>
Date: Fri, 20 Feb 2009 17:42:56 -0500
Subject: [net] enic: upstream update to version 1.0.0.933
Message-id: 20090220224256.GS12660@gospo.rdu.redhat.com
O-Subject: Re: [RHEL5.4 PATCH REPOST] enic: upstream update to version 1.0.0.933
Bugzilla: 484824
RH-Acked-by: David Miller <davem@redhat.com>
RH-Acked-by: Neil Horman <nhorman@redhat.com>

Several updates to the enic driver are needed for 5.4.  These changes
were requested by the hardware vendor as they correct several important
issues.  These changes are from the following four upstream commits:

    commit ed8af6b288c0643dfe0ad91f1bfc8c56c0d307cc
    Author: Scott Feldman <scofeldm@cisco.com>
    Date:   Mon Feb 9 23:23:50 2009 -0800

        enic: bug fix: return notify intr credits

        Return notify intr credits after notify intr from firmware.  This is
        especially important for legacy PCI intr mode, where not returning
        credits would cause PBA to remain asserted which would get us right
        back into the ISR.

    commit 4cdc44a231f906a6ec586637e6e4c4c216679da4
    Author: Scott Feldman <scofeldm@cisco.com>
    Date:   Mon Feb 9 23:25:33 2009 -0800

        enic: Add api for link down count and to get firmware notification status.

    commit 68f717089a62ee4c51933f4be43e4ef7b31539fd
    Author: Scott Feldman <scofeldm@cisco.com>
    Date:   Mon Feb 9 23:24:24 2009 -0800

        enic: bug fix: tx_timeout reset path fix-ups

        tx_timeout reset path needs to re-init dev and re-apply nic cfg to
        enable vlan stripping.

    commit bd9fb1a44a5c52a1c322ebacd08f6b7416a40a86
    Author: Scott Feldman <scofeldm@cisco.com>
    Date:   Mon Feb 9 23:24:08 2009 -0800

        enic: record all bad FCS errs as frame errors

        Report all bad FCS errs as frames errs.  This includes frames with bad
        FCS on wire detected by MAC and frames which may be truncated due to
        ingress FIFO overruns.  No longer print a driver msg on bad FCS err.

This will resolve the request in RHBZ 484824.

diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index df8b131..4becad6 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -34,7 +34,7 @@
 
 #define DRV_NAME		"enic"
 #define DRV_DESCRIPTION		"Cisco 10G Ethernet Driver"
-#define DRV_VERSION		"1.0.0.648"
+#define DRV_VERSION		"1.0.0.933"
 #define DRV_COPYRIGHT		"Copyright 2008 Cisco Systems, Inc"
 #define PFX			DRV_NAME ": "
 
@@ -99,6 +99,8 @@ struct enic {
 	____cacheline_aligned struct vnic_rq rq[1];
 	unsigned int rq_count;
 	int (*rq_alloc_buf)(struct vnic_rq *rq);
+	u64 rq_bad_fcs;
+
 	struct net_lro_mgr lro_mgr;
 	struct net_lro_desc lro_desc[ENIC_LRO_MAX_DESC];
 
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index e458cfa..a46da0a 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -397,10 +397,13 @@ static irqreturn_t enic_isr_legacy(int irq, void *data, struct pt_regs *regs)
 		return IRQ_NONE;	/* not our interrupt */
 	}
 
-	if (ENIC_TEST_INTR(pba, ENIC_INTX_NOTIFY))
+	if (ENIC_TEST_INTR(pba, ENIC_INTX_NOTIFY)) {
+		vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_NOTIFY]);
 		enic_notify_check(enic);
+	}
 
 	if (ENIC_TEST_INTR(pba, ENIC_INTX_ERR)) {
+		vnic_intr_return_all_credits(&enic->intr[ENIC_INTX_ERR]);
 		enic_log_q_error(enic);
 		/* schedule recovery from WQ/RQ error */
 		schedule_work(&enic->reset);
@@ -473,6 +476,8 @@ static irqreturn_t enic_isr_msix_err(int irq, void *data, struct pt_regs *regs)
 {
 	struct enic *enic = data;
 
+	vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_ERR]);
+
 	enic_log_q_error(enic);
 
 	/* schedule recovery from WQ/RQ error */
@@ -485,8 +490,8 @@ static irqreturn_t enic_isr_msix_notify(int irq, void *data, struct pt_regs *reg
 {
 	struct enic *enic = data;
 
+	vnic_intr_return_all_credits(&enic->intr[ENIC_MSIX_NOTIFY]);
 	enic_notify_check(enic);
-	vnic_intr_unmask(&enic->intr[ENIC_MSIX_NOTIFY]);
 
 	return IRQ_HANDLED;
 }
@@ -613,7 +618,7 @@ static inline void enic_queue_wq_skb(struct enic *enic,
 			vlan_tag_insert, vlan_tag);
 }
 
-/* netif_tx_lock held, process context with BHs disabled */
+/* netif_tx_lock held, process context with BHs disabled, or BH */
 static int enic_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
 	struct enic *enic = netdev_priv(netdev);
@@ -679,7 +684,7 @@ static struct net_device_stats *enic_get_stats(struct net_device *netdev)
 	enic->net_stats.rx_bytes = stats->rx.rx_bytes_ok;
 	enic->net_stats.rx_errors = stats->rx.rx_errors;
 	enic->net_stats.multicast = stats->rx.rx_multicast_frames_ok;
-	enic->net_stats.rx_crc_errors = stats->rx.rx_crc_errors;
+	enic->net_stats.rx_crc_errors = enic->rq_bad_fcs;
 	enic->net_stats.rx_dropped = stats->rx.rx_no_bufs;
 
 	return &enic->net_stats;
@@ -924,12 +929,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
 
 	if (packet_error) {
 
-		if (bytes_written > 0 && !fcs_ok) {
-			if (net_ratelimit())
-				printk(KERN_ERR PFX
-					"%s: packet error: bad FCS\n",
-					netdev->name);
-		}
+		if (bytes_written > 0 && !fcs_ok)
+			enic->rq_bad_fcs++;
 
 		dev_kfree_skb_any(skb);
 
@@ -1065,7 +1066,7 @@ static int enic_poll(struct net_device *netdev, int *budget)
 			lro_flush_all(&enic->lro_mgr);
 
 		netif_rx_complete(netdev);
-		vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]);
+		vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]);
 		return 0;
 	}
 
@@ -1091,9 +1092,9 @@ static int enic_poll_msix(struct net_device *netdev, int *budget)
 
 		vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
 
-		/* Accumulate intr event credits for this polling
+		/* Return intr event credits for this polling
 		 * cycle.  An intr event is the completion of a
-		 * a WQ or RQ packet.
+		 * RQ packet.
 		 */
 
 		vnic_intr_return_credits(&enic->intr[ENIC_MSIX_RQ],
@@ -1458,6 +1459,26 @@ static int enic_dev_soft_reset(struct enic *enic)
 	return err;
 }
 
+static int enic_set_niccfg(struct enic *enic)
+{
+	const u8 rss_default_cpu = 0;
+	const u8 rss_hash_type = 0;
+	const u8 rss_hash_bits = 0;
+	const u8 rss_base_cpu = 0;
+	const u8 rss_enable = 0;
+	const u8 tso_ipid_split_en = 0;
+	const u8 ig_vlan_strip_en = 1;
+
+	/* Enable VLAN tag stripping.  RSS not enabled (yet).
+	*/
+
+	return enic_set_nic_cfg(enic,
+		rss_default_cpu, rss_hash_type,
+		rss_hash_bits, rss_base_cpu,
+		rss_enable, tso_ipid_split_en,
+		ig_vlan_strip_en);
+}
+
 static void enic_reset(struct enic *enic)
 {
 	if (!netif_running(enic->netdev))
@@ -1471,8 +1492,10 @@ static void enic_reset(struct enic *enic)
 
 	enic_stop(enic->netdev);
 	enic_dev_soft_reset(enic);
+	vnic_dev_init(enic->vdev, 0);
 	enic_reset_mcaddrs(enic);
 	enic_init_vnic_resources(enic);
+	enic_set_niccfg(enic);
 	enic_open(enic->netdev);
 
 	rtnl_unlock();
@@ -1597,14 +1620,6 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 	unsigned int i;
 	int err;
 
-	const u8 rss_default_cpu = 0;
-	const u8 rss_hash_type = 0;
-	const u8 rss_hash_bits = 0;
-	const u8 rss_base_cpu = 0;
-	const u8 rss_enable = 0;
-	const u8 tso_ipid_split_en = 0;
-	const u8 ig_vlan_strip_en = 1;
-
 	/* Allocate net device structure and initialize.  Private
 	 * instance data is initialized to zero.
 	 */
@@ -1775,14 +1790,7 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 
 	enic_init_vnic_resources(enic);
 
-	/* Enable VLAN tag stripping.  RSS not enabled (yet).
-	 */
-
-	err = enic_set_nic_cfg(enic,
-		rss_default_cpu, rss_hash_type,
-		rss_hash_bits, rss_base_cpu,
-		rss_enable, tso_ipid_split_en,
-		ig_vlan_strip_en);
+	err = enic_set_niccfg(enic);
 	if (err) {
 		printk(KERN_ERR PFX
 			"Failed to config nic, aborting.\n");
@@ -1851,7 +1859,6 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 	if (using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
-
 	enic->csum_rx_enabled = ENIC_SETTING(enic, RXCSUM);
 
 	if (ENIC_SETTING(enic, LRO)) {
@@ -1864,7 +1871,6 @@ static int __devinit enic_probe(struct pci_dev *pdev,
 		enic->lro_mgr.ip_summed = CHECKSUM_COMPLETE;
 		enic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
 	}
-
 	err = register_netdev(netdev);
 	if (err) {
 		printk(KERN_ERR PFX
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 4a537d1..679e25e 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -34,6 +34,9 @@ struct vnic_res {
 	unsigned int count;
 };
 
+#define VNIC_DEV_CAP_INIT	0x0001
+#define VNIC_DEV_CAP_PERBI	0x0002
+
 struct vnic_dev {
 	void *priv;
 	struct pci_dev *pdev;
@@ -50,6 +53,7 @@ struct vnic_dev {
 	dma_addr_t stats_pa;
 	struct vnic_devcmd_fw_info *fw_info;
 	dma_addr_t fw_info_pa;
+	u32 cap_flags;
 };
 
 #define VNIC_MAX_RES_HDR_SIZE \
@@ -581,9 +585,9 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg)
 {
 	u64 a0 = (u32)arg, a1 = 0;
 	int wait = 1000;
-        int r = 0;
+	int r = 0;
 
-	if (vnic_dev_capable(vdev, CMD_INIT))
+	if (vdev->cap_flags & VNIC_DEV_CAP_INIT)
 		r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
 	else {
 		vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait);
@@ -593,8 +597,8 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg)
 			vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
 			vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
 		}
-        }
-        return r;
+	}
+	return r;
 }
 
 int vnic_dev_link_status(struct vnic_dev *vdev)
@@ -632,6 +636,22 @@ u32 vnic_dev_mtu(struct vnic_dev *vdev)
 	return vdev->notify_copy.mtu;
 }
 
+u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev)
+{
+	if (!vnic_dev_notify_ready(vdev))
+		return 0;
+
+	return vdev->notify_copy.link_down_cnt;
+}
+
+u32 vnic_dev_notify_status(struct vnic_dev *vdev)
+{
+	if (!vnic_dev_notify_ready(vdev))
+		return 0;
+
+	return vdev->notify_copy.status;
+}
+
 void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
 	enum vnic_dev_intr_mode intr_mode)
 {
@@ -688,6 +708,11 @@ struct vnic_dev *vnic_dev_register(struct vnic_dev *vdev,
 	if (!vdev->devcmd)
 		goto err_out;
 
+	vdev->cap_flags = 0;
+
+	if (vnic_dev_capable(vdev, CMD_INIT))
+		vdev->cap_flags |= VNIC_DEV_CAP_INIT;
+
 	return vdev;
 
 err_out:
diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h
index c0e3424..5d878eb 100644
--- a/drivers/net/enic/vnic_dev.h
+++ b/drivers/net/enic/vnic_dev.h
@@ -89,6 +89,8 @@ int vnic_dev_link_status(struct vnic_dev *vdev);
 u32 vnic_dev_port_speed(struct vnic_dev *vdev);
 u32 vnic_dev_msg_lvl(struct vnic_dev *vdev);
 u32 vnic_dev_mtu(struct vnic_dev *vdev);
+u32 vnic_dev_link_down_cnt(struct vnic_dev *vdev);
+u32 vnic_dev_notify_status(struct vnic_dev *vdev);
 int vnic_dev_close(struct vnic_dev *vdev);
 int vnic_dev_enable(struct vnic_dev *vdev);
 int vnic_dev_disable(struct vnic_dev *vdev);
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h
index 8062c75..2587f34 100644
--- a/drivers/net/enic/vnic_devcmd.h
+++ b/drivers/net/enic/vnic_devcmd.h
@@ -191,7 +191,7 @@ enum vnic_devcmd_cmd {
 	CMD_INIT_STATUS		= _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 31),
 
 	/* INT13 API: (u64)a0=paddr to vnic_int13_params struct
-	 *            (u8)a1=INT13_CMD_xxx */
+	 *            (u32)a1=INT13_CMD_xxx */
 	CMD_INT13               = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_FC, 32),
 
 	/* logical uplink enable/disable: (u64)a0: 0/1=disable/enable */
@@ -207,6 +207,11 @@ enum vnic_devcmd_cmd {
 	 * in:  (u32)a0=cmd
 	 * out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */
 	CMD_CAPABILITY		= _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36),
+
+	/* persistent binding info
+	 * in:  (u64)a0=paddr of arg
+	 *      (u32)a1=CMD_PERBI_XXX */
+	CMD_PERBI               = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_FC, 37),
 };
 
 /* flags for CMD_OPEN */
@@ -259,6 +264,7 @@ struct vnic_devcmd_notify {
 	u32 status;		/* status bits (see VNIC_STF_*) */
 	u32 error;		/* error code (see ERR_*) for first ERR */
 	u32 link_down_cnt;	/* running count of link down transitions */
+	u32 perbi_rebuild_cnt;	/* running count of perbi rebuilds */
 };
 #define VNIC_STF_FATAL_ERR	0x0001	/* fatal fw error */
 #define VNIC_STF_STD_PAUSE	0x0002	/* standard link-level pause on */
diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/enic/vnic_intr.h
index ce633a5..9a53604 100644
--- a/drivers/net/enic/vnic_intr.h
+++ b/drivers/net/enic/vnic_intr.h
@@ -76,6 +76,20 @@ static inline void vnic_intr_return_credits(struct vnic_intr *intr,
 	iowrite32(int_credit_return, &intr->ctrl->int_credit_return);
 }
 
+static inline unsigned int vnic_intr_credits(struct vnic_intr *intr)
+{
+	return ioread32(&intr->ctrl->int_credits);
+}
+
+static inline void vnic_intr_return_all_credits(struct vnic_intr *intr)
+{
+	unsigned int credits = vnic_intr_credits(intr);
+	int unmask = 1;
+	int reset_timer = 1;
+
+	vnic_intr_return_credits(intr, credits, unmask, reset_timer);
+}
+
 static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba)
 {
 	/* read PBA without clearing */