Sophie

Sophie

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

kernel-2.6.18-238.el5.src.rpm

From: Mike Christie <mchristi@redhat.com>
Date: Wed, 20 Jan 2010 04:22:15 -0500
Subject: [net] cnic: additional fixes for rhel5.5 update
Message-id: <1263961336-12311-1-git-send-email-mchristi@redhat.com>
Patchwork-id: 22666
O-Subject: [RHEL 5.5 PATCH 1/2] Update cnic driver
Bugzilla: 517378
RH-Acked-by: Stanislaw Gruszka <sgruszka@redhat.com>

From: Mike Christie <mchristi@redhat.com>

This is for BZ 517378.

This patch brings in the upstream commits:

    commit 3248e1682035eef6774c280cd7be19984feb78bb
    Author: Michael Chan <mchan@broadcom.com>
    Date:   Wed Dec 2 15:15:39 2009 +0000

        cnic: Use dma_alloc_coherent().

    commit 15971c3ce3caf9a92b603a61b07e0be8c9b9d276
    Author: Michael Chan <mchan@broadcom.com>
    Date:   Wed Dec 2 15:15:38 2009 +0000

        cnic: Fix rq_page_table DMA address.

    commit dd2e4dbce32a2802088f6d0132046afec9bfb2ad
    Author: Michael Chan <mchan@broadcom.com>
    Date:   Wed Dec 2 15:15:37 2009 +0000

        cnic: Fix bogus iSCSI MAC address

    commit 8b065b671d3096bfe0dbc9a833cb592f84642436
    Author: Michael Chan <mchan@broadcom.com>
    Date:   Wed Dec 2 15:15:36 2009 +0000

        cnic: Fix bnx2x ring shutdown.

    commit c7596b79feb3d15bea64007254f77233bda811f4
    Author: Michael Chan <mchan@broadcom.com>
    Date:   Wed Dec 2 15:15:35 2009 +0000

        cnic: Fix ring I/O address for bnx2x devices.

    commit 164165dad7e607ec359e64b6fae72abbf3640ea6
    Author: Joe Perches <joe@perches.com>
    Date:   Thu Nov 19 09:30:10 2009 +0000

        drivers/net: tasklet_init - Remove unnecessary leading & from
second arg

    commit 0d37f36ff9bc41067c71635d14b6a5834853a779
    Author: roel kluin <roel.kluin@gmail.com>
    Date:   Mon Nov 2 06:53:44 2009 +0000

        cnic: ensure ulp_type is not negative

I have tested the patch by creating/deleting sessions and
running IO with bnx2/cnic/bnx2i, and I did some tests
with bringing down interfaces and rmmoding modules to make
sure we could recover. I was not able to test
bnx2x/cnic/bnx2i, because I do not have access to that card.

Broadcom is doing most of the QE on this. It has passed all of
their internal testing.

diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 910b48f..fe15469 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -409,7 +409,7 @@ int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops)
 {
 	struct cnic_dev *dev;
 
-	if (ulp_type >= MAX_CNIC_ULP_TYPE) {
+	if (ulp_type < 0 || ulp_type >= MAX_CNIC_ULP_TYPE) {
 		printk(KERN_ERR PFX "cnic_register_driver: Bad type %d\n",
 		       ulp_type);
 		return -EINVAL;
@@ -455,7 +455,7 @@ int cnic_unregister_driver(int ulp_type)
 	struct cnic_ulp_ops *ulp_ops;
 	int i = 0;
 
-	if (ulp_type >= MAX_CNIC_ULP_TYPE) {
+	if (ulp_type < 0 || ulp_type >= MAX_CNIC_ULP_TYPE) {
 		printk(KERN_ERR PFX "cnic_unregister_driver: Bad type %d\n",
 		       ulp_type);
 		return -EINVAL;
@@ -511,7 +511,7 @@ static int cnic_register_device(struct cnic_dev *dev, int ulp_type,
 	struct cnic_local *cp = dev->cnic_priv;
 	struct cnic_ulp_ops *ulp_ops;
 
-	if (ulp_type >= MAX_CNIC_ULP_TYPE) {
+	if (ulp_type < 0 || ulp_type >= MAX_CNIC_ULP_TYPE) {
 		printk(KERN_ERR PFX "cnic_register_device: Bad type %d\n",
 		       ulp_type);
 		return -EINVAL;
@@ -552,7 +552,7 @@ static int cnic_unregister_device(struct cnic_dev *dev, int ulp_type)
 	struct cnic_local *cp = dev->cnic_priv;
 	int i = 0;
 
-	if (ulp_type >= MAX_CNIC_ULP_TYPE) {
+	if (ulp_type < 0 || ulp_type >= MAX_CNIC_ULP_TYPE) {
 		printk(KERN_ERR PFX "cnic_unregister_device: Bad type %d\n",
 		       ulp_type);
 		return -EINVAL;
@@ -668,14 +668,14 @@ static void cnic_free_dma(struct cnic_dev *dev, struct cnic_dma *dma)
 
 	for (i = 0; i < dma->num_pages; i++) {
 		if (dma->pg_arr[i]) {
-			pci_free_consistent(dev->pcidev, BCM_PAGE_SIZE,
-					    dma->pg_arr[i], dma->pg_map_arr[i]);
+			dma_free_coherent(&dev->pcidev->dev, BCM_PAGE_SIZE,
+					  dma->pg_arr[i], dma->pg_map_arr[i]);
 			dma->pg_arr[i] = NULL;
 		}
 	}
 	if (dma->pgtbl) {
-		pci_free_consistent(dev->pcidev, dma->pgtbl_size,
-				    dma->pgtbl, dma->pgtbl_map);
+		dma_free_coherent(&dev->pcidev->dev, dma->pgtbl_size,
+				  dma->pgtbl, dma->pgtbl_map);
 		dma->pgtbl = NULL;
 	}
 	kfree(dma->pg_arr);
@@ -726,9 +726,10 @@ static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma,
 	dma->num_pages = pages;
 
 	for (i = 0; i < pages; i++) {
-		dma->pg_arr[i] = pci_alloc_consistent(dev->pcidev,
-						      BCM_PAGE_SIZE,
-						      &dma->pg_map_arr[i]);
+		dma->pg_arr[i] = dma_alloc_coherent(&dev->pcidev->dev,
+						    BCM_PAGE_SIZE,
+						    &dma->pg_map_arr[i],
+						    GFP_ATOMIC);
 		if (dma->pg_arr[i] == NULL)
 			goto error;
 	}
@@ -737,8 +738,8 @@ static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma,
 
 	dma->pgtbl_size = ((pages * 8) + BCM_PAGE_SIZE - 1) &
 			  ~(BCM_PAGE_SIZE - 1);
-	dma->pgtbl = pci_alloc_consistent(dev->pcidev, dma->pgtbl_size,
-					  &dma->pgtbl_map);
+	dma->pgtbl = dma_alloc_coherent(&dev->pcidev->dev, dma->pgtbl_size,
+					&dma->pgtbl_map, GFP_ATOMIC);
 	if (dma->pgtbl == NULL)
 		goto error;
 
@@ -758,9 +759,9 @@ static void cnic_free_context(struct cnic_dev *dev)
 
 	for (i = 0; i < cp->ctx_blks; i++) {
 		if (cp->ctx_arr[i].ctx) {
-			pci_free_consistent(dev->pcidev, cp->ctx_blk_size,
-					    cp->ctx_arr[i].ctx,
-					    cp->ctx_arr[i].mapping);
+			dma_free_coherent(&dev->pcidev->dev, cp->ctx_blk_size,
+					  cp->ctx_arr[i].ctx,
+					  cp->ctx_arr[i].mapping);
 			cp->ctx_arr[i].ctx = NULL;
 		}
 	}
@@ -782,14 +783,14 @@ static void cnic_free_resc(struct cnic_dev *dev)
 	}
 
 	if (cp->l2_buf) {
-		pci_free_consistent(dev->pcidev, cp->l2_buf_size,
-				    cp->l2_buf, cp->l2_buf_map);
+		dma_free_coherent(&dev->pcidev->dev, cp->l2_buf_size,
+				  cp->l2_buf, cp->l2_buf_map);
 		cp->l2_buf = NULL;
 	}
 
 	if (cp->l2_ring) {
-		pci_free_consistent(dev->pcidev, cp->l2_ring_size,
-				    cp->l2_ring, cp->l2_ring_map);
+		dma_free_coherent(&dev->pcidev->dev, cp->l2_ring_size,
+				  cp->l2_ring, cp->l2_ring_map);
 		cp->l2_ring = NULL;
 	}
 
@@ -850,8 +851,10 @@ static int cnic_alloc_context(struct cnic_dev *dev)
 
 		for (i = 0; i < cp->ctx_blks; i++) {
 			cp->ctx_arr[i].ctx =
-				pci_alloc_consistent(dev->pcidev, BCM_PAGE_SIZE,
-						     &cp->ctx_arr[i].mapping);
+				dma_alloc_coherent(&dev->pcidev->dev,
+						   BCM_PAGE_SIZE,
+						   &cp->ctx_arr[i].mapping,
+						   GFP_KERNEL);
 			if (cp->ctx_arr[i].ctx == NULL)
 				return -ENOMEM;
 		}
@@ -864,15 +867,17 @@ static int cnic_alloc_l2_rings(struct cnic_dev *dev, int pages)
 	struct cnic_local *cp = dev->cnic_priv;
 
 	cp->l2_ring_size = pages * BCM_PAGE_SIZE;
-	cp->l2_ring = pci_alloc_consistent(dev->pcidev, cp->l2_ring_size,
-					   &cp->l2_ring_map);
+	cp->l2_ring = dma_alloc_coherent(&dev->pcidev->dev, cp->l2_ring_size,
+					 &cp->l2_ring_map,
+					 GFP_KERNEL | __GFP_COMP);
 	if (!cp->l2_ring)
 		return -ENOMEM;
 
 	cp->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size;
 	cp->l2_buf_size = PAGE_ALIGN(cp->l2_buf_size);
-	cp->l2_buf = pci_alloc_consistent(dev->pcidev, cp->l2_buf_size,
-					   &cp->l2_buf_map);
+	cp->l2_buf = dma_alloc_coherent(&dev->pcidev->dev, cp->l2_buf_size,
+					&cp->l2_buf_map,
+					GFP_KERNEL | __GFP_COMP);
 	if (!cp->l2_buf)
 		return -ENOMEM;
 
@@ -1007,8 +1012,9 @@ static int cnic_alloc_bnx2x_context(struct cnic_dev *dev)
 
 	for (i = 0; i < blks; i++) {
 		cp->ctx_arr[i].ctx =
-			pci_alloc_consistent(dev->pcidev, cp->ctx_blk_size,
-					     &cp->ctx_arr[i].mapping);
+			dma_alloc_coherent(&dev->pcidev->dev, cp->ctx_blk_size,
+					   &cp->ctx_arr[i].mapping,
+					   GFP_KERNEL);
 		if (cp->ctx_arr[i].ctx == NULL)
 			return -ENOMEM;
 
@@ -1099,6 +1105,8 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
 	cp->bnx2x_status_blk = cp->status_blk;
 	cp->bnx2x_def_status_blk = cp->ethdev->irq_arr[1].status_blk;
 
+	memset(cp->bnx2x_status_blk, 0, sizeof(struct host_status_block));
+
 	cp->l2_rx_ring_size = 15;
 
 	ret = cnic_alloc_l2_rings(dev, 4);
@@ -1501,9 +1509,9 @@ static int cnic_setup_bnx2x_ctx(struct cnic_dev *dev, struct kwqe *wqes[],
 	ictx->timers_context.flags |= ISCSI_TIMERS_BLOCK_CONTEXT_CONN_VALID_FLG;
 
 	ictx->ustorm_st_context.ring.rq.pbl_base.lo =
-		req2->rq_page_table_addr_lo & 0xffffffff;
+		req2->rq_page_table_addr_lo;
 	ictx->ustorm_st_context.ring.rq.pbl_base.hi =
-		(u64) req2->rq_page_table_addr_hi >> 32;
+		req2->rq_page_table_addr_hi;
 	ictx->ustorm_st_context.ring.rq.curr_pbe.lo = req3->qp_first_pte[0].hi;
 	ictx->ustorm_st_context.ring.rq.curr_pbe.hi = req3->qp_first_pte[0].lo;
 	ictx->ustorm_st_context.ring.r2tq.pbl_base.lo =
@@ -3394,7 +3402,7 @@ static int cnic_init_bnx2_irq(struct cnic_dev *dev)
 
 		cp->bnx2_status_blk = cp->status_blk;
 		cp->last_status_idx = cp->bnx2_status_blk->status_idx;
-		tasklet_init(&cp->cnic_irq_task, &cnic_service_bnx2_msix,
+		tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2_msix,
 			     (unsigned long) dev);
 		err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0,
 				  "cnic", dev);
@@ -3825,7 +3833,7 @@ static int cnic_init_bnx2x_irq(struct cnic_dev *dev)
 	struct cnic_eth_dev *ethdev = cp->ethdev;
 	int err = 0;
 
-	tasklet_init(&cp->cnic_irq_task, &cnic_service_bnx2x_bh,
+	tasklet_init(&cp->cnic_irq_task, cnic_service_bnx2x_bh,
 		     (unsigned long) dev);
 	if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
 		err = request_irq(ethdev->irq_arr[0].vector, cnic_irq, 0,
@@ -4035,15 +4043,19 @@ static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
 	if (base < 0xa0000 || base >= 0xc0000)
 		return;
 
-	val = BNX2X_SHMEM_ADDR(base,
+	addr = BNX2X_SHMEM_ADDR(base,
 		dev_info.port_hw_config[port].iscsi_mac_upper);
 
+	val = CNIC_RD(dev, addr);
+
 	dev->mac_addr[0] = (u8) (val >> 8);
 	dev->mac_addr[1] = (u8) val;
 
-	val = BNX2X_SHMEM_ADDR(base,
+	addr = BNX2X_SHMEM_ADDR(base,
 		dev_info.port_hw_config[port].iscsi_mac_lower);
 
+	val = CNIC_RD(dev, addr);
+
 	dev->mac_addr[2] = (u8) (val >> 24);
 	dev->mac_addr[3] = (u8) (val >> 16);
 	dev->mac_addr[4] = (u8) (val >> 8);
@@ -4169,22 +4181,20 @@ static void cnic_init_rings(struct cnic_dev *dev)
 		cnic_init_bnx2_rx_ring(dev);
 	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
 		struct cnic_local *cp = dev->cnic_priv;
-		struct cnic_eth_dev *ethdev = cp->ethdev;
 		u32 cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
 		union l5cm_specific_data l5_data;
 		struct ustorm_eth_rx_producers rx_prods = {0};
-		void __iomem *doorbell;
-		int i;
+		u32 off, i;
 
 		rx_prods.bd_prod = 0;
 		rx_prods.cqe_prod = BNX2X_MAX_RCQ_DESC_CNT;
 		barrier();
 
-		doorbell = ethdev->io_base2 + BAR_USTRORM_INTMEM +
+		off = BAR_USTRORM_INTMEM +
 			USTORM_RX_PRODS_OFFSET(CNIC_PORT(cp), cli);
 
 		for (i = 0; i < sizeof(struct ustorm_eth_rx_producers) / 4; i++)
-			writel(((u32 *) &rx_prods)[i], doorbell + i * 4);
+			CNIC_WR(dev, off + i * 4, ((u32 *) &rx_prods)[i]);
 
 		cnic_init_bnx2x_tx_ring(dev);
 		cnic_init_bnx2x_rx_ring(dev);
@@ -4204,8 +4214,21 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
 	} else if (test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
 		struct cnic_local *cp = dev->cnic_priv;
 		u32 cli = BNX2X_ISCSI_CL_ID(CNIC_E1HVN(cp));
+		union l5cm_specific_data l5_data;
 
 		cnic_ring_ctl(dev, BNX2X_ISCSI_L2_CID, cli, 0);
+
+		l5_data.phy_address.lo = cli;
+		l5_data.phy_address.hi = 0;
+		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_HALT,
+			BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE, &l5_data);
+		msleep(10);
+
+		memset(&l5_data, 0, sizeof(l5_data));
+		cnic_submit_kwqe_16(dev, RAMROD_CMD_ID_ETH_CFC_DEL,
+			BNX2X_ISCSI_L2_CID, ETH_CONNECTION_TYPE |
+			(1 << SPE_HDR_COMMON_RAMROD_SHIFT), &l5_data);
+		msleep(10);
 	}
 }
 
@@ -4281,6 +4304,9 @@ static void cnic_stop_bnx2x_hw(struct cnic_dev *dev)
 		  offsetof(struct cstorm_status_block_c,
 			   index_values[HC_INDEX_C_ISCSI_EQ_CONS]),
 		  0);
+	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
+		CSTORM_ISCSI_EQ_CONS_OFFSET(cp->func, 0), 0);
+	CNIC_WR16(dev, cp->kcq_io_addr, 0);
 	cnic_free_resc(dev);
 }