Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/1197507/?format=api
{ "id": 1197507, "url": "http://patchwork.ozlabs.org/api/patches/1197507/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20191119114540.42607-1-sasha.neftin@intel.com/", "project": { "id": 46, "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api", "name": "Intel Wired Ethernet development", "link_name": "intel-wired-lan", "list_id": "intel-wired-lan.osuosl.org", "list_email": "intel-wired-lan@osuosl.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20191119114540.42607-1-sasha.neftin@intel.com>", "list_archive_url": null, "date": "2019-11-19T11:45:40", "name": "[v1,15/15] igc: Remove no need declaration of the igc_sw_init", "commit_ref": null, "pull_url": null, "state": "accepted", "archived": false, "hash": "87804f9cae0b69f9a5ed80ac2691ca6baa83f0c7", "submitter": { "id": 69860, "url": "http://patchwork.ozlabs.org/api/people/69860/?format=api", "name": "Sasha Neftin", "email": "sasha.neftin@intel.com" }, "delegate": { "id": 68, "url": "http://patchwork.ozlabs.org/api/users/68/?format=api", "username": "jtkirshe", "first_name": "Jeff", "last_name": "Kirsher", "email": "jeffrey.t.kirsher@intel.com" }, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20191119114540.42607-1-sasha.neftin@intel.com/mbox/", "series": [ { "id": 143759, "url": "http://patchwork.ozlabs.org/api/series/143759/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=143759", "date": "2019-11-19T11:43:32", "name": "[v1,01/15] igc: Remove no need declaration of the igc_clean_tx_ring", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/143759/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/1197507/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/1197507/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@osuosl.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Delivered-To": [ "patchwork-incoming@bilbo.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Authentication-Results": [ "ozlabs.org; spf=pass (sender SPF authorized)\n\tsmtp.mailfrom=osuosl.org (client-ip=140.211.166.138;\n\thelo=whitealder.osuosl.org;\n\tenvelope-from=intel-wired-lan-bounces@osuosl.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdmarc=fail (p=none dis=none) header.from=intel.com" ], "Received": [ "from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256\n\tbits)) (No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 47HV7x6wNVz9sPn\n\tfor <incoming@patchwork.ozlabs.org>;\n\tWed, 20 Nov 2019 02:27:51 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 9179284BC2;\n\tTue, 19 Nov 2019 15:27:48 +0000 (UTC)", "from whitealder.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id KgTuTgzUI+Ef; Tue, 19 Nov 2019 15:27:35 +0000 (UTC)", "from ash.osuosl.org (ash.osuosl.org [140.211.166.34])\n\tby whitealder.osuosl.org (Postfix) with ESMTP id 1EBAA8272B;\n\tTue, 19 Nov 2019 15:27:35 +0000 (UTC)", "from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133])\n\tby ash.osuosl.org (Postfix) with ESMTP id C193B1BF83B\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 19 Nov 2019 11:45:50 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n\tby hemlock.osuosl.org (Postfix) with ESMTP id B1C1988309\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 19 Nov 2019 11:45:50 +0000 (UTC)", "from hemlock.osuosl.org ([127.0.0.1])\n\tby localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024)\n\twith ESMTP id 9UgjIwgrapCt for <intel-wired-lan@lists.osuosl.org>;\n\tTue, 19 Nov 2019 11:45:45 +0000 (UTC)", "from mga07.intel.com (mga07.intel.com [134.134.136.100])\n\tby hemlock.osuosl.org (Postfix) with ESMTPS id 48DD986963\n\tfor <intel-wired-lan@lists.osuosl.org>;\n\tTue, 19 Nov 2019 11:45:45 +0000 (UTC)", "from fmsmga003.fm.intel.com ([10.253.24.29])\n\tby orsmga105.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t19 Nov 2019 03:45:44 -0800", "from ccdlinuxdev08.iil.intel.com ([143.185.161.150])\n\tby FMSMGA003.fm.intel.com with ESMTP; 19 Nov 2019 03:45:41 -0800" ], "X-Virus-Scanned": [ "amavisd-new at osuosl.org", "amavisd-new at osuosl.org" ], "X-Greylist": "domain auto-whitelisted by SQLgrey-1.7.6", "X-Amp-Result": "SKIPPED(no attachment in message)", "X-Amp-File-Uploaded": "False", "X-ExtLoop1": "1", "X-IronPort-AV": "E=Sophos;i=\"5.68,322,1569308400\"; d=\"scan'208\";a=\"258701546\"", "From": "Sasha Neftin <sasha.neftin@intel.com>", "To": "intel-wired-lan@lists.osuosl.org", "Date": "Tue, 19 Nov 2019 13:45:40 +0200", "Message-Id": "<20191119114540.42607-1-sasha.neftin@intel.com>", "X-Mailer": "git-send-email 2.11.0", "X-Mailman-Approved-At": "Tue, 19 Nov 2019 15:27:33 +0000", "Subject": "[Intel-wired-lan] [PATCH v1 15/15] igc: Remove no need declaration\n\tof the igc_sw_init", "X-BeenThere": "intel-wired-lan@osuosl.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n\t<intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>", "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>, \n\t<mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"us-ascii\"", "Content-Transfer-Encoding": "7bit", "Errors-To": "intel-wired-lan-bounces@osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>" }, "content": "We want to avoid forward-declarations of function if possible.\nRearrange the igc_sw_init function implementation.\n\nSigned-off-by: Sasha Neftin <sasha.neftin@intel.com>\n---\n drivers/net/ethernet/intel/igc/igc_main.c | 2733 ++++++++++++++---------------\n 1 file changed, 1365 insertions(+), 1368 deletions(-)", "diff": "diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c\nindex 309e9694633a..d01ed6c55033 100644\n--- a/drivers/net/ethernet/intel/igc/igc_main.c\n+++ b/drivers/net/ethernet/intel/igc/igc_main.c\n@@ -51,9 +51,6 @@ static const struct pci_device_id igc_pci_tbl[] = {\n \n MODULE_DEVICE_TABLE(pci, igc_pci_tbl);\n \n-/* forward declaration */\n-static int igc_sw_init(struct igc_adapter *);\n-\n enum latency_range {\n \tlowest_latency = 0,\n \tlow_latency = 1,\n@@ -2354,1230 +2351,1302 @@ static void igc_irq_disable(struct igc_adapter *adapter)\n \t}\n }\n \n+void igc_set_flag_queue_pairs(struct igc_adapter *adapter,\n+\t\t\t const u32 max_rss_queues)\n+{\n+\t/* Determine if we need to pair queues. */\n+\t/* If rss_queues > half of max_rss_queues, pair the queues in\n+\t * order to conserve interrupts due to limited supply.\n+\t */\n+\tif (adapter->rss_queues > (max_rss_queues / 2))\n+\t\tadapter->flags |= IGC_FLAG_QUEUE_PAIRS;\n+\telse\n+\t\tadapter->flags &= ~IGC_FLAG_QUEUE_PAIRS;\n+}\n+\n+unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter)\n+{\n+\tunsigned int max_rss_queues;\n+\n+\t/* Determine the maximum number of RSS queues supported. */\n+\tmax_rss_queues = IGC_MAX_RX_QUEUES;\n+\n+\treturn max_rss_queues;\n+}\n+\n+static void igc_init_queue_configuration(struct igc_adapter *adapter)\n+{\n+\tu32 max_rss_queues;\n+\n+\tmax_rss_queues = igc_get_max_rss_queues(adapter);\n+\tadapter->rss_queues = min_t(u32, max_rss_queues, num_online_cpus());\n+\n+\tigc_set_flag_queue_pairs(adapter, max_rss_queues);\n+}\n+\n /**\n- * igc_up - Open the interface and prepare it to handle traffic\n- * @adapter: board private structure\n+ * igc_reset_q_vector - Reset config for interrupt vector\n+ * @adapter: board private structure to initialize\n+ * @v_idx: Index of vector to be reset\n+ *\n+ * If NAPI is enabled it will delete any references to the\n+ * NAPI struct. This is preparation for igc_free_q_vector.\n */\n-void igc_up(struct igc_adapter *adapter)\n+static void igc_reset_q_vector(struct igc_adapter *adapter, int v_idx)\n {\n-\tstruct igc_hw *hw = &adapter->hw;\n-\tint i = 0;\n+\tstruct igc_q_vector *q_vector = adapter->q_vector[v_idx];\n \n-\t/* hardware has been reset, we need to reload some things */\n-\tigc_configure(adapter);\n+\t/* if we're coming from igc_set_interrupt_capability, the vectors are\n+\t * not yet allocated\n+\t */\n+\tif (!q_vector)\n+\t\treturn;\n \n-\tclear_bit(__IGC_DOWN, &adapter->state);\n+\tif (q_vector->tx.ring)\n+\t\tadapter->tx_ring[q_vector->tx.ring->queue_index] = NULL;\n \n-\tfor (i = 0; i < adapter->num_q_vectors; i++)\n-\t\tnapi_enable(&adapter->q_vector[i]->napi);\n+\tif (q_vector->rx.ring)\n+\t\tadapter->rx_ring[q_vector->rx.ring->queue_index] = NULL;\n \n-\tif (adapter->msix_entries)\n-\t\tigc_configure_msix(adapter);\n-\telse\n-\t\tigc_assign_vector(adapter->q_vector[0], 0);\n+\tnetif_napi_del(&q_vector->napi);\n+}\n \n-\t/* Clear any pending interrupts. */\n-\trd32(IGC_ICR);\n-\tigc_irq_enable(adapter);\n+/**\n+ * igc_free_q_vector - Free memory allocated for specific interrupt vector\n+ * @adapter: board private structure to initialize\n+ * @v_idx: Index of vector to be freed\n+ *\n+ * This function frees the memory allocated to the q_vector.\n+ */\n+static void igc_free_q_vector(struct igc_adapter *adapter, int v_idx)\n+{\n+\tstruct igc_q_vector *q_vector = adapter->q_vector[v_idx];\n \n-\tnetif_tx_start_all_queues(adapter->netdev);\n+\tadapter->q_vector[v_idx] = NULL;\n \n-\t/* start the watchdog. */\n-\thw->mac.get_link_status = 1;\n-\tschedule_work(&adapter->watchdog_task);\n+\t/* igc_get_stats64() might access the rings on this vector,\n+\t * we must wait a grace period before freeing it.\n+\t */\n+\tif (q_vector)\n+\t\tkfree_rcu(q_vector, rcu);\n }\n \n /**\n- * igc_update_stats - Update the board statistics counters\n- * @adapter: board private structure\n+ * igc_free_q_vectors - Free memory allocated for interrupt vectors\n+ * @adapter: board private structure to initialize\n+ *\n+ * This function frees the memory allocated to the q_vectors. In addition if\n+ * NAPI is enabled it will delete any references to the NAPI struct prior\n+ * to freeing the q_vector.\n */\n-void igc_update_stats(struct igc_adapter *adapter)\n+static void igc_free_q_vectors(struct igc_adapter *adapter)\n {\n-\tstruct rtnl_link_stats64 *net_stats = &adapter->stats64;\n-\tstruct pci_dev *pdev = adapter->pdev;\n-\tstruct igc_hw *hw = &adapter->hw;\n-\tu64 _bytes, _packets;\n-\tu64 bytes, packets;\n-\tunsigned int start;\n-\tu32 mpc;\n-\tint i;\n+\tint v_idx = adapter->num_q_vectors;\n \n-\t/* Prevent stats update while adapter is being reset, or if the pci\n-\t * connection is down.\n-\t */\n-\tif (adapter->link_speed == 0)\n-\t\treturn;\n-\tif (pci_channel_offline(pdev))\n-\t\treturn;\n+\tadapter->num_tx_queues = 0;\n+\tadapter->num_rx_queues = 0;\n+\tadapter->num_q_vectors = 0;\n \n-\tpackets = 0;\n-\tbytes = 0;\n+\twhile (v_idx--) {\n+\t\tigc_reset_q_vector(adapter, v_idx);\n+\t\tigc_free_q_vector(adapter, v_idx);\n+\t}\n+}\n \n-\trcu_read_lock();\n-\tfor (i = 0; i < adapter->num_rx_queues; i++) {\n-\t\tstruct igc_ring *ring = adapter->rx_ring[i];\n-\t\tu32 rqdpc = rd32(IGC_RQDPC(i));\n+/**\n+ * igc_update_itr - update the dynamic ITR value based on statistics\n+ * @q_vector: pointer to q_vector\n+ * @ring_container: ring info to update the itr for\n+ *\n+ * Stores a new ITR value based on packets and byte\n+ * counts during the last interrupt. The advantage of per interrupt\n+ * computation is faster updates and more accurate ITR for the current\n+ * traffic pattern. Constants in this function were computed\n+ * based on theoretical maximum wire speed and thresholds were set based\n+ * on testing data as well as attempting to minimize response time\n+ * while increasing bulk throughput.\n+ * NOTE: These calculations are only valid when operating in a single-\n+ * queue environment.\n+ */\n+static void igc_update_itr(struct igc_q_vector *q_vector,\n+\t\t\t struct igc_ring_container *ring_container)\n+{\n+\tunsigned int packets = ring_container->total_packets;\n+\tunsigned int bytes = ring_container->total_bytes;\n+\tu8 itrval = ring_container->itr;\n \n-\t\tif (hw->mac.type >= igc_i225)\n-\t\t\twr32(IGC_RQDPC(i), 0);\n+\t/* no packets, exit with status unchanged */\n+\tif (packets == 0)\n+\t\treturn;\n \n-\t\tif (rqdpc) {\n-\t\t\tring->rx_stats.drops += rqdpc;\n-\t\t\tnet_stats->rx_fifo_errors += rqdpc;\n+\tswitch (itrval) {\n+\tcase lowest_latency:\n+\t\t/* handle TSO and jumbo frames */\n+\t\tif (bytes / packets > 8000)\n+\t\t\titrval = bulk_latency;\n+\t\telse if ((packets < 5) && (bytes > 512))\n+\t\t\titrval = low_latency;\n+\t\tbreak;\n+\tcase low_latency: /* 50 usec aka 20000 ints/s */\n+\t\tif (bytes > 10000) {\n+\t\t\t/* this if handles the TSO accounting */\n+\t\t\tif (bytes / packets > 8000)\n+\t\t\t\titrval = bulk_latency;\n+\t\t\telse if ((packets < 10) || ((bytes / packets) > 1200))\n+\t\t\t\titrval = bulk_latency;\n+\t\t\telse if ((packets > 35))\n+\t\t\t\titrval = lowest_latency;\n+\t\t} else if (bytes / packets > 2000) {\n+\t\t\titrval = bulk_latency;\n+\t\t} else if (packets <= 2 && bytes < 512) {\n+\t\t\titrval = lowest_latency;\n \t\t}\n-\n-\t\tdo {\n-\t\t\tstart = u64_stats_fetch_begin_irq(&ring->rx_syncp);\n-\t\t\t_bytes = ring->rx_stats.bytes;\n-\t\t\t_packets = ring->rx_stats.packets;\n-\t\t} while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start));\n-\t\tbytes += _bytes;\n-\t\tpackets += _packets;\n+\t\tbreak;\n+\tcase bulk_latency: /* 250 usec aka 4000 ints/s */\n+\t\tif (bytes > 25000) {\n+\t\t\tif (packets > 35)\n+\t\t\t\titrval = low_latency;\n+\t\t} else if (bytes < 1500) {\n+\t\t\titrval = low_latency;\n+\t\t}\n+\t\tbreak;\n \t}\n \n-\tnet_stats->rx_bytes = bytes;\n-\tnet_stats->rx_packets = packets;\n+\t/* clear work counters since we have the values we need */\n+\tring_container->total_bytes = 0;\n+\tring_container->total_packets = 0;\n \n-\tpackets = 0;\n-\tbytes = 0;\n-\tfor (i = 0; i < adapter->num_tx_queues; i++) {\n-\t\tstruct igc_ring *ring = adapter->tx_ring[i];\n+\t/* write updated itr to ring container */\n+\tring_container->itr = itrval;\n+}\n \n-\t\tdo {\n-\t\t\tstart = u64_stats_fetch_begin_irq(&ring->tx_syncp);\n-\t\t\t_bytes = ring->tx_stats.bytes;\n-\t\t\t_packets = ring->tx_stats.packets;\n-\t\t} while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start));\n-\t\tbytes += _bytes;\n-\t\tpackets += _packets;\n+static void igc_set_itr(struct igc_q_vector *q_vector)\n+{\n+\tstruct igc_adapter *adapter = q_vector->adapter;\n+\tu32 new_itr = q_vector->itr_val;\n+\tu8 current_itr = 0;\n+\n+\t/* for non-gigabit speeds, just fix the interrupt rate at 4000 */\n+\tswitch (adapter->link_speed) {\n+\tcase SPEED_10:\n+\tcase SPEED_100:\n+\t\tcurrent_itr = 0;\n+\t\tnew_itr = IGC_4K_ITR;\n+\t\tgoto set_itr_now;\n+\tdefault:\n+\t\tbreak;\n \t}\n-\tnet_stats->tx_bytes = bytes;\n-\tnet_stats->tx_packets = packets;\n-\trcu_read_unlock();\n \n-\t/* read stats registers */\n-\tadapter->stats.crcerrs += rd32(IGC_CRCERRS);\n-\tadapter->stats.gprc += rd32(IGC_GPRC);\n-\tadapter->stats.gorc += rd32(IGC_GORCL);\n-\trd32(IGC_GORCH); /* clear GORCL */\n-\tadapter->stats.bprc += rd32(IGC_BPRC);\n-\tadapter->stats.mprc += rd32(IGC_MPRC);\n-\tadapter->stats.roc += rd32(IGC_ROC);\n+\tigc_update_itr(q_vector, &q_vector->tx);\n+\tigc_update_itr(q_vector, &q_vector->rx);\n \n-\tadapter->stats.prc64 += rd32(IGC_PRC64);\n-\tadapter->stats.prc127 += rd32(IGC_PRC127);\n-\tadapter->stats.prc255 += rd32(IGC_PRC255);\n-\tadapter->stats.prc511 += rd32(IGC_PRC511);\n-\tadapter->stats.prc1023 += rd32(IGC_PRC1023);\n-\tadapter->stats.prc1522 += rd32(IGC_PRC1522);\n-\tadapter->stats.symerrs += rd32(IGC_SYMERRS);\n-\tadapter->stats.sec += rd32(IGC_SEC);\n+\tcurrent_itr = max(q_vector->rx.itr, q_vector->tx.itr);\n \n-\tmpc = rd32(IGC_MPC);\n-\tadapter->stats.mpc += mpc;\n-\tnet_stats->rx_fifo_errors += mpc;\n-\tadapter->stats.scc += rd32(IGC_SCC);\n-\tadapter->stats.ecol += rd32(IGC_ECOL);\n-\tadapter->stats.mcc += rd32(IGC_MCC);\n-\tadapter->stats.latecol += rd32(IGC_LATECOL);\n-\tadapter->stats.dc += rd32(IGC_DC);\n-\tadapter->stats.rlec += rd32(IGC_RLEC);\n-\tadapter->stats.xonrxc += rd32(IGC_XONRXC);\n-\tadapter->stats.xontxc += rd32(IGC_XONTXC);\n-\tadapter->stats.xoffrxc += rd32(IGC_XOFFRXC);\n-\tadapter->stats.xofftxc += rd32(IGC_XOFFTXC);\n-\tadapter->stats.fcruc += rd32(IGC_FCRUC);\n-\tadapter->stats.gptc += rd32(IGC_GPTC);\n-\tadapter->stats.gotc += rd32(IGC_GOTCL);\n-\trd32(IGC_GOTCH); /* clear GOTCL */\n-\tadapter->stats.rnbc += rd32(IGC_RNBC);\n-\tadapter->stats.ruc += rd32(IGC_RUC);\n-\tadapter->stats.rfc += rd32(IGC_RFC);\n-\tadapter->stats.rjc += rd32(IGC_RJC);\n-\tadapter->stats.tor += rd32(IGC_TORH);\n-\tadapter->stats.tot += rd32(IGC_TOTH);\n-\tadapter->stats.tpr += rd32(IGC_TPR);\n-\n-\tadapter->stats.ptc64 += rd32(IGC_PTC64);\n-\tadapter->stats.ptc127 += rd32(IGC_PTC127);\n-\tadapter->stats.ptc255 += rd32(IGC_PTC255);\n-\tadapter->stats.ptc511 += rd32(IGC_PTC511);\n-\tadapter->stats.ptc1023 += rd32(IGC_PTC1023);\n-\tadapter->stats.ptc1522 += rd32(IGC_PTC1522);\n-\n-\tadapter->stats.mptc += rd32(IGC_MPTC);\n-\tadapter->stats.bptc += rd32(IGC_BPTC);\n-\n-\tadapter->stats.tpt += rd32(IGC_TPT);\n-\tadapter->stats.colc += rd32(IGC_COLC);\n-\n-\tadapter->stats.algnerrc += rd32(IGC_ALGNERRC);\n-\n-\tadapter->stats.tsctc += rd32(IGC_TSCTC);\n-\tadapter->stats.tsctfc += rd32(IGC_TSCTFC);\n-\n-\tadapter->stats.iac += rd32(IGC_IAC);\n-\tadapter->stats.icrxoc += rd32(IGC_ICRXOC);\n-\tadapter->stats.icrxptc += rd32(IGC_ICRXPTC);\n-\tadapter->stats.icrxatc += rd32(IGC_ICRXATC);\n-\tadapter->stats.ictxptc += rd32(IGC_ICTXPTC);\n-\tadapter->stats.ictxatc += rd32(IGC_ICTXATC);\n-\tadapter->stats.ictxqec += rd32(IGC_ICTXQEC);\n-\tadapter->stats.ictxqmtc += rd32(IGC_ICTXQMTC);\n-\tadapter->stats.icrxdmtc += rd32(IGC_ICRXDMTC);\n-\n-\t/* Fill out the OS statistics structure */\n-\tnet_stats->multicast = adapter->stats.mprc;\n-\tnet_stats->collisions = adapter->stats.colc;\n-\n-\t/* Rx Errors */\n-\n-\t/* RLEC on some newer hardware can be incorrect so build\n-\t * our own version based on RUC and ROC\n-\t */\n-\tnet_stats->rx_errors = adapter->stats.rxerrc +\n-\t\tadapter->stats.crcerrs + adapter->stats.algnerrc +\n-\t\tadapter->stats.ruc + adapter->stats.roc +\n-\t\tadapter->stats.cexterr;\n-\tnet_stats->rx_length_errors = adapter->stats.ruc +\n-\t\t\t\t adapter->stats.roc;\n-\tnet_stats->rx_crc_errors = adapter->stats.crcerrs;\n-\tnet_stats->rx_frame_errors = adapter->stats.algnerrc;\n-\tnet_stats->rx_missed_errors = adapter->stats.mpc;\n-\n-\t/* Tx Errors */\n-\tnet_stats->tx_errors = adapter->stats.ecol +\n-\t\t\t adapter->stats.latecol;\n-\tnet_stats->tx_aborted_errors = adapter->stats.ecol;\n-\tnet_stats->tx_window_errors = adapter->stats.latecol;\n-\tnet_stats->tx_carrier_errors = adapter->stats.tncrs;\n+\t/* conservative mode (itr 3) eliminates the lowest_latency setting */\n+\tif (current_itr == lowest_latency &&\n+\t ((q_vector->rx.ring && adapter->rx_itr_setting == 3) ||\n+\t (!q_vector->rx.ring && adapter->tx_itr_setting == 3)))\n+\t\tcurrent_itr = low_latency;\n \n-\t/* Tx Dropped needs to be maintained elsewhere */\n+\tswitch (current_itr) {\n+\t/* counts and packets in update_itr are dependent on these numbers */\n+\tcase lowest_latency:\n+\t\tnew_itr = IGC_70K_ITR; /* 70,000 ints/sec */\n+\t\tbreak;\n+\tcase low_latency:\n+\t\tnew_itr = IGC_20K_ITR; /* 20,000 ints/sec */\n+\t\tbreak;\n+\tcase bulk_latency:\n+\t\tnew_itr = IGC_4K_ITR; /* 4,000 ints/sec */\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n \n-\t/* Management Stats */\n-\tadapter->stats.mgptc += rd32(IGC_MGTPTC);\n-\tadapter->stats.mgprc += rd32(IGC_MGTPRC);\n-\tadapter->stats.mgpdc += rd32(IGC_MGTPDC);\n+set_itr_now:\n+\tif (new_itr != q_vector->itr_val) {\n+\t\t/* this attempts to bias the interrupt rate towards Bulk\n+\t\t * by adding intermediate steps when interrupt rate is\n+\t\t * increasing\n+\t\t */\n+\t\tnew_itr = new_itr > q_vector->itr_val ?\n+\t\t\t max((new_itr * q_vector->itr_val) /\n+\t\t\t (new_itr + (q_vector->itr_val >> 2)),\n+\t\t\t new_itr) : new_itr;\n+\t\t/* Don't write the value here; it resets the adapter's\n+\t\t * internal timer, and causes us to delay far longer than\n+\t\t * we should between interrupts. Instead, we write the ITR\n+\t\t * value at the beginning of the next interrupt so the timing\n+\t\t * ends up being correct.\n+\t\t */\n+\t\tq_vector->itr_val = new_itr;\n+\t\tq_vector->set_itr = 1;\n+\t}\n }\n \n-static void igc_nfc_filter_exit(struct igc_adapter *adapter)\n+static void igc_reset_interrupt_capability(struct igc_adapter *adapter)\n {\n-\tstruct igc_nfc_filter *rule;\n-\n-\tspin_lock(&adapter->nfc_lock);\n-\n-\thlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node)\n-\t\tigc_erase_filter(adapter, rule);\n+\tint v_idx = adapter->num_q_vectors;\n \n-\thlist_for_each_entry(rule, &adapter->cls_flower_list, nfc_node)\n-\t\tigc_erase_filter(adapter, rule);\n+\tif (adapter->msix_entries) {\n+\t\tpci_disable_msix(adapter->pdev);\n+\t\tkfree(adapter->msix_entries);\n+\t\tadapter->msix_entries = NULL;\n+\t} else if (adapter->flags & IGC_FLAG_HAS_MSI) {\n+\t\tpci_disable_msi(adapter->pdev);\n+\t}\n \n-\tspin_unlock(&adapter->nfc_lock);\n+\twhile (v_idx--)\n+\t\tigc_reset_q_vector(adapter, v_idx);\n }\n \n /**\n- * igc_down - Close the interface\n- * @adapter: board private structure\n+ * igc_set_interrupt_capability - set MSI or MSI-X if supported\n+ * @adapter: Pointer to adapter structure\n+ * @msix: boolean value for MSI-X capability\n+ *\n+ * Attempt to configure interrupts using the best available\n+ * capabilities of the hardware and kernel.\n */\n-void igc_down(struct igc_adapter *adapter)\n+static void igc_set_interrupt_capability(struct igc_adapter *adapter,\n+\t\t\t\t\t bool msix)\n {\n-\tstruct net_device *netdev = adapter->netdev;\n-\tstruct igc_hw *hw = &adapter->hw;\n-\tu32 tctl, rctl;\n-\tint i = 0;\n-\n-\tset_bit(__IGC_DOWN, &adapter->state);\n-\n-\t/* disable receives in the hardware */\n-\trctl = rd32(IGC_RCTL);\n-\twr32(IGC_RCTL, rctl & ~IGC_RCTL_EN);\n-\t/* flush and sleep below */\n-\n-\tigc_nfc_filter_exit(adapter);\n-\n-\t/* set trans_start so we don't get spurious watchdogs during reset */\n-\tnetif_trans_update(netdev);\n+\tint numvecs, i;\n+\tint err;\n \n-\tnetif_carrier_off(netdev);\n-\tnetif_tx_stop_all_queues(netdev);\n+\tif (!msix)\n+\t\tgoto msi_only;\n+\tadapter->flags |= IGC_FLAG_HAS_MSIX;\n \n-\t/* disable transmits in the hardware */\n-\ttctl = rd32(IGC_TCTL);\n-\ttctl &= ~IGC_TCTL_EN;\n-\twr32(IGC_TCTL, tctl);\n-\t/* flush both disables and wait for them to finish */\n-\twrfl();\n-\tusleep_range(10000, 20000);\n+\t/* Number of supported queues. */\n+\tadapter->num_rx_queues = adapter->rss_queues;\n \n-\tigc_irq_disable(adapter);\n+\tadapter->num_tx_queues = adapter->rss_queues;\n \n-\tadapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;\n+\t/* start with one vector for every Rx queue */\n+\tnumvecs = adapter->num_rx_queues;\n \n-\tfor (i = 0; i < adapter->num_q_vectors; i++) {\n-\t\tif (adapter->q_vector[i]) {\n-\t\t\tnapi_synchronize(&adapter->q_vector[i]->napi);\n-\t\t\tnapi_disable(&adapter->q_vector[i]->napi);\n-\t\t}\n-\t}\n+\t/* if Tx handler is separate add 1 for every Tx queue */\n+\tif (!(adapter->flags & IGC_FLAG_QUEUE_PAIRS))\n+\t\tnumvecs += adapter->num_tx_queues;\n \n-\tdel_timer_sync(&adapter->watchdog_timer);\n-\tdel_timer_sync(&adapter->phy_info_timer);\n+\t/* store the number of vectors reserved for queues */\n+\tadapter->num_q_vectors = numvecs;\n \n-\t/* record the stats before reset*/\n-\tspin_lock(&adapter->stats64_lock);\n-\tigc_update_stats(adapter);\n-\tspin_unlock(&adapter->stats64_lock);\n+\t/* add 1 vector for link status interrupts */\n+\tnumvecs++;\n \n-\tadapter->link_speed = 0;\n-\tadapter->link_duplex = 0;\n+\tadapter->msix_entries = kcalloc(numvecs, sizeof(struct msix_entry),\n+\t\t\t\t\tGFP_KERNEL);\n \n-\tif (!pci_channel_offline(adapter->pdev))\n-\t\tigc_reset(adapter);\n+\tif (!adapter->msix_entries)\n+\t\treturn;\n \n-\t/* clear VLAN promisc flag so VFTA will be updated if necessary */\n-\tadapter->flags &= ~IGC_FLAG_VLAN_PROMISC;\n+\t/* populate entry values */\n+\tfor (i = 0; i < numvecs; i++)\n+\t\tadapter->msix_entries[i].entry = i;\n \n-\tigc_clean_all_tx_rings(adapter);\n-\tigc_clean_all_rx_rings(adapter);\n-}\n+\terr = pci_enable_msix_range(adapter->pdev,\n+\t\t\t\t adapter->msix_entries,\n+\t\t\t\t numvecs,\n+\t\t\t\t numvecs);\n+\tif (err > 0)\n+\t\treturn;\n \n-void igc_reinit_locked(struct igc_adapter *adapter)\n-{\n-\tWARN_ON(in_interrupt());\n-\twhile (test_and_set_bit(__IGC_RESETTING, &adapter->state))\n-\t\tusleep_range(1000, 2000);\n-\tigc_down(adapter);\n-\tigc_up(adapter);\n-\tclear_bit(__IGC_RESETTING, &adapter->state);\n-}\n+\tkfree(adapter->msix_entries);\n+\tadapter->msix_entries = NULL;\n \n-static void igc_reset_task(struct work_struct *work)\n-{\n-\tstruct igc_adapter *adapter;\n+\tigc_reset_interrupt_capability(adapter);\n \n-\tadapter = container_of(work, struct igc_adapter, reset_task);\n+msi_only:\n+\tadapter->flags &= ~IGC_FLAG_HAS_MSIX;\n \n-\tnetdev_err(adapter->netdev, \"Reset adapter\\n\");\n-\tigc_reinit_locked(adapter);\n+\tadapter->rss_queues = 1;\n+\tadapter->flags |= IGC_FLAG_QUEUE_PAIRS;\n+\tadapter->num_rx_queues = 1;\n+\tadapter->num_tx_queues = 1;\n+\tadapter->num_q_vectors = 1;\n+\tif (!pci_enable_msi(adapter->pdev))\n+\t\tadapter->flags |= IGC_FLAG_HAS_MSI;\n }\n \n /**\n- * igc_change_mtu - Change the Maximum Transfer Unit\n- * @netdev: network interface device structure\n- * @new_mtu: new value for maximum frame size\n+ * igc_update_ring_itr - update the dynamic ITR value based on packet size\n+ * @q_vector: pointer to q_vector\n *\n- * Returns 0 on success, negative on failure\n+ * Stores a new ITR value based on strictly on packet size. This\n+ * algorithm is less sophisticated than that used in igc_update_itr,\n+ * due to the difficulty of synchronizing statistics across multiple\n+ * receive rings. The divisors and thresholds used by this function\n+ * were determined based on theoretical maximum wire speed and testing\n+ * data, in order to minimize response time while increasing bulk\n+ * throughput.\n+ * NOTE: This function is called only when operating in a multiqueue\n+ * receive environment.\n */\n-static int igc_change_mtu(struct net_device *netdev, int new_mtu)\n+static void igc_update_ring_itr(struct igc_q_vector *q_vector)\n {\n-\tint max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;\n-\tstruct igc_adapter *adapter = netdev_priv(netdev);\n+\tstruct igc_adapter *adapter = q_vector->adapter;\n+\tint new_val = q_vector->itr_val;\n+\tint avg_wire_size = 0;\n+\tunsigned int packets;\n \n-\t/* adjust max frame to be at least the size of a standard frame */\n-\tif (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))\n-\t\tmax_frame = ETH_FRAME_LEN + ETH_FCS_LEN;\n+\t/* For non-gigabit speeds, just fix the interrupt rate at 4000\n+\t * ints/sec - ITR timer value of 120 ticks.\n+\t */\n+\tswitch (adapter->link_speed) {\n+\tcase SPEED_10:\n+\tcase SPEED_100:\n+\t\tnew_val = IGC_4K_ITR;\n+\t\tgoto set_itr_val;\n+\tdefault:\n+\t\tbreak;\n+\t}\n \n-\twhile (test_and_set_bit(__IGC_RESETTING, &adapter->state))\n-\t\tusleep_range(1000, 2000);\n+\tpackets = q_vector->rx.total_packets;\n+\tif (packets)\n+\t\tavg_wire_size = q_vector->rx.total_bytes / packets;\n \n-\t/* igc_down has a dependency on max_frame_size */\n-\tadapter->max_frame_size = max_frame;\n+\tpackets = q_vector->tx.total_packets;\n+\tif (packets)\n+\t\tavg_wire_size = max_t(u32, avg_wire_size,\n+\t\t\t\t q_vector->tx.total_bytes / packets);\n \n-\tif (netif_running(netdev))\n-\t\tigc_down(adapter);\n+\t/* if avg_wire_size isn't set no work was done */\n+\tif (!avg_wire_size)\n+\t\tgoto clear_counts;\n \n-\tnetdev_dbg(netdev, \"changing MTU from %d to %d\\n\",\n-\t\t netdev->mtu, new_mtu);\n-\tnetdev->mtu = new_mtu;\n+\t/* Add 24 bytes to size to account for CRC, preamble, and gap */\n+\tavg_wire_size += 24;\n \n-\tif (netif_running(netdev))\n-\t\tigc_up(adapter);\n+\t/* Don't starve jumbo frames */\n+\tavg_wire_size = min(avg_wire_size, 3000);\n+\n+\t/* Give a little boost to mid-size frames */\n+\tif (avg_wire_size > 300 && avg_wire_size < 1200)\n+\t\tnew_val = avg_wire_size / 3;\n \telse\n-\t\tigc_reset(adapter);\n+\t\tnew_val = avg_wire_size / 2;\n \n-\tclear_bit(__IGC_RESETTING, &adapter->state);\n+\t/* conservative mode (itr 3) eliminates the lowest_latency setting */\n+\tif (new_val < IGC_20K_ITR &&\n+\t ((q_vector->rx.ring && adapter->rx_itr_setting == 3) ||\n+\t (!q_vector->rx.ring && adapter->tx_itr_setting == 3)))\n+\t\tnew_val = IGC_20K_ITR;\n \n-\treturn 0;\n+set_itr_val:\n+\tif (new_val != q_vector->itr_val) {\n+\t\tq_vector->itr_val = new_val;\n+\t\tq_vector->set_itr = 1;\n+\t}\n+clear_counts:\n+\tq_vector->rx.total_bytes = 0;\n+\tq_vector->rx.total_packets = 0;\n+\tq_vector->tx.total_bytes = 0;\n+\tq_vector->tx.total_packets = 0;\n }\n \n-/**\n- * igc_get_stats - Get System Network Statistics\n- * @netdev: network interface device structure\n- *\n- * Returns the address of the device statistics structure.\n- * The statistics are updated here and also from the timer callback.\n- */\n-static struct net_device_stats *igc_get_stats(struct net_device *netdev)\n+static void igc_ring_irq_enable(struct igc_q_vector *q_vector)\n {\n-\tstruct igc_adapter *adapter = netdev_priv(netdev);\n+\tstruct igc_adapter *adapter = q_vector->adapter;\n+\tstruct igc_hw *hw = &adapter->hw;\n \n-\tif (!test_bit(__IGC_RESETTING, &adapter->state))\n-\t\tigc_update_stats(adapter);\n+\tif ((q_vector->rx.ring && (adapter->rx_itr_setting & 3)) ||\n+\t (!q_vector->rx.ring && (adapter->tx_itr_setting & 3))) {\n+\t\tif (adapter->num_q_vectors == 1)\n+\t\t\tigc_set_itr(q_vector);\n+\t\telse\n+\t\t\tigc_update_ring_itr(q_vector);\n+\t}\n \n-\t/* only return the current stats */\n-\treturn &netdev->stats;\n+\tif (!test_bit(__IGC_DOWN, &adapter->state)) {\n+\t\tif (adapter->msix_entries)\n+\t\t\twr32(IGC_EIMS, q_vector->eims_value);\n+\t\telse\n+\t\t\tigc_irq_enable(adapter);\n+\t}\n }\n \n-static netdev_features_t igc_fix_features(struct net_device *netdev,\n-\t\t\t\t\t netdev_features_t features)\n+static void igc_add_ring(struct igc_ring *ring,\n+\t\t\t struct igc_ring_container *head)\n {\n-\t/* Since there is no support for separate Rx/Tx vlan accel\n-\t * enable/disable make sure Tx flag is always in same state as Rx.\n-\t */\n-\tif (features & NETIF_F_HW_VLAN_CTAG_RX)\n-\t\tfeatures |= NETIF_F_HW_VLAN_CTAG_TX;\n-\telse\n-\t\tfeatures &= ~NETIF_F_HW_VLAN_CTAG_TX;\n-\n-\treturn features;\n+\thead->ring = ring;\n+\thead->count++;\n }\n \n-static int igc_set_features(struct net_device *netdev,\n-\t\t\t netdev_features_t features)\n+/**\n+ * igc_cache_ring_register - Descriptor ring to register mapping\n+ * @adapter: board private structure to initialize\n+ *\n+ * Once we know the feature-set enabled for the device, we'll cache\n+ * the register offset the descriptor ring is assigned to.\n+ */\n+static void igc_cache_ring_register(struct igc_adapter *adapter)\n {\n-\tnetdev_features_t changed = netdev->features ^ features;\n-\tstruct igc_adapter *adapter = netdev_priv(netdev);\n-\n-\t/* Add VLAN support */\n-\tif (!(changed & (NETIF_F_RXALL | NETIF_F_NTUPLE)))\n-\t\treturn 0;\n-\n-\tif (!(features & NETIF_F_NTUPLE)) {\n-\t\tstruct hlist_node *node2;\n-\t\tstruct igc_nfc_filter *rule;\n+\tint i = 0, j = 0;\n \n-\t\tspin_lock(&adapter->nfc_lock);\n-\t\thlist_for_each_entry_safe(rule, node2,\n-\t\t\t\t\t &adapter->nfc_filter_list, nfc_node) {\n-\t\t\tigc_erase_filter(adapter, rule);\n-\t\t\thlist_del(&rule->nfc_node);\n-\t\t\tkfree(rule);\n-\t\t}\n-\t\tspin_unlock(&adapter->nfc_lock);\n-\t\tadapter->nfc_filter_count = 0;\n+\tswitch (adapter->hw.mac.type) {\n+\tcase igc_i225:\n+\t/* Fall through */\n+\tdefault:\n+\t\tfor (; i < adapter->num_rx_queues; i++)\n+\t\t\tadapter->rx_ring[i]->reg_idx = i;\n+\t\tfor (; j < adapter->num_tx_queues; j++)\n+\t\t\tadapter->tx_ring[j]->reg_idx = j;\n+\t\tbreak;\n \t}\n-\n-\tnetdev->features = features;\n-\n-\tif (netif_running(netdev))\n-\t\tigc_reinit_locked(adapter);\n-\telse\n-\t\tigc_reset(adapter);\n-\n-\treturn 1;\n }\n \n-static netdev_features_t\n-igc_features_check(struct sk_buff *skb, struct net_device *dev,\n-\t\t netdev_features_t features)\n+/**\n+ * igc_poll - NAPI Rx polling callback\n+ * @napi: napi polling structure\n+ * @budget: count of how many packets we should handle\n+ */\n+static int igc_poll(struct napi_struct *napi, int budget)\n {\n-\tunsigned int network_hdr_len, mac_hdr_len;\n+\tstruct igc_q_vector *q_vector = container_of(napi,\n+\t\t\t\t\t\t struct igc_q_vector,\n+\t\t\t\t\t\t napi);\n+\tbool clean_complete = true;\n+\tint work_done = 0;\n \n-\t/* Make certain the headers can be described by a context descriptor */\n-\tmac_hdr_len = skb_network_header(skb) - skb->data;\n-\tif (unlikely(mac_hdr_len > IGC_MAX_MAC_HDR_LEN))\n-\t\treturn features & ~(NETIF_F_HW_CSUM |\n-\t\t\t\t NETIF_F_SCTP_CRC |\n-\t\t\t\t NETIF_F_HW_VLAN_CTAG_TX |\n-\t\t\t\t NETIF_F_TSO |\n-\t\t\t\t NETIF_F_TSO6);\n+\tif (q_vector->tx.ring)\n+\t\tclean_complete = igc_clean_tx_irq(q_vector, budget);\n \n-\tnetwork_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);\n-\tif (unlikely(network_hdr_len > IGC_MAX_NETWORK_HDR_LEN))\n-\t\treturn features & ~(NETIF_F_HW_CSUM |\n-\t\t\t\t NETIF_F_SCTP_CRC |\n-\t\t\t\t NETIF_F_TSO |\n-\t\t\t\t NETIF_F_TSO6);\n+\tif (q_vector->rx.ring) {\n+\t\tint cleaned = igc_clean_rx_irq(q_vector, budget);\n \n-\t/* We can only support IPv4 TSO in tunnels if we can mangle the\n-\t * inner IP ID field, so strip TSO if MANGLEID is not supported.\n+\t\twork_done += cleaned;\n+\t\tif (cleaned >= budget)\n+\t\t\tclean_complete = false;\n+\t}\n+\n+\t/* If all work not completed, return budget and keep polling */\n+\tif (!clean_complete)\n+\t\treturn budget;\n+\n+\t/* Exit the polling mode, but don't re-enable interrupts if stack might\n+\t * poll us due to busy-polling\n \t */\n-\tif (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))\n-\t\tfeatures &= ~NETIF_F_TSO;\n+\tif (likely(napi_complete_done(napi, work_done)))\n+\t\tigc_ring_irq_enable(q_vector);\n \n-\treturn features;\n+\treturn min(work_done, budget - 1);\n }\n \n-/* Add a MAC filter for 'addr' directing matching traffic to 'queue',\n- * 'flags' is used to indicate what kind of match is made, match is by\n- * default for the destination address, if matching by source address\n- * is desired the flag IGC_MAC_STATE_SRC_ADDR can be used.\n+/**\n+ * igc_alloc_q_vector - Allocate memory for a single interrupt vector\n+ * @adapter: board private structure to initialize\n+ * @v_count: q_vectors allocated on adapter, used for ring interleaving\n+ * @v_idx: index of vector in adapter struct\n+ * @txr_count: total number of Tx rings to allocate\n+ * @txr_idx: index of first Tx ring to allocate\n+ * @rxr_count: total number of Rx rings to allocate\n+ * @rxr_idx: index of first Rx ring to allocate\n+ *\n+ * We allocate one q_vector. If allocation fails we return -ENOMEM.\n */\n-static int igc_add_mac_filter_flags(struct igc_adapter *adapter,\n-\t\t\t\t const u8 *addr, const u8 queue,\n-\t\t\t\t const u8 flags)\n+static int igc_alloc_q_vector(struct igc_adapter *adapter,\n+\t\t\t unsigned int v_count, unsigned int v_idx,\n+\t\t\t unsigned int txr_count, unsigned int txr_idx,\n+\t\t\t unsigned int rxr_count, unsigned int rxr_idx)\n {\n-\tstruct igc_hw *hw = &adapter->hw;\n-\tint rar_entries = hw->mac.rar_entry_count;\n-\tint i;\n+\tstruct igc_q_vector *q_vector;\n+\tstruct igc_ring *ring;\n+\tint ring_count;\n \n-\tif (is_zero_ether_addr(addr))\n-\t\treturn -EINVAL;\n+\t/* igc only supports 1 Tx and/or 1 Rx queue per vector */\n+\tif (txr_count > 1 || rxr_count > 1)\n+\t\treturn -ENOMEM;\n \n-\t/* Search for the first empty entry in the MAC table.\n-\t * Do not touch entries at the end of the table reserved for the VF MAC\n-\t * addresses.\n-\t */\n-\tfor (i = 0; i < rar_entries; i++) {\n-\t\tif (!igc_mac_entry_can_be_used(&adapter->mac_table[i],\n-\t\t\t\t\t addr, flags))\n-\t\t\tcontinue;\n+\tring_count = txr_count + rxr_count;\n \n-\t\tether_addr_copy(adapter->mac_table[i].addr, addr);\n-\t\tadapter->mac_table[i].queue = queue;\n-\t\tadapter->mac_table[i].state |= IGC_MAC_STATE_IN_USE | flags;\n+\t/* allocate q_vector and rings */\n+\tq_vector = adapter->q_vector[v_idx];\n+\tif (!q_vector)\n+\t\tq_vector = kzalloc(struct_size(q_vector, ring, ring_count),\n+\t\t\t\t GFP_KERNEL);\n+\telse\n+\t\tmemset(q_vector, 0, struct_size(q_vector, ring, ring_count));\n+\tif (!q_vector)\n+\t\treturn -ENOMEM;\n \n-\t\tigc_rar_set_index(adapter, i);\n-\t\treturn i;\n-\t}\n+\t/* initialize NAPI */\n+\tnetif_napi_add(adapter->netdev, &q_vector->napi,\n+\t\t igc_poll, 64);\n \n-\treturn -ENOSPC;\n-}\n+\t/* tie q_vector and adapter together */\n+\tadapter->q_vector[v_idx] = q_vector;\n+\tq_vector->adapter = adapter;\n \n-int igc_add_mac_steering_filter(struct igc_adapter *adapter,\n-\t\t\t\tconst u8 *addr, u8 queue, u8 flags)\n-{\n-\treturn igc_add_mac_filter_flags(adapter, addr, queue,\n-\t\t\t\t\tIGC_MAC_STATE_QUEUE_STEERING | flags);\n-}\n+\t/* initialize work limits */\n+\tq_vector->tx.work_limit = adapter->tx_work_limit;\n \n-/* Remove a MAC filter for 'addr' directing matching traffic to\n- * 'queue', 'flags' is used to indicate what kind of match need to be\n- * removed, match is by default for the destination address, if\n- * matching by source address is to be removed the flag\n- * IGC_MAC_STATE_SRC_ADDR can be used.\n- */\n-static int igc_del_mac_filter_flags(struct igc_adapter *adapter,\n-\t\t\t\t const u8 *addr, const u8 queue,\n-\t\t\t\t const u8 flags)\n-{\n-\tstruct igc_hw *hw = &adapter->hw;\n-\tint rar_entries = hw->mac.rar_entry_count;\n-\tint i;\n+\t/* initialize ITR configuration */\n+\tq_vector->itr_register = adapter->io_addr + IGC_EITR(0);\n+\tq_vector->itr_val = IGC_START_ITR;\n \n-\tif (is_zero_ether_addr(addr))\n-\t\treturn -EINVAL;\n+\t/* initialize pointer to rings */\n+\tring = q_vector->ring;\n \n-\t/* Search for matching entry in the MAC table based on given address\n-\t * and queue. Do not touch entries at the end of the table reserved\n-\t * for the VF MAC addresses.\n-\t */\n-\tfor (i = 0; i < rar_entries; i++) {\n-\t\tif (!(adapter->mac_table[i].state & IGC_MAC_STATE_IN_USE))\n-\t\t\tcontinue;\n-\t\tif ((adapter->mac_table[i].state & flags) != flags)\n-\t\t\tcontinue;\n-\t\tif (adapter->mac_table[i].queue != queue)\n-\t\t\tcontinue;\n-\t\tif (!ether_addr_equal(adapter->mac_table[i].addr, addr))\n-\t\t\tcontinue;\n+\t/* initialize ITR */\n+\tif (rxr_count) {\n+\t\t/* rx or rx/tx vector */\n+\t\tif (!adapter->rx_itr_setting || adapter->rx_itr_setting > 3)\n+\t\t\tq_vector->itr_val = adapter->rx_itr_setting;\n+\t} else {\n+\t\t/* tx only vector */\n+\t\tif (!adapter->tx_itr_setting || adapter->tx_itr_setting > 3)\n+\t\t\tq_vector->itr_val = adapter->tx_itr_setting;\n+\t}\n \n-\t\t/* When a filter for the default address is \"deleted\",\n-\t\t * we return it to its initial configuration\n-\t\t */\n-\t\tif (adapter->mac_table[i].state & IGC_MAC_STATE_DEFAULT) {\n-\t\t\tadapter->mac_table[i].state =\n-\t\t\t\tIGC_MAC_STATE_DEFAULT | IGC_MAC_STATE_IN_USE;\n-\t\t} else {\n-\t\t\tadapter->mac_table[i].state = 0;\n-\t\t\tadapter->mac_table[i].queue = 0;\n-\t\t\tmemset(adapter->mac_table[i].addr, 0, ETH_ALEN);\n-\t\t}\n+\tif (txr_count) {\n+\t\t/* assign generic ring traits */\n+\t\tring->dev = &adapter->pdev->dev;\n+\t\tring->netdev = adapter->netdev;\n \n-\t\tigc_rar_set_index(adapter, i);\n-\t\treturn 0;\n+\t\t/* configure backlink on ring */\n+\t\tring->q_vector = q_vector;\n+\n+\t\t/* update q_vector Tx values */\n+\t\tigc_add_ring(ring, &q_vector->tx);\n+\n+\t\t/* apply Tx specific ring traits */\n+\t\tring->count = adapter->tx_ring_count;\n+\t\tring->queue_index = txr_idx;\n+\n+\t\t/* assign ring to adapter */\n+\t\tadapter->tx_ring[txr_idx] = ring;\n+\n+\t\t/* push pointer to next ring */\n+\t\tring++;\n \t}\n \n-\treturn -ENOENT;\n-}\n+\tif (rxr_count) {\n+\t\t/* assign generic ring traits */\n+\t\tring->dev = &adapter->pdev->dev;\n+\t\tring->netdev = adapter->netdev;\n \n-int igc_del_mac_steering_filter(struct igc_adapter *adapter,\n-\t\t\t\tconst u8 *addr, u8 queue, u8 flags)\n-{\n-\treturn igc_del_mac_filter_flags(adapter, addr, queue,\n-\t\t\t\t\tIGC_MAC_STATE_QUEUE_STEERING | flags);\n+\t\t/* configure backlink on ring */\n+\t\tring->q_vector = q_vector;\n+\n+\t\t/* update q_vector Rx values */\n+\t\tigc_add_ring(ring, &q_vector->rx);\n+\n+\t\t/* apply Rx specific ring traits */\n+\t\tring->count = adapter->rx_ring_count;\n+\t\tring->queue_index = rxr_idx;\n+\n+\t\t/* assign ring to adapter */\n+\t\tadapter->rx_ring[rxr_idx] = ring;\n+\t}\n+\n+\treturn 0;\n }\n \n /**\n- * igc_msix_other - msix other interrupt handler\n- * @irq: interrupt number\n- * @data: pointer to a q_vector\n+ * igc_alloc_q_vectors - Allocate memory for interrupt vectors\n+ * @adapter: board private structure to initialize\n+ *\n+ * We allocate one q_vector per queue interrupt. If allocation fails we\n+ * return -ENOMEM.\n */\n-static irqreturn_t igc_msix_other(int irq, void *data)\n+static int igc_alloc_q_vectors(struct igc_adapter *adapter)\n {\n-\tstruct igc_adapter *adapter = data;\n-\tstruct igc_hw *hw = &adapter->hw;\n-\tu32 icr = rd32(IGC_ICR);\n+\tint rxr_remaining = adapter->num_rx_queues;\n+\tint txr_remaining = adapter->num_tx_queues;\n+\tint rxr_idx = 0, txr_idx = 0, v_idx = 0;\n+\tint q_vectors = adapter->num_q_vectors;\n+\tint err;\n \n-\t/* reading ICR causes bit 31 of EICR to be cleared */\n-\tif (icr & IGC_ICR_DRSTA)\n-\t\tschedule_work(&adapter->reset_task);\n+\tif (q_vectors >= (rxr_remaining + txr_remaining)) {\n+\t\tfor (; rxr_remaining; v_idx++) {\n+\t\t\terr = igc_alloc_q_vector(adapter, q_vectors, v_idx,\n+\t\t\t\t\t\t 0, 0, 1, rxr_idx);\n \n-\tif (icr & IGC_ICR_DOUTSYNC) {\n-\t\t/* HW is reporting DMA is out of sync */\n-\t\tadapter->stats.doosync++;\n-\t}\n+\t\t\tif (err)\n+\t\t\t\tgoto err_out;\n \n-\tif (icr & IGC_ICR_LSC) {\n-\t\thw->mac.get_link_status = 1;\n-\t\t/* guard against interrupt when we're going down */\n-\t\tif (!test_bit(__IGC_DOWN, &adapter->state))\n-\t\t\tmod_timer(&adapter->watchdog_timer, jiffies + 1);\n+\t\t\t/* update counts and index */\n+\t\t\trxr_remaining--;\n+\t\t\trxr_idx++;\n+\t\t}\n \t}\n \n-\twr32(IGC_EIMS, adapter->eims_other);\n-\n-\treturn IRQ_HANDLED;\n-}\n-\n-static void igc_write_itr(struct igc_q_vector *q_vector)\n-{\n-\tu32 itr_val = q_vector->itr_val & IGC_QVECTOR_MASK;\n-\n-\tif (!q_vector->set_itr)\n-\t\treturn;\n+\tfor (; v_idx < q_vectors; v_idx++) {\n+\t\tint rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx);\n+\t\tint tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx);\n \n-\tif (!itr_val)\n-\t\titr_val = IGC_ITR_VAL_MASK;\n+\t\terr = igc_alloc_q_vector(adapter, q_vectors, v_idx,\n+\t\t\t\t\t tqpv, txr_idx, rqpv, rxr_idx);\n \n-\titr_val |= IGC_EITR_CNT_IGNR;\n+\t\tif (err)\n+\t\t\tgoto err_out;\n \n-\twritel(itr_val, q_vector->itr_register);\n-\tq_vector->set_itr = 0;\n-}\n+\t\t/* update counts and index */\n+\t\trxr_remaining -= rqpv;\n+\t\ttxr_remaining -= tqpv;\n+\t\trxr_idx++;\n+\t\ttxr_idx++;\n+\t}\n \n-static irqreturn_t igc_msix_ring(int irq, void *data)\n-{\n-\tstruct igc_q_vector *q_vector = data;\n+\treturn 0;\n \n-\t/* Write the ITR value calculated from the previous interrupt. */\n-\tigc_write_itr(q_vector);\n+err_out:\n+\tadapter->num_tx_queues = 0;\n+\tadapter->num_rx_queues = 0;\n+\tadapter->num_q_vectors = 0;\n \n-\tnapi_schedule(&q_vector->napi);\n+\twhile (v_idx--)\n+\t\tigc_free_q_vector(adapter, v_idx);\n \n-\treturn IRQ_HANDLED;\n+\treturn -ENOMEM;\n }\n \n /**\n- * igc_request_msix - Initialize MSI-X interrupts\n+ * igc_init_interrupt_scheme - initialize interrupts, allocate queues/vectors\n * @adapter: Pointer to adapter structure\n+ * @msix: boolean for MSI-X capability\n *\n- * igc_request_msix allocates MSI-X vectors and requests interrupts from the\n- * kernel.\n+ * This function initializes the interrupts and allocates all of the queues.\n */\n-static int igc_request_msix(struct igc_adapter *adapter)\n+static int igc_init_interrupt_scheme(struct igc_adapter *adapter, bool msix)\n {\n-\tint i = 0, err = 0, vector = 0, free_vector = 0;\n-\tstruct net_device *netdev = adapter->netdev;\n+\tstruct pci_dev *pdev = adapter->pdev;\n+\tint err = 0;\n \n-\terr = request_irq(adapter->msix_entries[vector].vector,\n-\t\t\t &igc_msix_other, 0, netdev->name, adapter);\n-\tif (err)\n-\t\tgoto err_out;\n+\tigc_set_interrupt_capability(adapter, msix);\n \n-\tfor (i = 0; i < adapter->num_q_vectors; i++) {\n-\t\tstruct igc_q_vector *q_vector = adapter->q_vector[i];\n+\terr = igc_alloc_q_vectors(adapter);\n+\tif (err) {\n+\t\tdev_err(&pdev->dev, \"Unable to allocate memory for vectors\\n\");\n+\t\tgoto err_alloc_q_vectors;\n+\t}\n \n-\t\tvector++;\n-\n-\t\tq_vector->itr_register = adapter->io_addr + IGC_EITR(vector);\n-\n-\t\tif (q_vector->rx.ring && q_vector->tx.ring)\n-\t\t\tsprintf(q_vector->name, \"%s-TxRx-%u\", netdev->name,\n-\t\t\t\tq_vector->rx.ring->queue_index);\n-\t\telse if (q_vector->tx.ring)\n-\t\t\tsprintf(q_vector->name, \"%s-tx-%u\", netdev->name,\n-\t\t\t\tq_vector->tx.ring->queue_index);\n-\t\telse if (q_vector->rx.ring)\n-\t\t\tsprintf(q_vector->name, \"%s-rx-%u\", netdev->name,\n-\t\t\t\tq_vector->rx.ring->queue_index);\n-\t\telse\n-\t\t\tsprintf(q_vector->name, \"%s-unused\", netdev->name);\n-\n-\t\terr = request_irq(adapter->msix_entries[vector].vector,\n-\t\t\t\t igc_msix_ring, 0, q_vector->name,\n-\t\t\t\t q_vector);\n-\t\tif (err)\n-\t\t\tgoto err_free;\n-\t}\n+\tigc_cache_ring_register(adapter);\n \n-\tigc_configure_msix(adapter);\n \treturn 0;\n \n-err_free:\n-\t/* free already assigned IRQs */\n-\tfree_irq(adapter->msix_entries[free_vector++].vector, adapter);\n-\n-\tvector--;\n-\tfor (i = 0; i < vector; i++) {\n-\t\tfree_irq(adapter->msix_entries[free_vector++].vector,\n-\t\t\t adapter->q_vector[i]);\n-\t}\n-err_out:\n+err_alloc_q_vectors:\n+\tigc_reset_interrupt_capability(adapter);\n \treturn err;\n }\n \n /**\n- * igc_reset_q_vector - Reset config for interrupt vector\n+ * igc_sw_init - Initialize general software structures (struct igc_adapter)\n * @adapter: board private structure to initialize\n- * @v_idx: Index of vector to be reset\n *\n- * If NAPI is enabled it will delete any references to the\n- * NAPI struct. This is preparation for igc_free_q_vector.\n+ * igc_sw_init initializes the Adapter private data structure.\n+ * Fields are initialized based on PCI device information and\n+ * OS network device settings (MTU size).\n */\n-static void igc_reset_q_vector(struct igc_adapter *adapter, int v_idx)\n+static int igc_sw_init(struct igc_adapter *adapter)\n {\n-\tstruct igc_q_vector *q_vector = adapter->q_vector[v_idx];\n-\n-\t/* if we're coming from igc_set_interrupt_capability, the vectors are\n-\t * not yet allocated\n-\t */\n-\tif (!q_vector)\n-\t\treturn;\n-\n-\tif (q_vector->tx.ring)\n-\t\tadapter->tx_ring[q_vector->tx.ring->queue_index] = NULL;\n+\tstruct net_device *netdev = adapter->netdev;\n+\tstruct pci_dev *pdev = adapter->pdev;\n+\tstruct igc_hw *hw = &adapter->hw;\n \n-\tif (q_vector->rx.ring)\n-\t\tadapter->rx_ring[q_vector->rx.ring->queue_index] = NULL;\n+\tint size = sizeof(struct igc_mac_addr) * hw->mac.rar_entry_count;\n \n-\tnetif_napi_del(&q_vector->napi);\n-}\n+\tpci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word);\n \n-static void igc_reset_interrupt_capability(struct igc_adapter *adapter)\n-{\n-\tint v_idx = adapter->num_q_vectors;\n+\t/* set default ring sizes */\n+\tadapter->tx_ring_count = IGC_DEFAULT_TXD;\n+\tadapter->rx_ring_count = IGC_DEFAULT_RXD;\n \n-\tif (adapter->msix_entries) {\n-\t\tpci_disable_msix(adapter->pdev);\n-\t\tkfree(adapter->msix_entries);\n-\t\tadapter->msix_entries = NULL;\n-\t} else if (adapter->flags & IGC_FLAG_HAS_MSI) {\n-\t\tpci_disable_msi(adapter->pdev);\n-\t}\n+\t/* set default ITR values */\n+\tadapter->rx_itr_setting = IGC_DEFAULT_ITR;\n+\tadapter->tx_itr_setting = IGC_DEFAULT_ITR;\n \n-\twhile (v_idx--)\n-\t\tigc_reset_q_vector(adapter, v_idx);\n-}\n+\t/* set default work limits */\n+\tadapter->tx_work_limit = IGC_DEFAULT_TX_WORK;\n \n-/**\n- * igc_set_interrupt_capability - set MSI or MSI-X if supported\n- * @adapter: Pointer to adapter structure\n- * @msix: boolean value for MSI-X capability\n- *\n- * Attempt to configure interrupts using the best available\n- * capabilities of the hardware and kernel.\n- */\n-static void igc_set_interrupt_capability(struct igc_adapter *adapter,\n-\t\t\t\t\t bool msix)\n-{\n-\tint numvecs, i;\n-\tint err;\n+\t/* adjust max frame to be at least the size of a standard frame */\n+\tadapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN +\n+\t\t\t\tVLAN_HLEN;\n+\tadapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;\n \n-\tif (!msix)\n-\t\tgoto msi_only;\n+\tspin_lock_init(&adapter->nfc_lock);\n+\tspin_lock_init(&adapter->stats64_lock);\n+\t/* Assume MSI-X interrupts, will be checked during IRQ allocation */\n \tadapter->flags |= IGC_FLAG_HAS_MSIX;\n \n-\t/* Number of supported queues. */\n-\tadapter->num_rx_queues = adapter->rss_queues;\n+\tadapter->mac_table = kzalloc(size, GFP_ATOMIC);\n+\tif (!adapter->mac_table)\n+\t\treturn -ENOMEM;\n \n-\tadapter->num_tx_queues = adapter->rss_queues;\n+\tigc_init_queue_configuration(adapter);\n \n-\t/* start with one vector for every Rx queue */\n-\tnumvecs = adapter->num_rx_queues;\n+\t/* This call may decrease the number of queues */\n+\tif (igc_init_interrupt_scheme(adapter, true)) {\n+\t\tdev_err(&pdev->dev, \"Unable to allocate memory for queues\\n\");\n+\t\treturn -ENOMEM;\n+\t}\n \n-\t/* if Tx handler is separate add 1 for every Tx queue */\n-\tif (!(adapter->flags & IGC_FLAG_QUEUE_PAIRS))\n-\t\tnumvecs += adapter->num_tx_queues;\n+\t/* Explicitly disable IRQ since the NIC can be in any state. */\n+\tigc_irq_disable(adapter);\n \n-\t/* store the number of vectors reserved for queues */\n-\tadapter->num_q_vectors = numvecs;\n+\tset_bit(__IGC_DOWN, &adapter->state);\n \n-\t/* add 1 vector for link status interrupts */\n-\tnumvecs++;\n+\treturn 0;\n+}\n \n-\tadapter->msix_entries = kcalloc(numvecs, sizeof(struct msix_entry),\n-\t\t\t\t\tGFP_KERNEL);\n+/**\n+ * igc_up - Open the interface and prepare it to handle traffic\n+ * @adapter: board private structure\n+ */\n+void igc_up(struct igc_adapter *adapter)\n+{\n+\tstruct igc_hw *hw = &adapter->hw;\n+\tint i = 0;\n \n-\tif (!adapter->msix_entries)\n-\t\treturn;\n+\t/* hardware has been reset, we need to reload some things */\n+\tigc_configure(adapter);\n \n-\t/* populate entry values */\n-\tfor (i = 0; i < numvecs; i++)\n-\t\tadapter->msix_entries[i].entry = i;\n+\tclear_bit(__IGC_DOWN, &adapter->state);\n \n-\terr = pci_enable_msix_range(adapter->pdev,\n-\t\t\t\t adapter->msix_entries,\n-\t\t\t\t numvecs,\n-\t\t\t\t numvecs);\n-\tif (err > 0)\n-\t\treturn;\n+\tfor (i = 0; i < adapter->num_q_vectors; i++)\n+\t\tnapi_enable(&adapter->q_vector[i]->napi);\n \n-\tkfree(adapter->msix_entries);\n-\tadapter->msix_entries = NULL;\n+\tif (adapter->msix_entries)\n+\t\tigc_configure_msix(adapter);\n+\telse\n+\t\tigc_assign_vector(adapter->q_vector[0], 0);\n \n-\tigc_reset_interrupt_capability(adapter);\n+\t/* Clear any pending interrupts. */\n+\trd32(IGC_ICR);\n+\tigc_irq_enable(adapter);\n \n-msi_only:\n-\tadapter->flags &= ~IGC_FLAG_HAS_MSIX;\n+\tnetif_tx_start_all_queues(adapter->netdev);\n \n-\tadapter->rss_queues = 1;\n-\tadapter->flags |= IGC_FLAG_QUEUE_PAIRS;\n-\tadapter->num_rx_queues = 1;\n-\tadapter->num_tx_queues = 1;\n-\tadapter->num_q_vectors = 1;\n-\tif (!pci_enable_msi(adapter->pdev))\n-\t\tadapter->flags |= IGC_FLAG_HAS_MSI;\n+\t/* start the watchdog. */\n+\thw->mac.get_link_status = 1;\n+\tschedule_work(&adapter->watchdog_task);\n }\n \n /**\n- * igc_free_q_vector - Free memory allocated for specific interrupt vector\n- * @adapter: board private structure to initialize\n- * @v_idx: Index of vector to be freed\n- *\n- * This function frees the memory allocated to the q_vector.\n+ * igc_update_stats - Update the board statistics counters\n+ * @adapter: board private structure\n */\n-static void igc_free_q_vector(struct igc_adapter *adapter, int v_idx)\n+void igc_update_stats(struct igc_adapter *adapter)\n {\n-\tstruct igc_q_vector *q_vector = adapter->q_vector[v_idx];\n-\n-\tadapter->q_vector[v_idx] = NULL;\n+\tstruct rtnl_link_stats64 *net_stats = &adapter->stats64;\n+\tstruct pci_dev *pdev = adapter->pdev;\n+\tstruct igc_hw *hw = &adapter->hw;\n+\tu64 _bytes, _packets;\n+\tu64 bytes, packets;\n+\tunsigned int start;\n+\tu32 mpc;\n+\tint i;\n \n-\t/* igc_get_stats64() might access the rings on this vector,\n-\t * we must wait a grace period before freeing it.\n+\t/* Prevent stats update while adapter is being reset, or if the pci\n+\t * connection is down.\n \t */\n-\tif (q_vector)\n-\t\tkfree_rcu(q_vector, rcu);\n-}\n+\tif (adapter->link_speed == 0)\n+\t\treturn;\n+\tif (pci_channel_offline(pdev))\n+\t\treturn;\n \n-/**\n- * igc_free_q_vectors - Free memory allocated for interrupt vectors\n- * @adapter: board private structure to initialize\n- *\n- * This function frees the memory allocated to the q_vectors. In addition if\n- * NAPI is enabled it will delete any references to the NAPI struct prior\n- * to freeing the q_vector.\n- */\n-static void igc_free_q_vectors(struct igc_adapter *adapter)\n-{\n-\tint v_idx = adapter->num_q_vectors;\n+\tpackets = 0;\n+\tbytes = 0;\n \n-\tadapter->num_tx_queues = 0;\n-\tadapter->num_rx_queues = 0;\n-\tadapter->num_q_vectors = 0;\n+\trcu_read_lock();\n+\tfor (i = 0; i < adapter->num_rx_queues; i++) {\n+\t\tstruct igc_ring *ring = adapter->rx_ring[i];\n+\t\tu32 rqdpc = rd32(IGC_RQDPC(i));\n \n-\twhile (v_idx--) {\n-\t\tigc_reset_q_vector(adapter, v_idx);\n-\t\tigc_free_q_vector(adapter, v_idx);\n-\t}\n-}\n+\t\tif (hw->mac.type >= igc_i225)\n+\t\t\twr32(IGC_RQDPC(i), 0);\n \n-/**\n- * igc_clear_interrupt_scheme - reset the device to a state of no interrupts\n- * @adapter: Pointer to adapter structure\n- *\n- * This function resets the device so that it has 0 rx queues, tx queues, and\n- * MSI-X interrupts allocated.\n- */\n-static void igc_clear_interrupt_scheme(struct igc_adapter *adapter)\n-{\n-\tigc_free_q_vectors(adapter);\n-\tigc_reset_interrupt_capability(adapter);\n-}\n+\t\tif (rqdpc) {\n+\t\t\tring->rx_stats.drops += rqdpc;\n+\t\t\tnet_stats->rx_fifo_errors += rqdpc;\n+\t\t}\n \n-/* Need to wait a few seconds after link up to get diagnostic information from\n- * the phy\n- */\n-static void igc_update_phy_info(struct timer_list *t)\n+\t\tdo {\n+\t\t\tstart = u64_stats_fetch_begin_irq(&ring->rx_syncp);\n+\t\t\t_bytes = ring->rx_stats.bytes;\n+\t\t\t_packets = ring->rx_stats.packets;\n+\t\t} while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start));\n+\t\tbytes += _bytes;\n+\t\tpackets += _packets;\n+\t}\n+\n+\tnet_stats->rx_bytes = bytes;\n+\tnet_stats->rx_packets = packets;\n+\n+\tpackets = 0;\n+\tbytes = 0;\n+\tfor (i = 0; i < adapter->num_tx_queues; i++) {\n+\t\tstruct igc_ring *ring = adapter->tx_ring[i];\n+\n+\t\tdo {\n+\t\t\tstart = u64_stats_fetch_begin_irq(&ring->tx_syncp);\n+\t\t\t_bytes = ring->tx_stats.bytes;\n+\t\t\t_packets = ring->tx_stats.packets;\n+\t\t} while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start));\n+\t\tbytes += _bytes;\n+\t\tpackets += _packets;\n+\t}\n+\tnet_stats->tx_bytes = bytes;\n+\tnet_stats->tx_packets = packets;\n+\trcu_read_unlock();\n+\n+\t/* read stats registers */\n+\tadapter->stats.crcerrs += rd32(IGC_CRCERRS);\n+\tadapter->stats.gprc += rd32(IGC_GPRC);\n+\tadapter->stats.gorc += rd32(IGC_GORCL);\n+\trd32(IGC_GORCH); /* clear GORCL */\n+\tadapter->stats.bprc += rd32(IGC_BPRC);\n+\tadapter->stats.mprc += rd32(IGC_MPRC);\n+\tadapter->stats.roc += rd32(IGC_ROC);\n+\n+\tadapter->stats.prc64 += rd32(IGC_PRC64);\n+\tadapter->stats.prc127 += rd32(IGC_PRC127);\n+\tadapter->stats.prc255 += rd32(IGC_PRC255);\n+\tadapter->stats.prc511 += rd32(IGC_PRC511);\n+\tadapter->stats.prc1023 += rd32(IGC_PRC1023);\n+\tadapter->stats.prc1522 += rd32(IGC_PRC1522);\n+\tadapter->stats.symerrs += rd32(IGC_SYMERRS);\n+\tadapter->stats.sec += rd32(IGC_SEC);\n+\n+\tmpc = rd32(IGC_MPC);\n+\tadapter->stats.mpc += mpc;\n+\tnet_stats->rx_fifo_errors += mpc;\n+\tadapter->stats.scc += rd32(IGC_SCC);\n+\tadapter->stats.ecol += rd32(IGC_ECOL);\n+\tadapter->stats.mcc += rd32(IGC_MCC);\n+\tadapter->stats.latecol += rd32(IGC_LATECOL);\n+\tadapter->stats.dc += rd32(IGC_DC);\n+\tadapter->stats.rlec += rd32(IGC_RLEC);\n+\tadapter->stats.xonrxc += rd32(IGC_XONRXC);\n+\tadapter->stats.xontxc += rd32(IGC_XONTXC);\n+\tadapter->stats.xoffrxc += rd32(IGC_XOFFRXC);\n+\tadapter->stats.xofftxc += rd32(IGC_XOFFTXC);\n+\tadapter->stats.fcruc += rd32(IGC_FCRUC);\n+\tadapter->stats.gptc += rd32(IGC_GPTC);\n+\tadapter->stats.gotc += rd32(IGC_GOTCL);\n+\trd32(IGC_GOTCH); /* clear GOTCL */\n+\tadapter->stats.rnbc += rd32(IGC_RNBC);\n+\tadapter->stats.ruc += rd32(IGC_RUC);\n+\tadapter->stats.rfc += rd32(IGC_RFC);\n+\tadapter->stats.rjc += rd32(IGC_RJC);\n+\tadapter->stats.tor += rd32(IGC_TORH);\n+\tadapter->stats.tot += rd32(IGC_TOTH);\n+\tadapter->stats.tpr += rd32(IGC_TPR);\n+\n+\tadapter->stats.ptc64 += rd32(IGC_PTC64);\n+\tadapter->stats.ptc127 += rd32(IGC_PTC127);\n+\tadapter->stats.ptc255 += rd32(IGC_PTC255);\n+\tadapter->stats.ptc511 += rd32(IGC_PTC511);\n+\tadapter->stats.ptc1023 += rd32(IGC_PTC1023);\n+\tadapter->stats.ptc1522 += rd32(IGC_PTC1522);\n+\n+\tadapter->stats.mptc += rd32(IGC_MPTC);\n+\tadapter->stats.bptc += rd32(IGC_BPTC);\n+\n+\tadapter->stats.tpt += rd32(IGC_TPT);\n+\tadapter->stats.colc += rd32(IGC_COLC);\n+\n+\tadapter->stats.algnerrc += rd32(IGC_ALGNERRC);\n+\n+\tadapter->stats.tsctc += rd32(IGC_TSCTC);\n+\tadapter->stats.tsctfc += rd32(IGC_TSCTFC);\n+\n+\tadapter->stats.iac += rd32(IGC_IAC);\n+\tadapter->stats.icrxoc += rd32(IGC_ICRXOC);\n+\tadapter->stats.icrxptc += rd32(IGC_ICRXPTC);\n+\tadapter->stats.icrxatc += rd32(IGC_ICRXATC);\n+\tadapter->stats.ictxptc += rd32(IGC_ICTXPTC);\n+\tadapter->stats.ictxatc += rd32(IGC_ICTXATC);\n+\tadapter->stats.ictxqec += rd32(IGC_ICTXQEC);\n+\tadapter->stats.ictxqmtc += rd32(IGC_ICTXQMTC);\n+\tadapter->stats.icrxdmtc += rd32(IGC_ICRXDMTC);\n+\n+\t/* Fill out the OS statistics structure */\n+\tnet_stats->multicast = adapter->stats.mprc;\n+\tnet_stats->collisions = adapter->stats.colc;\n+\n+\t/* Rx Errors */\n+\n+\t/* RLEC on some newer hardware can be incorrect so build\n+\t * our own version based on RUC and ROC\n+\t */\n+\tnet_stats->rx_errors = adapter->stats.rxerrc +\n+\t\tadapter->stats.crcerrs + adapter->stats.algnerrc +\n+\t\tadapter->stats.ruc + adapter->stats.roc +\n+\t\tadapter->stats.cexterr;\n+\tnet_stats->rx_length_errors = adapter->stats.ruc +\n+\t\t\t\t adapter->stats.roc;\n+\tnet_stats->rx_crc_errors = adapter->stats.crcerrs;\n+\tnet_stats->rx_frame_errors = adapter->stats.algnerrc;\n+\tnet_stats->rx_missed_errors = adapter->stats.mpc;\n+\n+\t/* Tx Errors */\n+\tnet_stats->tx_errors = adapter->stats.ecol +\n+\t\t\t adapter->stats.latecol;\n+\tnet_stats->tx_aborted_errors = adapter->stats.ecol;\n+\tnet_stats->tx_window_errors = adapter->stats.latecol;\n+\tnet_stats->tx_carrier_errors = adapter->stats.tncrs;\n+\n+\t/* Tx Dropped needs to be maintained elsewhere */\n+\n+\t/* Management Stats */\n+\tadapter->stats.mgptc += rd32(IGC_MGTPTC);\n+\tadapter->stats.mgprc += rd32(IGC_MGTPRC);\n+\tadapter->stats.mgpdc += rd32(IGC_MGTPDC);\n+}\n+\n+static void igc_nfc_filter_exit(struct igc_adapter *adapter)\n {\n-\tstruct igc_adapter *adapter = from_timer(adapter, t, phy_info_timer);\n+\tstruct igc_nfc_filter *rule;\n \n-\tigc_get_phy_info(&adapter->hw);\n+\tspin_lock(&adapter->nfc_lock);\n+\n+\thlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node)\n+\t\tigc_erase_filter(adapter, rule);\n+\n+\thlist_for_each_entry(rule, &adapter->cls_flower_list, nfc_node)\n+\t\tigc_erase_filter(adapter, rule);\n+\n+\tspin_unlock(&adapter->nfc_lock);\n }\n \n /**\n- * igc_has_link - check shared code for link and determine up/down\n- * @adapter: pointer to driver private info\n+ * igc_down - Close the interface\n+ * @adapter: board private structure\n */\n-bool igc_has_link(struct igc_adapter *adapter)\n+void igc_down(struct igc_adapter *adapter)\n {\n+\tstruct net_device *netdev = adapter->netdev;\n \tstruct igc_hw *hw = &adapter->hw;\n-\tbool link_active = false;\n+\tu32 tctl, rctl;\n+\tint i = 0;\n \n-\t/* get_link_status is set on LSC (link status) interrupt or\n-\t * rx sequence error interrupt. get_link_status will stay\n-\t * false until the igc_check_for_link establishes link\n-\t * for copper adapters ONLY\n-\t */\n-\tswitch (hw->phy.media_type) {\n-\tcase igc_media_type_copper:\n-\t\tif (!hw->mac.get_link_status)\n-\t\t\treturn true;\n-\t\thw->mac.ops.check_for_link(hw);\n-\t\tlink_active = !hw->mac.get_link_status;\n-\t\tbreak;\n-\tdefault:\n-\tcase igc_media_type_unknown:\n-\t\tbreak;\n-\t}\n+\tset_bit(__IGC_DOWN, &adapter->state);\n \n-\tif (hw->mac.type == igc_i225 &&\n-\t hw->phy.id == I225_I_PHY_ID) {\n-\t\tif (!netif_carrier_ok(adapter->netdev)) {\n-\t\t\tadapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;\n-\t\t} else if (!(adapter->flags & IGC_FLAG_NEED_LINK_UPDATE)) {\n-\t\t\tadapter->flags |= IGC_FLAG_NEED_LINK_UPDATE;\n-\t\t\tadapter->link_check_timeout = jiffies;\n+\t/* disable receives in the hardware */\n+\trctl = rd32(IGC_RCTL);\n+\twr32(IGC_RCTL, rctl & ~IGC_RCTL_EN);\n+\t/* flush and sleep below */\n+\n+\tigc_nfc_filter_exit(adapter);\n+\n+\t/* set trans_start so we don't get spurious watchdogs during reset */\n+\tnetif_trans_update(netdev);\n+\n+\tnetif_carrier_off(netdev);\n+\tnetif_tx_stop_all_queues(netdev);\n+\n+\t/* disable transmits in the hardware */\n+\ttctl = rd32(IGC_TCTL);\n+\ttctl &= ~IGC_TCTL_EN;\n+\twr32(IGC_TCTL, tctl);\n+\t/* flush both disables and wait for them to finish */\n+\twrfl();\n+\tusleep_range(10000, 20000);\n+\n+\tigc_irq_disable(adapter);\n+\n+\tadapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;\n+\n+\tfor (i = 0; i < adapter->num_q_vectors; i++) {\n+\t\tif (adapter->q_vector[i]) {\n+\t\t\tnapi_synchronize(&adapter->q_vector[i]->napi);\n+\t\t\tnapi_disable(&adapter->q_vector[i]->napi);\n \t\t}\n \t}\n \n-\treturn link_active;\n+\tdel_timer_sync(&adapter->watchdog_timer);\n+\tdel_timer_sync(&adapter->phy_info_timer);\n+\n+\t/* record the stats before reset*/\n+\tspin_lock(&adapter->stats64_lock);\n+\tigc_update_stats(adapter);\n+\tspin_unlock(&adapter->stats64_lock);\n+\n+\tadapter->link_speed = 0;\n+\tadapter->link_duplex = 0;\n+\n+\tif (!pci_channel_offline(adapter->pdev))\n+\t\tigc_reset(adapter);\n+\n+\t/* clear VLAN promisc flag so VFTA will be updated if necessary */\n+\tadapter->flags &= ~IGC_FLAG_VLAN_PROMISC;\n+\n+\tigc_clean_all_tx_rings(adapter);\n+\tigc_clean_all_rx_rings(adapter);\n }\n \n-/**\n- * igc_watchdog - Timer Call-back\n- * @t: timer for the watchdog\n- */\n-static void igc_watchdog(struct timer_list *t)\n+void igc_reinit_locked(struct igc_adapter *adapter)\n {\n-\tstruct igc_adapter *adapter = from_timer(adapter, t, watchdog_timer);\n-\t/* Do the rest outside of interrupt context */\n-\tschedule_work(&adapter->watchdog_task);\n+\tWARN_ON(in_interrupt());\n+\twhile (test_and_set_bit(__IGC_RESETTING, &adapter->state))\n+\t\tusleep_range(1000, 2000);\n+\tigc_down(adapter);\n+\tigc_up(adapter);\n+\tclear_bit(__IGC_RESETTING, &adapter->state);\n }\n \n-static void igc_watchdog_task(struct work_struct *work)\n+static void igc_reset_task(struct work_struct *work)\n {\n-\tstruct igc_adapter *adapter = container_of(work,\n-\t\t\t\t\t\t struct igc_adapter,\n-\t\t\t\t\t\t watchdog_task);\n-\tstruct net_device *netdev = adapter->netdev;\n-\tstruct igc_hw *hw = &adapter->hw;\n-\tstruct igc_phy_info *phy = &hw->phy;\n-\tu16 phy_data, retry_count = 20;\n-\tu32 connsw;\n-\tu32 link;\n-\tint i;\n+\tstruct igc_adapter *adapter;\n \n-\tlink = igc_has_link(adapter);\n+\tadapter = container_of(work, struct igc_adapter, reset_task);\n \n-\tif (adapter->flags & IGC_FLAG_NEED_LINK_UPDATE) {\n-\t\tif (time_after(jiffies, (adapter->link_check_timeout + HZ)))\n-\t\t\tadapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;\n-\t\telse\n-\t\t\tlink = false;\n-\t}\n+\tnetdev_err(adapter->netdev, \"Reset adapter\\n\");\n+\tigc_reinit_locked(adapter);\n+}\n \n-\t/* Force link down if we have fiber to swap to */\n-\tif (adapter->flags & IGC_FLAG_MAS_ENABLE) {\n-\t\tif (hw->phy.media_type == igc_media_type_copper) {\n-\t\t\tconnsw = rd32(IGC_CONNSW);\n-\t\t\tif (!(connsw & IGC_CONNSW_AUTOSENSE_EN))\n-\t\t\t\tlink = 0;\n-\t\t}\n-\t}\n-\tif (link) {\n-\t\tif (!netif_carrier_ok(netdev)) {\n-\t\t\tu32 ctrl;\n+/**\n+ * igc_change_mtu - Change the Maximum Transfer Unit\n+ * @netdev: network interface device structure\n+ * @new_mtu: new value for maximum frame size\n+ *\n+ * Returns 0 on success, negative on failure\n+ */\n+static int igc_change_mtu(struct net_device *netdev, int new_mtu)\n+{\n+\tint max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;\n+\tstruct igc_adapter *adapter = netdev_priv(netdev);\n \n-\t\t\thw->mac.ops.get_speed_and_duplex(hw,\n-\t\t\t\t\t\t\t &adapter->link_speed,\n-\t\t\t\t\t\t\t &adapter->link_duplex);\n+\t/* adjust max frame to be at least the size of a standard frame */\n+\tif (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))\n+\t\tmax_frame = ETH_FRAME_LEN + ETH_FCS_LEN;\n \n-\t\t\tctrl = rd32(IGC_CTRL);\n-\t\t\t/* Link status message must follow this format */\n-\t\t\tnetdev_info(netdev,\n-\t\t\t\t \"igc: %s NIC Link is Up %d Mbps %s Duplex, Flow Control: %s\\n\",\n-\t\t\t\t netdev->name,\n-\t\t\t\t adapter->link_speed,\n-\t\t\t\t adapter->link_duplex == FULL_DUPLEX ?\n-\t\t\t\t \"Full\" : \"Half\",\n-\t\t\t\t (ctrl & IGC_CTRL_TFCE) &&\n-\t\t\t\t (ctrl & IGC_CTRL_RFCE) ? \"RX/TX\" :\n-\t\t\t\t (ctrl & IGC_CTRL_RFCE) ? \"RX\" :\n-\t\t\t\t (ctrl & IGC_CTRL_TFCE) ? \"TX\" : \"None\");\n+\twhile (test_and_set_bit(__IGC_RESETTING, &adapter->state))\n+\t\tusleep_range(1000, 2000);\n \n-\t\t\t/* check if SmartSpeed worked */\n-\t\t\tigc_check_downshift(hw);\n-\t\t\tif (phy->speed_downgraded)\n-\t\t\t\tnetdev_warn(netdev, \"Link Speed was downgraded by SmartSpeed\\n\");\n+\t/* igc_down has a dependency on max_frame_size */\n+\tadapter->max_frame_size = max_frame;\n \n-\t\t\t/* adjust timeout factor according to speed/duplex */\n-\t\t\tadapter->tx_timeout_factor = 1;\n-\t\t\tswitch (adapter->link_speed) {\n-\t\t\tcase SPEED_10:\n-\t\t\t\tadapter->tx_timeout_factor = 14;\n-\t\t\t\tbreak;\n-\t\t\tcase SPEED_100:\n-\t\t\t\t/* maybe add some timeout factor ? */\n-\t\t\t\tbreak;\n-\t\t\t}\n+\tif (netif_running(netdev))\n+\t\tigc_down(adapter);\n \n-\t\t\tif (adapter->link_speed != SPEED_1000)\n-\t\t\t\tgoto no_wait;\n+\tnetdev_dbg(netdev, \"changing MTU from %d to %d\\n\",\n+\t\t netdev->mtu, new_mtu);\n+\tnetdev->mtu = new_mtu;\n \n-\t\t\t/* wait for Remote receiver status OK */\n-retry_read_status:\n-\t\t\tif (!igc_read_phy_reg(hw, PHY_1000T_STATUS,\n-\t\t\t\t\t &phy_data)) {\n-\t\t\t\tif (!(phy_data & SR_1000T_REMOTE_RX_STATUS) &&\n-\t\t\t\t retry_count) {\n-\t\t\t\t\tmsleep(100);\n-\t\t\t\t\tretry_count--;\n-\t\t\t\t\tgoto retry_read_status;\n-\t\t\t\t} else if (!retry_count) {\n-\t\t\t\t\tdev_err(&adapter->pdev->dev, \"exceed max 2 second\\n\");\n-\t\t\t\t}\n-\t\t\t} else {\n-\t\t\t\tdev_err(&adapter->pdev->dev, \"read 1000Base-T Status Reg\\n\");\n-\t\t\t}\n-no_wait:\n-\t\t\tnetif_carrier_on(netdev);\n+\tif (netif_running(netdev))\n+\t\tigc_up(adapter);\n+\telse\n+\t\tigc_reset(adapter);\n \n-\t\t\t/* link state has changed, schedule phy info update */\n-\t\t\tif (!test_bit(__IGC_DOWN, &adapter->state))\n-\t\t\t\tmod_timer(&adapter->phy_info_timer,\n-\t\t\t\t\t round_jiffies(jiffies + 2 * HZ));\n-\t\t}\n-\t} else {\n-\t\tif (netif_carrier_ok(netdev)) {\n-\t\t\tadapter->link_speed = 0;\n-\t\t\tadapter->link_duplex = 0;\n+\tclear_bit(__IGC_RESETTING, &adapter->state);\n \n-\t\t\t/* Links status message must follow this format */\n-\t\t\tnetdev_info(netdev, \"igc: %s NIC Link is Down\\n\",\n-\t\t\t\t netdev->name);\n-\t\t\tnetif_carrier_off(netdev);\n+\treturn 0;\n+}\n \n-\t\t\t/* link state has changed, schedule phy info update */\n-\t\t\tif (!test_bit(__IGC_DOWN, &adapter->state))\n-\t\t\t\tmod_timer(&adapter->phy_info_timer,\n-\t\t\t\t\t round_jiffies(jiffies + 2 * HZ));\n+/**\n+ * igc_get_stats - Get System Network Statistics\n+ * @netdev: network interface device structure\n+ *\n+ * Returns the address of the device statistics structure.\n+ * The statistics are updated here and also from the timer callback.\n+ */\n+static struct net_device_stats *igc_get_stats(struct net_device *netdev)\n+{\n+\tstruct igc_adapter *adapter = netdev_priv(netdev);\n \n-\t\t\t/* link is down, time to check for alternate media */\n-\t\t\tif (adapter->flags & IGC_FLAG_MAS_ENABLE) {\n-\t\t\t\tif (adapter->flags & IGC_FLAG_MEDIA_RESET) {\n-\t\t\t\t\tschedule_work(&adapter->reset_task);\n-\t\t\t\t\t/* return immediately */\n-\t\t\t\t\treturn;\n-\t\t\t\t}\n-\t\t\t}\n+\tif (!test_bit(__IGC_RESETTING, &adapter->state))\n+\t\tigc_update_stats(adapter);\n \n-\t\t/* also check for alternate media here */\n-\t\t} else if (!netif_carrier_ok(netdev) &&\n-\t\t\t (adapter->flags & IGC_FLAG_MAS_ENABLE)) {\n-\t\t\tif (adapter->flags & IGC_FLAG_MEDIA_RESET) {\n-\t\t\t\tschedule_work(&adapter->reset_task);\n-\t\t\t\t/* return immediately */\n-\t\t\t\treturn;\n-\t\t\t}\n-\t\t}\n-\t}\n+\t/* only return the current stats */\n+\treturn &netdev->stats;\n+}\n+\n+static netdev_features_t igc_fix_features(struct net_device *netdev,\n+\t\t\t\t\t netdev_features_t features)\n+{\n+\t/* Since there is no support for separate Rx/Tx vlan accel\n+\t * enable/disable make sure Tx flag is always in same state as Rx.\n+\t */\n+\tif (features & NETIF_F_HW_VLAN_CTAG_RX)\n+\t\tfeatures |= NETIF_F_HW_VLAN_CTAG_TX;\n+\telse\n+\t\tfeatures &= ~NETIF_F_HW_VLAN_CTAG_TX;\n+\n+\treturn features;\n+}\n+\n+static int igc_set_features(struct net_device *netdev,\n+\t\t\t netdev_features_t features)\n+{\n+\tnetdev_features_t changed = netdev->features ^ features;\n+\tstruct igc_adapter *adapter = netdev_priv(netdev);\n \n-\tspin_lock(&adapter->stats64_lock);\n-\tigc_update_stats(adapter);\n-\tspin_unlock(&adapter->stats64_lock);\n+\t/* Add VLAN support */\n+\tif (!(changed & (NETIF_F_RXALL | NETIF_F_NTUPLE)))\n+\t\treturn 0;\n \n-\tfor (i = 0; i < adapter->num_tx_queues; i++) {\n-\t\tstruct igc_ring *tx_ring = adapter->tx_ring[i];\n+\tif (!(features & NETIF_F_NTUPLE)) {\n+\t\tstruct hlist_node *node2;\n+\t\tstruct igc_nfc_filter *rule;\n \n-\t\tif (!netif_carrier_ok(netdev)) {\n-\t\t\t/* We've lost link, so the controller stops DMA,\n-\t\t\t * but we've got queued Tx work that's never going\n-\t\t\t * to get done, so reset controller to flush Tx.\n-\t\t\t * (Do the reset outside of interrupt context).\n-\t\t\t */\n-\t\t\tif (igc_desc_unused(tx_ring) + 1 < tx_ring->count) {\n-\t\t\t\tadapter->tx_timeout_count++;\n-\t\t\t\tschedule_work(&adapter->reset_task);\n-\t\t\t\t/* return immediately since reset is imminent */\n-\t\t\t\treturn;\n-\t\t\t}\n+\t\tspin_lock(&adapter->nfc_lock);\n+\t\thlist_for_each_entry_safe(rule, node2,\n+\t\t\t\t\t &adapter->nfc_filter_list, nfc_node) {\n+\t\t\tigc_erase_filter(adapter, rule);\n+\t\t\thlist_del(&rule->nfc_node);\n+\t\t\tkfree(rule);\n \t\t}\n-\n-\t\t/* Force detection of hung controller every watchdog period */\n-\t\tset_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags);\n+\t\tspin_unlock(&adapter->nfc_lock);\n+\t\tadapter->nfc_filter_count = 0;\n \t}\n \n-\t/* Cause software interrupt to ensure Rx ring is cleaned */\n-\tif (adapter->flags & IGC_FLAG_HAS_MSIX) {\n-\t\tu32 eics = 0;\n+\tnetdev->features = features;\n \n-\t\tfor (i = 0; i < adapter->num_q_vectors; i++)\n-\t\t\teics |= adapter->q_vector[i]->eims_value;\n-\t\twr32(IGC_EICS, eics);\n-\t} else {\n-\t\twr32(IGC_ICS, IGC_ICS_RXDMT0);\n-\t}\n+\tif (netif_running(netdev))\n+\t\tigc_reinit_locked(adapter);\n+\telse\n+\t\tigc_reset(adapter);\n \n-\t/* Reset the timer */\n-\tif (!test_bit(__IGC_DOWN, &adapter->state)) {\n-\t\tif (adapter->flags & IGC_FLAG_NEED_LINK_UPDATE)\n-\t\t\tmod_timer(&adapter->watchdog_timer,\n-\t\t\t\t round_jiffies(jiffies + HZ));\n-\t\telse\n-\t\t\tmod_timer(&adapter->watchdog_timer,\n-\t\t\t\t round_jiffies(jiffies + 2 * HZ));\n-\t}\n+\treturn 1;\n }\n \n-/**\n- * igc_update_ring_itr - update the dynamic ITR value based on packet size\n- * @q_vector: pointer to q_vector\n- *\n- * Stores a new ITR value based on strictly on packet size. This\n- * algorithm is less sophisticated than that used in igc_update_itr,\n- * due to the difficulty of synchronizing statistics across multiple\n- * receive rings. The divisors and thresholds used by this function\n- * were determined based on theoretical maximum wire speed and testing\n- * data, in order to minimize response time while increasing bulk\n- * throughput.\n- * NOTE: This function is called only when operating in a multiqueue\n- * receive environment.\n- */\n-static void igc_update_ring_itr(struct igc_q_vector *q_vector)\n+static netdev_features_t\n+igc_features_check(struct sk_buff *skb, struct net_device *dev,\n+\t\t netdev_features_t features)\n {\n-\tstruct igc_adapter *adapter = q_vector->adapter;\n-\tint new_val = q_vector->itr_val;\n-\tint avg_wire_size = 0;\n-\tunsigned int packets;\n+\tunsigned int network_hdr_len, mac_hdr_len;\n \n-\t/* For non-gigabit speeds, just fix the interrupt rate at 4000\n-\t * ints/sec - ITR timer value of 120 ticks.\n-\t */\n-\tswitch (adapter->link_speed) {\n-\tcase SPEED_10:\n-\tcase SPEED_100:\n-\t\tnew_val = IGC_4K_ITR;\n-\t\tgoto set_itr_val;\n-\tdefault:\n-\t\tbreak;\n-\t}\n+\t/* Make certain the headers can be described by a context descriptor */\n+\tmac_hdr_len = skb_network_header(skb) - skb->data;\n+\tif (unlikely(mac_hdr_len > IGC_MAX_MAC_HDR_LEN))\n+\t\treturn features & ~(NETIF_F_HW_CSUM |\n+\t\t\t\t NETIF_F_SCTP_CRC |\n+\t\t\t\t NETIF_F_HW_VLAN_CTAG_TX |\n+\t\t\t\t NETIF_F_TSO |\n+\t\t\t\t NETIF_F_TSO6);\n \n-\tpackets = q_vector->rx.total_packets;\n-\tif (packets)\n-\t\tavg_wire_size = q_vector->rx.total_bytes / packets;\n+\tnetwork_hdr_len = skb_checksum_start(skb) - skb_network_header(skb);\n+\tif (unlikely(network_hdr_len > IGC_MAX_NETWORK_HDR_LEN))\n+\t\treturn features & ~(NETIF_F_HW_CSUM |\n+\t\t\t\t NETIF_F_SCTP_CRC |\n+\t\t\t\t NETIF_F_TSO |\n+\t\t\t\t NETIF_F_TSO6);\n \n-\tpackets = q_vector->tx.total_packets;\n-\tif (packets)\n-\t\tavg_wire_size = max_t(u32, avg_wire_size,\n-\t\t\t\t q_vector->tx.total_bytes / packets);\n+\t/* We can only support IPv4 TSO in tunnels if we can mangle the\n+\t * inner IP ID field, so strip TSO if MANGLEID is not supported.\n+\t */\n+\tif (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID))\n+\t\tfeatures &= ~NETIF_F_TSO;\n \n-\t/* if avg_wire_size isn't set no work was done */\n-\tif (!avg_wire_size)\n-\t\tgoto clear_counts;\n+\treturn features;\n+}\n \n-\t/* Add 24 bytes to size to account for CRC, preamble, and gap */\n-\tavg_wire_size += 24;\n+/* Add a MAC filter for 'addr' directing matching traffic to 'queue',\n+ * 'flags' is used to indicate what kind of match is made, match is by\n+ * default for the destination address, if matching by source address\n+ * is desired the flag IGC_MAC_STATE_SRC_ADDR can be used.\n+ */\n+static int igc_add_mac_filter_flags(struct igc_adapter *adapter,\n+\t\t\t\t const u8 *addr, const u8 queue,\n+\t\t\t\t const u8 flags)\n+{\n+\tstruct igc_hw *hw = &adapter->hw;\n+\tint rar_entries = hw->mac.rar_entry_count;\n+\tint i;\n \n-\t/* Don't starve jumbo frames */\n-\tavg_wire_size = min(avg_wire_size, 3000);\n+\tif (is_zero_ether_addr(addr))\n+\t\treturn -EINVAL;\n \n-\t/* Give a little boost to mid-size frames */\n-\tif (avg_wire_size > 300 && avg_wire_size < 1200)\n-\t\tnew_val = avg_wire_size / 3;\n-\telse\n-\t\tnew_val = avg_wire_size / 2;\n+\t/* Search for the first empty entry in the MAC table.\n+\t * Do not touch entries at the end of the table reserved for the VF MAC\n+\t * addresses.\n+\t */\n+\tfor (i = 0; i < rar_entries; i++) {\n+\t\tif (!igc_mac_entry_can_be_used(&adapter->mac_table[i],\n+\t\t\t\t\t addr, flags))\n+\t\t\tcontinue;\n \n-\t/* conservative mode (itr 3) eliminates the lowest_latency setting */\n-\tif (new_val < IGC_20K_ITR &&\n-\t ((q_vector->rx.ring && adapter->rx_itr_setting == 3) ||\n-\t (!q_vector->rx.ring && adapter->tx_itr_setting == 3)))\n-\t\tnew_val = IGC_20K_ITR;\n+\t\tether_addr_copy(adapter->mac_table[i].addr, addr);\n+\t\tadapter->mac_table[i].queue = queue;\n+\t\tadapter->mac_table[i].state |= IGC_MAC_STATE_IN_USE | flags;\n \n-set_itr_val:\n-\tif (new_val != q_vector->itr_val) {\n-\t\tq_vector->itr_val = new_val;\n-\t\tq_vector->set_itr = 1;\n+\t\tigc_rar_set_index(adapter, i);\n+\t\treturn i;\n \t}\n-clear_counts:\n-\tq_vector->rx.total_bytes = 0;\n-\tq_vector->rx.total_packets = 0;\n-\tq_vector->tx.total_bytes = 0;\n-\tq_vector->tx.total_packets = 0;\n+\n+\treturn -ENOSPC;\n }\n \n-/**\n- * igc_update_itr - update the dynamic ITR value based on statistics\n- * @q_vector: pointer to q_vector\n- * @ring_container: ring info to update the itr for\n- *\n- * Stores a new ITR value based on packets and byte\n- * counts during the last interrupt. The advantage of per interrupt\n- * computation is faster updates and more accurate ITR for the current\n- * traffic pattern. Constants in this function were computed\n- * based on theoretical maximum wire speed and thresholds were set based\n- * on testing data as well as attempting to minimize response time\n- * while increasing bulk throughput.\n- * NOTE: These calculations are only valid when operating in a single-\n- * queue environment.\n+int igc_add_mac_steering_filter(struct igc_adapter *adapter,\n+\t\t\t\tconst u8 *addr, u8 queue, u8 flags)\n+{\n+\treturn igc_add_mac_filter_flags(adapter, addr, queue,\n+\t\t\t\t\tIGC_MAC_STATE_QUEUE_STEERING | flags);\n+}\n+\n+/* Remove a MAC filter for 'addr' directing matching traffic to\n+ * 'queue', 'flags' is used to indicate what kind of match need to be\n+ * removed, match is by default for the destination address, if\n+ * matching by source address is to be removed the flag\n+ * IGC_MAC_STATE_SRC_ADDR can be used.\n */\n-static void igc_update_itr(struct igc_q_vector *q_vector,\n-\t\t\t struct igc_ring_container *ring_container)\n+static int igc_del_mac_filter_flags(struct igc_adapter *adapter,\n+\t\t\t\t const u8 *addr, const u8 queue,\n+\t\t\t\t const u8 flags)\n {\n-\tunsigned int packets = ring_container->total_packets;\n-\tunsigned int bytes = ring_container->total_bytes;\n-\tu8 itrval = ring_container->itr;\n+\tstruct igc_hw *hw = &adapter->hw;\n+\tint rar_entries = hw->mac.rar_entry_count;\n+\tint i;\n \n-\t/* no packets, exit with status unchanged */\n-\tif (packets == 0)\n-\t\treturn;\n+\tif (is_zero_ether_addr(addr))\n+\t\treturn -EINVAL;\n \n-\tswitch (itrval) {\n-\tcase lowest_latency:\n-\t\t/* handle TSO and jumbo frames */\n-\t\tif (bytes / packets > 8000)\n-\t\t\titrval = bulk_latency;\n-\t\telse if ((packets < 5) && (bytes > 512))\n-\t\t\titrval = low_latency;\n-\t\tbreak;\n-\tcase low_latency: /* 50 usec aka 20000 ints/s */\n-\t\tif (bytes > 10000) {\n-\t\t\t/* this if handles the TSO accounting */\n-\t\t\tif (bytes / packets > 8000)\n-\t\t\t\titrval = bulk_latency;\n-\t\t\telse if ((packets < 10) || ((bytes / packets) > 1200))\n-\t\t\t\titrval = bulk_latency;\n-\t\t\telse if ((packets > 35))\n-\t\t\t\titrval = lowest_latency;\n-\t\t} else if (bytes / packets > 2000) {\n-\t\t\titrval = bulk_latency;\n-\t\t} else if (packets <= 2 && bytes < 512) {\n-\t\t\titrval = lowest_latency;\n-\t\t}\n-\t\tbreak;\n-\tcase bulk_latency: /* 250 usec aka 4000 ints/s */\n-\t\tif (bytes > 25000) {\n-\t\t\tif (packets > 35)\n-\t\t\t\titrval = low_latency;\n-\t\t} else if (bytes < 1500) {\n-\t\t\titrval = low_latency;\n+\t/* Search for matching entry in the MAC table based on given address\n+\t * and queue. Do not touch entries at the end of the table reserved\n+\t * for the VF MAC addresses.\n+\t */\n+\tfor (i = 0; i < rar_entries; i++) {\n+\t\tif (!(adapter->mac_table[i].state & IGC_MAC_STATE_IN_USE))\n+\t\t\tcontinue;\n+\t\tif ((adapter->mac_table[i].state & flags) != flags)\n+\t\t\tcontinue;\n+\t\tif (adapter->mac_table[i].queue != queue)\n+\t\t\tcontinue;\n+\t\tif (!ether_addr_equal(adapter->mac_table[i].addr, addr))\n+\t\t\tcontinue;\n+\n+\t\t/* When a filter for the default address is \"deleted\",\n+\t\t * we return it to its initial configuration\n+\t\t */\n+\t\tif (adapter->mac_table[i].state & IGC_MAC_STATE_DEFAULT) {\n+\t\t\tadapter->mac_table[i].state =\n+\t\t\t\tIGC_MAC_STATE_DEFAULT | IGC_MAC_STATE_IN_USE;\n+\t\t} else {\n+\t\t\tadapter->mac_table[i].state = 0;\n+\t\t\tadapter->mac_table[i].queue = 0;\n+\t\t\tmemset(adapter->mac_table[i].addr, 0, ETH_ALEN);\n \t\t}\n-\t\tbreak;\n+\n+\t\tigc_rar_set_index(adapter, i);\n+\t\treturn 0;\n \t}\n \n-\t/* clear work counters since we have the values we need */\n-\tring_container->total_bytes = 0;\n-\tring_container->total_packets = 0;\n+\treturn -ENOENT;\n+}\n \n-\t/* write updated itr to ring container */\n-\tring_container->itr = itrval;\n+int igc_del_mac_steering_filter(struct igc_adapter *adapter,\n+\t\t\t\tconst u8 *addr, u8 queue, u8 flags)\n+{\n+\treturn igc_del_mac_filter_flags(adapter, addr, queue,\n+\t\t\t\t\tIGC_MAC_STATE_QUEUE_STEERING | flags);\n }\n \n /**\n- * igc_intr_msi - Interrupt Handler\n+ * igc_msix_other - msix other interrupt handler\n * @irq: interrupt number\n- * @data: pointer to a network interface device structure\n+ * @data: pointer to a q_vector\n */\n-static irqreturn_t igc_intr_msi(int irq, void *data)\n+static irqreturn_t igc_msix_other(int irq, void *data)\n {\n \tstruct igc_adapter *adapter = data;\n-\tstruct igc_q_vector *q_vector = adapter->q_vector[0];\n \tstruct igc_hw *hw = &adapter->hw;\n-\t/* read ICR disables interrupts using IAM */\n \tu32 icr = rd32(IGC_ICR);\n \n-\tigc_write_itr(q_vector);\n-\n+\t/* reading ICR causes bit 31 of EICR to be cleared */\n \tif (icr & IGC_ICR_DRSTA)\n \t\tschedule_work(&adapter->reset_task);\n \n@@ -3586,408 +3655,428 @@ static irqreturn_t igc_intr_msi(int irq, void *data)\n \t\tadapter->stats.doosync++;\n \t}\n \n-\tif (icr & (IGC_ICR_RXSEQ | IGC_ICR_LSC)) {\n+\tif (icr & IGC_ICR_LSC) {\n \t\thw->mac.get_link_status = 1;\n+\t\t/* guard against interrupt when we're going down */\n \t\tif (!test_bit(__IGC_DOWN, &adapter->state))\n \t\t\tmod_timer(&adapter->watchdog_timer, jiffies + 1);\n \t}\n \n-\tnapi_schedule(&q_vector->napi);\n+\twr32(IGC_EIMS, adapter->eims_other);\n \n \treturn IRQ_HANDLED;\n }\n \n-/**\n- * igc_intr - Legacy Interrupt Handler\n- * @irq: interrupt number\n- * @data: pointer to a network interface device structure\n- */\n-static irqreturn_t igc_intr(int irq, void *data)\n+static void igc_write_itr(struct igc_q_vector *q_vector)\n {\n-\tstruct igc_adapter *adapter = data;\n-\tstruct igc_q_vector *q_vector = adapter->q_vector[0];\n-\tstruct igc_hw *hw = &adapter->hw;\n-\t/* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No\n-\t * need for the IMC write\n-\t */\n-\tu32 icr = rd32(IGC_ICR);\n+\tu32 itr_val = q_vector->itr_val & IGC_QVECTOR_MASK;\n \n-\t/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is\n-\t * not set, then the adapter didn't send an interrupt\n-\t */\n-\tif (!(icr & IGC_ICR_INT_ASSERTED))\n-\t\treturn IRQ_NONE;\n+\tif (!q_vector->set_itr)\n+\t\treturn;\n \n-\tigc_write_itr(q_vector);\n+\tif (!itr_val)\n+\t\titr_val = IGC_ITR_VAL_MASK;\n \n-\tif (icr & IGC_ICR_DRSTA)\n-\t\tschedule_work(&adapter->reset_task);\n+\titr_val |= IGC_EITR_CNT_IGNR;\n \n-\tif (icr & IGC_ICR_DOUTSYNC) {\n-\t\t/* HW is reporting DMA is out of sync */\n-\t\tadapter->stats.doosync++;\n-\t}\n+\twritel(itr_val, q_vector->itr_register);\n+\tq_vector->set_itr = 0;\n+}\n \n-\tif (icr & (IGC_ICR_RXSEQ | IGC_ICR_LSC)) {\n-\t\thw->mac.get_link_status = 1;\n-\t\t/* guard against interrupt when we're going down */\n-\t\tif (!test_bit(__IGC_DOWN, &adapter->state))\n-\t\t\tmod_timer(&adapter->watchdog_timer, jiffies + 1);\n-\t}\n+static irqreturn_t igc_msix_ring(int irq, void *data)\n+{\n+\tstruct igc_q_vector *q_vector = data;\n+\n+\t/* Write the ITR value calculated from the previous interrupt. */\n+\tigc_write_itr(q_vector);\n \n \tnapi_schedule(&q_vector->napi);\n \n \treturn IRQ_HANDLED;\n }\n \n-static void igc_set_itr(struct igc_q_vector *q_vector)\n+/**\n+ * igc_request_msix - Initialize MSI-X interrupts\n+ * @adapter: Pointer to adapter structure\n+ *\n+ * igc_request_msix allocates MSI-X vectors and requests interrupts from the\n+ * kernel.\n+ */\n+static int igc_request_msix(struct igc_adapter *adapter)\n {\n-\tstruct igc_adapter *adapter = q_vector->adapter;\n-\tu32 new_itr = q_vector->itr_val;\n-\tu8 current_itr = 0;\n+\tint i = 0, err = 0, vector = 0, free_vector = 0;\n+\tstruct net_device *netdev = adapter->netdev;\n \n-\t/* for non-gigabit speeds, just fix the interrupt rate at 4000 */\n-\tswitch (adapter->link_speed) {\n-\tcase SPEED_10:\n-\tcase SPEED_100:\n-\t\tcurrent_itr = 0;\n-\t\tnew_itr = IGC_4K_ITR;\n-\t\tgoto set_itr_now;\n-\tdefault:\n-\t\tbreak;\n-\t}\n+\terr = request_irq(adapter->msix_entries[vector].vector,\n+\t\t\t &igc_msix_other, 0, netdev->name, adapter);\n+\tif (err)\n+\t\tgoto err_out;\n \n-\tigc_update_itr(q_vector, &q_vector->tx);\n-\tigc_update_itr(q_vector, &q_vector->rx);\n+\tfor (i = 0; i < adapter->num_q_vectors; i++) {\n+\t\tstruct igc_q_vector *q_vector = adapter->q_vector[i];\n \n-\tcurrent_itr = max(q_vector->rx.itr, q_vector->tx.itr);\n+\t\tvector++;\n \n-\t/* conservative mode (itr 3) eliminates the lowest_latency setting */\n-\tif (current_itr == lowest_latency &&\n-\t ((q_vector->rx.ring && adapter->rx_itr_setting == 3) ||\n-\t (!q_vector->rx.ring && adapter->tx_itr_setting == 3)))\n-\t\tcurrent_itr = low_latency;\n+\t\tq_vector->itr_register = adapter->io_addr + IGC_EITR(vector);\n \n-\tswitch (current_itr) {\n-\t/* counts and packets in update_itr are dependent on these numbers */\n-\tcase lowest_latency:\n-\t\tnew_itr = IGC_70K_ITR; /* 70,000 ints/sec */\n-\t\tbreak;\n-\tcase low_latency:\n-\t\tnew_itr = IGC_20K_ITR; /* 20,000 ints/sec */\n-\t\tbreak;\n-\tcase bulk_latency:\n-\t\tnew_itr = IGC_4K_ITR; /* 4,000 ints/sec */\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n+\t\tif (q_vector->rx.ring && q_vector->tx.ring)\n+\t\t\tsprintf(q_vector->name, \"%s-TxRx-%u\", netdev->name,\n+\t\t\t\tq_vector->rx.ring->queue_index);\n+\t\telse if (q_vector->tx.ring)\n+\t\t\tsprintf(q_vector->name, \"%s-tx-%u\", netdev->name,\n+\t\t\t\tq_vector->tx.ring->queue_index);\n+\t\telse if (q_vector->rx.ring)\n+\t\t\tsprintf(q_vector->name, \"%s-rx-%u\", netdev->name,\n+\t\t\t\tq_vector->rx.ring->queue_index);\n+\t\telse\n+\t\t\tsprintf(q_vector->name, \"%s-unused\", netdev->name);\n \n-set_itr_now:\n-\tif (new_itr != q_vector->itr_val) {\n-\t\t/* this attempts to bias the interrupt rate towards Bulk\n-\t\t * by adding intermediate steps when interrupt rate is\n-\t\t * increasing\n-\t\t */\n-\t\tnew_itr = new_itr > q_vector->itr_val ?\n-\t\t\t max((new_itr * q_vector->itr_val) /\n-\t\t\t (new_itr + (q_vector->itr_val >> 2)),\n-\t\t\t new_itr) : new_itr;\n-\t\t/* Don't write the value here; it resets the adapter's\n-\t\t * internal timer, and causes us to delay far longer than\n-\t\t * we should between interrupts. Instead, we write the ITR\n-\t\t * value at the beginning of the next interrupt so the timing\n-\t\t * ends up being correct.\n-\t\t */\n-\t\tq_vector->itr_val = new_itr;\n-\t\tq_vector->set_itr = 1;\n+\t\terr = request_irq(adapter->msix_entries[vector].vector,\n+\t\t\t\t igc_msix_ring, 0, q_vector->name,\n+\t\t\t\t q_vector);\n+\t\tif (err)\n+\t\t\tgoto err_free;\n \t}\n-}\n \n-static void igc_ring_irq_enable(struct igc_q_vector *q_vector)\n-{\n-\tstruct igc_adapter *adapter = q_vector->adapter;\n-\tstruct igc_hw *hw = &adapter->hw;\n+\tigc_configure_msix(adapter);\n+\treturn 0;\n \n-\tif ((q_vector->rx.ring && (adapter->rx_itr_setting & 3)) ||\n-\t (!q_vector->rx.ring && (adapter->tx_itr_setting & 3))) {\n-\t\tif (adapter->num_q_vectors == 1)\n-\t\t\tigc_set_itr(q_vector);\n-\t\telse\n-\t\t\tigc_update_ring_itr(q_vector);\n-\t}\n+err_free:\n+\t/* free already assigned IRQs */\n+\tfree_irq(adapter->msix_entries[free_vector++].vector, adapter);\n \n-\tif (!test_bit(__IGC_DOWN, &adapter->state)) {\n-\t\tif (adapter->msix_entries)\n-\t\t\twr32(IGC_EIMS, q_vector->eims_value);\n-\t\telse\n-\t\t\tigc_irq_enable(adapter);\n+\tvector--;\n+\tfor (i = 0; i < vector; i++) {\n+\t\tfree_irq(adapter->msix_entries[free_vector++].vector,\n+\t\t\t adapter->q_vector[i]);\n \t}\n+err_out:\n+\treturn err;\n }\n \n /**\n- * igc_poll - NAPI Rx polling callback\n- * @napi: napi polling structure\n- * @budget: count of how many packets we should handle\n+ * igc_clear_interrupt_scheme - reset the device to a state of no interrupts\n+ * @adapter: Pointer to adapter structure\n+ *\n+ * This function resets the device so that it has 0 rx queues, tx queues, and\n+ * MSI-X interrupts allocated.\n */\n-static int igc_poll(struct napi_struct *napi, int budget)\n+static void igc_clear_interrupt_scheme(struct igc_adapter *adapter)\n {\n-\tstruct igc_q_vector *q_vector = container_of(napi,\n-\t\t\t\t\t\t struct igc_q_vector,\n-\t\t\t\t\t\t napi);\n-\tbool clean_complete = true;\n-\tint work_done = 0;\n-\n-\tif (q_vector->tx.ring)\n-\t\tclean_complete = igc_clean_tx_irq(q_vector, budget);\n-\n-\tif (q_vector->rx.ring) {\n-\t\tint cleaned = igc_clean_rx_irq(q_vector, budget);\n-\n-\t\twork_done += cleaned;\n-\t\tif (cleaned >= budget)\n-\t\t\tclean_complete = false;\n-\t}\n-\n-\t/* If all work not completed, return budget and keep polling */\n-\tif (!clean_complete)\n-\t\treturn budget;\n+\tigc_free_q_vectors(adapter);\n+\tigc_reset_interrupt_capability(adapter);\n+}\n \n-\t/* Exit the polling mode, but don't re-enable interrupts if stack might\n-\t * poll us due to busy-polling\n-\t */\n-\tif (likely(napi_complete_done(napi, work_done)))\n-\t\tigc_ring_irq_enable(q_vector);\n+/* Need to wait a few seconds after link up to get diagnostic information from\n+ * the phy\n+ */\n+static void igc_update_phy_info(struct timer_list *t)\n+{\n+\tstruct igc_adapter *adapter = from_timer(adapter, t, phy_info_timer);\n \n-\treturn min(work_done, budget - 1);\n+\tigc_get_phy_info(&adapter->hw);\n }\n \n-static void igc_add_ring(struct igc_ring *ring,\n-\t\t\t struct igc_ring_container *head)\n+/**\n+ * igc_has_link - check shared code for link and determine up/down\n+ * @adapter: pointer to driver private info\n+ */\n+bool igc_has_link(struct igc_adapter *adapter)\n {\n-\thead->ring = ring;\n-\thead->count++;\n+\tstruct igc_hw *hw = &adapter->hw;\n+\tbool link_active = false;\n+\n+\t/* get_link_status is set on LSC (link status) interrupt or\n+\t * rx sequence error interrupt. get_link_status will stay\n+\t * false until the igc_check_for_link establishes link\n+\t * for copper adapters ONLY\n+\t */\n+\tswitch (hw->phy.media_type) {\n+\tcase igc_media_type_copper:\n+\t\tif (!hw->mac.get_link_status)\n+\t\t\treturn true;\n+\t\thw->mac.ops.check_for_link(hw);\n+\t\tlink_active = !hw->mac.get_link_status;\n+\t\tbreak;\n+\tdefault:\n+\tcase igc_media_type_unknown:\n+\t\tbreak;\n+\t}\n+\n+\tif (hw->mac.type == igc_i225 &&\n+\t hw->phy.id == I225_I_PHY_ID) {\n+\t\tif (!netif_carrier_ok(adapter->netdev)) {\n+\t\t\tadapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;\n+\t\t} else if (!(adapter->flags & IGC_FLAG_NEED_LINK_UPDATE)) {\n+\t\t\tadapter->flags |= IGC_FLAG_NEED_LINK_UPDATE;\n+\t\t\tadapter->link_check_timeout = jiffies;\n+\t\t}\n+\t}\n+\n+\treturn link_active;\n }\n \n /**\n- * igc_alloc_q_vector - Allocate memory for a single interrupt vector\n- * @adapter: board private structure to initialize\n- * @v_count: q_vectors allocated on adapter, used for ring interleaving\n- * @v_idx: index of vector in adapter struct\n- * @txr_count: total number of Tx rings to allocate\n- * @txr_idx: index of first Tx ring to allocate\n- * @rxr_count: total number of Rx rings to allocate\n- * @rxr_idx: index of first Rx ring to allocate\n- *\n- * We allocate one q_vector. If allocation fails we return -ENOMEM.\n+ * igc_watchdog - Timer Call-back\n+ * @t: timer for the watchdog\n */\n-static int igc_alloc_q_vector(struct igc_adapter *adapter,\n-\t\t\t unsigned int v_count, unsigned int v_idx,\n-\t\t\t unsigned int txr_count, unsigned int txr_idx,\n-\t\t\t unsigned int rxr_count, unsigned int rxr_idx)\n+static void igc_watchdog(struct timer_list *t)\n {\n-\tstruct igc_q_vector *q_vector;\n-\tstruct igc_ring *ring;\n-\tint ring_count;\n+\tstruct igc_adapter *adapter = from_timer(adapter, t, watchdog_timer);\n+\t/* Do the rest outside of interrupt context */\n+\tschedule_work(&adapter->watchdog_task);\n+}\n \n-\t/* igc only supports 1 Tx and/or 1 Rx queue per vector */\n-\tif (txr_count > 1 || rxr_count > 1)\n-\t\treturn -ENOMEM;\n+static void igc_watchdog_task(struct work_struct *work)\n+{\n+\tstruct igc_adapter *adapter = container_of(work,\n+\t\t\t\t\t\t struct igc_adapter,\n+\t\t\t\t\t\t watchdog_task);\n+\tstruct net_device *netdev = adapter->netdev;\n+\tstruct igc_hw *hw = &adapter->hw;\n+\tstruct igc_phy_info *phy = &hw->phy;\n+\tu16 phy_data, retry_count = 20;\n+\tu32 connsw;\n+\tu32 link;\n+\tint i;\n \n-\tring_count = txr_count + rxr_count;\n+\tlink = igc_has_link(adapter);\n \n-\t/* allocate q_vector and rings */\n-\tq_vector = adapter->q_vector[v_idx];\n-\tif (!q_vector)\n-\t\tq_vector = kzalloc(struct_size(q_vector, ring, ring_count),\n-\t\t\t\t GFP_KERNEL);\n-\telse\n-\t\tmemset(q_vector, 0, struct_size(q_vector, ring, ring_count));\n-\tif (!q_vector)\n-\t\treturn -ENOMEM;\n+\tif (adapter->flags & IGC_FLAG_NEED_LINK_UPDATE) {\n+\t\tif (time_after(jiffies, (adapter->link_check_timeout + HZ)))\n+\t\t\tadapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;\n+\t\telse\n+\t\t\tlink = false;\n+\t}\n \n-\t/* initialize NAPI */\n-\tnetif_napi_add(adapter->netdev, &q_vector->napi,\n-\t\t igc_poll, 64);\n+\t/* Force link down if we have fiber to swap to */\n+\tif (adapter->flags & IGC_FLAG_MAS_ENABLE) {\n+\t\tif (hw->phy.media_type == igc_media_type_copper) {\n+\t\t\tconnsw = rd32(IGC_CONNSW);\n+\t\t\tif (!(connsw & IGC_CONNSW_AUTOSENSE_EN))\n+\t\t\t\tlink = 0;\n+\t\t}\n+\t}\n+\tif (link) {\n+\t\tif (!netif_carrier_ok(netdev)) {\n+\t\t\tu32 ctrl;\n \n-\t/* tie q_vector and adapter together */\n-\tadapter->q_vector[v_idx] = q_vector;\n-\tq_vector->adapter = adapter;\n+\t\t\thw->mac.ops.get_speed_and_duplex(hw,\n+\t\t\t\t\t\t\t &adapter->link_speed,\n+\t\t\t\t\t\t\t &adapter->link_duplex);\n \n-\t/* initialize work limits */\n-\tq_vector->tx.work_limit = adapter->tx_work_limit;\n+\t\t\tctrl = rd32(IGC_CTRL);\n+\t\t\t/* Link status message must follow this format */\n+\t\t\tnetdev_info(netdev,\n+\t\t\t\t \"igc: %s NIC Link is Up %d Mbps %s Duplex, Flow Control: %s\\n\",\n+\t\t\t\t netdev->name,\n+\t\t\t\t adapter->link_speed,\n+\t\t\t\t adapter->link_duplex == FULL_DUPLEX ?\n+\t\t\t\t \"Full\" : \"Half\",\n+\t\t\t\t (ctrl & IGC_CTRL_TFCE) &&\n+\t\t\t\t (ctrl & IGC_CTRL_RFCE) ? \"RX/TX\" :\n+\t\t\t\t (ctrl & IGC_CTRL_RFCE) ? \"RX\" :\n+\t\t\t\t (ctrl & IGC_CTRL_TFCE) ? \"TX\" : \"None\");\n \n-\t/* initialize ITR configuration */\n-\tq_vector->itr_register = adapter->io_addr + IGC_EITR(0);\n-\tq_vector->itr_val = IGC_START_ITR;\n+\t\t\t/* check if SmartSpeed worked */\n+\t\t\tigc_check_downshift(hw);\n+\t\t\tif (phy->speed_downgraded)\n+\t\t\t\tnetdev_warn(netdev, \"Link Speed was downgraded by SmartSpeed\\n\");\n \n-\t/* initialize pointer to rings */\n-\tring = q_vector->ring;\n+\t\t\t/* adjust timeout factor according to speed/duplex */\n+\t\t\tadapter->tx_timeout_factor = 1;\n+\t\t\tswitch (adapter->link_speed) {\n+\t\t\tcase SPEED_10:\n+\t\t\t\tadapter->tx_timeout_factor = 14;\n+\t\t\t\tbreak;\n+\t\t\tcase SPEED_100:\n+\t\t\t\t/* maybe add some timeout factor ? */\n+\t\t\t\tbreak;\n+\t\t\t}\n \n-\t/* initialize ITR */\n-\tif (rxr_count) {\n-\t\t/* rx or rx/tx vector */\n-\t\tif (!adapter->rx_itr_setting || adapter->rx_itr_setting > 3)\n-\t\t\tq_vector->itr_val = adapter->rx_itr_setting;\n-\t} else {\n-\t\t/* tx only vector */\n-\t\tif (!adapter->tx_itr_setting || adapter->tx_itr_setting > 3)\n-\t\t\tq_vector->itr_val = adapter->tx_itr_setting;\n-\t}\n+\t\t\tif (adapter->link_speed != SPEED_1000)\n+\t\t\t\tgoto no_wait;\n \n-\tif (txr_count) {\n-\t\t/* assign generic ring traits */\n-\t\tring->dev = &adapter->pdev->dev;\n-\t\tring->netdev = adapter->netdev;\n+\t\t\t/* wait for Remote receiver status OK */\n+retry_read_status:\n+\t\t\tif (!igc_read_phy_reg(hw, PHY_1000T_STATUS,\n+\t\t\t\t\t &phy_data)) {\n+\t\t\t\tif (!(phy_data & SR_1000T_REMOTE_RX_STATUS) &&\n+\t\t\t\t retry_count) {\n+\t\t\t\t\tmsleep(100);\n+\t\t\t\t\tretry_count--;\n+\t\t\t\t\tgoto retry_read_status;\n+\t\t\t\t} else if (!retry_count) {\n+\t\t\t\t\tdev_err(&adapter->pdev->dev, \"exceed max 2 second\\n\");\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tdev_err(&adapter->pdev->dev, \"read 1000Base-T Status Reg\\n\");\n+\t\t\t}\n+no_wait:\n+\t\t\tnetif_carrier_on(netdev);\n \n-\t\t/* configure backlink on ring */\n-\t\tring->q_vector = q_vector;\n+\t\t\t/* link state has changed, schedule phy info update */\n+\t\t\tif (!test_bit(__IGC_DOWN, &adapter->state))\n+\t\t\t\tmod_timer(&adapter->phy_info_timer,\n+\t\t\t\t\t round_jiffies(jiffies + 2 * HZ));\n+\t\t}\n+\t} else {\n+\t\tif (netif_carrier_ok(netdev)) {\n+\t\t\tadapter->link_speed = 0;\n+\t\t\tadapter->link_duplex = 0;\n \n-\t\t/* update q_vector Tx values */\n-\t\tigc_add_ring(ring, &q_vector->tx);\n+\t\t\t/* Links status message must follow this format */\n+\t\t\tnetdev_info(netdev, \"igc: %s NIC Link is Down\\n\",\n+\t\t\t\t netdev->name);\n+\t\t\tnetif_carrier_off(netdev);\n \n-\t\t/* apply Tx specific ring traits */\n-\t\tring->count = adapter->tx_ring_count;\n-\t\tring->queue_index = txr_idx;\n+\t\t\t/* link state has changed, schedule phy info update */\n+\t\t\tif (!test_bit(__IGC_DOWN, &adapter->state))\n+\t\t\t\tmod_timer(&adapter->phy_info_timer,\n+\t\t\t\t\t round_jiffies(jiffies + 2 * HZ));\n \n-\t\t/* assign ring to adapter */\n-\t\tadapter->tx_ring[txr_idx] = ring;\n+\t\t\t/* link is down, time to check for alternate media */\n+\t\t\tif (adapter->flags & IGC_FLAG_MAS_ENABLE) {\n+\t\t\t\tif (adapter->flags & IGC_FLAG_MEDIA_RESET) {\n+\t\t\t\t\tschedule_work(&adapter->reset_task);\n+\t\t\t\t\t/* return immediately */\n+\t\t\t\t\treturn;\n+\t\t\t\t}\n+\t\t\t}\n \n-\t\t/* push pointer to next ring */\n-\t\tring++;\n+\t\t/* also check for alternate media here */\n+\t\t} else if (!netif_carrier_ok(netdev) &&\n+\t\t\t (adapter->flags & IGC_FLAG_MAS_ENABLE)) {\n+\t\t\tif (adapter->flags & IGC_FLAG_MEDIA_RESET) {\n+\t\t\t\tschedule_work(&adapter->reset_task);\n+\t\t\t\t/* return immediately */\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t}\n \t}\n \n-\tif (rxr_count) {\n-\t\t/* assign generic ring traits */\n-\t\tring->dev = &adapter->pdev->dev;\n-\t\tring->netdev = adapter->netdev;\n+\tspin_lock(&adapter->stats64_lock);\n+\tigc_update_stats(adapter);\n+\tspin_unlock(&adapter->stats64_lock);\n \n-\t\t/* configure backlink on ring */\n-\t\tring->q_vector = q_vector;\n+\tfor (i = 0; i < adapter->num_tx_queues; i++) {\n+\t\tstruct igc_ring *tx_ring = adapter->tx_ring[i];\n+\n+\t\tif (!netif_carrier_ok(netdev)) {\n+\t\t\t/* We've lost link, so the controller stops DMA,\n+\t\t\t * but we've got queued Tx work that's never going\n+\t\t\t * to get done, so reset controller to flush Tx.\n+\t\t\t * (Do the reset outside of interrupt context).\n+\t\t\t */\n+\t\t\tif (igc_desc_unused(tx_ring) + 1 < tx_ring->count) {\n+\t\t\t\tadapter->tx_timeout_count++;\n+\t\t\t\tschedule_work(&adapter->reset_task);\n+\t\t\t\t/* return immediately since reset is imminent */\n+\t\t\t\treturn;\n+\t\t\t}\n+\t\t}\n \n-\t\t/* update q_vector Rx values */\n-\t\tigc_add_ring(ring, &q_vector->rx);\n+\t\t/* Force detection of hung controller every watchdog period */\n+\t\tset_bit(IGC_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags);\n+\t}\n \n-\t\t/* apply Rx specific ring traits */\n-\t\tring->count = adapter->rx_ring_count;\n-\t\tring->queue_index = rxr_idx;\n+\t/* Cause software interrupt to ensure Rx ring is cleaned */\n+\tif (adapter->flags & IGC_FLAG_HAS_MSIX) {\n+\t\tu32 eics = 0;\n \n-\t\t/* assign ring to adapter */\n-\t\tadapter->rx_ring[rxr_idx] = ring;\n+\t\tfor (i = 0; i < adapter->num_q_vectors; i++)\n+\t\t\teics |= adapter->q_vector[i]->eims_value;\n+\t\twr32(IGC_EICS, eics);\n+\t} else {\n+\t\twr32(IGC_ICS, IGC_ICS_RXDMT0);\n \t}\n \n-\treturn 0;\n+\t/* Reset the timer */\n+\tif (!test_bit(__IGC_DOWN, &adapter->state)) {\n+\t\tif (adapter->flags & IGC_FLAG_NEED_LINK_UPDATE)\n+\t\t\tmod_timer(&adapter->watchdog_timer,\n+\t\t\t\t round_jiffies(jiffies + HZ));\n+\t\telse\n+\t\t\tmod_timer(&adapter->watchdog_timer,\n+\t\t\t\t round_jiffies(jiffies + 2 * HZ));\n+\t}\n }\n \n /**\n- * igc_alloc_q_vectors - Allocate memory for interrupt vectors\n- * @adapter: board private structure to initialize\n- *\n- * We allocate one q_vector per queue interrupt. If allocation fails we\n- * return -ENOMEM.\n+ * igc_intr_msi - Interrupt Handler\n+ * @irq: interrupt number\n+ * @data: pointer to a network interface device structure\n */\n-static int igc_alloc_q_vectors(struct igc_adapter *adapter)\n+static irqreturn_t igc_intr_msi(int irq, void *data)\n {\n-\tint rxr_remaining = adapter->num_rx_queues;\n-\tint txr_remaining = adapter->num_tx_queues;\n-\tint rxr_idx = 0, txr_idx = 0, v_idx = 0;\n-\tint q_vectors = adapter->num_q_vectors;\n-\tint err;\n+\tstruct igc_adapter *adapter = data;\n+\tstruct igc_q_vector *q_vector = adapter->q_vector[0];\n+\tstruct igc_hw *hw = &adapter->hw;\n+\t/* read ICR disables interrupts using IAM */\n+\tu32 icr = rd32(IGC_ICR);\n \n-\tif (q_vectors >= (rxr_remaining + txr_remaining)) {\n-\t\tfor (; rxr_remaining; v_idx++) {\n-\t\t\terr = igc_alloc_q_vector(adapter, q_vectors, v_idx,\n-\t\t\t\t\t\t 0, 0, 1, rxr_idx);\n+\tigc_write_itr(q_vector);\n \n-\t\t\tif (err)\n-\t\t\t\tgoto err_out;\n+\tif (icr & IGC_ICR_DRSTA)\n+\t\tschedule_work(&adapter->reset_task);\n \n-\t\t\t/* update counts and index */\n-\t\t\trxr_remaining--;\n-\t\t\trxr_idx++;\n-\t\t}\n+\tif (icr & IGC_ICR_DOUTSYNC) {\n+\t\t/* HW is reporting DMA is out of sync */\n+\t\tadapter->stats.doosync++;\n \t}\n \n-\tfor (; v_idx < q_vectors; v_idx++) {\n-\t\tint rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx);\n-\t\tint tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx);\n-\n-\t\terr = igc_alloc_q_vector(adapter, q_vectors, v_idx,\n-\t\t\t\t\t tqpv, txr_idx, rqpv, rxr_idx);\n-\n-\t\tif (err)\n-\t\t\tgoto err_out;\n-\n-\t\t/* update counts and index */\n-\t\trxr_remaining -= rqpv;\n-\t\ttxr_remaining -= tqpv;\n-\t\trxr_idx++;\n-\t\ttxr_idx++;\n+\tif (icr & (IGC_ICR_RXSEQ | IGC_ICR_LSC)) {\n+\t\thw->mac.get_link_status = 1;\n+\t\tif (!test_bit(__IGC_DOWN, &adapter->state))\n+\t\t\tmod_timer(&adapter->watchdog_timer, jiffies + 1);\n \t}\n \n-\treturn 0;\n-\n-err_out:\n-\tadapter->num_tx_queues = 0;\n-\tadapter->num_rx_queues = 0;\n-\tadapter->num_q_vectors = 0;\n-\n-\twhile (v_idx--)\n-\t\tigc_free_q_vector(adapter, v_idx);\n+\tnapi_schedule(&q_vector->napi);\n \n-\treturn -ENOMEM;\n+\treturn IRQ_HANDLED;\n }\n \n /**\n- * igc_cache_ring_register - Descriptor ring to register mapping\n- * @adapter: board private structure to initialize\n- *\n- * Once we know the feature-set enabled for the device, we'll cache\n- * the register offset the descriptor ring is assigned to.\n+ * igc_intr - Legacy Interrupt Handler\n+ * @irq: interrupt number\n+ * @data: pointer to a network interface device structure\n */\n-static void igc_cache_ring_register(struct igc_adapter *adapter)\n+static irqreturn_t igc_intr(int irq, void *data)\n {\n-\tint i = 0, j = 0;\n+\tstruct igc_adapter *adapter = data;\n+\tstruct igc_q_vector *q_vector = adapter->q_vector[0];\n+\tstruct igc_hw *hw = &adapter->hw;\n+\t/* Interrupt Auto-Mask...upon reading ICR, interrupts are masked. No\n+\t * need for the IMC write\n+\t */\n+\tu32 icr = rd32(IGC_ICR);\n \n-\tswitch (adapter->hw.mac.type) {\n-\tcase igc_i225:\n-\t/* Fall through */\n-\tdefault:\n-\t\tfor (; i < adapter->num_rx_queues; i++)\n-\t\t\tadapter->rx_ring[i]->reg_idx = i;\n-\t\tfor (; j < adapter->num_tx_queues; j++)\n-\t\t\tadapter->tx_ring[j]->reg_idx = j;\n-\t\tbreak;\n-\t}\n-}\n+\t/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is\n+\t * not set, then the adapter didn't send an interrupt\n+\t */\n+\tif (!(icr & IGC_ICR_INT_ASSERTED))\n+\t\treturn IRQ_NONE;\n \n-/**\n- * igc_init_interrupt_scheme - initialize interrupts, allocate queues/vectors\n- * @adapter: Pointer to adapter structure\n- * @msix: boolean for MSI-X capability\n- *\n- * This function initializes the interrupts and allocates all of the queues.\n- */\n-static int igc_init_interrupt_scheme(struct igc_adapter *adapter, bool msix)\n-{\n-\tstruct pci_dev *pdev = adapter->pdev;\n-\tint err = 0;\n+\tigc_write_itr(q_vector);\n \n-\tigc_set_interrupt_capability(adapter, msix);\n+\tif (icr & IGC_ICR_DRSTA)\n+\t\tschedule_work(&adapter->reset_task);\n \n-\terr = igc_alloc_q_vectors(adapter);\n-\tif (err) {\n-\t\tdev_err(&pdev->dev, \"Unable to allocate memory for vectors\\n\");\n-\t\tgoto err_alloc_q_vectors;\n+\tif (icr & IGC_ICR_DOUTSYNC) {\n+\t\t/* HW is reporting DMA is out of sync */\n+\t\tadapter->stats.doosync++;\n \t}\n \n-\tigc_cache_ring_register(adapter);\n+\tif (icr & (IGC_ICR_RXSEQ | IGC_ICR_LSC)) {\n+\t\thw->mac.get_link_status = 1;\n+\t\t/* guard against interrupt when we're going down */\n+\t\tif (!test_bit(__IGC_DOWN, &adapter->state))\n+\t\t\tmod_timer(&adapter->watchdog_timer, jiffies + 1);\n+\t}\n \n-\treturn 0;\n+\tnapi_schedule(&q_vector->napi);\n \n-err_alloc_q_vectors:\n-\tigc_reset_interrupt_capability(adapter);\n-\treturn err;\n+\treturn IRQ_HANDLED;\n }\n \n static void igc_free_irq(struct igc_adapter *adapter)\n@@ -4776,98 +4865,6 @@ static struct pci_driver igc_driver = {\n \t.shutdown = igc_shutdown,\n };\n \n-void igc_set_flag_queue_pairs(struct igc_adapter *adapter,\n-\t\t\t const u32 max_rss_queues)\n-{\n-\t/* Determine if we need to pair queues. */\n-\t/* If rss_queues > half of max_rss_queues, pair the queues in\n-\t * order to conserve interrupts due to limited supply.\n-\t */\n-\tif (adapter->rss_queues > (max_rss_queues / 2))\n-\t\tadapter->flags |= IGC_FLAG_QUEUE_PAIRS;\n-\telse\n-\t\tadapter->flags &= ~IGC_FLAG_QUEUE_PAIRS;\n-}\n-\n-unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter)\n-{\n-\tunsigned int max_rss_queues;\n-\n-\t/* Determine the maximum number of RSS queues supported. */\n-\tmax_rss_queues = IGC_MAX_RX_QUEUES;\n-\n-\treturn max_rss_queues;\n-}\n-\n-static void igc_init_queue_configuration(struct igc_adapter *adapter)\n-{\n-\tu32 max_rss_queues;\n-\n-\tmax_rss_queues = igc_get_max_rss_queues(adapter);\n-\tadapter->rss_queues = min_t(u32, max_rss_queues, num_online_cpus());\n-\n-\tigc_set_flag_queue_pairs(adapter, max_rss_queues);\n-}\n-\n-/**\n- * igc_sw_init - Initialize general software structures (struct igc_adapter)\n- * @adapter: board private structure to initialize\n- *\n- * igc_sw_init initializes the Adapter private data structure.\n- * Fields are initialized based on PCI device information and\n- * OS network device settings (MTU size).\n- */\n-static int igc_sw_init(struct igc_adapter *adapter)\n-{\n-\tstruct net_device *netdev = adapter->netdev;\n-\tstruct pci_dev *pdev = adapter->pdev;\n-\tstruct igc_hw *hw = &adapter->hw;\n-\n-\tint size = sizeof(struct igc_mac_addr) * hw->mac.rar_entry_count;\n-\n-\tpci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word);\n-\n-\t/* set default ring sizes */\n-\tadapter->tx_ring_count = IGC_DEFAULT_TXD;\n-\tadapter->rx_ring_count = IGC_DEFAULT_RXD;\n-\n-\t/* set default ITR values */\n-\tadapter->rx_itr_setting = IGC_DEFAULT_ITR;\n-\tadapter->tx_itr_setting = IGC_DEFAULT_ITR;\n-\n-\t/* set default work limits */\n-\tadapter->tx_work_limit = IGC_DEFAULT_TX_WORK;\n-\n-\t/* adjust max frame to be at least the size of a standard frame */\n-\tadapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN +\n-\t\t\t\tVLAN_HLEN;\n-\tadapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;\n-\n-\tspin_lock_init(&adapter->nfc_lock);\n-\tspin_lock_init(&adapter->stats64_lock);\n-\t/* Assume MSI-X interrupts, will be checked during IRQ allocation */\n-\tadapter->flags |= IGC_FLAG_HAS_MSIX;\n-\n-\tadapter->mac_table = kzalloc(size, GFP_ATOMIC);\n-\tif (!adapter->mac_table)\n-\t\treturn -ENOMEM;\n-\n-\tigc_init_queue_configuration(adapter);\n-\n-\t/* This call may decrease the number of queues */\n-\tif (igc_init_interrupt_scheme(adapter, true)) {\n-\t\tdev_err(&pdev->dev, \"Unable to allocate memory for queues\\n\");\n-\t\treturn -ENOMEM;\n-\t}\n-\n-\t/* Explicitly disable IRQ since the NIC can be in any state. */\n-\tigc_irq_disable(adapter);\n-\n-\tset_bit(__IGC_DOWN, &adapter->state);\n-\n-\treturn 0;\n-}\n-\n /**\n * igc_reinit_queues - return error\n * @adapter: pointer to adapter structure\n", "prefixes": [ "v1", "15/15" ] }