Merge branch 'for-next/misc'
Conflicts: common/environment.c
This commit is contained in:
commit
a8a08f88cc
|
@ -54,6 +54,7 @@ SECTIONS
|
|||
/DISCARD/ : { *(.ARM.ex*) }
|
||||
|
||||
BAREBOX_BARE_INIT_SIZE
|
||||
BAREBOX_PBL_SIZE
|
||||
|
||||
. = ALIGN(4);
|
||||
.rodata : { *(.rodata*) }
|
||||
|
|
|
@ -124,9 +124,6 @@ static __init int clps711x_syscon_init(void)
|
|||
/* SYSCON2, SYSFLG2 */
|
||||
add_generic_device("syscon", 2, NULL, SYSCON2, SZ_128,
|
||||
IORESOURCE_MEM, NULL);
|
||||
/* SYSCON3 */
|
||||
add_generic_device("syscon", 3, NULL, SYSCON3, SZ_64,
|
||||
IORESOURCE_MEM, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3151,7 +3151,6 @@ static uint32_t rw_mgr_mem_calibrate_wlevel (uint32_t g, uint32_t test_bgn)
|
|||
tmp_delay += IO_DELAY_PER_DCHAIN_TAP;
|
||||
}
|
||||
dtaps_per_ptap--;
|
||||
tmp_delay = 0;
|
||||
#endif
|
||||
|
||||
/* starting phases */
|
||||
|
|
|
@ -57,6 +57,12 @@ config CMD_READLINE
|
|||
tristate
|
||||
prompt "readline"
|
||||
|
||||
config CMD_READF
|
||||
tristate
|
||||
prompt "readf"
|
||||
help
|
||||
The readf command is used to read a files content into a shell variable.
|
||||
|
||||
config CMD_LET
|
||||
tristate
|
||||
prompt "let"
|
||||
|
|
|
@ -93,3 +93,4 @@ obj-$(CONFIG_CMD_MIITOOL) += miitool.o
|
|||
obj-$(CONFIG_CMD_DETECT) += detect.o
|
||||
obj-$(CONFIG_CMD_BOOT) += boot.o
|
||||
obj-$(CONFIG_CMD_DEVINFO) += devinfo.o
|
||||
obj-$(CONFIG_CMD_READF) += readf.o
|
||||
|
|
|
@ -308,7 +308,7 @@ static int boot(const char *name)
|
|||
{
|
||||
struct blspec *blspec;
|
||||
struct blspec_entry *entry;
|
||||
int ret = -ENOENT;
|
||||
int ret;
|
||||
|
||||
blspec = blspec_alloc();
|
||||
ret = bootentry_parse_one(blspec, name);
|
||||
|
|
|
@ -128,9 +128,14 @@ static int do_dfu(int argc, char *argv[])
|
|||
|
||||
argstr = argv[optind];
|
||||
|
||||
if (!idProduct || !idVendor) {
|
||||
printf("productid or vendorid not given\n");
|
||||
return 1;
|
||||
if (!idProduct && !idVendor) {
|
||||
idVendor = 0x1d50; /* Openmoko, Inc */
|
||||
idProduct = 0x60a2; /* barebox bootloader USB DFU Mode */
|
||||
}
|
||||
|
||||
if ((idProduct && !idVendor) || (!idProduct && idVendor)) {
|
||||
printf("Only one of vendor id or product id given\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (n = 0; *argstr; n++) {
|
||||
|
|
|
@ -266,7 +266,7 @@ static int save_file(const char *path)
|
|||
fd = open(path, O_WRONLY | O_TRUNC | O_CREAT);
|
||||
if (fd < 0) {
|
||||
printf("could not open file for writing: %s\n", errno_str());
|
||||
return -1;
|
||||
return fd;
|
||||
}
|
||||
|
||||
line = buffer;
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
#include <common.h>
|
||||
#include <command.h>
|
||||
#include <fs.h>
|
||||
#include <malloc.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <environment.h>
|
||||
|
||||
static int do_readf(int argc, char *argv[])
|
||||
{
|
||||
unsigned char *buf = NULL, *val;
|
||||
char *variable, *filename;
|
||||
struct stat s;
|
||||
size_t size;
|
||||
int ret, i;
|
||||
|
||||
if (argc != 3)
|
||||
return COMMAND_ERROR_USAGE;
|
||||
|
||||
filename = argv[1];
|
||||
variable = argv[2];
|
||||
|
||||
ret = stat(filename, &s);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (s.st_size > 1024) {
|
||||
ret = -EFBIG;
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf = read_file(filename, &size);
|
||||
if (!buf)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (!isprint(buf[i])) {
|
||||
buf[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
val = strim(buf);
|
||||
|
||||
ret = setenv(variable, val);
|
||||
out:
|
||||
free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BAREBOX_CMD_HELP_START(readf)
|
||||
BAREBOX_CMD_HELP_USAGE("readf <file> <variable>\n")
|
||||
BAREBOX_CMD_HELP_SHORT("Read a single line of a file into a shell variable. Leading and trailing whitespaces\n")
|
||||
BAREBOX_CMD_HELP_SHORT("are removed, nonvisible characters are stripped. Input is limited to 1024\n")
|
||||
BAREBOX_CMD_HELP_SHORT("characters.\n")
|
||||
BAREBOX_CMD_HELP_END
|
||||
|
||||
BAREBOX_CMD_START(readf)
|
||||
.cmd = do_readf,
|
||||
.usage = "read file into variable",
|
||||
BAREBOX_CMD_HELP(cmd_readf_help)
|
||||
BAREBOX_CMD_END
|
|
@ -145,13 +145,24 @@ config BAREBOX_MAX_IMAGE_SIZE
|
|||
help
|
||||
Define the maximum size of barebox
|
||||
|
||||
config BAREBOX_MAX_BARE_INIT_SIZE
|
||||
prompt "Maximum bare_init size"
|
||||
config BAREBOX_MAX_PBL_SIZE
|
||||
depends on PBL_IMAGE
|
||||
prompt "Maximum pre-bootloader size"
|
||||
hex
|
||||
default 0xffffffff
|
||||
help
|
||||
On some hardware the ROM code can load the pbl into SRAM, but not
|
||||
the whole image. This option specifies how big the pbl may get.
|
||||
|
||||
config BAREBOX_MAX_BARE_INIT_SIZE
|
||||
prompt "Maximum bare_init size"
|
||||
hex
|
||||
range 0x0 BAREBOX_MAX_PBL_SIZE if LOAD_PBL_SRAM
|
||||
default BAREBOX_MAX_PBL_SIZE if LOAD_PBL_SRAM
|
||||
default 0xffffffff
|
||||
help
|
||||
Define the maximum size of bare_init
|
||||
this will allow your bare_init will fit in SRAM as example
|
||||
this will allow your bare_init to fit in SRAM as example
|
||||
ARCH can overwrite it via ARCH_BAREBOX_MAX_BARE_INIT_SIZE
|
||||
|
||||
config HAVE_CONFIGURABLE_MEMORY_LAYOUT
|
||||
|
|
|
@ -167,10 +167,10 @@ static unsigned long get_symbol_pos(unsigned long addr,
|
|||
* It resides in a module.
|
||||
* - We also guarantee that modname will be valid until rescheduled.
|
||||
*/
|
||||
const char *kallsyms_lookup(unsigned long addr,
|
||||
unsigned long *symbolsize,
|
||||
unsigned long *offset,
|
||||
char **modname, char *namebuf)
|
||||
static const char *kallsyms_lookup(unsigned long addr,
|
||||
unsigned long *symbolsize,
|
||||
unsigned long *offset,
|
||||
char **modname, char *namebuf)
|
||||
{
|
||||
namebuf[KSYM_NAME_LEN - 1] = 0;
|
||||
namebuf[0] = 0;
|
||||
|
|
|
@ -78,7 +78,7 @@ static unsigned long clk_divider_recalc_rate(struct clk *clk,
|
|||
return parent_rate / div->table[val].div;
|
||||
}
|
||||
|
||||
struct clk_ops clk_divider_table_ops = {
|
||||
static struct clk_ops clk_divider_table_ops = {
|
||||
.set_rate = clk_divider_set_rate,
|
||||
.recalc_rate = clk_divider_recalc_rate,
|
||||
};
|
||||
|
|
|
@ -35,7 +35,7 @@ static unsigned long clk_fixed_factor_recalc_rate(struct clk *clk,
|
|||
return (parent_rate / f->div) * f->mult;
|
||||
}
|
||||
|
||||
struct clk_ops clk_fixed_factor_ops = {
|
||||
static struct clk_ops clk_fixed_factor_ops = {
|
||||
.recalc_rate = clk_fixed_factor_recalc_rate,
|
||||
};
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ static unsigned long clk_fixed_recalc_rate(struct clk *clk,
|
|||
return fix->rate;
|
||||
}
|
||||
|
||||
struct clk_ops clk_fixed_ops = {
|
||||
static struct clk_ops clk_fixed_ops = {
|
||||
.recalc_rate = clk_fixed_recalc_rate,
|
||||
.is_enabled = clk_is_enabled_always,
|
||||
};
|
||||
|
|
|
@ -76,7 +76,7 @@ static int clk_gate_is_enabled(struct clk *clk)
|
|||
return g->flags & CLK_GATE_INVERTED ? 1 : 0;
|
||||
}
|
||||
|
||||
struct clk_ops clk_gate_ops = {
|
||||
static struct clk_ops clk_gate_ops = {
|
||||
.enable = clk_gate_enable,
|
||||
.disable = clk_gate_disable,
|
||||
.is_enabled = clk_gate_is_enabled,
|
||||
|
|
|
@ -50,7 +50,7 @@ static int clk_mux_set_parent(struct clk *clk, u8 idx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct clk_ops clk_mux_ops = {
|
||||
static struct clk_ops clk_mux_ops = {
|
||||
.get_parent = clk_mux_get_parent,
|
||||
.set_parent = clk_mux_set_parent,
|
||||
};
|
||||
|
|
|
@ -179,9 +179,11 @@ struct clk *clk_get(struct device_d *dev, const char *con_id)
|
|||
if (!IS_ERR(clk))
|
||||
return clk;
|
||||
|
||||
clk = of_clk_get_by_name(dev->device_node, con_id);
|
||||
if (!IS_ERR(clk))
|
||||
return clk;
|
||||
if (dev) {
|
||||
clk = of_clk_get_by_name(dev->device_node, con_id);
|
||||
if (!IS_ERR(clk))
|
||||
return clk;
|
||||
}
|
||||
|
||||
return clk_get_sys(dev_id, con_id);
|
||||
}
|
||||
|
|
|
@ -294,8 +294,7 @@ static int at25_probe(struct device_d *dev)
|
|||
return 0;
|
||||
|
||||
fail:
|
||||
if (at25)
|
||||
free(at25);
|
||||
free(at25);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -243,8 +243,8 @@ EXPORT_SYMBOL(i2c_write_reg);
|
|||
*
|
||||
* Returns the new device, or NULL.
|
||||
*/
|
||||
struct i2c_client *i2c_new_device(struct i2c_adapter *adapter,
|
||||
struct i2c_board_info *chip)
|
||||
static struct i2c_client *i2c_new_device(struct i2c_adapter *adapter,
|
||||
struct i2c_board_info *chip)
|
||||
{
|
||||
struct i2c_client *client;
|
||||
int status;
|
||||
|
@ -269,9 +269,8 @@ struct i2c_client *i2c_new_device(struct i2c_adapter *adapter,
|
|||
|
||||
return client;
|
||||
}
|
||||
EXPORT_SYMBOL(i2c_new_device);
|
||||
|
||||
void of_i2c_register_devices(struct i2c_adapter *adap)
|
||||
static void of_i2c_register_devices(struct i2c_adapter *adap)
|
||||
{
|
||||
struct device_node *n;
|
||||
|
||||
|
|
|
@ -404,7 +404,8 @@ int add_mtd_device(struct mtd_info *mtd, char *devname, int device_id)
|
|||
}
|
||||
|
||||
devfs_create(&mtd->cdev);
|
||||
of_parse_partitions(&mtd->cdev, mtd->parent->device_node);
|
||||
if (mtd->parent)
|
||||
of_parse_partitions(&mtd->cdev, mtd->parent->device_node);
|
||||
|
||||
list_for_each_entry(hook, &mtd_register_hooks, hook)
|
||||
if (hook->add_mtd_device)
|
||||
|
|
|
@ -518,7 +518,7 @@ static int imx_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat,
|
|||
struct nand_chip *nand_chip = mtd->priv;
|
||||
struct imx_nand_host *host = nand_chip->priv;
|
||||
u32 ecc_stat, err;
|
||||
int no_subpages = 1;
|
||||
int no_subpages;
|
||||
int ret = 0;
|
||||
u8 ecc_bit_mask, err_limit;
|
||||
|
||||
|
|
|
@ -382,7 +382,7 @@ static int asix_get_ethaddr(struct eth_device *edev, unsigned char *adr)
|
|||
|
||||
if (ret < 0) {
|
||||
debug("Failed to read MAC address: %d\n", ret);
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -403,7 +403,7 @@ static int ax88172_get_ethaddr(struct eth_device *edev, unsigned char *adr)
|
|||
if ((ret = asix_read_cmd(udev, AX88172_CMD_READ_NODE_ID,
|
||||
0, 0, 6, adr)) < 0) {
|
||||
debug("read AX_CMD_READ_NODE_ID failed: %d\n", ret);
|
||||
return -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -447,7 +447,7 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
|
|||
udelay(10 * 1000);
|
||||
bmcr = smsc95xx_mdio_read(&dev->miibus, phy_id, MII_BMCR);
|
||||
timeout++;
|
||||
} while ((bmcr & MII_BMCR) && (timeout < 100));
|
||||
} while ((bmcr & BMCR_RESET) && (timeout < 100));
|
||||
|
||||
if (timeout >= 100) {
|
||||
netdev_warn(dev->net, "timeout on PHY Reset");
|
||||
|
|
|
@ -67,9 +67,9 @@ struct alias_prop {
|
|||
|
||||
static LIST_HEAD(aliases_lookup);
|
||||
|
||||
struct device_node *root_node;
|
||||
static struct device_node *root_node;
|
||||
|
||||
struct device_node *of_aliases;
|
||||
static struct device_node *of_aliases;
|
||||
|
||||
#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1
|
||||
#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 1
|
||||
|
@ -1721,8 +1721,8 @@ int of_add_memory(struct device_node *node, bool dump)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct device_node *of_chosen;
|
||||
const char *of_model;
|
||||
static struct device_node *of_chosen;
|
||||
static const char *of_model;
|
||||
|
||||
const char *of_get_model(void)
|
||||
{
|
||||
|
|
|
@ -112,7 +112,7 @@ static void altera_spi_cs_inactive(struct spi_device *spi)
|
|||
static unsigned altera_spi_do_xfer(struct spi_device *spi, struct spi_transfer *t)
|
||||
{
|
||||
struct altera_spi *altera_spi = container_of(spi->master, struct altera_spi, master);
|
||||
int word_len = spi->bits_per_word;
|
||||
int word_len;
|
||||
unsigned retval = 0;
|
||||
u32 txval;
|
||||
u32 rxval;
|
||||
|
|
|
@ -504,8 +504,7 @@ int usb_host_detect(struct usb_host *host, int force)
|
|||
|
||||
list_del(&dev->list);
|
||||
unregister_device(&dev->dev);
|
||||
if (dev->hub)
|
||||
free(dev->hub);
|
||||
free(dev->hub);
|
||||
dma_free(dev->setup_packet);
|
||||
dma_free(dev->descriptor);
|
||||
free(dev);
|
||||
|
|
|
@ -204,7 +204,7 @@ int __init usb_interface_id(struct usb_configuration *config,
|
|||
static int config_buf(struct usb_configuration *config,
|
||||
enum usb_device_speed speed, void *buf, u8 type)
|
||||
{
|
||||
struct usb_config_descriptor *c = buf;
|
||||
struct usb_config_descriptor *c;
|
||||
void *next = buf + USB_DT_CONFIG_SIZE;
|
||||
int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE;
|
||||
struct usb_function *f;
|
||||
|
|
|
@ -607,8 +607,10 @@ static int dfu_bind_config(struct usb_configuration *c)
|
|||
func->disable = dfu_disable;
|
||||
|
||||
dfu->dnreq = usb_ep_alloc_request(c->cdev->gadget->ep0);
|
||||
if (!dfu->dnreq)
|
||||
if (!dfu->dnreq) {
|
||||
printf("usb_ep_alloc_request failed\n");
|
||||
goto out;
|
||||
}
|
||||
dfu->dnreq->buf = dma_alloc(CONFIG_USBD_DFU_XFER_SIZE);
|
||||
dfu->dnreq->complete = dn_complete;
|
||||
dfu->dnreq->zero = 0;
|
||||
|
|
|
@ -51,7 +51,7 @@ int ulpi_read(int reg, void __iomem *view)
|
|||
int ret;
|
||||
|
||||
/* make sure interface is running */
|
||||
if (!(readl(view) && ULPIVW_SS)) {
|
||||
if (!(readl(view) & ULPIVW_SS)) {
|
||||
writel(ULPIVW_WU, view);
|
||||
|
||||
/* wait for wakeup */
|
||||
|
@ -73,7 +73,7 @@ int ulpi_set(u8 bits, int reg, void __iomem *view)
|
|||
int ret;
|
||||
|
||||
/* make sure the interface is running */
|
||||
if (!(readl(view) && ULPIVW_SS)) {
|
||||
if (!(readl(view) & ULPIVW_SS)) {
|
||||
writel(ULPIVW_WU, view);
|
||||
/* wait for wakeup */
|
||||
ret = ulpi_poll(view, ULPIVW_WU);
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include <fs.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fs.h>
|
||||
#include <malloc.h>
|
||||
#include <init.h>
|
||||
#include <linux/stat.h>
|
||||
|
@ -438,7 +437,7 @@ static int bpkfs_probe(struct device_d *dev)
|
|||
|
||||
dev_dbg(dev, "%d: type = 0x%x => %s\n", i, d->type, d->name);
|
||||
dev_dbg(dev, "%d: size = %llu\n", i, d->size);
|
||||
dev_dbg(dev, "%d: offset = %d\n", i, d->offset);
|
||||
dev_dbg(dev, "%d: offset = %zu\n", i, d->offset);
|
||||
|
||||
dev_dbg(dev, "%d: hw_id = 0x%x => %s\n", i, h->hw_id, h->name);
|
||||
|
||||
|
|
|
@ -60,6 +60,13 @@ CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE < CONFIG_BAREBOX_MAX_BARE_INIT_SIZE
|
|||
#define MAX_BARE_INIT_SIZE CONFIG_BAREBOX_MAX_BARE_INIT_SIZE
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ARCH_BAREBOX_MAX_PBL_SIZE) && \
|
||||
CONFIG_ARCH_BAREBOX_MAX_PBL_SIZE < CONFIG_BAREBOX_MAX_PBL_SIZE
|
||||
#define MAX_PBL_SIZE CONFIG_ARCH_BAREBOX_MAX_PBL_SIZE
|
||||
#else
|
||||
#define MAX_PBL_SIZE CONFIG_BAREBOX_MAX_PBL_SIZE
|
||||
#endif
|
||||
|
||||
#include <linux/stringify.h>
|
||||
/* use 2 ASSERT because ld can not accept '"size" "10"' format */
|
||||
#define BAREBOX_BARE_INIT_SIZE \
|
||||
|
@ -67,3 +74,9 @@ CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE < CONFIG_BAREBOX_MAX_BARE_INIT_SIZE
|
|||
ASSERT(_barebox_bare_init_size < MAX_BARE_INIT_SIZE, "Barebox bare_init size > ") \
|
||||
ASSERT(_barebox_bare_init_size < MAX_BARE_INIT_SIZE, __stringify(MAX_BARE_INIT_SIZE)) \
|
||||
|
||||
#define BAREBOX_PBL_SIZE \
|
||||
_barebox_pbl_size = __bss_start - _text; \
|
||||
ASSERT(MAX_BARE_INIT_SIZE <= MAX_PBL_SIZE, "bare_init cannot be bigger than pbl") \
|
||||
ASSERT(_barebox_pbl_size < MAX_PBL_SIZE, "Barebox pbl size > ") \
|
||||
ASSERT(_barebox_pbl_size < MAX_PBL_SIZE, __stringify(MAX_PBL_SIZE)) \
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ EXPORT_SYMBOL(concat_path_file);
|
|||
|
||||
char *concat_subpath_file(const char *path, const char *f)
|
||||
{
|
||||
if (f && DOT_OR_DOTDOT(f))
|
||||
if (DOT_OR_DOTDOT(f))
|
||||
return NULL;
|
||||
return concat_path_file(path, f);
|
||||
}
|
||||
|
|
|
@ -306,7 +306,7 @@ static const char *arith_lookup_val(arith_state_t *math_state, var_or_num_t *t)
|
|||
/* treat undefined var as 0 */
|
||||
t->val = 0;
|
||||
}
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* "Applying" a token means performing it on the top elements on the integer
|
||||
|
@ -546,8 +546,8 @@ static arith_t evaluate_string(arith_state_t *math_state, const char *expr)
|
|||
arith_t result;
|
||||
|
||||
if (numstack == NULL || stack == NULL) {
|
||||
errmsg = "out of memory";
|
||||
goto err_with_custom_msg;
|
||||
math_state->errmsg = "out of memory";
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Start with a left paren */
|
||||
|
|
|
@ -108,8 +108,7 @@ int dev_set_param(struct device_d *dev, const char *name, const char *val)
|
|||
int dev_param_set_generic(struct device_d *dev, struct param_d *p,
|
||||
const char *val)
|
||||
{
|
||||
if (p->value)
|
||||
free(p->value);
|
||||
free(p->value);
|
||||
if (!val) {
|
||||
p->value = NULL;
|
||||
return 0;
|
||||
|
|
|
@ -382,7 +382,7 @@ void eth_unregister(struct eth_device *edev)
|
|||
|
||||
dev_remove_parameters(&edev->dev);
|
||||
|
||||
if (IS_ENABLED(CONFIG_OFDEVICE) && edev->nodepath)
|
||||
if (IS_ENABLED(CONFIG_OFDEVICE))
|
||||
free(edev->nodepath);
|
||||
|
||||
unregister_device(&edev->dev);
|
||||
|
|
|
@ -552,7 +552,6 @@ kwboot_mmap_image(const char *path, size_t *size, int prot)
|
|||
void *img;
|
||||
|
||||
rc = -1;
|
||||
fd = -1;
|
||||
img = NULL;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
|
|
Loading…
Reference in New Issue