From patchwork Wed Aug 31 18:03:28 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Raghu Vatsavayi X-Patchwork-Id: 664645 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3sPYYG6wJ7z9sDk for ; Thu, 1 Sep 2016 04:18:42 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=CAVIUMNETWORKS.onmicrosoft.com header.i=@CAVIUMNETWORKS.onmicrosoft.com header.b=Ei1bVUmv; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932633AbcHaSSi (ORCPT ); Wed, 31 Aug 2016 14:18:38 -0400 Received: from mail-by2nam01on0057.outbound.protection.outlook.com ([104.47.34.57]:16615 "EHLO NAM01-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752578AbcHaSSg (ORCPT ); Wed, 31 Aug 2016 14:18:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=CAVIUMNETWORKS.onmicrosoft.com; s=selector1-cavium-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=F8rSZOUCj/KFPp6jMb+Hl393/q2pkPtoOfwmY3pzJTw=; b=Ei1bVUmvy+goEt/UBXsuQE4xfl2LjIf/9Ikh4KOk4fxzKI6QISPZiKuDnadaC/2Gf7vaalf34AViWOoU8swCfBbFaPyC7bxAkVnBrLJO0Z4a/oXrSSii/oGhODCsUR7/3UC8zITPbgXiASGNG7ml1um565B1Hj1MABGMpZqVU/g= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Raghu.Vatsavayi@cavium.com; Received: from localhost.caveonetworks.com (50.233.148.156) by CY1PR07MB2133.namprd07.prod.outlook.com (10.164.112.11) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.587.13; Wed, 31 Aug 2016 18:03:48 +0000 From: Raghu Vatsavayi To: CC: , Raghu Vatsavayi , Derek Chickles , Satanand Burla , Felix Manlunas , Raghu Vatsavayi Subject: [PATCH net-next V4 09/10] liquidio: MSIX support for CN23XX Date: Wed, 31 Aug 2016 11:03:28 -0700 Message-ID: <1472666609-19503-10-git-send-email-rvatsavayi@caviumnetworks.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1472666609-19503-1-git-send-email-rvatsavayi@caviumnetworks.com> References: <1472666609-19503-1-git-send-email-rvatsavayi@caviumnetworks.com> MIME-Version: 1.0 X-Originating-IP: [50.233.148.156] X-ClientProxiedBy: CO2PR11CA0004.namprd11.prod.outlook.com (10.141.242.142) To CY1PR07MB2133.namprd07.prod.outlook.com (10.164.112.11) X-MS-Office365-Filtering-Correlation-Id: 8a15c6b3-9439-4d4c-b48d-08d3d1c9287e X-Microsoft-Exchange-Diagnostics: 1; CY1PR07MB2133; 2:Pu7K+xFjPcvhjDyzsS12phkBmVG5hOg4onrZQuq736l1hiXPUd5F+mLa9Y/5tfxzapNl/hvco/g60H0q+Ms2gOYXy6dFPRrZfzhNV7vOUiBW66a2i/zEFLJ4CizY17K/E8KRZTReSYaCOLCqf4+6BlhVkusKBx9+tTD8AJpYqkmHZmDriH2oLriRwaS3YmNa; 3:JTfCOEKrTxUg69iStWq8EHVvbXFKg439mImaByNsx1u3f8r+eu05ZBoC3nD5i6ye8oZuvGN2MLmGn2CQb6rR8iRazGh68S44B23feJ7kJKWDIF+CZ/MXcN1GoxFxSsln X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:CY1PR07MB2133; X-Microsoft-Exchange-Diagnostics: 1; CY1PR07MB2133; 25:zMbFqYPjH/xKADk0lb4L5yx8U9yqzzNYpuUIYppQ++kKYr58CMG1jmjctex582k0QmK6a+VcB4V+sIFLd9lahlE9apW0MD/iGNrNNc/gDVchKeCsDpc+ycy13fOV+vijcFuv26EcxthrJDNgwV16230xR62sH3ki/B+SDcl+c98thf09U7oMUXjYoDZJvxYQVNMe7/SnFSxwiRcErpaEKFCowXuWEOnUsQuhqRtn5Hsnl6vMG/C5ZgJPg82ut73zpN1Qom9RXmZrifmISvAKKISdHO+obCvT7vufE73zsdmbm37F8F1RG5kg71C7eIbczoWK32arcVjb7bB2zzOBYR9fVAOwsQcky9AGjumPLLN+X74oQBLVshiJTg2NcAesM5Y64A2HBu84yUzeo+elupfv3PHHexJ7hvtUAJ2tPMB/Q/grXKzhLBtEaRoKjZS2V/95AoHfwoFJWDAnHFRYmEKUjlK40S6VgNUtFcneZU/NPJuRn7ecsp0kHO3yEGNr+09xtk97Vmora3f2kyQUdMnfAoCMdQj9Ev28vUAKU7gSNVXQrb5sfthw38BDYe8bXrnSao1m/kGyihfiQ2ZMUswVxPBnBdNtR+sFWGyXXHcokYXnc3Y4QuYvp7q3G8kga1BdizPi6D7UVbHfsHApgtzmzSV0JNTaS2hkLdPpxeFJejZVJpJ+h9zpdrNLLjQaPyv3BFXq++g5qGzVLGdbM1EUPKJpeoArZEoUsLQi+8LBksVMDfxrSyqZYxjFT66uW9lCNo9LddF6FITJsMIZKg== X-Microsoft-Exchange-Diagnostics: 1; CY1PR07MB2133; 31:0YPKWLz6MSpecbroFFTBfWWMzZ18N3QKkb5lhRZwWPgy0BeY3E04A5qAtvmSy7hHciVVNwDs3StdA8SrZdQxp9miusflpZJVCVFYgXEv0yQbXxlH1rAIJSSsDrse7Rib96+a8NW32Rn3xo1s4pH8A8ozwgRsSOO6KO14ROteQMcl452FCdB9jsl7yRevI4u4DmUCN9Ir6z2C16pKZWBUCjb08c9I6nTzCe5j4DCUIoc=; 20:axqiJbc3QuudP1Wm8XmzVAn33aCpV9ApMYsiNq0XTbyieoxqQPdsVac/sGeR7ETqv6coYjVBx316/ls6ZCK0l9jmGOH84EX8T4cG/ZD94MRw+Ko2Mg8TQQKRZC9R/K+tNqNR9iXcZ3JJSZKwVyu3LviVY+U7Wsokg7gDr9eLTBl60RmwX3DJvdRBu1mVpbYbNYfyrR72j3mhaWtH9lDx3cevKFI3btgNQBPQK595yIilekphoMSsuxxQ5Y8k3kkbt/dy9QaC3vz8dsDizFxNO5Z2udAbLtWMQGNKTpb8ZnaMYxIIiQQ3ijU15VOdGubCp57kqIMOS9NiJYNwkYO/Cg6aXcLUEXe6WCVZ2UQnz5EKrrK1+qYUwwQHL4zYyve2Xq3RLu0uPftWlLVX0uqbwXUTEXmroLbYITqanbwUNyrE+Z0Un8vUYLv+S3oot56Gdt4ZXZkq3Sta4FBP6/ke120TAQyct3h5Try9j2o0HCj3n86p+UJ2mqAfSEGBzNn+CgQ/zeuUi4EReFMAzkx8XRnFe9qerty7RJwrUM0lPHhLx4RJZSQxGSONi/6RSBL/HhawyzfeMUqttsiCKPc7RB5hCFgR5RZReHQ1RVEUJp4= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040176)(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001); SRVR:CY1PR07MB2133; BCL:0; PCL:0; RULEID:; SRVR:CY1PR07MB2133; X-Microsoft-Exchange-Diagnostics: 1; CY1PR07MB2133; 4:qbqEIP2QTxJj0N/DNpYDS9/e3g8DyBhVuVSiS81ndFWOXdO/XuWXpZendwsydQTpXP5q8/opDd1smAaK7XfuF96rKMriXgicVP3q9ahahLQaIaXiFfNZ48kjP0E5VbRaFTCo70u69h1iKY3eqUvY46qbiWNGPjBLlseGNE8toXvD619qcTs/VhmUS1LIi4t5sO36c0TeQibLlXVea3bpKbW/gG9OplanRi7yDNM518di6KNe021SlWKM2QvYTt5XbTG6zLFEoPJTXvWWOKjgbuvVRF872HY3/Opjo5Tl6Gxu4NLskdf8tTuc4QzJM/gEAgy/UTJWU3PjOm51d+1usoxMZtyC3u1Yg9Am+4pQ+P4Joo/yQIOZPUCgUr4HP7ThglJGaDyrD0XJXEDV6dVZHA== X-Forefront-PRVS: 00514A2FE6 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6069001)(6009001)(7916002)(199003)(189002)(19580395003)(92566002)(76506005)(97736004)(50986999)(68736007)(42186005)(31430400001)(2906002)(5003940100001)(4326007)(105586002)(76176999)(107886002)(53416004)(229853001)(189998001)(77096005)(69596002)(48376002)(50226002)(33646002)(81166006)(19580405001)(7846002)(66066001)(110136002)(101416001)(8676002)(2351001)(47776003)(586003)(2950100001)(6116002)(5660300001)(305945005)(81156014)(36756003)(106356001)(4001430100002)(7736002)(3846002)(50466002)(4720700001); DIR:OUT; SFP:1101; SCL:1; SRVR:CY1PR07MB2133; H:localhost.caveonetworks.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: cavium.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CY1PR07MB2133; 23:36UaYeDnYzA9GIrCO/fm3DwtoK7aaRgNXS7HUWLLI?= =?us-ascii?Q?9s5eniz/4i2nP4YmPKOnXemWoEGKH4UEe8lPox5ONov4xJguqOcbRZL5cPDV?= =?us-ascii?Q?DHSGvHuSNNdUFioRX56dQHTqQZ5Jbn78XckDzZDHAz4ahhlmx/9Td8BlX8dr?= =?us-ascii?Q?OweYMmbSpsW4j/v1kJLVROuwuRJpFW6fD6fy/zGfX+uQVU3MDNRAT1SUjn7r?= =?us-ascii?Q?ke+7MHQOr3QkD3SD2JRQBSJonJ8cd83Ux4fl80upKTyacW/iP/NYH94oCPyJ?= =?us-ascii?Q?tlNP1v/jAbWmHYg9vRvXALz4DxiWUSZbQcZ2LMTTK6pjnaoXwsPVOibqp4TO?= =?us-ascii?Q?Mu7ddvoLv5XEdqxlLgfl+YLpHQpYADCKtlgOaVG7KSkW5xlL/WZxR04w8IVw?= =?us-ascii?Q?GEoRmICunhhIW4YZNkfAPDtzUUNBTe6Z/TKUZIZEOtcjZBzWVwNWop0EwVkU?= =?us-ascii?Q?rwnDz/idMYUxoDDEpjk4uDrqo88fV7QfUMxpV5+8xfwpL7PI4VtuDz2tHhZ9?= =?us-ascii?Q?bjbSvUamDTvrfdB5LuE53eiELCup1WNpK1xBSMK+aSOIhvbPORFpXi3DaPnF?= =?us-ascii?Q?tt0HppdetdiF650vUUQZm/WU2NIr2dPtw2pBScdYUxa0u++NKwKigeD0C4tf?= =?us-ascii?Q?w8DOluQEBov9VDHXSzI1sIV8B/DQeEi5S+FznzCWVIa1pIq33nNxSaggjSwC?= =?us-ascii?Q?WYXDxHQMiYEKZHGb+GKDyRlW/uu5TNKdeyehCMcLRU8eRoYxQRFDPQbwuJyA?= =?us-ascii?Q?5MTV+enLxUTeyplVuXqjaDTvDG2MlgIT8yOlLE5WJR5IoWR6QpF8PQUJpwkQ?= =?us-ascii?Q?v2Yec8tXNCGsoQQ+Hqcx1qY9SV6ILTLAX29/94Eef/WETduS5PX77dOm9o7G?= =?us-ascii?Q?cTATd6br21LvfiStFHZv0t22NrSokK11ZJ0biIz6MbHzZTJlnLvG6Uys37JR?= =?us-ascii?Q?DHkExM8KOhJP/NqjM/IcY3tDRf6APIkEm0tTAwCT4tic0s8n8i9WYUv36Ha7?= =?us-ascii?Q?zbHXmEszYsNyLOITxdPV0ZzfZecOLDwXZ5cNEcHsEt8jLohNX0nY/kikfub2?= =?us-ascii?Q?hhRWDWCizuvM/q0zY/FNQAfTwUPSFEgoBnUee6rdZUQKJ6CCWXvxIIC7QM0T?= =?us-ascii?Q?uca42C6OxeEU/EpMunaD5n3f0k5n6FWwyUgQ6EYUbSJJkVFh8DoQ24cSB1Rg?= =?us-ascii?Q?WweoTmp6F/df9OtJL/pdiZh9gH83xTUFHlmWjhFdfAs2V0dbgU8jmOyJmpMR?= =?us-ascii?Q?JHPcCWbVNukfWbPb6KuExBnBii8feGOPM0MtAYr?= X-Microsoft-Exchange-Diagnostics: 1; CY1PR07MB2133; 6:1WXYA53SBXoPJBIpd7G4h3BjqhNyp5DK0boWJZ6mwnmPInSK8zwnOiVN8+acn4G4iY7APGM7Q/ULrBk43GcSjMrL+M95h3WSJXF6hW5uPGaPrH7+mkAFVJg5qOAe+yQfk4+aCr/KRnb2tDA5rUlnTYhnlwHZ3sNgR9gt1fjDB5R8qX7jdCuWVdsdhJA2VRVX/IJ+3z7O/dBQ6yUkXn7KK2zXPO4BYeR8Ekfx0rWTJB90dClb6X45w2+TXglBL65oHDQQ4TgtgrUxv7culfv29x6KqpVEfXe1uDCP0k7303M=; 5:AHWo5nuI1bYLO/IWc+SNs1gltyeNT2c7csnEAO3NsHHTJDsuODqvFTFyX6T23mgbphLegB3uy0OabA/34sgkSLliLuiHI//V/aZb0zohP1wSGnr/xldcuXBL8qswkDiWGGd5DNeFeR6gEu5g0wlLRQ==; 24:WmTT/+7o6cJxOmGW3lSR5y8ZjXY+jyKh3FxFpY7gkG3WCQwCPIL0TXX9kwHicNra0s6X/fQ9+mvzNkVx975LndeKKjVdpp8jAQ2/oPJIebM=; 7:/Li154J8yfq9AyQldF3VqCiw5c7ocby5IYNZDcLE8CwD4d/+NcoXJmjVVoBEVqN5SuKw8+e+M/kFwW7Wctpnz1m072WMNroHLJWzcNSpmeaT+/Y6sgryUQGtIBoQUA7lCVxFx4KAZiLKJ+MVWz+k2UXVhpuSTqC06SM8KRXIRHt3FLA5vqClojpVr7z5bHtSyIU14zQ4WqieHAeltI/5WFGJCtF0dOp7+aJmi+ywKBcO6TrlX5GyoNYL6xjv0zmp SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: caviumnetworks.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 31 Aug 2016 18:03:48.2892 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR07MB2133 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This patch adds support msix interrupt for cn23xx device. Signed-off-by: Derek Chickles Signed-off-by: Satanand Burla Signed-off-by: Felix Manlunas Signed-off-by: Raghu Vatsavayi --- .../ethernet/cavium/liquidio/cn23xx_pf_device.c | 166 +++++++++++-- .../net/ethernet/cavium/liquidio/cn66xx_device.c | 10 +- .../net/ethernet/cavium/liquidio/cn66xx_device.h | 4 +- drivers/net/ethernet/cavium/liquidio/lio_main.c | 269 +++++++++++++++++---- .../net/ethernet/cavium/liquidio/octeon_device.c | 39 +++ .../net/ethernet/cavium/liquidio/octeon_device.h | 33 ++- 6 files changed, 452 insertions(+), 69 deletions(-) diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c index 7e932a3..2e78101 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c @@ -567,10 +567,16 @@ static void cn23xx_setup_iq_regs(struct octeon_device *oct, u32 iq_no) */ pkt_in_done = readq(iq->inst_cnt_reg); - /* Clear the count by writing back what we read, but don't - * enable interrupts - */ - writeq(pkt_in_done, iq->inst_cnt_reg); + if (oct->msix_on) { + /* Set CINT_ENB to enable IQ interrupt */ + writeq((pkt_in_done | CN23XX_INTR_CINT_ENB), + iq->inst_cnt_reg); + } else { + /* Clear the count by writing back what we read, but don't + * enable interrupts + */ + writeq(pkt_in_done, iq->inst_cnt_reg); + } iq->reset_instr_cnt = 0; } @@ -579,6 +585,9 @@ static void cn23xx_setup_oq_regs(struct octeon_device *oct, u32 oq_no) { u32 reg_val; struct octeon_droq *droq = oct->droq[oq_no]; + struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip; + u64 time_threshold; + u64 cnt_threshold; oq_no += oct->sriov_info.pf_srn; @@ -595,19 +604,31 @@ static void cn23xx_setup_oq_regs(struct octeon_device *oct, u32 oq_no) droq->pkts_credit_reg = (u8 *)oct->mmio[0].hw_addr + CN23XX_SLI_OQ_PKTS_CREDIT(oq_no); - /* Enable this output queue to generate Packet Timer Interrupt - */ - reg_val = octeon_read_csr(oct, CN23XX_SLI_OQ_PKT_CONTROL(oq_no)); - reg_val |= CN23XX_PKT_OUTPUT_CTL_TENB; - octeon_write_csr(oct, CN23XX_SLI_OQ_PKT_CONTROL(oq_no), - reg_val); + if (!oct->msix_on) { + /* Enable this output queue to generate Packet Timer Interrupt + */ + reg_val = + octeon_read_csr(oct, CN23XX_SLI_OQ_PKT_CONTROL(oq_no)); + reg_val |= CN23XX_PKT_OUTPUT_CTL_TENB; + octeon_write_csr(oct, CN23XX_SLI_OQ_PKT_CONTROL(oq_no), + reg_val); - /* Enable this output queue to generate Packet Count Interrupt - */ - reg_val = octeon_read_csr(oct, CN23XX_SLI_OQ_PKT_CONTROL(oq_no)); - reg_val |= CN23XX_PKT_OUTPUT_CTL_CENB; - octeon_write_csr(oct, CN23XX_SLI_OQ_PKT_CONTROL(oq_no), - reg_val); + /* Enable this output queue to generate Packet Count Interrupt + */ + reg_val = + octeon_read_csr(oct, CN23XX_SLI_OQ_PKT_CONTROL(oq_no)); + reg_val |= CN23XX_PKT_OUTPUT_CTL_CENB; + octeon_write_csr(oct, CN23XX_SLI_OQ_PKT_CONTROL(oq_no), + reg_val); + } else { + time_threshold = cn23xx_pf_get_oq_ticks( + oct, (u32)CFG_GET_OQ_INTR_TIME(cn23xx->conf)); + cnt_threshold = (u32)CFG_GET_OQ_INTR_PKT(cn23xx->conf); + + octeon_write_csr64( + oct, CN23XX_SLI_OQ_PKT_INT_LEVELS(oq_no), + ((time_threshold << 32 | cnt_threshold))); + } } static int cn23xx_enable_io_queues(struct octeon_device *oct) @@ -762,6 +783,110 @@ static void cn23xx_disable_io_queues(struct octeon_device *oct) } } +static u64 cn23xx_pf_msix_interrupt_handler(void *dev) +{ + struct octeon_ioq_vector *ioq_vector = (struct octeon_ioq_vector *)dev; + struct octeon_device *oct = ioq_vector->oct_dev; + u64 pkts_sent; + u64 ret = 0; + struct octeon_droq *droq = oct->droq[ioq_vector->droq_index]; + + dev_dbg(&oct->pci_dev->dev, "In %s octeon_dev @ %p\n", __func__, oct); + + if (!droq) { + dev_err(&oct->pci_dev->dev, "23XX bringup FIXME: oct pfnum:%d ioq_vector->ioq_num :%d droq is NULL\n", + oct->pf_num, ioq_vector->ioq_num); + return 0; + } + + pkts_sent = readq(droq->pkts_sent_reg); + + /* If our device has interrupted, then proceed. Also check + * for all f's if interrupt was triggered on an error + * and the PCI read fails. + */ + if (!pkts_sent || (pkts_sent == 0xFFFFFFFFFFFFFFFFULL)) + return ret; + + /* Write count reg in sli_pkt_cnts to clear these int.*/ + if ((pkts_sent & CN23XX_INTR_PO_INT) || + (pkts_sent & CN23XX_INTR_PI_INT)) { + if (pkts_sent & CN23XX_INTR_PO_INT) + ret |= MSIX_PO_INT; + } + + if (pkts_sent & CN23XX_INTR_PI_INT) + /* We will clear the count when we update the read_index. */ + ret |= MSIX_PI_INT; + + /* Never need to handle msix mbox intr for pf. They arrive on the last + * msix + */ + return ret; +} + +static irqreturn_t cn23xx_interrupt_handler(void *dev) +{ + struct octeon_device *oct = (struct octeon_device *)dev; + struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip; + u64 intr64; + + dev_dbg(&oct->pci_dev->dev, "In %s octeon_dev @ %p\n", __func__, oct); + intr64 = readq(cn23xx->intr_sum_reg64); + + oct->int_status = 0; + + if (intr64 & CN23XX_INTR_ERR) + dev_err(&oct->pci_dev->dev, "OCTEON[%d]: Error Intr: 0x%016llx\n", + oct->octeon_id, CVM_CAST64(intr64)); + + if (oct->msix_on != LIO_FLAG_MSIX_ENABLED) { + if (intr64 & CN23XX_INTR_PKT_DATA) + oct->int_status |= OCT_DEV_INTR_PKT_DATA; + } + + if (intr64 & (CN23XX_INTR_DMA0_FORCE)) + oct->int_status |= OCT_DEV_INTR_DMA0_FORCE; + if (intr64 & (CN23XX_INTR_DMA1_FORCE)) + oct->int_status |= OCT_DEV_INTR_DMA1_FORCE; + + /* Clear the current interrupts */ + writeq(intr64, cn23xx->intr_sum_reg64); + + return IRQ_HANDLED; +} + +static void cn23xx_enable_pf_interrupt(struct octeon_device *oct, u8 intr_flag) +{ + struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip; + u64 intr_val = 0; + + /* Divide the single write to multiple writes based on the flag. */ + /* Enable Interrupt */ + if (intr_flag == OCTEON_ALL_INTR) { + writeq(cn23xx->intr_mask64, cn23xx->intr_enb_reg64); + } else if (intr_flag & OCTEON_OUTPUT_INTR) { + intr_val = readq(cn23xx->intr_enb_reg64); + intr_val |= CN23XX_INTR_PKT_DATA; + writeq(intr_val, cn23xx->intr_enb_reg64); + } +} + +static void cn23xx_disable_pf_interrupt(struct octeon_device *oct, u8 intr_flag) +{ + struct octeon_cn23xx_pf *cn23xx = (struct octeon_cn23xx_pf *)oct->chip; + u64 intr_val = 0; + + /* Disable Interrupts */ + if (intr_flag == OCTEON_ALL_INTR) { + writeq(0, cn23xx->intr_enb_reg64); + } else if (intr_flag & OCTEON_OUTPUT_INTR) { + intr_val = readq(cn23xx->intr_enb_reg64); + intr_val &= ~CN23XX_INTR_PKT_DATA; + writeq(intr_val, cn23xx->intr_enb_reg64); + } +} + static void cn23xx_get_pcie_qlmport(struct octeon_device *oct) { oct->pcie_port = (octeon_read_csr(oct, CN23XX_SLI_MAC_NUMBER)) & 0xff; @@ -816,7 +941,8 @@ static void cn23xx_setup_reg_address(struct octeon_device *oct) cn23xx_get_pcie_qlmport(oct); cn23xx->intr_mask64 = CN23XX_INTR_MASK; - cn23xx->intr_mask64 |= CN23XX_INTR_PKT_TIME; + if (!oct->msix_on) + cn23xx->intr_mask64 |= CN23XX_INTR_PKT_TIME; if (oct->rev_id >= OCTEON_CN23XX_REV_1_1) cn23xx->intr_mask64 |= CN23XX_INTR_VF_MBOX; @@ -901,8 +1027,14 @@ int setup_cn23xx_octeon_pf_device(struct octeon_device *oct) oct->fn_list.setup_iq_regs = cn23xx_setup_iq_regs; oct->fn_list.setup_oq_regs = cn23xx_setup_oq_regs; + oct->fn_list.process_interrupt_regs = cn23xx_interrupt_handler; + oct->fn_list.msix_interrupt_handler = cn23xx_pf_msix_interrupt_handler; + oct->fn_list.setup_device_regs = cn23xx_setup_pf_device_regs; + oct->fn_list.enable_interrupt = cn23xx_enable_pf_interrupt; + oct->fn_list.disable_interrupt = cn23xx_disable_pf_interrupt; + oct->fn_list.enable_io_queues = cn23xx_enable_io_queues; oct->fn_list.disable_io_queues = cn23xx_disable_io_queues; diff --git a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c index 7ff7247..e779af8 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c @@ -479,18 +479,20 @@ lio_cn6xxx_update_read_index(struct octeon_instr_queue *iq) return new_idx; } -void lio_cn6xxx_enable_interrupt(void *chip) +void lio_cn6xxx_enable_interrupt(struct octeon_device *oct, + u8 unused __attribute__((unused))) { - struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)chip; + struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip; u64 mask = cn6xxx->intr_mask64 | CN6XXX_INTR_DMA0_FORCE; /* Enable Interrupt */ writeq(mask, cn6xxx->intr_enb_reg64); } -void lio_cn6xxx_disable_interrupt(void *chip) +void lio_cn6xxx_disable_interrupt(struct octeon_device *oct, + u8 unused __attribute__((unused))) { - struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)chip; + struct octeon_cn6xxx *cn6xxx = (struct octeon_cn6xxx *)oct->chip; /* Disable Interrupts */ writeq(0, cn6xxx->intr_enb_reg64); diff --git a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.h b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.h index 5286f9e..a40a913 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.h +++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.h @@ -89,8 +89,8 @@ void lio_cn6xxx_bar1_idx_write(struct octeon_device *oct, u32 idx, u32 mask); u32 lio_cn6xxx_bar1_idx_read(struct octeon_device *oct, u32 idx); u32 lio_cn6xxx_update_read_index(struct octeon_instr_queue *iq); -void lio_cn6xxx_enable_interrupt(void *chip); -void lio_cn6xxx_disable_interrupt(void *chip); +void lio_cn6xxx_enable_interrupt(struct octeon_device *oct, u8 unused); +void lio_cn6xxx_disable_interrupt(struct octeon_device *oct, u8 unused); void cn6xxx_get_pcie_qlmport(struct octeon_device *oct); void lio_cn6xxx_setup_reg_address(struct octeon_device *oct, void *chip, struct octeon_reg_list *reg_list); diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index cb58381..464d42b 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -195,6 +195,19 @@ static void octeon_droq_bh(unsigned long pdev) reschedule |= octeon_droq_process_packets(oct, oct->droq[q_no], MAX_PACKET_BUDGET); lio_enable_irq(oct->droq[q_no], NULL); + + if (OCTEON_CN23XX_PF(oct) && oct->msix_on) { + /* set time and cnt interrupt thresholds for this DROQ + * for NAPI + */ + int adjusted_q_no = q_no + oct->sriov_info.pf_srn; + + octeon_write_csr64( + oct, CN23XX_SLI_OQ_PKT_INT_LEVELS(adjusted_q_no), + 0x5700000040ULL); + octeon_write_csr64( + oct, CN23XX_SLI_OQ_PKTS_SENT(adjusted_q_no), 0); + } } if (reschedule) @@ -347,7 +360,7 @@ static void stop_pci_io(struct octeon_device *oct) pci_disable_device(oct->pci_dev); /* Disable interrupts */ - oct->fn_list.disable_interrupt(oct->chip); + oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR); pcierror_quiesce_device(oct); @@ -910,6 +923,27 @@ static void update_txq_status(struct octeon_device *oct, int iq_num) } } +static +int liquidio_schedule_msix_droq_pkt_handler(struct octeon_droq *droq, u64 ret) +{ + struct octeon_device *oct = droq->oct_dev; + struct octeon_device_priv *oct_priv = + (struct octeon_device_priv *)oct->priv; + + if (droq->ops.poll_mode) { + droq->ops.napi_fn(droq); + } else { + if (ret & MSIX_PO_INT) { + tasklet_schedule(&oct_priv->droq_tasklet); + return 1; + } + /* this will be flushed periodically by check iq db */ + if (ret & MSIX_PI_INT) + return 0; + } + return 0; +} + /** * \brief Droq packet processor sceduler * @param oct octeon device @@ -940,19 +974,36 @@ void liquidio_schedule_droq_pkt_handlers(struct octeon_device *oct) } } +static irqreturn_t +liquidio_msix_intr_handler(int irq __attribute__((unused)), void *dev) +{ + u64 ret; + struct octeon_ioq_vector *ioq_vector = (struct octeon_ioq_vector *)dev; + struct octeon_device *oct = ioq_vector->oct_dev; + struct octeon_droq *droq = oct->droq[ioq_vector->droq_index]; + + ret = oct->fn_list.msix_interrupt_handler(ioq_vector); + + if ((ret & MSIX_PO_INT) || (ret & MSIX_PI_INT)) + liquidio_schedule_msix_droq_pkt_handler(droq, ret); + + return IRQ_HANDLED; +} + /** * \brief Interrupt handler for octeon * @param irq unused * @param dev octeon device */ static -irqreturn_t liquidio_intr_handler(int irq __attribute__((unused)), void *dev) +irqreturn_t liquidio_legacy_intr_handler(int irq __attribute__((unused)), + void *dev) { struct octeon_device *oct = (struct octeon_device *)dev; irqreturn_t ret; /* Disable our interrupts for the duration of ISR */ - oct->fn_list.disable_interrupt(oct->chip); + oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR); ret = oct->fn_list.process_interrupt_regs(oct); @@ -961,7 +1012,7 @@ irqreturn_t liquidio_intr_handler(int irq __attribute__((unused)), void *dev) /* Re-enable our interrupts */ if (!(atomic_read(&oct->status) == OCT_DEV_IN_RESET)) - oct->fn_list.enable_interrupt(oct->chip); + oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR); return ret; } @@ -975,24 +1026,110 @@ irqreturn_t liquidio_intr_handler(int irq __attribute__((unused)), void *dev) static int octeon_setup_interrupt(struct octeon_device *oct) { int irqret, err; + struct msix_entry *msix_entries; + int i; + int num_ioq_vectors; + int num_alloc_ioq_vectors; - err = pci_enable_msi(oct->pci_dev); - if (err) - dev_warn(&oct->pci_dev->dev, "Reverting to legacy interrupts. Error: %d\n", - err); - else - oct->flags |= LIO_FLAG_MSI_ENABLED; - - irqret = request_irq(oct->pci_dev->irq, liquidio_intr_handler, - IRQF_SHARED, "octeon", oct); - if (irqret) { - if (oct->flags & LIO_FLAG_MSI_ENABLED) - pci_disable_msi(oct->pci_dev); - dev_err(&oct->pci_dev->dev, "Request IRQ failed with code: %d\n", - irqret); - return 1; - } + if (OCTEON_CN23XX_PF(oct) && oct->msix_on) { + oct->num_msix_irqs = oct->sriov_info.num_pf_rings; + /* one non ioq interrupt for handling sli_mac_pf_int_sum */ + oct->num_msix_irqs += 1; + oct->msix_entries = kcalloc( + oct->num_msix_irqs, sizeof(struct msix_entry), GFP_KERNEL); + if (!oct->msix_entries) + return 1; + + msix_entries = (struct msix_entry *)oct->msix_entries; + /*Assumption is that pf msix vectors start from pf srn to pf to + * trs and not from 0. if not change this code + */ + for (i = 0; i < oct->num_msix_irqs - 1; i++) + msix_entries[i].entry = oct->sriov_info.pf_srn + i; + msix_entries[oct->num_msix_irqs - 1].entry = + oct->sriov_info.trs; + num_alloc_ioq_vectors = pci_enable_msix_range( + oct->pci_dev, msix_entries, + oct->num_msix_irqs, + oct->num_msix_irqs); + if (num_alloc_ioq_vectors < 0) { + dev_err(&oct->pci_dev->dev, "unable to Allocate MSI-X interrupts\n"); + kfree(oct->msix_entries); + oct->msix_entries = NULL; + return 1; + } + dev_dbg(&oct->pci_dev->dev, "OCTEON: Enough MSI-X interrupts are allocated...\n"); + + num_ioq_vectors = oct->num_msix_irqs; + + /** For PF, there is one non-ioq interrupt handler */ + num_ioq_vectors -= 1; + irqret = request_irq(msix_entries[num_ioq_vectors].vector, + liquidio_legacy_intr_handler, 0, "octeon", + oct); + if (irqret) { + dev_err(&oct->pci_dev->dev, + "OCTEON: Request_irq failed for MSIX interrupt Error: %d\n", + irqret); + pci_disable_msix(oct->pci_dev); + kfree(oct->msix_entries); + oct->msix_entries = NULL; + return 1; + } + + for (i = 0; i < num_ioq_vectors; i++) { + irqret = request_irq(msix_entries[i].vector, + liquidio_msix_intr_handler, 0, + "octeon", &oct->ioq_vector[i]); + if (irqret) { + dev_err(&oct->pci_dev->dev, + "OCTEON: Request_irq failed for MSIX interrupt Error: %d\n", + irqret); + /** Freeing the non-ioq irq vector here . */ + free_irq(msix_entries[num_ioq_vectors].vector, + oct); + + while (i) { + i--; + /** clearing affinity mask. */ + irq_set_affinity_hint( + msix_entries[i].vector, NULL); + free_irq(msix_entries[i].vector, + &oct->ioq_vector[i]); + } + pci_disable_msix(oct->pci_dev); + kfree(oct->msix_entries); + oct->msix_entries = NULL; + return 1; + } + oct->ioq_vector[i].vector = msix_entries[i].vector; + /* assign the cpu mask for this msix interrupt vector */ + irq_set_affinity_hint( + msix_entries[i].vector, + (&oct->ioq_vector[i].affinity_mask)); + } + dev_dbg(&oct->pci_dev->dev, "OCTEON[%d]: MSI-X enabled\n", + oct->octeon_id); + } else { + err = pci_enable_msi(oct->pci_dev); + if (err) + dev_warn(&oct->pci_dev->dev, "Reverting to legacy interrupts. Error: %d\n", + err); + else + oct->flags |= LIO_FLAG_MSI_ENABLED; + + irqret = request_irq(oct->pci_dev->irq, + liquidio_legacy_intr_handler, IRQF_SHARED, + "octeon", oct); + if (irqret) { + if (oct->flags & LIO_FLAG_MSI_ENABLED) + pci_disable_msi(oct->pci_dev); + dev_err(&oct->pci_dev->dev, "Request IRQ failed with code: %d\n", + irqret); + return 1; + } + } return 0; } @@ -1015,6 +1152,9 @@ liquidio_probe(struct pci_dev *pdev, return -ENOMEM; } + if (pdev->device == OCTEON_CN23XX_PF_VID) + oct_dev->msix_on = LIO_FLAG_MSIX_ENABLED; + dev_info(&pdev->dev, "Initializing device %x:%x.\n", (u32)pdev->vendor, (u32)pdev->device); @@ -1054,6 +1194,7 @@ liquidio_probe(struct pci_dev *pdev, static void octeon_destroy_resources(struct octeon_device *oct) { int i; + struct msix_entry *msix_entries; struct octeon_device_priv *oct_priv = (struct octeon_device_priv *)oct->priv; @@ -1098,21 +1239,40 @@ static void octeon_destroy_resources(struct octeon_device *oct) dev_err(&oct->pci_dev->dev, "OQ had pending packets\n"); /* Disable interrupts */ - oct->fn_list.disable_interrupt(oct->chip); + oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR); + + if (oct->msix_on) { + msix_entries = (struct msix_entry *)oct->msix_entries; + for (i = 0; i < oct->num_msix_irqs - 1; i++) { + /* clear the affinity_cpumask */ + irq_set_affinity_hint(msix_entries[i].vector, + NULL); + free_irq(msix_entries[i].vector, + &oct->ioq_vector[i]); + } + /* non-iov vector's argument is oct struct */ + free_irq(msix_entries[i].vector, oct); - /* Release the interrupt line */ - free_irq(oct->pci_dev->irq, oct); + pci_disable_msix(oct->pci_dev); + kfree(oct->msix_entries); + oct->msix_entries = NULL; + } else { + /* Release the interrupt line */ + free_irq(oct->pci_dev->irq, oct); - if (oct->flags & LIO_FLAG_MSI_ENABLED) - pci_disable_msi(oct->pci_dev); + if (oct->flags & LIO_FLAG_MSI_ENABLED) + pci_disable_msi(oct->pci_dev); + } - /* fallthrough */ + if (OCTEON_CN23XX_PF(oct)) + octeon_free_ioq_vector(oct); + /* fallthrough */ case OCT_DEV_IN_RESET: case OCT_DEV_DROQ_INIT_DONE: /*atomic_set(&oct->status, OCT_DEV_DROQ_INIT_DONE);*/ mdelay(100); for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) { - if (!(oct->io_qmask.oq & (1ULL << i))) + if (!(oct->io_qmask.oq & BIT_ULL(i))) continue; octeon_delete_droq(oct, i); } @@ -2147,7 +2307,7 @@ static void octnet_poll_check_txq_status(struct work_struct *work) * \brief Sets up the txq poll check * @param netdev network device */ -static inline void setup_tx_poll_fn(struct net_device *netdev) +static inline int setup_tx_poll_fn(struct net_device *netdev) { struct lio *lio = GET_LIO(netdev); struct octeon_device *oct = lio->oct_dev; @@ -2156,21 +2316,24 @@ static inline void setup_tx_poll_fn(struct net_device *netdev) WQ_MEM_RECLAIM, 0); if (!lio->txq_status_wq.wq) { dev_err(&oct->pci_dev->dev, "unable to create cavium txq status wq\n"); - return; + return -1; } INIT_DELAYED_WORK(&lio->txq_status_wq.wk.work, octnet_poll_check_txq_status); lio->txq_status_wq.wk.ctxptr = lio; queue_delayed_work(lio->txq_status_wq.wq, &lio->txq_status_wq.wk.work, msecs_to_jiffies(1)); + return 0; } static inline void cleanup_tx_poll_fn(struct net_device *netdev) { struct lio *lio = GET_LIO(netdev); - cancel_delayed_work_sync(&lio->txq_status_wq.wk.work); - destroy_workqueue(lio->txq_status_wq.wq); + if (lio->txq_status_wq.wq) { + cancel_delayed_work_sync(&lio->txq_status_wq.wk.work); + destroy_workqueue(lio->txq_status_wq.wq); + } } /** @@ -2194,7 +2357,14 @@ static int liquidio_open(struct net_device *netdev) ifstate_set(lio, LIO_IFSTATE_RUNNING); - setup_tx_poll_fn(netdev); + if (OCTEON_CN23XX_PF(oct)) { + if (!oct->msix_on) + if (setup_tx_poll_fn(netdev)) + return -1; + } else { + if (setup_tx_poll_fn(netdev)) + return -1; + } start_txq(netdev); @@ -2240,7 +2410,12 @@ static int liquidio_stop(struct net_device *netdev) /* Now it should be safe to tell Octeon that nic interface is down. */ send_rx_ctrl_cmd(lio, 0); - cleanup_tx_poll_fn(netdev); + if (OCTEON_CN23XX_PF(oct)) { + if (!oct->msix_on) + cleanup_tx_poll_fn(netdev); + } else { + cleanup_tx_poll_fn(netdev); + } if (lio->ptp_clock) { ptp_clock_unregister(lio->ptp_clock); @@ -3739,15 +3914,23 @@ static int octeon_device_init(struct octeon_device *octeon_dev) atomic_set(&octeon_dev->status, OCT_DEV_DROQ_INIT_DONE); - /* The input and output queue registers were setup earlier (the queues - * were not enabled). Any additional registers that need to be - * programmed should be done now. - */ - ret = octeon_dev->fn_list.setup_device_regs(octeon_dev); - if (ret) { - dev_err(&octeon_dev->pci_dev->dev, - "Failed to configure device registers\n"); - return ret; + if (OCTEON_CN23XX_PF(octeon_dev)) { + if (octeon_allocate_ioq_vector(octeon_dev)) { + dev_err(&octeon_dev->pci_dev->dev, "OCTEON: ioq vector allocation failed\n"); + return 1; + } + + } else { + /* The input and output queue registers were setup earlier (the + * queues were not enabled). Any additional registers + * that need to be programmed should be done now. + */ + ret = octeon_dev->fn_list.setup_device_regs(octeon_dev); + if (ret) { + dev_err(&octeon_dev->pci_dev->dev, + "Failed to configure device registers\n"); + return ret; + } } /* Initialize the tasklet that handles output queue packet processing.*/ @@ -3761,7 +3944,7 @@ static int octeon_device_init(struct octeon_device *octeon_dev) return 1; /* Enable Octeon device interrupts */ - octeon_dev->fn_list.enable_interrupt(octeon_dev->chip); + octeon_dev->fn_list.enable_interrupt(octeon_dev, OCTEON_ALL_INTR); /* Enable the input and output queues for this Octeon device */ ret = octeon_dev->fn_list.enable_io_queues(octeon_dev); diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.c b/drivers/net/ethernet/cavium/liquidio/octeon_device.c index 120b78e..5252763 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_device.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.c @@ -746,6 +746,45 @@ struct octeon_device *octeon_allocate_device(u32 pci_id, return oct; } +int +octeon_allocate_ioq_vector(struct octeon_device *oct) +{ + int i, num_ioqs = 0; + struct octeon_ioq_vector *ioq_vector; + int cpu_num; + int size; + + if (OCTEON_CN23XX_PF(oct)) + num_ioqs = oct->sriov_info.num_pf_rings; + size = sizeof(struct octeon_ioq_vector) * num_ioqs; + + oct->ioq_vector = vmalloc(size); + if (!oct->ioq_vector) + return 1; + memset(oct->ioq_vector, 0, size); + for (i = 0; i < num_ioqs; i++) { + ioq_vector = &oct->ioq_vector[i]; + ioq_vector->oct_dev = oct; + ioq_vector->iq_index = i; + ioq_vector->droq_index = i; + + cpu_num = i % num_online_cpus(); + cpumask_set_cpu(cpu_num, &ioq_vector->affinity_mask); + + if (oct->chip_id == OCTEON_CN23XX_PF_VID) + ioq_vector->ioq_num = i + oct->sriov_info.pf_srn; + else + ioq_vector->ioq_num = i; + } + return 0; +} + +void +octeon_free_ioq_vector(struct octeon_device *oct) +{ + vfree(oct->ioq_vector); +} + /* this function is only for setting up the first queue */ int octeon_setup_instr_queues(struct octeon_device *oct) { diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.h b/drivers/net/ethernet/cavium/liquidio/octeon_device.h index 2439cc5..99fc1d8 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_device.h +++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.h @@ -52,6 +52,9 @@ enum octeon_pci_swap_mode { OCTEON_PCI_32BIT_LW_SWAP = 3 }; +#define OCTEON_OUTPUT_INTR (2) +#define OCTEON_ALL_INTR 0xff + /*--------------- PCI BAR1 index registers -------------*/ /* BAR1 Mask */ @@ -204,6 +207,7 @@ struct octeon_fn_list { void (*setup_oq_regs)(struct octeon_device *, u32); irqreturn_t (*process_interrupt_regs)(void *); + u64 (*msix_interrupt_handler)(void *); int (*soft_reset)(struct octeon_device *); int (*setup_device_regs)(struct octeon_device *); void (*bar1_idx_setup)(struct octeon_device *, u64, u32, int); @@ -214,8 +218,8 @@ struct octeon_fn_list { void (*enable_oq_pkt_time_intr)(struct octeon_device *, u32); void (*disable_oq_pkt_time_intr)(struct octeon_device *, u32); - void (*enable_interrupt)(void *); - void (*disable_interrupt)(void *); + void (*enable_interrupt)(struct octeon_device *, u8); + void (*disable_interrupt)(struct octeon_device *, u8); int (*enable_io_queues)(struct octeon_device *); void (*disable_io_queues)(struct octeon_device *); @@ -276,6 +280,10 @@ struct octdev_props { struct net_device *netdev; }; +#define LIO_FLAG_MSIX_ENABLED 0x1 +#define MSIX_PO_INT 0x1 +#define MSIX_PI_INT 0x2 + struct octeon_pf_vf_hs_word { #ifdef __LITTLE_ENDIAN_BITFIELD /** PKIND value assigned for the DPI interface */ @@ -323,6 +331,15 @@ struct octeon_sriov_info { }; +struct octeon_ioq_vector { + struct octeon_device *oct_dev; + int iq_index; + int droq_index; + int vector; + struct cpumask affinity_mask; + u32 ioq_num; +}; + /** The Octeon device. * Each Octeon device has this structure to represent all its * components. @@ -357,7 +374,6 @@ struct octeon_device { u16 flags; #define LIO_FLAG_MSI_ENABLED (u32)(1 << 1) -#define LIO_FLAG_MSIX_ENABLED (u32)(1 << 2) /** The state of this device */ atomic_t status; @@ -447,10 +463,19 @@ struct octeon_device { void *priv; + int num_msix_irqs; + + void *msix_entries; + struct octeon_sriov_info sriov_info; struct octeon_pf_vf_hs_word pfvf_hsword; + int msix_on; + + /** IOq information of it's corresponding MSI-X interrupt. */ + struct octeon_ioq_vector *ioq_vector; + int rx_pause; int tx_pause; @@ -718,6 +743,8 @@ void *oct_get_config_info(struct octeon_device *oct, u16 card_type); */ struct octeon_config *octeon_get_conf(struct octeon_device *oct); +void octeon_free_ioq_vector(struct octeon_device *oct); +int octeon_allocate_ioq_vector(struct octeon_device *oct); void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq); /* LiquidIO driver pivate flags */