2021-06-10 07:25:24

by Guangbin Huang

[permalink] [raw]
Subject: [PATCH net-next 0/8] net: ixp4xx_hss: clean up some code style issues

From: Peng Li <[email protected]>

This patchset clean up some code style issues.

Peng Li (8):
net: ixp4xx_hss: remove redundant blank lines
net: ixp4xx_hss: add blank line after declarations
net: ixp4xx_hss: fix the code style issue about "foo* bar"
net: ixp4xx_hss: move out assignment in if condition
net: ixp4xx_hss: add some required spaces
net: ixp4xx_hss: remove redundant spaces
net: ixp4xx_hss: fix the comments style issue
net: ixp4xx_hss: add braces {} to all arms of the statement

drivers/net/wan/ixp4xx_hss.c | 144 ++++++++++++++++++++++++-------------------
1 file changed, 80 insertions(+), 64 deletions(-)

--
2.8.1


2021-06-10 07:25:28

by Guangbin Huang

[permalink] [raw]
Subject: [PATCH net-next 3/8] net: ixp4xx_hss: fix the code style issue about "foo* bar"

From: Peng Li <[email protected]>

Fix the checkpatch error as "foo* bar" and should be "foo *bar",
and "(foo*)" should be "(foo *)".

Signed-off-by: Peng Li <[email protected]>
Signed-off-by: Guangbin Huang <[email protected]>
---
drivers/net/wan/ixp4xx_hss.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 6aa01d5..48bc914 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -332,7 +332,7 @@ static const struct {
* utility functions
****************************************************************************/

-static inline struct port* dev_to_port(struct net_device *dev)
+static inline struct port *dev_to_port(struct net_device *dev)
{
return dev_to_hdlc(dev)->priv;
}
@@ -351,9 +351,9 @@ static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt)
* HSS access
****************************************************************************/

-static void hss_npe_send(struct port *port, struct msg *msg, const char* what)
+static void hss_npe_send(struct port *port, struct msg *msg, const char *what)
{
- u32 *val = (u32*)msg;
+ u32 *val = (u32 *)msg;

if (npe_send_message(port->npe, msg, what)) {
pr_crit("HSS-%i: unable to send command [%08X:%08X] to %s\n",
--
2.8.1

2021-06-10 07:25:37

by Guangbin Huang

[permalink] [raw]
Subject: [PATCH net-next 8/8] net: ixp4xx_hss: add braces {} to all arms of the statement

From: Peng Li <[email protected]>

Braces {} should be used on all arms of this statement.

Signed-off-by: Peng Li <[email protected]>
---
drivers/net/wan/ixp4xx_hss.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 319ae50..e975211 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -1299,11 +1299,11 @@ static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EINVAL;

port->clock_type = clk; /* Update settings */
- if (clk == CLOCK_INT)
+ if (clk == CLOCK_INT) {
find_best_clock(port->plat->timer_freq,
new_line.clock_rate,
&port->clock_rate, &port->clock_reg);
- else {
+ } else {
port->clock_rate = 0;
port->clock_reg = CLK42X_SPEED_2048KHZ;
}
--
2.8.1

2021-06-10 07:25:50

by Guangbin Huang

[permalink] [raw]
Subject: [PATCH net-next 7/8] net: ixp4xx_hss: fix the comments style issue

From: Peng Li <[email protected]>

Networking block comments don't use an empty /* line,
use /* Comment...

Block comments use * on subsequent lines.
Block comments use a trailing */ on a separate line.

This patch fixes the comments style issues.

Signed-off-by: Peng Li <[email protected]>
Signed-off-by: Guangbin Huang <[email protected]>
---
drivers/net/wan/ixp4xx_hss.c | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 30a6df4..319ae50 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -166,8 +166,7 @@
#define CLK46X_SPEED_4096KHZ ((16 << 22) | (280 << 12) | 1023)
#define CLK46X_SPEED_8192KHZ ((8 << 22) | (280 << 12) | 2047)

-/*
- * HSS_CONFIG_CLOCK_CR register consists of 3 parts:
+/* HSS_CONFIG_CLOCK_CR register consists of 3 parts:
* A (10 bits), B (10 bits) and C (12 bits).
* IXP42x HSS clock generator operation (verified with an oscilloscope):
* Each clock bit takes 7.5 ns (1 / 133.xx MHz).
@@ -217,7 +216,8 @@
#define PORT_ERROR_READ 0x42

/* triggers the NPE to reset internal status and enable the HssPacketized
- operation for the flow specified by pPipe */
+ * operation for the flow specified by pPipe
+ */
#define PKT_PIPE_FLOW_ENABLE 0x50
#define PKT_PIPE_FLOW_DISABLE 0x51
#define PKT_NUM_PIPES_WRITE 0x52
@@ -232,7 +232,8 @@
#define ERR_HDLC_ALIGN 2 /* HDLC alignment error */
#define ERR_HDLC_FCS 3 /* HDLC Frame Check Sum error */
#define ERR_RXFREE_Q_EMPTY 4 /* RX-free queue became empty while receiving
- this packet (if buf_len < pkt_len) */
+ * this packet (if buf_len < pkt_len)
+ */
#define ERR_HDLC_TOO_LONG 5 /* HDLC frame size too long */
#define ERR_HDLC_ABORT 6 /* abort sequence received */
#define ERR_DISCONNECTING 7 /* disconnect is in progress */
@@ -602,7 +603,8 @@ static inline void queue_put_desc(unsigned int queue, u32 phys,
BUG_ON(phys & 0x1F);
qmgr_put_entry(queue, phys);
/* Don't check for queue overflow here, we've allocated sufficient
- length and queues >= 32 don't support this check anyway. */
+ * length and queues >= 32 don't support this check anyway.
+ */
}

static inline void dma_unmap_tx(struct port *port, struct desc *desc)
--
2.8.1

2021-06-10 07:27:13

by Guangbin Huang

[permalink] [raw]
Subject: [PATCH net-next 4/8] net: ixp4xx_hss: move out assignment in if condition

From: Peng Li <[email protected]>

Should not use assignment in if condition.

Signed-off-by: Peng Li <[email protected]>
Signed-off-by: Guangbin Huang <[email protected]>
---
drivers/net/wan/ixp4xx_hss.c | 66 +++++++++++++++++++++++++++++---------------
1 file changed, 43 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 48bc914..d657bca 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -510,10 +510,12 @@ static int hss_load_firmware(struct port *port)
if (port->initialized)
return 0;

- if (!npe_running(port->npe) &&
- (err = npe_load_firmware(port->npe, npe_name(port->npe),
- port->dev)))
- return err;
+ if (!npe_running(port->npe)) {
+ err = npe_load_firmware(port->npe, npe_name(port->npe),
+ port->dev);
+ if (err)
+ return err;
+ }

/* HDLC mode configuration */
memset(&msg, 0, sizeof(msg));
@@ -579,7 +581,8 @@ static inline int queue_get_desc(unsigned int queue, struct port *port,
u32 phys, tab_phys, n_desc;
struct desc *tab;

- if (!(phys = qmgr_get_entry(queue)))
+ phys = qmgr_get_entry(queue);
+ if (!phys)
return -1;

BUG_ON(phys & 0x1F);
@@ -664,7 +667,8 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget)
u32 phys;
#endif

- if ((n = queue_get_desc(rxq, port, 0)) < 0) {
+ n = queue_get_desc(rxq, port, 0);
+ if (n < 0) {
#if DEBUG_RX
printk(KERN_DEBUG "%s: hss_hdlc_poll"
" napi_complete\n", dev->name);
@@ -699,7 +703,8 @@ static int hss_hdlc_poll(struct napi_struct *napi, int budget)
switch (desc->status) {
case 0:
#ifdef __ARMEB__
- if ((skb = netdev_alloc_skb(dev, RX_SIZE)) != NULL) {
+ skb = netdev_alloc_skb(dev, RX_SIZE);
+ if (skb) {
phys = dma_map_single(&dev->dev, skb->data,
RX_SIZE,
DMA_FROM_DEVICE);
@@ -847,7 +852,8 @@ static int hss_hdlc_xmit(struct sk_buff *skb, struct net_device *dev)
#else
offset = (int)skb->data & 3; /* keep 32-bit alignment */
bytes = ALIGN(offset + len, 4);
- if (!(mem = kmalloc(bytes, GFP_ATOMIC))) {
+ mem = kmalloc(bytes, GFP_ATOMIC);
+ if (!mem) {
dev_kfree_skb(skb);
dev->stats.tx_dropped++;
return NETDEV_TX_OK;
@@ -966,8 +972,9 @@ static int init_hdlc_queues(struct port *port)
return -ENOMEM;
}

- if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
- &port->desc_tab_phys)))
+ port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
+ &port->desc_tab_phys);
+ if (!port->desc_tab)
return -ENOMEM;
memset(port->desc_tab, 0, POOL_ALLOC_SIZE);
memset(port->rx_buff_tab, 0, sizeof(port->rx_buff_tab)); /* tables */
@@ -979,11 +986,13 @@ static int init_hdlc_queues(struct port *port)
buffer_t *buff;
void *data;
#ifdef __ARMEB__
- if (!(buff = netdev_alloc_skb(port->netdev, RX_SIZE)))
+ buff = netdev_alloc_skb(port->netdev, RX_SIZE);
+ if (!buff)
return -ENOMEM;
data = buff->data;
#else
- if (!(buff = kmalloc(RX_SIZE, GFP_KERNEL)))
+ buff = kmalloc(RX_SIZE, GFP_KERNEL);
+ if (!buff)
return -ENOMEM;
data = buff;
#endif
@@ -1041,23 +1050,29 @@ static int hss_hdlc_open(struct net_device *dev)
unsigned long flags;
int i, err = 0;

- if ((err = hdlc_open(dev)))
+ err = hdlc_open(dev);
+ if (err)
return err;

- if ((err = hss_load_firmware(port)))
+ err = hss_load_firmware(port);
+ if (err)
goto err_hdlc_close;

- if ((err = request_hdlc_queues(port)))
+ err = request_hdlc_queues(port);
+ if (err)
goto err_hdlc_close;

- if ((err = init_hdlc_queues(port)))
+ err = init_hdlc_queues(port);
+ if (err)
goto err_destroy_queues;

spin_lock_irqsave(&npe_lock, flags);
- if (port->plat->open)
- if ((err = port->plat->open(port->id, dev,
- hss_hdlc_set_carrier)))
+ if (port->plat->open) {
+ err = port->plat->open(port->id, dev, hss_hdlc_set_carrier);
+ if (err)
goto err_unlock;
+ }
+
spin_unlock_irqrestore(&npe_lock, flags);

/* Populate queues with buffers, no failure after this point */
@@ -1328,15 +1343,19 @@ static int hss_init_one(struct platform_device *pdev)
hdlc_device *hdlc;
int err;

- if ((port = kzalloc(sizeof(*port), GFP_KERNEL)) == NULL)
+ port = kzalloc(sizeof(*port), GFP_KERNEL);
+ if (!port)
return -ENOMEM;

- if ((port->npe = npe_request(0)) == NULL) {
+ port->npe = npe_request(0);
+ if (!port->npe) {
err = -ENODEV;
goto err_free;
}

- if ((port->netdev = dev = alloc_hdlcdev(port)) == NULL) {
+ dev = alloc_hdlcdev(port);
+ port->netdev = alloc_hdlcdev(port);
+ if (!port->netdev) {
err = -ENOMEM;
goto err_plat;
}
@@ -1355,7 +1374,8 @@ static int hss_init_one(struct platform_device *pdev)
port->plat = pdev->dev.platform_data;
netif_napi_add(dev, &port->napi, hss_hdlc_poll, NAPI_WEIGHT);

- if ((err = register_hdlc_device(dev)))
+ err = register_hdlc_device(dev);
+ if (err)
goto err_free_netdev;

platform_set_drvdata(pdev, port);
--
2.8.1

2021-06-10 07:27:14

by Guangbin Huang

[permalink] [raw]
Subject: [PATCH net-next 6/8] net: ixp4xx_hss: remove redundant spaces

From: Peng Li <[email protected]>

According to the chackpatch.pl,
space prohibited after that open parenthesis '('.

Signed-off-by: Peng Li <[email protected]>
Signed-off-by: Guangbin Huang <[email protected]>
---
drivers/net/wan/ixp4xx_hss.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index d8f1df9..30a6df4 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -150,21 +150,21 @@
#define CCR_SECOND_HSS 0x01000000

/* hss_config, clkCR: main:10, num:10, denom:12 */
-#define CLK42X_SPEED_EXP ((0x3FF << 22) | ( 2 << 12) | 15) /*65 KHz*/
-
-#define CLK42X_SPEED_512KHZ (( 130 << 22) | ( 2 << 12) | 15)
-#define CLK42X_SPEED_1536KHZ (( 43 << 22) | ( 18 << 12) | 47)
-#define CLK42X_SPEED_1544KHZ (( 43 << 22) | ( 33 << 12) | 192)
-#define CLK42X_SPEED_2048KHZ (( 32 << 22) | ( 34 << 12) | 63)
-#define CLK42X_SPEED_4096KHZ (( 16 << 22) | ( 34 << 12) | 127)
-#define CLK42X_SPEED_8192KHZ (( 8 << 22) | ( 34 << 12) | 255)
-
-#define CLK46X_SPEED_512KHZ (( 130 << 22) | ( 24 << 12) | 127)
-#define CLK46X_SPEED_1536KHZ (( 43 << 22) | (152 << 12) | 383)
-#define CLK46X_SPEED_1544KHZ (( 43 << 22) | ( 66 << 12) | 385)
-#define CLK46X_SPEED_2048KHZ (( 32 << 22) | (280 << 12) | 511)
-#define CLK46X_SPEED_4096KHZ (( 16 << 22) | (280 << 12) | 1023)
-#define CLK46X_SPEED_8192KHZ (( 8 << 22) | (280 << 12) | 2047)
+#define CLK42X_SPEED_EXP ((0x3FF << 22) | (2 << 12) | 15) /*65 KHz*/
+
+#define CLK42X_SPEED_512KHZ ((130 << 22) | (2 << 12) | 15)
+#define CLK42X_SPEED_1536KHZ ((43 << 22) | (18 << 12) | 47)
+#define CLK42X_SPEED_1544KHZ ((43 << 22) | (33 << 12) | 192)
+#define CLK42X_SPEED_2048KHZ ((32 << 22) | (34 << 12) | 63)
+#define CLK42X_SPEED_4096KHZ ((16 << 22) | (34 << 12) | 127)
+#define CLK42X_SPEED_8192KHZ ((8 << 22) | (34 << 12) | 255)
+
+#define CLK46X_SPEED_512KHZ ((130 << 22) | (24 << 12) | 127)
+#define CLK46X_SPEED_1536KHZ ((43 << 22) | (152 << 12) | 383)
+#define CLK46X_SPEED_1544KHZ ((43 << 22) | (66 << 12) | 385)
+#define CLK46X_SPEED_2048KHZ ((32 << 22) | (280 << 12) | 511)
+#define CLK46X_SPEED_4096KHZ ((16 << 22) | (280 << 12) | 1023)
+#define CLK46X_SPEED_8192KHZ ((8 << 22) | (280 << 12) | 2047)

/*
* HSS_CONFIG_CLOCK_CR register consists of 3 parts:
--
2.8.1

2021-06-10 07:28:06

by Guangbin Huang

[permalink] [raw]
Subject: [PATCH net-next 5/8] net: ixp4xx_hss: add some required spaces

From: Peng Li <[email protected]>

Add space required before the open parenthesis '('.
Add space required after that close brace '}'.

Signed-off-by: Peng Li <[email protected]>
Signed-off-by: Guangbin Huang <[email protected]>
---
drivers/net/wan/ixp4xx_hss.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index d657bca..d8f1df9 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -322,7 +322,7 @@ static DEFINE_SPINLOCK(npe_lock);

static const struct {
int tx, txdone, rx, rxfree;
-}queue_ids[2] = {{HSS0_PKT_TX0_QUEUE, HSS0_PKT_TXDONE_QUEUE, HSS0_PKT_RX_QUEUE,
+} queue_ids[2] = {{HSS0_PKT_TX0_QUEUE, HSS0_PKT_TXDONE_QUEUE, HSS0_PKT_RX_QUEUE,
HSS0_PKT_RXFREE0_QUEUE},
{HSS1_PKT_TX0_QUEUE, HSS1_PKT_TXDONE_QUEUE, HSS1_PKT_RX_QUEUE,
HSS1_PKT_RXFREE0_QUEUE},
@@ -1177,7 +1177,7 @@ static int hss_hdlc_attach(struct net_device *dev, unsigned short encoding,
if (encoding != ENCODING_NRZ)
return -EINVAL;

- switch(parity) {
+ switch (parity) {
case PARITY_CRC16_PR1_CCITT:
port->hdlc_cfg = 0;
return 0;
@@ -1264,7 +1264,7 @@ static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (cmd != SIOCWANDEV)
return hdlc_ioctl(dev, ifr, cmd);

- switch(ifr->ifr_settings.type) {
+ switch (ifr->ifr_settings.type) {
case IF_GET_IFACE:
ifr->ifr_settings.type = IF_IFACE_V35;
if (ifr->ifr_settings.size < size) {
@@ -1281,7 +1281,7 @@ static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)

case IF_IFACE_SYNC_SERIAL:
case IF_IFACE_V35:
- if(!capable(CAP_NET_ADMIN))
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (copy_from_user(&new_line, line, size))
return -EFAULT;
--
2.8.1

2021-06-10 07:28:08

by Guangbin Huang

[permalink] [raw]
Subject: [PATCH net-next 2/8] net: ixp4xx_hss: add blank line after declarations

From: Peng Li <[email protected]>

This patch fixes the checkpatch error about missing a blank line
after declarations.

Signed-off-by: Peng Li <[email protected]>
Signed-off-by: Guangbin Huang <[email protected]>
---
drivers/net/wan/ixp4xx_hss.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
index 2c135a9..6aa01d5 100644
--- a/drivers/net/wan/ixp4xx_hss.c
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -341,6 +341,7 @@ static inline struct port* dev_to_port(struct net_device *dev)
static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt)
{
int i;
+
for (i = 0; i < cnt; i++)
dest[i] = swab32(src[i]);
}
@@ -353,6 +354,7 @@ static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt)
static void hss_npe_send(struct port *port, struct msg *msg, const char* what)
{
u32 *val = (u32*)msg;
+
if (npe_send_message(port->npe, msg, what)) {
pr_crit("HSS-%i: unable to send command [%08X:%08X] to %s\n",
port->id, val[0], val[1], npe_name(port->npe));
@@ -1006,6 +1008,7 @@ static void destroy_hdlc_queues(struct port *port)
for (i = 0; i < RX_DESCS; i++) {
struct desc *desc = rx_desc_ptr(port, i);
buffer_t *buff = port->rx_buff_tab[i];
+
if (buff) {
dma_unmap_single(&port->netdev->dev,
desc->data, RX_SIZE,
@@ -1016,6 +1019,7 @@ static void destroy_hdlc_queues(struct port *port)
for (i = 0; i < TX_DESCS; i++) {
struct desc *desc = tx_desc_ptr(port, i);
buffer_t *buff = port->tx_buff_tab[i];
+
if (buff) {
dma_unmap_tx(port, desc);
free_buffer(buff);
@@ -1213,6 +1217,7 @@ static void find_best_clock(u32 timer_freq, u32 rate, u32 *best, u32 *reg)

for (b = 0; b < 0x400; b++) {
u64 c = (b + 1) * (u64)rate;
+
do_div(c, timer_freq - rate * a);
c--;
if (c >= 0xFFF) { /* 12-bit - no need to check more 'b's */
--
2.8.1

2021-06-10 21:02:35

by patchwork-bot+netdevbpf

[permalink] [raw]
Subject: Re: [PATCH net-next 0/8] net: ixp4xx_hss: clean up some code style issues

Hello:

This series was applied to netdev/net-next.git (refs/heads/master):

On Thu, 10 Jun 2021 15:19:57 +0800 you wrote:
> From: Peng Li <[email protected]>
>
> This patchset clean up some code style issues.
>
> Peng Li (8):
> net: ixp4xx_hss: remove redundant blank lines
> net: ixp4xx_hss: add blank line after declarations
> net: ixp4xx_hss: fix the code style issue about "foo* bar"
> net: ixp4xx_hss: move out assignment in if condition
> net: ixp4xx_hss: add some required spaces
> net: ixp4xx_hss: remove redundant spaces
> net: ixp4xx_hss: fix the comments style issue
> net: ixp4xx_hss: add braces {} to all arms of the statement
>
> [...]

Here is the summary with links:
- [net-next,1/8] net: ixp4xx_hss: remove redundant blank lines
https://git.kernel.org/netdev/net-next/c/5c32fdbb8997
- [net-next,2/8] net: ixp4xx_hss: add blank line after declarations
https://git.kernel.org/netdev/net-next/c/6f2016ed6538
- [net-next,3/8] net: ixp4xx_hss: fix the code style issue about "foo* bar"
https://git.kernel.org/netdev/net-next/c/6487fab04f27
- [net-next,4/8] net: ixp4xx_hss: move out assignment in if condition
https://git.kernel.org/netdev/net-next/c/99ebe65eb9c0
- [net-next,5/8] net: ixp4xx_hss: add some required spaces
https://git.kernel.org/netdev/net-next/c/dee014567732
- [net-next,6/8] net: ixp4xx_hss: remove redundant spaces
https://git.kernel.org/netdev/net-next/c/137d5672f80f
- [net-next,7/8] net: ixp4xx_hss: fix the comments style issue
https://git.kernel.org/netdev/net-next/c/17ce9764bb26
- [net-next,8/8] net: ixp4xx_hss: add braces {} to all arms of the statement
https://git.kernel.org/netdev/net-next/c/e0bd276463e8

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html