Commit 64cb104e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6

* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6:
  [PATCH] Kconfig: remove redundant NETDEVICES depends
  [PATCH] ehea: 64K page support fix
  [PATCH] ehea: Removed redundant define
  [PATCH] ehea: Nullpointer dereferencation fix
  [PATCH] bcm43xx: fix unexpected LED control values in BCM4303 sprom
  [PATCH] bcm43xx: Fix low-traffic netdev watchdog TX timeouts
  [PATCH] hostap_plx: fix CIS verification
  [PATCH] ieee80211: don't flood log with errors
parents 0c7bb31d 78eb77a9
...@@ -486,7 +486,7 @@ config SGI_IOC3_ETH_HW_TX_CSUM ...@@ -486,7 +486,7 @@ config SGI_IOC3_ETH_HW_TX_CSUM
config MIPS_SIM_NET config MIPS_SIM_NET
tristate "MIPS simulator Network device (EXPERIMENTAL)" tristate "MIPS simulator Network device (EXPERIMENTAL)"
depends on NETDEVICES && MIPS_SIM && EXPERIMENTAL depends on MIPS_SIM && EXPERIMENTAL
help help
The MIPSNET device is a simple Ethernet network device which is The MIPSNET device is a simple Ethernet network device which is
emulated by the MIPS Simulator. emulated by the MIPS Simulator.
...@@ -2467,7 +2467,7 @@ config ISERIES_VETH ...@@ -2467,7 +2467,7 @@ config ISERIES_VETH
config RIONET config RIONET
tristate "RapidIO Ethernet over messaging driver support" tristate "RapidIO Ethernet over messaging driver support"
depends on NETDEVICES && RAPIDIO depends on RAPIDIO
config RIONET_TX_SIZE config RIONET_TX_SIZE
int "Number of outbound queue entries" int "Number of outbound queue entries"
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#include <asm/io.h> #include <asm/io.h>
#define DRV_NAME "ehea" #define DRV_NAME "ehea"
#define DRV_VERSION "EHEA_0034" #define DRV_VERSION "EHEA_0043"
#define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \ #define EHEA_MSG_DEFAULT (NETIF_MSG_LINK | NETIF_MSG_TIMER \
| NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR) | NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
...@@ -105,9 +105,6 @@ ...@@ -105,9 +105,6 @@
#define EHEA_BCMC_VLANID_ALL 0x01 #define EHEA_BCMC_VLANID_ALL 0x01
#define EHEA_BCMC_VLANID_SINGLE 0x00 #define EHEA_BCMC_VLANID_SINGLE 0x00
/* Use this define to kmallocate pHYP control blocks */
#define H_CB_ALIGNMENT 4096
#define EHEA_CACHE_LINE 128 #define EHEA_CACHE_LINE 128
/* Memory Regions */ /* Memory Regions */
......
...@@ -238,7 +238,7 @@ static void ehea_get_ethtool_stats(struct net_device *dev, ...@@ -238,7 +238,7 @@ static void ehea_get_ethtool_stats(struct net_device *dev,
data[i++] = port->port_res[0].swqe_refill_th; data[i++] = port->port_res[0].swqe_refill_th;
data[i++] = port->resets; data[i++] = port->resets;
cb6 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); cb6 = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!cb6) { if (!cb6) {
ehea_error("no mem for cb6"); ehea_error("no mem for cb6");
return; return;
......
...@@ -92,7 +92,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev) ...@@ -92,7 +92,7 @@ static struct net_device_stats *ehea_get_stats(struct net_device *dev)
memset(stats, 0, sizeof(*stats)); memset(stats, 0, sizeof(*stats));
cb2 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); cb2 = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!cb2) { if (!cb2) {
ehea_error("no mem for cb2"); ehea_error("no mem for cb2");
goto out; goto out;
...@@ -586,7 +586,7 @@ int ehea_sense_port_attr(struct ehea_port *port) ...@@ -586,7 +586,7 @@ int ehea_sense_port_attr(struct ehea_port *port)
u64 hret; u64 hret;
struct hcp_ehea_port_cb0 *cb0; struct hcp_ehea_port_cb0 *cb0;
cb0 = kzalloc(H_CB_ALIGNMENT, GFP_ATOMIC); /* May be called via */ cb0 = kzalloc(PAGE_SIZE, GFP_ATOMIC); /* May be called via */
if (!cb0) { /* ehea_neq_tasklet() */ if (!cb0) { /* ehea_neq_tasklet() */
ehea_error("no mem for cb0"); ehea_error("no mem for cb0");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -670,7 +670,7 @@ int ehea_set_portspeed(struct ehea_port *port, u32 port_speed) ...@@ -670,7 +670,7 @@ int ehea_set_portspeed(struct ehea_port *port, u32 port_speed)
u64 hret; u64 hret;
int ret = 0; int ret = 0;
cb4 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!cb4) { if (!cb4) {
ehea_error("no mem for cb4"); ehea_error("no mem for cb4");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -985,7 +985,7 @@ static int ehea_configure_port(struct ehea_port *port) ...@@ -985,7 +985,7 @@ static int ehea_configure_port(struct ehea_port *port)
struct hcp_ehea_port_cb0 *cb0; struct hcp_ehea_port_cb0 *cb0;
ret = -ENOMEM; ret = -ENOMEM;
cb0 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!cb0) if (!cb0)
goto out; goto out;
...@@ -1443,7 +1443,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa) ...@@ -1443,7 +1443,7 @@ static int ehea_set_mac_addr(struct net_device *dev, void *sa)
goto out; goto out;
} }
cb0 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!cb0) { if (!cb0) {
ehea_error("no mem for cb0"); ehea_error("no mem for cb0");
ret = -ENOMEM; ret = -ENOMEM;
...@@ -1501,7 +1501,7 @@ static void ehea_promiscuous(struct net_device *dev, int enable) ...@@ -1501,7 +1501,7 @@ static void ehea_promiscuous(struct net_device *dev, int enable)
if ((enable && port->promisc) || (!enable && !port->promisc)) if ((enable && port->promisc) || (!enable && !port->promisc))
return; return;
cb7 = kzalloc(H_CB_ALIGNMENT, GFP_ATOMIC); cb7 = kzalloc(PAGE_SIZE, GFP_ATOMIC);
if (!cb7) { if (!cb7) {
ehea_error("no mem for cb7"); ehea_error("no mem for cb7");
goto out; goto out;
...@@ -1870,7 +1870,7 @@ static void ehea_vlan_rx_register(struct net_device *dev, ...@@ -1870,7 +1870,7 @@ static void ehea_vlan_rx_register(struct net_device *dev,
port->vgrp = grp; port->vgrp = grp;
cb1 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!cb1) { if (!cb1) {
ehea_error("no mem for cb1"); ehea_error("no mem for cb1");
goto out; goto out;
...@@ -1899,7 +1899,7 @@ static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) ...@@ -1899,7 +1899,7 @@ static void ehea_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
int index; int index;
u64 hret; u64 hret;
cb1 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!cb1) { if (!cb1) {
ehea_error("no mem for cb1"); ehea_error("no mem for cb1");
goto out; goto out;
...@@ -1935,7 +1935,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid) ...@@ -1935,7 +1935,7 @@ static void ehea_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
if (port->vgrp) if (port->vgrp)
port->vgrp->vlan_devices[vid] = NULL; port->vgrp->vlan_devices[vid] = NULL;
cb1 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); cb1 = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!cb1) { if (!cb1) {
ehea_error("no mem for cb1"); ehea_error("no mem for cb1");
goto out; goto out;
...@@ -1968,7 +1968,7 @@ int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp) ...@@ -1968,7 +1968,7 @@ int ehea_activate_qp(struct ehea_adapter *adapter, struct ehea_qp *qp)
u64 dummy64 = 0; u64 dummy64 = 0;
struct hcp_modify_qp_cb0* cb0; struct hcp_modify_qp_cb0* cb0;
cb0 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); cb0 = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!cb0) { if (!cb0) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
...@@ -2269,7 +2269,7 @@ int ehea_sense_adapter_attr(struct ehea_adapter *adapter) ...@@ -2269,7 +2269,7 @@ int ehea_sense_adapter_attr(struct ehea_adapter *adapter)
u64 hret; u64 hret;
int ret; int ret;
cb = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); cb = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!cb) { if (!cb) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
...@@ -2340,7 +2340,7 @@ static int ehea_setup_single_port(struct ehea_port *port, ...@@ -2340,7 +2340,7 @@ static int ehea_setup_single_port(struct ehea_port *port,
goto out; goto out;
/* Enable Jumbo frames */ /* Enable Jumbo frames */
cb4 = kzalloc(H_CB_ALIGNMENT, GFP_KERNEL); cb4 = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!cb4) { if (!cb4) {
ehea_error("no mem for cb4"); ehea_error("no mem for cb4");
} else { } else {
......
...@@ -506,7 +506,7 @@ u64 ehea_h_register_rpage_mr(const u64 adapter_handle, const u64 mr_handle, ...@@ -506,7 +506,7 @@ u64 ehea_h_register_rpage_mr(const u64 adapter_handle, const u64 mr_handle,
const u8 pagesize, const u8 queue_type, const u8 pagesize, const u8 queue_type,
const u64 log_pageaddr, const u64 count) const u64 log_pageaddr, const u64 count)
{ {
if ((count > 1) && (log_pageaddr & 0xfff)) { if ((count > 1) && (log_pageaddr & ~PAGE_MASK)) {
ehea_error("not on pageboundary"); ehea_error("not on pageboundary");
return H_PARAMETER; return H_PARAMETER;
} }
......
...@@ -81,14 +81,16 @@ static inline u32 get_longbusy_msecs(int long_busy_ret_code) ...@@ -81,14 +81,16 @@ static inline u32 get_longbusy_msecs(int long_busy_ret_code)
static inline void hcp_epas_ctor(struct h_epas *epas, u64 paddr_kernel, static inline void hcp_epas_ctor(struct h_epas *epas, u64 paddr_kernel,
u64 paddr_user) u64 paddr_user)
{ {
epas->kernel.addr = ioremap(paddr_kernel, PAGE_SIZE); /* To support 64k pages we must round to 64k page boundary */
epas->kernel.addr = ioremap((paddr_kernel & PAGE_MASK), PAGE_SIZE) +
(paddr_kernel & ~PAGE_MASK);
epas->user.addr = paddr_user; epas->user.addr = paddr_user;
} }
static inline void hcp_epas_dtor(struct h_epas *epas) static inline void hcp_epas_dtor(struct h_epas *epas)
{ {
if (epas->kernel.addr) if (epas->kernel.addr)
iounmap(epas->kernel.addr); iounmap((void __iomem*)((u64)epas->kernel.addr & PAGE_MASK));
epas->user.addr = 0; epas->user.addr = 0;
epas->kernel.addr = 0; epas->kernel.addr = 0;
......
...@@ -209,11 +209,11 @@ int ehea_destroy_cq(struct ehea_cq *cq) ...@@ -209,11 +209,11 @@ int ehea_destroy_cq(struct ehea_cq *cq)
{ {
u64 adapter_handle, hret; u64 adapter_handle, hret;
adapter_handle = cq->adapter->handle;
if (!cq) if (!cq)
return 0; return 0;
adapter_handle = cq->adapter->handle;
/* deregister all previous registered pages */ /* deregister all previous registered pages */
hret = ehea_h_free_resource(adapter_handle, cq->fw_handle); hret = ehea_h_free_resource(adapter_handle, cq->fw_handle);
if (hret != H_SUCCESS) { if (hret != H_SUCCESS) {
...@@ -512,7 +512,7 @@ int ehea_reg_mr_adapter(struct ehea_adapter *adapter) ...@@ -512,7 +512,7 @@ int ehea_reg_mr_adapter(struct ehea_adapter *adapter)
start = KERNELBASE; start = KERNELBASE;
end = (u64)high_memory; end = (u64)high_memory;
nr_pages = (end - start) / PAGE_SIZE; nr_pages = (end - start) / EHEA_PAGESIZE;
pt = kzalloc(PAGE_SIZE, GFP_KERNEL); pt = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!pt) { if (!pt) {
...@@ -538,9 +538,9 @@ int ehea_reg_mr_adapter(struct ehea_adapter *adapter) ...@@ -538,9 +538,9 @@ int ehea_reg_mr_adapter(struct ehea_adapter *adapter)
if (nr_pages > 1) { if (nr_pages > 1) {
u64 num_pages = min(nr_pages, (u64)512); u64 num_pages = min(nr_pages, (u64)512);
for (i = 0; i < num_pages; i++) for (i = 0; i < num_pages; i++)
pt[i] = virt_to_abs((void*)(((u64)start) pt[i] = virt_to_abs((void*)(((u64)start) +
+ ((k++) * ((k++) *
PAGE_SIZE))); EHEA_PAGESIZE)));
hret = ehea_h_register_rpage_mr(adapter->handle, hret = ehea_h_register_rpage_mr(adapter->handle,
adapter->mr.handle, 0, adapter->mr.handle, 0,
...@@ -548,8 +548,9 @@ int ehea_reg_mr_adapter(struct ehea_adapter *adapter) ...@@ -548,8 +548,9 @@ int ehea_reg_mr_adapter(struct ehea_adapter *adapter)
num_pages); num_pages);
nr_pages -= num_pages; nr_pages -= num_pages;
} else { } else {
u64 abs_adr = virt_to_abs((void*)(((u64)start) u64 abs_adr = virt_to_abs((void*)(((u64)start) +
+ (k * PAGE_SIZE))); (k * EHEA_PAGESIZE)));
hret = ehea_h_register_rpage_mr(adapter->handle, hret = ehea_h_register_rpage_mr(adapter->handle,
adapter->mr.handle, 0, adapter->mr.handle, 0,
0, abs_adr,1); 0, abs_adr,1);
......
...@@ -189,20 +189,24 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) ...@@ -189,20 +189,24 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
case BCM43xx_LED_INACTIVE: case BCM43xx_LED_INACTIVE:
continue; continue;
case BCM43xx_LED_OFF: case BCM43xx_LED_OFF:
case BCM43xx_LED_BCM4303_3:
break; break;
case BCM43xx_LED_ON: case BCM43xx_LED_ON:
turn_on = 1; turn_on = 1;
break; break;
case BCM43xx_LED_ACTIVITY: case BCM43xx_LED_ACTIVITY:
case BCM43xx_LED_BCM4303_0:
turn_on = activity; turn_on = activity;
break; break;
case BCM43xx_LED_RADIO_ALL: case BCM43xx_LED_RADIO_ALL:
turn_on = radio->enabled; turn_on = radio->enabled;
break; break;
case BCM43xx_LED_RADIO_A: case BCM43xx_LED_RADIO_A:
case BCM43xx_LED_BCM4303_2:
turn_on = (radio->enabled && phy->type == BCM43xx_PHYTYPE_A); turn_on = (radio->enabled && phy->type == BCM43xx_PHYTYPE_A);
break; break;
case BCM43xx_LED_RADIO_B: case BCM43xx_LED_RADIO_B:
case BCM43xx_LED_BCM4303_1:
turn_on = (radio->enabled && turn_on = (radio->enabled &&
(phy->type == BCM43xx_PHYTYPE_B || (phy->type == BCM43xx_PHYTYPE_B ||
phy->type == BCM43xx_PHYTYPE_G)); phy->type == BCM43xx_PHYTYPE_G));
...@@ -257,7 +261,8 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) ...@@ -257,7 +261,8 @@ void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity)
continue; continue;
#endif /* CONFIG_BCM43XX_DEBUG */ #endif /* CONFIG_BCM43XX_DEBUG */
default: default:
assert(0); dprintkl(KERN_INFO PFX "Bad value in leds_update,"
" led->behaviour: 0x%x\n", led->behaviour);
}; };
if (led->activelow) if (led->activelow)
......
...@@ -46,6 +46,12 @@ enum { /* LED behaviour values */ ...@@ -46,6 +46,12 @@ enum { /* LED behaviour values */
BCM43xx_LED_TEST_BLINKSLOW, BCM43xx_LED_TEST_BLINKSLOW,
BCM43xx_LED_TEST_BLINKMEDIUM, BCM43xx_LED_TEST_BLINKMEDIUM,
BCM43xx_LED_TEST_BLINKFAST, BCM43xx_LED_TEST_BLINKFAST,
/* Misc values for BCM4303 */
BCM43xx_LED_BCM4303_0 = 0x2B,
BCM43xx_LED_BCM4303_1 = 0x78,
BCM43xx_LED_BCM4303_2 = 0x2E,
BCM43xx_LED_BCM4303_3 = 0x19,
}; };
int bcm43xx_leds_init(struct bcm43xx_private *bcm); int bcm43xx_leds_init(struct bcm43xx_private *bcm);
......
...@@ -3163,9 +3163,11 @@ static int estimate_periodic_work_badness(unsigned int state) ...@@ -3163,9 +3163,11 @@ static int estimate_periodic_work_badness(unsigned int state)
static void bcm43xx_periodic_work_handler(void *d) static void bcm43xx_periodic_work_handler(void *d)
{ {
struct bcm43xx_private *bcm = d; struct bcm43xx_private *bcm = d;
struct net_device *net_dev = bcm->net_dev;
unsigned long flags; unsigned long flags;
u32 savedirqs = 0; u32 savedirqs = 0;
int badness; int badness;
unsigned long orig_trans_start = 0;
mutex_lock(&bcm->mutex); mutex_lock(&bcm->mutex);
badness = estimate_periodic_work_badness(bcm->periodic_state); badness = estimate_periodic_work_badness(bcm->periodic_state);
...@@ -3173,7 +3175,18 @@ static void bcm43xx_periodic_work_handler(void *d) ...@@ -3173,7 +3175,18 @@ static void bcm43xx_periodic_work_handler(void *d)
/* Periodic work will take a long time, so we want it to /* Periodic work will take a long time, so we want it to
* be preemtible. * be preemtible.
*/ */
netif_tx_disable(bcm->net_dev);
netif_tx_lock_bh(net_dev);
/* We must fake a started transmission here, as we are going to
* disable TX. If we wouldn't fake a TX, it would be possible to
* trigger the netdev watchdog, if the last real TX is already
* some time on the past (slightly less than 5secs)
*/
orig_trans_start = net_dev->trans_start;
net_dev->trans_start = jiffies;
netif_stop_queue(net_dev);
netif_tx_unlock_bh(net_dev);
spin_lock_irqsave(&bcm->irq_lock, flags); spin_lock_irqsave(&bcm->irq_lock, flags);
bcm43xx_mac_suspend(bcm); bcm43xx_mac_suspend(bcm);
if (bcm43xx_using_pio(bcm)) if (bcm43xx_using_pio(bcm))
...@@ -3198,6 +3211,7 @@ static void bcm43xx_periodic_work_handler(void *d) ...@@ -3198,6 +3211,7 @@ static void bcm43xx_periodic_work_handler(void *d)
bcm43xx_pio_thaw_txqueues(bcm); bcm43xx_pio_thaw_txqueues(bcm);
bcm43xx_mac_enable(bcm); bcm43xx_mac_enable(bcm);
netif_wake_queue(bcm->net_dev); netif_wake_queue(bcm->net_dev);
net_dev->trans_start = orig_trans_start;
} }
mmiowb(); mmiowb();
spin_unlock_irqrestore(&bcm->irq_lock, flags); spin_unlock_irqrestore(&bcm->irq_lock, flags);
......
...@@ -364,7 +364,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, ...@@ -364,7 +364,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
pos = 0; pos = 0;
while (pos < CIS_MAX_LEN - 1 && cis[pos] != CISTPL_END) { while (pos < CIS_MAX_LEN - 1 && cis[pos] != CISTPL_END) {
if (pos + cis[pos + 1] >= CIS_MAX_LEN) if (pos + 2 + cis[pos + 1] > CIS_MAX_LEN)
goto cis_error; goto cis_error;
switch (cis[pos]) { switch (cis[pos]) {
...@@ -391,7 +391,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, ...@@ -391,7 +391,7 @@ static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len,
break; break;
case CISTPL_MANFID: case CISTPL_MANFID:
if (cis[pos + 1] < 5) if (cis[pos + 1] < 4)
goto cis_error; goto cis_error;
manfid1 = cis[pos + 2] + (cis[pos + 3] << 8); manfid1 = cis[pos + 2] + (cis[pos + 3] << 8);
manfid2 = cis[pos + 4] + (cis[pos + 5] << 8); manfid2 = cis[pos + 4] + (cis[pos + 5] << 8);
......
...@@ -1078,7 +1078,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element ...@@ -1078,7 +1078,7 @@ static int ieee80211_parse_info_param(struct ieee80211_info_element
while (length >= sizeof(*info_element)) { while (length >= sizeof(*info_element)) {
if (sizeof(*info_element) + info_element->len > length) { if (sizeof(*info_element) + info_element->len > length) {
IEEE80211_ERROR("Info elem: parse failed: " IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
"info_element->len + 2 > left : " "info_element->len + 2 > left : "
"info_element->len+2=%zd left=%d, id=%d.\n", "info_element->len+2=%zd left=%d, id=%d.\n",
info_element->len + info_element->len +
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment