Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next v2 4/5] qed: Adapter flash update support.
From: Sudarsana Reddy Kalluru @ 2018-03-28  8:43 UTC (permalink / raw)
  To: davem; +Cc: netdev, Ariel.Elior, yuvalm
In-Reply-To: <20180328084331.2435-1-sudarsana.kalluru@cavium.com>

This patch adds the required driver support for updating the flash or
non volatile memory of the adapter. At highlevel, flash upgrade comprises
of reading the flash images from the input file, validating the images and
writing them to the respective paritions.

Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
 drivers/net/ethernet/qlogic/qed/qed_main.c | 338 +++++++++++++++++++++++++++++
 include/linux/qed/qed_if.h                 |  17 ++
 2 files changed, 355 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index 2783288..9bce4ae 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -45,6 +45,7 @@
 #include <linux/etherdevice.h>
 #include <linux/vmalloc.h>
 #include <linux/crash_dump.h>
+#include <linux/crc32.h>
 #include <linux/qed/qed_if.h>
 #include <linux/qed/qed_ll2_if.h>
 
@@ -1553,6 +1554,342 @@ static int qed_drain(struct qed_dev *cdev)
 	return 0;
 }
 
+static u32 qed_nvm_flash_image_access_crc(struct qed_dev *cdev,
+					  struct qed_nvm_image_att *nvm_image,
+					  u32 *crc)
+{
+	u8 *buf = NULL;
+	int rc, j;
+	u32 val;
+
+	/* Allocate a buffer for holding the nvram image */
+	buf = kzalloc(nvm_image->length, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	/* Read image into buffer */
+	rc = qed_mcp_nvm_read(cdev, nvm_image->start_addr,
+			      buf, nvm_image->length);
+	if (rc) {
+		DP_ERR(cdev, "Failed reading image from nvm\n");
+		goto out;
+	}
+
+	/* Convert the buffer into big-endian format (excluding the
+	 * closing 4 bytes of CRC).
+	 */
+	for (j = 0; j < nvm_image->length - 4; j += 4) {
+		val = cpu_to_be32(*(u32 *)&buf[j]);
+		*(u32 *)&buf[j] = val;
+	}
+
+	/* Calc CRC for the "actual" image buffer, i.e. not including
+	 * the last 4 CRC bytes.
+	 */
+	*crc = (~cpu_to_be32(crc32(0xffffffff, buf, nvm_image->length - 4)));
+
+out:
+	kfree(buf);
+
+	return rc;
+}
+
+/* Binary file format -
+ *     /----------------------------------------------------------------------\
+ * 0B  |                       0x4 [command index]                            |
+ * 4B  | image_type     | Options        |  Number of register settings       |
+ * 8B  |                       Value                                          |
+ * 12B |                       Mask                                           |
+ * 16B |                       Offset                                         |
+ *     \----------------------------------------------------------------------/
+ * There can be several Value-Mask-Offset sets as specified by 'Number of...'.
+ * Options - 0'b - Calculate & Update CRC for image
+ */
+static int qed_nvm_flash_image_access(struct qed_dev *cdev, const u8 **data,
+				      bool *check_resp)
+{
+	struct qed_nvm_image_att nvm_image;
+	struct qed_hwfn *p_hwfn;
+	bool is_crc = false;
+	u32 image_type;
+	int rc = 0, i;
+	u16 len;
+
+	*data += 4;
+	image_type = **data;
+	p_hwfn = QED_LEADING_HWFN(cdev);
+	for (i = 0; i < p_hwfn->nvm_info.num_images; i++)
+		if (image_type == p_hwfn->nvm_info.image_att[i].image_type)
+			break;
+	if (i == p_hwfn->nvm_info.num_images) {
+		DP_ERR(cdev, "Failed to find nvram image of type %08x\n",
+		       image_type);
+		return -ENOENT;
+	}
+
+	nvm_image.start_addr = p_hwfn->nvm_info.image_att[i].nvm_start_addr;
+	nvm_image.length = p_hwfn->nvm_info.image_att[i].len;
+
+	DP_VERBOSE(cdev, NETIF_MSG_DRV,
+		   "Read image %02x; type = %08x; NVM [%08x,...,%08x]\n",
+		   **data, image_type, nvm_image.start_addr,
+		   nvm_image.start_addr + nvm_image.length - 1);
+	(*data)++;
+	is_crc = !!(**data & BIT(0));
+	(*data)++;
+	len = *((u16 *)*data);
+	*data += 2;
+	if (is_crc) {
+		u32 crc = 0;
+
+		rc = qed_nvm_flash_image_access_crc(cdev, &nvm_image, &crc);
+		if (rc) {
+			DP_ERR(cdev, "Failed calculating CRC, rc = %d\n", rc);
+			goto exit;
+		}
+
+		rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM,
+				       (nvm_image.start_addr +
+					nvm_image.length - 4), (u8 *)&crc, 4);
+		if (rc)
+			DP_ERR(cdev, "Failed writing to %08x, rc = %d\n",
+			       nvm_image.start_addr + nvm_image.length - 4, rc);
+		goto exit;
+	}
+
+	/* Iterate over the values for setting */
+	while (len) {
+		u32 offset, mask, value, cur_value;
+		u8 buf[4];
+
+		value = *((u32 *)*data);
+		*data += 4;
+		mask = *((u32 *)*data);
+		*data += 4;
+		offset = *((u32 *)*data);
+		*data += 4;
+
+		rc = qed_mcp_nvm_read(cdev, nvm_image.start_addr + offset, buf,
+				      4);
+		if (rc) {
+			DP_ERR(cdev, "Failed reading from %08x\n",
+			       nvm_image.start_addr + offset);
+			goto exit;
+		}
+
+		cur_value = le32_to_cpu(*((__le32 *)buf));
+		DP_VERBOSE(cdev, NETIF_MSG_DRV,
+			   "NVM %08x: %08x -> %08x [Value %08x Mask %08x]\n",
+			   nvm_image.start_addr + offset, cur_value,
+			   (cur_value & ~mask) | (value & mask), value, mask);
+		value = (value & mask) | (cur_value & ~mask);
+		rc = qed_mcp_nvm_write(cdev, QED_NVM_WRITE_NVRAM,
+				       nvm_image.start_addr + offset,
+				       (u8 *)&value, 4);
+		if (rc) {
+			DP_ERR(cdev, "Failed writing to %08x\n",
+			       nvm_image.start_addr + offset);
+			goto exit;
+		}
+
+		len--;
+	}
+exit:
+	return rc;
+}
+
+/* Binary file format -
+ *     /----------------------------------------------------------------------\
+ * 0B  |                       0x3 [command index]                            |
+ * 4B  | b'0: check_response?   | b'1-127  reserved                           |
+ * 8B  | File-type |                   reserved                               |
+ *     \----------------------------------------------------------------------/
+ *     Start a new file of the provided type
+ */
+static int qed_nvm_flash_image_file_start(struct qed_dev *cdev,
+					  const u8 **data, bool *check_resp)
+{
+	int rc;
+
+	*data += 4;
+	*check_resp = !!(**data & BIT(0));
+	*data += 4;
+
+	DP_VERBOSE(cdev, NETIF_MSG_DRV,
+		   "About to start a new file of type %02x\n", **data);
+	rc = qed_mcp_nvm_put_file_begin(cdev, **data);
+	*data += 4;
+
+	return rc;
+}
+
+/* Binary file format -
+ *     /----------------------------------------------------------------------\
+ * 0B  |                       0x2 [command index]                            |
+ * 4B  |                       Length in bytes                                |
+ * 8B  | b'0: check_response?   | b'1-127  reserved                           |
+ * 12B |                       Offset in bytes                                |
+ * 16B |                       Data ...                                       |
+ *     \----------------------------------------------------------------------/
+ *     Write data as part of a file that was previously started. Data should be
+ *     of length equal to that provided in the message
+ */
+static int qed_nvm_flash_image_file_data(struct qed_dev *cdev,
+					 const u8 **data, bool *check_resp)
+{
+	u32 offset, len;
+	int rc;
+
+	*data += 4;
+	len = *((u32 *)(*data));
+	*data += 4;
+	*check_resp = !!(**data & BIT(0));
+	*data += 4;
+	offset = *((u32 *)(*data));
+	*data += 4;
+
+	DP_VERBOSE(cdev, NETIF_MSG_DRV,
+		   "About to write File-data: %08x bytes to offset %08x\n",
+		   len, offset);
+
+	rc = qed_mcp_nvm_write(cdev, QED_PUT_FILE_DATA, offset,
+			       (char *)(*data), len);
+	*data += len;
+
+	return rc;
+}
+
+/* Binary file format [General header] -
+ *     /----------------------------------------------------------------------\
+ * 0B  |                       0x12435687 [signature]                         |
+ * 4B  |                       Length in bytes                                |
+ * 8B  | Highest command in this batchfile |          Reserved                |
+ *     \----------------------------------------------------------------------/
+ */
+static int qed_nvm_flash_image_validate(struct qed_dev *cdev,
+					const struct firmware *image,
+					const u8 **data)
+{
+	u32 signature, len;
+
+	/* Check minimum size */
+	if (image->size < 12) {
+		DP_ERR(cdev, "Image is too short [%08x]\n", (u32)image->size);
+		return -EINVAL;
+	}
+
+	/* Check signature */
+	signature = *((u32 *)(*data));
+	if (signature != 0x12435687) {
+		DP_ERR(cdev, "Wrong signature '%08x'\n", signature);
+		return -EINVAL;
+	}
+
+	*data += 4;
+	/* Validate internal size equals the image-size */
+	len = *((u32 *)(*data));
+	if (len != image->size) {
+		DP_ERR(cdev, "Size mismatch: internal = %08x image = %08x\n",
+		       len, (u32)image->size);
+		return -EINVAL;
+	}
+
+	*data += 4;
+	/* Make sure driver familiar with all commands necessary for this */
+	if (*((u16 *)(*data)) >= QED_NVM_FLASH_CMD_NVM_MAX) {
+		DP_ERR(cdev, "File contains unsupported commands [Need %04x]\n",
+		       *((u16 *)(*data)));
+		return -EINVAL;
+	}
+
+	*data += 4;
+
+	return 0;
+}
+
+static int qed_nvm_flash(struct qed_dev *cdev, const char *name)
+{
+	const struct firmware *image;
+	const u8 *data, *data_end;
+	u32 cmd_type;
+	int rc;
+
+	rc = request_firmware(&image, name, &cdev->pdev->dev);
+	if (rc) {
+		DP_ERR(cdev, "Failed to find '%s'\n", name);
+		return rc;
+	}
+
+	DP_VERBOSE(cdev, NETIF_MSG_DRV,
+		   "Flashing '%s' - firmware's data at %p, size is %08x\n",
+		   name, image->data, (u32)image->size);
+	data = image->data;
+	data_end = data + image->size;
+
+	rc = qed_nvm_flash_image_validate(cdev, image, &data);
+	if (rc)
+		goto exit;
+
+	while (data < data_end) {
+		bool check_resp = false;
+
+		/* Parse the actual command */
+		cmd_type = *((u32 *)data);
+		switch (cmd_type) {
+		case QED_NVM_FLASH_CMD_FILE_DATA:
+			rc = qed_nvm_flash_image_file_data(cdev, &data,
+							   &check_resp);
+			break;
+		case QED_NVM_FLASH_CMD_FILE_START:
+			rc = qed_nvm_flash_image_file_start(cdev, &data,
+							    &check_resp);
+			break;
+		case QED_NVM_FLASH_CMD_NVM_CHANGE:
+			rc = qed_nvm_flash_image_access(cdev, &data,
+							&check_resp);
+			break;
+		default:
+			DP_ERR(cdev, "Unknown command %08x\n", cmd_type);
+			rc = -EINVAL;
+			goto exit;
+		}
+
+		if (rc) {
+			DP_ERR(cdev, "Command %08x failed\n", cmd_type);
+			goto exit;
+		}
+
+		/* Check response if needed */
+		if (check_resp) {
+			u32 mcp_response = 0;
+
+			if (qed_mcp_nvm_resp(cdev, (u8 *)&mcp_response)) {
+				DP_ERR(cdev, "Failed getting MCP response\n");
+				rc = -EINVAL;
+				goto exit;
+			}
+
+			switch (mcp_response & FW_MSG_CODE_MASK) {
+			case FW_MSG_CODE_OK:
+			case FW_MSG_CODE_NVM_OK:
+			case FW_MSG_CODE_NVM_PUT_FILE_FINISH_OK:
+			case FW_MSG_CODE_PHY_OK:
+				break;
+			default:
+				DP_ERR(cdev, "MFW returns error: %08x\n",
+				       mcp_response);
+				rc = -EINVAL;
+				goto exit;
+			}
+		}
+	}
+
+exit:
+	release_firmware(image);
+
+	return rc;
+}
+
 static int qed_nvm_get_image(struct qed_dev *cdev, enum qed_nvm_images type,
 			     u8 *buf, u16 len)
 {
@@ -1719,6 +2056,7 @@ static int qed_update_mtu(struct qed_dev *cdev, u16 mtu)
 	.dbg_all_data_size = &qed_dbg_all_data_size,
 	.chain_alloc = &qed_chain_alloc,
 	.chain_free = &qed_chain_free,
+	.nvm_flash = &qed_nvm_flash,
 	.nvm_get_image = &qed_nvm_get_image,
 	.set_coalesce = &qed_set_coalesce,
 	.set_led = &qed_set_led,
diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
index 15e398c..ab4e48d 100644
--- a/include/linux/qed/qed_if.h
+++ b/include/linux/qed/qed_if.h
@@ -483,6 +483,13 @@ struct qed_int_info {
 	u8			used_cnt;
 };
 
+enum qed_nvm_flash_cmd {
+	QED_NVM_FLASH_CMD_FILE_DATA = 0x2,
+	QED_NVM_FLASH_CMD_FILE_START = 0x3,
+	QED_NVM_FLASH_CMD_NVM_CHANGE = 0x4,
+	QED_NVM_FLASH_CMD_NVM_MAX,
+};
+
 struct qed_common_cb_ops {
 	void (*arfs_filter_op)(void *dev, void *fltr, u8 fw_rc);
 	void	(*link_update)(void			*dev,
@@ -658,6 +665,16 @@ struct qed_common_ops {
 				      struct qed_chain *p_chain);
 
 /**
+ * @brief nvm_flash - Flash nvm data.
+ *
+ * @param cdev
+ * @param name - file containing the data
+ *
+ * @return 0 on success, error otherwise.
+ */
+	int (*nvm_flash)(struct qed_dev *cdev, const char *name);
+
+/**
  * @brief nvm_get_image - reads an entire image from nvram
  *
  * @param cdev
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH net-next v2 5/5] qede: Ethtool flash update support.
From: Sudarsana Reddy Kalluru @ 2018-03-28  8:43 UTC (permalink / raw)
  To: davem; +Cc: netdev, Ariel.Elior, yuvalm
In-Reply-To: <20180328084331.2435-1-sudarsana.kalluru@cavium.com>

The patch adds ethtool callback implementation for flash update.

Signed-off-by: Sudarsana Reddy Kalluru <Sudarsana.Kalluru@cavium.com>
Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
---
 drivers/net/ethernet/qlogic/qede/qede_ethtool.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
index 4ca3847..ecbf1de 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c
@@ -699,6 +699,14 @@ static u32 qede_get_link(struct net_device *dev)
 	return current_link.link_up;
 }
 
+static int qede_flash_device(struct net_device *dev,
+			     struct ethtool_flash *flash)
+{
+	struct qede_dev *edev = netdev_priv(dev);
+
+	return edev->ops->common->nvm_flash(edev->cdev, flash->data);
+}
+
 static int qede_get_coalesce(struct net_device *dev,
 			     struct ethtool_coalesce *coal)
 {
@@ -1806,6 +1814,7 @@ static int qede_set_eee(struct net_device *dev, struct ethtool_eee *edata)
 
 	.get_tunable = qede_get_tunable,
 	.set_tunable = qede_set_tunable,
+	.flash_device = qede_flash_device,
 };
 
 static const struct ethtool_ops qede_vf_ethtool_ops = {
-- 
1.8.3.1

^ permalink raw reply related

* Re: [PATCH 0/7] net: thunderx: implement DMAC filtering support
From: Vadim Lomovtsev @ 2018-03-28  8:47 UTC (permalink / raw)
  To: David Miller
  Cc: sgoutham, sunil.kovvuri, robert.richter, linux-arm-kernel, netdev,
	linux-kernel, dnelson, Vadim.Lomovtsev
In-Reply-To: <20180327.132822.403377635482599502.davem@davemloft.net>

Hi David,

Thanks for feedback.

On Tue, Mar 27, 2018 at 01:28:22PM -0400, David Miller wrote:
> From: Vadim Lomovtsev <Vadim.Lomovtsev@caviumnetworks.com>
> Date: Tue, 27 Mar 2018 08:07:29 -0700
> 
> > From: Vadim Lomovtsev <Vadim.Lomovtsev@cavium.com>
> > 
> > By default CN88XX BGX accepts all incoming multicast and broadcast
> > packets and filtering is disabled. The nic driver doesn't provide
> > an ability to change such behaviour.
> > 
> > This series is to implement DMAC filtering management for CN88XX
> > nic driver allowing user to enable/disable filtering and configure
> > specific MAC addresses to filter traffic.
> 
> This doesn't even compile:
> 
> drivers/net/ethernet/cavium/thunder/thunder_bgx.c: In function ‘bgx_lmac_save_filter’:
> drivers/net/ethernet/cavium/thunder/thunder_bgx.c:286:3: warning: ‘return’ with no value, in function returning non-void [-Wreturn-type]
>    return;
>    ^~~~~~
> drivers/net/ethernet/cavium/thunder/thunder_bgx.c:281:12: note: declared here
>  static int bgx_lmac_save_filter(struct lmac *lmac, u64 dmac, u8 vf_id)
>             ^~~~~~~~~~~~~~~~~~~~
> In file included from drivers/net/ethernet/cavium/thunder/nic.h:15:0,
>                  from drivers/net/ethernet/cavium/thunder/thunder_bgx.c:21:
> drivers/net/ethernet/cavium/thunder/thunder_bgx.c: In function ‘bgx_set_dmac_cam_filter_mac’:
> drivers/net/ethernet/cavium/thunder/thunder_bgx.h:61:38: warning: left shift count >= width of type [-Wshift-count-overflow]
>  #define  RX_DMACX_CAM_LMACID(x)   (x << 49)
>                                       ^
> drivers/net/ethernet/cavium/thunder/thunder_bgx.c:324:8: note: in expansion of macro ‘RX_DMACX_CAM_LMACID’
>   cfg = RX_DMACX_CAM_LMACID(lmacid & LMAC_ID_MASK) |
>         ^~~~~~~~~~~~~~~~~~~

Will update and repost series as v2.
Do you have any other comments ?

WBR,
Vadim

^ permalink raw reply

* Re: [PATCH bpf-next] bpf: sockmap: initialize sg table entries properly
From: Daniel Borkmann @ 2018-03-28  8:51 UTC (permalink / raw)
  To: Prashant Bhole
  Cc: John Fastabend, Alexei Starovoitov, David S . Miller, netdev
In-Reply-To: <92d66b9e-d93a-9f87-a6db-84aee0c14284@lab.ntt.co.jp>

On 03/28/2018 08:18 AM, Prashant Bhole wrote:
> On 3/27/2018 6:05 PM, Daniel Borkmann wrote:
>> On 03/27/2018 10:41 AM, Prashant Bhole wrote:
>>> On 3/27/2018 12:15 PM, John Fastabend wrote:
>>>> On 03/25/2018 11:54 PM, Prashant Bhole wrote:
>>>>> When CONFIG_DEBUG_SG is set, sg->sg_magic is initialized to SG_MAGIC,
>>>>> when sg table is initialized using sg_init_table(). Magic is checked
>>>>> while navigating the scatterlist. We hit BUG_ON when magic check is
>>>>> failed.
>>>>>
>>>>> Fixed following things:
>>>>> - Initialization of sg table in bpf_tcp_sendpage() was missing,
>>>>>     initialized it using sg_init_table()
>>>>>
>>>>> - bpf_tcp_sendmsg() initializes sg table using sg_init_table() before
>>>>>     entering the loop, but further consumed sg entries are initialized
>>>>>     using memset. Fixed it by replacing memset with sg_init_table() in
>>>>>     function bpf_tcp_push()
>>>>>
>>>>> Signed-off-by: Prashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
>>>>> ---
>>>>>    kernel/bpf/sockmap.c | 11 +++++++----
>>>>>    1 file changed, 7 insertions(+), 4 deletions(-)
>>>>>
>>>>> diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c
>>>>> index 69c5bccabd22..8a848a99d768 100644
>>>>> --- a/kernel/bpf/sockmap.c
>>>>> +++ b/kernel/bpf/sockmap.c
>>>>> @@ -312,7 +312,7 @@ static int bpf_tcp_push(struct sock *sk, int apply_bytes,
>>>>>                md->sg_start++;
>>>>>                if (md->sg_start == MAX_SKB_FRAGS)
>>>>>                    md->sg_start = 0;
>>>>> -            memset(sg, 0, sizeof(*sg));
>>>>> +            sg_init_table(sg, 1);
>>>>
>>>> Looks OK here.
>>>>
>>>>>                  if (md->sg_start == md->sg_end)
>>>>>                    break;
>>>>> @@ -763,10 +763,14 @@ static int bpf_tcp_sendpage(struct sock *sk, struct page *page,
>>>>>          lock_sock(sk);
>>>>>    -    if (psock->cork_bytes)
>>>>> +    if (psock->cork_bytes) {
>>>>>            m = psock->cork;
>>>>> -    else
>>>>> +        sg = &m->sg_data[m->sg_end];
>>>>> +    } else {
>>>>>            m = &md;
>>>>> +        sg = m->sg_data;
>>>>> +        sg_init_table(sg, MAX_SKB_FRAGS);
>>>>
>>>> sg_init_table() does an unnecessary memset() though. We
>>>> probably either want a new scatterlist API or just open
>>>> code this,
>>>>
>>>> #ifdef CONFIG_DEBUG_SG
>>>> {
>>>>      unsigned int i;
>>>>      for (i = 0; i < nents; i++)
>>>>          sgl[i].sg_magic = SG_MAGIC;
>>>> }
>>>
>>> Similar sg_init_table() is present in bpf_tcp_sendmsg().
>>> I agree that it causes unnecessary memset, but I don't agree with open coded fix.
>>
>> But then lets fix is properly and add a static inline helper to the
>> include/linux/scatterlist.h header like ...
>>
>> static inline void sg_init_debug_marker(struct scatterlist *sgl,
>>                     unsigned int nents)
>> {
>> #ifdef CONFIG_DEBUG_SG
>>     unsigned int i;
>>
>>     for (i = 0; i < nents; i++)
>>         sgl[i].sg_magic = SG_MAGIC;
>> #endif
>> }
>>
>> ... and reuse it in all the places that would otherwise open-code this,
>> as well as sg_init_table():
>>
>> void sg_init_table(struct scatterlist *sgl, unsigned int nents)
>> {
>>          memset(sgl, 0, sizeof(*sgl) * nents);
>>     sg_init_debug_marker(sgl, nents);
>>          sg_mark_end(&sgl[nents - 1]);
>> }
>>
>> This would be a lot cleaner than having this duplicated in various places.
> 
> Daniel, This is a good suggestion. Is it ok if I submit both changes in
> a patch series?

Sure, that's fine.

> How scatterlist related changes will be picked up by other subsystems?

Once this gets applied into bpf-next, this will be pushed to net-next tree,
and during the merge window net-next will be pulled into Linus' tree if this
is what you are asking. Then also other subsystems outside of bpf/networking
can make use of the sg_init_debug_marker() helper if suitable for their
situation.

> -Prashant
> 

^ permalink raw reply

* Re: RFC on writel and writel_relaxed
From: Will Deacon @ 2018-03-28  9:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Linus Torvalds, Alexander Duyck, Sinan Kaya, Arnd Bergmann,
	Jason Gunthorpe, David Laight, Oliver,
	open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
	linux-rdma@vger.kernel.org, Paul E. McKenney,
	netdev@vger.kernel.org
In-Reply-To: <1522219376.7364.109.camel@kernel.crashing.org>

On Wed, Mar 28, 2018 at 05:42:56PM +1100, Benjamin Herrenschmidt wrote:
> On Tue, 2018-03-27 at 20:26 -1000, Linus Torvalds wrote:
> > On Tue, Mar 27, 2018 at 6:33 PM, Benjamin Herrenschmidt
> > <benh@kernel.crashing.org> wrote:
> > > 
> > > This is why, I want (with your agreement) to define clearly and once
> > > and for all, that the Linux semantics of writel are that it is ordered
> > > with previous writes to coherent memory (*)
> > 
> > Honestly, I think those are the sane semantics. In fact, make it
> > "ordered with previous writes" full stop, since it's not only ordered
> > wrt previous writes to memory, but also previous writel's.
> 
> Of course. It was somewhat a given that it's ordered vs. any previous
> MMIO actually, but it doesn't hurt to spell it out once more.

Good. So I think this confirms our understanding so far.

> 
> > > Also, can I assume the above ordering with writel() equally applies to
> > > readl() or not ?
> > > 
> > > IE:
> > >         dma_buf->foo = 1;
> > >         readl(STUPID_DEVICE_DMA_KICK_ON_READ);
> > 
> > If that KICK_ON_READ is UC, then that's definitely the case. And
> > honestly, status registers like that really should always be UC.
> > 
> > But if somebody sets the area WC (which is crazy), then I think it
> > might be at least debatable. x86 semantics does allow reads to be done
> > before previous writes (or, put another way, writes to be buffered -
> > the buffers are ordered so writes don't get re-ordered, but reads can
> > happen during the buffering).
> 
> Right, for now I worry about UC semantics. Once we have nailed that, we
> can look at WC, which is a lot more tricky as archs differs more
> widely, but one thing at a time.
> 
> > But UC accesses are always  done entirely ordered, and honestly, any
> > status register that starts a DMA would not make sense any other way.
> > 
> > Of course, you'd have to be pretty odd to want to start a DMA with a
> > read anyway - partly exactly because it's bad for performance since
> > reads will be synchronous and not buffered like a write).
> 
> I have bad memories of old adaptec controllers ...
> 
> That said, I think the above might not be right on ARM if we want to
> make it the rule, Will, what do you reckon ?

So there are two cases to consider:

1.
	if (readl(DEVICE_DMA_STATUS) == DMA_DONE)
		mydata = *dma_bufp;



2.
	*dma_bufp = 42;
	readl(DEVICE_DMA_KICK_ON_READ);


For arm/arm64 we guarantee ordering for (1) but not for (2) -- you'd need to
add an mb() to make it work.

Do both of these work on power? If so, I guess I can make readl even more
expensive :/ Feels a bit like the tail wagging the dog, though.

Another thing I just realised is that we restrict the barriers we use in
readl/writel on arm64 so that they don't necessary apply to both loads and
stores. To be specific:

   writel is ordered against prior writes to memory, but not reads

   readl is ordered against subsequent reads of memory, but not writes (but
   note that in example (1) above, the control dependency ensures that).

If necessary, I could move the barrier in our readl implementation to be
before the read, then play the control-dependency + instruction-sync (ISB)
trick that you do on power.

Will

^ permalink raw reply

* Problems: network rx out-of-order issue
From: Anny Hu @ 2018-03-28  9:20 UTC (permalink / raw)
  To: netdev

Dears,

Recently, we find the following patch will impact multi-core network throughput performance on kernel-4.9,
for it will cause rx packet out-of-order.
commit id: 4cd13c21b207e80ddb1144c576500098f2d5f882

[kernel version]: 
kernel-4.9

[repeat steps]
1. two our phones with load based on kernel-4.9, enable wifi and set up P2P connection; 
2. two reference phones with load based on kernel-4.4, enable wifi and set up P2P connection; 
3. do iperf UDP downlink test with the following commands;
Client: adb shell iperf -c 192.168.49.xx -u -i 1 -t 60 -b 15M
Server: adb shell iperf -s -u
4. out-of-order rate of our phones are obviously higher than reference phone:
DUT                                  Lost rate              out of order
Our phone                            0.011%                  164    
Reference phone                      0.0091%                 1

[Code flow]
Wi-Fi driver trigger rx_thread to receive rx packets and call netif_rx_ni() to push packets to tcp stack in thread context.

[netlog]:
No      Time                            Source ip       Dest ip         Protocol Len     Ip id                   Info
3811    2010-01-01 08:11:35.075522      192.168.43.1    192.168.43.90   UDP      144     0x25ee (9710)           60834 -> 5201 Len=100
3812    2010-01-01 08:11:35.075805      192.168.43.1    192.168.43.90   UDP      144     0x25f5 (9717)           60834 -> 5201 Len=100
3813    2010-01-01 08:11:35.075549      192.168.43.1    192.168.43.90   UDP      144     0x25ef (9711)           60834 -> 5201 Len=100
3814    2010-01-01 08:11:35.075944      192.168.43.1    192.168.43.90   UDP      144     0x25f6 (9718)           60834 -> 5201 Len=100
3815    2010-01-01 08:11:35.075567      192.168.43.1    192.168.43.90   UDP      144     0x25f0 (9712)           60834 -> 5201 Len=100 

out-of-order issue happens on:
1) ip_id=0x25f5 is received before ip_id=0x25ef, which are belong to the same downlink connection;
2) ip_id=0x25f6 is received before ip_id=0x25f0, which are belong to the same downlink connection.


[kernel log]:
We add debug log in rx kernel flow, such as netif_rx_ni() -> enqueue_to_backlog -> do_softirq() -> net_rx_action() -> process_backlog()

    kernel time
    |          cpu id which process running on
    |           |         process name         function name
    |           |         |                    |
[  598.837358] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25ee, pending=0x8a, backlog_state=1

// wifi rx_thread is running on cpu7 to receive rx packets of ip_id 0x25ee ~ 0x25f4, which are only enqueued.
[  598.837366] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25ee, input_qlen=1, proc_qlen=0, pending=0x8a, backlog_state=1  
 
// because ksoftirqd is in running queue, do_softirq() exit and net_rx_action isn't executed actually.
   
[  598.837373] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8a, ksoftirqd_running=1                          

[  598.837383] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25ef,input_qlen=2, proc_qlen=0, pending=0x8a, backlog_state=1 
[  598.837391] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0 pending=0x8a, ksoftirqd_running=1 
[  598.837400] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25f0,input_qlen=3, proc_qlen=0, pending=0x8a, backlog_state=1 
[  598.837407] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8a, ksoftirqd_running=1 
[  598.837417] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25f1,input_qlen=4, proc_qlen=0, pending=0x8a, backlog_state=1 
[  598.837424] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8a, ksoftirqd_running=1 
[  598.837434] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25f2,input_qlen=5, proc_qlen=0, pending=0x8a, backlog_state=1 
[  598.837441] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8a, ksoftirqd_running=1 
[  598.837450] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25f3,input_qlen=6, proc_qlen=0, pending=0x8a, backlog_state=1 
[  598.837458] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8a, ksoftirqd_running=1 

// after ip_id(0x25f4), there is no rx packet in this wifi interrupt, so rx_thread exit.
[  598.837470] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25f4,input_qlen=7, proc_qlen=0, pending=0x8a, backlog_state=1
[  598.837479] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8a, ksoftirqd_running=1                                  

//  ksoftirqd is scheduled to run and call do_softirq(), so net_rx_action() is executed.    
[  598.837511] (7)[45:ksoftirqd/7]: [RX]net_rx_action: budget=300, time=4295042005  
//  net_rx_action() call process_backlog() to handle rx packet of ip_id=0x25ee
                                                                                 
[  598.837646] (7)[45:ksoftirqd/7]: [RX]process_backlog: ip_id=0x25ee, delay=126308, work=1, input_qlen=0, proc_qlen=6  

// wifi interrupt happens and trigger rx_thread to receive the next rx packet, which is running on cpu1 this time. 
[  598.837660] (1)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25f5, input_qlen=1, proc_qlen=0, pending=0x8, backlog_state=1     
// because ksoftirqd is not running, net_rx softirq is executed immediately.
[  598.837666] (1)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8, ksoftirqd_running =0                                  

// so ksoftirqd on cpu7 and rx_thread on cpu1 are running at the same time.
[  598.837679] (1)[3282:rx_thread]: [RX]net_rx_action: budget=300, time=4295042005  
  
//  ip_id=0x25ef is handled on cpu7 by net_rx softirq in ksoftirqd() thread context.                                                                                      
[  598.837762] (7)[45:ksoftirqd/7]: [RX]process_backlog: ip_id=0x25ef, delay=70385, work=2, input_qlen=0, proc_qlen=5  
 
//  ip_id=0x25f5 is handled on cpu1 by net_rx softirq in rx_thread context, out-of-order issue happens.
                                                  
[  598.837768] (1)[3282:rx_thread]: [RX]process_backlog: ip_id=0x25f5, delay=82000, work=1, quota=64, input_qlen=0, proc_qlen=0 
             
//  ip_id=0x25f0 is handled on cpu7 by net_rx softirq in ksoftirqd() thread context.                              
[  598.837878] (7)[45:ksoftirqd/7]: [RX]process_backlog:ip_id=0x25f0, delay=47539, work=3, input_qlen=0, proc_qlen=4   

                               
Could you please help to check if this out-of-order issue is caused by kernel-4.9 patch above?

Thanks very much!

^ permalink raw reply

* RE: [PATCH 1/1] xen-netback: process malformed sk_buff correctly to avoid BUG_ON()
From: Paul Durrant @ 2018-03-28  9:21 UTC (permalink / raw)
  To: 'Dongli Zhang', xen-devel@lists.xenproject.org,
	linux-kernel@vger.kernel.org
  Cc: netdev@vger.kernel.org, Wei Liu
In-Reply-To: <1522194136-11985-1-git-send-email-dongli.zhang@oracle.com>

> -----Original Message-----
> From: Dongli Zhang [mailto:dongli.zhang@oracle.com]
> Sent: 28 March 2018 00:42
> To: xen-devel@lists.xenproject.org; linux-kernel@vger.kernel.org
> Cc: netdev@vger.kernel.org; Wei Liu <wei.liu2@citrix.com>; Paul Durrant
> <Paul.Durrant@citrix.com>
> Subject: [PATCH 1/1] xen-netback: process malformed sk_buff correctly to
> avoid BUG_ON()
> 
> The "BUG_ON(!frag_iter)" in function xenvif_rx_next_chunk() is triggered if
> the received sk_buff is malformed, that is, when the sk_buff has pattern
> (skb->data_len && !skb_shinfo(skb)->nr_frags). Below is a sample call
> stack:
> 
> [  438.652658] ------------[ cut here ]------------
> [  438.652660] kernel BUG at drivers/net/xen-netback/rx.c:325!
> [  438.652714] invalid opcode: 0000 [#1] SMP NOPTI
> [  438.652813] CPU: 0 PID: 2492 Comm: vif1.0-q0-guest Tainted: G           O
> 4.16.0-rc6+ #1
> [  438.652896] RIP: e030:xenvif_rx_skb+0x3c2/0x5e0 [xen_netback]
> [  438.652926] RSP: e02b:ffffc90040877dc8 EFLAGS: 00010246
> [  438.652956] RAX: 0000000000000160 RBX: 0000000000000022 RCX:
> 0000000000000001
> [  438.652993] RDX: ffffc900402890d0 RSI: 0000000000000000 RDI:
> ffffc90040889000
> [  438.653029] RBP: ffff88002b460040 R08: ffffc90040877de0 R09:
> 0100000000000000
> [  438.653065] R10: 0000000000007ff0 R11: 0000000000000002 R12:
> ffffc90040889000
> [  438.653100] R13: ffffffff80000000 R14: 0000000000000022 R15:
> 0000000080000000
> [  438.653149] FS:  00007f15603778c0(0000) GS:ffff880030400000(0000)
> knlGS:0000000000000000
> [  438.653188] CS:  e033 DS: 0000 ES: 0000 CR0: 0000000080050033
> [  438.653219] CR2: 0000000001832a08 CR3: 0000000029c12000 CR4:
> 0000000000042660
> [  438.653262] Call Trace:
> [  438.653284]  ? xen_hypercall_event_channel_op+0xa/0x20
> [  438.653313]  xenvif_rx_action+0x41/0x80 [xen_netback]
> [  438.653341]  xenvif_kthread_guest_rx+0xb2/0x2a8 [xen_netback]
> [  438.653374]  ? __schedule+0x352/0x700
> [  438.653398]  ? wait_woken+0x80/0x80
> [  438.653421]  kthread+0xf3/0x130
> [  438.653442]  ? xenvif_rx_action+0x80/0x80 [xen_netback]
> [  438.653470]  ? kthread_destroy_worker+0x40/0x40
> [  438.653497]  ret_from_fork+0x35/0x40
> 
> The issue is hit by xen-netback when there is bug with other networking
> interface (e.g., dom0 physical NIC), who has generated and forwarded
> malformed sk_buff to dom0 vifX.Y. It is possible to reproduce the issue on
> purpose with below sample code in a kernel module:
> 
> skb->dev = dev; // dev of vifX.Y
> skb->len = 386;
> skb->data_len = 352;
> skb->tail = 98;
> skb->end = 384;
> dev->netdev_ops->ndo_start_xmit(skb, dev);
> 
> This patch stops processing sk_buff immediately if it is detected as
> malformed, that is, pkt->frag_iter is NULL but there is still remaining
> pkt->remaining_len.
> 
> Signed-off-by: Dongli Zhang <dongli.zhang@oracle.com>
> ---
>  drivers/net/xen-netback/rx.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/drivers/net/xen-netback/rx.c b/drivers/net/xen-netback/rx.c
> index b1cf7c6..289cc82 100644
> --- a/drivers/net/xen-netback/rx.c
> +++ b/drivers/net/xen-netback/rx.c
> @@ -369,6 +369,14 @@ static void xenvif_rx_data_slot(struct xenvif_queue
> *queue,
>  		offset += len;
>  		pkt->remaining_len -= len;
> 
> +		if (unlikely(!pkt->frag_iter && pkt->remaining_len)) {
> +			pkt->remaining_len = 0;
> +			pkt->extra_count = 0;
> +			pr_err_ratelimited("malformed sk_buff at %s\n",
> +					   queue->name);
> +			break;
> +		}
> +

This looks fine, but I think it would also be good to indicate the error to the frontend by setting rsp->status below. That should cause the frontend to bin the packet.

  Paul

>  	} while (offset < XEN_PAGE_SIZE && pkt->remaining_len > 0);
> 
>  	if (pkt->remaining_len > 0)
> --
> 2.7.4

^ permalink raw reply

* Problems: network rx out-of-order issue
From: Anny Hu @ 2018-03-28  9:26 UTC (permalink / raw)
  To: netdev; +Cc: zhen.jiang

Dears,

Recently, we find the following patch will impact multi-core network throughput performance on kernel-4.9,
for it will cause rx packet out-of-order.
commit id: 4cd13c21b207e80ddb1144c576500098f2d5f882

[kernel version]: 
kernel-4.9

[repeat steps]
1. two our phones with load based on kernel-4.9, enable wifi and set up P2P connection; 
2. two reference phones with load based on kernel-4.4, enable wifi and set up P2P connection; 
3. do iperf UDP downlink test with the following commands;
Client: adb shell iperf -c 192.168.49.xx -u -i 1 -t 60 -b 15M
Server: adb shell iperf -s -u
4. out-of-order rate of our phones are obviously higher than reference phone:
DUT                                  Lost rate              out of order
Our phone                            0.011%                  164    
Reference phone                      0.0091%                 1

[Code flow]
Wi-Fi driver trigger rx_thread to receive rx packets and call netif_rx_ni() to push packets to tcp stack in thread context.

[netlog]:
No      Time                            Source ip       Dest ip         Protocol Len     Ip id                   Info
3811    2010-01-01 08:11:35.075522      192.168.43.1    192.168.43.90   UDP      144     0x25ee (9710)           60834 -> 5201 Len=100
3812    2010-01-01 08:11:35.075805      192.168.43.1    192.168.43.90   UDP      144     0x25f5 (9717)           60834 -> 5201 Len=100
3813    2010-01-01 08:11:35.075549      192.168.43.1    192.168.43.90   UDP      144     0x25ef (9711)           60834 -> 5201 Len=100
3814    2010-01-01 08:11:35.075944      192.168.43.1    192.168.43.90   UDP      144     0x25f6 (9718)           60834 -> 5201 Len=100
3815    2010-01-01 08:11:35.075567      192.168.43.1    192.168.43.90   UDP      144     0x25f0 (9712)           60834 -> 5201 Len=100 

out-of-order issue happens on:
1) ip_id=0x25f5 is received before ip_id=0x25ef, which are belong to the same downlink connection;
2) ip_id=0x25f6 is received before ip_id=0x25f0, which are belong to the same downlink connection.


[kernel log]:
We add debug log in rx kernel flow, such as netif_rx_ni() -> enqueue_to_backlog -> do_softirq() -> net_rx_action() -> process_backlog()

    kernel time
    |          cpu id which process running on
    |           |         process name         function name
    |           |         |                    |
[  598.837358] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25ee, pending=0x8a, backlog_state=1

// wifi rx_thread is running on cpu7 to receive rx packets of ip_id 0x25ee ~ 0x25f4, which are only enqueued.
[  598.837366] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25ee, input_qlen=1, proc_qlen=0, pending=0x8a, backlog_state=1  
 
// because ksoftirqd is in running queue, do_softirq() exit and net_rx_action isn't executed actually.
   
[  598.837373] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8a, ksoftirqd_running=1                          

[  598.837383] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25ef,input_qlen=2, proc_qlen=0, pending=0x8a, backlog_state=1 
[  598.837391] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0 pending=0x8a, ksoftirqd_running=1 
[  598.837400] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25f0,input_qlen=3, proc_qlen=0, pending=0x8a, backlog_state=1 
[  598.837407] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8a, ksoftirqd_running=1 
[  598.837417] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25f1,input_qlen=4, proc_qlen=0, pending=0x8a, backlog_state=1 
[  598.837424] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8a, ksoftirqd_running=1 
[  598.837434] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25f2,input_qlen=5, proc_qlen=0, pending=0x8a, backlog_state=1 
[  598.837441] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8a, ksoftirqd_running=1 
[  598.837450] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25f3,input_qlen=6, proc_qlen=0, pending=0x8a, backlog_state=1 
[  598.837458] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8a, ksoftirqd_running=1 

// after ip_id(0x25f4), there is no rx packet in this wifi interrupt, so rx_thread exit.
[  598.837470] (7)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25f4,input_qlen=7, proc_qlen=0, pending=0x8a, backlog_state=1
[  598.837479] (7)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8a, ksoftirqd_running=1                                  

// ksoftirqd is scheduled to run and call do_softirq(), so net_rx_action() is executed.    
[  598.837511] (7)[45:ksoftirqd/7]: [RX]net_rx_action: budget=300, time=4295042005  
//  net_rx_action() call process_backlog() to handle rx packet of ip_id=0x25ee
                                                                                 
[  598.837646] (7)[45:ksoftirqd/7]: [RX]process_backlog: ip_id=0x25ee, delay=126308, work=1, input_qlen=0, proc_qlen=6  

// wifi interrupt happens and trigger rx_thread to receive the next rx packet, which is running on cpu1 this time. 
[  598.837660] (1)[3282:rx_thread]: [RX]enqueue_to_backlog: ip_id=0x25f5, input_qlen=1, proc_qlen=0, pending=0x8, backlog_state=1     
// because ksoftirqd is not running, net_rx softirq is executed immediately.
[  598.837666] (1)[3282:rx_thread]: [RX]do_softirq: preempt=0x1, in_interrupt()=0x0, pending=0x8, ksoftirqd_running =0                                  

// so ksoftirqd on cpu7 and rx_thread on cpu1 are running at the same time.
[  598.837679] (1)[3282:rx_thread]: [RX]net_rx_action: budget=300, time=4295042005  
  
// ip_id=0x25ef is handled on cpu7 by net_rx softirq in ksoftirqd() thread context.                                                                                      
[  598.837762] (7)[45:ksoftirqd/7]: [RX]process_backlog: ip_id=0x25ef, delay=70385, work=2, input_qlen=0, proc_qlen=5  
 
// ip_id=0x25f5 is handled on cpu1 by net_rx softirq in rx_thread context, out-of-order issue happens.
                                                  
[  598.837768] (1)[3282:rx_thread]: [RX]process_backlog: ip_id=0x25f5, delay=82000, work=1, quota=64, input_qlen=0, proc_qlen=0 
             
// ip_id=0x25f0 is handled on cpu7 by net_rx softirq in ksoftirqd() thread context.                              
[  598.837878] (7)[45:ksoftirqd/7]: [RX]process_backlog:ip_id=0x25f0, delay=47539, work=3, input_qlen=0, proc_qlen=4   

                               
Could you please help to check if this out-of-order issue is caused by kernel-4.9 patch above?

Thanks very much!

^ permalink raw reply

* Re: [PATCH net-next 2/4] net: phy: phylink: Provide PHY interface to mac_link_{up,down}
From: Russell King - ARM Linux @ 2018-03-28  9:50 UTC (permalink / raw)
  To: Florian Fainelli
  Cc: netdev, privat, andrew, vivien.didelot, davem, sean.wang,
	Woojung.Huh, john, cphealy
In-Reply-To: <20180318185246.19311-3-f.fainelli@gmail.com>

On Sun, Mar 18, 2018 at 11:52:44AM -0700, Florian Fainelli wrote:
> In preparation for having DSA transition entirely to PHYLINK, we need to pass a
> PHY interface type to the mac_link_{up,down} callbacks because we may have to
> make decisions on that (e.g: turn on/off RGMII interfaces etc.). We do not pass
> an entire phylink_link_state because not all parameters (pause, duplex etc.) are
> defined when the link is down, only link and interface are.

If we're going to make this change, we ought to decide whether David
should pick this up for the coming merge window or not independently
of the remaining patches - there are other users of phylink in the
pipeline (bootlin are working on mvpp2 support, so this will be a
minor source of build error pain for folk.)

To that end,

Acked-by: Russell King <rmk+kernel@armlinux.org.uk>

However, the documentation probably ought to make it clear that the
configuration of the interface mode of the MAC should always happen
in the mac_config() callback, not in the mac_link_*() functions.

Thanks.

> Update mvneta accordingly since it currently implements phylink_mac_ops.
> 
> Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
> ---
>  drivers/net/ethernet/marvell/mvneta.c |  4 +++-
>  drivers/net/phy/phylink.c             |  6 +++++-
>  include/linux/phylink.h               | 10 ++++++++--
>  3 files changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
> index 25e9a551cc8c..60de9b8d62c2 100644
> --- a/drivers/net/ethernet/marvell/mvneta.c
> +++ b/drivers/net/ethernet/marvell/mvneta.c
> @@ -3396,7 +3396,8 @@ static void mvneta_set_eee(struct mvneta_port *pp, bool enable)
>  	mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi_ctl1);
>  }
>  
> -static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode)
> +static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode,
> +				 phy_interface_t interface)
>  {
>  	struct mvneta_port *pp = netdev_priv(ndev);
>  	u32 val;
> @@ -3415,6 +3416,7 @@ static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode)
>  }
>  
>  static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode,
> +			       phy_interface_t interface,
>  			       struct phy_device *phy)
>  {
>  	struct mvneta_port *pp = netdev_priv(ndev);
> diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
> index 51a011a349fe..cef3c1356a8c 100644
> --- a/drivers/net/phy/phylink.c
> +++ b/drivers/net/phy/phylink.c
> @@ -423,8 +423,10 @@ static void phylink_resolve(struct work_struct *w)
>  	if (pl->phylink_disable_state) {
>  		pl->mac_link_dropped = false;
>  		link_state.link = false;
> +		link_state.interface = pl->phy_state.interface;
>  	} else if (pl->mac_link_dropped) {
>  		link_state.link = false;
> +		link_state.interface = pl->phy_state.interface;
>  	} else {
>  		switch (pl->link_an_mode) {
>  		case MLO_AN_PHY:
> @@ -470,10 +472,12 @@ static void phylink_resolve(struct work_struct *w)
>  	if (link_state.link != netif_carrier_ok(ndev)) {
>  		if (!link_state.link) {
>  			netif_carrier_off(ndev);
> -			pl->ops->mac_link_down(ndev, pl->link_an_mode);
> +			pl->ops->mac_link_down(ndev, pl->link_an_mode,
> +					       pl->phy_state.interface);
>  			netdev_info(ndev, "Link is Down\n");
>  		} else {
>  			pl->ops->mac_link_up(ndev, pl->link_an_mode,
> +					     pl->phy_state.interface,
>  					     pl->phydev);
>  
>  			netif_carrier_on(ndev);
> diff --git a/include/linux/phylink.h b/include/linux/phylink.h
> index bd137c273d38..f29a40947de9 100644
> --- a/include/linux/phylink.h
> +++ b/include/linux/phylink.h
> @@ -73,8 +73,10 @@ struct phylink_mac_ops {
>  	void (*mac_config)(struct net_device *ndev, unsigned int mode,
>  			   const struct phylink_link_state *state);
>  	void (*mac_an_restart)(struct net_device *ndev);
> -	void (*mac_link_down)(struct net_device *ndev, unsigned int mode);
> +	void (*mac_link_down)(struct net_device *ndev, unsigned int mode,
> +			      phy_interface_t interface);
>  	void (*mac_link_up)(struct net_device *ndev, unsigned int mode,
> +			    phy_interface_t interface,
>  			    struct phy_device *phy);
>  };
>  
> @@ -161,17 +163,20 @@ void mac_an_restart(struct net_device *ndev);
>   * mac_link_down() - take the link down
>   * @ndev: a pointer to a &struct net_device for the MAC.
>   * @mode: link autonegotiation mode
> + * @interface: link &typedef phy_interface_t mode
>   *
>   * If @mode is not an in-band negotiation mode (as defined by
>   * phylink_autoneg_inband()), force the link down and disable any
>   * Energy Efficient Ethernet MAC configuration.
>   */
> -void mac_link_down(struct net_device *ndev, unsigned int mode);
> +void mac_link_down(struct net_device *ndev, unsigned int mode,
> +		   phy_interface_t interface);
>  
>  /**
>   * mac_link_up() - allow the link to come up
>   * @ndev: a pointer to a &struct net_device for the MAC.
>   * @mode: link autonegotiation mode
> + * @interface: link &typedef phy_interface_t mode
>   * @phy: any attached phy
>   *
>   * If @mode is not an in-band negotiation mode (as defined by
> @@ -180,6 +185,7 @@ void mac_link_down(struct net_device *ndev, unsigned int mode);
>   * phy_init_eee() and perform appropriate MAC configuration for EEE.
>   */
>  void mac_link_up(struct net_device *ndev, unsigned int mode,
> +		 phy_interface_t interface,
>  		 struct phy_device *phy);
>  #endif
>  
> -- 
> 2.14.1
> 

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply

* Re: RFC on writel and writel_relaxed
From: Benjamin Herrenschmidt @ 2018-03-28  9:56 UTC (permalink / raw)
  To: Will Deacon
  Cc: Linus Torvalds, Alexander Duyck, Sinan Kaya, Arnd Bergmann,
	Jason Gunthorpe, David Laight, Oliver,
	open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
	linux-rdma@vger.kernel.org, Paul E. McKenney,
	netdev@vger.kernel.org
In-Reply-To: <20180328090710.GB28871@arm.com>

On Wed, 2018-03-28 at 10:07 +0100, Will Deacon wrote:
> 
> For arm/arm64 we guarantee ordering for (1) but not for (2) -- you'd need to
> add an mb() to make it work.
> 
> Do both of these work on power? 

Yes. There's even another quirk, see further down ;-)

> If so, I guess I can make readl even more
> expensive :/ Feels a bit like the tail wagging the dog, though.

Maybe, but then readl is always horribly slow anyway so you may not
necessarily be losing that much.

> Another thing I just realised is that we restrict the barriers we use in
> readl/writel on arm64 so that they don't necessary apply to both loads and
> stores. To be specific:
> 
>    writel is ordered against prior writes to memory, but not reads

That could be tricky... You may end up with something that reads before
triggering a DMA and ends up with the post-DMA value ... ugh.

>    readl is ordered against subsequent reads of memory, but not writes (but
>    note that in example (1) above, the control dependency ensures that).
> 
> If necessary, I could move the barrier in our readl implementation to be
> before the read, then play the control-dependency + instruction-sync (ISB)
> trick that you do on power.

Yeah so that other trick I'm talking about is also used for timing
accuracy.

For example, let's say I have a device with a reset bit and the spec
says the reset bit needs to be set for at least 10us.

This is wrong:

	writel(1, RESET_REG);
	usleep(10);
	writel(0, RESET_REG);

Because of write posting, the first write might arrive to the device
right before the second one.

The typical "fix" is to turn that into:

	writel(1, RESET_REG);
	readl(RESET_REG); /* Flush posted writes */
	usleep(10);
	writel(0, RESET_REG);

*However* the issue here, at least on power, is that the CPU can issue
that readl but doesn't necessarily wait for it to complete (ie, the
data to return), before proceeding to the usleep. Now a usleep contains
a bunch of loads and stores and is probably fine, but a udelay which
just loops on the timebase may not be.

Thus we may still violate the timing requirement.

What we did inside readl, with the twi;isync sequence (which basically
means, trap on return value with "trap never" as a condition, followed
by isync that ensures all excpetion conditions are resolved), is force
the CPU to "consume" the data from the read before moving on.

This effectively makes readl fully synchronous (we would probably avoid
that if we were to implement a readl_relaxed).

Cheers,
Ben.

^ permalink raw reply

* [PATCH] samples/bpf: fix spelling mistake: "revieve" -> "receive"
From: Colin King @ 2018-03-28 10:07 UTC (permalink / raw)
  To: Alexei Starovoitov, Daniel Borkmann, netdev; +Cc: kernel-janitors, linux-kernel

From: Colin Ian King <colin.king@canonical.com>

Trivial fix to spelling mistake in error message text

Signed-off-by: Colin Ian King <colin.king@canonical.com>
---
 samples/bpf/cookie_uid_helper_example.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/samples/bpf/cookie_uid_helper_example.c b/samples/bpf/cookie_uid_helper_example.c
index 9d751e209f31..8eca27e595ae 100644
--- a/samples/bpf/cookie_uid_helper_example.c
+++ b/samples/bpf/cookie_uid_helper_example.c
@@ -246,7 +246,7 @@ static void udp_client(void)
 		recv_len = recvfrom(s_rcv, &buf, sizeof(buf), 0,
 			     (struct sockaddr *)&si_me, &slen);
 		if (recv_len < 0)
-			error(1, errno, "revieve\n");
+			error(1, errno, "receive\n");
 		res = memcmp(&(si_other.sin_addr), &(si_me.sin_addr),
 			   sizeof(si_me.sin_addr));
 		if (res != 0)
-- 
2.15.1

^ permalink raw reply related

* Aw: Re: RFC on writel and writel_relaxed
From: Lino Sanfilippo @ 2018-03-28 10:13 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Will Deacon, Linus Torvalds, Alexander Duyck, Sinan Kaya,
	Arnd Bergmann, Jason Gunthorpe, David Laight, Oliver,
	open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
	linux-rdma@vger.kernel.org, Paul E. McKenney,
	netdev@vger.kernel.org
In-Reply-To: <1522230988.21446.7.camel@kernel.crashing.org>

Hi,


> 
> Yeah so that other trick I'm talking about is also used for timing
> accuracy.
> 
> For example, let's say I have a device with a reset bit and the spec
> says the reset bit needs to be set for at least 10us.
> 
> This is wrong:
> 
> 	writel(1, RESET_REG);
> 	usleep(10);
> 	writel(0, RESET_REG);
> 
> Because of write posting, the first write might arrive to the device
> right before the second one.
> 

Does not write posting only concern PCI? This seems to be a different topic. Furthermore
write posting should not include write reordering...

Regards,
Lino

^ permalink raw reply

* Re: [PATCH] staging: fsl-dpaa2/ethsw: Fix TCI values overwrite
From: kbuild test robot @ 2018-03-28 10:15 UTC (permalink / raw)
  To: Razvan Stefanescu
  Cc: devel, andrew, stuyoder, gregkh, ioana.ciornei,
	alexandru.marginean, linux-kernel, kbuild-all, netdev,
	laurentiu.tudor
In-Reply-To: <20180327131050.30581-1-razvan.stefanescu@nxp.com>

[-- Attachment #1: Type: text/plain, Size: 3042 bytes --]

Hi Razvan,

I love your patch! Yet something to improve:

[auto build test ERROR on staging/staging-testing]
[also build test ERROR on next-20180327]
[cannot apply to v4.16-rc7]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Razvan-Stefanescu/staging-fsl-dpaa2-ethsw-Fix-TCI-values-overwrite/20180328-154703
config: i386-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   drivers/staging/fsl-dpaa2/ethsw/dpsw.c: In function 'dpsw_if_get_tci':
>> drivers/staging/fsl-dpaa2/ethsw/dpsw.c:547:9: error: variable 'cmd' has initializer but incomplete type
     struct mc_command cmd = { 0 };
            ^~~~~~~~~~
>> drivers/staging/fsl-dpaa2/ethsw/dpsw.c:547:28: warning: excess elements in struct initializer
     struct mc_command cmd = { 0 };
                               ^
   drivers/staging/fsl-dpaa2/ethsw/dpsw.c:547:28: note: (near initialization for 'cmd')
>> drivers/staging/fsl-dpaa2/ethsw/dpsw.c:547:20: error: storage size of 'cmd' isn't known
     struct mc_command cmd = { 0 };
                       ^~~
   drivers/staging/fsl-dpaa2/ethsw/dpsw.c:547:20: warning: unused variable 'cmd' [-Wunused-variable]

vim +/cmd +547 drivers/staging/fsl-dpaa2/ethsw/dpsw.c

   530	
   531	/**
   532	 * dpsw_if_get_tci() - Get default VLAN Tag Control Information (TCI)
   533	 * @mc_io:	Pointer to MC portal's I/O object
   534	 * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
   535	 * @token:	Token of DPSW object
   536	 * @if_id:	Interface Identifier
   537	 * @cfg:	Tag Control Information Configuration
   538	 *
   539	 * Return:	Completion status. '0' on Success; Error code otherwise.
   540	 */
   541	int dpsw_if_get_tci(struct fsl_mc_io *mc_io,
   542			    u32 cmd_flags,
   543			    u16 token,
   544			    u16 if_id,
   545			    struct dpsw_tci_cfg *cfg)
   546	{
 > 547		struct mc_command cmd = { 0 };
   548		struct dpsw_cmd_if_get_tci *cmd_params;
   549		struct dpsw_rsp_if_get_tci *rsp_params;
   550		int err;
   551	
   552		/* prepare command */
   553		cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_TCI,
   554						  cmd_flags,
   555						  token);
   556		cmd_params = (struct dpsw_cmd_if_get_tci *)cmd.params;
   557		cmd_params->if_id = cpu_to_le16(if_id);
   558	
   559		/* send command to mc*/
   560		err = mc_send_command(mc_io, &cmd);
   561		if (err)
   562			return err;
   563	
   564		/* retrieve response parameters */
   565		rsp_params = (struct dpsw_rsp_if_get_tci *)cmd.params;
   566		cfg->pcp = rsp_params->pcp;
   567		cfg->dei = rsp_params->dei;
   568		cfg->vlan_id = le16_to_cpu(rsp_params->vlan_id);
   569	
   570		return 0;
   571	}
   572	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 62898 bytes --]

[-- Attachment #3: Type: text/plain, Size: 169 bytes --]

_______________________________________________
devel mailing list
devel@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

^ permalink raw reply

* [PATCH] sfp: allow cotsworks modules
From: Russell King @ 2018-03-28 10:18 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli; +Cc: netdev

Cotsworks modules fail the checksums - it appears that Cotsworks
reprograms the EEPROM at the end of production with the final product
information (serial, date code, and exact part number for module
options) and fails to update the checksum.

Work around this by detecting the Cotsworks name in the manufacturer
field, and reducing the checksum failures to warnings rather than a
hard error.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/sfp.c | 41 +++++++++++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 10 deletions(-)

diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 83bf4959b043..4ab6e9a50bbe 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -560,6 +560,7 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
 {
 	/* SFP module inserted - read I2C data */
 	struct sfp_eeprom_id id;
+	bool cotsworks;
 	u8 check;
 	int ret;
 
@@ -574,23 +575,43 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
 		return -EAGAIN;
 	}
 
+	/* Cotsworks do not seem to update the checksums when they
+	 * do the final programming with the final module part number,
+	 * serial number and date code.
+	 */
+	cotsworks = !memcmp(id.base.vendor_name, "COTSWORKS       ", 16);
+
 	/* Validate the checksum over the base structure */
 	check = sfp_check(&id.base, sizeof(id.base) - 1);
 	if (check != id.base.cc_base) {
-		dev_err(sfp->dev,
-			"EEPROM base structure checksum failure: 0x%02x\n",
-			check);
-		print_hex_dump(KERN_ERR, "sfp EE: ", DUMP_PREFIX_OFFSET,
-			       16, 1, &id, sizeof(id.base) - 1, true);
-		return -EINVAL;
+		if (cotsworks) {
+			dev_warn(sfp->dev,
+				 "EEPROM base structure checksum failure (0x%02x != 0x%02x)\n",
+				 check, id.base.cc_base);
+		} else {
+			dev_err(sfp->dev,
+				"EEPROM base structure checksum failure: 0x%02x != 0x%02x\n",
+				check, id.base.cc_base);
+			print_hex_dump(KERN_ERR, "sfp EE: ", DUMP_PREFIX_OFFSET,
+				       16, 1, &id, sizeof(id), true);
+			return -EINVAL;
+		}
 	}
 
 	check = sfp_check(&id.ext, sizeof(id.ext) - 1);
 	if (check != id.ext.cc_ext) {
-		dev_err(sfp->dev,
-			"EEPROM extended structure checksum failure: 0x%02x\n",
-			check);
-		memset(&id.ext, 0, sizeof(id.ext));
+		if (cotsworks) {
+			dev_warn(sfp->dev,
+				 "EEPROM extended structure checksum failure (0x%02x != 0x%02x)\n",
+				 check, id.ext.cc_ext);
+		} else {
+			dev_err(sfp->dev,
+				"EEPROM extended structure checksum failure: 0x%02x != 0x%02x\n",
+				check, id.ext.cc_ext);
+			print_hex_dump(KERN_ERR, "sfp EE: ", DUMP_PREFIX_OFFSET,
+				       16, 1, &id, sizeof(id), true);
+			memset(&id.ext, 0, sizeof(id.ext));
+		}
 	}
 
 	sfp->id = id;
-- 
2.7.4

^ permalink raw reply related

* [PATCH] net: phy: marvell10g: add thermal hwmon device
From: Russell King @ 2018-03-28 10:20 UTC (permalink / raw)
  To: Andrew Lunn, Florian Fainelli; +Cc: netdev

Add a thermal monitoring device for the Marvell 88x3310, which updates
once a second.  We also need to hook into the suspend/resume mechanism
to ensure that the thermal monitoring is reconfigured when we resume.

Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
 drivers/net/phy/marvell10g.c | 184 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 182 insertions(+), 2 deletions(-)

diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 8a0bd98fdec7..db9d66781da6 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -21,8 +21,10 @@
  * If both the fiber and copper ports are connected, the first to gain
  * link takes priority and the other port is completely locked out.
  */
-#include <linux/phy.h>
+#include <linux/ctype.h>
+#include <linux/hwmon.h>
 #include <linux/marvell_phy.h>
+#include <linux/phy.h>
 
 enum {
 	MV_PCS_BASE_T		= 0x0000,
@@ -40,6 +42,19 @@ enum {
 	 */
 	MV_AN_CTRL1000		= 0x8000, /* 1000base-T control register */
 	MV_AN_STAT1000		= 0x8001, /* 1000base-T status register */
+
+	/* Vendor2 MMD registers */
+	MV_V2_TEMP_CTRL		= 0xf08a,
+	MV_V2_TEMP_CTRL_MASK	= 0xc000,
+	MV_V2_TEMP_CTRL_SAMPLE	= 0x0000,
+	MV_V2_TEMP_CTRL_DISABLE	= 0xc000,
+	MV_V2_TEMP		= 0xf08c,
+	MV_V2_TEMP_UNKNOWN	= 0x9600, /* unknown function */
+};
+
+struct mv3310_priv {
+	struct device *hwmon_dev;
+	char *hwmon_name;
 };
 
 static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
@@ -60,17 +75,180 @@ static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
 	return ret < 0 ? ret : 1;
 }
 
+#ifdef CONFIG_HWMON
+static umode_t mv3310_hwmon_is_visible(const void *data,
+				       enum hwmon_sensor_types type,
+				       u32 attr, int channel)
+{
+	if (type == hwmon_chip && attr == hwmon_chip_update_interval)
+		return 0444;
+	if (type == hwmon_temp && attr == hwmon_temp_input)
+		return 0444;
+	return 0;
+}
+
+static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
+			     u32 attr, int channel, long *value)
+{
+	struct phy_device *phydev = dev_get_drvdata(dev);
+	int temp;
+
+	if (type == hwmon_chip && attr == hwmon_chip_update_interval) {
+		*value = MSEC_PER_SEC;
+		return 0;
+	}
+
+	if (type == hwmon_temp && attr == hwmon_temp_input) {
+		temp = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP);
+		if (temp < 0)
+			return temp;
+
+		*value = ((temp & 0xff) - 75) * 1000;
+
+		return 0;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static const struct hwmon_ops mv3310_hwmon_ops = {
+	.is_visible = mv3310_hwmon_is_visible,
+	.read = mv3310_hwmon_read,
+};
+
+static u32 mv3310_hwmon_chip_config[] = {
+	HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL,
+	0,
+};
+
+static const struct hwmon_channel_info mv3310_hwmon_chip = {
+	.type = hwmon_chip,
+	.config = mv3310_hwmon_chip_config,
+};
+
+static u32 mv3310_hwmon_temp_config[] = {
+	HWMON_T_INPUT,
+	0,
+};
+
+static const struct hwmon_channel_info mv3310_hwmon_temp = {
+	.type = hwmon_temp,
+	.config = mv3310_hwmon_temp_config,
+};
+
+static const struct hwmon_channel_info *mv3310_hwmon_info[] = {
+	&mv3310_hwmon_chip,
+	&mv3310_hwmon_temp,
+	NULL,
+};
+
+static const struct hwmon_chip_info mv3310_hwmon_chip_info = {
+	.ops = &mv3310_hwmon_ops,
+	.info = mv3310_hwmon_info,
+};
+
+static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
+{
+	u16 val;
+	int ret;
+
+	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP,
+			    MV_V2_TEMP_UNKNOWN);
+	if (ret < 0)
+		return ret;
+
+	val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE;
+	ret = mv3310_modify(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,
+			    MV_V2_TEMP_CTRL_MASK, val);
+
+	return ret < 0 ? ret : 0;
+}
+
+static void mv3310_hwmon_disable(void *data)
+{
+	struct phy_device *phydev = data;
+
+	mv3310_hwmon_config(phydev, false);
+}
+
+static int mv3310_hwmon_probe(struct phy_device *phydev)
+{
+	struct device *dev = &phydev->mdio.dev;
+	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
+	int i, j, ret;
+
+	priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
+	if (!priv->hwmon_name)
+		return -ENODEV;
+
+	for (i = j = 0; priv->hwmon_name[i]; i++) {
+		if (isalnum(priv->hwmon_name[i])) {
+			if (i != j)
+				priv->hwmon_name[j] = priv->hwmon_name[i];
+			j++;
+		}
+	}
+	priv->hwmon_name[j] = '\0';
+
+	ret = mv3310_hwmon_config(phydev, true);
+	if (ret)
+		return ret;
+
+	ret = devm_add_action_or_reset(dev, mv3310_hwmon_disable, phydev);
+	if (ret)
+		return ret;
+
+	priv->hwmon_dev = devm_hwmon_device_register_with_info(dev,
+				priv->hwmon_name, phydev,
+				&mv3310_hwmon_chip_info, NULL);
+
+	return PTR_ERR_OR_ZERO(priv->hwmon_dev);
+}
+#else
+static inline int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
+{
+	return 0;
+}
+
+static int mv3310_hwmon_probe(struct phy_device *phydev)
+{
+	return 0;
+}
+#endif
+
 static int mv3310_probe(struct phy_device *phydev)
 {
+	struct mv3310_priv *priv;
 	u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
+	int ret;
 
 	if (!phydev->is_c45 ||
 	    (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
 		return -ENODEV;
 
+	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	dev_set_drvdata(&phydev->mdio.dev, priv);
+
+	ret = mv3310_hwmon_probe(phydev);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int mv3310_suspend(struct phy_device *phydev)
+{
 	return 0;
 }
 
+static int mv3310_resume(struct phy_device *phydev)
+{
+	return mv3310_hwmon_config(phydev, true);
+}
+
 /*
  * Resetting the MV88X3310 causes it to become non-responsive.  Avoid
  * setting the reset bit(s).
@@ -376,9 +554,11 @@ static struct phy_driver mv3310_drivers[] = {
 				  SUPPORTED_FIBRE |
 				  SUPPORTED_10000baseT_Full |
 				  SUPPORTED_Backplane,
-		.probe		= mv3310_probe,
 		.soft_reset	= mv3310_soft_reset,
 		.config_init	= mv3310_config_init,
+		.probe		= mv3310_probe,
+		.suspend	= mv3310_suspend,
+		.resume		= mv3310_resume,
 		.config_aneg	= mv3310_config_aneg,
 		.aneg_done	= mv3310_aneg_done,
 		.read_status	= mv3310_read_status,
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH] sfp: allow cotsworks modules
From: Joe Perches @ 2018-03-28 10:33 UTC (permalink / raw)
  To: Russell King, Andrew Lunn, Florian Fainelli; +Cc: netdev
In-Reply-To: <E1f189x-00059j-J9@rmk-PC.armlinux.org.uk>

On Wed, 2018-03-28 at 11:18 +0100, Russell King wrote:
> Cotsworks modules fail the checksums - it appears that Cotsworks
> reprograms the EEPROM at the end of production with the final product
> information (serial, date code, and exact part number for module
> options) and fails to update the checksum.

trivia:

> diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
[]
> @@ -574,23 +575,43 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
[]
> +		if (cotsworks) {
> +			dev_warn(sfp->dev,
> +				 "EEPROM base structure checksum failure (0x%02x != 0x%02x)\n",
> +				 check, id.base.cc_base);
> +		} else {
> +			dev_err(sfp->dev,
> +				"EEPROM base structure checksum failure: 0x%02x != 0x%02x\n",

It'd be better to move this above the if and
use only a single format string instead of
using 2 slightly different formats.

> +				check, id.base.cc_base);
> +			print_hex_dump(KERN_ERR, "sfp EE: ", DUMP_PREFIX_OFFSET,
> +				       16, 1, &id, sizeof(id), true);
> +			return -EINVAL;
> +		}
>  	}
>  
>  	check = sfp_check(&id.ext, sizeof(id.ext) - 1);
>  	if (check != id.ext.cc_ext) {
> -		dev_err(sfp->dev,
> -			"EEPROM extended structure checksum failure: 0x%02x\n",
> -			check);
> -		memset(&id.ext, 0, sizeof(id.ext));
> +		if (cotsworks) {
> +			dev_warn(sfp->dev,
> +				 "EEPROM extended structure checksum failure (0x%02x != 0x%02x)\n",
> +				 check, id.ext.cc_ext);
> +		} else {
> +			dev_err(sfp->dev,
> +				"EEPROM extended structure checksum failure: 0x%02x != 0x%02x\n",
> +				check, id.ext.cc_ext);


here too

^ permalink raw reply

* [PATCH net 1/1] qede: Do not drop rx-checksum invalidated packets.
From: Manish Chopra @ 2018-03-28 10:35 UTC (permalink / raw)
  To: davem; +Cc: netdev, ariel.elior

Today, driver drops received packets which are indicated as
invalid checksum by the device. Instead of dropping such packets,
pass them to the stack with CHECKSUM_NONE indication in skb.

Signed-off-by: Ariel Elior <ariel.elior@cavium.com>
Signed-off-by: Manish Chopra <manish.chopra@cavium.com>
---
 drivers/net/ethernet/qlogic/qede/qede_fp.c |   10 ++--------
 1 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ethernet/qlogic/qede/qede_fp.c b/drivers/net/ethernet/qlogic/qede/qede_fp.c
index 2e921ca..1494130 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_fp.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_fp.c
@@ -1247,16 +1247,10 @@ static int qede_rx_process_cqe(struct qede_dev *edev,
 
 	csum_flag = qede_check_csum(parse_flag);
 	if (unlikely(csum_flag == QEDE_CSUM_ERROR)) {
-		if (qede_pkt_is_ip_fragmented(fp_cqe, parse_flag)) {
+		if (qede_pkt_is_ip_fragmented(fp_cqe, parse_flag))
 			rxq->rx_ip_frags++;
-		} else {
-			DP_NOTICE(edev,
-				  "CQE has error, flags = %x, dropping incoming packet\n",
-				  parse_flag);
+		else
 			rxq->rx_hw_errors++;
-			qede_recycle_rx_bd_ring(rxq, fp_cqe->bd_num);
-			return 0;
-		}
 	}
 
 	/* Basic validation passed; Need to prepare an SKB. This would also
-- 
1.7.1

^ permalink raw reply related

* Re: Aw: Re: RFC on writel and writel_relaxed
From: Benjamin Herrenschmidt @ 2018-03-28 10:20 UTC (permalink / raw)
  To: Lino Sanfilippo
  Cc: Will Deacon, Linus Torvalds, Alexander Duyck, Sinan Kaya,
	Arnd Bergmann, Jason Gunthorpe, David Laight, Oliver,
	open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
	linux-rdma@vger.kernel.org, Paul E. McKenney,
	netdev@vger.kernel.org
In-Reply-To: <trinity-2ee224b5-cbac-415e-9f8c-305e802b5369-1522232002354@3c-app-gmx-bs61>

On Wed, 2018-03-28 at 12:13 +0200, Lino Sanfilippo wrote:
> Hi,
> 
> 
> > 
> > Yeah so that other trick I'm talking about is also used for timing
> > accuracy.
> > 
> > For example, let's say I have a device with a reset bit and the spec
> > says the reset bit needs to be set for at least 10us.
> > 
> > This is wrong:
> > 
> > 	writel(1, RESET_REG);
> > 	usleep(10);
> > 	writel(0, RESET_REG);
> > 
> > Because of write posting, the first write might arrive to the device
> > right before the second one.
> > 
> 
> Does not write posting only concern PCI? This seems to be a different topic. Furthermore
> write posting should not include write reordering...

Nobody's talking about re-ordering and no, write posting is rather
common practice on a whole lot of different busses, not just PCI(e).

Cheers,
Ben.

^ permalink raw reply

* Re: A cry for help, please don't ignore!
From: Sandra Y @ 2018-03-28 10:40 UTC (permalink / raw)


Good Day,

Forgive my indignation if this message comes to you as a surprise and may offend your personality for contacting you without your prior consent and writing through this channel.

I came across your name and contact on the course of my personal searching when i was searching for a foreign reliable partner. I was assured of your capability and reliability after going true your profile.

I'm (Miss. Sandra) from Benghazi libya, My father of blessed memory by name late General Abdel Fattah Younes who was shot death by Islamist-linked militia within the anti-Gaddafi forces on 28th July, 2011 and after two days later my mother with my two brothers was killed one early morning by the rebels as result of civil war that is going on in my country Libya, then after the burial of my parents, my uncles conspired and sold my father's properties and left nothing for me. On a faithful morning, I opened my father's briefcase and discover a document which he has deposited ($6.250M USD) in a bank in a Turkish Bank which has a small branch in Canada with my name as the legitimate/next of kin. Meanwhile i have located the bank,and have also discussed the possiblity of transfering the fund. M
 y father left a clause to the bank that i must introduce a trusted foreign partner who would be my trustee to help me invest this fund; hence the need for your assistance,
i request that you be my trustee and assist me in this process.

You will also be responsible for the investment and management of the fund for me and also you will help me get a good school where i will further my education.
I agreed to give you 40% of the $6.250M once the transfer is done. this is my true life story, I will be glad to receive your respond soonest for more details to enable us start and champion the transfer less than 14 banking days as i was informed by the bank manager.

Thanks for giving me your attention,

Yours sincerely,
Miss. Sandra Younes

^ permalink raw reply

* Re: [PATCH] sfp: allow cotsworks modules
From: Russell King - ARM Linux @ 2018-03-28 10:41 UTC (permalink / raw)
  To: Joe Perches; +Cc: Andrew Lunn, Florian Fainelli, netdev
In-Reply-To: <1522233237.12357.96.camel@perches.com>

On Wed, Mar 28, 2018 at 03:33:57AM -0700, Joe Perches wrote:
> On Wed, 2018-03-28 at 11:18 +0100, Russell King wrote:
> > Cotsworks modules fail the checksums - it appears that Cotsworks
> > reprograms the EEPROM at the end of production with the final product
> > information (serial, date code, and exact part number for module
> > options) and fails to update the checksum.
> 
> trivia:
> 
> > diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
> []
> > @@ -574,23 +575,43 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
> []
> > +		if (cotsworks) {
> > +			dev_warn(sfp->dev,
> > +				 "EEPROM base structure checksum failure (0x%02x != 0x%02x)\n",
> > +				 check, id.base.cc_base);
> > +		} else {
> > +			dev_err(sfp->dev,
> > +				"EEPROM base structure checksum failure: 0x%02x != 0x%02x\n",
> 
> It'd be better to move this above the if and
> use only a single format string instead of
> using 2 slightly different formats.

No.  I think you've missed the fact that one is a _warning_ the other is
an _error_ and they are emitted at the appropriate severity.  It's not
just that the format strings are slightly different.

> 
> > +				check, id.base.cc_base);
> > +			print_hex_dump(KERN_ERR, "sfp EE: ", DUMP_PREFIX_OFFSET,
> > +				       16, 1, &id, sizeof(id), true);
> > +			return -EINVAL;
> > +		}
> >  	}
> >  
> >  	check = sfp_check(&id.ext, sizeof(id.ext) - 1);
> >  	if (check != id.ext.cc_ext) {
> > -		dev_err(sfp->dev,
> > -			"EEPROM extended structure checksum failure: 0x%02x\n",
> > -			check);
> > -		memset(&id.ext, 0, sizeof(id.ext));
> > +		if (cotsworks) {
> > +			dev_warn(sfp->dev,
> > +				 "EEPROM extended structure checksum failure (0x%02x != 0x%02x)\n",
> > +				 check, id.ext.cc_ext);
> > +		} else {
> > +			dev_err(sfp->dev,
> > +				"EEPROM extended structure checksum failure: 0x%02x != 0x%02x\n",
> > +				check, id.ext.cc_ext);
> 
> 
> here too

Same applies.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

^ permalink raw reply

* [PATCH v3] staging: fsl-dpaa2/ethsw: Fix tag control information value overwrite
From: Razvan Stefanescu @ 2018-03-28 10:50 UTC (permalink / raw)
  To: gregkh
  Cc: devel, andrew, netdev, alexandru.marginean, linux-kernel,
	ioana.ciornei, laurentiu.tudor

The tag control information (TCI) part of the VLAN header contains several
fields, including PCP (priority code point) and PVID (port VLAN id).

Current implementation uses function ethsw_port_set_tci() to set the PVID
value and mistakenly overwrites the rest of the TCI fields with 0,
including PCP which by default has a value of 7.

Fix this by adding support to retrieve TCI set in hardware. Read existing
value and only updated the PVID fields, leaving others unchanged.

Signed-off-by: Razvan Stefanescu <razvan.stefanescu@nxp.com>
---
Changelog
 v2: improve patch description

 v3: use the updated MC command stuct name

 drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 13 +++++++++
 drivers/staging/fsl-dpaa2/ethsw/dpsw.c     | 42 ++++++++++++++++++++++++++++++
 drivers/staging/fsl-dpaa2/ethsw/dpsw.h     |  6 +++++
 drivers/staging/fsl-dpaa2/ethsw/ethsw.c    | 37 +++++++++++++-------------
 4 files changed, 79 insertions(+), 19 deletions(-)

diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
index 1c203e6..da744f2 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
+++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
@@ -49,6 +49,8 @@
 #define DPSW_CMDID_IF_SET_FLOODING          DPSW_CMD_ID(0x047)
 #define DPSW_CMDID_IF_SET_BROADCAST         DPSW_CMD_ID(0x048)
 
+#define DPSW_CMDID_IF_GET_TCI               DPSW_CMD_ID(0x04A)
+
 #define DPSW_CMDID_IF_SET_LINK_CFG          DPSW_CMD_ID(0x04C)
 
 #define DPSW_CMDID_VLAN_ADD                 DPSW_CMD_ID(0x060)
@@ -206,6 +208,17 @@ struct dpsw_cmd_if_set_tci {
 	__le16 conf;
 };
 
+struct dpsw_cmd_if_get_tci {
+	__le16 if_id;
+};
+
+struct dpsw_rsp_if_get_tci {
+	__le16 pad;
+	__le16 vlan_id;
+	u8 dei;
+	u8 pcp;
+};
+
 #define DPSW_STATE_SHIFT	0
 #define DPSW_STATE_SIZE		4
 
diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c
index 9b9bc60..cabed77 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c
@@ -529,6 +529,48 @@ int dpsw_if_set_tci(struct fsl_mc_io *mc_io,
 }
 
 /**
+ * dpsw_if_get_tci() - Get default VLAN Tag Control Information (TCI)
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPSW object
+ * @if_id:	Interface Identifier
+ * @cfg:	Tag Control Information Configuration
+ *
+ * Return:	Completion status. '0' on Success; Error code otherwise.
+ */
+int dpsw_if_get_tci(struct fsl_mc_io *mc_io,
+		    u32 cmd_flags,
+		    u16 token,
+		    u16 if_id,
+		    struct dpsw_tci_cfg *cfg)
+{
+	struct fsl_mc_command cmd = { 0 };
+	struct dpsw_cmd_if_get_tci *cmd_params;
+	struct dpsw_rsp_if_get_tci *rsp_params;
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_TCI,
+					  cmd_flags,
+					  token);
+	cmd_params = (struct dpsw_cmd_if_get_tci *)cmd.params;
+	cmd_params->if_id = cpu_to_le16(if_id);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	rsp_params = (struct dpsw_rsp_if_get_tci *)cmd.params;
+	cfg->pcp = rsp_params->pcp;
+	cfg->dei = rsp_params->dei;
+	cfg->vlan_id = le16_to_cpu(rsp_params->vlan_id);
+
+	return 0;
+}
+
+/**
  * dpsw_if_set_stp() - Function sets Spanning Tree Protocol (STP) state.
  * @mc_io:	Pointer to MC portal's I/O object
  * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
diff --git a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h
index 3335add..82f80c40 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/dpsw.h
+++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h
@@ -306,6 +306,12 @@ int dpsw_if_set_tci(struct fsl_mc_io *mc_io,
 		    u16 if_id,
 		    const struct dpsw_tci_cfg *cfg);
 
+int dpsw_if_get_tci(struct fsl_mc_io *mc_io,
+		    u32 cmd_flags,
+		    u16 token,
+		    u16 if_id,
+		    struct dpsw_tci_cfg *cfg);
+
 /**
  * enum dpsw_stp_state - Spanning Tree Protocol (STP) states
  * @DPSW_STP_STATE_BLOCKING: Blocking state
diff --git a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
index c723a04..ab81a6c 100644
--- a/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
+++ b/drivers/staging/fsl-dpaa2/ethsw/ethsw.c
@@ -50,14 +50,23 @@ static int ethsw_add_vlan(struct ethsw_core *ethsw, u16 vid)
 	return 0;
 }
 
-static int ethsw_port_set_tci(struct ethsw_port_priv *port_priv,
-			      struct dpsw_tci_cfg *tci_cfg)
+static int ethsw_port_set_pvid(struct ethsw_port_priv *port_priv, u16 pvid)
 {
 	struct ethsw_core *ethsw = port_priv->ethsw_data;
 	struct net_device *netdev = port_priv->netdev;
+	struct dpsw_tci_cfg tci_cfg = { 0 };
 	bool is_oper;
 	int err, ret;
 
+	err = dpsw_if_get_tci(ethsw->mc_io, 0, ethsw->dpsw_handle,
+			      port_priv->idx, &tci_cfg);
+	if (err) {
+		netdev_err(netdev, "dpsw_if_get_tci err %d\n", err);
+		return err;
+	}
+
+	tci_cfg.vlan_id = pvid;
+
 	/* Interface needs to be down to change PVID */
 	is_oper = netif_oper_up(netdev);
 	if (is_oper) {
@@ -71,17 +80,16 @@ static int ethsw_port_set_tci(struct ethsw_port_priv *port_priv,
 	}
 
 	err = dpsw_if_set_tci(ethsw->mc_io, 0, ethsw->dpsw_handle,
-			      port_priv->idx, tci_cfg);
+			      port_priv->idx, &tci_cfg);
 	if (err) {
 		netdev_err(netdev, "dpsw_if_set_tci err %d\n", err);
 		goto set_tci_error;
 	}
 
 	/* Delete previous PVID info and mark the new one */
-	if (port_priv->pvid)
-		port_priv->vlans[port_priv->pvid] &= ~ETHSW_VLAN_PVID;
-	port_priv->vlans[tci_cfg->vlan_id] |= ETHSW_VLAN_PVID;
-	port_priv->pvid = tci_cfg->vlan_id;
+	port_priv->vlans[port_priv->pvid] &= ~ETHSW_VLAN_PVID;
+	port_priv->vlans[pvid] |= ETHSW_VLAN_PVID;
+	port_priv->pvid = pvid;
 
 set_tci_error:
 	if (is_oper) {
@@ -133,13 +141,7 @@ static int ethsw_port_add_vlan(struct ethsw_port_priv *port_priv,
 	}
 
 	if (flags & BRIDGE_VLAN_INFO_PVID) {
-		struct dpsw_tci_cfg tci_cfg = {
-			.pcp = 0,
-			.dei = 0,
-			.vlan_id = vid,
-		};
-
-		err = ethsw_port_set_tci(port_priv, &tci_cfg);
+		err = ethsw_port_set_pvid(port_priv, vid);
 		if (err)
 			return err;
 	}
@@ -819,9 +821,7 @@ static int ethsw_port_del_vlan(struct ethsw_port_priv *port_priv, u16 vid)
 		return -ENOENT;
 
 	if (port_priv->vlans[vid] & ETHSW_VLAN_PVID) {
-		struct dpsw_tci_cfg tci_cfg = { 0 };
-
-		err = ethsw_port_set_tci(port_priv, &tci_cfg);
+		err = ethsw_port_set_pvid(port_priv, 0);
 		if (err)
 			return err;
 	}
@@ -1254,7 +1254,6 @@ static int ethsw_port_init(struct ethsw_port_priv *port_priv, u16 port)
 	const char def_mcast[ETH_ALEN] = {0x01, 0x00, 0x5e, 0x00, 0x00, 0x01};
 	struct net_device *netdev = port_priv->netdev;
 	struct ethsw_core *ethsw = port_priv->ethsw_data;
-	struct dpsw_tci_cfg tci_cfg = {0};
 	struct dpsw_vlan_if_cfg vcfg;
 	int err;
 
@@ -1272,7 +1271,7 @@ static int ethsw_port_init(struct ethsw_port_priv *port_priv, u16 port)
 		return err;
 	}
 
-	err = ethsw_port_set_tci(port_priv, &tci_cfg);
+	err = ethsw_port_set_pvid(port_priv, 0);
 	if (err)
 		return err;
 
-- 
1.9.1

^ permalink raw reply related

* 4.14.29 - tcp_push() - null skb's cb dereference
From: Krzysztof Blaszkowski @ 2018-03-28 10:51 UTC (permalink / raw)
  To: netdev

Hi,

I noticed a kernel bug report like below:

[95576.826393] BUG: unable to handle kernel NULL pointer dereference at
0000000000000038
[95576.834296] IP: tcp_push+0x3d/0x110
[95576.837829] PGD 2c8474067 P4D 2c8474067 PUD 1119cf067 PMD 0 
[95576.843536] Oops: 0002 [#1] SMP NOPTI
[95576.847247] CPU: 3 PID: 1682 Comm: nginx Not tainted 4.14.29 #1
[95576.854421] Hardware name: PC-FACTORY empty/Tyan Transport GT24-
B3992-E, BIOS 'V1.06.B10 ' 06/23/2009
[95576.863678] task: ffff9e4f150b2580 task.stack: ffffb21401a50000
[95576.869641] RIP: 0010:tcp_push+0x3d/0x110
[95576.873692] RSP: 0018:ffffb21401a53be0 EFLAGS: 00010246
[95576.878959] RAX: 0000000000000000 RBX: 0000000000009310 RCX:
0000000000000000
[95576.886133] RDX: 0000000000000001 RSI: 0000000000000040 RDI:
ffff9e4e79871f00
[95576.893306] RBP: ffffb21401a53c78 R08: 00000000000065d0 R09:
ffff9e4e79872048
[95576.900479] R10: 00000000000005a8 R11: 0000000000000000 R12:
00000000ffffffe0
[95576.907652] R13: ffffb21401a53cf8 R14: ffff9e4e79871f00 R15:
ffff9e4f68727100
[95576.914824] FS:  00007f683b4e1700(0000) GS:ffff9e50732c0000(0000)
knlGS:0000000000000000
[95576.922953] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[95576.928737] CR2: 0000000000000038 CR3: 000000020aa0e000 CR4:
00000000000006e0
[95576.935908] Call Trace:
[95576.938403]  ? tcp_sendmsg_locked+0x60a/0xd90
[95576.942872]  tcp_sendmsg+0x27/0x40
[95576.946386]  inet_sendmsg+0x2c/0xa0
[95576.949987]  sock_sendmsg+0x33/0x40
[95576.953587]  sock_write_iter+0x76/0xd0
[95576.957448]  do_iter_readv_writev+0x108/0x160
[95576.961917]  do_iter_write+0x82/0x190
[95576.965690]  vfs_writev+0xbb/0x120
[95576.969203]  ? ep_poll+0x240/0x3f0
[95576.972714]  do_writev+0x4d/0xd0
[95576.976052]  ? do_writev+0x4d/0xd0
[95576.979564]  SyS_writev+0xb/0x10
[95576.982905]  do_syscall_64+0x5a/0x110
[95576.986678]  entry_SYSCALL_64_after_hwframe+0x3d/0xa2
[95576.991838] RIP: 0033:0x7f6839e56170
[95576.995523] RSP: 002b:00007ffe34c9cf48 EFLAGS: 00000246 ORIG_RAX:
0000000000000014
[95577.003265] RAX: ffffffffffffffda RBX: 0000000004b622c0 RCX:
00007f6839e56170
[95577.010507] RDX: 0000000000000017 RSI: 00007ffe34c9cfd0 RDI:
0000000000000012
[95577.017749] RBP: 00007ffe34c9cfb0 R08: 00000000004b1c2f R09:
00007ffe34c9d130
[95577.024989] R10: 000000000001d6c2 R11: 0000000000000246 R12:
0000000002f3eec0
[95577.032228] R13: 000000007fffefff R14: 0000000000000000 R15:
0000000002f3eec0
[95577.039469] Code: 01 00 00 4c 8d 8f 48 01 00 00 41 89 d2 41 89 f3 89
ca b9 00 00 00 00 49 39 c1 48 0f 44 c1 41 81 e3 00 80 00 00 0f 85 ac 00
00 00 <80> 48 38 08 8b 8f 64 06 00 00 89 8f 6c 06 00 00 83 e6 01 74 0c 
[95577.058617] RIP: tcp_push+0x3d/0x110 RSP: ffffb21401a53be0
[95577.064208] CR2: 0000000000000038
[95577.068056] ---[ end trace 19bfaf872fd3ef10 ]--



further report analysis ended up in net/ipv4/tcp.c : 


(gdb) list *(tcp_push+0x3d)
0xfd is in tcp_push (/data/work/linux-4.14.29/net/ipv4/tcp.c:630).
625	}
626	EXPORT_SYMBOL(tcp_ioctl);
627	
628	static inline void tcp_mark_push(struct tcp_sock *tp, struct
sk_buff *skb)
629	{
630		TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_PSH;
631		tp->pushed_seq = tp->write_seq;
632	}


and tcp_mark_push() is inlined in tcp_push() indeed.

Looking forward to seeing rationale for tcp_write_queue_tail(sk)
returning null skb - assuming the above is correct.

Thanks

^ permalink raw reply

* Passing uninitialised local variable
From: Himanshu Jha @ 2018-03-28 11:20 UTC (permalink / raw)
  To: arend.vanspriel, franky.lin, hante.meuleman, chi-hsien.lin,
	wright.feng
  Cc: kvalo, johannes.berg, linux-wireless, brcm80211-dev-list.pdl,
	brcm80211-dev-list, netdev

Hello everyone,


I recently found that a local variable in passed uninitialised to the
function at 

drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:2950

                u32 var; 
                err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var);
                if (err) {
                        brcmf_err("wl dtim_assoc failed (%d)\n", err);
                        goto update_bss_info_out;
                }
                dtim_period = (u8)var;


Now, the brcmf_fil_iovar_int_get() is defined as:

s32
brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data)
{
        __le32 data_le = cpu_to_le32(*data);
        s32 err;

        err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le));
        if (err == 0)
                *data = le32_to_cpu(data_le);
        return err;
}

We can cleary see that 'var' in used uninitialised in the very first line
which is an undefined behavior.

So, what could be a possible fix for the above ?

I'm not sure initialising 'var' to 0 would be the correct solution.

-- 
Thanks
Himanshu Jha

^ permalink raw reply

* RE: RFC on writel and writel_relaxed
From: David Laight @ 2018-03-28 11:30 UTC (permalink / raw)
  To: 'Benjamin Herrenschmidt', Will Deacon
  Cc: Linus Torvalds, Alexander Duyck, Sinan Kaya, Arnd Bergmann,
	Jason Gunthorpe, Oliver,
	open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
	linux-rdma@vger.kernel.org, Paul E. McKenney,
	netdev@vger.kernel.org
In-Reply-To: <1522230988.21446.7.camel@kernel.crashing.org>

From: Benjamin Herrenschmidt
> Sent: 28 March 2018 10:56
...
> For example, let's say I have a device with a reset bit and the spec
> says the reset bit needs to be set for at least 10us.
> 
> This is wrong:
> 
> 	writel(1, RESET_REG);
> 	usleep(10);
> 	writel(0, RESET_REG);
> 
> Because of write posting, the first write might arrive to the device
> right before the second one.
> 
> The typical "fix" is to turn that into:
> 
> 	writel(1, RESET_REG);
> 	readl(RESET_REG); /* Flush posted writes */

Would a writel(1, RESET_REG) here provide enough synchronsiation?

> 	usleep(10);
> 	writel(0, RESET_REG);
> 
> *However* the issue here, at least on power, is that the CPU can issue
> that readl but doesn't necessarily wait for it to complete (ie, the
> data to return), before proceeding to the usleep. Now a usleep contains
> a bunch of loads and stores and is probably fine, but a udelay which
> just loops on the timebase may not be.
> 
> Thus we may still violate the timing requirement.

I've seem that sort of code (with udelay() and no read back) quite often.
How many were in linux I don't know.

For small delays I usually fix it by repeated writes (of the same value)
to the device register. That can guarantee very short intervals.

The only time I've actually seen buffered writes break timing was
between a 286 and an 8859 interrupt controller.
If you wrote to the mask then enabled interrupts the first IACK cycle
could be too close to write and break the cycle recovery time.
That clobbered most of the interrupt controller registers.
That probably affected every 286 board ever built!
Not sure how much software added the required extra bus cycle.

> What we did inside readl, with the twi;isync sequence (which basically
> means, trap on return value with "trap never" as a condition, followed
> by isync that ensures all excpetion conditions are resolved), is force
> the CPU to "consume" the data from the read before moving on.
> 
> This effectively makes readl fully synchronous (we would probably avoid
> that if we were to implement a readl_relaxed).

I've always wondered exactly what the twi;isync were for - always seemed
very heavy handed for most mmio reads.
Particularly if you are doing mmio reads from a data fifo.

Perhaps there should be a writel_wait() that is allowed to do a read back
for such code paths?

	David


^ permalink raw reply

* Re: RFC on writel and writel_relaxed
From: okaya @ 2018-03-28 11:41 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Benjamin Herrenschmidt, Alexander Duyck, Will Deacon,
	Arnd Bergmann, Jason Gunthorpe, David Laight, Oliver,
	open list:LINUX FOR POWERPC (32-BIT AND 64-BIT), linux-rdma,
	Alexander Duyck, Paul E. McKenney, netdev, linus971
In-Reply-To: <CA+55aFxULkhZGhg-tTBBxBBvXbL7QV7f6zvwW7U2wHFijqGEqw@mail.gmail.com>

On 2018-03-28 02:14, Linus Torvalds wrote:
> On Tue, Mar 27, 2018 at 5:24 PM, Sinan Kaya <okaya@codeaurora.org> 
> wrote:
>> 
>> Basically changing it to
>> 
>> dma_buffer->foo = 1;                    /* WB */
>> wmb()
>> writel_relaxed(KICK, DMA_KICK_REGISTER);        /* UC */
>> mmiowb()
> 
> Why?
> 
> Why not  just remove the wmb(), and keep the barrier in the writel()?

Yes, we want to get there indeed. It is because of some arch not 
implementing writel properly. Maintainers want to play safe.

That is why I asked if IA64 and other well known archs follow the 
strongly ordered rule at this moment like PPC and ARM.

Or should we go and inform every arch about this before yanking wmb()?

Maintainers are afraid of introducing a regression.

> 
> The above code makes no sense, and just looks stupid to me. It also
> generates pointlessly bad code on x86, so it's bad there too.
> 
>                Linus

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox