+++ /dev/null
-From 81889eb2b37bc21df4ff259441e8fc12d4f27cd9 Mon Sep 17 00:00:00 2001
-From: Linus Walleij <linus.walleij@linaro.org>
-Date: Thu, 9 May 2024 08:48:31 +0200
-Subject: [PATCH] net: ethernet: cortina: Locking fixes
-
-This fixes a probably long standing problem in the Cortina
-Gemini ethernet driver: there are some paths in the code
-where the IRQ registers are written without taking the proper
-locks.
-
-Fixes: 4d5ae32f5e1e ("net: ethernet: Add a driver for Gemini gigabit ethernet")
-Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
----
- drivers/net/ethernet/cortina/gemini.c | 12 ++++++++++--
- 1 file changed, 10 insertions(+), 2 deletions(-)
-
---- a/drivers/net/ethernet/cortina/gemini.c
-+++ b/drivers/net/ethernet/cortina/gemini.c
-@@ -1107,10 +1107,13 @@ static void gmac_tx_irq_enable(struct ne
- {
- struct gemini_ethernet_port *port = netdev_priv(netdev);
- struct gemini_ethernet *geth = port->geth;
-+ unsigned long flags;
- u32 val, mask;
-
- netdev_dbg(netdev, "%s device %d\n", __func__, netdev->dev_id);
-
-+ spin_lock_irqsave(&geth->irq_lock, flags);
-+
- mask = GMAC0_IRQ0_TXQ0_INTS << (6 * netdev->dev_id + txq);
-
- if (en)
-@@ -1119,6 +1122,8 @@ static void gmac_tx_irq_enable(struct ne
- val = readl(geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG);
- val = en ? val | mask : val & ~mask;
- writel(val, geth->base + GLOBAL_INTERRUPT_ENABLE_0_REG);
-+
-+ spin_unlock_irqrestore(&geth->irq_lock, flags);
- }
-
- static void gmac_tx_irq(struct net_device *netdev, unsigned int txq_num)
-@@ -1415,15 +1420,19 @@ static unsigned int gmac_rx(struct net_d
- union gmac_rxdesc_3 word3;
- struct page *page = NULL;
- unsigned int page_offs;
-+ unsigned long flags;
- unsigned short r, w;
- union dma_rwptr rw;
- dma_addr_t mapping;
- int frag_nr = 0;
-
-+ spin_lock_irqsave(&geth->irq_lock, flags);
- rw.bits32 = readl(ptr_reg);
- /* Reset interrupt as all packages until here are taken into account */
- writel(DEFAULT_Q0_INT_BIT << netdev->dev_id,
- geth->base + GLOBAL_INTERRUPT_STATUS_1_REG);
-+ spin_unlock_irqrestore(&geth->irq_lock, flags);
-+
- r = rw.bits.rptr;
- w = rw.bits.wptr;
-
-@@ -1726,10 +1735,9 @@ static irqreturn_t gmac_irq(int irq, voi
- gmac_update_hw_stats(netdev);
-
- if (val & (GMAC0_RX_OVERRUN_INT_BIT << (netdev->dev_id * 8))) {
-+ spin_lock(&geth->irq_lock);
- writel(GMAC0_RXDERR_INT_BIT << (netdev->dev_id * 8),
- geth->base + GLOBAL_INTERRUPT_STATUS_4_REG);
--
-- spin_lock(&geth->irq_lock);
- u64_stats_update_begin(&port->ir_stats_syncp);
- ++port->stats.rx_fifo_errors;
- u64_stats_update_end(&port->ir_stats_syncp);
+++ /dev/null
-From patchwork Sun Apr 21 07:39:52 2024
-Content-Type: text/plain; charset="utf-8"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-X-Patchwork-Submitter: INAGAKI Hiroshi <musashino.open@gmail.com>
-X-Patchwork-Id: 13637306
-From: INAGAKI Hiroshi <musashino.open@gmail.com>
-To: axboe@kernel.dk
-Cc: yang.yang29@zte.com,
- justinstitt@google.com,
- xu.panda@zte.com.cn,
- linux-block@vger.kernel.org,
- linux-kernel@vger.kernel.org,
- INAGAKI Hiroshi <musashino.open@gmail.com>,
- Naohiro Aota <naota@elisp.net>
-Subject: [PATCH] block: fix and simplify blkdevparts= cmdline parsing
-Date: Sun, 21 Apr 2024 16:39:52 +0900
-Message-ID: <20240421074005.565-1-musashino.open@gmail.com>
-X-Mailer: git-send-email 2.42.0.windows.2
-Precedence: bulk
-X-Mailing-List: linux-block@vger.kernel.org
-List-Id: <linux-block.vger.kernel.org>
-List-Subscribe: <mailto:linux-block+subscribe@vger.kernel.org>
-List-Unsubscribe: <mailto:linux-block+unsubscribe@vger.kernel.org>
-MIME-Version: 1.0
-
-Fix the cmdline parsing of the "blkdevparts=" parameter using strsep(),
-which makes the code simpler.
-
-Before commit 146afeb235cc ("block: use strscpy() to instead of
-strncpy()"), we used a strncpy() to copy a block device name and partition
-names. The commit simply replaced a strncpy() and NULL termination with
-a strscpy(). It did not update calculations of length passed to strscpy().
-While the length passed to strncpy() is just a length of valid characters
-without NULL termination ('\0'), strscpy() takes it as a length of the
-destination buffer, including a NULL termination.
-
-Since the source buffer is not necessarily NULL terminated, the current
-code copies "length - 1" characters and puts a NULL character in the
-destination buffer. It replaces the last character with NULL and breaks
-the parsing.
-
-As an example, that buffer will be passed to parse_parts() and breaks
-parsing sub-partitions due to the missing ')' at the end, like the
-following.
-
-example (Check Point V-80 & OpenWrt):
-
-- Linux Kernel 6.6
-
- [ 0.000000] Kernel command line: console=ttyS0,115200 earlycon=uart8250,mmio32,0xf0512000 crashkernel=30M mvpp2x.queue_mode=1 blkdevparts=mmcblk1:48M@10M(kernel-1),1M(dtb-1),720M(rootfs-1),48M(kernel-2),1M(dtb-2),720M(rootfs-2),300M(default_sw),650M(logs),1M(preset_cfg),1M(adsl),-(storage) maxcpus=4
- ...
- [ 0.884016] mmc1: new HS200 MMC card at address 0001
- [ 0.889951] mmcblk1: mmc1:0001 004GA0 3.69 GiB
- [ 0.895043] cmdline partition format is invalid.
- [ 0.895704] mmcblk1: p1
- [ 0.903447] mmcblk1boot0: mmc1:0001 004GA0 2.00 MiB
- [ 0.908667] mmcblk1boot1: mmc1:0001 004GA0 2.00 MiB
- [ 0.913765] mmcblk1rpmb: mmc1:0001 004GA0 512 KiB, chardev (248:0)
-
- 1. "48M@10M(kernel-1),..." is passed to strscpy() with length=17
- from parse_parts()
- 2. strscpy() returns -E2BIG and the destination buffer has
- "48M@10M(kernel-1\0"
- 3. "48M@10M(kernel-1\0" is passed to parse_subpart()
- 4. parse_subpart() fails to find ')' when parsing a partition name,
- and returns error
-
-- Linux Kernel 6.1
-
- [ 0.000000] Kernel command line: console=ttyS0,115200 earlycon=uart8250,mmio32,0xf0512000 crashkernel=30M mvpp2x.queue_mode=1 blkdevparts=mmcblk1:48M@10M(kernel-1),1M(dtb-1),720M(rootfs-1),48M(kernel-2),1M(dtb-2),720M(rootfs-2),300M(default_sw),650M(logs),1M(preset_cfg),1M(adsl),-(storage) maxcpus=4
- ...
- [ 0.953142] mmc1: new HS200 MMC card at address 0001
- [ 0.959114] mmcblk1: mmc1:0001 004GA0 3.69 GiB
- [ 0.964259] mmcblk1: p1(kernel-1) p2(dtb-1) p3(rootfs-1) p4(kernel-2) p5(dtb-2) 6(rootfs-2) p7(default_sw) p8(logs) p9(preset_cfg) p10(adsl) p11(storage)
- [ 0.979174] mmcblk1boot0: mmc1:0001 004GA0 2.00 MiB
- [ 0.984674] mmcblk1boot1: mmc1:0001 004GA0 2.00 MiB
- [ 0.989926] mmcblk1rpmb: mmc1:0001 004GA0 512 KiB, chardev (248:0
-
-By the way, strscpy() takes a length of destination buffer and it is
-often confusing when copying characters with a specified length. Using
-strsep() helps to separate the string by the specified character. Then,
-we can use strscpy() naturally with the size of the destination buffer.
-
-Separating the string on the fly is also useful to omit the redundant
-string copy, reducing memory usage and improve the code readability.
-
-Fixes: 146afeb235cc ("block: use strscpy() to instead of strncpy()")
-Suggested-by: Naohiro Aota <naota@elisp.net>
-Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
-Reviewed-by: Daniel Golle <daniel@makrotopia.org>
----
- block/partitions/cmdline.c | 49 ++++++++++----------------------------
- 1 file changed, 12 insertions(+), 37 deletions(-)
-
---- a/block/partitions/cmdline.c
-+++ b/block/partitions/cmdline.c
-@@ -70,8 +70,8 @@ static int parse_subpart(struct cmdline_
- }
-
- if (*partdef == '(') {
-- int length;
-- char *next = strchr(++partdef, ')');
-+ partdef++;
-+ char *next = strsep(&partdef, ")");
-
- if (!next) {
- pr_warn("cmdline partition format is invalid.");
-@@ -79,11 +79,7 @@ static int parse_subpart(struct cmdline_
- goto fail;
- }
-
-- length = min_t(int, next - partdef,
-- sizeof(new_subpart->name) - 1);
-- strscpy(new_subpart->name, partdef, length);
--
-- partdef = ++next;
-+ strscpy(new_subpart->name, next, sizeof(new_subpart->name));
- } else
- new_subpart->name[0] = '\0';
-
-@@ -117,14 +113,12 @@ static void free_subpart(struct cmdline_
- }
- }
-
--static int parse_parts(struct cmdline_parts **parts, const char *bdevdef)
-+static int parse_parts(struct cmdline_parts **parts, char *bdevdef)
- {
- int ret = -EINVAL;
- char *next;
-- int length;
- struct cmdline_subpart **next_subpart;
- struct cmdline_parts *newparts;
-- char buf[BDEVNAME_SIZE + 32 + 4];
-
- *parts = NULL;
-
-@@ -132,28 +126,19 @@ static int parse_parts(struct cmdline_pa
- if (!newparts)
- return -ENOMEM;
-
-- next = strchr(bdevdef, ':');
-+ next = strsep(&bdevdef, ":");
- if (!next) {
- pr_warn("cmdline partition has no block device.");
- goto fail;
- }
-
-- length = min_t(int, next - bdevdef, sizeof(newparts->name) - 1);
-- strscpy(newparts->name, bdevdef, length);
-+ strscpy(newparts->name, next, sizeof(newparts->name));
- newparts->nr_subparts = 0;
-
- next_subpart = &newparts->subpart;
-
-- while (next && *(++next)) {
-- bdevdef = next;
-- next = strchr(bdevdef, ',');
--
-- length = (!next) ? (sizeof(buf) - 1) :
-- min_t(int, next - bdevdef, sizeof(buf) - 1);
--
-- strscpy(buf, bdevdef, length);
--
-- ret = parse_subpart(next_subpart, buf);
-+ while ((next = strsep(&bdevdef, ","))) {
-+ ret = parse_subpart(next_subpart, next);
- if (ret)
- goto fail;
-
-@@ -199,24 +184,17 @@ static int cmdline_parts_parse(struct cm
-
- *parts = NULL;
-
-- next = pbuf = buf = kstrdup(cmdline, GFP_KERNEL);
-+ pbuf = buf = kstrdup(cmdline, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- next_parts = parts;
-
-- while (next && *pbuf) {
-- next = strchr(pbuf, ';');
-- if (next)
-- *next = '\0';
--
-- ret = parse_parts(next_parts, pbuf);
-+ while ((next = strsep(&pbuf, ";"))) {
-+ ret = parse_parts(next_parts, next);
- if (ret)
- goto fail;
-
-- if (next)
-- pbuf = ++next;
--
- next_parts = &(*next_parts)->next_parts;
- }
-
-@@ -250,7 +228,6 @@ static struct cmdline_parts *bdev_parts;
- static int add_part(int slot, struct cmdline_subpart *subpart,
- struct parsed_partitions *state)
- {
-- int label_min;
- struct partition_meta_info *info;
- char tmp[sizeof(info->volname) + 4];
-
-@@ -262,9 +239,7 @@ static int add_part(int slot, struct cmd
-
- info = &state->parts[slot].info;
-
-- label_min = min_t(int, sizeof(info->volname) - 1,
-- sizeof(subpart->name));
-- strscpy(info->volname, subpart->name, label_min);
-+ strscpy(info->volname, subpart->name, sizeof(info->volname));
-
- snprintf(tmp, sizeof(tmp), "(%s)", info->volname);
- strlcat(state->pp_buf, tmp, PAGE_SIZE);