From patchwork Fri Feb 14 23:22:22 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238395 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8YX0TVgz9s29 for ; Sat, 15 Feb 2020 10:22:40 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728280AbgBNXWj (ORCPT ); Fri, 14 Feb 2020 18:22:39 -0500 Received: from mga11.intel.com ([192.55.52.93]:12667 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728238AbgBNXWb (ORCPT ); Fri, 14 Feb 2020 18:22:31 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:29 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629342" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:29 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 1/2] devlink: add support for DEVLINK_CMD_REGION_NEW Date: Fri, 14 Feb 2020 15:22:22 -0800 Message-Id: <20200214232223.3442651-24-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add support to request that a new snapshot be taken immediately for a devlink region. Optionally allow specifying the snapshot id to use. If no snapshot id is provided, the kernel will select a suitable id automatically. If the region does not support snapshots on demand, the command will return an error indicating the operation is not supported. Signed-off-by: Jacob Keller --- devlink/devlink.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/devlink/devlink.c b/devlink/devlink.c index f9e58c1d7394..71c300ba16ed 100644 --- a/devlink/devlink.c +++ b/devlink/devlink.c @@ -6347,10 +6347,27 @@ static int cmd_region_read(struct dl *dl) return err; } +static int cmd_region_snapshot_new(struct dl *dl) +{ + struct nlmsghdr *nlh; + int err; + + nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_REGION_NEW, + NLM_F_REQUEST | NLM_F_ACK); + + err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE_REGION, + DL_OPT_REGION_SNAPSHOT_ID); + if (err) + return err; + + return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); +} + static void cmd_region_help(void) { pr_err("Usage: devlink region show [ DEV/REGION ]\n"); pr_err(" devlink region del DEV/REGION snapshot SNAPSHOT_ID\n"); + pr_err(" devlink region new DEV/REGION [snapshot SNAPSHOT_ID]\n"); pr_err(" devlink region dump DEV/REGION [ snapshot SNAPSHOT_ID ]\n"); pr_err(" devlink region read DEV/REGION [ snapshot SNAPSHOT_ID ] address ADDRESS length LENGTH\n"); } @@ -6374,6 +6391,9 @@ static int cmd_region(struct dl *dl) } else if (dl_argv_match(dl, "read")) { dl_arg_inc(dl); return cmd_region_read(dl); + } else if (dl_argv_match(dl, "new")) { + dl_arg_inc(dl); + return cmd_region_snapshot_new(dl); } pr_err("Command \"%s\" not found\n", dl_argv(dl)); return -ENOENT; From patchwork Fri Feb 14 23:22:23 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238396 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8YX5dVMz9sPK for ; Sat, 15 Feb 2020 10:22:40 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728229AbgBNXWh (ORCPT ); Fri, 14 Feb 2020 18:22:37 -0500 Received: from mga11.intel.com ([192.55.52.93]:12666 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728240AbgBNXWb (ORCPT ); Fri, 14 Feb 2020 18:22:31 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:29 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629347" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:29 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 2/2] devlink: stop requiring snapshot for regions Date: Fri, 14 Feb 2020 15:22:23 -0800 Message-Id: <20200214232223.3442651-25-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The region dump and region read commands currently require the snapshot to work. Recent changes to the kernel have enabled optionally supporting direct read of a region's contents without a snapshot id. Enable this by allowing the read and dump commands to execute without a snapshot id. On older kernels, this will return -EINVAL as the kernel will reject such a command. On newer kernels, this will directly read the region contents without taking a snapshot. If a region does not support direct read, it will return -EOPNOTSUPP. Signed-off-by: Jacob Keller --- devlink/devlink.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/devlink/devlink.c b/devlink/devlink.c index 71c300ba16ed..f98f2dc034ea 100644 --- a/devlink/devlink.c +++ b/devlink/devlink.c @@ -6312,8 +6312,8 @@ static int cmd_region_dump(struct dl *dl) nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_REGION_READ, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE_REGION | - DL_OPT_REGION_SNAPSHOT_ID, 0); + err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE_REGION, + DL_OPT_REGION_SNAPSHOT_ID); if (err) return err; @@ -6334,8 +6334,8 @@ static int cmd_region_read(struct dl *dl) NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE_REGION | - DL_OPT_REGION_ADDRESS | DL_OPT_REGION_LENGTH | - DL_OPT_REGION_SNAPSHOT_ID, 0); + DL_OPT_REGION_ADDRESS | DL_OPT_REGION_LENGTH, + DL_OPT_REGION_SNAPSHOT_ID); if (err) return err; From patchwork Fri Feb 14 23:22:02 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238414 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8ZM6Qh7z9sPK for ; Sat, 15 Feb 2020 10:23:23 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728360AbgBNXXW (ORCPT ); Fri, 14 Feb 2020 18:23:22 -0500 Received: from mga02.intel.com ([134.134.136.20]:41445 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727787AbgBNXW2 (ORCPT ); Fri, 14 Feb 2020 18:22:28 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:26 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629274" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:26 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jesse Brandeburg , Jacob Keller Subject: [RFC PATCH v2 03/22] ice: implement full NVM read from ETHTOOL_GEEPROM Date: Fri, 14 Feb 2020 15:22:02 -0800 Message-Id: <20200214232223.3442651-4-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Jesse Brandeburg The current implementation of .get_eeprom only enables reading from the Shadow RAM portion of the NVM contents. Implement support for reading the entire flash contents instead of only the initial portion contained in the Shadow RAM. A complete dump can take several seconds, but the ETHTOOL_GEEPROM ioctl is capable of reading only a limited portion at a time by specifying the offset and length to read. In order to perform the reads directly, several functions are made non static. Additionally, the unused ice_read_sr_buf_aq and ice_read_sr_buf functions are removed. Signed-off-by: Jesse Brandeburg Signed-off-by: Jacob Keller --- .../net/ethernet/intel/ice/ice_adminq_cmd.h | 1 + drivers/net/ethernet/intel/ice/ice_common.h | 3 - drivers/net/ethernet/intel/ice/ice_ethtool.c | 36 +++-- drivers/net/ethernet/intel/ice/ice_nvm.c | 150 +----------------- drivers/net/ethernet/intel/ice/ice_nvm.h | 4 + 5 files changed, 31 insertions(+), 163 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h index 04bc092e8f45..ba4e4f9a89ad 100644 --- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h +++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h @@ -1758,6 +1758,7 @@ enum ice_aq_err { ICE_AQ_RC_ENOMEM = 9, /* Out of memory */ ICE_AQ_RC_EBUSY = 12, /* Device or resource busy */ ICE_AQ_RC_EEXIST = 13, /* Object already exists */ + ICE_AQ_RC_EINVAL = 14, /* Invalid argument */ ICE_AQ_RC_ENOSPC = 16, /* No space left or allocation failure */ ICE_AQ_RC_ENOSYS = 17, /* Function not implemented */ ICE_AQ_RC_ENOSEC = 24, /* Missing security manifest */ diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index f9fc005d35a7..9d5e86c9f886 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -38,9 +38,6 @@ enum ice_status ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res); enum ice_status ice_free_hw_res(struct ice_hw *hw, u16 type, u16 num, u16 *res); -enum ice_status ice_init_nvm(struct ice_hw *hw); -enum ice_status -ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data); enum ice_status ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries, struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index b002ab4e5838..223e8e707dcb 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -251,39 +251,51 @@ ice_get_eeprom(struct net_device *netdev, struct ethtool_eeprom *eeprom, u8 *bytes) { struct ice_netdev_priv *np = netdev_priv(netdev); - u16 first_word, last_word, nwords; struct ice_vsi *vsi = np->vsi; struct ice_pf *pf = vsi->back; struct ice_hw *hw = &pf->hw; enum ice_status status; struct device *dev; int ret = 0; - u16 *buf; + u8 *buf; dev = ice_pf_to_dev(pf); eeprom->magic = hw->vendor_id | (hw->device_id << 16); + netdev_dbg(netdev, "GEEPROM cmd 0x%08x, offset 0x%08x, len 0x%08x\n", + eeprom->cmd, eeprom->offset, eeprom->len); - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - nwords = last_word - first_word + 1; - - buf = devm_kcalloc(dev, nwords, sizeof(u16), GFP_KERNEL); + buf = kzalloc(eeprom->len, GFP_KERNEL); if (!buf) return -ENOMEM; - status = ice_read_sr_buf(hw, first_word, &nwords, buf); + status = ice_acquire_nvm(hw, ICE_RES_READ); if (status) { - dev_err(dev, "ice_read_sr_buf failed, err %d aq_err %d\n", + dev_err(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", status, hw->adminq.sq_last_status); - eeprom->len = sizeof(u16) * nwords; ret = -EIO; goto out; } - memcpy(bytes, (u8 *)buf + (eeprom->offset & 1), eeprom->len); + status = ice_read_flat_nvm(hw, eeprom->offset, &eeprom->len, buf, false); + if (status == ICE_ERR_AQ_ERROR && + hw->adminq.sq_last_status == ICE_AQ_RC_EINVAL) { + /* do nothing, we reached the end */ + ice_release_nvm(hw); + goto out; + } else if (status) { + dev_err(dev, "ice_read_flat_nvm failed, err %d aq_err %d\n", + status, hw->adminq.sq_last_status); + ret = -EIO; + ice_release_nvm(hw); + goto out; + } + + ice_release_nvm(hw); + + memcpy(bytes, buf, eeprom->len); out: - devm_kfree(dev, buf); + kfree(buf); return ret; } diff --git a/drivers/net/ethernet/intel/ice/ice_nvm.c b/drivers/net/ethernet/intel/ice/ice_nvm.c index e2214c076ca9..aaf5fd064725 100644 --- a/drivers/net/ethernet/intel/ice/ice_nvm.c +++ b/drivers/net/ethernet/intel/ice/ice_nvm.c @@ -108,70 +108,6 @@ ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data, return status; } -/** - * ice_check_sr_access_params - verify params for Shadow RAM R/W operations. - * @hw: pointer to the HW structure - * @offset: offset in words from module start - * @words: number of words to access - */ -static enum ice_status -ice_check_sr_access_params(struct ice_hw *hw, u32 offset, u16 words) -{ - if ((offset + words) > hw->nvm.sr_words) { - ice_debug(hw, ICE_DBG_NVM, - "NVM error: offset beyond SR lmt.\n"); - return ICE_ERR_PARAM; - } - - if (words > ICE_SR_SECTOR_SIZE_IN_WORDS) { - /* We can access only up to 4KB (one sector), in one AQ write */ - ice_debug(hw, ICE_DBG_NVM, - "NVM error: tried to access %d words, limit is %d.\n", - words, ICE_SR_SECTOR_SIZE_IN_WORDS); - return ICE_ERR_PARAM; - } - - if (((offset + (words - 1)) / ICE_SR_SECTOR_SIZE_IN_WORDS) != - (offset / ICE_SR_SECTOR_SIZE_IN_WORDS)) { - /* A single access cannot spread over two sectors */ - ice_debug(hw, ICE_DBG_NVM, - "NVM error: cannot spread over two sectors.\n"); - return ICE_ERR_PARAM; - } - - return 0; -} - -/** - * ice_read_sr_aq - Read Shadow RAM. - * @hw: pointer to the HW structure - * @offset: offset in words from module start - * @words: number of words to read - * @data: storage for the words read from Shadow RAM (Little Endian) - * @last_command: tells the AdminQ that this is the last command - * - * Reads 16-bit Little Endian word buffers from the Shadow RAM using the admin - * command. - */ -static enum ice_status -ice_read_sr_aq(struct ice_hw *hw, u32 offset, u16 words, __le16 *data, - bool last_command) -{ - enum ice_status status; - - status = ice_check_sr_access_params(hw, offset, words); - - /* values in "offset" and "words" parameters are sized as words - * (16 bits) but ice_aq_read_nvm expects these values in bytes. - * So do this conversion while calling ice_aq_read_nvm. - */ - if (!status) - status = ice_aq_read_nvm(hw, 0, 2 * offset, 2 * words, data, - last_command, true, NULL); - - return status; -} - /** * ice_read_sr_word_aq - Reads Shadow RAM via AQ * @hw: pointer to the HW structure @@ -199,63 +135,6 @@ ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data) return 0; } -/** - * ice_read_sr_buf_aq - Reads Shadow RAM buf via AQ - * @hw: pointer to the HW structure - * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) - * @words: (in) number of words to read; (out) number of words actually read - * @data: words read from the Shadow RAM - * - * Reads 16 bit words (data buf) from the SR using the ice_read_sr_aq - * method. Ownership of the NVM is taken before reading the buffer and later - * released. - */ -static enum ice_status -ice_read_sr_buf_aq(struct ice_hw *hw, u16 offset, u16 *words, u16 *data) -{ - enum ice_status status; - bool last_cmd = false; - u16 words_read = 0; - u16 i = 0; - - do { - u16 read_size, off_w; - - /* Calculate number of bytes we should read in this step. - * It's not allowed to read more than one page at a time or - * to cross page boundaries. - */ - off_w = offset % ICE_SR_SECTOR_SIZE_IN_WORDS; - read_size = off_w ? - min_t(u16, *words, - (ICE_SR_SECTOR_SIZE_IN_WORDS - off_w)) : - min_t(u16, (*words - words_read), - ICE_SR_SECTOR_SIZE_IN_WORDS); - - /* Check if this is last command, if so set proper flag */ - if ((words_read + read_size) >= *words) - last_cmd = true; - - status = ice_read_sr_aq(hw, offset, read_size, - data + words_read, last_cmd); - if (status) - goto read_nvm_buf_aq_exit; - - /* Increment counter for words already read and move offset to - * new read location - */ - words_read += read_size; - offset += read_size; - } while (words_read < *words); - - for (i = 0; i < *words; i++) - data[i] = le16_to_cpu(((__force __le16 *)data)[i]); - -read_nvm_buf_aq_exit: - *words = words_read; - return status; -} - /** * ice_acquire_nvm - Generic request for acquiring the NVM ownership * @hw: pointer to the HW structure @@ -263,7 +142,7 @@ ice_read_sr_buf_aq(struct ice_hw *hw, u16 offset, u16 *words, u16 *data) * * This function will request NVM ownership. */ -static enum ice_status +enum ice_status ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access) { if (hw->nvm.blank_nvm_mode) @@ -278,7 +157,7 @@ ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access) * * This function will release NVM ownership. */ -static void ice_release_nvm(struct ice_hw *hw) +void ice_release_nvm(struct ice_hw *hw) { if (hw->nvm.blank_nvm_mode) return; @@ -412,31 +291,6 @@ enum ice_status ice_init_nvm(struct ice_hw *hw) return 0; } -/** - * ice_read_sr_buf - Reads Shadow RAM buf and acquire lock if necessary - * @hw: pointer to the HW structure - * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) - * @words: (in) number of words to read; (out) number of words actually read - * @data: words read from the Shadow RAM - * - * Reads 16 bit words (data buf) from the SR using the ice_read_nvm_buf_aq - * method. The buf read is preceded by the NVM ownership take - * and followed by the release. - */ -enum ice_status -ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data) -{ - enum ice_status status; - - status = ice_acquire_nvm(hw, ICE_RES_READ); - if (!status) { - status = ice_read_sr_buf_aq(hw, offset, words, data); - ice_release_nvm(hw); - } - - return status; -} - /** * ice_nvm_validate_checksum * @hw: pointer to the HW struct diff --git a/drivers/net/ethernet/intel/ice/ice_nvm.h b/drivers/net/ethernet/intel/ice/ice_nvm.h index 4245ef988edf..7375f6b96919 100644 --- a/drivers/net/ethernet/intel/ice/ice_nvm.h +++ b/drivers/net/ethernet/intel/ice/ice_nvm.h @@ -4,8 +4,12 @@ #ifndef _ICE_NVM_H_ #define _ICE_NVM_H_ +enum ice_status +ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access); +void ice_release_nvm(struct ice_hw *hw); enum ice_status ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data, bool read_shadow_ram); +enum ice_status ice_init_nvm(struct ice_hw *hw); enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data); #endif /* _ICE_NVM_H_ */ From patchwork Fri Feb 14 23:22:03 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238403 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Yt5hcNz9s29 for ; Sat, 15 Feb 2020 10:22:58 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728218AbgBNXWa (ORCPT ); Fri, 14 Feb 2020 18:22:30 -0500 Received: from mga02.intel.com ([134.134.136.20]:41443 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728146AbgBNXW2 (ORCPT ); Fri, 14 Feb 2020 18:22:28 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:26 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629277" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:26 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 04/22] ice: enable initial devlink support Date: Fri, 14 Feb 2020 15:22:03 -0800 Message-Id: <20200214232223.3442651-5-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Begin implementing support for the devlink interface with the ice driver. The pf structure is currently memory managed through devres, via a devm_alloc. To mimic this behavior, after allocating the devlink pointer, use devm_add_action to add a teardown action for releasing the devlink memory on exit. The ice hardware is a multi-function PCIe device. Thus, each physical function will get its own devlink instance. This means that each function will be treated independently, with its own parameters and configuration. This is done because the ice driver loads a separate instance for each function. Due to this, the implementation does not enable devlink to manage device-wide resources or configuration, as each physical function will be treated independently. This is done for simplicity, as managing a devlink instance across multiple driver instances would significantly increase the complexity for minimal gain. Signed-off-by: Jacob Keller --- drivers/net/ethernet/intel/Kconfig | 1 + drivers/net/ethernet/intel/ice/Makefile | 1 + drivers/net/ethernet/intel/ice/ice.h | 4 + drivers/net/ethernet/intel/ice/ice_devlink.c | 119 +++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_devlink.h | 14 +++ drivers/net/ethernet/intel/ice/ice_main.c | 19 ++- 6 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 drivers/net/ethernet/intel/ice/ice_devlink.c create mode 100644 drivers/net/ethernet/intel/ice/ice_devlink.h diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index 154e2e818ec6..ad34e4335df2 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig @@ -294,6 +294,7 @@ config ICE tristate "Intel(R) Ethernet Connection E800 Series Support" default n depends on PCI_MSI + select NET_DEVLINK ---help--- This driver supports Intel(R) Ethernet Connection E800 Series of devices. For more information on how to identify your adapter, go diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile index 59544b0fc086..e2502ff3229d 100644 --- a/drivers/net/ethernet/intel/ice/Makefile +++ b/drivers/net/ethernet/intel/ice/Makefile @@ -19,6 +19,7 @@ ice-y := ice_main.o \ ice_txrx.o \ ice_flex_pipe.o \ ice_flow.o \ + ice_devlink.o \ ice_ethtool.o ice-$(CONFIG_PCI_IOV) += ice_virtchnl_pf.o ice_sriov.o ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index cb10abb14e11..a195135f840f 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -36,6 +36,7 @@ #include #include #include +#include #include "ice_devids.h" #include "ice_type.h" #include "ice_txrx.h" @@ -346,6 +347,9 @@ enum ice_pf_flags { struct ice_pf { struct pci_dev *pdev; + /* devlink port data */ + struct devlink_port devlink_port; + /* OS reserved IRQ details */ struct msix_entry *msix_entries; struct ice_res_tracker *irq_tracker; diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c new file mode 100644 index 000000000000..2a72857c4b26 --- /dev/null +++ b/drivers/net/ethernet/intel/ice/ice_devlink.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2019, Intel Corporation. */ + +#include "ice.h" +#include "ice_devlink.h" + +const struct devlink_ops ice_devlink_ops = { +}; + +static void ice_devlink_free(void *devlink_ptr) +{ + devlink_free((struct devlink *)devlink_ptr); +} + +/** + * ice_allocate_pf - Allocate devlink and return PF structure pointer + * @dev: the device to allocate for + * + * Allocate a devlink instance for this device and return the private area as + * the PF structure. The devlink memory is kept track of through devres by + * adding an action to remove it when unwinding. + */ +struct ice_pf *ice_allocate_pf(struct device *dev) +{ + struct devlink *devlink; + + devlink = devlink_alloc(&ice_devlink_ops, sizeof(struct ice_pf)); + if (!devlink) + return NULL; + + /* Add an action to teardown the devlink when unwinding the driver */ + if (devm_add_action(dev, ice_devlink_free, devlink)) { + devlink_free(devlink); + return NULL; + } + + return devlink_priv(devlink); +} + +/** + * ice_devlink_register - Register devlink interface for this PF + * @pf: the PF to register the devlink for. + * + * Register the devlink instance associated with this physical function. + * + * @returns zero on success or an error code on failure. + */ +int ice_devlink_register(struct ice_pf *pf) +{ + struct devlink *devlink = priv_to_devlink(pf); + struct device *dev = ice_pf_to_dev(pf); + int err; + + err = devlink_register(devlink, dev); + if (err) { + dev_err(dev, "devlink registration failed: %d\n", err); + return err; + } + + return 0; +} + +/** + * ice_devlink_unregister - Unregister devlink resources for this PF. + * @pf: the PF structure to cleanup + * + * Releases resources used by devlink and cleans up associated memory. + */ +void ice_devlink_unregister(struct ice_pf *pf) +{ + devlink_unregister(priv_to_devlink(pf)); +} + +/** + * ice_devlink_create_port - Create a devlink port for this PF + * @pf: the PF to create a port for + * + * Create and register a devlink_port for this PF. Note that although each + * physical function is connected to a separate devlink instance, the port + * will still be numbered according to the physical function id. + * + * @returns zero on success or an error code on failure. + */ +int ice_devlink_create_port(struct ice_pf *pf) +{ + struct devlink *devlink = priv_to_devlink(pf); + struct ice_vsi *vsi = ice_get_main_vsi(pf); + struct device *dev = ice_pf_to_dev(pf); + int err; + + if (!vsi) { + dev_err(dev, "%s: unable to find main VSI\n", __func__); + return -EIO; + } + + devlink_port_attrs_set(&pf->devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL, + pf->hw.pf_id, false, 0, NULL, 0); + err = devlink_port_register(devlink, &pf->devlink_port, pf->hw.pf_id); + if (err) { + dev_err(dev, "devlink_port_register failed: %d\n", err); + return err; + } + if (vsi->netdev) + devlink_port_type_eth_set(&pf->devlink_port, vsi->netdev); + + return 0; +} + +/** + * ice_devlink_destroy_port - Destroy the devlink_port for this PF + * @pf: the PF to cleanup + * + * Unregisters the devlink_port structure associated with this PF. + */ +void ice_devlink_destroy_port(struct ice_pf *pf) +{ + devlink_port_type_clear(&pf->devlink_port); + devlink_port_unregister(&pf->devlink_port); +} diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.h b/drivers/net/ethernet/intel/ice/ice_devlink.h new file mode 100644 index 000000000000..f94dc93c24c5 --- /dev/null +++ b/drivers/net/ethernet/intel/ice/ice_devlink.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2019, Intel Corporation. */ + +#ifndef _ICE_DEVLINK_H_ +#define _ICE_DEVLINK_H_ + +struct ice_pf *ice_allocate_pf(struct device *dev); + +int ice_devlink_register(struct ice_pf *pf); +void ice_devlink_unregister(struct ice_pf *pf); +int ice_devlink_create_port(struct ice_pf *pf); +void ice_devlink_destroy_port(struct ice_pf *pf); + +#endif /* _ICE_DEVLINK_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 5ef28052c0f8..f2cca810977d 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -10,6 +10,7 @@ #include "ice_lib.h" #include "ice_dcb_lib.h" #include "ice_dcb_nl.h" +#include "ice_devlink.h" #define DRV_VERSION_MAJOR 0 #define DRV_VERSION_MINOR 8 @@ -3166,7 +3167,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) return err; } - pf = devm_kzalloc(dev, sizeof(*pf), GFP_KERNEL); + pf = ice_allocate_pf(dev); if (!pf) return -ENOMEM; @@ -3204,6 +3205,12 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M); + err = ice_devlink_register(pf); + if (err) { + dev_err(dev, "ice_devlink_register failed: %d\n", err); + goto err_exit_unroll; + } + #ifndef CONFIG_DYNAMIC_DEBUG if (debug < -1) hw->debug_mask = debug; @@ -3295,6 +3302,11 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) goto err_alloc_sw_unroll; } + err = ice_devlink_create_port(pf); + if (err) + goto err_alloc_sw_unroll; + + clear_bit(__ICE_SERVICE_DIS, pf->state); /* tell the firmware we are up */ @@ -3336,6 +3348,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) return 0; err_alloc_sw_unroll: + ice_devlink_destroy_port(pf); set_bit(__ICE_SERVICE_DIS, pf->state); set_bit(__ICE_DOWN, pf->state); devm_kfree(dev, pf->first_sw); @@ -3348,6 +3361,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) ice_deinit_pf(pf); ice_deinit_hw(hw); err_exit_unroll: + ice_devlink_unregister(pf); pci_disable_pcie_error_reporting(pdev); return err; } @@ -3375,6 +3389,7 @@ static void ice_remove(struct pci_dev *pdev) if (test_bit(ICE_FLAG_SRIOV_ENA, pf->flags)) ice_free_vfs(pf); + ice_devlink_destroy_port(pf); ice_vsi_release_all(pf); ice_free_irq_msix_misc(pf); ice_for_each_vsi(pf, i) { @@ -3384,6 +3399,8 @@ static void ice_remove(struct pci_dev *pdev) } ice_deinit_pf(pf); ice_deinit_hw(&pf->hw); + ice_devlink_unregister(pf); + /* Issue a PFR as part of the prescribed driver unload flow. Do not * do it via ice_schedule_reset() since there is no need to rebuild * and the service task is already stopped. From patchwork Fri Feb 14 23:22:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238411 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Z93w1jz9s29 for ; Sat, 15 Feb 2020 10:23:13 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728331AbgBNXXJ (ORCPT ); Fri, 14 Feb 2020 18:23:09 -0500 Received: from mga02.intel.com ([134.134.136.20]:41445 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728173AbgBNXW2 (ORCPT ); Fri, 14 Feb 2020 18:22:28 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:27 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629280" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:26 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 05/22] ice: rename variables used for Option ROM version Date: Fri, 14 Feb 2020 15:22:04 -0800 Message-Id: <20200214232223.3442651-6-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The function ice_get_nvm_version reports data for both the NVM map version and the version of the combined Option ROM. The version data for the option ROM uses variables with the prefix "oem". This causes confusion as it makes it difficult for a reviewer to understand what the version actually represents. Rename the variables to use the prefix "orom", and update the code comments to mention that this is the combined Option ROM version. This helps the code clarify what the version actually represents. Signed-off-by: Jacob Keller --- drivers/net/ethernet/intel/ice/ice_common.c | 19 ++++++++++--------- drivers/net/ethernet/intel/ice/ice_common.h | 4 ++-- drivers/net/ethernet/intel/ice/ice_ethtool.c | 8 ++++---- drivers/net/ethernet/intel/ice/ice_nvm.c | 16 ++++++++-------- drivers/net/ethernet/intel/ice/ice_type.h | 16 ++++++++-------- 5 files changed, 32 insertions(+), 31 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 04d5db0a25bf..a74532520112 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -617,22 +617,23 @@ static void ice_get_itr_intrl_gran(struct ice_hw *hw) /** * ice_get_nvm_version - get cached NVM version data * @hw: pointer to the hardware structure - * @oem_ver: 8 bit NVM version - * @oem_build: 16 bit NVM build number - * @oem_patch: 8 NVM patch number + * @orom_ver: 8 bit version of combined Option ROM + * @orom_build: 16 bit build number of combined Option ROM + * @orom_patch: 8 bit patch level of combined Option ROM * @ver_hi: high 16 bits of the NVM version * @ver_lo: low 16 bits of the NVM version */ void -ice_get_nvm_version(struct ice_hw *hw, u8 *oem_ver, u16 *oem_build, - u8 *oem_patch, u8 *ver_hi, u8 *ver_lo) +ice_get_nvm_version(struct ice_hw *hw, u8 *orom_ver, u16 *orom_build, + u8 *orom_patch, u8 *ver_hi, u8 *ver_lo) { struct ice_nvm_info *nvm = &hw->nvm; - *oem_ver = (u8)((nvm->oem_ver & ICE_OEM_VER_MASK) >> ICE_OEM_VER_SHIFT); - *oem_patch = (u8)(nvm->oem_ver & ICE_OEM_VER_PATCH_MASK); - *oem_build = (u16)((nvm->oem_ver & ICE_OEM_VER_BUILD_MASK) >> - ICE_OEM_VER_BUILD_SHIFT); + *orom_ver = (u8)((nvm->orom_ver & ICE_OROM_VER_MASK) >> + ICE_OROM_VER_SHIFT); + *orom_patch = (u8)(nvm->orom_ver & ICE_OROM_VER_PATCH_MASK); + *orom_build = (u16)((nvm->orom_ver & ICE_OROM_VER_BUILD_MASK) >> + ICE_OROM_VER_BUILD_SHIFT); *ver_hi = (nvm->ver & ICE_NVM_VER_HI_MASK) >> ICE_NVM_VER_HI_SHIFT; *ver_lo = (nvm->ver & ICE_NVM_VER_LO_MASK) >> ICE_NVM_VER_LO_SHIFT; } diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index 9d5e86c9f886..0f9aa1986cab 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -151,8 +151,8 @@ void ice_stat_update32(struct ice_hw *hw, u32 reg, bool prev_stat_loaded, u64 *prev_stat, u64 *cur_stat); void -ice_get_nvm_version(struct ice_hw *hw, u8 *oem_ver, u16 *oem_build, - u8 *oem_patch, u8 *ver_hi, u8 *ver_lo); +ice_get_nvm_version(struct ice_hw *hw, u8 *orom_ver, u16 *orom_build, + u8 *orom_patch, u8 *ver_hi, u8 *ver_lo); enum ice_status ice_sched_query_elem(struct ice_hw *hw, u32 node_teid, struct ice_aqc_get_elem *buf); diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 223e8e707dcb..af5e5d6fc29c 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -166,11 +166,11 @@ static void ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) { struct ice_netdev_priv *np = netdev_priv(netdev); - u8 oem_ver, oem_patch, nvm_ver_hi, nvm_ver_lo; + u8 orom_ver, orom_patch, nvm_ver_hi, nvm_ver_lo; struct ice_vsi *vsi = np->vsi; struct ice_pf *pf = vsi->back; struct ice_hw *hw = &pf->hw; - u16 oem_build; + u16 orom_build; strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver)); strlcpy(drvinfo->version, ice_drv_ver, sizeof(drvinfo->version)); @@ -178,11 +178,11 @@ ice_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) /* Display NVM version (from which the firmware version can be * determined) which contains more pertinent information. */ - ice_get_nvm_version(hw, &oem_ver, &oem_build, &oem_patch, + ice_get_nvm_version(hw, &orom_ver, &orom_build, &orom_patch, &nvm_ver_hi, &nvm_ver_lo); snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%x.%02x 0x%x %d.%d.%d", nvm_ver_hi, nvm_ver_lo, - hw->nvm.eetrack, oem_ver, oem_build, oem_patch); + hw->nvm.eetrack, orom_ver, orom_build, orom_patch); strlcpy(drvinfo->bus_info, pci_name(pf->pdev), sizeof(drvinfo->bus_info)); diff --git a/drivers/net/ethernet/intel/ice/ice_nvm.c b/drivers/net/ethernet/intel/ice/ice_nvm.c index aaf5fd064725..7d5f2a6296c9 100644 --- a/drivers/net/ethernet/intel/ice/ice_nvm.c +++ b/drivers/net/ethernet/intel/ice/ice_nvm.c @@ -195,7 +195,7 @@ enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data) */ enum ice_status ice_init_nvm(struct ice_hw *hw) { - u16 oem_hi, oem_lo, boot_cfg_tlv, boot_cfg_tlv_len; + u16 orom_hi, orom_lo, boot_cfg_tlv, boot_cfg_tlv_len; struct ice_nvm_info *nvm = &hw->nvm; u16 eetrack_lo, eetrack_hi; enum ice_status status; @@ -272,21 +272,21 @@ enum ice_status ice_init_nvm(struct ice_hw *hw) return ICE_ERR_INVAL_SIZE; } - status = ice_read_sr_word(hw, (boot_cfg_tlv + ICE_NVM_OEM_VER_OFF), - &oem_hi); + status = ice_read_sr_word(hw, (boot_cfg_tlv + ICE_NVM_OROM_VER_OFF), + &orom_hi); if (status) { - ice_debug(hw, ICE_DBG_INIT, "Failed to read OEM_VER hi.\n"); + ice_debug(hw, ICE_DBG_INIT, "Failed to read OROM_VER hi.\n"); return status; } - status = ice_read_sr_word(hw, (boot_cfg_tlv + ICE_NVM_OEM_VER_OFF + 1), - &oem_lo); + status = ice_read_sr_word(hw, (boot_cfg_tlv + ICE_NVM_OROM_VER_OFF + 1), + &orom_lo); if (status) { - ice_debug(hw, ICE_DBG_INIT, "Failed to read OEM_VER lo.\n"); + ice_debug(hw, ICE_DBG_INIT, "Failed to read OROM_VER lo.\n"); return status; } - nvm->oem_ver = ((u32)oem_hi << 16) | oem_lo; + nvm->orom_ver = ((u32)orom_hi << 16) | orom_lo; return 0; } diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index db0ef6ba907f..1d9420cd53b1 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -242,7 +242,7 @@ struct ice_fc_info { /* NVM Information */ struct ice_nvm_info { u32 eetrack; /* NVM data version */ - u32 oem_ver; /* OEM version info */ + u32 orom_ver; /* Combined Option ROM version info */ u16 sr_words; /* Shadow RAM size in words */ u16 ver; /* NVM package version */ u8 blank_nvm_mode; /* is NVM empty (no FW present) */ @@ -626,7 +626,7 @@ struct ice_hw_port_stats { /* Checksum and Shadow RAM pointers */ #define ICE_SR_BOOT_CFG_PTR 0x132 -#define ICE_NVM_OEM_VER_OFF 0x02 +#define ICE_NVM_OROM_VER_OFF 0x02 #define ICE_SR_NVM_DEV_STARTER_VER 0x18 #define ICE_SR_NVM_EETRACK_LO 0x2D #define ICE_SR_NVM_EETRACK_HI 0x2E @@ -634,12 +634,12 @@ struct ice_hw_port_stats { #define ICE_NVM_VER_LO_MASK (0xff << ICE_NVM_VER_LO_SHIFT) #define ICE_NVM_VER_HI_SHIFT 12 #define ICE_NVM_VER_HI_MASK (0xf << ICE_NVM_VER_HI_SHIFT) -#define ICE_OEM_VER_PATCH_SHIFT 0 -#define ICE_OEM_VER_PATCH_MASK (0xff << ICE_OEM_VER_PATCH_SHIFT) -#define ICE_OEM_VER_BUILD_SHIFT 8 -#define ICE_OEM_VER_BUILD_MASK (0xffff << ICE_OEM_VER_BUILD_SHIFT) -#define ICE_OEM_VER_SHIFT 24 -#define ICE_OEM_VER_MASK (0xff << ICE_OEM_VER_SHIFT) +#define ICE_OROM_VER_PATCH_SHIFT 0 +#define ICE_OROM_VER_PATCH_MASK (0xff << ICE_OROM_VER_PATCH_SHIFT) +#define ICE_OROM_VER_BUILD_SHIFT 8 +#define ICE_OROM_VER_BUILD_MASK (0xffff << ICE_OROM_VER_BUILD_SHIFT) +#define ICE_OROM_VER_SHIFT 24 +#define ICE_OROM_VER_MASK (0xff << ICE_OROM_VER_SHIFT) #define ICE_SR_PFA_PTR 0x40 #define ICE_SR_SECTOR_SIZE_IN_WORDS 0x800 #define ICE_SR_WORDS_IN_1KB 512 From patchwork Fri Feb 14 23:22:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238390 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8YL2syGz9s29 for ; Sat, 15 Feb 2020 10:22:30 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728196AbgBNXW3 (ORCPT ); Fri, 14 Feb 2020 18:22:29 -0500 Received: from mga17.intel.com ([192.55.52.151]:1652 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727860AbgBNXW1 (ORCPT ); Fri, 14 Feb 2020 18:22:27 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:27 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629284" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:26 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 06/22] ice: add basic handler for devlink .info_get Date: Fri, 14 Feb 2020 15:22:05 -0800 Message-Id: <20200214232223.3442651-7-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The devlink .info_get callback allows the driver to report detailed version information. The following devlink versions are reported with this initial implementation: "fw.mgmt" -> The version of the firmware that controls PHY, link, etc "fw.mgmt.api" -> API version of interface exposed over the AdminQ "fw.mgmt.bundle" -> Unique identifier for the firmware bundle "fw.undi.orom" -> Version of the Option ROM containing the UEFI driver "nvm.psid" -> Version of the format for the NVM parameter set "nvm.bundle" -> Unique identifier for the combined NVM image With this, devlink can now report at least the same information as reported by the older ethtool interface. Each section of the "firmware-version" is also reported independently so that it is easier to understand the meaning. Signed-off-by: Jacob Keller --- Documentation/networking/devlink/ice.rst | 55 +++++++++++++ Documentation/networking/devlink/index.rst | 1 + drivers/net/ethernet/intel/ice/ice_devlink.c | 81 ++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 Documentation/networking/devlink/ice.rst diff --git a/Documentation/networking/devlink/ice.rst b/Documentation/networking/devlink/ice.rst new file mode 100644 index 000000000000..5545e708f18f --- /dev/null +++ b/Documentation/networking/devlink/ice.rst @@ -0,0 +1,55 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=================== +ice devlink support +=================== + +This document describes the devlink features implemented by the ``ice`` +device driver. + +Info versions +============= + +The ``ice`` driver reports the following versions + +.. list-table:: devlink info versions implemented + :widths: 5 5 5 90 + + * - Name + - Type + - Example + - Description + * - ``fw.mgmt`` + - running + - 1.16.10 + - 3-digit version number of the management firmware that controls the + PHY, link, etc. + * - ``fw.mgmt.api`` + - running + - 1.5 + - 2-digit version number of the API exported over the AdminQ by the + management firmware. Used by the driver to identify what commands + are supported. + * - ``fw.mgmt.bundle`` + - running + - 0xecabd066 + - Unique identifier of the management firmware build. + * - ``fw.undi.orom`` + - running + - 1.2186.0 + - Version of the Option ROM containing the UEFI driver. The version is + reported in ``major.minor.patch`` format. The major version is + incremented whenever a major breaking change occurs, or when the + minor version would overflow. The minor version is incremented for + non-breaking changes and reset to 1 when the major version is + incremented. The patch version is normally 0 but is incremented when + a fix is delivered as a patch against an older base Option ROM. + * - ``nvm.psid`` + - running + - 0.50 + - Version describing the format of the NVM parameter set. + * - ``nvm.bundle`` + - running + - 0x80001709 + - Unique identifier of the NVM image contents, also known as the + EETRACK id. diff --git a/Documentation/networking/devlink/index.rst b/Documentation/networking/devlink/index.rst index 087ff54d53fc..272509cd9215 100644 --- a/Documentation/networking/devlink/index.rst +++ b/Documentation/networking/devlink/index.rst @@ -32,6 +32,7 @@ parameters, info versions, and other features it supports. bnxt ionic + ice mlx4 mlx5 mlxsw diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c index 2a72857c4b26..f834025d58aa 100644 --- a/drivers/net/ethernet/intel/ice/ice_devlink.c +++ b/drivers/net/ethernet/intel/ice/ice_devlink.c @@ -2,9 +2,90 @@ /* Copyright (c) 2019, Intel Corporation. */ #include "ice.h" +#include "ice_lib.h" #include "ice_devlink.h" +/** + * ice_devlink_info_get - .info_get devlink handler + * @devlink: devlink instance structure + * @req: the devlink info request + * @extack: extended netdev ack structure + * + * Callback for the devlink .info_get operation. Reports information about the + * device. + * + * @returns zero on success or an error code on failure. + */ +static int ice_devlink_info_get(struct devlink *devlink, + struct devlink_info_req *req, + struct netlink_ext_ack *extack) +{ + u8 orom_maj, orom_patch, nvm_ver_hi, nvm_ver_lo; + struct ice_pf *pf = devlink_priv(devlink); + struct ice_hw *hw = &pf->hw; + u16 orom_min; + char buf[32]; + int err; + + ice_get_nvm_version(hw, &orom_maj, &orom_min, &orom_patch, &nvm_ver_hi, + &nvm_ver_lo); + + err = devlink_info_driver_name_put(req, KBUILD_MODNAME); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Unable to set driver name"); + return err; + } + + snprintf(buf, sizeof(buf), "%u.%u.%u", hw->fw_maj_ver, hw->fw_min_ver, + hw->fw_patch); + err = devlink_info_version_running_put(req, + DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, + buf); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Unable to set fw version data"); + return err; + } + + snprintf(buf, sizeof(buf), "%u.%u", hw->api_maj_ver, hw->api_min_ver); + err = devlink_info_version_running_put(req, "fw.mgmt.api", buf); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Unable to set mgmt fw API data"); + return err; + } + + snprintf(buf, sizeof(buf), "0x%08x", hw->fw_build); + err = devlink_info_version_running_put(req, "fw.mgmt.bundle", buf); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Unable to set fw bundle data"); + return err; + } + + snprintf(buf, sizeof(buf), "%u.%u.%u", orom_maj, orom_min, orom_patch); + err = devlink_info_version_running_put(req, "fw.undi.orom", buf); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Unable to set Option ROM version"); + return err; + } + + snprintf(buf, sizeof(buf), "%x.%02x", nvm_ver_hi, nvm_ver_lo); + err = devlink_info_version_running_put(req, "nvm.psid", buf); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Unable to set NVM parameter set version data"); + return err; + } + + snprintf(buf, sizeof(buf), "0x%0X", hw->nvm.eetrack); + err = devlink_info_version_running_put(req, "nvm.bundle", buf); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Unable to set NVM bundle data"); + return err; + } + + return 0; +} + const struct devlink_ops ice_devlink_ops = { + .info_get = ice_devlink_info_get, }; static void ice_devlink_free(void *devlink_ptr) From patchwork Fri Feb 14 23:22:06 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238401 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Yq4kzyz9s29 for ; Sat, 15 Feb 2020 10:22:55 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728225AbgBNXWb (ORCPT ); Fri, 14 Feb 2020 18:22:31 -0500 Received: from mga17.intel.com ([192.55.52.151]:1652 "EHLO mga17.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728143AbgBNXW2 (ORCPT ); Fri, 14 Feb 2020 18:22:28 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga107.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:27 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629287" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:26 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 07/22] ice: add board identifier info to devlink .info_get Date: Fri, 14 Feb 2020 15:22:06 -0800 Message-Id: <20200214232223.3442651-8-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Export a unique board identifier using "board.id" for devlink's .info_get command. Obtain this by reading the NVM for the PBA identification string. Signed-off-by: Jacob Keller --- Documentation/networking/devlink/ice.rst | 4 + drivers/net/ethernet/intel/ice/ice_common.c | 66 ---------- drivers/net/ethernet/intel/ice/ice_common.h | 3 - drivers/net/ethernet/intel/ice/ice_devlink.c | 15 +++ drivers/net/ethernet/intel/ice/ice_nvm.c | 125 +++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_nvm.h | 5 + drivers/net/ethernet/intel/ice/ice_type.h | 1 + 7 files changed, 150 insertions(+), 69 deletions(-) diff --git a/Documentation/networking/devlink/ice.rst b/Documentation/networking/devlink/ice.rst index 5545e708f18f..10ec6c1900b0 100644 --- a/Documentation/networking/devlink/ice.rst +++ b/Documentation/networking/devlink/ice.rst @@ -19,6 +19,10 @@ The ``ice`` driver reports the following versions - Type - Example - Description + * - ``board.id`` + - fixed + - K65390-000 + - The Product Board Assembly (PBA) identifier of the board. * - ``fw.mgmt`` - running - 1.16.10 diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index a74532520112..2ecf8bec795b 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -958,72 +958,6 @@ enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req) return ice_check_reset(hw); } -/** - * ice_get_pfa_module_tlv - Reads sub module TLV from NVM PFA - * @hw: pointer to hardware structure - * @module_tlv: pointer to module TLV to return - * @module_tlv_len: pointer to module TLV length to return - * @module_type: module type requested - * - * Finds the requested sub module TLV type from the Preserved Field - * Area (PFA) and returns the TLV pointer and length. The caller can - * use these to read the variable length TLV value. - */ -enum ice_status -ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len, - u16 module_type) -{ - enum ice_status status; - u16 pfa_len, pfa_ptr; - u16 next_tlv; - - status = ice_read_sr_word(hw, ICE_SR_PFA_PTR, &pfa_ptr); - if (status) { - ice_debug(hw, ICE_DBG_INIT, "Preserved Field Array pointer.\n"); - return status; - } - status = ice_read_sr_word(hw, pfa_ptr, &pfa_len); - if (status) { - ice_debug(hw, ICE_DBG_INIT, "Failed to read PFA length.\n"); - return status; - } - /* Starting with first TLV after PFA length, iterate through the list - * of TLVs to find the requested one. - */ - next_tlv = pfa_ptr + 1; - while (next_tlv < pfa_ptr + pfa_len) { - u16 tlv_sub_module_type; - u16 tlv_len; - - /* Read TLV type */ - status = ice_read_sr_word(hw, next_tlv, &tlv_sub_module_type); - if (status) { - ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV type.\n"); - break; - } - /* Read TLV length */ - status = ice_read_sr_word(hw, next_tlv + 1, &tlv_len); - if (status) { - ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV length.\n"); - break; - } - if (tlv_sub_module_type == module_type) { - if (tlv_len) { - *module_tlv = next_tlv; - *module_tlv_len = tlv_len; - return 0; - } - return ICE_ERR_INVAL_SIZE; - } - /* Check next TLV, i.e. current TLV pointer + length + 2 words - * (for current TLV's type and length) - */ - next_tlv = next_tlv + tlv_len + 2; - } - /* Module does not exist */ - return ICE_ERR_DOES_NOT_EXIST; -} - /** * ice_copy_rxq_ctx_to_hw * @hw: pointer to the hardware structure diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index 0f9aa1986cab..8903e0aa42c5 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -15,9 +15,6 @@ enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw); enum ice_status ice_init_hw(struct ice_hw *hw); void ice_deinit_hw(struct ice_hw *hw); -enum ice_status -ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len, - u16 module_type); enum ice_status ice_check_reset(struct ice_hw *hw); enum ice_status ice_reset(struct ice_hw *hw, enum ice_reset_req req); enum ice_status ice_create_all_ctrlq(struct ice_hw *hw); diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c index f834025d58aa..1f755b98d785 100644 --- a/drivers/net/ethernet/intel/ice/ice_devlink.c +++ b/drivers/net/ethernet/intel/ice/ice_devlink.c @@ -23,6 +23,7 @@ static int ice_devlink_info_get(struct devlink *devlink, u8 orom_maj, orom_patch, nvm_ver_hi, nvm_ver_lo; struct ice_pf *pf = devlink_priv(devlink); struct ice_hw *hw = &pf->hw; + enum ice_status status; u16 orom_min; char buf[32]; int err; @@ -36,6 +37,20 @@ static int ice_devlink_info_get(struct devlink *devlink, return err; } + status = ice_read_pba_string(hw, buf, sizeof(buf)); + if (status) { + NL_SET_ERR_MSG_MOD(extack, "Unable to obtain PBA string"); + return -EIO; + } + + err = devlink_info_version_fixed_put(req, + DEVLINK_INFO_VERSION_GENERIC_BOARD_ID, + buf); + if (err) { + NL_SET_ERR_MSG_MOD(extack, "Unable to set board identifier"); + return err; + } + snprintf(buf, sizeof(buf), "%u.%u.%u", hw->fw_maj_ver, hw->fw_min_ver, hw->fw_patch); err = devlink_info_version_running_put(req, diff --git a/drivers/net/ethernet/intel/ice/ice_nvm.c b/drivers/net/ethernet/intel/ice/ice_nvm.c index 7d5f2a6296c9..d964311bdd66 100644 --- a/drivers/net/ethernet/intel/ice/ice_nvm.c +++ b/drivers/net/ethernet/intel/ice/ice_nvm.c @@ -186,6 +186,131 @@ enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data) return status; } +/** + * ice_get_pfa_module_tlv - Reads sub module TLV from NVM PFA + * @hw: pointer to hardware structure + * @module_tlv: pointer to module TLV to return + * @module_tlv_len: pointer to module TLV length to return + * @module_type: module type requested + * + * Finds the requested sub module TLV type from the Preserved Field + * Area (PFA) and returns the TLV pointer and length. The caller can + * use these to read the variable length TLV value. + */ +enum ice_status +ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len, + u16 module_type) +{ + enum ice_status status; + u16 pfa_len, pfa_ptr; + u16 next_tlv; + + status = ice_read_sr_word(hw, ICE_SR_PFA_PTR, &pfa_ptr); + if (status) { + ice_debug(hw, ICE_DBG_INIT, "Preserved Field Array pointer.\n"); + return status; + } + status = ice_read_sr_word(hw, pfa_ptr, &pfa_len); + if (status) { + ice_debug(hw, ICE_DBG_INIT, "Failed to read PFA length.\n"); + return status; + } + /* Starting with first TLV after PFA length, iterate through the list + * of TLVs to find the requested one. + */ + next_tlv = pfa_ptr + 1; + while (next_tlv < pfa_ptr + pfa_len) { + u16 tlv_sub_module_type; + u16 tlv_len; + + /* Read TLV type */ + status = ice_read_sr_word(hw, next_tlv, &tlv_sub_module_type); + if (status) { + ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV type.\n"); + break; + } + /* Read TLV length */ + status = ice_read_sr_word(hw, next_tlv + 1, &tlv_len); + if (status) { + ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV length.\n"); + break; + } + if (tlv_sub_module_type == module_type) { + if (tlv_len) { + *module_tlv = next_tlv; + *module_tlv_len = tlv_len; + return 0; + } + return ICE_ERR_INVAL_SIZE; + } + /* Check next TLV, i.e. current TLV pointer + length + 2 words + * (for current TLV's type and length) + */ + next_tlv = next_tlv + tlv_len + 2; + } + /* Module does not exist */ + return ICE_ERR_DOES_NOT_EXIST; +} + +/** + * ice_read_pba_string - Reads part number string from NVM + * @hw: pointer to hardware structure + * @pba_num: stores the part number string from the NVM + * @pba_num_size: part number string buffer length + * + * Reads the part number string from the NVM. + */ +enum ice_status +ice_read_pba_string(struct ice_hw *hw, u8 *pba_num, u32 pba_num_size) +{ + u16 pba_tlv, pba_tlv_len; + enum ice_status status; + u16 pba_word, pba_size; + u16 i; + + status = ice_get_pfa_module_tlv(hw, &pba_tlv, &pba_tlv_len, + ICE_SR_PBA_BLOCK_PTR); + if (status) { + ice_debug(hw, ICE_DBG_INIT, "Failed to read PBA Block TLV.\n"); + return status; + } + + /* pba_size is the next word */ + status = ice_read_sr_word(hw, (pba_tlv + 2), &pba_size); + if (status) { + ice_debug(hw, ICE_DBG_INIT, "Failed to read PBA Section size.\n"); + return status; + } + + if (pba_tlv_len < pba_size) { + ice_debug(hw, ICE_DBG_INIT, "Invalid PBA Block TLV size.\n"); + return ICE_ERR_INVAL_SIZE; + } + + /* Subtract one to get PBA word count (PBA Size word is included in + * total size) + */ + pba_size--; + if (pba_num_size < (((u32)pba_size * 2) + 1)) { + ice_debug(hw, ICE_DBG_INIT, "Buffer too small for PBA data.\n"); + return ICE_ERR_PARAM; + } + + for (i = 0; i < pba_size; i++) { + status = ice_read_sr_word(hw, (pba_tlv + 2 + 1) + i, &pba_word); + if (status) { + ice_debug(hw, ICE_DBG_INIT, "Failed to read PBA Block word %d.\n", i); + return status; + } + + pba_num[(i * 2)] = (pba_word >> 8) & 0xFF; + pba_num[(i * 2) + 1] = pba_word & 0xFF; + } + pba_num[(pba_size * 2)] = '\0'; + + return status; +} + /** * ice_init_nvm - initializes NVM setting * @hw: pointer to the HW struct diff --git a/drivers/net/ethernet/intel/ice/ice_nvm.h b/drivers/net/ethernet/intel/ice/ice_nvm.h index 7375f6b96919..999f273ba6ad 100644 --- a/drivers/net/ethernet/intel/ice/ice_nvm.h +++ b/drivers/net/ethernet/intel/ice/ice_nvm.h @@ -10,6 +10,11 @@ void ice_release_nvm(struct ice_hw *hw); enum ice_status ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data, bool read_shadow_ram); +enum ice_status +ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len, + u16 module_type); +enum ice_status +ice_read_pba_string(struct ice_hw *hw, u8 *pba_num, u32 pba_num_size); enum ice_status ice_init_nvm(struct ice_hw *hw); enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data); #endif /* _ICE_NVM_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index 1d9420cd53b1..12e0aa061260 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -627,6 +627,7 @@ struct ice_hw_port_stats { /* Checksum and Shadow RAM pointers */ #define ICE_SR_BOOT_CFG_PTR 0x132 #define ICE_NVM_OROM_VER_OFF 0x02 +#define ICE_SR_PBA_BLOCK_PTR 0x16 #define ICE_SR_NVM_DEV_STARTER_VER 0x18 #define ICE_SR_NVM_EETRACK_LO 0x2D #define ICE_SR_NVM_EETRACK_HI 0x2E From patchwork Fri Feb 14 23:22:07 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238410 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Z84999z9sPK for ; Sat, 15 Feb 2020 10:23:12 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728336AbgBNXXK (ORCPT ); Fri, 14 Feb 2020 18:23:10 -0500 Received: from mga02.intel.com ([134.134.136.20]:41443 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727458AbgBNXW2 (ORCPT ); Fri, 14 Feb 2020 18:22:28 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:27 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629290" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:27 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 08/22] devlink: prepare to support region operations Date: Fri, 14 Feb 2020 15:22:07 -0800 Message-Id: <20200214232223.3442651-9-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Modify the devlink region code in preparation for adding new operations on regions. Create a devlink_region_ops structure, and move the name pointer from within the devlink_region structure into the ops structure (similar to the devlink_health_reporter_ops). This prepares the regions to enable support of additional operations in the future such as requesting snapshots, or accessing the region directly without a snapshot. In order to re-use the constant strings in the mlx4 driver their declaration must be changed to 'const char * const' to ensure the compiler realizes that both the data and the pointer cannot change. Signed-off-by: Jacob Keller Reviewed-by: Jakub Kicinski Reviewed-by: Jiri Pirko --- drivers/net/ethernet/mellanox/mlx4/crdump.c | 16 +++++++++++---- drivers/net/netdevsim/dev.c | 6 +++++- include/net/devlink.h | 16 +++++++++++---- net/core/devlink.c | 22 ++++++++++----------- 4 files changed, 40 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/crdump.c b/drivers/net/ethernet/mellanox/mlx4/crdump.c index 64ed725aec28..cc2bf596c74b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/crdump.c +++ b/drivers/net/ethernet/mellanox/mlx4/crdump.c @@ -38,8 +38,16 @@ #define CR_ENABLE_BIT_OFFSET 0xF3F04 #define MAX_NUM_OF_DUMPS_TO_STORE (8) -static const char *region_cr_space_str = "cr-space"; -static const char *region_fw_health_str = "fw-health"; +static const char * const region_cr_space_str = "cr-space"; +static const char * const region_fw_health_str = "fw-health"; + +static const struct devlink_region_ops region_cr_space_ops = { + .name = region_cr_space_str, +}; + +static const struct devlink_region_ops region_fw_health_ops = { + .name = region_fw_health_str, +}; /* Set to true in case cr enable bit was set to true before crdump */ static bool crdump_enbale_bit_set; @@ -205,7 +213,7 @@ int mlx4_crdump_init(struct mlx4_dev *dev) /* Create cr-space region */ crdump->region_crspace = devlink_region_create(devlink, - region_cr_space_str, + ®ion_cr_space_ops, MAX_NUM_OF_DUMPS_TO_STORE, pci_resource_len(pdev, 0)); if (IS_ERR(crdump->region_crspace)) @@ -216,7 +224,7 @@ int mlx4_crdump_init(struct mlx4_dev *dev) /* Create fw-health region */ crdump->region_fw_health = devlink_region_create(devlink, - region_fw_health_str, + ®ion_fw_health_ops, MAX_NUM_OF_DUMPS_TO_STORE, HEALTH_BUFFER_SIZE); if (IS_ERR(crdump->region_fw_health)) diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index d7706a0346f2..3365de48ea9d 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -245,11 +245,15 @@ static void nsim_devlink_param_load_driverinit_values(struct devlink *devlink) #define NSIM_DEV_DUMMY_REGION_SNAPSHOT_MAX 16 +static const struct devlink_region_ops dummy_region_ops = { + .name = "dummy", +}; + static int nsim_dev_dummy_region_init(struct nsim_dev *nsim_dev, struct devlink *devlink) { nsim_dev->dummy_region = - devlink_region_create(devlink, "dummy", + devlink_region_create(devlink, &dummy_region_ops, NSIM_DEV_DUMMY_REGION_SNAPSHOT_MAX, NSIM_DEV_DUMMY_REGION_SIZE); return PTR_ERR_OR_ZERO(nsim_dev->dummy_region); diff --git a/include/net/devlink.h b/include/net/devlink.h index ce5cea428fdc..7012bda22aa8 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -495,6 +495,14 @@ struct devlink_info_req; typedef void devlink_snapshot_data_dest_t(const void *data); +/** + * struct devlink_region_ops - Region operations + * @name: region name + */ +struct devlink_region_ops { + const char *name; +}; + struct devlink_fmsg; struct devlink_health_reporter; @@ -949,10 +957,10 @@ void devlink_port_param_value_changed(struct devlink_port *devlink_port, u32 param_id); void devlink_param_value_str_fill(union devlink_param_value *dst_val, const char *src); -struct devlink_region *devlink_region_create(struct devlink *devlink, - const char *region_name, - u32 region_max_snapshots, - u64 region_size); +struct devlink_region * +devlink_region_create(struct devlink *devlink, + const struct devlink_region_ops *ops, + u32 region_max_snapshots, u64 region_size); void devlink_region_destroy(struct devlink_region *region); u32 devlink_region_snapshot_id_get(struct devlink *devlink); int devlink_region_snapshot_create(struct devlink_region *region, diff --git a/net/core/devlink.c b/net/core/devlink.c index 549ee56b7a21..4128fd1f604a 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -344,7 +344,7 @@ devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb, struct devlink_region { struct devlink *devlink; struct list_head list; - const char *name; + const struct devlink_region_ops *ops; struct list_head snapshot_list; u32 max_snapshots; u32 cur_snapshots; @@ -365,7 +365,7 @@ devlink_region_get_by_name(struct devlink *devlink, const char *region_name) struct devlink_region *region; list_for_each_entry(region, &devlink->region_list, list) - if (!strcmp(region->name, region_name)) + if (!strcmp(region->ops->name, region_name)) return region; return NULL; @@ -3687,7 +3687,7 @@ static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink, if (err) goto nla_put_failure; - err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->name); + err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name); if (err) goto nla_put_failure; @@ -3733,7 +3733,7 @@ static void devlink_nl_region_notify(struct devlink_region *region, goto out_cancel_msg; err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, - region->name); + region->ops->name); if (err) goto out_cancel_msg; @@ -7536,21 +7536,21 @@ EXPORT_SYMBOL_GPL(devlink_param_value_str_fill); * devlink_region_create - create a new address region * * @devlink: devlink - * @region_name: region name + * @ops: region operations and name * @region_max_snapshots: Maximum supported number of snapshots for region * @region_size: size of region */ -struct devlink_region *devlink_region_create(struct devlink *devlink, - const char *region_name, - u32 region_max_snapshots, - u64 region_size) +struct devlink_region * +devlink_region_create(struct devlink *devlink, + const struct devlink_region_ops *ops, + u32 region_max_snapshots, u64 region_size) { struct devlink_region *region; int err = 0; mutex_lock(&devlink->lock); - if (devlink_region_get_by_name(devlink, region_name)) { + if (devlink_region_get_by_name(devlink, ops->name)) { err = -EEXIST; goto unlock; } @@ -7563,7 +7563,7 @@ struct devlink_region *devlink_region_create(struct devlink *devlink, region->devlink = devlink; region->max_snapshots = region_max_snapshots; - region->name = region_name; + region->ops = ops; region->size = region_size; INIT_LIST_HEAD(®ion->snapshot_list); list_add_tail(®ion->list, &devlink->region_list); From patchwork Fri Feb 14 23:22:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238407 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Z161y6z9sPK for ; Sat, 15 Feb 2020 10:23:05 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728320AbgBNXXE (ORCPT ); Fri, 14 Feb 2020 18:23:04 -0500 Received: from mga02.intel.com ([134.134.136.20]:41443 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728208AbgBNXW3 (ORCPT ); Fri, 14 Feb 2020 18:22:29 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:27 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629293" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:27 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 09/22] devlink: convert snapshot destructor callback to region op Date: Fri, 14 Feb 2020 15:22:08 -0800 Message-Id: <20200214232223.3442651-10-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org It does not makes sense that two snapshots for a given region would use different destructors. Simplify snapshot creation by adding a .destructor op for regions. This operation will replace the data_destructor for the snapshot creation, and makes snapshot creation easier. Noticed-by: Jakub Kicinski Signed-off-by: Jacob Keller Reviewed-by: Jiri Pirko --- drivers/net/ethernet/mellanox/mlx4/crdump.c | 6 ++++-- drivers/net/netdevsim/dev.c | 3 ++- include/net/devlink.h | 7 +++---- net/core/devlink.c | 11 +++++------ 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/crdump.c b/drivers/net/ethernet/mellanox/mlx4/crdump.c index cc2bf596c74b..c3f90c0f9554 100644 --- a/drivers/net/ethernet/mellanox/mlx4/crdump.c +++ b/drivers/net/ethernet/mellanox/mlx4/crdump.c @@ -43,10 +43,12 @@ static const char * const region_fw_health_str = "fw-health"; static const struct devlink_region_ops region_cr_space_ops = { .name = region_cr_space_str, + .destructor = &kvfree, }; static const struct devlink_region_ops region_fw_health_ops = { .name = region_fw_health_str, + .destructor = &kvfree, }; /* Set to true in case cr enable bit was set to true before crdump */ @@ -107,7 +109,7 @@ static void mlx4_crdump_collect_crspace(struct mlx4_dev *dev, readl(cr_space + offset); err = devlink_region_snapshot_create(crdump->region_crspace, - crspace_data, id, &kvfree); + crspace_data, id); if (err) { kvfree(crspace_data); mlx4_warn(dev, "crdump: devlink create %s snapshot id %d err %d\n", @@ -146,7 +148,7 @@ static void mlx4_crdump_collect_fw_health(struct mlx4_dev *dev, readl(health_buf_start + offset); err = devlink_region_snapshot_create(crdump->region_fw_health, - health_data, id, &kvfree); + health_data, id); if (err) { kvfree(health_data); mlx4_warn(dev, "crdump: devlink create %s snapshot id %d err %d\n", diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 3365de48ea9d..5b1ba67fd4a0 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -55,7 +55,7 @@ static ssize_t nsim_dev_take_snapshot_write(struct file *file, id = devlink_region_snapshot_id_get(priv_to_devlink(nsim_dev)); err = devlink_region_snapshot_create(nsim_dev->dummy_region, - dummy_data, id, kfree); + dummy_data, id); if (err) { pr_err("Failed to create region snapshot\n"); kfree(dummy_data); @@ -247,6 +247,7 @@ static void nsim_devlink_param_load_driverinit_values(struct devlink *devlink) static const struct devlink_region_ops dummy_region_ops = { .name = "dummy", + .destructor = &kfree, }; static int nsim_dev_dummy_region_init(struct nsim_dev *nsim_dev, diff --git a/include/net/devlink.h b/include/net/devlink.h index 7012bda22aa8..437d3f51a5ab 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -493,14 +493,14 @@ enum devlink_param_generic_id { struct devlink_region; struct devlink_info_req; -typedef void devlink_snapshot_data_dest_t(const void *data); - /** * struct devlink_region_ops - Region operations * @name: region name + * @destructor: callback used to free snapshot memory when deleting */ struct devlink_region_ops { const char *name; + void (*destructor)(const void *data); }; struct devlink_fmsg; @@ -964,8 +964,7 @@ devlink_region_create(struct devlink *devlink, void devlink_region_destroy(struct devlink_region *region); u32 devlink_region_snapshot_id_get(struct devlink *devlink); int devlink_region_snapshot_create(struct devlink_region *region, - u8 *data, u32 snapshot_id, - devlink_snapshot_data_dest_t *data_destructor); + u8 *data, u32 snapshot_id); int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn); int devlink_info_driver_name_put(struct devlink_info_req *req, diff --git a/net/core/devlink.c b/net/core/devlink.c index 4128fd1f604a..7f9e98776434 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -354,7 +354,6 @@ struct devlink_region { struct devlink_snapshot { struct list_head list; struct devlink_region *region; - devlink_snapshot_data_dest_t *data_destructor; u8 *data; u32 id; }; @@ -3767,7 +3766,7 @@ static void devlink_region_snapshot_del(struct devlink_region *region, devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL); region->cur_snapshots--; list_del(&snapshot->list); - (*snapshot->data_destructor)(snapshot->data); + region->ops->destructor(snapshot->data); kfree(snapshot); } @@ -7548,6 +7547,9 @@ devlink_region_create(struct devlink *devlink, struct devlink_region *region; int err = 0; + if (WARN_ON(!ops) || WARN_ON(!ops->destructor)) + return ERR_PTR(-EINVAL); + mutex_lock(&devlink->lock); if (devlink_region_get_by_name(devlink, ops->name)) { @@ -7634,11 +7636,9 @@ EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get); * @region: devlink region of the snapshot * @data: snapshot data * @snapshot_id: snapshot id to be created - * @data_destructor: pointer to destructor function to free data */ int devlink_region_snapshot_create(struct devlink_region *region, - u8 *data, u32 snapshot_id, - devlink_snapshot_data_dest_t *data_destructor) + u8 *data, u32 snapshot_id) { struct devlink *devlink = region->devlink; struct devlink_snapshot *snapshot; @@ -7666,7 +7666,6 @@ int devlink_region_snapshot_create(struct devlink_region *region, snapshot->id = snapshot_id; snapshot->region = region; snapshot->data = data; - snapshot->data_destructor = data_destructor; list_add_tail(&snapshot->list, ®ion->snapshot_list); From patchwork Fri Feb 14 23:22:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238408 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Z329LKz9s29 for ; Sat, 15 Feb 2020 10:23:07 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728325AbgBNXXG (ORCPT ); Fri, 14 Feb 2020 18:23:06 -0500 Received: from mga02.intel.com ([134.134.136.20]:41445 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728204AbgBNXW3 (ORCPT ); Fri, 14 Feb 2020 18:22:29 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:27 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629297" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:27 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 10/22] devlink: trivial: fix tab in function documentation Date: Fri, 14 Feb 2020 15:22:09 -0800 Message-Id: <20200214232223.3442651-11-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The function documentation comment for devlink_region_snapshot_create included a literal tab character between 'future analyses' that was difficult to spot as it happened to only display as one space wide. Fix the comment to use a space here instead of a stray tab appearing in the middle of a sentence. Signed-off-by: Jacob Keller Reviewed-by: Jiri Pirko --- net/core/devlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/devlink.c b/net/core/devlink.c index 7f9e98776434..fef93f48028c 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -7629,7 +7629,7 @@ EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get); * devlink_region_snapshot_create - create a new snapshot * This will add a new snapshot of a region. The snapshot * will be stored on the region struct and can be accessed - * from devlink. This is useful for future analyses of snapshots. + * from devlink. This is useful for future analyses of snapshots. * Multiple snapshots can be created on a region. * The @snapshot_id should be obtained using the getter function. * From patchwork Fri Feb 14 23:22:10 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238392 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8YQ3b4sz9sPk for ; Sat, 15 Feb 2020 10:22:34 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728259AbgBNXWd (ORCPT ); Fri, 14 Feb 2020 18:22:33 -0500 Received: from mga02.intel.com ([134.134.136.20]:41449 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728211AbgBNXWa (ORCPT ); Fri, 14 Feb 2020 18:22:30 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:28 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629300" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:27 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 11/22] devlink: add functions to take snapshot while locked Date: Fri, 14 Feb 2020 15:22:10 -0800 Message-Id: <20200214232223.3442651-12-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org A future change is going to add a new devlink command to request a snapshot on demand. This function will want to call the devlink_region_snapshot_id_get and devlink_region_snapshot_create functions while already holding the devlink instance lock. Extract the logic of these two functions into static functions prefixed by `__` to indicate they are internal helper functions. Modify the original functions to be implemented in terms of the new locked functions. Signed-off-by: Jacob Keller Reviewed-by: Jiri Pirko --- net/core/devlink.c | 93 ++++++++++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 32 deletions(-) diff --git a/net/core/devlink.c b/net/core/devlink.c index fef93f48028c..0e94887713f4 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -3760,6 +3760,65 @@ static void devlink_nl_region_notify(struct devlink_region *region, nlmsg_free(msg); } +/** + * __devlink_region_snapshot_id_get - get snapshot ID + * @devlink: devlink instance + * + * Returns a new snapshot id. Must be called while holding the + * devlink instance lock. + */ +static u32 __devlink_region_snapshot_id_get(struct devlink *devlink) +{ + lockdep_assert_held(&devlink->lock); + return ++devlink->snapshot_id; +} + +/** + * __devlink_region_snapshot_create - create a new snapshot + * This will add a new snapshot of a region. The snapshot + * will be stored on the region struct and can be accessed + * from devlink. This is useful for future analyses of snapshots. + * Multiple snapshots can be created on a region. + * The @snapshot_id should be obtained using the getter function. + * + * Must be called only while holding the devlink instance lock. + * + * @region: devlink region of the snapshot + * @data: snapshot data + * @snapshot_id: snapshot id to be created + */ +static int +__devlink_region_snapshot_create(struct devlink_region *region, + u8 *data, u32 snapshot_id) +{ + struct devlink *devlink = region->devlink; + struct devlink_snapshot *snapshot; + + lockdep_assert_held(&devlink->lock); + + /* check if region can hold one more snapshot */ + if (region->cur_snapshots == region->max_snapshots) + return -ENOMEM; + + if (devlink_region_snapshot_get_by_id(region, snapshot_id)) + return -EEXIST; + + snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL); + if (!snapshot) + return -ENOMEM; + + snapshot->id = snapshot_id; + snapshot->region = region; + snapshot->data = data; + + list_add_tail(&snapshot->list, ®ion->snapshot_list); + + region->cur_snapshots++; + + devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW); + return 0; +} + static void devlink_region_snapshot_del(struct devlink_region *region, struct devlink_snapshot *snapshot) { @@ -7618,7 +7677,7 @@ u32 devlink_region_snapshot_id_get(struct devlink *devlink) u32 id; mutex_lock(&devlink->lock); - id = ++devlink->snapshot_id; + id = __devlink_region_snapshot_id_get(devlink); mutex_unlock(&devlink->lock); return id; @@ -7641,42 +7700,12 @@ int devlink_region_snapshot_create(struct devlink_region *region, u8 *data, u32 snapshot_id) { struct devlink *devlink = region->devlink; - struct devlink_snapshot *snapshot; int err; mutex_lock(&devlink->lock); - - /* check if region can hold one more snapshot */ - if (region->cur_snapshots == region->max_snapshots) { - err = -ENOMEM; - goto unlock; - } - - if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { - err = -EEXIST; - goto unlock; - } - - snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL); - if (!snapshot) { - err = -ENOMEM; - goto unlock; - } - - snapshot->id = snapshot_id; - snapshot->region = region; - snapshot->data = data; - - list_add_tail(&snapshot->list, ®ion->snapshot_list); - - region->cur_snapshots++; - - devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW); + err = __devlink_region_snapshot_create(region, data, snapshot_id); mutex_unlock(&devlink->lock); - return 0; -unlock: - mutex_unlock(&devlink->lock); return err; } EXPORT_SYMBOL_GPL(devlink_region_snapshot_create); From patchwork Fri Feb 14 23:22:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238409 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Z74nMbz9s29 for ; Sat, 15 Feb 2020 10:23:11 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728055AbgBNXXK (ORCPT ); Fri, 14 Feb 2020 18:23:10 -0500 Received: from mga12.intel.com ([192.55.52.136]:61912 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728176AbgBNXW2 (ORCPT ); Fri, 14 Feb 2020 18:22:28 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:28 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629304" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:27 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 12/22] devlink: convert snapshot id getter to return an error Date: Fri, 14 Feb 2020 15:22:11 -0800 Message-Id: <20200214232223.3442651-13-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Modify the devlink_snapshot_id_get function to return a signed value, enabling reporting an error on failure. This enables easily refactoring how IDs are generated and kept track of in the future. For now, just report ENOSPC once INT_MAX snapshot ids have been returned. Signed-off-by: Jacob Keller Reviewed-by: Jiri Pirko --- drivers/net/ethernet/mellanox/mlx4/crdump.c | 10 +++++++--- drivers/net/netdevsim/dev.c | 7 +++++-- include/net/devlink.h | 2 +- net/core/devlink.c | 16 +++++++++++----- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/crdump.c b/drivers/net/ethernet/mellanox/mlx4/crdump.c index c3f90c0f9554..723a66efdf32 100644 --- a/drivers/net/ethernet/mellanox/mlx4/crdump.c +++ b/drivers/net/ethernet/mellanox/mlx4/crdump.c @@ -169,7 +169,7 @@ int mlx4_crdump_collect(struct mlx4_dev *dev) struct pci_dev *pdev = dev->persist->pdev; unsigned long cr_res_size; u8 __iomem *cr_space; - u32 id; + int id; if (!dev->caps.health_buffer_addrs) { mlx4_info(dev, "crdump: FW doesn't support health buffer access, skipping\n"); @@ -189,10 +189,14 @@ int mlx4_crdump_collect(struct mlx4_dev *dev) return -ENODEV; } - crdump_enable_crspace_access(dev, cr_space); - /* Get the available snapshot ID for the dumps */ id = devlink_region_snapshot_id_get(devlink); + if (id < 0) { + mlx4_err(dev, "crdump: devlink get snapshot id err %d\n", id); + return id; + } + + crdump_enable_crspace_access(dev, cr_space); /* Try to capture dumps */ mlx4_crdump_collect_crspace(dev, cr_space, id); diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 5b1ba67fd4a0..e30bd94c3d52 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -44,8 +44,7 @@ static ssize_t nsim_dev_take_snapshot_write(struct file *file, { struct nsim_dev *nsim_dev = file->private_data; void *dummy_data; - int err; - u32 id; + int err, id; dummy_data = kmalloc(NSIM_DEV_DUMMY_REGION_SIZE, GFP_KERNEL); if (!dummy_data) @@ -54,6 +53,10 @@ static ssize_t nsim_dev_take_snapshot_write(struct file *file, get_random_bytes(dummy_data, NSIM_DEV_DUMMY_REGION_SIZE); id = devlink_region_snapshot_id_get(priv_to_devlink(nsim_dev)); + if (id < 0) { + pr_err("Failed to get snapshot id\n"); + return id; + } err = devlink_region_snapshot_create(nsim_dev->dummy_region, dummy_data, id); if (err) { diff --git a/include/net/devlink.h b/include/net/devlink.h index 437d3f51a5ab..3a7759355434 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -962,7 +962,7 @@ devlink_region_create(struct devlink *devlink, const struct devlink_region_ops *ops, u32 region_max_snapshots, u64 region_size); void devlink_region_destroy(struct devlink_region *region); -u32 devlink_region_snapshot_id_get(struct devlink *devlink); +int devlink_region_snapshot_id_get(struct devlink *devlink); int devlink_region_snapshot_create(struct devlink_region *region, u8 *data, u32 snapshot_id); int devlink_info_serial_number_put(struct devlink_info_req *req, diff --git a/net/core/devlink.c b/net/core/devlink.c index 0e94887713f4..da4e669f425b 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -3764,12 +3764,16 @@ static void devlink_nl_region_notify(struct devlink_region *region, * __devlink_region_snapshot_id_get - get snapshot ID * @devlink: devlink instance * - * Returns a new snapshot id. Must be called while holding the - * devlink instance lock. + * Returns a new snapshot id or a negative error code on failure. Must be + * called while holding the devlink instance lock. */ -static u32 __devlink_region_snapshot_id_get(struct devlink *devlink) +static int __devlink_region_snapshot_id_get(struct devlink *devlink) { lockdep_assert_held(&devlink->lock); + + if (devlink->snapshot_id >= INT_MAX) + return -ENOSPC; + return ++devlink->snapshot_id; } @@ -7670,11 +7674,13 @@ EXPORT_SYMBOL_GPL(devlink_region_destroy); * Driver should use the same id for multiple snapshots taken * on multiple regions at the same time/by the same trigger. * + * Returns a positive id or a negative error code on failure. + * * @devlink: devlink */ -u32 devlink_region_snapshot_id_get(struct devlink *devlink) +int devlink_region_snapshot_id_get(struct devlink *devlink) { - u32 id; + int id; mutex_lock(&devlink->lock); id = __devlink_region_snapshot_id_get(devlink); From patchwork Fri Feb 14 23:22:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238398 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Yk4PnSz9sPK for ; Sat, 15 Feb 2020 10:22:50 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728241AbgBNXWc (ORCPT ); Fri, 14 Feb 2020 18:22:32 -0500 Received: from mga12.intel.com ([192.55.52.136]:61912 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728202AbgBNXW3 (ORCPT ); Fri, 14 Feb 2020 18:22:29 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:28 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629307" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:27 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 13/22] devlink: track snapshot ids using an IDR and refcounts Date: Fri, 14 Feb 2020 15:22:12 -0800 Message-Id: <20200214232223.3442651-14-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org New snapshot ids are generated by calling a getter function. The same id may be used by multiple snapshots created at the same trigger event. Currently no effort is made to release any previously used snapshot ids. Replace the basic logic of using a single devlink integer for tracking ids with the IDR interface. snapshot IDs will be reference counted using a refcount stored in the IDR. First, ids are allocated using idr_alloc without a refcount (using the NULL pointer). Once the devlink_region_snapshot_create function is called, it will call the new __devlink_region_snapshot_id_ref(). This function will insert a new refcount or increment the pre-existing refcount. devlink_region_snapshot_destroy will call the new __devlink_region_snapshot_id_deref(), decrementing the reference count. Once there are no other references, the refcount will be removed from IDR. Signed-off-by: Jacob Keller --- include/net/devlink.h | 3 +- net/core/devlink.c | 141 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 138 insertions(+), 6 deletions(-) diff --git a/include/net/devlink.h b/include/net/devlink.h index 3a7759355434..3a5ff6bea143 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -17,6 +17,7 @@ #include #include #include +#include struct devlink_ops; @@ -28,13 +29,13 @@ struct devlink { struct list_head resource_list; struct list_head param_list; struct list_head region_list; - u32 snapshot_id; struct list_head reporter_list; struct mutex reporters_lock; /* protects reporter_list */ struct devlink_dpipe_headers *dpipe_headers; struct list_head trap_list; struct list_head trap_group_list; const struct devlink_ops *ops; + struct idr snapshot_idr; struct device *dev; possible_net_t _net; struct mutex lock; diff --git a/net/core/devlink.c b/net/core/devlink.c index da4e669f425b..9571063846cc 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -3760,21 +3760,118 @@ static void devlink_nl_region_notify(struct devlink_region *region, nlmsg_free(msg); } +/** + * __devlink_region_snapshot_id_ref - Increment reference for a snapshot ID + * @devlink: devlink instance + * @id: the snapshot id being referenced + * + * Increments the reference count for the given snapshot id. If the id + * was not yet allocated, it is allocated immediately. If the id was + * allocated but no references exist, a new refcount is created and + * inserted. + */ +static int __devlink_region_snapshot_id_ref(struct devlink *devlink, u32 id) +{ + struct idr *idr = &devlink->snapshot_idr; + refcount_t *ref; + void *old_ptr; + int err; + + lockdep_assert_held(&devlink->lock); + + if (id < 1 || id >= INT_MAX) + return -EINVAL; + + /* Check if a refcount already exists. If so, increment it and exit */ + ref = idr_find(idr, id); + if (ref) { + refcount_inc(ref); + return 0; + } + + /* Allocate a new reference count */ + ref = kzalloc(sizeof(*ref), GFP_KERNEL); + refcount_set(ref, 1); + + /* The id was likely allocated ahead of time using + * devlink_region_snapshot_id_get, so attempt to replace the NULL + * pointer with the refcount. Since idr_find returned NULL, + * idr_replace should either return ERR_PTR(-ENOENT) or NULL. + */ + old_ptr = idr_replace(idr, ref, id); + /* if old_ptr is NULL, we've inserted the reference */ + if (old_ptr == NULL) + return 0; + if (PTR_ERR(old_ptr) != -ENOENT) { + kfree(ref); + return PTR_ERR(old_ptr); + } + + /* the snapshot id was not reserved, so reserve it now. */ + err = idr_alloc(idr, ref, id, id+1, GFP_KERNEL); + if (err < 0) + return err; + WARN_ON(err != id); + + return 0; +} + +/** + * __devlink_region_snapshot_id_deref - Decrement reference for a snapshot ID + * @devlink: devlink instance + * @id: the snapshot id being referenced + * + * Decrements the reference count for a given snapshot id. If the + * refcount has reached zero then remove the reference from the IDR. + */ +static void __devlink_region_snapshot_id_deref(struct devlink *devlink, u32 id) +{ + struct idr *idr = &devlink->snapshot_idr; + refcount_t *ref; + + lockdep_assert_held(&devlink->lock); + + if (WARN_ON(id < 1 || id >= INT_MAX)) + return; + + /* Find the reference pointer */ + ref = idr_find(idr, id); + if (!ref) { + WARN(true, "no previous reference was inserted"); + /* this shouldn't happen, but at least attempt to cleanup if + * something went wrong. + */ + idr_remove(idr, id); + return; + } + + if (refcount_dec_and_test(ref)) { + /* There are no more references, so remove it from the IDR and + * free the reference count. + */ + idr_remove(idr, id); + kfree(ref); + } +} + /** * __devlink_region_snapshot_id_get - get snapshot ID * @devlink: devlink instance * * Returns a new snapshot id or a negative error code on failure. Must be * called while holding the devlink instance lock. + * + * Snapshot ids are stored in an IDR and reference counted by the number + * of snapshots currently using that id. This function pre-allocates + * a snapshot id but does not fill in a reference count. A later call to + * devlink_region_snapshot_create will update the IDR pointer to + * a reference count. On devlink_region_snapshot_destory, if there are no + * further references, the id will be removed from the IDR. */ static int __devlink_region_snapshot_id_get(struct devlink *devlink) { lockdep_assert_held(&devlink->lock); - - if (devlink->snapshot_id >= INT_MAX) - return -ENOSPC; - - return ++devlink->snapshot_id; + return idr_alloc(&devlink->snapshot_idr, NULL, 1, INT_MAX, GFP_KERNEL); } /** @@ -3797,6 +3894,7 @@ __devlink_region_snapshot_create(struct devlink_region *region, { struct devlink *devlink = region->devlink; struct devlink_snapshot *snapshot; + int err; lockdep_assert_held(&devlink->lock); @@ -3811,6 +3909,11 @@ __devlink_region_snapshot_create(struct devlink_region *region, if (!snapshot) return -ENOMEM; + /* Increment snapshot id reference */ + err = __devlink_region_snapshot_id_ref(devlink, snapshot_id); + if (err) + goto err_free_snapshot; + snapshot->id = snapshot_id; snapshot->region = region; snapshot->data = data; @@ -3821,15 +3924,25 @@ __devlink_region_snapshot_create(struct devlink_region *region, devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW); return 0; + +err_free_snapshot: + kfree(snapshot); + return err; } static void devlink_region_snapshot_del(struct devlink_region *region, struct devlink_snapshot *snapshot) { + struct devlink *devlink = region->devlink; + + lockdep_assert_held(&devlink_mutex); + devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL); region->cur_snapshots--; list_del(&snapshot->list); region->ops->destructor(snapshot->data); + __devlink_region_snapshot_id_deref(devlink, snapshot->id); + kfree(snapshot); } @@ -6388,6 +6501,7 @@ struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) if (!devlink) return NULL; devlink->ops = ops; + idr_init(&devlink->snapshot_idr); __devlink_net_set(devlink, &init_net); INIT_LIST_HEAD(&devlink->port_list); INIT_LIST_HEAD(&devlink->sb_list); @@ -6480,6 +6594,23 @@ EXPORT_SYMBOL_GPL(devlink_reload_disable); */ void devlink_free(struct devlink *devlink) { + struct idr *idr = &devlink->snapshot_idr; + + mutex_lock(&devlink->lock); + if (!idr_is_empty(idr)) { + refcount_t *ref; + int id; + + WARN(true, "snapshot IDR is not empty"); + + idr_for_each_entry(idr, ref, id) { + if (ref) + kfree(ref); + } + } + idr_destroy(&devlink->snapshot_idr); + mutex_unlock(&devlink->lock); + mutex_destroy(&devlink->reporters_lock); mutex_destroy(&devlink->lock); WARN_ON(!list_empty(&devlink->trap_group_list)); From patchwork Fri Feb 14 23:22:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238405 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Yz0nlrz9s29 for ; Sat, 15 Feb 2020 10:23:03 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728311AbgBNXXC (ORCPT ); Fri, 14 Feb 2020 18:23:02 -0500 Received: from mga12.intel.com ([192.55.52.136]:61914 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728209AbgBNXW3 (ORCPT ); Fri, 14 Feb 2020 18:22:29 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:28 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629310" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:27 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 14/22] devlink: implement DEVLINK_CMD_REGION_NEW Date: Fri, 14 Feb 2020 15:22:13 -0800 Message-Id: <20200214232223.3442651-15-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Implement support for the DEVLINK_CMD_REGION_NEW command for creating snapshots. This new command parallels the existing DEVLINK_CMD_REGION_DEL. In order for DEVLINK_CMD_REGION_NEW to work for a region, the new ".snapshot" operation must be implemented in the region's ops structure. The desired snapshot id may be provided. If the requested id is already in use, an error will be reported. If no id is provided one will be selected in the same way as a triggered snapshot. In either case, the reference count for that id will be incremented in the snapshot IDR. Signed-off-by: Jacob Keller --- .../networking/devlink/devlink-region.rst | 12 +++- include/net/devlink.h | 6 ++ net/core/devlink.c | 72 +++++++++++++++++++ 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/Documentation/networking/devlink/devlink-region.rst b/Documentation/networking/devlink/devlink-region.rst index 1a7683e7acb2..a24faf2b6b7a 100644 --- a/Documentation/networking/devlink/devlink-region.rst +++ b/Documentation/networking/devlink/devlink-region.rst @@ -20,6 +20,11 @@ address regions that are otherwise inaccessible to the user. Regions may also be used to provide an additional way to debug complex error states, but see also :doc:`devlink-health` +Regions may optionally support capturing a snapshot on demand via the +``DEVLINK_CMD_REGION_NEW`` netlink message. A driver wishing to allow +requested snapshots must implement the ``.snapshot`` callback for the region +in its ``devlink_region_ops`` structure. + example usage ------------- @@ -40,8 +45,11 @@ example usage # Delete a snapshot using: $ devlink region del pci/0000:00:05.0/cr-space snapshot 1 - # Trigger (request) a snapshot be taken: - $ devlink region trigger pci/0000:00:05.0/cr-space + # Request an immediate snapshot, if supported by the region + $ devlink region new pci/0000:00:05.0/cr-space + + # Request an immediate snapshot with a specific id + $ devlink region new pci/0000:00:05.0/cr-space snapshot 5 # Dump a snapshot: $ devlink region dump pci/0000:00:05.0/fw-health snapshot 1 diff --git a/include/net/devlink.h b/include/net/devlink.h index 3a5ff6bea143..3cd0ff2040b2 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -498,10 +498,16 @@ struct devlink_info_req; * struct devlink_region_ops - Region operations * @name: region name * @destructor: callback used to free snapshot memory when deleting + * @snapshot: callback to request an immediate snapshot. On success, + * the data variable must be updated to point to the snapshot data. + * The function will be called while the devlink instance lock is + * held. */ struct devlink_region_ops { const char *name; void (*destructor)(const void *data); + int (*snapshot)(struct devlink *devlink, struct netlink_ext_ack *extack, + u8 **data); }; struct devlink_fmsg; diff --git a/net/core/devlink.c b/net/core/devlink.c index 9571063846cc..b5d1b21e5178 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -4045,6 +4045,71 @@ static int devlink_nl_cmd_region_del(struct sk_buff *skb, return 0; } +static int +devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info) +{ + struct devlink *devlink = info->user_ptr[0]; + struct devlink_region *region; + const char *region_name; + u32 snapshot_id; + u8 *data; + int err; + + if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) { + NL_SET_ERR_MSG_MOD(info->extack, "No region name provided"); + return -EINVAL; + } + + region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); + region = devlink_region_get_by_name(devlink, region_name); + if (!region) { + NL_SET_ERR_MSG_MOD(info->extack, + "The requested region does not exist"); + return -EINVAL; + } + + if (!region->ops->snapshot) { + NL_SET_ERR_MSG_MOD(info->extack, + "The requested region does not support taking an immediate snapshot"); + return -EOPNOTSUPP; + } + + if (region->cur_snapshots == region->max_snapshots) { + NL_SET_ERR_MSG_MOD(info->extack, + "The region has reached the maximum number of stored snapshots"); + return -ENOMEM; + } + + if (info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) { + /* __devlink_region_snapshot_create will take care of + * inserting the snapshot id into the IDR if necessary. + */ + snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); + + if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { + NL_SET_ERR_MSG_MOD(info->extack, + "The requested snapshot id is already in use"); + return -EEXIST; + } + } else { + snapshot_id = __devlink_region_snapshot_id_get(devlink); + } + + err = region->ops->snapshot(devlink, info->extack, &data); + if (err) + return err; + + err = __devlink_region_snapshot_create(region, data, snapshot_id); + if (err) + goto err_free_snapshot_data; + + return 0; + +err_free_snapshot_data: + region->ops->destructor(data); + return err; +} + static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, struct devlink *devlink, u8 *chunk, u32 chunk_size, @@ -6358,6 +6423,13 @@ static const struct genl_ops devlink_nl_ops[] = { .flags = GENL_ADMIN_PERM, .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, }, + { + .cmd = DEVLINK_CMD_REGION_NEW, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, + .doit = devlink_nl_cmd_region_new, + .flags = GENL_ADMIN_PERM, + .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, + }, { .cmd = DEVLINK_CMD_REGION_DEL, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, From patchwork Fri Feb 14 23:22:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238394 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8YS6S1sz9sPK for ; Sat, 15 Feb 2020 10:22:36 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728269AbgBNXWf (ORCPT ); Fri, 14 Feb 2020 18:22:35 -0500 Received: from mga06.intel.com ([134.134.136.31]:30964 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728229AbgBNXWb (ORCPT ); Fri, 14 Feb 2020 18:22:31 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:28 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629314" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:28 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 15/22] netdevsim: support taking immediate snapshot via devlink Date: Fri, 14 Feb 2020 15:22:14 -0800 Message-Id: <20200214232223.3442651-16-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Implement the .snapshot region operation for the dummy data region. This enables a region snapshot to be taken upon request via the new DEVLINK_CMD_REGION_SNAPSHOT command. Signed-off-by: Jacob Keller --- drivers/net/netdevsim/dev.c | 27 +++++++++++++++---- .../drivers/net/netdevsim/devlink.sh | 15 +++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index e30bd94c3d52..a54b03d49c89 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -38,13 +38,11 @@ static struct dentry *nsim_dev_ddir; #define NSIM_DEV_DUMMY_REGION_SIZE (1024 * 32) -static ssize_t nsim_dev_take_snapshot_write(struct file *file, - const char __user *data, - size_t count, loff_t *ppos) +static int +nsim_dev_take_snapshot(struct devlink *devlink, struct netlink_ext_ack *extack, + u8 **data) { - struct nsim_dev *nsim_dev = file->private_data; void *dummy_data; - int err, id; dummy_data = kmalloc(NSIM_DEV_DUMMY_REGION_SIZE, GFP_KERNEL); if (!dummy_data) @@ -52,6 +50,24 @@ static ssize_t nsim_dev_take_snapshot_write(struct file *file, get_random_bytes(dummy_data, NSIM_DEV_DUMMY_REGION_SIZE); + *data = dummy_data; + + return 0; +} + +static ssize_t nsim_dev_take_snapshot_write(struct file *file, + const char __user *data, + size_t count, loff_t *ppos) +{ + struct nsim_dev *nsim_dev = file->private_data; + u8 *dummy_data; + int err, id; + + err = nsim_dev_take_snapshot(priv_to_devlink(nsim_dev), NULL, + &dummy_data); + if (err) + return err; + id = devlink_region_snapshot_id_get(priv_to_devlink(nsim_dev)); if (id < 0) { pr_err("Failed to get snapshot id\n"); @@ -251,6 +267,7 @@ static void nsim_devlink_param_load_driverinit_values(struct devlink *devlink) static const struct devlink_region_ops dummy_region_ops = { .name = "dummy", .destructor = &kfree, + .snapshot = nsim_dev_take_snapshot, }; static int nsim_dev_dummy_region_init(struct nsim_dev *nsim_dev, diff --git a/tools/testing/selftests/drivers/net/netdevsim/devlink.sh b/tools/testing/selftests/drivers/net/netdevsim/devlink.sh index 025a84c2ab5a..f23383fd108c 100755 --- a/tools/testing/selftests/drivers/net/netdevsim/devlink.sh +++ b/tools/testing/selftests/drivers/net/netdevsim/devlink.sh @@ -141,6 +141,21 @@ regions_test() check_region_snapshot_count dummy post-first-delete 2 + devlink region new $DL_HANDLE/dummy + check_err $? "Failed to create a new a snapshot" + + check_region_snapshot_count dummy post-request 3 + + devlink region new $DL_HANDLE/dummy snapshot 25 + check_err $? "Failed to create a new snapshot with id 25" + + check_region_snapshot_count dummy post-request 4 + + devlink region del $DL_HANDLE/dummy snapshot 25 + check_err $? "Failed to delete snapshot with id 25" + + check_region_snapshot_count dummy post-request 3 + log_test "regions test" } From patchwork Fri Feb 14 23:22:15 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238391 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8YP2Z4kz9sPK for ; Sat, 15 Feb 2020 10:22:33 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728252AbgBNXWc (ORCPT ); Fri, 14 Feb 2020 18:22:32 -0500 Received: from mga11.intel.com ([192.55.52.93]:12666 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728214AbgBNXWa (ORCPT ); Fri, 14 Feb 2020 18:22:30 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:29 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629317" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:28 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 16/22] devlink: simplify arguments for read_snapshot_fill Date: Fri, 14 Feb 2020 15:22:15 -0800 Message-Id: <20200214232223.3442651-17-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Simplify the devlink_nl_region_read_snapshot_fill function by looking up the snapshot pointer ahead of time and passing that instead of the region pointer. Check for the snapshot existence within the region_read_dumpit function and exit early if it does not exist. This also enables removing additionally the dump parameter and the netlink attrs parameter. Simply calculate the proper end_offset ahead of time before calling the read_snapshot_fill function. Signed-off-by: Jacob Keller --- net/core/devlink.c | 47 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/net/core/devlink.c b/net/core/devlink.c index b5d1b21e5178..e5bc0046f13f 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -4141,30 +4141,19 @@ static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, #define DEVLINK_REGION_READ_CHUNK_SIZE 256 -static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, - struct devlink *devlink, - struct devlink_region *region, - struct nlattr **attrs, - u64 start_offset, - u64 end_offset, - bool dump, - u64 *new_offset) +static int +devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, + struct devlink *devlink, + struct devlink_snapshot *snapshot, + u64 start_offset, + u64 end_offset, + u64 *new_offset) { - struct devlink_snapshot *snapshot; u64 curr_offset = start_offset; - u32 snapshot_id; int err = 0; *new_offset = start_offset; - snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); - snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); - if (!snapshot) - return -EINVAL; - - if (end_offset > region->size || dump) - end_offset = region->size; - while (curr_offset < end_offset) { u32 data_size; u8 *data; @@ -4194,11 +4183,12 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, const struct genl_dumpit_info *info = genl_dumpit_info(cb); u64 ret_offset, start_offset, end_offset = 0; struct nlattr **attrs = info->attrs; + struct devlink_snapshot *snapshot; struct devlink_region *region; struct nlattr *chunks_attr; const char *region_name; struct devlink *devlink; - bool dump = true; + u32 snapshot_id; void *hdr; int err; @@ -4232,6 +4222,13 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, goto out_unlock; } + snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); + snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); + if (!snapshot) { + err = -EINVAL; + goto out_unlock; + } + hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, DEVLINK_CMD_REGION_READ); @@ -4262,13 +4259,15 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]); - dump = false; + + if (end_offset > region->size) + end_offset = region->size; + } else { + end_offset = region->size; } - err = devlink_nl_region_read_snapshot_fill(skb, devlink, - region, attrs, - start_offset, - end_offset, dump, + err = devlink_nl_region_read_snapshot_fill(skb, devlink, snapshot, + start_offset, end_offset, &ret_offset); if (err && err != -EMSGSIZE) From patchwork Fri Feb 14 23:22:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238406 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Yz58Tfz9sPK for ; Sat, 15 Feb 2020 10:23:03 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728317AbgBNXXD (ORCPT ); Fri, 14 Feb 2020 18:23:03 -0500 Received: from mga11.intel.com ([192.55.52.93]:12666 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728212AbgBNXW3 (ORCPT ); Fri, 14 Feb 2020 18:22:29 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:29 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629321" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:28 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 17/22] devlink: use min_t to calculate data_size Date: Fri, 14 Feb 2020 15:22:16 -0800 Message-Id: <20200214232223.3442651-18-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The calculation for the data_size in the devlink_nl_read_snapshot_fill function uses an if statement that is better expressed using the min_t macro. Noticed-by: Jakub Kicinski Signed-off-by: Jacob Keller --- net/core/devlink.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/net/core/devlink.c b/net/core/devlink.c index e5bc0046f13f..60f4d231470e 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -4155,14 +4155,10 @@ devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, *new_offset = start_offset; while (curr_offset < end_offset) { - u32 data_size; + u32 data_size = min_t(u32, end_offset - curr_offset, + DEVLINK_REGION_READ_CHUNK_SIZE); u8 *data; - if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE) - data_size = end_offset - curr_offset; - else - data_size = DEVLINK_REGION_READ_CHUNK_SIZE; - data = &snapshot->data[curr_offset]; err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink, data, data_size, From patchwork Fri Feb 14 23:22:17 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238404 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Yw5LXQz9s29 for ; Sat, 15 Feb 2020 10:23:00 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728307AbgBNXW7 (ORCPT ); Fri, 14 Feb 2020 18:22:59 -0500 Received: from mga11.intel.com ([192.55.52.93]:12666 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728216AbgBNXWa (ORCPT ); Fri, 14 Feb 2020 18:22:30 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:29 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629325" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:28 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 18/22] devlink: report extended error message in region_read_dumpit Date: Fri, 14 Feb 2020 15:22:17 -0800 Message-Id: <20200214232223.3442651-19-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Report extended error details in the devlink_nl_cmd_region_read_dumpit function, by using the extack structure from the netlink_callback. Signed-off-by: Jacob Keller --- net/core/devlink.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/net/core/devlink.c b/net/core/devlink.c index 60f4d231470e..e81b56f83128 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -4199,8 +4199,14 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, mutex_lock(&devlink->lock); - if (!attrs[DEVLINK_ATTR_REGION_NAME] || - !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) { + if (!attrs[DEVLINK_ATTR_REGION_NAME]) { + NL_SET_ERR_MSG_MOD(cb->extack, "No region name provided"); + err = -EINVAL; + goto out_unlock; + } + + if (!attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) { + NL_SET_ERR_MSG_MOD(cb->extack, "No snapshot id provided"); err = -EINVAL; goto out_unlock; } @@ -4208,6 +4214,8 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]); region = devlink_region_get_by_name(devlink, region_name); if (!region) { + NL_SET_ERR_MSG_MOD(cb->extack, + "The requested region does not exist"); err = -EINVAL; goto out_unlock; } @@ -4221,6 +4229,8 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); if (!snapshot) { + NL_SET_ERR_MSG_MOD(cb->extack, + "The requested snapshot id does not exist"); err = -EINVAL; goto out_unlock; } From patchwork Fri Feb 14 23:22:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238402 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Yr5Kr9z9sPK for ; Sat, 15 Feb 2020 10:22:56 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728304AbgBNXW4 (ORCPT ); Fri, 14 Feb 2020 18:22:56 -0500 Received: from mga11.intel.com ([192.55.52.93]:12666 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728143AbgBNXWb (ORCPT ); Fri, 14 Feb 2020 18:22:31 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:29 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629328" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:28 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 19/22] devlink: remove unnecessary parameter from chunk_fill function Date: Fri, 14 Feb 2020 15:22:18 -0800 Message-Id: <20200214232223.3442651-20-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The devlink parameter of the devlink_nl_cmd_region_read_chunk_fill function is not used. Remove it, to simplify the function signature. Once removed, it is also obvious that the devlink parameter is not necessary for the devlink_nl_region_read_snapshot_fill either. Signed-off-by: Jacob Keller --- net/core/devlink.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/net/core/devlink.c b/net/core/devlink.c index e81b56f83128..a722272f42b4 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -4111,7 +4111,6 @@ devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info) } static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, - struct devlink *devlink, u8 *chunk, u32 chunk_size, u64 addr) { @@ -4143,7 +4142,6 @@ static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, - struct devlink *devlink, struct devlink_snapshot *snapshot, u64 start_offset, u64 end_offset, @@ -4160,8 +4158,8 @@ devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, u8 *data; data = &snapshot->data[curr_offset]; - err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink, - data, data_size, + err = devlink_nl_cmd_region_read_chunk_fill(skb, data, + data_size, curr_offset); if (err) break; @@ -4272,9 +4270,8 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, end_offset = region->size; } - err = devlink_nl_region_read_snapshot_fill(skb, devlink, snapshot, - start_offset, end_offset, - &ret_offset); + err = devlink_nl_region_read_snapshot_fill(skb, snapshot, start_offset, + end_offset, &ret_offset); if (err && err != -EMSGSIZE) goto nla_put_failure; From patchwork Fri Feb 14 23:22:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238399 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Yn3QDzz9s29 for ; Sat, 15 Feb 2020 10:22:53 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728301AbgBNXWw (ORCPT ); Fri, 14 Feb 2020 18:22:52 -0500 Received: from mga11.intel.com ([192.55.52.93]:12667 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728228AbgBNXWb (ORCPT ); Fri, 14 Feb 2020 18:22:31 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:29 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629331" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:28 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 20/22] devlink: refactor region_read_snapshot_fill to use a callback function Date: Fri, 14 Feb 2020 15:22:19 -0800 Message-Id: <20200214232223.3442651-21-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The devlink_nl_region_read_snapshot_fill is used to copy the contents of a snapshot into a message for reporting to userspace via the DEVLINK_CMG_REGION_READ netlink message. A future change is going to add support for directly reading from a region. Almost all of the logic for this new capability is identical. To help reduce code duplication and make this logic more generic, refactor the function to take a cb and cb_priv pointer for doing the actual copy. Add a devlink_region_snapshot_fill implementation that will simply copy the relevant chunk of the region. This does require allocating some storage for the chunk as opposed to simply passing the correct address forward to the devlink_nl_cmg_region_read_chunk_fill function. A future change to implement support for directly reading from a region without a snapshot will provide a separate implementation that calls the newly added devlink region operation. Signed-off-by: Jacob Keller --- net/core/devlink.c | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/net/core/devlink.c b/net/core/devlink.c index a722272f42b4..c200701e1839 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -4140,24 +4140,34 @@ static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, #define DEVLINK_REGION_READ_CHUNK_SIZE 256 +typedef int devlink_chunk_fill_t(void *cb_priv, u8 *chunk, u32 chunk_size, + u64 curr_offset, + struct netlink_ext_ack *extack); + static int -devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, - struct devlink_snapshot *snapshot, - u64 start_offset, - u64 end_offset, - u64 *new_offset) +devlink_nl_region_read_fill(struct sk_buff *skb, devlink_chunk_fill_t *cb, + void *cb_priv, u64 start_offset, u64 end_offset, + u64 *new_offset, struct netlink_ext_ack *extack) { u64 curr_offset = start_offset; int err = 0; + u8 *data; + + /* Allocate and re-use a single buffer */ + data = kzalloc(DEVLINK_REGION_READ_CHUNK_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; *new_offset = start_offset; while (curr_offset < end_offset) { u32 data_size = min_t(u32, end_offset - curr_offset, DEVLINK_REGION_READ_CHUNK_SIZE); - u8 *data; - data = &snapshot->data[curr_offset]; + err = cb(cb_priv, data, data_size, curr_offset, extack); + if (err) + break; + err = devlink_nl_cmd_region_read_chunk_fill(skb, data, data_size, curr_offset); @@ -4168,9 +4178,23 @@ devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, } *new_offset = curr_offset; + kfree(data); + return err; } +static int +devlink_region_snapshot_fill(void *cb_priv, u8 *chunk, u32 chunk_size, + u64 curr_offset, + struct __always_unused netlink_ext_ack *extack) +{ + struct devlink_snapshot *snapshot = cb_priv; + + memcpy(chunk, &snapshot->data[curr_offset], chunk_size); + + return 0; +} + static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, struct netlink_callback *cb) { @@ -4270,8 +4294,9 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, end_offset = region->size; } - err = devlink_nl_region_read_snapshot_fill(skb, snapshot, start_offset, - end_offset, &ret_offset); + err = devlink_nl_region_read_fill(skb, &devlink_region_snapshot_fill, + snapshot, start_offset, end_offset, + &ret_offset, cb->extack); if (err && err != -EMSGSIZE) goto nla_put_failure; From patchwork Fri Feb 14 23:22:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238400 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8Yp3tZ1z9s29 for ; Sat, 15 Feb 2020 10:22:54 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728298AbgBNXWv (ORCPT ); Fri, 14 Feb 2020 18:22:51 -0500 Received: from mga11.intel.com ([192.55.52.93]:12666 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728234AbgBNXWb (ORCPT ); Fri, 14 Feb 2020 18:22:31 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:29 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629335" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:29 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 21/22] devlink: support directly reading from region memory Date: Fri, 14 Feb 2020 15:22:20 -0800 Message-Id: <20200214232223.3442651-22-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a new region operation for directly reading from a region, without taking a full snapshot. Extend the DEVLINK_CMD_REGION_READ to allow directly reading from a region, if supported. Instead of reporting a missing snapshot id as invalid, check to see if direct reading is implemented for the region. If so, use the direct read operation to grab the current contents of the region. This new behavior of DEVLINK_CMD_REGION_READ should be backwards compatible. Previously, all kernels rejected such a DEVLINK_CMD_REGION_READ with -EINVAL, and will now either accept the call or report -EOPNOTSUPP for regions which do not implement direct access. Signed-off-by: Jacob Keller --- .../networking/devlink/devlink-region.rst | 8 +++ include/net/devlink.h | 6 ++ net/core/devlink.c | 59 +++++++++++++------ 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/Documentation/networking/devlink/devlink-region.rst b/Documentation/networking/devlink/devlink-region.rst index a24faf2b6b7a..aeb4e6a5051b 100644 --- a/Documentation/networking/devlink/devlink-region.rst +++ b/Documentation/networking/devlink/devlink-region.rst @@ -25,6 +25,10 @@ Regions may optionally support capturing a snapshot on demand via the requested snapshots must implement the ``.snapshot`` callback for the region in its ``devlink_region_ops`` structure. +Regions may optionally allow directly reading from their contents without a +snapshot. A driver wishing to enable this for a region should implement the +``.read`` callback in the ``devlink_region_ops`` structure. + example usage ------------- @@ -63,6 +67,10 @@ example usage length 16 0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30 + # Read from the region without a snapshot + $ devlink region read pci/0000:00:05.0/fw-health address 16 length 16 + 0000000000000010 0000 0000 ffff ff04 0029 8c00 0028 8cc8 + As regions are likely very device or driver specific, no generic regions are defined. See the driver-specific documentation files for information on the specific regions a driver supports. diff --git a/include/net/devlink.h b/include/net/devlink.h index 3cd0ff2040b2..3f00e0890d92 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -502,12 +502,18 @@ struct devlink_info_req; * the data variable must be updated to point to the snapshot data. * The function will be called while the devlink instance lock is * held. + * @read: callback to directly read a portion of the region. On success, + * the data pointer will be updated with the contents of the + * requested portion of the region. The function will be called + * while the devlink instance lock is held. */ struct devlink_region_ops { const char *name; void (*destructor)(const void *data); int (*snapshot)(struct devlink *devlink, struct netlink_ext_ack *extack, u8 **data); + int (*read)(struct devlink *devlink, struct netlink_ext_ack *extack, + u64 curr_offset, u32 data_size, u8 *data); }; struct devlink_fmsg; diff --git a/net/core/devlink.c b/net/core/devlink.c index c200701e1839..86fa9d53157e 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -4195,18 +4195,30 @@ devlink_region_snapshot_fill(void *cb_priv, u8 *chunk, u32 chunk_size, return 0; } +static int +devlink_region_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size, + u64 curr_offset, struct netlink_ext_ack *extack) +{ + struct devlink_region *region = cb_priv; + struct devlink *devlink = region->devlink; + + return region->ops->read(devlink, extack, curr_offset, chunk_size, + chunk); +} + static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, struct netlink_callback *cb) { const struct genl_dumpit_info *info = genl_dumpit_info(cb); u64 ret_offset, start_offset, end_offset = 0; struct nlattr **attrs = info->attrs; - struct devlink_snapshot *snapshot; + devlink_chunk_fill_t *region_cb; struct devlink_region *region; struct nlattr *chunks_attr; const char *region_name; struct devlink *devlink; - u32 snapshot_id; + void *region_cb_priv; + bool direct; void *hdr; int err; @@ -4227,12 +4239,6 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, goto out_unlock; } - if (!attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) { - NL_SET_ERR_MSG_MOD(cb->extack, "No snapshot id provided"); - err = -EINVAL; - goto out_unlock; - } - region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]); region = devlink_region_get_by_name(devlink, region_name); if (!region) { @@ -4248,13 +4254,30 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, goto out_unlock; } - snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); - snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); - if (!snapshot) { - NL_SET_ERR_MSG_MOD(cb->extack, - "The requested snapshot id does not exist"); - err = -EINVAL; - goto out_unlock; + direct = !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]; + + if (direct) { + if (!region->ops->read) { + NL_SET_ERR_MSG_MOD(cb->extack, + "The requested region does not support direct read"); + err = -EOPNOTSUPP; + goto out_unlock; + } + region_cb = &devlink_region_direct_fill; + region_cb_priv = region; + } else { + u32 snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); + struct devlink_snapshot *snapshot; + + snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); + if (!snapshot) { + NL_SET_ERR_MSG_MOD(cb->extack, + "The requested snapshot id does not exist"); + err = -EINVAL; + goto out_unlock; + } + region_cb = &devlink_region_snapshot_fill; + region_cb_priv = snapshot; } hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, @@ -4294,9 +4317,9 @@ static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, end_offset = region->size; } - err = devlink_nl_region_read_fill(skb, &devlink_region_snapshot_fill, - snapshot, start_offset, end_offset, - &ret_offset, cb->extack); + err = devlink_nl_region_read_fill(skb, region_cb, region_cb_priv, + start_offset, end_offset, &ret_offset, + cb->extack); if (err && err != -EMSGSIZE) goto nla_put_failure; From patchwork Fri Feb 14 23:22:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jacob Keller X-Patchwork-Id: 1238393 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=intel.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48K8YR6sWnz9s29 for ; Sat, 15 Feb 2020 10:22:35 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728266AbgBNXWe (ORCPT ); Fri, 14 Feb 2020 18:22:34 -0500 Received: from mga11.intel.com ([192.55.52.93]:12667 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728236AbgBNXWb (ORCPT ); Fri, 14 Feb 2020 18:22:31 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 14 Feb 2020 15:22:29 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.70,442,1574150400"; d="scan'208";a="228629338" Received: from jekeller-desk.amr.corp.intel.com (HELO jekeller-desk.jekeller.internal) ([10.166.244.172]) by fmsmga008.fm.intel.com with ESMTP; 14 Feb 2020 15:22:29 -0800 From: Jacob Keller To: netdev@vger.kernel.org Cc: jiri@resnulli.us, valex@mellanox.com, linyunsheng@huawei.com, lihong.yang@intel.com, kuba@kernel.org, Jacob Keller Subject: [RFC PATCH v2 22/22] ice: add a devlink region to dump shadow RAM contents Date: Fri, 14 Feb 2020 15:22:21 -0800 Message-Id: <20200214232223.3442651-23-jacob.e.keller@intel.com> X-Mailer: git-send-email 2.25.0.368.g28a2d05eebfb In-Reply-To: <20200214232223.3442651-1-jacob.e.keller@intel.com> References: <20200214232223.3442651-1-jacob.e.keller@intel.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a devlink region for exposing the device's Shadow RAM contents. Support immediate snapshots by implementing the .snapshot callback. Currently, no driver event triggers a snapshot automatically. Users must request a snapshot via the new DEVLINK_CMD_REGION_TAKE_SNAPSHOT command. The recently added .read region operation is also implemented, enabling direct access to the Shadow RAM contents without a snapshot. This is useful when the atomic guarantee of a full snapshot isn't necessary and when userspace only wants to read a small portion of the region. Signed-off-by: Jacob Keller --- Documentation/networking/devlink/ice.rst | 28 ++++ drivers/net/ethernet/intel/ice/ice.h | 2 + drivers/net/ethernet/intel/ice/ice_devlink.c | 145 +++++++++++++++++++ drivers/net/ethernet/intel/ice/ice_devlink.h | 3 + drivers/net/ethernet/intel/ice/ice_main.c | 4 + 5 files changed, 182 insertions(+) diff --git a/Documentation/networking/devlink/ice.rst b/Documentation/networking/devlink/ice.rst index 10ec6c1900b0..452498fc0858 100644 --- a/Documentation/networking/devlink/ice.rst +++ b/Documentation/networking/devlink/ice.rst @@ -57,3 +57,31 @@ The ``ice`` driver reports the following versions - 0x80001709 - Unique identifier of the NVM image contents, also known as the EETRACK id. + +Regions +======= + +The ``ice`` driver enables access to the contents of the Shadow RAM portion +of the flash chip via the ``shadow-ram`` region. + +Users can request an immediate capture of a snapshot via the +``DEVLINK_CMD_REGION_TAKE_SNAPSHOT`` + +.. code:: shell + + $ devlink region snapshot pci/0000:01:00.0/shadow-ram + $ devlink region dump pci/0000:01:00.0/shadow-ram snapshot 1 + +Directly reading a portion of the Shadow RAM without a snapshot is also +supported + +.. code:: shell + + $ devlink region dump pci/0000:01:00.0/shadow-ram + 0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30 + 0000000000000010 0000 0000 ffff ff04 0029 8c00 0028 8cc8 + 0000000000000020 0016 0bb8 0016 1720 0000 0000 c00f 3ffc + 0000000000000030 bada cce5 bada cce5 bada cce5 bada cce5 + + $ devlink region read pci/0000:01:00.0/shadow-ram address 0 length 16 + 0000000000000000 0014 95dc 0014 9514 0035 1670 0034 db30 diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index a195135f840f..43deda152dd3 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -350,6 +350,8 @@ struct ice_pf { /* devlink port data */ struct devlink_port devlink_port; + struct devlink_region *sr_region; + /* OS reserved IRQ details */ struct msix_entry *msix_entries; struct ice_res_tracker *irq_tracker; diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c index 1f755b98d785..b78687aed3c8 100644 --- a/drivers/net/ethernet/intel/ice/ice_devlink.c +++ b/drivers/net/ethernet/intel/ice/ice_devlink.c @@ -213,3 +213,148 @@ void ice_devlink_destroy_port(struct ice_pf *pf) devlink_port_type_clear(&pf->devlink_port); devlink_port_unregister(&pf->devlink_port); } + +/** + * ice_devlink_sr_read - Read a portion of the shadow RAM + * @devlink: the devlink instance + * @extack: netlink extended ack structure + * @curr_offset: offset to start at + * @data_size: portion of the region to read + * @data: buffer to store region contents + * + * This function is called to directly read from the shadow-ram region in + * response to a DEVLINK_CMD_REGION_READ without a snapshot id. + * + * @returns zero on success and updates the contents of the data region, + * otherwise returns a non-zero error code on failure. + */ +static int +ice_devlink_sr_read(struct devlink *devlink, struct netlink_ext_ack *extack, + u64 curr_offset, u32 data_size, u8 *data) +{ + struct ice_pf *pf = devlink_priv(devlink); + struct device *dev = ice_pf_to_dev(pf); + struct ice_hw *hw = &pf->hw; + enum ice_status status; + + if (curr_offset + data_size > hw->nvm.sr_words * sizeof(u16)) + return -ERANGE; + + status = ice_acquire_nvm(hw, ICE_RES_READ); + if (status) { + dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", + status, hw->adminq.sq_last_status); + NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); + return -EIO; + } + + status = ice_read_flat_nvm(hw, curr_offset, &data_size, data, true); + if (status) { + dev_dbg(dev, "ice_read_flat_nvm failed after reading %u data_size from offset %llu, err %d aq_err %d\n", + data_size, curr_offset, status, hw->adminq.sq_last_status); + NL_SET_ERR_MSG_MOD(extack, "Failed to read Shadow RAM contents"); + ice_release_nvm(hw); + return -EIO; + } + + ice_release_nvm(hw); + + return 0; +} + +/** + * ice_devlink_sr_snapshot - Capture a snapshot of the Shadow RAM contents + * @devlink: the devlink instance + * @extack: extended ACK response structure + * @data: on exit points to snapshot data buffer + * + * This function is called in response to the DEVLINK_CMD_REGION_TRIGGER for + * the shadow-ram devlink region. It captures a snapshot of the shadow ram + * contents. This snapshot can later be viewed via the devlink-region + * interface. + * + * @returns zero on success, and updates the data pointer. Returns a non-zero + * error code on failure. + */ +static int +ice_devlink_sr_snapshot(struct devlink *devlink, struct netlink_ext_ack *extack, + u8 **data) +{ + struct ice_pf *pf = devlink_priv(devlink); + struct device *dev = ice_pf_to_dev(pf); + struct ice_hw *hw = &pf->hw; + enum ice_status status; + void *sr_data; + u32 sr_size; + + sr_size = hw->nvm.sr_words * sizeof(u16); + sr_data = kzalloc(sr_size, GFP_KERNEL); + if (!sr_data) { + NL_SET_ERR_MSG_MOD(extack, "Out of memory"); + return -ENOMEM; + } + + status = ice_acquire_nvm(hw, ICE_RES_READ); + if (status) { + dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n", + status, hw->adminq.sq_last_status); + NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore"); + kfree(sr_data); + return -EIO; + } + + status = ice_read_flat_nvm(hw, 0, &sr_size, sr_data, true); + if (status) { + dev_dbg(dev, "ice_read_flat_nvm failed after reading %u bytes, err %d aq_err %d\n", + sr_size, status, hw->adminq.sq_last_status); + NL_SET_ERR_MSG_MOD(extack, "Failed to read Shadow RAM contents"); + ice_release_nvm(hw); + kfree(sr_data); + return -EIO; + } + + ice_release_nvm(hw); + + *data = sr_data; + + return 0; +} + +static const struct devlink_region_ops ice_sr_region_ops = { + .name = "shadow-ram", + .destructor = kfree, + .snapshot = ice_devlink_sr_snapshot, + .read = ice_devlink_sr_read, +}; + +/** + * ice_devlink_init_regions - Initialize devlink regions + * @pf: the PF device structure + * + * Create devlink regions used to enable access to dump the contents of the + * flash memory on the device. + */ +void ice_devlink_init_regions(struct ice_pf *pf) +{ + struct devlink *devlink = priv_to_devlink(pf); + struct device *dev = ice_pf_to_dev(pf); + u64 shadow_ram_size; + + shadow_ram_size = pf->hw.nvm.sr_words * sizeof(u16); + pf->sr_region = devlink_region_create(devlink, &ice_sr_region_ops, 1, + shadow_ram_size); + if (IS_ERR(pf->sr_region)) + dev_warn(dev, "failed to create shadow-ram devlink region, err %ld\n", + PTR_ERR(pf->sr_region)); +} + +/** + * ice_devlink_destroy_regions - Destroy devlink regions + * @pf: the PF device structure + * + * Remove previously created regions for this PF. + */ +void ice_devlink_destroy_regions(struct ice_pf *pf) +{ + devlink_region_destroy(pf->sr_region); +} diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.h b/drivers/net/ethernet/intel/ice/ice_devlink.h index f94dc93c24c5..6e806a08dc23 100644 --- a/drivers/net/ethernet/intel/ice/ice_devlink.h +++ b/drivers/net/ethernet/intel/ice/ice_devlink.h @@ -11,4 +11,7 @@ void ice_devlink_unregister(struct ice_pf *pf); int ice_devlink_create_port(struct ice_pf *pf); void ice_devlink_destroy_port(struct ice_pf *pf); +void ice_devlink_init_regions(struct ice_pf *pf); +void ice_devlink_destroy_regions(struct ice_pf *pf); + #endif /* _ICE_DEVLINK_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index f2cca810977d..3d199596e17d 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3245,6 +3245,8 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) goto err_init_pf_unroll; } + ice_devlink_init_regions(pf); + pf->num_alloc_vsi = hw->func_caps.guar_num_vsi; if (!pf->num_alloc_vsi) { err = -EIO; @@ -3359,6 +3361,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) devm_kfree(dev, pf->vsi); err_init_pf_unroll: ice_deinit_pf(pf); + ice_devlink_destroy_regions(pf); ice_deinit_hw(hw); err_exit_unroll: ice_devlink_unregister(pf); @@ -3398,6 +3401,7 @@ static void ice_remove(struct pci_dev *pdev) ice_vsi_free_q_vectors(pf->vsi[i]); } ice_deinit_pf(pf); + ice_devlink_destroy_regions(pf); ice_deinit_hw(&pf->hw); ice_devlink_unregister(pf);