From patchwork Tue Nov 29 00:54:40 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Raghu Vatsavayi X-Patchwork-Id: 700259 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 3tSQ8j1ZxBz9vDw for ; Tue, 29 Nov 2016 11:56:05 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=CAVIUMNETWORKS.onmicrosoft.com header.i=@CAVIUMNETWORKS.onmicrosoft.com header.b="dtjsY7ws"; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755488AbcK2Az4 (ORCPT ); Mon, 28 Nov 2016 19:55:56 -0500 Received: from mail-cys01nam02on0088.outbound.protection.outlook.com ([104.47.37.88]:23744 "EHLO NAM02-CY1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1755348AbcK2Azc (ORCPT ); Mon, 28 Nov 2016 19:55:32 -0500 X-Greylist: delayed 56918 seconds by postgrey-1.27 at vger.kernel.org; Mon, 28 Nov 2016 19:55:05 EST 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=kyiSaLdl333KgbOIr2CUw9HbLtMSLGpce9cqLvDh/z0=; b=dtjsY7wsfpNyVc7q3ZdNDAENk3qDD3XPGx1qhPimU1YQxQUMfAM7r3xtf1IH03IvB3eKe0NaclLA0gXJtrskb2dLj+EaC4Lp5yuML3eDDKsuCvnuIM5+cqiwDYa/y2POwGdsrSTtZCqOWOeWH5vuWLzZaP3yxjd5/5CZtq6ai5w= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Raghu.Vatsavayi@cavium.com; Received: from localhost.caveonetworks.com (50.233.148.156) by DM3PR07MB2139.namprd07.prod.outlook.com (10.164.4.145) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.747.13; Tue, 29 Nov 2016 00:55:10 +0000 From: Raghu Vatsavayi To: CC: , Raghu Vatsavayi , Raghu Vatsavayi , Derek Chickles , Satanand Burla , Felix Manlunas Subject: [PATCH net-next V3 8/9] liquidio CN23XX: VF interrupt Date: Mon, 28 Nov 2016 16:54:40 -0800 Message-ID: <1480380881-19255-9-git-send-email-rvatsavayi@caviumnetworks.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1480380881-19255-1-git-send-email-rvatsavayi@caviumnetworks.com> References: <1480380881-19255-1-git-send-email-rvatsavayi@caviumnetworks.com> MIME-Version: 1.0 X-Originating-IP: [50.233.148.156] X-ClientProxiedBy: DM2PR0501CA0034.namprd05.prod.outlook.com (10.162.29.172) To DM3PR07MB2139.namprd07.prod.outlook.com (10.164.4.145) X-MS-Office365-Filtering-Correlation-Id: a0b5ace1-0d8a-4f39-bd82-08d417f25ee1 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001); SRVR:DM3PR07MB2139; X-Microsoft-Exchange-Diagnostics: 1; DM3PR07MB2139; 3:uML9ymnxrQV4ohMISE5j5uI/uVU9LclVEPFgv/QKSlVx0rWSsDUYwmZ5TdKNVjGzpjeJCTM+0BWLOMrfiFKDdotnXYKqMJKq/DWbv3g+WBJLfSGHpqiCNd+yCOWdn7bTtWHPpejXwAw79DSe8fglDko0TVYSD9dAklM65r1mgpNNrBwQ8Fa0H6yZ6Q5hjh7DnKGZ5PqA26V/2AuImiecx2Y+V7d3Kfv6Pzq8t46JloeItc+DInzb/C4RxQg/8ElycpeIJjXUipSsQiUCweCLQw==; 25:QbKNphhL9f/Tq9bUudjxwYAyxzbycHEBx0+/PWFerVn3Io0BN3RfpkNbm2CmI9d671XjYvWfr8845io83sZ09rFF1FJd78uIQ85QO+5jafOEiVZ8UaB7klkXUw75B4ga7bBQMBeaWLno1TyjAM7Q3iPAUh9eT6Fm70LkPW/Dx/NepZFkhcAPgFj47iFq3swyXD/4fvBgKBgyXvAE1Iavl2Ta2RqWJM+T2UP6HEmf5BU7h1Lc+Fbej/mngIGiJqILmooeHMVHBEkHuJ8O76MaSyJpKCssz/DUDWCKSBrbgfVgWcQr291NRrn9bN9t5RvuKR4q3V+ZNf+Kqt8ofYUfsH6ZPxMWM4Yf+UpJ06SLSHEZY2xk2K6K3PK+tavfXYvc7DaidH01UC8nzVNIUOvhxlp2dWLcyfwyO6TPVz9zdur/2O2OIYTEyjrNkGuSk7AbW/a9mfVc/2Ed0N+ajS8z0Q== X-Microsoft-Exchange-Diagnostics: 1; DM3PR07MB2139; 31:OXVghPSxngmBG/xqsQyDOIKwO37ThZofGS48QrmAP+5x092cGjJgawl86xqWMVUUqD+2tbqrOt2uuyHHwkbEqNzHYMIv1yYxpybIkv03P3p59SP2nQ62CwEYjDJbRBuHC5V0L5a2/OtEJJ5pocxZc1V9h/hIRozF9xgY+8HFgD7zr45k9SKoh4jMxoxI7RAI/98wL9jOMFmwcTLakrE5qsE02mvg+Dm6LsB9hQvkofvAeOnGlSb2WIALutB85fckMi5WVES+sMw5I3IE7r0FXozs2j/T3VrBvFACAbK3oXYWWO/vrJAijVcnYH3Fhw+a; 20:Kvx2fdv6r3duap0/nGKqn/TteDhha1yegoPiH/kQilGzT79wosdaXS4TMODIr7H7Xl98V53s++9oTHKFSm6p6c1Y3n8P85DglbEnrpizVZQ7wGuNVoZUktAUCFkOYj0Zpvixf1nk69PR8tZtOiUCxGd9/lXqUMVg2Wi4fi30AkFf6S/7jXR39FrgylxP0RV77/tD//sOn0aHc0k4ggb4Ldgv2jm+JROBu4UuWm/8qv4HXocIs9KTd49y5uW86EatKMjTkp/f+inUwZ+sHk8skPEtQcuHEDe/L9YtmoFPj08WAEPh1nSGiSk/QGNVLJEbGEWPtGO3e4GbqVSFiM49vdZXm4GIy6hxEHiAvjpUI6m7j4jQdOyo5mID+hU7JtV8Jm2Ci+BRS4jmfHc60mnjmS8vNasK8sIl8wdqeZs4GKSEOPMNcey2kWMtTpnOM3zfHeRbNqFMfDIFEpbxf9R4QpO9V9CvmvME80wW1HfwQJ8EAbMYUoRBONAFn/BCOff0NCakmrfREiW7SQdG6QRlnTv7IP0TrCgunt5gxQ3XgicYLt3L9NBYn2h7rNy/8L7olx8myEuOuC+FhqQwZENB+JI8CmsiE+8Mc+O6svOp9aU= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(211171220733660); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6060326)(6040361)(6045199)(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001)(6061324)(6041248)(20161123558021)(20161123555025)(20161123560025)(20161123564025)(20161123562025); SRVR:DM3PR07MB2139; BCL:0; PCL:0; RULEID:; SRVR:DM3PR07MB2139; X-Microsoft-Exchange-Diagnostics: 1; DM3PR07MB2139; 4:Lr88SBmWC0XT0r/WJZN1kaGp/Ra7w/8Z9zC07GIB3I2VOFOxG3mfBDX7zNkCuiehARyI8Zc1h9tev3SYSFuvlyRcimvee4dKX1Wc+v8l5o0vMhPW2MrOsmVuiiYwd2GZKrOcL56dgw8jLeIe8Kn8sn4/CucZ3FxxchGNacazAdhmnx59fhsGXWRHveOeYAJtmXUVKCOCDl5Nux3nMaIhrbYNrGckV/3qYzI07UhY0zoyJqCh2fUBQOoC7YI6BR+fLsX9a5rR5k0pUFMEiuwiCdbu8Bwv/ARmi0+65NzpxMxSSmnLg3+1+2J2C7kXA03zUG+jAcwc65pPrWguQndyvXmFDTHNZXrR/zBRFEt3HXCtPJKx+1TGLxcXDlrb6WPAY8szV6FvUw/Grw0diEpwLcoBrxyQ1fJNkR8w3GCOSDU7eR2LecIhD+dhXk3MEvWUmef2i2e3KJqnvsB9Gv3R2ZW4olI9SjJZBMKaPhYhf6zK9IxNdBRXFz1GPzxOtDOiCEfg2e4MbiLY0FDVcMiwDbYaEWZo+08kY4cvWs/WBJTDp6rovYQFKg0dkuZxQGlqyOcZbHCtu4F6rW+l3IlAtmhxk9GZvXRG/2CdruYOKs1PrIP5R2Jafpqq839eLU7LI/mH3lVXn4Ff659pULw5A/ISvtqEd2bdWFaKk3mKc4FDmc9x/i7xr5RxAoFEnPdO X-Forefront-PRVS: 01415BB535 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(6009001)(6069001)(7916002)(189002)(199003)(76176999)(50986999)(36756003)(107886002)(4326007)(5003940100001)(2950100002)(6916009)(81166006)(42882006)(47776003)(5660300001)(33646002)(4720700003)(92566002)(110136003)(81156014)(7736002)(305945005)(7846002)(6666003)(8676002)(69596002)(39400400001)(2351001)(105586002)(97736004)(106356001)(4001430100002)(38730400001)(733004)(6486002)(53416004)(76506005)(101416001)(39410400001)(50226002)(42186005)(39380400001)(3846002)(2906002)(50466002)(6116002)(48376002)(68736007)(39450400002)(66066001)(189998001); DIR:OUT; SFP:1101; SCL:1; SRVR:DM3PR07MB2139; H:localhost.caveonetworks.com; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A: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; DM3PR07MB2139; 23:RmhN3fQ4ERx2TAyFJRkipDTcEGj0/XcnQo7JSpRqw?= =?us-ascii?Q?VbGolK65/y15gwaLK14rovReIx4+NgdCrikccsNRCPZkv3/ihYcy8MyfmSv3?= =?us-ascii?Q?nWYqqiE85EiJukkCUXh+MdsoGFtFgP1f0yJqFw9Lln64yUEduUQu+qZM2eVd?= =?us-ascii?Q?bXJlx0hVFagkEiIbpNEns+WfbVKcS6nxYti2ebzd4B8s7nN+0fuSH34mCPJl?= =?us-ascii?Q?l4/N1ewRJb2TG1jmd71DDAeEb0Jh4JbicJN5zp/yCWf+ToLw9UQ/i6xfskss?= =?us-ascii?Q?CMrE+jRSkxzGmFw9YLy0IMEUyKSpgQbP3HxHIah722lZHVGknDRByKXEqrYe?= =?us-ascii?Q?ZSH8PUU3o5Zwbx9Dr5NZG+mKLZlYC8Gwr1NsK+kY6bu0pdmLNiK08QF3jYBc?= =?us-ascii?Q?DvI5yuehQ/oAriYBRgf+mQyHDhe5qlYUfA+4UJgqrF30/pxCtbfaQ1DYvJ3K?= =?us-ascii?Q?i36j5zxUj7HtmQZz1orAlBiGKrTOpdj9WQOOOmXmHswnVVL2A4IDz1f4No0u?= =?us-ascii?Q?XyKnuLOCyGW9LrzhBvXhcMY6ApJ4nkDwz7VoVXSdHWJZDHqC9hiHScIxDM96?= =?us-ascii?Q?ymlogfchfqodAaWsBzqa6qToBJ//oYp6oCGZOCsHUF08/SHIXA+fu6tmBX4f?= =?us-ascii?Q?RhViVB632594SCa+u8v89hoziUTFgKdaF8INiDSbvHMd+WmNWCMjyZCIDADM?= =?us-ascii?Q?f4YULEBduMJZZi0AbIj2LrnL0jbFyjLoPlkv9JNEEb7QS1o00B+nnXGMWtFd?= =?us-ascii?Q?dGVAMe9nedSRLGqpz4xhpEl9d/kzrX1rkcFmFimo/a5SGyvuxAw6NTAHUDze?= =?us-ascii?Q?IkpT2LAcnRILv6c5afpIQWYEviV2YykxE+cGz8QdOUXBrR5unCn3O8caeH/k?= =?us-ascii?Q?X0qt/vixwMtmHBTAKftRzyofud8LoEtPUHfftF60esktDmwilEOABsC4909J?= =?us-ascii?Q?wteJV1th6Xgd+LXuCGjRvpDFeOg0NLNcDQ5qzbr4RzKFZoI5THmHbaYXKf+e?= =?us-ascii?Q?oLt63sXmqHtDy1fMB2wDm1xqILGRFOzr19VyHPL/dVZmSzsa33FBmByalW4e?= =?us-ascii?Q?hVdCzliLRPELzQ2znL330/s8ahlz9BXCiN95a49GgQ+fohWajcJUhKiFwVrG?= =?us-ascii?Q?/ohpJIpmmJTKdt0lAx1PQNimQ4xVcLJP+aqWcg39BvqA34Y9uBh0tTi91pfw?= =?us-ascii?Q?JpOvPg3PdoX2utvX/cCtCS4BgQw5cgE2T1Ck9XErtD6aahTDM+UoPAJjgpkb?= =?us-ascii?Q?uV9FsVyHv+C0wG9lqZi1iT4/oHoyKO0Myk46P+yStUG8nnAbjhHy3QS843H8?= =?us-ascii?Q?SokB+0OLdaanJ5tRnAJG/o=3D?= X-Microsoft-Exchange-Diagnostics: 1; DM3PR07MB2139; 6:ugD+KMZDhEKn/FcB/EQDdBNMvbiWnjq2/MtmsrFeFHuwdcbzL6FetAJZp+22xT/qPPKWxjRVc3IrxLez49ufjtlZGCwgi7+tOo2QJ2aNegxRwLeeK3oVonJB62dJ03QUi16c6kM0/dp9bKDBpYCOOaW98a0ySFT5H+boW+Y58Vr+LzMzcMbop1grfXM9vw+qBpaXOvsdQBJ0dVF/WTEblWKIhrzMIvAeqxInr7uiWAB0bVMwCBZp2G/S17lyyQENeJrpLUdOz3i5q1888SDMUszDMm2Wji9zTqrXgIKo6OOTvAzpU5vkOFnQG1ltjbJBGFDxSuEIuRX6Y6cLZo+GDPX63+ERSArCM554ZoTpoZBnf1EXBWUBTXc2gMIg8+nKzLcfXBBu2WBFC9iDlVHJoAA+C1W8H5apNQevZ3HvjMK2cj+tQrTswQx2s7rk0qtUkW82Nrj5yR27xCkNiCKoXg==; 5:6CrN8Tv3t1f9+W29jqhgWOyVhgPVTYnDGfDZJcYP7nER2YXqbu/jvtnaKf4XIq7F9sypL7h5+uBUu+8E8y/hWDkwWfWl8xWgKaV/ZR3yU0hTeAB6m78jIOU5bU2Egy/bYpzcoWATknGPcWZ1wFAQ3A==; 24:eaj4EubqPQsHVl36qjwL1lExzeohncWzdEiRShLBxdB2ytp6VISwMpG7A4BEjKwYiLg1yym5qEgOS2Hlv2CBWdI5uJboikMEkI6stOj4CWM= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; DM3PR07MB2139; 7:Jk5hpS5WEm30C3ehyhC34VgNnYivSz7AbH+x7rY1+qWOcjn9sDpKxxlIZnAQMGJxIi50glw/4UsXdmVjgrSYwUB5Iw8lXmqZFU/mP4HRYUu7bDHZLF4+UXidZbbW5m5uOgJ7vRUaJvftE1GNSy29GI0yJ1IyC+12t3HXlzACrsfNucqu1CmAqoQkUCnXCJuHCIHj7u6hFNJmZ4i7sgQ5NwVDiN6Evb35gfYvJn/RnldyoR28X4YWRs2JIdMTiuxVhZB0SgWBWH08PErHXvPAWpWpU+G3ma/r6qjYsPuV5wk5RzdU9dYB9Bdg8twy7+13ze/W4czc0BkSgOmWteZKk/grXrDwhrDLQd/KFP9fHx8/GhKx2I45DhGN1+uwc82gIekvD/rhIDWw9R0CxEH7AdC4PZ5rBpY0UIEiQkPQCb182s9ZXzCK2djU6x9OIKMMGHeIhL4BTz2KS7woTuVHZw== X-OriginatorOrg: caviumnetworks.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Nov 2016 00:55:10.2575 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM3PR07MB2139 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Adds support for VF interrupt processing. Signed-off-by: Raghu Vatsavayi Signed-off-by: Derek Chickles Signed-off-by: Satanand Burla Signed-off-by: Felix Manlunas --- .../ethernet/cavium/liquidio/cn23xx_vf_device.c | 265 +++++++++++++++++++++ .../ethernet/cavium/liquidio/cn23xx_vf_device.h | 6 + drivers/net/ethernet/cavium/liquidio/lio_core.c | 7 - drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | 162 +++++++++++++ .../net/ethernet/cavium/liquidio/octeon_device.c | 3 + .../net/ethernet/cavium/liquidio/octeon_device.h | 2 + 6 files changed, 438 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c index 7dfec44..108e487 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c @@ -27,6 +27,26 @@ #include "octeon_main.h" #include "octeon_mailbox.h" +u32 cn23xx_vf_get_oq_ticks(struct octeon_device *oct, u32 time_intr_in_us) +{ + /* This gives the SLI clock per microsec */ + u32 oqticks_per_us = (u32)oct->pfvf_hsword.coproc_tics_per_us; + + /* This gives the clock cycles per millisecond */ + oqticks_per_us *= 1000; + + /* This gives the oq ticks (1024 core clock cycles) per millisecond */ + oqticks_per_us /= 1024; + + /* time_intr is in microseconds. The next 2 steps gives the oq ticks + * corressponding to time_intr. + */ + oqticks_per_us *= time_intr_in_us; + oqticks_per_us /= 1000; + + return oqticks_per_us; +} + static int cn23xx_vf_reset_io_queues(struct octeon_device *oct, u32 num_queues) { u32 loop = BUSY_READING_REG_VF_LOOP_COUNT; @@ -212,6 +232,11 @@ static void cn23xx_setup_vf_iq_regs(struct octeon_device *oct, u32 iq_no) */ pkt_in_done = readq(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); + } iq->reset_instr_cnt = 0; } @@ -342,6 +367,240 @@ static void cn23xx_disable_vf_io_queues(struct octeon_device *oct) cn23xx_vf_reset_io_queues(oct, num_queues); } +void cn23xx_vf_ask_pf_to_do_flr(struct octeon_device *oct) +{ + struct octeon_mbox_cmd mbox_cmd; + + mbox_cmd.msg.u64 = 0; + mbox_cmd.msg.s.type = OCTEON_MBOX_REQUEST; + mbox_cmd.msg.s.resp_needed = 0; + mbox_cmd.msg.s.cmd = OCTEON_VF_FLR_REQUEST; + mbox_cmd.msg.s.len = 1; + mbox_cmd.q_no = 0; + mbox_cmd.recv_len = 0; + mbox_cmd.recv_status = 0; + mbox_cmd.fn = NULL; + mbox_cmd.fn_arg = 0; + + octeon_mbox_write(oct, &mbox_cmd); +} + +static void octeon_pfvf_hs_callback(struct octeon_device *oct, + struct octeon_mbox_cmd *cmd, + void *arg) +{ + u32 major = 0; + + memcpy((uint8_t *)&oct->pfvf_hsword, cmd->msg.s.params, + CN23XX_MAILBOX_MSGPARAM_SIZE); + if (cmd->recv_len > 1) { + major = ((struct lio_version *)(cmd->data))->major; + major = major << 16; + } + + atomic_set((atomic_t *)arg, major | 1); +} + +int cn23xx_octeon_pfvf_handshake(struct octeon_device *oct) +{ + struct octeon_mbox_cmd mbox_cmd; + u32 q_no, count = 0; + atomic_t status; + u32 pfmajor; + u32 vfmajor; + u32 ret; + + /* Sending VF_ACTIVE indication to the PF driver */ + dev_dbg(&oct->pci_dev->dev, "requesting info from pf\n"); + + mbox_cmd.msg.u64 = 0; + mbox_cmd.msg.s.type = OCTEON_MBOX_REQUEST; + mbox_cmd.msg.s.resp_needed = 1; + mbox_cmd.msg.s.cmd = OCTEON_VF_ACTIVE; + mbox_cmd.msg.s.len = 2; + mbox_cmd.data[0] = 0; + ((struct lio_version *)&mbox_cmd.data[0])->major = + LIQUIDIO_BASE_MAJOR_VERSION; + ((struct lio_version *)&mbox_cmd.data[0])->minor = + LIQUIDIO_BASE_MINOR_VERSION; + ((struct lio_version *)&mbox_cmd.data[0])->micro = + LIQUIDIO_BASE_MICRO_VERSION; + mbox_cmd.q_no = 0; + mbox_cmd.recv_len = 0; + mbox_cmd.recv_status = 0; + mbox_cmd.fn = (octeon_mbox_callback_t)octeon_pfvf_hs_callback; + mbox_cmd.fn_arg = &status; + + /* Interrupts are not enabled at this point. + * Enable them with default oq ticks + */ + oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR); + + octeon_mbox_write(oct, &mbox_cmd); + + atomic_set(&status, 0); + + do { + schedule_timeout_uninterruptible(1); + } while ((!atomic_read(&status)) && (count++ < 100000)); + + /* Disable the interrupt so that the interrupsts will be reenabled + * with the oq ticks received from the PF + */ + oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR); + + ret = atomic_read(&status); + if (!ret) { + dev_err(&oct->pci_dev->dev, "octeon_pfvf_handshake timeout\n"); + return 1; + } + + for (q_no = 0 ; q_no < oct->num_iqs ; q_no++) + oct->instr_queue[q_no]->txpciq.s.pkind = oct->pfvf_hsword.pkind; + + vfmajor = LIQUIDIO_BASE_MAJOR_VERSION; + pfmajor = ret >> 16; + if (pfmajor != vfmajor) { + dev_err(&oct->pci_dev->dev, + "VF Liquidio driver (major version %d) is not compatible with Liquidio PF driver (major version %d)\n", + vfmajor, pfmajor); + return 1; + } + + dev_dbg(&oct->pci_dev->dev, + "VF Liquidio driver (major version %d), Liquidio PF driver (major version %d)\n", + vfmajor, pfmajor); + + dev_dbg(&oct->pci_dev->dev, "got data from pf pkind is %d\n", + oct->pfvf_hsword.pkind); + + return 0; +} + +static void cn23xx_handle_vf_mbox_intr(struct octeon_ioq_vector *ioq_vector) +{ + struct octeon_device *oct = ioq_vector->oct_dev; + u64 mbox_int_val; + + if (!ioq_vector->droq_index) { + /* read and clear by writing 1 */ + mbox_int_val = readq(oct->mbox[0]->mbox_int_reg); + writeq(mbox_int_val, oct->mbox[0]->mbox_int_reg); + if (octeon_mbox_read(oct->mbox[0])) + schedule_delayed_work(&oct->mbox[0]->mbox_poll_wk.work, + msecs_to_jiffies(0)); + } +} + +static u64 cn23xx_vf_msix_interrupt_handler(void *dev) +{ + 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]; + u64 pkts_sent; + u64 ret = 0; + + dev_dbg(&oct->pci_dev->dev, "In %s octeon_dev @ %p\n", __func__, oct); + 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; + + if (pkts_sent & CN23XX_INTR_MBOX_INT) { + cn23xx_handle_vf_mbox_intr(ioq_vector); + ret |= MSIX_MBOX_INT; + } + + return ret; +} + +static void cn23xx_enable_vf_interrupt(struct octeon_device *oct, u8 intr_flag) +{ + struct octeon_cn23xx_vf *cn23xx = (struct octeon_cn23xx_vf *)oct->chip; + u32 q_no, time_threshold; + + if (intr_flag & OCTEON_OUTPUT_INTR) { + for (q_no = 0; q_no < oct->num_oqs; q_no++) { + /* Set up interrupt packet and time thresholds + * for all the OQs + */ + time_threshold = cn23xx_vf_get_oq_ticks( + oct, (u32)CFG_GET_OQ_INTR_TIME(cn23xx->conf)); + + octeon_write_csr64( + oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no), + (CFG_GET_OQ_INTR_PKT(cn23xx->conf) | + ((u64)time_threshold << 32))); + } + } + + if (intr_flag & OCTEON_INPUT_INTR) { + for (q_no = 0; q_no < oct->num_oqs; q_no++) { + /* Set CINT_ENB to enable IQ interrupt */ + octeon_write_csr64( + oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no), + ((octeon_read_csr64( + oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no)) & + ~CN23XX_PKT_IN_DONE_CNT_MASK) | + CN23XX_INTR_CINT_ENB)); + } + } + + /* Set queue-0 MBOX_ENB to enable VF mailbox interrupt */ + if (intr_flag & OCTEON_MBOX_INTR) { + octeon_write_csr64( + oct, CN23XX_VF_SLI_PKT_MBOX_INT(0), + (octeon_read_csr64(oct, CN23XX_VF_SLI_PKT_MBOX_INT(0)) | + CN23XX_INTR_MBOX_ENB)); + } +} + +static void cn23xx_disable_vf_interrupt(struct octeon_device *oct, u8 intr_flag) +{ + u32 q_no; + + if (intr_flag & OCTEON_OUTPUT_INTR) { + for (q_no = 0; q_no < oct->num_oqs; q_no++) { + /* Write all 1's in INT_LEVEL reg to disable PO_INT */ + octeon_write_csr64( + oct, CN23XX_VF_SLI_OQ_PKT_INT_LEVELS(q_no), + 0x3fffffffffffff); + } + } + if (intr_flag & OCTEON_INPUT_INTR) { + for (q_no = 0; q_no < oct->num_oqs; q_no++) { + octeon_write_csr64( + oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no), + (octeon_read_csr64( + oct, CN23XX_VF_SLI_IQ_INSTR_COUNT64(q_no)) & + ~(CN23XX_INTR_CINT_ENB | + CN23XX_PKT_IN_DONE_CNT_MASK))); + } + } + + if (intr_flag & OCTEON_MBOX_INTR) { + octeon_write_csr64( + oct, CN23XX_VF_SLI_PKT_MBOX_INT(0), + (octeon_read_csr64(oct, CN23XX_VF_SLI_PKT_MBOX_INT(0)) & + ~CN23XX_INTR_MBOX_ENB)); + } +} + int cn23xx_setup_octeon_vf_device(struct octeon_device *oct) { struct octeon_cn23xx_vf *cn23xx = (struct octeon_cn23xx_vf *)oct->chip; @@ -397,8 +656,14 @@ int cn23xx_setup_octeon_vf_device(struct octeon_device *oct) oct->fn_list.setup_oq_regs = cn23xx_setup_vf_oq_regs; oct->fn_list.setup_mbox = cn23xx_setup_vf_mbox; oct->fn_list.free_mbox = cn23xx_free_vf_mbox; + + oct->fn_list.msix_interrupt_handler = cn23xx_vf_msix_interrupt_handler; + oct->fn_list.setup_device_regs = cn23xx_setup_vf_device_regs; + oct->fn_list.enable_interrupt = cn23xx_enable_vf_interrupt; + oct->fn_list.disable_interrupt = cn23xx_disable_vf_interrupt; + oct->fn_list.enable_io_queues = cn23xx_enable_vf_io_queues; oct->fn_list.disable_io_queues = cn23xx_disable_vf_io_queues; diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h index d17c1ce..8590bdb 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.h @@ -34,6 +34,12 @@ struct octeon_cn23xx_vf { #define BUSY_READING_REG_VF_LOOP_COUNT 10000 +#define CN23XX_MAILBOX_MSGPARAM_SIZE 6 + +void cn23xx_vf_ask_pf_to_do_flr(struct octeon_device *oct); + +int cn23xx_octeon_pfvf_handshake(struct octeon_device *oct); + int cn23xx_setup_octeon_vf_device(struct octeon_device *oct); void cn23xx_dump_vf_initialized_regs(struct octeon_device *oct); diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c index 403bcaa..f629c2f 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_core.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c @@ -85,13 +85,6 @@ void octeon_update_tx_completion_counters(void *buf, int reqtype, } (*pkts_compl)++; -/*TODO, Use some other pound define to suggest - * the fact that iqs are not tied to netdevs - * and can take traffic from different netdevs - * hence bql reporting is done per packet - * than in bulk. Usage of NO_NAPI in txq completion is - * a little confusing - */ *bytes_compl += skb->len; } diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c index 43a1e3f..3d5c61a 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c @@ -59,6 +59,118 @@ struct octeon_device_priv { .remove = liquidio_vf_remove, }; +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) { + dev_err(&oct->pci_dev->dev, + "should not come here should not get rx when poll mode = 0 for vf\n"); + 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; +} + +static irqreturn_t +liquidio_msix_intr_handler(int irq __attribute__((unused)), void *dev) +{ + 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]; + u64 ret; + + 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 Setup interrupt for octeon device + * @param oct octeon device + * + * Enable interrupt in Octeon device as given in the PCI interrupt mask. + */ +static int octeon_setup_interrupt(struct octeon_device *oct) +{ + struct msix_entry *msix_entries; + int num_alloc_ioq_vectors; + int num_ioq_vectors; + int irqret; + int i; + + if (oct->msix_on) { + oct->num_msix_irqs = oct->sriov_info.rings_per_vf; + + 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; + + for (i = 0; i < oct->num_msix_irqs; i++) + msix_entries[i].entry = i; + 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 (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); + + while (i) { + i--; + 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); + } + return 0; +} + /** * \brief PCI probe handler * @param pdev PCI device structure @@ -77,6 +189,7 @@ struct octeon_device_priv { dev_err(&pdev->dev, "Unable to allocate device\n"); return -ENOMEM; } + oct_dev->msix_on = LIO_FLAG_MSIX_ENABLED; dev_info(&pdev->dev, "Initializing device %x:%x.\n", (u32)pdev->vendor, (u32)pdev->device); @@ -140,9 +253,37 @@ static void octeon_pci_flr(struct octeon_device *oct) */ static void octeon_destroy_resources(struct octeon_device *oct) { + struct msix_entry *msix_entries; int i; switch (atomic_read(&oct->status)) { + case OCT_DEV_INTR_SET_DONE: + /* Disable interrupts */ + 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; i++) { + 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; + } + /* Soft reset the octeon device before exiting */ + if (oct->pci_dev->reset_fn) + octeon_pci_flr(oct); + else + cn23xx_vf_ask_pf_to_do_flr(oct); + + /* fallthrough */ + case OCT_DEV_MSIX_ALLOC_VECTOR_DONE: + octeon_free_ioq_vector(oct); + + /* fallthrough */ case OCT_DEV_MBOX_SETUP_DONE: oct->fn_list.free_mbox(oct); @@ -326,6 +467,27 @@ static int octeon_device_init(struct octeon_device *oct) } atomic_set(&oct->status, OCT_DEV_MBOX_SETUP_DONE); + if (octeon_allocate_ioq_vector(oct)) { + dev_err(&oct->pci_dev->dev, "ioq vector allocation failed\n"); + return 1; + } + atomic_set(&oct->status, OCT_DEV_MSIX_ALLOC_VECTOR_DONE); + + dev_info(&oct->pci_dev->dev, "OCTEON_CN23XX VF Version: %s, %d ioqs\n", + LIQUIDIO_VERSION, oct->sriov_info.rings_per_vf); + + /* Setup the interrupt handler and record the INT SUM register address*/ + if (octeon_setup_interrupt(oct)) + return 1; + + if (cn23xx_octeon_pfvf_handshake(oct)) + return 1; + + /* Enable Octeon device interrupts */ + oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR); + + atomic_set(&oct->status, OCT_DEV_INTR_SET_DONE); + return 0; } diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.c b/drivers/net/ethernet/cavium/liquidio/octeon_device.c index fcc5f10..6d54032 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_device.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.c @@ -754,6 +754,9 @@ struct octeon_device *octeon_allocate_device(u32 pci_id, if (OCTEON_CN23XX_PF(oct)) num_ioqs = oct->sriov_info.num_pf_rings; + else if (OCTEON_CN23XX_VF(oct)) + num_ioqs = oct->sriov_info.rings_per_vf; + size = sizeof(struct octeon_ioq_vector) * num_ioqs; oct->ioq_vector = vmalloc(size); diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.h b/drivers/net/ethernet/cavium/liquidio/octeon_device.h index 1e6bfa1..18f6836 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_device.h +++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.h @@ -53,6 +53,7 @@ enum { NUM_OCTEON_CONFS, }; +#define OCTEON_INPUT_INTR (1) #define OCTEON_OUTPUT_INTR (2) #define OCTEON_MBOX_INTR (4) #define OCTEON_ALL_INTR 0xff @@ -294,6 +295,7 @@ struct octdev_props { #define LIO_FLAG_MSIX_ENABLED 0x1 #define MSIX_PO_INT 0x1 #define MSIX_PI_INT 0x2 +#define MSIX_MBOX_INT 0x4 struct octeon_pf_vf_hs_word { #ifdef __LITTLE_ENDIAN_BITFIELD