From patchwork Tue Nov 8 06:57:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Rangankar, Manish" X-Patchwork-Id: 9416995 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 157BA6022E for ; Tue, 8 Nov 2016 09:31:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 059A329070 for ; Tue, 8 Nov 2016 09:31:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id EE30C29078; Tue, 8 Nov 2016 09:31:14 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C843C29070 for ; Tue, 8 Nov 2016 09:31:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933091AbcKHJbM (ORCPT ); Tue, 8 Nov 2016 04:31:12 -0500 Received: from mail-bl2nam02on0078.outbound.protection.outlook.com ([104.47.38.78]:21756 "EHLO NAM02-BL2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S932926AbcKHJbG (ORCPT ); Tue, 8 Nov 2016 04:31:06 -0500 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=deyblkS1+E29nKE5l8mii6Y8MmNWjhWda6mB25y5mUw=; b=kg8EZZwqVZocDEJ2d61MYzpbqpU/sEaPqZ9V9/tZZx9piymZjaIfs1J1xtzITA3yjXzvGif0ol2XpP1TYjMyQMQbhSlFavwPBTl9FsMxBEqVekem8iDEl0JtIgrrlFeRj4gzYAbO/xKazUZriVGLzIJUS4Yg5/XuhTZi5v07V44= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Manish.Rangankar@cavium.com; Received: from cavium.com (173.186.134.106) by BN3PR07MB2484.namprd07.prod.outlook.com (10.167.4.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.707.6; Tue, 8 Nov 2016 06:57:51 +0000 From: Manish Rangankar To: , , CC: , , , Subject: [PATCH v2 4/6] qedi: Add LL2 iSCSI interface for offload iSCSI. Date: Mon, 7 Nov 2016 22:57:01 -0800 Message-ID: <1478588223-16183-5-git-send-email-manish.rangankar@cavium.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1478588223-16183-1-git-send-email-manish.rangankar@cavium.com> References: <1478588223-16183-1-git-send-email-manish.rangankar@cavium.com> MIME-Version: 1.0 X-Originating-IP: [173.186.134.106] X-ClientProxiedBy: BY1PR0501CA0021.namprd05.prod.outlook.com (10.162.139.31) To BN3PR07MB2484.namprd07.prod.outlook.com (10.167.4.25) X-MS-Office365-Filtering-Correlation-Id: 51e42dea-59f7-4336-c462-08d407a48f46 X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2484; 2:j0y2RoaFI7y7n/vzg0Q9nMjb0PVepgHSqaVunwLeyiUf9V1+TXYONmdjaSKSQCBcTysQ6BvZCEwKpqgSlozxnsCES3q8rJtwA/cjF5DyBwV2xgPvjmKiKgTnjHS9VX8cPJRYSBbQP4tqqIlysMlnJTBZh8qNpe4U+ko7tYvrQNYk70+lUHEvJdr1ADxEogHXaIQLKQgaJTKj0fzpo0PLlw==; 3:0flvYrIocZQYSpfz9gdS2C5Pem3Y8xyDN7lUWkO0QzpUP8O3pAggWgBfoPG6zLcHa4Pr7wnHV9muy/g/PphIEhau2CHbRP/ZljzwD2RPOdeFH7AyXszZI+dfHtJgM9BzyeKT7o5T9umCaeex8L1GSA==; 25:npiXD/hBzBeqxmT7cpbyUfA+n8ywTYGiLEEPV5lsZRnvkC0Kd7G+8NRDtudwkcDkVxPlbn6g8bWVLinZw47uyN/aNC2rSrIIZWQ9GAqSoiTnxmSrvH26BgxQK1s0RDdEKAQoqKP0FUxQPLdppK/S9xrA7azO7eMrJLq6OEBzwAyxligll7aAM/hE5b17Vhyfuw7tWJRY732KO78Bn1qaX+N49Mi2AJqx4i/MxPow5zZQ6os7wKGD07/25pRFHnvFFYd4cfP7LkDbwenucRJUw54+DcqthnGubWnZL3EGEH83iQpQ6cOprTcabk4R2Wqwx5/Q0uKO7RpC1F9Le1a6/uxue/N9bJqw02Uv8eJtNXgrc0n6mZO/Wr0SfVFSGthkTYSEnaeb0/9l0jJiYbiFYJKw0eT7McaA8GIFXh61aC4zN/w5nsZtMx17TVD9ptzH X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN3PR07MB2484; X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2484; 31:hmQLY6cna2wGGmAuG+HWOebr9jmYxraGdY0Sd70obZAG+T6GK9Vp1XLLO4S6/JGtEIczAXd2gAIPbm0QfXCs9dMhWUYo7eDoWtc4ptF/9DNU/z1M7ospHPhC0IjUf5et9lo87qvw8nh+lsfN5cK+iP42k53SeLMaRj1QbP9LtU9pVKrigRWbRJQ079oREhG5kc/fUweiNhVxp317rV1RR0F7aR7WLG6Xv7gs8TTMuQcnJJEFSNB2mYZtTNq0k85v9EnD6MOcER8SgN7OYkmaYg==; 20:nWRYcNLkK07qim146QXU65snWMtRg6HC8bXv5030VctB62p6QKDmsmFbLPH8z0j1w9qM/enRMue5VSkKooVVjggg3aSo5W0o47u/hMh0W7XSsV1W/puBjLw1cCkJjaHTt/BNaLLGtUlyNz+h6uHLLo5usQRpg6BgHgp/mM/lncqnLQOH3zG0nk/EStQ81Jq1KGzD/ZPxNynbikC5zRZQW0ht1AfjZvFV/lnKqkIyn3M4pjFPE8wzOEqYHzBntPd9Zvis1QCVCFUsa0SPR/lOXJHZcwTzGPV6nK7QS996S3s8Tgj2SCxZ8f+K8PMEn7iX6FAAiVoAODCKJty2/aq+9bo1m1awiBYpdlI7uLSv42lZE9oGmulCV/0cRCyDoOmdOMU+/P4nxXFH9oEVJCuAGrRWlaKWZTQgKUMAGB9F4KRla6OafJFMnsvbPN6Dt51yC3kIxO+kOcsMht1dQ1pt0TNnp+vRDT+pGJu3biHUT3ETpPxfetxMGaaYuxYHnVNg X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(131327999870524); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040176)(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001); SRVR:BN3PR07MB2484; BCL:0; PCL:0; RULEID:; SRVR:BN3PR07MB2484; X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2484; 4:XZhdBm8SLF/5M220BCeGWM/a7qj5jtr/97+9yLsJDOa+NU+fzieKsWeZEyyNzQ8v5orWSfn92UJcnUnotSCF4VITQazGo2lv6luhbEje3RV3oi6AD7i3Nn+A7uy0qKJZ6bq3EYDLI0vKd9iW9WFA+NRiMEemolxbaXGC3ddTgWaQme6Af8QYY158vg+oI1IPi07ZVgpw7p21bTsly8R630QMf9HtWBA7hzLxGHWZzx/su/1vD08GuL/9achviI/KEsn3/rFPTSijUIs6SJwBmeiEIbspjv5eNYHqRX7iyPsc2sex+e/G3uocaW3KkYaIy1tV6UHwhSWCD1huauNwr/Y7DCdmwc9JM1QzjpcHiMYRGdt6CeiVxrfZfJ1JKsiXSAEb2fT9GDKZgfmXjarL8H2f1zlm+UwEileTVwAVAM75D2tvtcplv0DKHkuwhwAyN8w8JGrXa/HOGnr61RH4FA== X-Forefront-PRVS: 01208B1E18 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(4630300001)(979002)(6009001)(7916002)(199003)(189002)(33646002)(50986999)(229853001)(36756003)(6116002)(586003)(3846002)(7846002)(5003940100001)(8676002)(81166006)(81156014)(4001430100002)(7736002)(50466002)(101416001)(76176999)(2201001)(305945005)(48376002)(47776003)(5660300001)(97736004)(6666003)(2950100002)(68736007)(5001770100001)(86362001)(66066001)(77096005)(92566002)(105586002)(69596002)(2906002)(4720700003)(42186005)(50226002)(189998001)(21086003)(4326007)(107886002)(106356001)(969003)(989001)(999001)(1009001)(1019001); DIR:OUT; SFP:1101; SCL:1; SRVR:BN3PR07MB2484; H:cavium.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; BN3PR07MB2484; 23:S0zsRxAf30Se2K+sKiTtmHYHaTs3I5XdXXImIqFFi?= =?us-ascii?Q?rZyjhmG/qchkZieMyHoxbdIiZg/JYBw1jVoHZCe2KS1RgguVWD7Zfqcbthvx?= =?us-ascii?Q?hTu48+YMIFU8gdcqzZIrlBYLzK4UNOAMwj72lSpZg1516be6zcHrhAN1g5Ez?= =?us-ascii?Q?lmYrdqOb63NXXCvwaM353+2su0mJserA7Aj5Lswrm22PFC9nSfBDzR5bi84d?= =?us-ascii?Q?E+44AfNnUrRgnm6w8h/9H42b0NMFg+a9WkrQsUVKstJ5vh3xhofWKD6hLce/?= =?us-ascii?Q?nvRLwqUZHrzND7BILsXhp3MzNHiN6sUmI6vNJmL6EC7BgQ5RXHAGpRkOYkZM?= =?us-ascii?Q?xZUkoxhB4pdOhM7m0BPS9t8lZzWxVAezPrgYFXDO/j7RAXl6sh+WD7/KLljI?= =?us-ascii?Q?rrCjgKVFMve23ysa4JK8X34zesnsOi48Ew0IP0njeWoxbS00RijTjH9SDmVV?= =?us-ascii?Q?DB9W12mf2cVhzja9E01+zkgfuXlbjd7WHeWliBIH0IKPGU2uvFxyQwLXe5ma?= =?us-ascii?Q?KNu6zbiguuqAaCSN9uv39VlqHQAdwMBSn7IATgDsybETlAAsN13o04kAJA00?= =?us-ascii?Q?l7jTofsCBeaML5Dp11254G7NDuyGzqWNb8Zh+JXTzWTxuPzGze1zCPZtUdq7?= =?us-ascii?Q?5x2rzn8DdC1+GKdUJ8WL+Sendy0OCnkTnqABoy3LTAk48lXdjCx5tnCwNern?= =?us-ascii?Q?gHuJHqxsFMrd+wh0aEAaq1Bi4gLFWjf2KMAERDctd297OZOkc6Y1Trs+pam5?= =?us-ascii?Q?PakEWkyHY7cYcJt66EiiKL5EeCxmbijNg3SQQYmo9TBChoWpL8I99LM2ctzx?= =?us-ascii?Q?7dGHIKDJLK/zPDVaHDdXQHUvocd49SSG2K8h2bqYxhWeAj7t2zQ4dnJ6UHNa?= =?us-ascii?Q?dkaqNNozM2hGCH9hndyb1P8caIorGcBhAcngjY226QWdhkl/U6EBNkYrnEoL?= =?us-ascii?Q?B1hzXZ5Zinnrb+u/199gx1mpcqgAigecjK056lsuUoci5OVBqismN/CIKaJY?= =?us-ascii?Q?TyQ0H6vVYk+xjy1Sdct8gciPd/csqXVq9cXvB9ZO9IM5o8OOuAQGRIASVJZl?= =?us-ascii?Q?nxmzaWYafqTBH9bPT5j7oJdMmgJqyK+D4Ak6a4tGETocYyyMv0QWyjWU9dhY?= =?us-ascii?Q?t7AiKOZB/H8hW+NYWifX5MWqyBIkSmpQFg9eVXteUJ+valHSCzYfooxEpRXr?= =?us-ascii?Q?Id9iiSqC86B0V9Em1j+RvGMW/Dd0EJCnHYKE4mfhK2NVrJb8PIqVje8cWvJM?= =?us-ascii?Q?zbnxTMzilPz9/1pcyuGY3XCsSNdspcXxyK7iXBHw7Bw2/RY0w9RnHSw3lt9G?= =?us-ascii?B?dz09?= X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2484; 6:M9Ydlb5frjejeXgIX0ObY2tA05WtmH1El2NWzHMOhsfLLZz7af6/+fuK12+hImi4bO2DX8Az8A428/qO2BxvHfklkXtAiSSdIX5lbAP2/4rc1JVklzlv3XnJ2JHMBZw5lP3UkVY59e1lS7hS7p2xiYzsMSF0eMwae2mk6jw9OedE6F1RXHNviHi9vWlVQlueY9m5KLXQkhdVZXJy2V3RLAAiOi8iax50MF32MF8ZcDJk7mh6oa+gAqp4E4yKXKmFvbkqNs1r7fHyw/XtV+XBt+G8cGrP2fG3wO0CmEESCOHPBD55fsJa5E5Y3UVVi2vq; 5:ITf6lB9Eo4h5spSZg6jKy6v7m1gCE5PEX/CMyH4a2jZdH/wOBq8QZNg7DFbOiWpZ40FCNQuYff6FCK0COCfj8PwpcQrulZKzf5dN16KVnLqVB+Mgt2G94sW8ri3MbqgsZjHie+dUoipx04wIpy9k78W54tLnHY54Y8R/E8Wc4ak=; 24:wBrHX7aeBlwdBaGVsIclJc39AghT9bSZDzLZt2zl4k1W5FssBGKYTCs09PgXPuzJYqYdO1icv/EQvLHiVp0YOOaTGBUheMwywG8hm22OFHg= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; BN3PR07MB2484; 7:e8TqSIBvZlyLACBcXPISfaya2gPxQ1JRysEqH7uA1kMrUa9QllDOsXUWxe4790Qi2EU2up/GpEgp2yTJBGLFRaVQid093XzhlhM1ffnVa7SyvFEkuOH2diLRxxEeG5EKMdP9Zy5pqAx9Ks4a3USTP+qdGUK4AAYFZvZ7ZaHXZ6Y4FX4KDpoJecdPXNmygxTPpCc8uOEyhw67YrH8BYSWfbE93623Gd2gnyzFoARl6hVYv7OXDuIuL0zyu3QIZYPFRQL4N/oiMACYEwUnAWL4TatgakL6AAMHS/MC6ef7D5IFjXB57JBOo1hocxMwbwb8B3bktOZ07t4LhZF8E7h47WE6uigjI/RCbWfIH0TcwxU= X-OriginatorOrg: cavium.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 08 Nov 2016 06:57:51.9998 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3PR07MB2484 Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds support for iscsiuio interface using Light L2 (LL2) qed interface. Signed-off-by: Nilesh Javali Signed-off-by: Adheer Chandravanshi Signed-off-by: Chad Dupuis Signed-off-by: Saurav Kashyap Signed-off-by: Arun Easi Signed-off-by: Manish Rangankar Reviewed-by: Hannes Reinecke --- drivers/scsi/qedi/qedi.h | 73 +++++++++ drivers/scsi/qedi/qedi_main.c | 357 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 430 insertions(+) diff --git a/drivers/scsi/qedi/qedi.h b/drivers/scsi/qedi/qedi.h index 92136a3..e00c141 100644 --- a/drivers/scsi/qedi/qedi.h +++ b/drivers/scsi/qedi/qedi.h @@ -21,6 +21,7 @@ #include #include "qedi_dbg.h" #include +#include #include "qedi_version.h" #define QEDI_MODULE_NAME "qedi" @@ -54,6 +55,78 @@ #define QEDI_LOCAL_PORT_MAX 61024 #define QEDI_LOCAL_PORT_RANGE (QEDI_LOCAL_PORT_MAX - QEDI_LOCAL_PORT_MIN) #define QEDI_LOCAL_PORT_INVALID 0xffff +#define TX_RX_RING 16 +#define RX_RING (TX_RX_RING - 1) +#define LL2_SINGLE_BUF_SIZE 0x400 +#define QEDI_PAGE_SIZE 4096 +#define QEDI_PAGE_ALIGN(addr) ALIGN(addr, QEDI_PAGE_SIZE) +#define QEDI_PAGE_MASK (~((QEDI_PAGE_SIZE) - 1)) + +#define QEDI_PAGE_SIZE 4096 +#define QEDI_PATH_HANDLE 0xFE0000000UL + +struct qedi_uio_ctrl { + /* meta data */ + u32 uio_hsi_version; + + /* user writes */ + u32 host_tx_prod; + u32 host_rx_cons; + u32 host_rx_bd_cons; + u32 host_tx_pkt_len; + u32 host_rx_cons_cnt; + + /* driver writes */ + u32 hw_tx_cons; + u32 hw_rx_prod; + u32 hw_rx_bd_prod; + u32 hw_rx_prod_cnt; + + /* other */ + u8 mac_addr[6]; + u8 reserve[2]; +}; + +struct qedi_rx_bd { + u32 rx_pkt_index; + u32 rx_pkt_len; + u16 vlan_id; +}; + +#define QEDI_RX_DESC_CNT (QEDI_PAGE_SIZE / sizeof(struct qedi_rx_bd)) +#define QEDI_MAX_RX_DESC_CNT (QEDI_RX_DESC_CNT - 1) +#define QEDI_NUM_RX_BD (QEDI_RX_DESC_CNT * 1) +#define QEDI_MAX_RX_BD (QEDI_NUM_RX_BD - 1) + +#define QEDI_NEXT_RX_IDX(x) ((((x) & (QEDI_MAX_RX_DESC_CNT)) == \ + (QEDI_MAX_RX_DESC_CNT - 1)) ? \ + (x) + 2 : (x) + 1) + +struct qedi_uio_dev { + struct uio_info qedi_uinfo; + u32 uio_dev; + struct list_head list; + + u32 ll2_ring_size; + void *ll2_ring; + + u32 ll2_buf_size; + void *ll2_buf; + + void *rx_pkt; + void *tx_pkt; + + struct qedi_ctx *qedi; + struct pci_dev *pdev; + void *uctrl; +}; + +/* List to maintain the skb pointers */ +struct skb_work_list { + struct list_head list; + struct sk_buff *skb; + u16 vlan_id; +}; /* Queue sizes in number of elements */ #define QEDI_SQ_SIZE MAX_OUSTANDING_TASKS_PER_CON diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 5845dc9..ef309c6 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -45,10 +45,13 @@ static struct scsi_transport_template *qedi_scsi_transport; static struct pci_driver qedi_pci_driver; static DEFINE_PER_CPU(struct qedi_percpu_s, qedi_percpu); +static LIST_HEAD(qedi_udev_list); /* Static function declaration */ static int qedi_alloc_global_queues(struct qedi_ctx *qedi); static void qedi_free_global_queues(struct qedi_ctx *qedi); static struct qedi_cmd *qedi_get_cmd_from_tid(struct qedi_ctx *qedi, u32 tid); +static void qedi_reset_uio_rings(struct qedi_uio_dev *udev); +static void qedi_ll2_free_skbs(struct qedi_ctx *qedi); static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void *fw_handle) { @@ -113,6 +116,224 @@ static int qedi_iscsi_event_cb(void *context, u8 fw_event_code, void *fw_handle) return rval; } +static int qedi_uio_open(struct uio_info *uinfo, struct inode *inode) +{ + struct qedi_uio_dev *udev = uinfo->priv; + struct qedi_ctx *qedi = udev->qedi; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (udev->uio_dev != -1) + return -EBUSY; + + rtnl_lock(); + udev->uio_dev = iminor(inode); + qedi_reset_uio_rings(udev); + set_bit(UIO_DEV_OPENED, &qedi->flags); + rtnl_unlock(); + + return 0; +} + +static int qedi_uio_close(struct uio_info *uinfo, struct inode *inode) +{ + struct qedi_uio_dev *udev = uinfo->priv; + struct qedi_ctx *qedi = udev->qedi; + + udev->uio_dev = -1; + clear_bit(UIO_DEV_OPENED, &qedi->flags); + qedi_ll2_free_skbs(qedi); + return 0; +} + +static void __qedi_free_uio_rings(struct qedi_uio_dev *udev) +{ + if (udev->ll2_ring) { + free_page((unsigned long)udev->ll2_ring); + udev->ll2_ring = NULL; + } + + if (udev->ll2_buf) { + free_pages((unsigned long)udev->ll2_buf, 2); + udev->ll2_buf = NULL; + } +} + +static void __qedi_free_uio(struct qedi_uio_dev *udev) +{ + uio_unregister_device(&udev->qedi_uinfo); + + __qedi_free_uio_rings(udev); + + pci_dev_put(udev->pdev); + kfree(udev->uctrl); + kfree(udev); +} + +static void qedi_free_uio(struct qedi_uio_dev *udev) +{ + if (!udev) + return; + + list_del_init(&udev->list); + __qedi_free_uio(udev); +} + +static void qedi_reset_uio_rings(struct qedi_uio_dev *udev) +{ + struct qedi_ctx *qedi = NULL; + struct qedi_uio_ctrl *uctrl = NULL; + + qedi = udev->qedi; + uctrl = udev->uctrl; + + spin_lock_bh(&qedi->ll2_lock); + uctrl->host_rx_cons = 0; + uctrl->hw_rx_prod = 0; + uctrl->hw_rx_bd_prod = 0; + uctrl->host_rx_bd_cons = 0; + + memset(udev->ll2_ring, 0, udev->ll2_ring_size); + memset(udev->ll2_buf, 0, udev->ll2_buf_size); + spin_unlock_bh(&qedi->ll2_lock); +} + +static int __qedi_alloc_uio_rings(struct qedi_uio_dev *udev) +{ + int rc = 0; + + if (udev->ll2_ring || udev->ll2_buf) + return rc; + + /* Allocating memory for LL2 ring */ + udev->ll2_ring_size = QEDI_PAGE_SIZE; + udev->ll2_ring = (void *)get_zeroed_page(GFP_KERNEL | __GFP_COMP); + if (!udev->ll2_ring) { + rc = -ENOMEM; + goto exit_alloc_ring; + } + + /* Allocating memory for Tx/Rx pkt buffer */ + udev->ll2_buf_size = TX_RX_RING * LL2_SINGLE_BUF_SIZE; + udev->ll2_buf_size = QEDI_PAGE_ALIGN(udev->ll2_buf_size); + udev->ll2_buf = (void *)__get_free_pages(GFP_KERNEL | __GFP_COMP | + __GFP_ZERO, 2); + if (!udev->ll2_buf) { + rc = -ENOMEM; + goto exit_alloc_buf; + } + return rc; + +exit_alloc_buf: + free_page((unsigned long)udev->ll2_ring); + udev->ll2_ring = NULL; +exit_alloc_ring: + return rc; +} + +static int qedi_alloc_uio_rings(struct qedi_ctx *qedi) +{ + struct qedi_uio_dev *udev = NULL; + struct qedi_uio_ctrl *uctrl = NULL; + int rc = 0; + + list_for_each_entry(udev, &qedi_udev_list, list) { + if (udev->pdev == qedi->pdev) { + udev->qedi = qedi; + if (__qedi_alloc_uio_rings(udev)) { + udev->qedi = NULL; + return -ENOMEM; + } + qedi->udev = udev; + return 0; + } + } + + udev = kzalloc(sizeof(*udev), GFP_KERNEL); + if (!udev) { + rc = -ENOMEM; + goto err_udev; + } + + uctrl = kzalloc(sizeof(*uctrl), GFP_KERNEL); + if (!uctrl) { + rc = -ENOMEM; + goto err_uctrl; + } + + udev->uio_dev = -1; + + udev->qedi = qedi; + udev->pdev = qedi->pdev; + udev->uctrl = uctrl; + + rc = __qedi_alloc_uio_rings(udev); + if (rc) + goto err_uio_rings; + + list_add(&udev->list, &qedi_udev_list); + + pci_dev_get(udev->pdev); + qedi->udev = udev; + + udev->tx_pkt = udev->ll2_buf; + udev->rx_pkt = udev->ll2_buf + LL2_SINGLE_BUF_SIZE; + return 0; + + err_uio_rings: + kfree(uctrl); + err_uctrl: + kfree(udev); + err_udev: + return -ENOMEM; +} + +static int qedi_init_uio(struct qedi_ctx *qedi) +{ + struct qedi_uio_dev *udev = qedi->udev; + struct uio_info *uinfo; + int ret = 0; + + if (!udev) + return -ENOMEM; + + uinfo = &udev->qedi_uinfo; + + uinfo->mem[0].addr = (unsigned long)udev->uctrl; + uinfo->mem[0].size = sizeof(struct qedi_uio_ctrl); + uinfo->mem[0].memtype = UIO_MEM_LOGICAL; + + uinfo->mem[1].addr = (unsigned long)udev->ll2_ring; + uinfo->mem[1].size = udev->ll2_ring_size; + uinfo->mem[1].memtype = UIO_MEM_LOGICAL; + + uinfo->mem[2].addr = (unsigned long)udev->ll2_buf; + uinfo->mem[2].size = udev->ll2_buf_size; + uinfo->mem[2].memtype = UIO_MEM_LOGICAL; + + uinfo->name = "qedi_uio"; + uinfo->version = QEDI_MODULE_VERSION; + uinfo->irq = UIO_IRQ_CUSTOM; + + uinfo->open = qedi_uio_open; + uinfo->release = qedi_uio_close; + + if (udev->uio_dev == -1) { + if (!uinfo->priv) { + uinfo->priv = udev; + + ret = uio_register_device(&udev->pdev->dev, uinfo); + if (ret) { + QEDI_ERR(&qedi->dbg_ctx, + "UIO registration failed\n"); + } + } + } + + return ret; +} + static int qedi_alloc_and_init_sb(struct qedi_ctx *qedi, struct qed_sb_info *sb_info, u16 sb_id) { @@ -442,6 +663,142 @@ static struct qedi_ctx *qedi_host_alloc(struct pci_dev *pdev) return qedi; } +static int qedi_ll2_rx(void *cookie, struct sk_buff *skb, u32 arg1, u32 arg2) +{ + struct qedi_ctx *qedi = (struct qedi_ctx *)cookie; + struct qedi_uio_dev *udev; + struct qedi_uio_ctrl *uctrl; + struct skb_work_list *work; + u32 prod; + + if (!qedi) { + QEDI_ERR(NULL, "qedi is NULL\n"); + return -1; + } + + if (!test_bit(UIO_DEV_OPENED, &qedi->flags)) { + QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_UIO, + "UIO DEV is not opened\n"); + kfree_skb(skb); + return 0; + } + + udev = qedi->udev; + uctrl = udev->uctrl; + + work = kzalloc(sizeof(*work), GFP_ATOMIC); + if (!work) { + QEDI_WARN(&qedi->dbg_ctx, + "Could not allocate work so dropping frame.\n"); + kfree_skb(skb); + return 0; + } + + INIT_LIST_HEAD(&work->list); + work->skb = skb; + + if (skb_vlan_tag_present(skb)) + work->vlan_id = skb_vlan_tag_get(skb); + + if (work->vlan_id) + __vlan_insert_tag(work->skb, htons(ETH_P_8021Q), work->vlan_id); + + spin_lock_bh(&qedi->ll2_lock); + list_add_tail(&work->list, &qedi->ll2_skb_list); + + ++uctrl->hw_rx_prod_cnt; + prod = (uctrl->hw_rx_prod + 1) % RX_RING; + if (prod != uctrl->host_rx_cons) { + uctrl->hw_rx_prod = prod; + spin_unlock_bh(&qedi->ll2_lock); + wake_up_process(qedi->ll2_recv_thread); + return 0; + } + + spin_unlock_bh(&qedi->ll2_lock); + return 0; +} + +/* map this skb to iscsiuio mmaped region */ +static int qedi_ll2_process_skb(struct qedi_ctx *qedi, struct sk_buff *skb, + u16 vlan_id) +{ + struct qedi_uio_dev *udev = NULL; + struct qedi_uio_ctrl *uctrl = NULL; + struct qedi_rx_bd rxbd; + struct qedi_rx_bd *p_rxbd; + u32 rx_bd_prod; + void *pkt; + int len = 0; + + if (!qedi) { + QEDI_ERR(NULL, "qedi is NULL\n"); + return -1; + } + + udev = qedi->udev; + uctrl = udev->uctrl; + pkt = udev->rx_pkt + (uctrl->hw_rx_prod * LL2_SINGLE_BUF_SIZE); + len = min_t(u32, skb->len, (u32)LL2_SINGLE_BUF_SIZE); + memcpy(pkt, skb->data, len); + + memset(&rxbd, 0, sizeof(rxbd)); + rxbd.rx_pkt_index = uctrl->hw_rx_prod; + rxbd.rx_pkt_len = len; + rxbd.vlan_id = vlan_id; + + uctrl->hw_rx_bd_prod = (uctrl->hw_rx_bd_prod + 1) % QEDI_NUM_RX_BD; + rx_bd_prod = uctrl->hw_rx_bd_prod; + p_rxbd = (struct qedi_rx_bd *)udev->ll2_ring; + p_rxbd += rx_bd_prod; + + memcpy(p_rxbd, &rxbd, sizeof(rxbd)); + + /* notify the iscsiuio about new packet */ + uio_event_notify(&udev->qedi_uinfo); + + return 0; +} + +static void qedi_ll2_free_skbs(struct qedi_ctx *qedi) +{ + struct skb_work_list *work, *work_tmp; + + spin_lock_bh(&qedi->ll2_lock); + list_for_each_entry_safe(work, work_tmp, &qedi->ll2_skb_list, list) { + list_del(&work->list); + if (work->skb) + kfree_skb(work->skb); + kfree(work); + } + spin_unlock_bh(&qedi->ll2_lock); +} + +static int qedi_ll2_recv_thread(void *arg) +{ + struct qedi_ctx *qedi = (struct qedi_ctx *)arg; + struct skb_work_list *work, *work_tmp; + + set_user_nice(current, -20); + + while (!kthread_should_stop()) { + spin_lock_bh(&qedi->ll2_lock); + list_for_each_entry_safe(work, work_tmp, &qedi->ll2_skb_list, + list) { + list_del(&work->list); + qedi_ll2_process_skb(qedi, work->skb, work->vlan_id); + kfree_skb(work->skb); + kfree(work); + } + set_current_state(TASK_INTERRUPTIBLE); + spin_unlock_bh(&qedi->ll2_lock); + schedule(); + } + + __set_current_state(TASK_RUNNING); + return 0; +} + static int qedi_set_iscsi_pf_param(struct qedi_ctx *qedi) { u8 num_sq_pages;