From 26d92f9276a56d55511a427fb70bd70886af647a Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 21 Jan 2010 22:52:08 -0800 Subject: be2net: fix bug in rx page posting Pages are posted to the rxq in such a way that more than one frag can share the page. The last frag that uses the page unmaps the page. In the case when a page is not fully used (due to lack of space in rxq) the last frag that uses the page is not being set as a "last_page_user"; instead, the next frag in the rxq is incorrectly being set. The fix has also been tested on ppc64 with 64k pages... Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 3a1f7902c16d..33ab8c7f14fe 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -910,7 +910,7 @@ static inline struct page *be_alloc_pages(u32 size) static void be_post_rx_frags(struct be_adapter *adapter) { struct be_rx_page_info *page_info_tbl = adapter->rx_obj.page_info_tbl; - struct be_rx_page_info *page_info = NULL; + struct be_rx_page_info *page_info = NULL, *prev_page_info = NULL; struct be_queue_info *rxq = &adapter->rx_obj.q; struct page *pagep = NULL; struct be_eth_rx_d *rxd; @@ -941,7 +941,6 @@ static void be_post_rx_frags(struct be_adapter *adapter) rxd = queue_head_node(rxq); rxd->fragpa_lo = cpu_to_le32(frag_dmaaddr & 0xFFFFFFFF); rxd->fragpa_hi = cpu_to_le32(upper_32_bits(frag_dmaaddr)); - queue_head_inc(rxq); /* Any space left in the current big page for another frag? */ if ((page_offset + rx_frag_size + rx_frag_size) > @@ -949,10 +948,13 @@ static void be_post_rx_frags(struct be_adapter *adapter) pagep = NULL; page_info->last_page_user = true; } + + prev_page_info = page_info; + queue_head_inc(rxq); page_info = &page_info_tbl[rxq->head]; } if (pagep) - page_info->last_page_user = true; + prev_page_info->last_page_user = true; if (posted) { atomic_add(posted, &rxq->used); -- cgit v1.2.3 From 7b139c83c590d4965259aad8889cbb08104b2891 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Wed, 27 Jan 2010 21:56:44 +0000 Subject: be2net: Bug fix to support newer generation of BE ASIC Bug fix in be2net for newer generation of BladeEngine ASIC. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 33ab8c7f14fe..90c5661b336f 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2051,6 +2051,7 @@ static void be_unmap_pci_bars(struct be_adapter *adapter) static int be_map_pci_bars(struct be_adapter *adapter) { u8 __iomem *addr; + int pcicfg_reg; addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2), pci_resource_len(adapter->pdev, 2)); @@ -2064,8 +2065,13 @@ static int be_map_pci_bars(struct be_adapter *adapter) goto pci_map_err; adapter->db = addr; - addr = ioremap_nocache(pci_resource_start(adapter->pdev, 1), - pci_resource_len(adapter->pdev, 1)); + if (adapter->generation == BE_GEN2) + pcicfg_reg = 1; + else + pcicfg_reg = 0; + + addr = ioremap_nocache(pci_resource_start(adapter->pdev, pcicfg_reg), + pci_resource_len(adapter->pdev, pcicfg_reg)); if (addr == NULL) goto pci_map_err; adapter->pcicfg = addr; @@ -2162,6 +2168,7 @@ static int be_stats_init(struct be_adapter *adapter) cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma); if (cmd->va == NULL) return -1; + memset(cmd->va, cmd->size, 0); return 0; } @@ -2240,6 +2247,20 @@ static int __devinit be_probe(struct pci_dev *pdev, goto rel_reg; } adapter = netdev_priv(netdev); + + switch (pdev->device) { + case BE_DEVICE_ID1: + case OC_DEVICE_ID1: + adapter->generation = BE_GEN2; + break; + case BE_DEVICE_ID2: + case OC_DEVICE_ID2: + adapter->generation = BE_GEN3; + break; + default: + adapter->generation = 0; + } + adapter->pdev = pdev; pci_set_drvdata(pdev, adapter); adapter->netdev = netdev; -- cgit v1.2.3 From d291b9af1a1a12f59a464494900c6e0db26e2ec3 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Thu, 28 Jan 2010 21:36:21 -0800 Subject: be2net: Fix memset() arg ordering. Noticed by Ben Hutchings. Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 90c5661b336f..6f2633887dc3 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2168,7 +2168,7 @@ static int be_stats_init(struct be_adapter *adapter) cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma); if (cmd->va == NULL) return -1; - memset(cmd->va, cmd->size, 0); + memset(cmd->va, 0, cmd->size); return 0; } -- cgit v1.2.3 From 55bdeed9f67a92f184e1ddcdd722e622d9dd10c6 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Tue, 2 Feb 2010 07:48:40 -0800 Subject: be2net: use eq-id to calculate cev-isr reg offset cev-isr reg offset for each function is better calculated using (any) eq-id alloted to that function instead of using pci-func number(which does not work in some configurations...) Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 6f2633887dc3..626b76c0ebc7 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1350,7 +1350,7 @@ static irqreturn_t be_intx(int irq, void *dev) int isr; isr = ioread32(adapter->csr + CEV_ISR0_OFFSET + - be_pci_func(adapter) * CEV_ISR_SIZE); + (adapter->tx_eq.q.id/ 8) * CEV_ISR_SIZE); if (!isr) return IRQ_NONE; -- cgit v1.2.3 From 4cd24eaf0c6ee7f0242e34ee77ec899f255e66b5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 8 Feb 2010 04:30:35 +0000 Subject: net: use netdev_mc_count and netdev_mc_empty when appropriate This patch replaces dev->mc_count in all drivers (hopefully I didn't miss anything). Used spatch and did small tweaks and conding style changes when it was suitable. Jirka Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 626b76c0ebc7..0014a4e86446 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -565,14 +565,15 @@ static void be_set_multicast_list(struct net_device *netdev) } /* Enable multicast promisc if num configured exceeds what we support */ - if (netdev->flags & IFF_ALLMULTI || netdev->mc_count > BE_MAX_MC) { + if (netdev->flags & IFF_ALLMULTI || + netdev_mc_count(netdev) > BE_MAX_MC) { be_cmd_multicast_set(adapter, adapter->if_handle, NULL, 0, &adapter->mc_cmd_mem); goto done; } be_cmd_multicast_set(adapter, adapter->if_handle, netdev->mc_list, - netdev->mc_count, &adapter->mc_cmd_mem); + netdev_mc_count(netdev), &adapter->mc_cmd_mem); done: return; } -- cgit v1.2.3 From e254f6ecaeb4e7c0588e739bf4641df0e8c22bba Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 9 Feb 2010 01:28:35 +0000 Subject: be2net: remove unused pci device id We are not going to use this device id. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 0014a4e86446..0779f6b5e29b 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -34,7 +34,6 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID2) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, - { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) }, { 0 } }; MODULE_DEVICE_TABLE(pci, be_dev_ids); -- cgit v1.2.3 From 3f0d4560aedaa67546eaeb3dc75fcdf68ec21036 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 9 Feb 2010 01:30:35 +0000 Subject: be2net: bug fix for flashing the BladeEngine3 ASIC Now flashing both BE2 and BE3 devices is supported. From: Naresh G Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 239 +++++++++++++++++++++++--------------------- 1 file changed, 127 insertions(+), 112 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 0779f6b5e29b..99061488eeb3 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1798,15 +1798,19 @@ char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; static bool be_flash_redboot(struct be_adapter *adapter, - const u8 *p) + const u8 *p, u32 img_start, int image_size, + int hdr_size) { u32 crc_offset; u8 flashed_crc[4]; int status; - crc_offset = FLASH_REDBOOT_START + FLASH_REDBOOT_IMAGE_MAX_SIZE - 4 - + sizeof(struct flash_file_hdr) - 32*1024; + + crc_offset = hdr_size + img_start + image_size - 4; + p += crc_offset; - status = be_cmd_get_flash_crc(adapter, flashed_crc); + + status = be_cmd_get_flash_crc(adapter, flashed_crc, + (img_start + image_size - 4)); if (status) { dev_err(&adapter->pdev->dev, "could not get crc from flash, not flashing redboot\n"); @@ -1818,102 +1822,124 @@ static bool be_flash_redboot(struct be_adapter *adapter, return false; else return true; - } -static int be_flash_image(struct be_adapter *adapter, +static int be_flash_data(struct be_adapter *adapter, const struct firmware *fw, - struct be_dma_mem *flash_cmd, u32 flash_type) + struct be_dma_mem *flash_cmd, int num_of_images) + { - int status; - u32 flash_op, image_offset = 0, total_bytes, image_size = 0; + int status = 0, i, filehdr_size = 0; + u32 total_bytes = 0, flash_op; int num_bytes; const u8 *p = fw->data; struct be_cmd_write_flashrom *req = flash_cmd->va; - - switch (flash_type) { - case FLASHROM_TYPE_ISCSI_ACTIVE: - image_offset = FLASH_iSCSI_PRIMARY_IMAGE_START; - image_size = FLASH_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_ISCSI_BACKUP: - image_offset = FLASH_iSCSI_BACKUP_IMAGE_START; - image_size = FLASH_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_FCOE_FW_ACTIVE: - image_offset = FLASH_FCoE_PRIMARY_IMAGE_START; - image_size = FLASH_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_FCOE_FW_BACKUP: - image_offset = FLASH_FCoE_BACKUP_IMAGE_START; - image_size = FLASH_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_BIOS: - image_offset = FLASH_iSCSI_BIOS_START; - image_size = FLASH_BIOS_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_FCOE_BIOS: - image_offset = FLASH_FCoE_BIOS_START; - image_size = FLASH_BIOS_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_PXE_BIOS: - image_offset = FLASH_PXE_BIOS_START; - image_size = FLASH_BIOS_IMAGE_MAX_SIZE; - break; - case FLASHROM_TYPE_REDBOOT: - if (!be_flash_redboot(adapter, fw->data)) - return 0; - image_offset = FLASH_REDBOOT_ISM_START; - image_size = FLASH_REDBOOT_IMAGE_MAX_SIZE; - break; - default: - return 0; + struct flash_comp *pflashcomp; + + struct flash_comp gen3_flash_types[8] = { + { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE, + FLASH_IMAGE_MAX_SIZE_g3}, + { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT, + FLASH_REDBOOT_IMAGE_MAX_SIZE_g3}, + { FLASH_iSCSI_BIOS_START_g3, IMG_TYPE_BIOS, + FLASH_BIOS_IMAGE_MAX_SIZE_g3}, + { FLASH_PXE_BIOS_START_g3, IMG_TYPE_PXE_BIOS, + FLASH_BIOS_IMAGE_MAX_SIZE_g3}, + { FLASH_FCoE_BIOS_START_g3, IMG_TYPE_FCOE_BIOS, + FLASH_BIOS_IMAGE_MAX_SIZE_g3}, + { FLASH_iSCSI_BACKUP_IMAGE_START_g3, IMG_TYPE_ISCSI_BACKUP, + FLASH_IMAGE_MAX_SIZE_g3}, + { FLASH_FCoE_PRIMARY_IMAGE_START_g3, IMG_TYPE_FCOE_FW_ACTIVE, + FLASH_IMAGE_MAX_SIZE_g3}, + { FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP, + FLASH_IMAGE_MAX_SIZE_g3} + }; + struct flash_comp gen2_flash_types[8] = { + { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE, + FLASH_IMAGE_MAX_SIZE_g2}, + { FLASH_REDBOOT_START_g2, IMG_TYPE_REDBOOT, + FLASH_REDBOOT_IMAGE_MAX_SIZE_g2}, + { FLASH_iSCSI_BIOS_START_g2, IMG_TYPE_BIOS, + FLASH_BIOS_IMAGE_MAX_SIZE_g2}, + { FLASH_PXE_BIOS_START_g2, IMG_TYPE_PXE_BIOS, + FLASH_BIOS_IMAGE_MAX_SIZE_g2}, + { FLASH_FCoE_BIOS_START_g2, IMG_TYPE_FCOE_BIOS, + FLASH_BIOS_IMAGE_MAX_SIZE_g2}, + { FLASH_iSCSI_BACKUP_IMAGE_START_g2, IMG_TYPE_ISCSI_BACKUP, + FLASH_IMAGE_MAX_SIZE_g2}, + { FLASH_FCoE_PRIMARY_IMAGE_START_g2, IMG_TYPE_FCOE_FW_ACTIVE, + FLASH_IMAGE_MAX_SIZE_g2}, + { FLASH_FCoE_BACKUP_IMAGE_START_g2, IMG_TYPE_FCOE_FW_BACKUP, + FLASH_IMAGE_MAX_SIZE_g2} + }; + + if (adapter->generation == BE_GEN3) { + pflashcomp = gen3_flash_types; + filehdr_size = sizeof(struct flash_file_hdr_g3); + } else { + pflashcomp = gen2_flash_types; + filehdr_size = sizeof(struct flash_file_hdr_g2); } - - p += sizeof(struct flash_file_hdr) + image_offset; - if (p + image_size > fw->data + fw->size) + for (i = 0; i < 8; i++) { + if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) && + (!be_flash_redboot(adapter, fw->data, + pflashcomp[i].offset, pflashcomp[i].size, + filehdr_size))) + continue; + p = fw->data; + p += filehdr_size + pflashcomp[i].offset + + (num_of_images * sizeof(struct image_hdr)); + if (p + pflashcomp[i].size > fw->data + fw->size) return -1; - - total_bytes = image_size; - - while (total_bytes) { - if (total_bytes > 32*1024) - num_bytes = 32*1024; - else - num_bytes = total_bytes; - total_bytes -= num_bytes; - - if (!total_bytes) - flash_op = FLASHROM_OPER_FLASH; - else - flash_op = FLASHROM_OPER_SAVE; - memcpy(req->params.data_buf, p, num_bytes); - p += num_bytes; - status = be_cmd_write_flashrom(adapter, flash_cmd, - flash_type, flash_op, num_bytes); - if (status) { - dev_err(&adapter->pdev->dev, - "cmd to write to flash rom failed. type/op %d/%d\n", - flash_type, flash_op); - return -1; + total_bytes = pflashcomp[i].size; + while (total_bytes) { + if (total_bytes > 32*1024) + num_bytes = 32*1024; + else + num_bytes = total_bytes; + total_bytes -= num_bytes; + + if (!total_bytes) + flash_op = FLASHROM_OPER_FLASH; + else + flash_op = FLASHROM_OPER_SAVE; + memcpy(req->params.data_buf, p, num_bytes); + p += num_bytes; + status = be_cmd_write_flashrom(adapter, flash_cmd, + pflashcomp[i].optype, flash_op, num_bytes); + if (status) { + dev_err(&adapter->pdev->dev, + "cmd to write to flash rom failed.\n"); + return -1; + } + yield(); } - yield(); } - return 0; } +static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr) +{ + if (fhdr == NULL) + return 0; + if (fhdr->build[0] == '3') + return BE_GEN3; + else if (fhdr->build[0] == '2') + return BE_GEN2; + else + return 0; +} + int be_load_fw(struct be_adapter *adapter, u8 *func) { char fw_file[ETHTOOL_FLASH_MAX_FILENAME]; const struct firmware *fw; - struct flash_file_hdr *fhdr; - struct flash_section_info *fsec = NULL; + struct flash_file_hdr_g2 *fhdr; + struct flash_file_hdr_g3 *fhdr3; + struct image_hdr *img_hdr_ptr = NULL; struct be_dma_mem flash_cmd; - int status; + int status, i = 0; const u8 *p; - bool entry_found = false; - int flash_type; char fw_ver[FW_VER_LEN]; char fw_cfg; @@ -1931,34 +1957,9 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) goto fw_exit; p = fw->data; - fhdr = (struct flash_file_hdr *) p; - if (memcmp(fhdr->sign, FW_FILE_HDR_SIGN, strlen(FW_FILE_HDR_SIGN))) { - dev_err(&adapter->pdev->dev, - "Firmware(%s) load error (signature did not match)\n", - fw_file); - status = -1; - goto fw_exit; - } - + fhdr = (struct flash_file_hdr_g2 *) p; dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file); - p += sizeof(struct flash_file_hdr); - while (p < (fw->data + fw->size)) { - fsec = (struct flash_section_info *)p; - if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) { - entry_found = true; - break; - } - p += 32; - } - - if (!entry_found) { - status = -1; - dev_err(&adapter->pdev->dev, - "Flash cookie not found in firmware image\n"); - goto fw_exit; - } - flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; flash_cmd.va = pci_alloc_consistent(adapter->pdev, flash_cmd.size, &flash_cmd.dma); @@ -1969,12 +1970,26 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) goto fw_exit; } - for (flash_type = FLASHROM_TYPE_ISCSI_ACTIVE; - flash_type <= FLASHROM_TYPE_FCOE_FW_BACKUP; flash_type++) { - status = be_flash_image(adapter, fw, &flash_cmd, - flash_type); - if (status) - break; + if ((adapter->generation == BE_GEN3) && + (get_ufigen_type(fhdr) == BE_GEN3)) { + fhdr3 = (struct flash_file_hdr_g3 *) fw->data; + for (i = 0; i < fhdr3->num_imgs; i++) { + img_hdr_ptr = (struct image_hdr *) (fw->data + + (sizeof(struct flash_file_hdr_g3) + + i * sizeof(struct image_hdr))); + if (img_hdr_ptr->imageid == 1) { + status = be_flash_data(adapter, fw, + &flash_cmd, fhdr3->num_imgs); + } + + } + } else if ((adapter->generation == BE_GEN2) && + (get_ufigen_type(fhdr) == BE_GEN2)) { + status = be_flash_data(adapter, fw, &flash_cmd, 0); + } else { + dev_err(&adapter->pdev->dev, + "UFI and Interface are not compatible for flashing\n"); + status = -1; } pci_free_consistent(adapter->pdev, flash_cmd.size, flash_cmd.va, -- cgit v1.2.3 From 34a89b8c75abe2873a95524552cc266fdd3b6a85 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 9 Feb 2010 01:32:43 +0000 Subject: be2net: bug fix in be_change_mtu Current code allows the new mtu to cross the supported value. This patch fixes the boundary checks. From: Suresh R Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 99061488eeb3..c65c63427d41 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -473,10 +473,12 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) { struct be_adapter *adapter = netdev_priv(netdev); if (new_mtu < BE_MIN_MTU || - new_mtu > BE_MAX_JUMBO_FRAME_SIZE) { + new_mtu > (BE_MAX_JUMBO_FRAME_SIZE - + (ETH_HLEN + ETH_FCS_LEN))) { dev_info(&adapter->pdev->dev, "MTU must be between %d and %d bytes\n", - BE_MIN_MTU, BE_MAX_JUMBO_FRAME_SIZE); + BE_MIN_MTU, + (BE_MAX_JUMBO_FRAME_SIZE - (ETH_HLEN + ETH_FCS_LEN))); return -EINVAL; } dev_info(&adapter->pdev->dev, "MTU changed from %d to %d bytes\n", -- cgit v1.2.3 From 205859a2ff922d0587a819b08007398cbd0a6a30 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 9 Feb 2010 01:34:21 +0000 Subject: be2net: minor code optimizations Couple of code optimizations in the Rx path (to avoid a memset). From: Sathya P Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index c65c63427d41..1951d7620a88 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -636,9 +636,11 @@ get_rx_page_info(struct be_adapter *adapter, u16 frag_idx) rx_page_info = &adapter->rx_obj.page_info_tbl[frag_idx]; BUG_ON(!rx_page_info->page); - if (rx_page_info->last_page_user) + if (rx_page_info->last_page_user) { pci_unmap_page(adapter->pdev, pci_unmap_addr(rx_page_info, bus), adapter->big_page_size, PCI_DMA_FROMDEVICE); + rx_page_info->last_page_user = false; + } atomic_dec(&rxq->used); return rx_page_info; @@ -706,7 +708,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, skb->data_len = curr_frag_len - hdr_len; skb->tail += hdr_len; } - memset(page_info, 0, sizeof(*page_info)); + page_info->page = NULL; if (pktsize <= rx_frag_size) { BUG_ON(num_rcvd != 1); @@ -739,7 +741,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter, skb->len += curr_frag_len; skb->data_len += curr_frag_len; - memset(page_info, 0, sizeof(*page_info)); + page_info->page = NULL; } BUG_ON(j > MAX_SKB_FRAGS); -- cgit v1.2.3 From 82903e4bfca1578336a91c0c17839b484c12295d Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Tue, 9 Feb 2010 01:34:57 +0000 Subject: be2net: fix to limit max vlans supported in certain skews In certain skews the ASIC can support only 16 vlans per interface. Once the limit is crossed, the ASIC is programmed in vlan promiscuous mode. Switch off the vlan promiscuous mode once the number of vlans falls back to the max vlans supported. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 1951d7620a88..92c55f679466 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -488,17 +488,16 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) } /* - * if there are BE_NUM_VLANS_SUPPORTED or lesser number of VLANS configured, - * program them in BE. If more than BE_NUM_VLANS_SUPPORTED are configured, - * set the BE in promiscuous VLAN mode. + * A max of 64 (BE_NUM_VLANS_SUPPORTED) vlans can be configured in BE. + * If the user configures more, place BE in vlan promiscuous mode. */ static int be_vid_config(struct be_adapter *adapter) { u16 vtag[BE_NUM_VLANS_SUPPORTED]; u16 ntags = 0, i; - int status; + int status = 0; - if (adapter->num_vlans <= BE_NUM_VLANS_SUPPORTED) { + if (adapter->vlans_added <= adapter->max_vlans) { /* Construct VLAN Table to give to HW */ for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { if (adapter->vlan_tag[i]) { @@ -532,21 +531,21 @@ static void be_vlan_add_vid(struct net_device *netdev, u16 vid) { struct be_adapter *adapter = netdev_priv(netdev); - adapter->num_vlans++; adapter->vlan_tag[vid] = 1; - - be_vid_config(adapter); + adapter->vlans_added++; + if (adapter->vlans_added <= (adapter->max_vlans + 1)) + be_vid_config(adapter); } static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) { struct be_adapter *adapter = netdev_priv(netdev); - adapter->num_vlans--; adapter->vlan_tag[vid] = 0; - vlan_group_set_device(adapter->vlan_grp, vid, NULL); - be_vid_config(adapter); + adapter->vlans_added--; + if (adapter->vlans_added <= adapter->max_vlans) + be_vid_config(adapter); } static void be_set_multicast_list(struct net_device *netdev) @@ -786,7 +785,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, skb->dev = adapter->netdev; if (vlanf) { - if (!adapter->vlan_grp || adapter->num_vlans == 0) { + if (!adapter->vlan_grp || adapter->vlans_added == 0) { kfree_skb(skb); return; } @@ -866,7 +865,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); vid = be16_to_cpu(vid); - if (!adapter->vlan_grp || adapter->num_vlans == 0) + if (!adapter->vlan_grp || adapter->vlans_added == 0) return; vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid); @@ -2241,6 +2240,11 @@ static int be_get_config(struct be_adapter *adapter) memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN); + if (adapter->cap & 0x400) + adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/4; + else + adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; + return 0; } -- cgit v1.2.3 From cf588477a3fbf085426e5c0b6205984ebb7e2187 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Sun, 14 Feb 2010 21:22:01 +0000 Subject: be2net: implement EEH pci error recovery handlers The code has been tested on IBM pSeries server. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 103 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 92c55f679466..cbfaa3feb7c4 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -68,6 +68,9 @@ static void be_intr_set(struct be_adapter *adapter, bool enable) u32 reg = ioread32(addr); u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; + if (adapter->eeh_err) + return; + if (!enabled && enable) reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; else if (enabled && !enable) @@ -99,6 +102,10 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid, { u32 val = 0; val |= qid & DB_EQ_RING_ID_MASK; + + if (adapter->eeh_err) + return; + if (arm) val |= 1 << DB_EQ_REARM_SHIFT; if (clear_int) @@ -112,6 +119,10 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped) { u32 val = 0; val |= qid & DB_CQ_RING_ID_MASK; + + if (adapter->eeh_err) + return; + if (arm) val |= 1 << DB_CQ_REARM_SHIFT; val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; @@ -2154,6 +2165,7 @@ static int be_ctrl_init(struct be_adapter *adapter) spin_lock_init(&adapter->mcc_lock); spin_lock_init(&adapter->mcc_cq_lock); + pci_save_state(adapter->pdev); return 0; free_mbox: @@ -2417,13 +2429,102 @@ static int be_resume(struct pci_dev *pdev) return 0; } +static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, + pci_channel_state_t state) +{ + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + dev_err(&adapter->pdev->dev, "EEH error detected\n"); + + adapter->eeh_err = true; + + netif_device_detach(netdev); + + if (netif_running(netdev)) { + rtnl_lock(); + be_close(netdev); + rtnl_unlock(); + } + be_clear(adapter); + + if (state == pci_channel_io_perm_failure) + return PCI_ERS_RESULT_DISCONNECT; + + pci_disable_device(pdev); + + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) +{ + struct be_adapter *adapter = pci_get_drvdata(pdev); + int status; + + dev_info(&adapter->pdev->dev, "EEH reset\n"); + adapter->eeh_err = false; + + status = pci_enable_device(pdev); + if (status) + return PCI_ERS_RESULT_DISCONNECT; + + pci_set_master(pdev); + pci_set_power_state(pdev, 0); + pci_restore_state(pdev); + + /* Check if card is ok and fw is ready */ + status = be_cmd_POST(adapter); + if (status) + return PCI_ERS_RESULT_DISCONNECT; + + return PCI_ERS_RESULT_RECOVERED; +} + +static void be_eeh_resume(struct pci_dev *pdev) +{ + int status = 0; + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + dev_info(&adapter->pdev->dev, "EEH resume\n"); + + pci_save_state(pdev); + + /* tell fw we're ready to fire cmds */ + status = be_cmd_fw_init(adapter); + if (status) + goto err; + + status = be_setup(adapter); + if (status) + goto err; + + if (netif_running(netdev)) { + status = be_open(netdev); + if (status) + goto err; + } + netif_device_attach(netdev); + return; +err: + dev_err(&adapter->pdev->dev, "EEH resume failed\n"); + return; +} + +static struct pci_error_handlers be_eeh_handlers = { + .error_detected = be_eeh_err_detected, + .slot_reset = be_eeh_reset, + .resume = be_eeh_resume, +}; + static struct pci_driver be_driver = { .name = DRV_NAME, .id_table = be_dev_ids, .probe = be_probe, .remove = be_remove, .suspend = be_suspend, - .resume = be_resume + .resume = be_resume, + .err_handler = &be_eeh_handlers }; static int __init be_init_module(void) -- cgit v1.2.3 From a058a632747dd0f1799b12f4ecd54e43f5b5f10d Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 17 Feb 2010 01:34:22 +0000 Subject: be2net: a mini optimization in rx_compl_process() code Introduce unlikely() for skb alloc failure and vlanf checks... Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index cbfaa3feb7c4..7bf1900df665 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -768,16 +768,8 @@ static void be_rx_compl_process(struct be_adapter *adapter, u32 vlanf, vid; u8 vtm; - vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); - vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp); - - /* vlanf could be wrongly set in some cards. - * ignore if vtm is not set */ - if ((adapter->cap & 0x400) && !vtm) - vlanf = 0; - skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN); - if (!skb) { + if (unlikely(!skb)) { if (net_ratelimit()) dev_warn(&adapter->pdev->dev, "skb alloc failed\n"); be_rx_compl_discard(adapter, rxcp); @@ -795,7 +787,15 @@ static void be_rx_compl_process(struct be_adapter *adapter, skb->protocol = eth_type_trans(skb, adapter->netdev); skb->dev = adapter->netdev; - if (vlanf) { + vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); + vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp); + + /* vlanf could be wrongly set in some cards. + * ignore if vtm is not set */ + if ((adapter->cap & 0x400) && !vtm) + vlanf = 0; + + if (unlikely(vlanf)) { if (!adapter->vlan_grp || adapter->vlans_added == 0) { kfree_skb(skb); return; -- cgit v1.2.3 From 7a1e9b2059d147461cff3dfbabbfb43f296a1eef Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 17 Feb 2010 01:35:11 +0000 Subject: be2net: don't rearm mcc cq when device is not open When an MCC cmd is issued (via a netdev/ethtool op) while the device is not open, the MCC CQ gets processed but the EQ is not processed (as isr is not registered.) This can cause the EQ to become full. So, while the device is not open, CQ must not be re-armed to prevent EQ entries. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 7bf1900df665..43dbe288a5ef 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1655,6 +1655,9 @@ static int be_open(struct net_device *netdev) /* Rx compl queue may be in unarmed state; rearm it */ be_cq_notify(adapter, adapter->rx_obj.cq.id, true, 0); + /* Now that interrupts are on we can process async mcc */ + be_async_mcc_enable(adapter); + status = be_cmd_link_status_query(adapter, &link_up, &mac_speed, &link_speed); if (status) @@ -1780,6 +1783,8 @@ static int be_close(struct net_device *netdev) cancel_delayed_work_sync(&adapter->work); + be_async_mcc_disable(adapter); + netif_stop_queue(netdev); netif_carrier_off(netdev); adapter->link_up = false; -- cgit v1.2.3 From 89420424fce28769c338909393518087befe8b37 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 17 Feb 2010 01:35:26 +0000 Subject: be2net: fix rx-path to ignore a flush completion The flush compl (compl with numfrags == 0; no data) is rcvd from hw to indicate completion of RXQ destory operation. Fix the RX path to not process it as RX data. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 43dbe288a5ef..2c3deadd2d83 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -680,17 +680,17 @@ static void be_rx_compl_discard(struct be_adapter *adapter, * indicated by rxcp. */ static void skb_fill_rx_data(struct be_adapter *adapter, - struct sk_buff *skb, struct be_eth_rx_compl *rxcp) + struct sk_buff *skb, struct be_eth_rx_compl *rxcp, + u16 num_rcvd) { struct be_queue_info *rxq = &adapter->rx_obj.q; struct be_rx_page_info *page_info; - u16 rxq_idx, i, num_rcvd, j; + u16 rxq_idx, i, j; u32 pktsize, hdr_len, curr_frag_len, size; u8 *start; rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); - num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); page_info = get_rx_page_info(adapter, rxq_idx); @@ -766,8 +766,14 @@ static void be_rx_compl_process(struct be_adapter *adapter, { struct sk_buff *skb; u32 vlanf, vid; + u16 num_rcvd; u8 vtm; + num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + /* Is it a flush compl that has no data */ + if (unlikely(num_rcvd == 0)) + return; + skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN); if (unlikely(!skb)) { if (net_ratelimit()) @@ -776,7 +782,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, return; } - skb_fill_rx_data(adapter, skb, rxcp); + skb_fill_rx_data(adapter, skb, rxcp, num_rcvd); if (do_pkt_csum(rxcp, adapter->rx_csum)) skb->ip_summed = CHECKSUM_NONE; @@ -823,6 +829,10 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter, u8 vtm; num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + /* Is it a flush compl that has no data */ + if (unlikely(num_rcvd == 0)) + return; + pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); @@ -1273,6 +1283,11 @@ static void be_rx_queues_destroy(struct be_adapter *adapter) q = &adapter->rx_obj.q; if (q->created) { be_cmd_q_destroy(adapter, q, QTYPE_RXQ); + + /* After the rxq is invalidated, wait for a grace time + * of 1ms for all dma to end and the flush compl to arrive + */ + mdelay(1); be_rx_q_clean(adapter); } be_queue_free(adapter, q); -- cgit v1.2.3 From 82456b031e3c3b5bf95a7e49bd9b68b146446e76 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 17 Feb 2010 01:35:37 +0000 Subject: be2net: implement pci shutdown handler Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 2c3deadd2d83..68e7848ac0b0 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -2449,6 +2449,26 @@ static int be_resume(struct pci_dev *pdev) return 0; } +/* + * An FLR will stop BE from DMAing any data. + */ +static void be_shutdown(struct pci_dev *pdev) +{ + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + + be_cmd_reset_function(adapter); + + if (adapter->wol) + be_setup_wol(adapter, true); + + pci_disable_device(pdev); + + return; +} + static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, pci_channel_state_t state) { @@ -2544,6 +2564,7 @@ static struct pci_driver be_driver = { .remove = be_remove, .suspend = be_suspend, .resume = be_resume, + .shutdown = be_shutdown, .err_handler = &be_eeh_handlers }; -- cgit v1.2.3 From b03388d6389e8853ddd9ae19d2ba15a6dbbe5d21 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 18 Feb 2010 00:37:17 +0000 Subject: be2net: free tx buffers when completions never arrive be2net: free tx buffers when completions never arrive In cases like when a pci device is disconnected on an error, pending tx completions will never arrive. Unmap and free such buffers in the tx cleanup path. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 68e7848ac0b0..545c8417fc26 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1128,6 +1128,9 @@ static void be_tx_compl_clean(struct be_adapter *adapter) struct be_queue_info *txq = &adapter->tx_obj.q; struct be_eth_tx_compl *txcp; u16 end_idx, cmpl = 0, timeo = 0; + struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; + struct sk_buff *sent_skb; + bool dummy_wrb; /* Wait for a max of 200ms for all the tx-completions to arrive. */ do { @@ -1151,6 +1154,15 @@ static void be_tx_compl_clean(struct be_adapter *adapter) if (atomic_read(&txq->used)) dev_err(&adapter->pdev->dev, "%d pending tx-completions\n", atomic_read(&txq->used)); + + /* free posted tx for which compls will never arrive */ + while (atomic_read(&txq->used)) { + sent_skb = sent_skbs[txq->tail]; + end_idx = txq->tail; + index_adv(&end_idx, + wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len); + be_tx_compl_process(adapter, end_idx); + } } static void be_mcc_queues_destroy(struct be_adapter *adapter) -- cgit v1.2.3 From 294aedcf875b982e2d3bd6d2d9b8124ccb163bf6 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Fri, 19 Feb 2010 13:54:58 +0000 Subject: be2net: update copyright dates Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 545c8417fc26..f66704460876 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2009 ServerEngines + * Copyright (C) 2005 - 2010 ServerEngines * All rights reserved. * * This program is free software; you can redistribute it and/or -- cgit v1.2.3 From 91992e446cadbbde1a304de6954afd715af5121e Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Fri, 19 Feb 2010 13:57:12 +0000 Subject: be2net: Maintain tx and rx counters in driver For certain skews of the BE adapter, H/W Tx and Rx counters could be common for more than one interface. Add Tx and Rx counters in the adapter structure (to maintain stats on a per interfae basis). Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index f66704460876..de0830e14aa5 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -159,13 +159,10 @@ void netdev_stats_update(struct be_adapter *adapter) struct net_device_stats *dev_stats = &adapter->netdev->stats; struct be_erx_stats *erx_stats = &hw_stats->erx; - dev_stats->rx_packets = port_stats->rx_total_frames; - dev_stats->tx_packets = port_stats->tx_unicastframes + - port_stats->tx_multicastframes + port_stats->tx_broadcastframes; - dev_stats->rx_bytes = (u64) port_stats->rx_bytes_msd << 32 | - (u64) port_stats->rx_bytes_lsd; - dev_stats->tx_bytes = (u64) port_stats->tx_bytes_msd << 32 | - (u64) port_stats->tx_bytes_lsd; + dev_stats->rx_packets = drvr_stats(adapter)->be_rx_pkts; + dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts; + dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes; + dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes; /* bad pkts received */ dev_stats->rx_errors = port_stats->rx_crc_errors + @@ -322,12 +319,13 @@ static void be_tx_rate_update(struct be_adapter *adapter) } static void be_tx_stats_update(struct be_adapter *adapter, - u32 wrb_cnt, u32 copied, bool stopped) + u32 wrb_cnt, u32 copied, u32 gso_segs, bool stopped) { struct be_drvr_stats *stats = drvr_stats(adapter); stats->be_tx_reqs++; stats->be_tx_wrbs += wrb_cnt; stats->be_tx_bytes += copied; + stats->be_tx_pkts += (gso_segs ? gso_segs : 1); if (stopped) stats->be_tx_stops++; } @@ -472,7 +470,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, be_txq_notify(adapter, txq->id, wrb_cnt); - be_tx_stats_update(adapter, wrb_cnt, copied, stopped); + be_tx_stats_update(adapter, wrb_cnt, copied, + skb_shinfo(skb)->gso_segs, stopped); } else { txq->head = start; dev_kfree_skb_any(skb); @@ -619,6 +618,7 @@ static void be_rx_stats_update(struct be_adapter *adapter, stats->be_rx_compl++; stats->be_rx_frags += numfrags; stats->be_rx_bytes += pktsize; + stats->be_rx_pkts++; } static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso) -- cgit v1.2.3 From 0ddf477b8a9b02412a6cabd51c486998811c7dd1 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 20 Feb 2010 00:13:58 +0000 Subject: net: convert multiple drivers to use netdev_for_each_mc_addr, part3 Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index de0830e14aa5..27ccdd80257b 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -577,13 +577,13 @@ static void be_set_multicast_list(struct net_device *netdev) /* Enable multicast promisc if num configured exceeds what we support */ if (netdev->flags & IFF_ALLMULTI || netdev_mc_count(netdev) > BE_MAX_MC) { - be_cmd_multicast_set(adapter, adapter->if_handle, NULL, 0, + be_cmd_multicast_set(adapter, adapter->if_handle, NULL, &adapter->mc_cmd_mem); goto done; } - be_cmd_multicast_set(adapter, adapter->if_handle, netdev->mc_list, - netdev_mc_count(netdev), &adapter->mc_cmd_mem); + be_cmd_multicast_set(adapter, adapter->if_handle, netdev, + &adapter->mc_cmd_mem); done: return; } -- cgit v1.2.3 From f31e50a802baae939c49819b8acd8f077019d398 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Tue, 2 Mar 2010 03:56:39 -0800 Subject: be2net: fix tx completion polling In tx/mcc polling, napi_complete() is being incorrectly called before reaping tx completions. This can cause tx compl processing to be scheduled on another cpu concurrently which can result in a panic. This if fixed by calling napi complete() after tx/mcc compl processing but before re-enabling interrupts (via a cq notify). Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 47 ++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 24 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 27ccdd80257b..a703ed8e24fe 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -583,7 +583,7 @@ static void be_set_multicast_list(struct net_device *netdev) } be_cmd_multicast_set(adapter, adapter->if_handle, netdev, - &adapter->mc_cmd_mem); + &adapter->mc_cmd_mem); done: return; } @@ -1469,23 +1469,38 @@ int be_poll_rx(struct napi_struct *napi, int budget) return work_done; } -void be_process_tx(struct be_adapter *adapter) +/* As TX and MCC share the same EQ check for both TX and MCC completions. + * For TX/MCC we don't honour budget; consume everything + */ +static int be_poll_tx_mcc(struct napi_struct *napi, int budget) { + struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); + struct be_adapter *adapter = + container_of(tx_eq, struct be_adapter, tx_eq); struct be_queue_info *txq = &adapter->tx_obj.q; struct be_queue_info *tx_cq = &adapter->tx_obj.cq; struct be_eth_tx_compl *txcp; - u32 num_cmpl = 0; + int tx_compl = 0, mcc_compl, status = 0; u16 end_idx; while ((txcp = be_tx_compl_get(tx_cq))) { end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, - wrb_index, txcp); + wrb_index, txcp); be_tx_compl_process(adapter, end_idx); - num_cmpl++; + tx_compl++; } - if (num_cmpl) { - be_cq_notify(adapter, tx_cq->id, true, num_cmpl); + mcc_compl = be_process_mcc(adapter, &status); + + napi_complete(napi); + + if (mcc_compl) { + struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; + be_cq_notify(adapter, mcc_obj->cq.id, true, mcc_compl); + } + + if (tx_compl) { + be_cq_notify(adapter, adapter->tx_obj.cq.id, true, tx_compl); /* As Tx wrbs have been freed up, wake up netdev queue if * it was stopped due to lack of tx wrbs. @@ -1496,24 +1511,8 @@ void be_process_tx(struct be_adapter *adapter) } drvr_stats(adapter)->be_tx_events++; - drvr_stats(adapter)->be_tx_compl += num_cmpl; + drvr_stats(adapter)->be_tx_compl += tx_compl; } -} - -/* As TX and MCC share the same EQ check for both TX and MCC completions. - * For TX/MCC we don't honour budget; consume everything - */ -static int be_poll_tx_mcc(struct napi_struct *napi, int budget) -{ - struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); - struct be_adapter *adapter = - container_of(tx_eq, struct be_adapter, tx_eq); - - napi_complete(napi); - - be_process_tx(adapter); - - be_process_mcc(adapter); return 1; } -- cgit v1.2.3 From 9fe969345b10931319b3f1e7034fbdeb786de234 Mon Sep 17 00:00:00 2001 From: Sarveshwar Bandi Date: Tue, 2 Mar 2010 22:37:28 +0000 Subject: be2net: download NCSI section during firmware update Adding code to update NCSI section while updating firmware on the controller. Signed-off-by: Sarveshwar Bandi Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index a703ed8e24fe..22f787f2a30b 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1880,8 +1880,9 @@ static int be_flash_data(struct be_adapter *adapter, const u8 *p = fw->data; struct be_cmd_write_flashrom *req = flash_cmd->va; struct flash_comp *pflashcomp; + int num_comp; - struct flash_comp gen3_flash_types[8] = { + struct flash_comp gen3_flash_types[9] = { { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE, FLASH_IMAGE_MAX_SIZE_g3}, { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT, @@ -1897,7 +1898,9 @@ static int be_flash_data(struct be_adapter *adapter, { FLASH_FCoE_PRIMARY_IMAGE_START_g3, IMG_TYPE_FCOE_FW_ACTIVE, FLASH_IMAGE_MAX_SIZE_g3}, { FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP, - FLASH_IMAGE_MAX_SIZE_g3} + FLASH_IMAGE_MAX_SIZE_g3}, + { FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW, + FLASH_NCSI_IMAGE_MAX_SIZE_g3} }; struct flash_comp gen2_flash_types[8] = { { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE, @@ -1921,11 +1924,16 @@ static int be_flash_data(struct be_adapter *adapter, if (adapter->generation == BE_GEN3) { pflashcomp = gen3_flash_types; filehdr_size = sizeof(struct flash_file_hdr_g3); + num_comp = 9; } else { pflashcomp = gen2_flash_types; filehdr_size = sizeof(struct flash_file_hdr_g2); + num_comp = 8; } - for (i = 0; i < 8; i++) { + for (i = 0; i < num_comp; i++) { + if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) && + memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) + continue; if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) && (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset, pflashcomp[i].size, -- cgit v1.2.3 From 500ca9ba241304937c54c379e515b24400379353 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Sun, 7 Mar 2010 14:21:27 +0000 Subject: be2net: remove usage of be_pci_func When PCI functions are virtuialized in applications by assigning PCI functions to VM (PCI passthrough), the be2net driver in the VM sees a different function number. So, use of PCI function number in any calculation will break existing code. This patch takes care of it. Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 22f787f2a30b..7c9b57eb780e 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1382,7 +1382,7 @@ rx_eq_free: /* There are 8 evt ids per func. Retruns the evt id's bit number */ static inline int be_evt_bit_get(struct be_adapter *adapter, u32 eq_id) { - return eq_id - 8 * be_pci_func(adapter); + return eq_id % 8; } static irqreturn_t be_intx(int irq, void *dev) -- cgit v1.2.3 From 7e8a9298adf7531c58d73ba9c499353e3807cf19 Mon Sep 17 00:00:00 2001 From: Ajit Khaparde Date: Sun, 7 Mar 2010 14:23:44 +0000 Subject: be2net: remove unused code in be_load_fw This patch cleans up some unused code from be_load_fw(). Signed-off-by: Ajit Khaparde Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/net/benet/be_main.c') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 7c9b57eb780e..43e8032f9236 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1993,16 +1993,7 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) struct be_dma_mem flash_cmd; int status, i = 0; const u8 *p; - char fw_ver[FW_VER_LEN]; - char fw_cfg; - status = be_cmd_get_fw_ver(adapter, fw_ver); - if (status) - return status; - - fw_cfg = *(fw_ver + 2); - if (fw_cfg == '0') - fw_cfg = '1'; strcpy(fw_file, func); status = request_firmware(&fw, fw_file, &adapter->pdev->dev); -- cgit v1.2.3