mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-08-21 14:23:40 +03:00
enable a different pseudo-vlan mode in the marvell switch (uses a proprietary header instead of a proprietary trailer) - fixes some mtu issues
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@10975 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
544232b227
commit
b84c7cd55b
@ -1,32 +1,41 @@
|
|||||||
Index: linux-2.6.23.16/drivers/net/ar2313/ar2313.c
|
Index: linux-2.6.23.16/drivers/net/ar2313/ar2313.c
|
||||||
===================================================================
|
===================================================================
|
||||||
--- linux-2.6.23.16.orig/drivers/net/ar2313/ar2313.c 2008-04-20 10:26:15.000000000 +0200
|
--- linux-2.6.23.16.orig/drivers/net/ar2313/ar2313.c 2008-04-29 14:51:39.000000000 +0200
|
||||||
+++ linux-2.6.23.16/drivers/net/ar2313/ar2313.c 2008-04-20 10:26:16.000000000 +0200
|
+++ linux-2.6.23.16/drivers/net/ar2313/ar2313.c 2008-04-29 14:52:14.000000000 +0200
|
||||||
@@ -955,7 +955,7 @@
|
@@ -219,7 +219,7 @@
|
||||||
|
dev->do_ioctl = &ar2313_ioctl;
|
||||||
|
|
||||||
|
// SAMEER: do we need this?
|
||||||
|
- dev->features |= NETIF_F_SG | NETIF_F_HIGHDMA;
|
||||||
|
+ dev->features |= NETIF_F_HIGHDMA | NETIF_F_HW_CSUM;
|
||||||
|
|
||||||
|
tasklet_init(&sp->rx_tasklet, rx_tasklet_func, (unsigned long) dev);
|
||||||
|
tasklet_disable(&sp->rx_tasklet);
|
||||||
|
@@ -953,9 +953,9 @@
|
||||||
|
((status >> DMA_RX_LEN_SHIFT) & 0x3fff) - CRC_LEN);
|
||||||
|
|
||||||
dev->stats.rx_bytes += skb->len;
|
dev->stats.rx_bytes += skb->len;
|
||||||
skb->protocol = eth_type_trans(skb, dev);
|
- skb->protocol = eth_type_trans(skb, dev);
|
||||||
|
+
|
||||||
/* pass the packet to upper layers */
|
/* pass the packet to upper layers */
|
||||||
- netif_rx(skb);
|
- netif_rx(skb);
|
||||||
+ sp->rx(skb);
|
+ sp->rx(skb);
|
||||||
|
|
||||||
skb_new->dev = dev;
|
skb_new->dev = dev;
|
||||||
/* 16 bit align */
|
/* 16 bit align */
|
||||||
@@ -1370,6 +1370,11 @@
|
@@ -1370,6 +1370,8 @@
|
||||||
return PTR_ERR(phydev);
|
return PTR_ERR(phydev);
|
||||||
}
|
}
|
||||||
|
|
||||||
+ if (phydev->netif_rx)
|
+ sp->rx = phydev->netif_rx;
|
||||||
+ sp->rx = phydev->netif_rx;
|
|
||||||
+ else
|
|
||||||
+ sp->rx = netif_rx;
|
|
||||||
+
|
+
|
||||||
/* mask with MAC supported features */
|
/* mask with MAC supported features */
|
||||||
phydev->supported &= (SUPPORTED_10baseT_Half
|
phydev->supported &= (SUPPORTED_10baseT_Half
|
||||||
| SUPPORTED_10baseT_Full
|
| SUPPORTED_10baseT_Full
|
||||||
Index: linux-2.6.23.16/drivers/net/ar2313/ar2313.h
|
Index: linux-2.6.23.16/drivers/net/ar2313/ar2313.h
|
||||||
===================================================================
|
===================================================================
|
||||||
--- linux-2.6.23.16.orig/drivers/net/ar2313/ar2313.h 2008-04-20 10:26:15.000000000 +0200
|
--- linux-2.6.23.16.orig/drivers/net/ar2313/ar2313.h 2008-04-29 14:51:39.000000000 +0200
|
||||||
+++ linux-2.6.23.16/drivers/net/ar2313/ar2313.h 2008-04-20 10:26:16.000000000 +0200
|
+++ linux-2.6.23.16/drivers/net/ar2313/ar2313.h 2008-04-29 14:52:15.000000000 +0200
|
||||||
@@ -107,6 +107,8 @@
|
@@ -107,6 +107,8 @@
|
||||||
*/
|
*/
|
||||||
struct ar2313_private {
|
struct ar2313_private {
|
||||||
|
@ -30,6 +30,10 @@
|
|||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include "mvswitch.h"
|
#include "mvswitch.h"
|
||||||
|
|
||||||
|
/* Undefine this to use trailer mode instead.
|
||||||
|
* I don't know if header mode works with all chips */
|
||||||
|
#define HEADER_MODE 1
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Marvell 88E6060 Switch driver");
|
MODULE_DESCRIPTION("Marvell 88E6060 Switch driver");
|
||||||
MODULE_AUTHOR("Felix Fietkau");
|
MODULE_AUTHOR("Felix Fietkau");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
@ -55,11 +59,11 @@ w16(struct phy_device *phydev, int addr, int reg, u16 val)
|
|||||||
phydev->bus->write(phydev->bus, addr, reg, val);
|
phydev->bus->write(phydev->bus, addr, reg, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mvswitch_mangle_tx(struct sk_buff *skb, struct net_device *dev)
|
mvswitch_mangle_tx(struct sk_buff *skb, struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct mvswitch_priv *priv;
|
struct mvswitch_priv *priv;
|
||||||
struct vlan_ethhdr *eh;
|
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
u16 vid;
|
u16 vid;
|
||||||
|
|
||||||
@ -70,30 +74,34 @@ mvswitch_mangle_tx(struct sk_buff *skb, struct net_device *dev)
|
|||||||
if (unlikely(skb->len < 16))
|
if (unlikely(skb->len < 16))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
eh = (struct vlan_ethhdr *) skb->data;
|
#ifdef HEADER_MODE
|
||||||
if (be16_to_cpu(eh->h_vlan_proto) != 0x8100)
|
if (__vlan_hwaccel_get_tag(skb, &vid))
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if ((skb->len <= 62) || (skb_headroom(skb) < MV_HEADER_SIZE)) {
|
||||||
|
if (pskb_expand_head(skb, MV_HEADER_SIZE, 0, GFP_ATOMIC))
|
||||||
|
goto error_expand;
|
||||||
|
if (skb->len < 62)
|
||||||
|
skb->len = 62;
|
||||||
|
}
|
||||||
|
buf = skb_push(skb, MV_HEADER_SIZE);
|
||||||
|
#else
|
||||||
|
if (__vlan_get_tag(skb, &vid))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
vid = be16_to_cpu(eh->h_vlan_TCI) & VLAN_VID_MASK;
|
|
||||||
if (unlikely((vid > 15 || !priv->vlans[vid])))
|
if (unlikely((vid > 15 || !priv->vlans[vid])))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (skb->len <= 64) {
|
if (skb->len <= 64) {
|
||||||
if (pskb_expand_head(skb, 0, 68 - skb->len, GFP_ATOMIC)) {
|
if (pskb_expand_head(skb, 0, 64 + MV_TRAILER_SIZE - skb->len, GFP_ATOMIC))
|
||||||
if (net_ratelimit())
|
goto error_expand;
|
||||||
printk("%s: failed to expand/update skb for the switch\n", dev->name);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = skb->data + 64;
|
buf = skb->data + 64;
|
||||||
skb->len = 68;
|
skb->len = 64 + MV_TRAILER_SIZE;
|
||||||
} else {
|
} else {
|
||||||
if (skb_cloned(skb) || unlikely(skb_tailroom(skb) < 4)) {
|
if (skb_cloned(skb) || unlikely(skb_tailroom(skb) < 4)) {
|
||||||
if (pskb_expand_head(skb, 0, 4, GFP_ATOMIC)) {
|
if (pskb_expand_head(skb, 0, 4, GFP_ATOMIC))
|
||||||
if (net_ratelimit())
|
goto error_expand;
|
||||||
printk("%s: failed to expand/update skb for the switch\n", dev->name);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
buf = skb_put(skb, 4);
|
buf = skb_put(skb, 4);
|
||||||
}
|
}
|
||||||
@ -103,18 +111,32 @@ mvswitch_mangle_tx(struct sk_buff *skb, struct net_device *dev)
|
|||||||
skb->data += 4;
|
skb->data += 4;
|
||||||
skb->len -= 4;
|
skb->len -= 4;
|
||||||
skb->mac_header += 4;
|
skb->mac_header += 4;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!buf)
|
if (!buf)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* append the tag */
|
|
||||||
*((u32 *) buf) = (
|
#ifdef HEADER_MODE
|
||||||
(0x80 << 24) |
|
/* prepend the tag */
|
||||||
((priv->vlans[vid] & 0x1f) << 16)
|
*((__be16 *) buf) = cpu_to_be16(
|
||||||
|
((vid << MV_HEADER_VLAN_S) & MV_HEADER_VLAN_M) |
|
||||||
|
((priv->vlans[vid] << MV_HEADER_PORTS_S) & MV_HEADER_PORTS_M)
|
||||||
);
|
);
|
||||||
|
#else
|
||||||
|
/* append the tag */
|
||||||
|
*((__be32 *) buf) = cpu_to_be32((
|
||||||
|
(MV_TRAILER_OVERRIDE << MV_TRAILER_FLAGS_S) |
|
||||||
|
((priv->vlans[vid] & MV_TRAILER_PORTS_M) << MV_TRAILER_PORTS_S)
|
||||||
|
));
|
||||||
|
#endif
|
||||||
|
|
||||||
return priv->hardstart(skb, dev);
|
return priv->hardstart(skb, dev);
|
||||||
|
|
||||||
|
error_expand:
|
||||||
|
if (net_ratelimit())
|
||||||
|
printk("%s: failed to expand/update skb for the switch\n", dev->name);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
/* any errors? drop the packet! */
|
/* any errors? drop the packet! */
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
@ -141,9 +163,14 @@ mvswitch_mangle_rx(struct sk_buff *skb, int napi)
|
|||||||
if (!priv->grp)
|
if (!priv->grp)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
buf = skb->data + skb->len - 4;
|
#ifdef HEADER_MODE
|
||||||
|
buf = skb->data;
|
||||||
|
skb_pull(skb, MV_HEADER_SIZE);
|
||||||
|
#else
|
||||||
|
buf = skb->data + skb->len - MV_TRAILER_SIZE;
|
||||||
if (buf[0] != 0x80)
|
if (buf[0] != 0x80)
|
||||||
goto error;
|
goto error;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* look for the vlan matching the incoming port */
|
/* look for the vlan matching the incoming port */
|
||||||
for (i = 0; i < ARRAY_SIZE(priv->vlans); i++) {
|
for (i = 0; i < ARRAY_SIZE(priv->vlans); i++) {
|
||||||
@ -154,6 +181,8 @@ mvswitch_mangle_rx(struct sk_buff *skb, int napi)
|
|||||||
if (vlan == -1)
|
if (vlan == -1)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||||
|
|
||||||
if (napi)
|
if (napi)
|
||||||
return vlan_hwaccel_receive_skb(skb, priv->grp, vlan);
|
return vlan_hwaccel_receive_skb(skb, priv->grp, vlan);
|
||||||
else
|
else
|
||||||
@ -234,9 +263,13 @@ mvswitch_config_init(struct phy_device *pdev)
|
|||||||
|
|
||||||
/* initialize the cpu port */
|
/* initialize the cpu port */
|
||||||
w16(pdev, MV_PORTREG(CONTROL, MV_CPUPORT),
|
w16(pdev, MV_PORTREG(CONTROL, MV_CPUPORT),
|
||||||
MV_PORTCTRL_ENABLED |
|
#ifdef HEADER_MODE
|
||||||
|
MV_PORTCTRL_HEADER |
|
||||||
|
#else
|
||||||
MV_PORTCTRL_RXTR |
|
MV_PORTCTRL_RXTR |
|
||||||
MV_PORTCTRL_TXTR
|
MV_PORTCTRL_TXTR |
|
||||||
|
#endif
|
||||||
|
MV_PORTCTRL_ENABLED
|
||||||
);
|
);
|
||||||
/* wait for the phy change to settle in */
|
/* wait for the phy change to settle in */
|
||||||
msleep(2);
|
msleep(2);
|
||||||
@ -300,7 +333,11 @@ mvswitch_config_init(struct phy_device *pdev)
|
|||||||
pdev->netif_rx = mvswitch_netif_rx;
|
pdev->netif_rx = mvswitch_netif_rx;
|
||||||
dev->hard_start_xmit = mvswitch_mangle_tx;
|
dev->hard_start_xmit = mvswitch_mangle_tx;
|
||||||
dev->vlan_rx_register = mvswitch_vlan_rx_register;
|
dev->vlan_rx_register = mvswitch_vlan_rx_register;
|
||||||
|
#ifdef HEADER_MODE
|
||||||
|
dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;
|
||||||
|
#else
|
||||||
dev->features |= NETIF_F_HW_VLAN_RX;
|
dev->features |= NETIF_F_HW_VLAN_RX;
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,19 @@
|
|||||||
#ifndef __MVSWITCH_H
|
#ifndef __MVSWITCH_H
|
||||||
#define __MVSWITCH_H
|
#define __MVSWITCH_H
|
||||||
|
|
||||||
|
#define MV_HEADER_SIZE 2
|
||||||
|
#define MV_HEADER_PORTS_M 0x001f
|
||||||
|
#define MV_HEADER_PORTS_S 0
|
||||||
|
#define MV_HEADER_VLAN_M 0xf000
|
||||||
|
#define MV_HEADER_VLAN_S 12
|
||||||
|
|
||||||
|
#define MV_TRAILER_SIZE 4
|
||||||
|
#define MV_TRAILER_PORTS_M 0x1f
|
||||||
|
#define MV_TRAILER_PORTS_S 16
|
||||||
|
#define MV_TRAILER_FLAGS_S 24
|
||||||
|
#define MV_TRAILER_OVERRIDE 0x80
|
||||||
|
|
||||||
|
|
||||||
#define MV_PORTS 5
|
#define MV_PORTS 5
|
||||||
#define MV_WANPORT 4
|
#define MV_WANPORT 4
|
||||||
#define MV_CPUPORT 5
|
#define MV_CPUPORT 5
|
||||||
@ -36,7 +49,7 @@ enum {
|
|||||||
MV_PHY_INTR_EN = 0x12,
|
MV_PHY_INTR_EN = 0x12,
|
||||||
MV_PHY_INTR_STATUS = 0x13,
|
MV_PHY_INTR_STATUS = 0x13,
|
||||||
MV_PHY_INTR_PORT = 0x14,
|
MV_PHY_INTR_PORT = 0x14,
|
||||||
MV_PHY_RECV_COUNTER = 0x15,
|
MV_PHY_RECV_COUNTER = 0x16,
|
||||||
MV_PHY_LED_PARALLEL = 0x16,
|
MV_PHY_LED_PARALLEL = 0x16,
|
||||||
MV_PHY_LED_STREAM = 0x17,
|
MV_PHY_LED_STREAM = 0x17,
|
||||||
MV_PHY_LED_CTRL = 0x18,
|
MV_PHY_LED_CTRL = 0x18,
|
||||||
@ -64,6 +77,7 @@ enum {
|
|||||||
MV_PORTCTRL_ENABLED = (3 << 0),
|
MV_PORTCTRL_ENABLED = (3 << 0),
|
||||||
MV_PORTCTRL_VLANTUN = (1 << 7), /* Enforce VLANs on packets */
|
MV_PORTCTRL_VLANTUN = (1 << 7), /* Enforce VLANs on packets */
|
||||||
MV_PORTCTRL_RXTR = (1 << 8), /* Enable Marvell packet trailer for ingress */
|
MV_PORTCTRL_RXTR = (1 << 8), /* Enable Marvell packet trailer for ingress */
|
||||||
|
MV_PORTCTRL_HEADER = (1 << 11), /* Enable Marvell packet header mode for port */
|
||||||
MV_PORTCTRL_TXTR = (1 << 14), /* Enable Marvell packet trailer for egress */
|
MV_PORTCTRL_TXTR = (1 << 14), /* Enable Marvell packet trailer for egress */
|
||||||
MV_PORTCTRL_FORCEFL = (1 << 15), /* force flow control */
|
MV_PORTCTRL_FORCEFL = (1 << 15), /* force flow control */
|
||||||
};
|
};
|
||||||
@ -88,6 +102,17 @@ enum {
|
|||||||
};
|
};
|
||||||
#define MV_SWITCHREG(_type) MV_SWITCHREGS, MV_SWITCH_##_type
|
#define MV_SWITCHREG(_type) MV_SWITCHREGS, MV_SWITCH_##_type
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MV_SWITCHCTL_EEIE = (1 << 0), /* EEPROM interrupt enable */
|
||||||
|
MV_SWITCHCTL_PHYIE = (1 << 1), /* PHY interrupt enable */
|
||||||
|
MV_SWITCHCTL_ATUDONE= (1 << 2), /* ATU done interrupt enable */
|
||||||
|
MV_SWITCHCTL_ATUIE = (1 << 3), /* ATU interrupt enable */
|
||||||
|
MV_SWITCHCTL_CTRMODE= (1 << 8), /* statistics for rx and tx errors */
|
||||||
|
MV_SWITCHCTL_RELOAD = (1 << 9), /* reload registers from eeprom */
|
||||||
|
MV_SWITCHCTL_MSIZE = (1 << 10), /* increase maximum frame size */
|
||||||
|
MV_SWITCHCTL_DROP = (1 << 13), /* discard frames with excessive collisions */
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
#define MV_ATUCTL_AGETIME(_n) ((((_n) / 16) & 0xff) << 4)
|
#define MV_ATUCTL_AGETIME(_n) ((((_n) / 16) & 0xff) << 4)
|
||||||
MV_ATUCTL_ATU_256 = (0 << 12),
|
MV_ATUCTL_ATU_256 = (0 << 12),
|
||||||
|
@ -1,20 +1,39 @@
|
|||||||
Index: linux-2.6.23.16/drivers/net/phy/phy_device.c
|
Index: linux-2.6.23.16/drivers/net/phy/phy_device.c
|
||||||
===================================================================
|
===================================================================
|
||||||
--- linux-2.6.23.16.orig/drivers/net/phy/phy_device.c 2008-02-11 07:06:32.000000000 +0100
|
--- linux-2.6.23.16.orig/drivers/net/phy/phy_device.c 2008-04-20 10:16:21.000000000 +0200
|
||||||
+++ linux-2.6.23.16/drivers/net/phy/phy_device.c 2008-04-20 05:42:28.000000000 +0200
|
+++ linux-2.6.23.16/drivers/net/phy/phy_device.c 2008-04-29 14:20:03.000000000 +0200
|
||||||
@@ -67,6 +67,8 @@
|
@@ -44,6 +44,18 @@
|
||||||
|
extern int mdio_bus_init(void);
|
||||||
|
extern void mdio_bus_exit(void);
|
||||||
|
|
||||||
|
+static int generic_receive_skb(struct sk_buff *skb)
|
||||||
|
+{
|
||||||
|
+ skb->protocol = eth_type_trans(skb, skb->dev);
|
||||||
|
+ return netif_receive_skb(skb);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int generic_rx(struct sk_buff *skb)
|
||||||
|
+{
|
||||||
|
+ skb->protocol = eth_type_trans(skb, skb->dev);
|
||||||
|
+ return netif_rx(skb);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id)
|
||||||
|
{
|
||||||
|
struct phy_device *dev;
|
||||||
|
@@ -67,6 +79,8 @@
|
||||||
dev->bus = bus;
|
dev->bus = bus;
|
||||||
|
|
||||||
dev->state = PHY_DOWN;
|
dev->state = PHY_DOWN;
|
||||||
+ dev->netif_receive_skb = &netif_receive_skb;
|
+ dev->netif_receive_skb = &generic_receive_skb;
|
||||||
+ dev->netif_rx = &netif_rx;
|
+ dev->netif_rx = &generic_rx;
|
||||||
|
|
||||||
spin_lock_init(&dev->lock);
|
spin_lock_init(&dev->lock);
|
||||||
|
|
||||||
Index: linux-2.6.23.16/include/linux/phy.h
|
Index: linux-2.6.23.16/include/linux/phy.h
|
||||||
===================================================================
|
===================================================================
|
||||||
--- linux-2.6.23.16.orig/include/linux/phy.h 2008-04-20 04:40:31.000000000 +0200
|
--- linux-2.6.23.16.orig/include/linux/phy.h 2008-04-20 10:16:21.000000000 +0200
|
||||||
+++ linux-2.6.23.16/include/linux/phy.h 2008-04-20 05:53:21.000000000 +0200
|
+++ linux-2.6.23.16/include/linux/phy.h 2008-04-20 10:17:58.000000000 +0200
|
||||||
@@ -289,6 +289,17 @@
|
@@ -289,6 +289,17 @@
|
||||||
void (*adjust_link)(struct net_device *dev);
|
void (*adjust_link)(struct net_device *dev);
|
||||||
|
|
||||||
@ -35,8 +54,8 @@ Index: linux-2.6.23.16/include/linux/phy.h
|
|||||||
|
|
||||||
Index: linux-2.6.23.16/include/linux/netdevice.h
|
Index: linux-2.6.23.16/include/linux/netdevice.h
|
||||||
===================================================================
|
===================================================================
|
||||||
--- linux-2.6.23.16.orig/include/linux/netdevice.h 2008-02-11 07:06:32.000000000 +0100
|
--- linux-2.6.23.16.orig/include/linux/netdevice.h 2008-04-20 10:16:21.000000000 +0200
|
||||||
+++ linux-2.6.23.16/include/linux/netdevice.h 2008-04-20 06:33:25.000000000 +0200
|
+++ linux-2.6.23.16/include/linux/netdevice.h 2008-04-20 10:17:58.000000000 +0200
|
||||||
@@ -426,6 +426,7 @@
|
@@ -426,6 +426,7 @@
|
||||||
void *ax25_ptr; /* AX.25 specific data */
|
void *ax25_ptr; /* AX.25 specific data */
|
||||||
struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data,
|
struct wireless_dev *ieee80211_ptr; /* IEEE 802.11 specific data,
|
||||||
|
Loading…
Reference in New Issue
Block a user