net: See to it that sent data is aligned to the ethernet controllers wishes
Subsystems (2)
PATCH 1/1 net: See to it that sent data is aligned to the ethernet controllers wishes
See to it that sent data is aligned to the ethernet controllers wishes
This patch adds a send_alignment member to the eth_device structure which specifies what the alignment requirements are for the particular device. eth_send checks this alignment on sends, and if it doesn't match the device requirement, allocates an aligned buffer and copies the data there.
Currently kirkwood_egiga.c has an 8-byte requirement. This patch is an alternative and replacement for "[PATCH] arm:kirkwood See to it that sent data is 8-byte aligned" sent here
http://lists.denx.de/pipermail/u-boot/2009-August/058829.html
For other devices, I've setup send_alignment to 1.
--- board/MAI/AmigaOneG3SE/enet.c | 1 + board/Marvell/db64360/mv_eth.c | 1 + board/Marvell/db64460/mv_eth.c | 1 + board/esd/cpci750/mv_eth.c | 1 + board/evb64260/eth.c | 1 + board/prodrive/p3mx/mv_eth.c | 1 + cpu/ixp/npe/npe.c | 1 + cpu/mips/au1x00_eth.c | 1 + cpu/mpc8260/ether_scc.c | 1 + drivers/net/4xx_enet.c | 1 + drivers/net/ax88180.c | 1 + drivers/net/bfin_mac.c | 1 + drivers/net/davinci_emac.c | 1 + drivers/net/dc2114x.c | 1 + drivers/net/dm9000x.c | 1 + drivers/net/dnet.c | 1 + drivers/net/e1000.c | 1 + drivers/net/eepro100.c | 1 + drivers/net/fec_mxc.c | 1 + drivers/net/fsl_mcdmafec.c | 1 + drivers/net/ftmac100.c | 1 + drivers/net/greth.c | 1 + drivers/net/inca-ip_sw.c | 1 + drivers/net/kirkwood_egiga.c | 1 + drivers/net/macb.c | 1 + drivers/net/mcffec.c | 1 + drivers/net/mpc5xxx_fec.c | 1 + drivers/net/natsemi.c | 1 + drivers/net/ns8382x.c | 1 + drivers/net/pcnet.c | 1 + drivers/net/plb2800_eth.c | 1 + drivers/net/rtl8139.c | 1 + drivers/net/rtl8169.c | 1 + drivers/net/sh_eth.c | 1 + drivers/net/sk98lin/uboot_drv.c | 1 + drivers/net/smc911x.c | 1 + drivers/net/tsec.c | 1 + drivers/net/tsi108_eth.c | 1 + drivers/net/uli526x.c | 1 + drivers/qe/uec.c | 1 + include/net.h | 1 + net/eth.c | 31 ++++++++++++++++++++++++++++++- 42 files changed, 71 insertions(+), 1 deletions(-)
board/MAI/AmigaOneG3SE/enet.c +1 -0
@@ -481,6 +481,7 @@ int eth_3com_initialize (bd_t * bis)sprintf (dev->name,"3Com 3c920c#%d" , card_number); dev->iobase = eth_iobase; + dev->send_alignment =1 ; dev->priv = (void *) devno; dev->init = eth_3com_init; dev->halt = eth_3com_halt;
board/Marvell/db64360/mv_eth.c +1 -0
@@ -262,6 +262,7 @@ void mv6436x_eth_initialize (bd_t * bis)/* ronen - set the MAC addr in the HW */ eth_port_uc_addr_set (devnum, dev->enetaddr,0 ); + dev->send_alignment =1 ; dev->init = (void *) db64360_eth_probe; dev->halt = (void *) ethernet_phy_reset; dev->send = (void *) db64360_eth_transmit;
board/Marvell/db64460/mv_eth.c +1 -0
@@ -262,6 +262,7 @@ void mv6446x_eth_initialize (bd_t * bis)/* ronen - set the MAC addr in the HW */ eth_port_uc_addr_set (devnum, dev->enetaddr,0 ); + dev->send_alignment =1 ; dev->init = (void *) db64460_eth_probe; dev->halt = (void *) ethernet_phy_reset; dev->send = (void *) db64460_eth_transmit;
board/esd/cpci750/mv_eth.c +1 -0
@@ -262,6 +262,7 @@ void mv6436x_eth_initialize (bd_t * bis)/* ronen - set the MAC addr in the HW */ eth_port_uc_addr_set (devnum, dev->enetaddr,0 ); + dev->send_alignment =1 ; dev->init = (void *) db64360_eth_probe; dev->halt = (void *) ethernet_phy_reset; dev->send = (void *) db64360_eth_transmit;
board/evb64260/eth.c +1 -0
@@ -720,6 +720,7 @@ gt6426x_eth_initialize(bd_t *bis) s = (*e) ? e+1 : e; } + dev->send_alignment =1 ; dev->init = (void *)gt6426x_eth_probe; dev->halt = (void *)gt6426x_eth_reset; dev->send = (void *)gt6426x_eth_transmit;
board/prodrive/p3mx/mv_eth.c +1 -0
@@ -312,6 +312,7 @@ void mv6446x_eth_initialize (bd_t * bis)/* ronen - set the MAC addr in the HW */ eth_port_uc_addr_set (devnum, dev->enetaddr,0 ); + dev->send_alignment =1 ; dev->init = (void *) db64460_eth_probe; dev->halt = (void *) ethernet_phy_reset; dev->send = (void *) db64460_eth_transmit;
cpu/ixp/npe/npe.c +1 -0
@@ -607,6 +607,7 @@ int npe_initialize(bd_t * bis) p_npe->phy_no =CONFIG_PHY_ADDR ;sprintf (dev->name,"NPE%d" , eth_num); + dev->send_alignment =1 ; dev->priv = (void *)p_npe; dev->init = npe_init; dev->halt = npe_halt;
cpu/mips/au1x00_eth.c +1 -0
@@ -294,6 +294,7 @@ int au1x00_enet_initialize(bd_t *bis){sprintf (dev->name,"Au1X00 ethernet" ); dev->iobase =0 ; + dev->send_alignment =1 ; dev->priv =0 ; dev->init = au1x00_init; dev->halt = au1x00_halt;
cpu/mpc8260/ether_scc.c +1 -0
@@ -376,6 +376,7 @@ int mpc82xx_scc_enet_initialize(bd_t *bis)memset (dev,0 ,sizeof *dev);sprintf (dev->name,"SCC ETHERNET" ); + dev->send_alignment =1 ; dev->init = sec_init; dev->halt = sec_halt; dev->send = sec_send;
drivers/net/4xx_enet.c +1 -0
@@ -2016,6 +2016,7 @@ int ppc_4xx_eth_initialize (bd_t * bis) hw->print_speed =1 ;sprintf (dev->name,"ppc_4xx_eth%d" , eth_num -CONFIG_EMAC_NR_START ); + dev->send_alignment =1 ; dev->priv = (void *) hw; dev->init = ppc_4xx_eth_init; dev->halt = ppc_4xx_eth_halt;
drivers/net/ax88180.c +1 -0
@@ -694,6 +694,7 @@ int ax88180_initialize (bd_t * bis)sprintf (dev->name,"ax88180" ); dev->iobase =AX88180_BASE ; + dev->send_alignment =1 ; dev->priv = priv; dev->init = ax88180_init; dev->halt = ax88180_halt;
drivers/net/bfin_mac.c +1 -0
@@ -101,6 +101,7 @@ int bfin_EMAC_initialize(bd_t *bis)sprintf (dev->name,"Blackfin EMAC" ); dev->iobase =0 ; + dev->send_alignment =1 ; dev->priv =0 ; dev->init = bfin_EMAC_init; dev->halt = bfin_EMAC_halt;
drivers/net/davinci_emac.c +1 -0
@@ -556,6 +556,7 @@ int davinci_emac_initialize(void)memset (dev,0 ,sizeof *dev); dev->iobase =0 ; + dev->send_alignment =1 ; dev->init = davinci_eth_open; dev->halt = davinci_eth_close; dev->send = davinci_eth_send_packet;
drivers/net/dc2114x.c +1 -0
@@ -291,6 +291,7 @@ int dc21x4x_initialize(bd_t *bis)#else dev->iobase =pci_mem_to_phys (devbusfn, iobase);#endif + dev->send_alignment =1 ; dev->priv = (void *) devbusfn; dev->init = dc21x4x_init; dev->halt = dc21x4x_halt;
drivers/net/dm9000x.c +1 -0
@@ -621,6 +621,7 @@ int dm9000_initialize(bd_t *bis) {struct eth_device *dev = &(dm9000_info.netdev); + dev->send_alignment =1 ; dev->init = dm9000_init; dev->halt = dm9000_halt; dev->send = dm9000_send;
drivers/net/dnet.c +1 -0
@@ -377,6 +377,7 @@ int dnet_eth_initialize(int id, void *regs, unsigned int phy_addr) dnet->phy_addr = phy_addr;sprintf (netdev->name,"dnet%d" , id); + netdev->send_alignment =1 ; netdev->init = dnet_init; netdev->halt = dnet_halt; netdev->send = dnet_send;
drivers/net/e1000.c +1 -0
@@ -5215,6 +5215,7 @@ e1000_initialize(bd_t * bis) nic->enetaddr[0 ], nic->enetaddr[1 ], nic->enetaddr[2 ], nic->enetaddr[3], nic->enetaddr[4], nic->enetaddr[5]); + nic->send_alignment =1 ; nic->init = e1000_init; nic->recv = e1000_poll; nic->send = e1000_transmit;
drivers/net/eepro100.c +1 -0
@@ -453,6 +453,7 @@ int eepro100_initialize (bd_t * bis)sprintf (dev->name,"i82559#%d" , card_number); dev->priv = (void *) devno;/* this have to come before bus_to_phys() */ dev->iobase =bus_to_phys (iobase); + dev->send_alignment =1 ; dev->init = eepro100_init; dev->halt = eepro100_halt; dev->send = eepro100_send;
drivers/net/fec_mxc.c +1 -0
@@ -665,6 +665,7 @@ static int fec_probe(bd_t *bd)return -ENOMEM ; } edev->priv = fec; + edev->send_alignment =1 ; edev->init = fec_init; edev->send = fec_send; edev->recv = fec_recv;
drivers/net/fsl_mcdmafec.c +1 -0
@@ -533,6 +533,7 @@ int mcdmafec_initialize(bd_t * bis)sprintf (dev->name,"FEC%d" , fec_info[i].index); + dev->send_alignment =1 ; dev->priv = &fec_info[i]; dev->init = fec_init; dev->halt = fec_halt;
drivers/net/ftmac100.c +1 -0
@@ -261,6 +261,7 @@ int ftmac100_initialize (bd_t *bd)sprintf (dev->name,"FTMAC100" ); dev->iobase =CONFIG_FTMAC100_BASE ; + dev->send_alignment =1 ; dev->init = ftmac100_init; dev->halt = ftmac100_halt; dev->send = ftmac100_send;
drivers/net/greth.c +1 -0
@@ -601,6 +601,7 @@ int greth_initialize(bd_t * bis)#endif dev->priv = (void *)greth; dev->iobase = (unsigned int )greth->regs; + dev->send_alignment =1 ; dev->init = greth_init; dev->halt = greth_halt; dev->send = greth_send;
drivers/net/inca-ip_sw.c +1 -0
@@ -189,6 +189,7 @@ int inca_switch_initialize(bd_t * bis)#endif sprintf (dev->name,"INCA-IP Switch" ); + dev->send_alignment =1 ; dev->init = inca_switch_init; dev->halt = inca_switch_halt; dev->send = inca_switch_send;
drivers/net/kirkwood_egiga.c +1 -0
@@ -660,6 +660,7 @@ int kirkwood_egiga_initialize(bd_t * bis)eth_setenv_enetaddr (s, dev->enetaddr); } + dev->send_alignment =8 ; dev->init = (void *)kwgbe_init; dev->halt = (void *)kwgbe_halt; dev->send = (void *)kwgbe_send;
drivers/net/macb.c +1 -0
@@ -519,6 +519,7 @@ int macb_eth_initialize(int id, void *regs, unsigned int phy_addr) macb->phy_addr = phy_addr;sprintf (netdev->name,"macb%d" , id); + netdev->send_alignment =1 ; netdev->init = macb_init; netdev->halt = macb_halt; netdev->send = macb_send;
drivers/net/mcffec.c +1 -0
@@ -572,6 +572,7 @@ int mcffec_initialize(bd_t * bis)sprintf (dev->name,"FEC%d" , fec_info[i].index); + dev->send_alignment =1 ; dev->priv = &fec_info[i]; dev->init = fec_init; dev->halt = fec_halt;
drivers/net/mpc5xxx_fec.c +1 -0
@@ -918,6 +918,7 @@ int mpc5xxx_fec_initialize(bd_t * bis) dev->priv = (void *)fec; dev->iobase =MPC5XXX_FEC ; + dev->send_alignment =1 ; dev->init = mpc5xxx_fec_init; dev->halt = mpc5xxx_fec_halt; dev->send = mpc5xxx_fec_send;
drivers/net/natsemi.c +1 -0
@@ -327,6 +327,7 @@ natsemi_initialize(bd_t * bis)#ifdef NATSEMI_DEBUG printf ("natsemi: NatSemi ns8381[56] @ %#x\n" , dev->iobase);#endif + dev->send_alignment =1 ; dev->priv = (void *) devno; dev->init = natsemi_init; dev->halt = natsemi_disable;
drivers/net/ns8382x.c +1 -0
@@ -343,6 +343,7 @@ ns8382x_initialize(bd_t * bis)sprintf (dev->name,"dp8382x#%d" , card_number); dev->iobase =bus_to_phys (iobase); + dev->send_alignment =1 ; dev->priv = (void *) devno; dev->init = ns8382x_init; dev->halt = ns8382x_disable;
drivers/net/pcnet.c +1 -0
@@ -223,6 +223,7 @@ int pcnet_initialize (bd_t * bis)/* * Setup device structure and register the driver. */ + dev->send_alignment =1 ; dev->init = pcnet_init; dev->halt = pcnet_halt; dev->send = pcnet_send;
drivers/net/plb2800_eth.c +1 -0
@@ -111,6 +111,7 @@ int plb2800_eth_initialize(bd_t * bis)memset (dev,0 ,sizeof (*dev));sprintf (dev->name,"PLB2800 Switch" ); + dev->send_alignment =1 ; dev->init = plb2800_eth_init; dev->halt = plb2800_eth_halt; dev->send = plb2800_eth_send;
drivers/net/rtl8139.c +1 -0
@@ -225,6 +225,7 @@ int rtl8139_initialize(bd_t *bis) dev->priv = (void *) devno; dev->iobase = (int )bus_to_phys (iobase); + dev->send_alignment =1 ; dev->init = rtl8139_probe; dev->halt = rtl_disable; dev->send = rtl_transmit;
drivers/net/rtl8169.c +1 -0
@@ -899,6 +899,7 @@ int rtl8169_initialize(bd_t *bis) dev->priv = (void *) devno; dev->iobase = (int )pci_mem_to_phys (devno, iobase); + dev->send_alignment =1 ; dev->init = rtl_reset; dev->halt = rtl_halt;
drivers/net/sh_eth.c +1 -0
@@ -652,6 +652,7 @@ int sh_eth_initialize(bd_t *bd) dev->priv = (void *)eth; dev->iobase =0 ; + dev->send_alignment =1 ; dev->init = sh_eth_init; dev->halt = sh_eth_halt; dev->send = sh_eth_send;
drivers/net/sk98lin/uboot_drv.c +1 -0
@@ -63,6 +63,7 @@ int skge_initialize(bd_t * bis) {sprintf (dev[i]->name,"SK98#%d" , i); + dev[i]->send_alignment =1 ; dev[i]->init = skge_init; dev[i]->halt = skge_halt; dev[i]->send = skge_send;
drivers/net/smc911x.c +1 -0
@@ -262,6 +262,7 @@ int smc911x_initialize(u8 dev_num, int base_addr) dev->enetaddr[4 ] = addrh; dev->enetaddr[5 ] = addrh >>8 ; + dev->send_alignment =1 ; dev->init = smc911x_init; dev->halt = smc911x_halt; dev->send = smc911x_send;
drivers/net/tsec.c +1 -0
@@ -141,6 +141,7 @@ int tsec_initialize(bd_t * bis, struct tsec_info_struct *tsec_info)sprintf (dev->name, tsec_info->devname); dev->iobase =0 ; + dev->send_alignment =1 ; dev->priv = priv; dev->init = tsec_init; dev->halt = tsec_halt;
drivers/net/tsi108_eth.c +1 -0
@@ -735,6 +735,7 @@ int tsi108_eth_initialize (bd_t * bis)sprintf (dev->name,"TSI108_eth%d" , index); dev->iobase =ETH_BASE + (index *ETH_PORT_OFFSET ); + dev->send_alignment =1 ; dev->priv = (void *)(phy_address[index]); dev->init = tsi108_eth_probe; dev->halt = tsi108_eth_halt;
drivers/net/uli526x.c +1 -0
@@ -232,6 +232,7 @@ int uli526x_initialize(bd_t *bis) dev->priv = db; db->pdev = devno; dev->iobase = iobase; + dev->send_alignment =1 ; dev->init = uli526x_init_one; dev->halt = uli526x_disable;
drivers/qe/uec.c +1 -0
@@ -1354,6 +1354,7 @@ int uec_initialize(bd_t *bis, uec_info_t *uec_info)sprintf (dev->name,"FSL UEC%d" , uec_info->uf_info.ucc_num); dev->iobase =0 ; + dev->send_alignment =1 ; dev->priv = (void *)uec; dev->init = uec_init; dev->halt = uec_halt;
include/net.h +1 -0
@@ -97,6 +97,7 @@ struct eth_device {unsigned char enetaddr[6 ];int iobase;int state; +int send_alignment;/* Power of two send buffer alignment requirement */ int (*init) (struct eth_device *,bd_t *);int (*send) (struct eth_device *,volatile void * packet,int length);
net/eth.c +30 -1
@@ -362,10 +362,39 @@ void eth_halt(void)int eth_send (volatile void *packet,int length) { +void *p = (void *)packet; +if (!eth_current)return -1 ; -return eth_current->send (eth_current, packet, length); +/* Copy buffer if it's misaligned */ +if ((u32 ) packet & (eth_current->send_alignment -1 )) { +static void *aligned_buf; + +/* eth_current might have changed, so possibly reallocate the buf +* if it doesn't match the requirements for eth_current */ +if (aligned_buf && + ((u32 )aligned_buf & (eth_current->send_alignment -1 ))) { +free (aligned_buf); + aligned_buf =NULL ; + } + +if (!aligned_buf) + aligned_buf =memalign (eth_current->send_alignment, +PKTSIZE_ALIGN ); +if (!aligned_buf) { +printf ("eth_send: Cannot allocate aligned buffer\n" ); +return -1 ; + } +if (length >PKTSIZE_ALIGN ) { +printf ("eth_send: Non-aligned data too large (%d)\n" , length); +return -1 ; + } +memcpy (aligned_buf, p, length); + p = aligned_buf; + } + +return eth_current->send (eth_current, p, length); }int eth_rx (void )
Signature · 1 line
1.6.0.4
PATCH 1/1 net: See to it that sent data is aligned to the ethernet controllers wishes
Quoted 11 lines
See to it that sent data is aligned to the ethernet controllers wishes
This patch adds a
send_alignmentmember to theeth_devicestructure which specifies what the alignment requirements are for the particular device.eth_sendchecks this alignment on sends, and if it doesn't match
the device requirement, allocates an aligned buffer and copies the data
there.
Quoted 7 lines
Currently
kirkwood_egiga.chas an 8-byte requirement. This patch is an alternative and replacement for "[PATCH] arm:kirkwood See to it that sent data is 8-byte aligned" sent herehttp://lists.denx.de/pipermail/u-boot/2009-August/058829.html
For other devices, I've setup
send_alignmentto 1.
Basically NACK for it.
Why you don't resolve the alignment issue in your driver?
Thanks, Dave
PATCH 1/1 net: See to it that sent data is aligned to the ethernet controllers wishes
Quoted 10 lines · On Wed, 19 Aug 2009 15:36:04 +0800 "Liu Dave-R63238" <[email protected]>…
Quoted 7 lines
Currently
kirkwood_egiga.chas an 8-byte requirement. This patch is an alternative and replacement for "[PATCH] arm:kirkwood See to it that sent data is 8-byte aligned" sent herehttp://lists.denx.de/pipermail/u-boot/2009-August/058829.html
For other devices, I've setup
send_alignmentto 1.Basically NACK for it.
Why you don't resolve the alignment issue in your driver?
Well, that's what the other patch I sent does (the link above), but there were wishes then to handle this above the driver layer, hence this patch :-)
I'm fine with either way, but if there are other drivers with alignment requirements, I'd prefer this variant.
// Simon
PATCH 1/1 net: See to it that sent data is aligned to the ethernet controllers wishes
Quoted 6 lines
Well, that's what the other patch I sent does (the link above), but there were wishes then to handle this above the driver layer, hence this patch :-)
I'm fine with either way, but if there are other drivers with alignment requirements, I'd prefer this variant.
I believe some Freescale's CPM/QE controllers need care the alignement requirement.
If you don't care the performance, you can malloc memory to get the aligned buffer pool in the initiaize phase,
then use the buffer pool to resolve your alignment issue, of course It needs a copy, but it avoids to malloc/free buffer in run-time.
Thanks, Dave
PATCH 1/1 net: See to it that sent data is aligned to the ethernet controllers wishes
Quoted 7 lines · On Wed, 19 Aug 2009 16:06:12 +0800 "Liu Dave-R63238" <[email protected]>…
Quoted 6 lines
Well, that's what the other patch I sent does (the link above), but there were wishes then to handle this above the driver layer, hence this patch :-)
I'm fine with either way, but if there are other drivers with alignment requirements, I'd prefer this variant.
Quoted 7 lines
I believe some Freescale's CPM/QE controllers need care the alignement requirement.
If you don't care the performance, you can malloc memory to get the aligned buffer pool in the initiaize phase,
then use the buffer pool to resolve your alignment issue, of course It needs a copy, but it avoids to malloc/free buffer in run-time.
The malloc is only done once - the first time a non-aligned send is done. After that it's just reused until the alignment requirement exceeds the current allocation (if another interface is set as current).
So I think the performance impact is very small.
// Simon
PATCH 1/1 net: See to it that sent data is aligned to the ethernet controllers wishes
Quoted 25 lines · Simon Kagstrom
Quoted 7 lines · On Wed, 19 Aug 2009 16:06:12 +0800 "Liu Dave-R63238" <[email protected]>…
Quoted 7 lines
Well, that's what the other patch I sent does (the link above), but there were wishes then to handle this above the driver layer, hence this patch :-)
I'm fine with either way, but if there are other drivers with alignment requirements, I'd prefer this variant.
Quoted 8 lines
I believe some Freescale's CPM/QE controllers need care the alignement requirement.
If you don't care the performance, you can malloc memory to get the aligned buffer pool in the initiaize phase,
then use the buffer pool to resolve your alignment issue, of course It needs a copy, but it avoids to malloc/free buffer in run-time.The malloc is only done once - the first time a non-aligned send is done. After that it's just reused until the alignment requirement exceeds the current allocation (if another interface is set as current).
Quoted 8 lines
So I think the performance impact is very small.
// Simon
_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
My preference is for the drivers to handle alignment. I like Dave's idea of creating a buffer (or multiple buffers) in initialization(), then memcpy'ing to to it in the send() routine. You could make it smart to only memcpy if the frame is not aligned as needed.
Your original patch created a buffer of size 9000, which I commented was probably bigger than necessary. I didn't see a response to that (which doesn't mean you didn't send one, but I get a lot of e-mail :)
regards,
Ben
PATCH 1/1 net: See to it that sent data is aligned to the ethernet controllers wishes
Quoted 1 line · On Wed, 19 Aug 2009 09:55:46 -0700 Ben Warren <[email protected]> wrote:
My preference is for the drivers to handle alignment.
OK, I'm fine with that. I'd like to withdraw this patch then.
Quoted 3 lines
I like Dave's idea of creating a buffer (or multiple buffers) in
initialization(), then memcpy'ing to to it in thesend()routine. You could make it smart to only memcpy if the frame is not aligned as needed.
It already only memcpys unaligned buffers, but I'll go with Daves suggestion and allocate it at startup instead.
Quoted 3 lines
Your original patch created a buffer of size 9000, which I commented was probably bigger than necessary. I didn't see a response to that (which doesn't mean you didn't send one, but I get a lot of e-mail :)
I was off for vacation [*], so I only sent it this week. I'll rework this patch a bit to address a small bug I found.
Thanks for the comments!
// Simon
[*] By now the U-boot list is probably tired of hearing about my
vacation, but I can assure you that I had a good time!