Re: fix nvme(4): NULL deref. and empty device attachments

2021-02-24 Thread Patrick Wildt
Am Wed, Feb 24, 2021 at 05:34:48PM +0100 schrieb Jan Klemkow:
> Hi,
> 
> While attaching the following disks, the nvme driver runs into a NULL
> dereference in nvme_scsi_capacity16() and nvme_scsi_capacity().
> 
> nvme0 at pci1 dev 0 function 0 vendor "Intel", unknown product 0x0a54 rev 
> 0x00: msix, NVMe 1.2
> nvme0: INTEL SSDPE2KX040T8, firmware VDV10170, serial PHLJ0413002P4P0DGN
> scsibus1 at nvme0: 129 targets, initiator 0
> sd0 at scsibus1 targ 1 lun 0: 
> sd0: 3815447MB, 512 bytes/sector, 7814037168 sectors
> sd1 at scsibus1 targ 2 lun 0: 
> uvm_fault(0x821d00e8, 0x0, 0, 1) -> e
> kernel: page fault trap, code=0
> Stopped at  nvme_scsi_capacity16+0x39:  movq0(%rax),%rcx
> ddb{0}>
> 
> "ns" in both functions will be NULL, if "identify" is not allocated in
> nvme_scsi_probe().  Thus, its better to just not attach this empty
> disks/LUNs.
> 
> nvme0 at pci1 dev 0 function 0 vendor "Intel", unknown product 0x0a54 rev 
> 0x00: msix, NVMe 1.2
> nvme0: INTEL SSDPE2KX040T8, firmware VDV10170, serial PHLJ0413002P4P0DGN
> scsibus1 at nvme0: 129 targets, initiator 0
> sd0 at scsibus1 targ 1 lun 0: 
> sd0: 3815447MB, 512 bytes/sector, 7814037168 sectors
> ppb1 at pci0 dev 3 function 2 "AMD 17h PCIE" rev 0x00: msi
> pci2 at ppb1 bus 98
> nvme1 at pci2 dev 0 function 0 vendor "Intel", unknown product 0x0a54 rev 
> 0x00: msix, NVMe 1.2
> nvme1: INTEL SSDPE2KX040T8, firmware VDV10170, serial PHLJ041500C34P0DGN
> scsibus2 at nvme1: 129 targets, initiator 0
> sd1 at scsibus2 targ 1 lun 0: 
> sd1: 3815447MB, 512 bytes/sector, 7814037168 sectors
> ppb2 at pci0 dev 3 function 3 "AMD 17h PCIE" rev 0x00: msi
> pci3 at ppb2 bus 99
> nvme2 at pci3 dev 0 function 0 vendor "Intel", unknown product 0x0a54 rev 
> 0x00: msix, NVMe 1.2
> nvme2: INTEL SSDPE2KX040T8, firmware VDV10170, serial PHLJ041402Z64P0DGN
> scsibus3 at nvme2: 129 targets, initiator 0
> sd2 at scsibus3 targ 1 lun 0: 
> sd2: 3815447MB, 512 bytes/sector, 7814037168 sectors
> ppb3 at pci0 dev 3 function 4 "AMD 17h PCIE" rev 0x00: msi
> pci4 at ppb3 bus 100
> nvme3 at pci4 dev 0 function 0 vendor "Intel", unknown product 0x0a54 rev 
> 0x00: msix, NVMe 1.2
> nvme3: INTEL SSDPE2KX040T8, firmware VDV10170, serial PHLJ041403134P0DGN
> scsibus4 at nvme3: 129 targets, initiator 0
> sd3 at scsibus4 targ 1 lun 0: 
> sd3: 3815447MB, 512 bytes/sector, 7814037168 sectors
> 
> The following diff signals an error for the upper probing function in
> the SCSI layer to prevents further function calls in nvme(4) which would
> just leads to the upper described error and hundreds of not configured
> devices.
> 
> OK?

I think this is the correct way to fix it.  The issue essentially is
that we still return "ok" even though the size is zero.  And we should
probably fail similarly as if it didn't exist.  FreeBSD has a similar
check here, which explains it a little:

/*
 * If the size of is zero, chances are this isn't a valid
 * namespace (eg one that's not been configured yet). The
 * standard says the entire id will be zeros, so this is a
 * cheap way to test for that.
 */
if (ns->data.nsze == 0)
return (ENXIO);

I wondered if this block of code could be written a bit differently, but
I couldn't make it look any better.

ok patrick@ fwiw

> bye,
> Jan
> 
> Index: dev/ic/nvme.c
> ===
> RCS file: /cvs//src/sys/dev/ic/nvme.c,v
> retrieving revision 1.90
> diff -u -p -r1.90 nvme.c
> --- dev/ic/nvme.c 9 Feb 2021 01:50:10 -   1.90
> +++ dev/ic/nvme.c 24 Feb 2021 16:01:48 -
> @@ -463,11 +463,16 @@ nvme_scsi_probe(struct scsi_link *link)
>   scsi_io_put(>sc_iopool, ccb);
>  
>   identify = NVME_DMA_KVA(mem);
> - if (rv == 0 && lemtoh64(>nsze) > 0) {
> - /* Commit namespace if it has a size greater than zero. */
> - identify = malloc(sizeof(*identify), M_DEVBUF, M_WAITOK);
> - memcpy(identify, NVME_DMA_KVA(mem), sizeof(*identify));
> - sc->sc_namespaces[link->target].ident = identify;
> + if (rv == 0) {
> + if (lemtoh64(>nsze) > 0) {
> + /* Commit namespace if it has a size greater than zero. 
> */
> + identify = malloc(sizeof(*identify), M_DEVBUF, 
> M_WAITOK);
> + memcpy(identify, NVME_DMA_KVA(mem), sizeof(*identify));
> + sc->sc_namespaces[link->target].ident = identify;
> + } else {
> + /* Don't attach a namespace if its size is zero. */
> + rv = ENXIO;
> + }
>   }
>  
>   nvme_dmamem_free(sc, mem);
> 



sdmmc(4): check and retry bus width change

2021-02-22 Thread Patrick Wildt
Hi,

it seems like some eMMCs are not capable of doing 8-bit operation,
even if the controller supports it.  I was questioning our drivers
first, but it looks like it's the same on Linux.  In the case that
8-bit doesn't work, they seem to fall back to lower values to make
that HW work.

This diff implements a mechanism that tries 8-bit, if available,
then 4-bit and in the end falls back to 1-bit.  This makes my HW
work, but I would like to have this tested by a broader audience.

Apparently there's a "bus test" command, but it isn't implemented
on all host controllers.  Hence I simply try to read the EXT_CSD
to make sure the transfer works.

For testing, a print like

printf("%s: using %u-bit width\n", DEVNAME(sc), width);

could be added at line 928.

What could possible regressions be?  The width could become smaller
then previously.  This would reduce the read/write transfer speed.
Also it's possible that eMMCs are not recognized/initialized anymore.

What could possible improvements be?  eMMCs that previously didn't
work now work, with at least 1-bit or 4-bit wide transfers.

Please note that this only works for eMMCs.  SD cards are *not* using
this code path.  SD cards have a different initialization code path.

Please report any changes or non-changes.  If nothing changes, that's
perfect.

Patrick

diff --git a/sys/dev/sdmmc/sdmmc_mem.c b/sys/dev/sdmmc/sdmmc_mem.c
index 59bcb1b4a11..5856b9bb1b3 100644
--- a/sys/dev/sdmmc/sdmmc_mem.c
+++ b/sys/dev/sdmmc/sdmmc_mem.c
@@ -56,6 +56,8 @@ int   sdmmc_mem_signal_voltage(struct sdmmc_softc *, int);
 
 intsdmmc_mem_sd_init(struct sdmmc_softc *, struct sdmmc_function *);
 intsdmmc_mem_mmc_init(struct sdmmc_softc *, struct sdmmc_function *);
+intsdmmc_mem_mmc_select_bus_width(struct sdmmc_softc *,
+   struct sdmmc_function *, int);
 intsdmmc_mem_single_read_block(struct sdmmc_function *, int, u_char *,
size_t);
 intsdmmc_mem_read_block_subr(struct sdmmc_function *, bus_dmamap_t,
@@ -908,31 +910,20 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *sc, struct 
sdmmc_function *sf)
ext_csd[EXT_CSD_CARD_TYPE]);
}
 
-   if (ISSET(sc->sc_caps, SMC_CAPS_8BIT_MODE)) {
+   if (ISSET(sc->sc_caps, SMC_CAPS_8BIT_MODE) &&
+   sdmmc_mem_mmc_select_bus_width(sc, sf, 8) == 0)
width = 8;
-   value = EXT_CSD_BUS_WIDTH_8;
-   } else if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE)) {
+   else if (ISSET(sc->sc_caps, SMC_CAPS_4BIT_MODE) &&
+   sdmmc_mem_mmc_select_bus_width(sc, sf, 4) == 0)
width = 4;
-   value = EXT_CSD_BUS_WIDTH_4;
-   } else {
-   width = 1;
-   value = EXT_CSD_BUS_WIDTH_1;
-   }
-
-   if (width != 1) {
-   error = sdmmc_mem_mmc_switch(sf, EXT_CSD_CMD_SET_NORMAL,
-   EXT_CSD_BUS_WIDTH, value);
-   if (error == 0)
-   error = sdmmc_chip_bus_width(sc->sct,
-   sc->sch, width);
-   else {
+   else {
+   error = sdmmc_mem_mmc_select_bus_width(sc, sf, 1);
+   if (error != 0) {
DPRINTF(("%s: can't change bus width"
" (%d bit)\n", DEVNAME(sc), width));
return error;
}
-
-   /* : need bus test? (using by CMD14 & CMD19) */
-   sdmmc_delay(1);
+   width = 1;
}
 
if (timing != SDMMC_TIMING_LEGACY) {
@@ -1041,6 +1032,59 @@ sdmmc_mem_mmc_init(struct sdmmc_softc *sc, struct 
sdmmc_function *sf)
return error;
 }
 
+int
+sdmmc_mem_mmc_select_bus_width(struct sdmmc_softc *sc, struct sdmmc_function 
*sf,
+int width)
+{
+   u_int8_t ext_csd[512];
+   int error, value;
+
+   switch (width) {
+   case 8:
+   value = EXT_CSD_BUS_WIDTH_8;
+   break;
+   case 4:
+   value = EXT_CSD_BUS_WIDTH_4;
+   break;
+   case 1:
+   value = EXT_CSD_BUS_WIDTH_1;
+   break;
+   default:
+   printf("%s: invalid bus width\n", DEVNAME(sc));
+   return EINVAL;
+   }
+
+   error = sdmmc_mem_mmc_switch(sf, EXT_CSD_CMD_SET_NORMAL,
+   EXT_CSD_BUS_WIDTH, value);
+   if (error != 0) {
+   DPRINTF(("%s: can't change card bus width"
+   " (%d bit)\n", DEVNAME(sc), width));
+   return error;
+   }
+
+   error = sdmmc_chip_bus_width(sc->sct,
+   sc->sch, width);
+   if (error != 0) {
+   DPRINTF(("%s: can't change host bus width"
+   " (%d bit)\n", 

Re: add simplepmbus(4)

2021-02-17 Thread Patrick Wildt
Am Wed, Feb 17, 2021 at 11:56:16AM +1100 schrieb Jonathan Gray:
> Add a driver for "simple-pm-bus" a way to enable a clock and/or
> power domain for a group of devices.
> 
> https://www.kernel.org/doc/Documentation/devicetree/bindings/bus/simple-pm-bus.txt
> 
> This is needed to use am335x/omap4 dtbs from linux 5.11.

"A Simple Power-Managed Bus is a transparent bus that doesn't need a real
driver, as it's typically initialized by the boot loader."

That's a bit funny though. :-)  But I think they meant "it doesn't need
a real driver, apart from the generic simple-pm-bus driver".


> Index: sys/dev/fdt/files.fdt
> ===
> RCS file: /cvs/src/sys/dev/fdt/files.fdt,v
> retrieving revision 1.146
> diff -u -p -r1.146 files.fdt
> --- sys/dev/fdt/files.fdt 5 Feb 2021 00:05:20 -   1.146
> +++ sys/dev/fdt/files.fdt 17 Feb 2021 00:49:02 -
> @@ -23,6 +23,10 @@ device simplepanel
>  attach   simplepanel at fdt
>  file dev/fdt/simplepanel.c   simplepanel
>  
> +device   simplepmbus: fdt
> +attach   simplepmbus at fdt
> +file dev/fdt/simplepmbus.c   simplepmbus
> +
>  device   sxiccmu
>  attach   sxiccmu at fdt
>  file dev/fdt/sxiccmu.c   sxiccmu
> Index: share/man/man4/Makefile
> ===
> RCS file: /cvs/src/share/man/man4/Makefile,v
> retrieving revision 1.792
> diff -u -p -r1.792 Makefile
> --- share/man/man4/Makefile   4 Feb 2021 16:25:38 -   1.792
> +++ share/man/man4/Makefile   17 Feb 2021 00:49:02 -
> @@ -72,7 +72,8 @@ MAN=aac.4 abcrtc.4 abl.4 ac97.4 acphy.4
>   rl.4 rlphy.4 route.4 rsu.4 rtsx.4 rum.4 run.4 rtw.4 rtwn.4 \
>   safe.4 safte.4 sbus.4 schsio.4 scsi.4 sd.4 \
>   sdmmc.4 sdhc.4 se.4 ses.4 sf.4 sili.4 \
> - simpleamp.4 simpleaudio.4 simplefb.4 simplepanel.4 siop.4 sis.4 sk.4 \
> + simpleamp.4 simpleaudio.4 simplefb.4 simplepanel.4 simplepmbus.4 \
> + siop.4 sis.4 sk.4 \
>   sm.4 smsc.4 softraid.4 spdmem.4 sdtemp.4 speaker.4 sppp.4 sqphy.4 \
>   ssdfb.4 st.4 ste.4 stge.4 sti.4 stp.4 sv.4 switch.4 sxiccmu.4 \
>   sxidog.4 sximmc.4 sxipio.4 sxipwm.4 sxirsb.4 sxirtc.4 sxisid.4 \
> Index: sys/arch/armv7/conf/GENERIC
> ===
> RCS file: /cvs/src/sys/arch/armv7/conf/GENERIC,v
> retrieving revision 1.134
> diff -u -p -r1.134 GENERIC
> --- sys/arch/armv7/conf/GENERIC   4 Feb 2021 16:25:39 -   1.134
> +++ sys/arch/armv7/conf/GENERIC   17 Feb 2021 00:49:02 -
> @@ -31,6 +31,7 @@ config  bsd swap generic
>  # The main bus device
>  mainbus0 at root
>  simplebus*   at fdt?
> +simplepmbus* at fdt?
>  cpu0 at mainbus?
>  
>  # Cortex-A9
> Index: sys/arch/armv7/conf/RAMDISK
> ===
> RCS file: /cvs/src/sys/arch/armv7/conf/RAMDISK,v
> retrieving revision 1.119
> diff -u -p -r1.119 RAMDISK
> --- sys/arch/armv7/conf/RAMDISK   18 Jun 2020 08:48:04 -  1.119
> +++ sys/arch/armv7/conf/RAMDISK   17 Feb 2021 00:49:02 -
> @@ -30,6 +30,7 @@ config  bsd root on rd0a swap on rd0b
>  mainbus0 at root
>  softraid0at root
>  simplebus*   at fdt?
> +simplepmbus* at fdt?
>  cpu0 at mainbus?
>  
>  # Cortex-A9
> --- /dev/null Wed Feb 17 11:49:05 2021
> +++ sys/dev/fdt/simplepmbus.c Tue Feb 16 17:24:55 2021
> @@ -0,0 +1,62 @@
> +/*   $OpenBSD$   */
> +/*
> + * Copyright (c) 2021 Jonathan Gray 
> + *
> + * Permission to use, copy, modify, and distribute this software for any
> + * purpose with or without fee is hereby granted, provided that the above
> + * copyright notice and this permission notice appear in all copies.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
> + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> + */
> +
> +#include 
> +#include 
> +
> +#include 
> +
> +#include 
> +#include 
> +#include 
> +
> +#include 

Maybe like this, was we have in rkpinctrl?

#ifdef __armv7__
#include 
#else
#include 
#endif

Generally I was wondering if we shouldn't just add this to simplebus.c
itself?  You'd need to add a compatible to the match function, and in
the attach function you'd need to check for the compatible and then
do

power_domain_enable(faa->fa_node);
clock_enable_all(faa->fa_node);

in the if-block.

Haven't made my mind up yet what I like better, maybe kettenis@ has an
opinion.

Patrick

> +
> +int  

Re: Posted vs. non-posted device access

2021-02-14 Thread Patrick Wildt
Am Mon, Feb 15, 2021 at 09:55:56AM +1000 schrieb David Gwynne:
> 
> 
> > On 15 Feb 2021, at 07:54, Mark Kettenis  wrote:
> > 
> > One of the aspects of device access is whether CPU writes to a device
> > are posted or non-posted.  For non-posted writes, the CPU will wait
> > for the device to acknowledge that the write has performed.  If the
> > device sits on a bus far away, this can take a while and slow things
> > down.  The alternative are so-called posted writes.  The CPU will
> > "post" the write to the bus without waiting for an acknowledgement.
> > The CPU may receive an asynchronous notifaction at a later time that
> > the write didn't succeed or a failing write may be dropped without
> > further botification.  On most architectures whether writes are posted
> > or not is a property of the bus between the CPU and the device.  For
> > example, memory mapped I/O on the PCI bus is always posted and there
> > is nothing the CPU can do about it.
> > 
> > On the ARM architecture though we can indicate to the CPU whether
> > writes to a certain address range should be posted or not.  This is
> > done by specifying certain memory attributes in the mappings used by
> > the MMU.  The OpenBSD kernel always specifies device access as
> > non-posted.  On all ARM implementations we have seen so far this seems
> > to work even for writes to devices connected to a PCIe bus.  There
> > might be a penalty though, so I need to investigate this a bit
> > further.
> > 
> > However, on Apple's M1 SoC, this isn't the case.  Non-posted writes to
> > a bus that uses posted writes fail and vice-versa.  So in order to use
> > the PCIe bus on these SoCs we need to specify the right memory
> > attributes.  The diff below implements this by introducing a new
> > BUS_SPACE_MAP_POSTED flag.  At this point I don't expect generic
> > drivers to use this flag yet.  So there is no need to add it for other
> > architectures.  But I don't rule out we may have to use this flag in
> > sys/dev/fdt sometime in the future.  That is why I posted this to a
> > wider audience.
> 
> You don't want to (ab)use one of the existing flags? If I squint and read 
> kind of quickly I could imagine this is kind of like write combining, like 
> what BUS_SPACE_MAP_PREFETCHABLE can do on pci busses.

BUS_SPACE_MAP_PREFETCHABLE should be "normal uncached" memory on arm64,
which is different to device memory.  That said I have a device where
amdgpu(4) doesn't behave if it's "normal uncached", and I'm not sure if
it's the HW's fault or if there's some barrier missing.  Still, I would
not use BUS_SPACE_MAP_PREFETCHABLE for nGnRnE vs nGnRE.

More info on device vs normal is here:

https://developer.arm.com/documentation/102376/0100/Normal-memory
https://developer.arm.com/documentation/102376/0100/Device-memory

> If this does leak into fdt, would it just be a nop on other archs that use 
> those drivers?
> 
> dlg
> 
> > 
> > ok?
> > 
> > 
> > Index: arch/arm64/arm64/locore.S
> > ===
> > RCS file: /cvs/src/sys/arch/arm64/arm64/locore.S,v
> > retrieving revision 1.32
> > diff -u -p -r1.32 locore.S
> > --- arch/arm64/arm64/locore.S   19 Oct 2020 17:57:40 -  1.32
> > +++ arch/arm64/arm64/locore.S   14 Feb 2021 21:28:26 -
> > @@ -233,9 +233,10 @@ switch_mmu_kernel:
> > mair:
> > /* Device | Normal (no cache, write-back, write-through) */
> > .quad   MAIR_ATTR(0x00, 0) |\
> > -   MAIR_ATTR(0x44, 1) |\
> > -   MAIR_ATTR(0xff, 2) |\
> > -   MAIR_ATTR(0x88, 3)
> > +   MAIR_ATTR(0x04, 1) |\
> > +   MAIR_ATTR(0x44, 2) |\
> > +   MAIR_ATTR(0xff, 3) |\
> > +   MAIR_ATTR(0x88, 4)
> > tcr:
> > .quad (TCR_T1SZ(64 - VIRT_BITS) | TCR_T0SZ(64 - 48) | \
> > TCR_AS | TCR_TG1_4K | TCR_CACHE_ATTRS | TCR_SMP_ATTRS)
> > Index: arch/arm64/arm64/locore0.S
> > ===
> > RCS file: /cvs/src/sys/arch/arm64/arm64/locore0.S,v
> > retrieving revision 1.5
> > diff -u -p -r1.5 locore0.S
> > --- arch/arm64/arm64/locore0.S  28 May 2019 20:32:30 -  1.5
> > +++ arch/arm64/arm64/locore0.S  14 Feb 2021 21:28:26 -
> > @@ -34,8 +34,8 @@
> > #include 
> > 
> > #define DEVICE_MEM  0
> > -#defineNORMAL_UNCACHED 1
> > -#defineNORMAL_MEM  2
> > +#defineNORMAL_UNCACHED 2
> > +#defineNORMAL_MEM  3
> > 
> > /*
> >  * We assume:
> > Index: arch/arm64/arm64/machdep.c
> > ===
> > RCS file: /cvs/src/sys/arch/arm64/arm64/machdep.c,v
> > retrieving revision 1.57
> > diff -u -p -r1.57 machdep.c
> > --- arch/arm64/arm64/machdep.c  11 Feb 2021 23:55:48 -  1.57
> > +++ arch/arm64/arm64/machdep.c  14 Feb 2021 21:28:27 -
> > @@ -1188,7 +1188,7 @@ pmap_bootstrap_bs_map(bus_space_tag_t t,
> > 
> > for (pa = startpa; pa < endpa; pa += PAGE_SIZE, 

Re: Add missing break statement on if_rge.c

2021-02-11 Thread Patrick Wildt
Am Thu, Feb 11, 2021 at 12:24:37PM + schrieb Ricardo Mestre:
> Hi,
> 
> Add missing break statement. OK?

makes sense to me, ok patrick@

> CID 1501710
> 
> Index: if_rge.c
> ===
> RCS file: /cvs/src/sys/dev/pci/if_rge.c,v
> retrieving revision 1.11
> diff -u -p -c -u -r1.11 if_rge.c
> --- if_rge.c  24 Dec 2020 06:34:03 -  1.11
> +++ if_rge.c  11 Feb 2021 12:21:33 -
> @@ -311,6 +311,7 @@ rge_activate(struct device *self, int ac
>  #ifndef SMALL_KERNEL
>   rge_wol_power(sc);
>  #endif
> + break;
>   default:
>   rv = config_activate_children(self, act);
>   break;
> 



Re: isakmpd link dynamically

2021-02-11 Thread Patrick Wildt
Am Thu, Feb 11, 2021 at 11:29:58AM +0100 schrieb Alexander Bluhm:
> - recommit in /usr/src/usr.sbin -> we loose history

I know no one cares about git, but if the move was committed in a
"single cvs commit", git would understand it's simply a move of files.
So yeah, cvs wouldn't cope, but git would.



Re: Swapped arguments on stoeplitz_ip{4,6}port

2021-02-11 Thread Patrick Wildt
Already committed as of 7 minutes ago, heh!

Am Thu, Feb 11, 2021 at 10:48:16AM + schrieb Ricardo Mestre:
> Hi,
> 
> It seems this got the args swapped as described in CID 1501717.
> 
> stoeplitz_ip6port being a macro for stoeplitz_hash_ip6port and the arguments
> placed as shown below. Similarly stoeplitz_ip4port also has the same problem
> most likely due to copypasto.
> 
> Comments? OK?
> 
> 173 uint16_t
> 174 stoeplitz_hash_ip6port(const struct stoeplitz_cache *scache,
> 175 const struct in6_addr *faddr6, const struct in6_addr *laddr6,
> 176 in_port_t fport, in_port_t lport)
> 
> Index: netinet/in_pcb.c
> ===
> RCS file: /cvs/src/sys/netinet/in_pcb.c,v
> retrieving revision 1.253
> diff -u -p -u -r1.253 in_pcb.c
> --- netinet/in_pcb.c  25 Jan 2021 03:40:46 -  1.253
> +++ netinet/in_pcb.c  11 Feb 2021 10:34:50 -
> @@ -522,8 +522,8 @@ in_pcbconnect(struct inpcb *inp, struct 
>   inp->inp_fport = sin->sin_port;
>   in_pcbrehash(inp);
>  #if NSTOEPLITZ > 0
> - inp->inp_flowid = stoeplitz_ip4port(inp->inp_laddr.s_addr,
> - inp->inp_faddr.s_addr, inp->inp_lport, inp->inp_fport);
> + inp->inp_flowid = stoeplitz_ip4port(inp->inp_faddr.s_addr,
> + inp->inp_laddr.s_addr, inp->inp_fport, inp->inp_lport);
>  #endif
>  #ifdef IPSEC
>   {
> Index: netinet6/in6_pcb.c
> ===
> RCS file: /cvs/src/sys/netinet6/in6_pcb.c,v
> retrieving revision 1.111
> diff -u -p -u -r1.111 in6_pcb.c
> --- netinet6/in6_pcb.c25 Jan 2021 03:40:47 -  1.111
> +++ netinet6/in6_pcb.c11 Feb 2021 10:34:50 -
> @@ -303,8 +303,8 @@ in6_pcbconnect(struct inpcb *inp, struct
>   inp->inp_flowinfo |=
>   (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
>  #if NSTOEPLITZ > 0
> - inp->inp_flowid = stoeplitz_ip6port(>inp_laddr6,
> - >inp_faddr6, inp->inp_lport, inp->inp_fport);
> + inp->inp_flowid = stoeplitz_ip6port(>inp_faddr6,
> + >inp_laddr6, inp->inp_fport, inp->inp_lport);
>  #endif
>   in_pcbrehash(inp);
>   return (0);
> 



Re: rasops1

2020-12-23 Thread Patrick Wildt
Am Wed, Dec 23, 2020 at 11:32:58PM +0100 schrieb Frederic Cambus:
> Hi Mark,
> 
> On Fri, Dec 18, 2020 at 10:33:52PM +0100, Mark Kettenis wrote:
> 
> > The diff below disables the optimized functions on little-endian
> > architectures such that we always use rasops1_putchar().  This makes
> > ssdfb(4) work with the default 8x16 font on arm64.
> 
> I noticed it was committed already, but it seems the following
> directives:
> 
> #if defined(RASOPS_SMALL) && BYTE_ORDER == BIG_ENDIAN
> 
> Should have been:
> 
> #if !defined(RASOPS_SMALL) && BYTE_ORDER == BIG_ENDIAN
> 
> We want to include the optimized putchar functions only if RASOPS_SMALL
> is not defined.
> 

True that.  In one #endif comment he actually kept the !, but the actual
ifs lost it.



Re: tsleep(9): add global "nowake" channel

2020-12-23 Thread Patrick Wildt
Am Wed, Dec 23, 2020 at 05:04:23PM -0600 schrieb Scott Cheloha:
> On Wed, Dec 23, 2020 at 02:42:18PM -0700, Theo de Raadt wrote:
> > I agree.  This chunk below is really gross and does not follow the
> > special wakeup channel metaphor.
> > 
> > It is *entirely clear* that a  called "nowake" has no wakeup.
> > Like duh.
> > 
> > > +/*
> > > + * nowake is a global sleep channel for threads that do not want
> > > + * to receive wakeup(9) broadcasts.
> > > + */
> > > +int __nowake;
> > > +void *nowake = &__nowake;
> 
> So we'll go with this?
> 
> Index: kern/kern_synch.c
> ===
> RCS file: /cvs/src/sys/kern/kern_synch.c,v
> retrieving revision 1.172
> diff -u -p -r1.172 kern_synch.c
> --- kern/kern_synch.c 7 Dec 2020 16:55:29 -   1.172
> +++ kern/kern_synch.c 23 Dec 2020 23:03:31 -
> @@ -87,6 +87,11 @@ sleep_queue_init(void)
>   TAILQ_INIT([i]);
>  }
>  
> +/*
> + * Global sleep channel for threads that do not want to
> + * receive wakeup(9) broadcasts.
> + */
> +int nowake;
>  
>  /*
>   * During autoconfiguration or after a panic, a sleep will simply
> @@ -119,6 +124,7 @@ tsleep(const volatile void *ident, int p
>  #endif
>  
>   KASSERT((priority & ~(PRIMASK | PCATCH)) == 0);
> + KASSERT(ident != nowake || ISSET(priority, PCATCH) || timo != 0);

Sure you compiled this? ident is void *, nowake is int.  Should be ident
!= ?  Same for the other code in the diff.

>  
>  #ifdef MULTIPROCESSOR
>   KASSERT(timo || _kernel_lock_held());
> @@ -213,6 +219,7 @@ msleep(const volatile void *ident, struc
>  #endif
>  
>   KASSERT((priority & ~(PRIMASK | PCATCH | PNORELOCK)) == 0);
> + KASSERT(ident != nowake || ISSET(priority, PCATCH) || timo != 0);
>   KASSERT(mtx != NULL);
>  
>   if (priority & PCATCH)
> @@ -301,6 +308,7 @@ rwsleep(const volatile void *ident, stru
>   int error, status;
>  
>   KASSERT((priority & ~(PRIMASK | PCATCH | PNORELOCK)) == 0);
> + KASSERT(ident != nowake || ISSET(priority, PCATCH) || timo != 0);
>   rw_assert_anylock(rwl);
>   status = rw_status(rwl);
>  
> Index: sys/systm.h
> ===
> RCS file: /cvs/src/sys/sys/systm.h,v
> retrieving revision 1.148
> diff -u -p -r1.148 systm.h
> --- sys/systm.h   26 Aug 2020 03:29:07 -  1.148
> +++ sys/systm.h   23 Dec 2020 23:03:31 -
> @@ -107,6 +107,8 @@ extern struct vnode *rootvp;  /* vnode eq
>  extern dev_t swapdev;/* swapping device */
>  extern struct vnode *swapdev_vp;/* vnode equivalent to above */
>  
> +extern int nowake;   /* dead wakeup(9) channel */
> +
>  struct proc;
>  struct process;
>  #define curproc curcpu()->ci_curproc
> 



Re: xhci zero length transfers 'leak' one transfer buffer count

2020-12-23 Thread Patrick Wildt
Am Wed, Dec 23, 2020 at 10:44:21AM +0100 schrieb Marcus Glocker:
> On Wed, 23 Dec 2020 09:47:44 +0100
> Marcus Glocker  wrote:
> 
> > On Tue, 22 Dec 2020 20:55:41 +0100
> > Marcus Glocker  wrote:
> > 
> > > > > Did you consider incrementing xx->ntrb instead?
> > >   
> > > >That doesn't work either, because the status completion code needs
> > > >xx->ntrb to be correct for the data TD to be handled correctly.
> > > >Incrementing xx->ntrb means the number of TRBs for the data TD is
> > > >incorrect, since it includes the (optional) zero TD's TRB.
> > > >
> > > >In this case the zero TD allocates a TRB but doesn't do proper
> > > >accounting, and currently there's no place where this could be
> > > >accounted properly.
> > > >
> > > >In the end it's all software, so I guess the diff will simply have
> > > >to be bigger than just a one-liner.
> > >   
> > > > > With the diff below the produced TRB isn't accounted which might
> > > > > lead
> > > > > to and off-by-one.
> > > 
> > > Sorry, I missed this thread and had to re-grab the last mail from
> > > MARC.
> > > 
> > > Can't we just take account of the zero trb separately?  
> > 
> > We also want to reset the zerotrb.
> 
> Re-thinking this again I think we should only increase the zerotrb to
> avoid again a possible miss match for free_trbs, and leave the
> responsibility to the caller of xhci_xfer_get_trb() to request the
> right amount of zerotrb.
> 
> 
> Index: dev/usb/xhci.c
> ===
> RCS file: /cvs/src/sys/dev/usb/xhci.c,v
> retrieving revision 1.119
> diff -u -p -u -p -r1.119 xhci.c
> --- dev/usb/xhci.c31 Jul 2020 19:27:57 -  1.119
> +++ dev/usb/xhci.c23 Dec 2020 09:38:58 -
> @@ -1135,8 +1135,10 @@ xhci_xfer_done(struct usbd_xfer *xfer)
>   i = (xp->ring.ntrb - 1);
>   }
>   xp->free_trbs += xx->ntrb;
> + xp->free_trbs += xx->zerotrb;
>   xx->index = -1;
>   xx->ntrb = 0;
> + xx->zerotrb = 0;
>  
>   timeout_del(>timeout_handle);
>   usb_rem_task(xfer->device, >abort_task);
> @@ -1842,6 +1844,7 @@ xhci_xfer_get_trb(struct xhci_softc *sc,
>   switch (last) {
>   case -1:/* This will be a zero-length TD. */
>   xp->pending_xfers[xp->ring.index] = NULL;
> + xx->zerotrb += 1;
>   break;
>   case 0: /* This will be in a chain. */
>   xp->pending_xfers[xp->ring.index] = xfer;
> Index: dev/usb/xhcivar.h
> ===
> RCS file: /cvs/src/sys/dev/usb/xhcivar.h,v
> retrieving revision 1.11
> diff -u -p -u -p -r1.11 xhcivar.h
> --- dev/usb/xhcivar.h 6 Oct 2019 17:30:00 -   1.11
> +++ dev/usb/xhcivar.h 23 Dec 2020 09:38:58 -
> @@ -40,6 +40,7 @@ struct xhci_xfer {
>   struct usbd_xfer xfer;
>   int  index; /* Index of the last TRB */
>   size_t   ntrb;  /* Number of associated TRBs */
> + size_t   zerotrb;   /* Is zero len TRB required? */

It's a zero-length TD, not TRB.  I mean, it indeed is a zero-legth TRB,
but the important thing is that it's part of an extra TD.  So at least
update the comment, maybe even the variable name.

The difference is that a TD means that it's a separate transfer.  It
also completes seperately from the TD before.  In theory xfer done will
be called on the initial TD, not on the zero TD, which means that we
could have a race where our accounting "frees" the zero TD, even though
the controller isn't there yet.  In practice I think this is not an
issue, the ring's hopefully long enough that we don't immediately reuse
the TRB that we just freed.

So, I think the approach taken in this diff is fine, the code looks
good, only the naming I think can be improved.  Maybe really just call
it zerotd, then it also fits with the comment.

>  };
>  
>  struct xhci_ring {
> 



Re: uplcom driver update for 23a3 (HXN) chip

2020-10-26 Thread Patrick Wildt
On Mon, Oct 26, 2020 at 09:12:17AM +0100, Stefan Huber wrote:
> Hey all,
> 
> I recently got hands on an USB-TTY converter that is not (yet) supported by
> OpenBSD:
> 
> > addr 03: 067b:23a3 Prolific Technology Inc., USB-Serial Controller
> 
> Simply adding the device ID to usbdevs and the uplcom driver did not do the
> trick, as apparently it is what the linux driver calls a "HXN" chip, which
> is (as of now) not yet supported by the uplcom driver (also, not in NetBSD
> where the uplcom driver seems to come from). Some hours (days) later, I have
> produced the following diff, butchering both the uplcom and the linux
> driver. I know it looks like shit, but it works (for now and for me). I will
> try to "streamline" the driver, and am happy for any feedback (since you may
> see watching the code I am not a good kernel hacker yet).
> 
> I was also thinking of adding all the other IDs from the linux driver to
> uplcom, but then I can't test them since I only have the two chips 067b:2303
> and 067b:23a3. So I'd rather not merge the other IDs to prevent the kernel
> from doing nasty things to them (or was it the other way around?)
> 
> The diff's below. Works for me. Not looking for okay or a merge, mostly
> feedback and maybe a merge for a future version of this diff.

First of all, we need unified diffs.  Usually you have a CVS checkout
and then run cvs diff -u.  Yours don't look like you used cvs, was that
a diff -r?  Well, even then you should add -u, otherwise diffs become
unreadable.

Second, only OpenBSD account holders can ask for OKs. :)

So, please resend with diff -u, otherwise no one will have a look at it
since the diff is hard to follow.

Thanks,
Patrick

> Happy Hacking,
> Stefan
> 
> 
> Common subdirectories: /home/src_orig/sys/dev/usb/CVS and
> /usr/src/sys/dev/usb/CVS
> Common subdirectories: /home/src_orig/sys/dev/usb/dwc2 and
> /usr/src/sys/dev/usb/dwc2
> diff /home/src_orig/sys/dev/usb/uplcom.c /usr/src/sys/dev/usb/uplcom.c
> 66c66
> < #define DPRINTF(x) DPRINTFN(0, x)
> ---
> > #define DPRINTF(x) printf x;
> 71a72,74
> > #define UPLCOM_SET_NREQUEST 0x80
> > #define UPLCOM_READ_REQUEST 0x01
> > #define UPLCOM_READ_NREQUEST0x81
> 77a81,91
> > #define UPLCOM_READ_HX_STATUS   0x8080
> > #define UPLCOM_HXN_RESET_REG0x07
> > #define UPLCOM_HXN_RESET_UPSTREAM_PIPE  0x02
> > #define UPLCOM_HXN_RESET_DOWNSTREAM_PIPE0x01
> > 
> > #define UPLCOM_HXN_FLOWCTRL_REG 0x0a
> > #define UPLCOM_HXN_FLOWCTRL_MASK0x1c
> > #define UPLCOM_HXN_FLOWCTRL_NONE0x1c
> > #define UPLCOM_HXN_FLOWCTRL_RTS_CTS 0x18
> > #define UPLCOM_HXN_FLOWCTRL_XON_XOFF0x0c
> > 
> 98a113
> > int  sc_type_hxn;   /* HXN variant */
> 108a124,127
> > usbd_status uplcom_update_reg(struct uplcom_softc *sc, char reg, char
> > mask, char val);
> > usbd_status uplcom_vendor_read(struct uplcom_softc *sc, char val, char
> > buf[1]);
> > usbd_status uplcom_vendor_write(struct uplcom_softc *sc, char val, char
> > index);
> > int uplcom_test_hxn(struct uplcom_softc *);
> 153a173
> > { USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL23a3 },
> 250c270,272
> < if (ddesc->bDeviceClass == 0x02)
> ---
> > printf("[DEBUG] DeviceClass: %x\n", ddesc->bDeviceClass);
> > printf("[DEBUG] MaxPacketSize: %x\n", ddesc->bMaxPacketSize);
> > if (ddesc->bDeviceClass == 0x02) { /* type 0 */
> 252c274,276
> < else if (ddesc->bMaxPacketSize == 0x40)
> ---
> > sc->sc_type_hxn = 0;
> > }
> > else if (ddesc->bMaxPacketSize == 0x40) { /* type hx */
> 254c278,280
> < else
> ---
> > sc->sc_type_hxn = 0;
> > }
> > else { /* probably type 1 */
> 255a282,283
> > sc->sc_type_hxn = 0;
> > }
> 256a285,298
> > /*
> >  * The Linux driver also distinguishes HXN variant...
> >  * Let's see if that is needed for the 23a3 variant.
> >  */
> > if (sc->sc_type_hx == 1) {
> > printf("[DEBUG] seems to be HX type. Checking for HXN type.\n");
> > if (uplcom_test_hxn(sc)) {
> > printf("[DEBUG] Probably HXN.\n");
> > sc->sc_type_hxn = 1;
> > } else {
> > printf("[DEBUG] Probably not HXN.\n");
> > }
> > }
> > 
> 259c301,303
> < if (sc->sc_type_hx) {
> ---
> > if (sc->sc_type_hxn) {
> > DPRINTF(("uplcom_attach: chiptype 2303XN\n"));
> > } else if (sc->sc_type_hx) {
> 419a464,471
> > 
> > if (sc->sc_type_hxn) {
> > DPRINTF(("[DEBUG] trying to reset hxn\n"));
> > req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
> > req.bRequest = UPLCOM_SET_NREQUEST;
> > USETW(req.wValue, 0x07);
> > USETW(req.wIndex, UPLCOM_HXN_RESET_UPSTREAM_PIPE |
> > UPLCOM_HXN_RESET_DOWNSTREAM_PIPE);
> > USETW(req.wLength, 0);
> 421,425c473,484
> < 

Re: xhci zero length transfers 'leak' one transfer buffer count

2020-10-11 Thread Patrick Wildt
On Sun, Oct 11, 2020 at 08:12:29AM +0200, Martin Pieuchot wrote:
> On 09/10/20(Fri) 12:37, Jonathon Fletcher wrote:
> > In xhci_xfer_get_trb, the count of transfer buffers in the pipe 
> > (xp->free_trbs) is always decremented but the count of transfer buffers 
> > used in the transfer (xx->ntrb) is not incremented for zero-length 
> > transfers. The result of this is that, at the end of a zero length 
> > transfer, xp->free_trbs has 'lost' one.
> > 
> > Over time, this mismatch of unconditional decrement (xp->free_trbs) vs 
> > conditional increment (xx->ntrb) results in xhci_device_*_start returning 
> > USBD_NOMEM.
> > 
> > The patch below works around this by only decrementing xp->free_trbs in the 
> > cases when xx->ntrb is incremented.
> 
> Did you consider incrementing xx->ntrb instead?

That doesn't work either, because the status completion code needs
xx->ntrb to be correct for the data TD to be handled correctly.
Incrementing xx->ntrb means the number of TRBs for the data TD is
incorrect, since it includes the (optional) zero TD's TRB.

In this case the zero TD allocates a TRB but doesn't do proper
accounting, and currently there's no place where this could be
accounted properly.

In the end it's all software, so I guess the diff will simply have
to be bigger than just a one-liner.

> With the diff below the produced TRB isn't accounted which might lead to
> and off-by-one.
> 
> > Index: xhci.c
> > ===
> > RCS file: /cvs/src/sys/dev/usb/xhci.c,v
> > retrieving revision 1.119
> > diff -u -p -u -r1.119 xhci.c
> > --- xhci.c  31 Jul 2020 19:27:57 -  1.119
> > +++ xhci.c  9 Oct 2020 19:11:45 -
> > @@ -1836,7 +1836,6 @@ xhci_xfer_get_trb(struct xhci_softc *sc,
> > struct xhci_xfer *xx = (struct xhci_xfer *)xfer;
> >  
> > KASSERT(xp->free_trbs >= 1);
> > -   xp->free_trbs--;
> > *togglep = xp->ring.toggle;
> >  
> > switch (last) {
> > @@ -1847,11 +1846,13 @@ xhci_xfer_get_trb(struct xhci_softc *sc,
> > xp->pending_xfers[xp->ring.index] = xfer;
> > xx->index = -2;
> > xx->ntrb += 1;
> > +   xp->free_trbs--;
> > break;
> > case 1: /* This will terminate a chain. */
> > xp->pending_xfers[xp->ring.index] = xfer;
> > xx->index = xp->ring.index;
> > xx->ntrb += 1;
> > +   xp->free_trbs--;
> > break;
> > }
> >  
> > 
> 



Re: mfokclock(4) -> mfokrtc(4): loongson's hugging arm

2020-09-29 Thread Patrick Wildt
On Tue, Sep 29, 2020 at 11:23:03AM -0600, Theo de Raadt wrote:
> +   if (strcmp(ia->ia_name, "st,m41t83") == 0)
> 
> fine with me.  But in that case, why not call the driver i2c/m41t83.c

Because it's a series of chips, like m41t80, m41t81, m41t82.  Machines
and their device trees encode the specific chip, because some versions
might have a different feature set as others.  We do the same x-place-
holder-notation for other drivers as well.

For now I only match on st,m41t83 since that is the version of the chip
the driver was originally written for.  For every additional supported
variant of that series, the code needs to be checked for correctness.

But the file is still supposed to cover more than this one specific
variant of the series.



mfokclock(4) -> mfokrtc(4): loongson's hugging arm

2020-09-29 Thread Patrick Wildt
Hi,

some arm64 that I'd like to use as replacement server for the one that's
crashing all the time (probably HW-related) has a Microcrystal RV4162
RTC.  As it turns out, this is about the same as the ST M41T8x series.

For that one we already have mfokclock(4), but only for loongson.  After
talking to kettenis@, we think that first of all sys/arch/loongson/dev/
m41t8xclock.c should be moved to sys/dev/i2c/m41t8x.c so that the file
can be re-used by multiple architectures.  And usually we don't have the
type of device in the filename, so I removed that as well.

Usually we reserve clock for clock control subsystems, while we call
RTCs as they are.  That's why I renamed mfokclock(4) to mfokrtc(4),
and also renamed the code accordingly.

Instead of matching on the driver's name, let's match on st,m41t83, as
when the driver was imported that specific chip was the reason for the
driver.  This also means changing the iic controller to pass a different
string.

Can someone make sure this still works on their loongson devices?  Are
there any objections to this?

Thank you,
Patrick

diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index 4a3df6b33b1..8ba306f41ed 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -47,8 +47,8 @@ MAN=  aac.4 abcrtc.4 abl.4 ac97.4 acphy.4 acrtc.4 \
kate.4 kcov.4 km.4 ksmn.4 ksyms.4 kubsan.4 kue.4 lc.4 lge.4 lii.4 \
lisa.4 lm.4 lmenv.4 lmn.4 lmtemp.4 lo.4 lpt.4 lxtphy.4 luphy.4 \
maestro.4 mainbus.4 malo.4 maxds.4 maxrtc.4 maxtmp.4 mbg.4 \
-   mcprtc.4 mcx.4 midi.4 mii.4 mfi.4 \
-   mfii.4 mlphy.4 moscom.4 mos.4 mpe.4 mpath.4 mpi.4 mpii.4 \
+   mcprtc.4 mcx.4 midi.4 mii.4 mfi.4 mfii.4 mfokrtc.4 \
+   mlphy.4 moscom.4 mos.4 mpe.4 mpath.4 mpi.4 mpii.4 \
mpip.4 mpu.4 msk.4 mpw.4 msts.4 mtd.4 mtdphy.4 mtio.4 mue.4 \
multicast.4 mvclock.4 mvdog.4 mvgicp.4 mvgpio.4 mvicu.4 mviic.4 \
mvneta.4 mvpinctrl.4 mvpp.4 mvrng.4 mvrtc.4 mvspi.4 mvtemp.4 mvuart.4 \
diff --git a/share/man/man4/man4.loongson/Makefile 
b/share/man/man4/man4.loongson/Makefile
index 6e133c04f62..b3d5b061c84 100644
--- a/share/man/man4/man4.loongson/Makefile
+++ b/share/man/man4/man4.loongson/Makefile
@@ -1,7 +1,7 @@
 #  $OpenBSD: Makefile,v 1.10 2016/11/17 15:06:16 visa Exp $
 
 MAN=   apm.4 autoconf.4 bonito.4 gdiumiic.4 glxclk.4 glxpcib.4 htb.4 intro.4 \
-   leioc.4 mem.4 mfokclock.4 sisfb.4 smfb.4 stsec.4 voyager.4 ykbec.4
+   leioc.4 mem.4 sisfb.4 smfb.4 stsec.4 voyager.4 ykbec.4
 MANSUBDIR=loongson
 
 .include 
diff --git a/share/man/man4/man4.loongson/mfokclock.4 
b/share/man/man4/man4.loongson/mfokclock.4
deleted file mode 100644
index 69d122dfdf2..000
--- a/share/man/man4/man4.loongson/mfokclock.4
+++ /dev/null
@@ -1,31 +0,0 @@
-.\"$OpenBSD: mfokclock.4,v 1.2 2018/06/18 06:06:52 jmc Exp $
-.\"
-.\" Copyright (c) 2010 Miodrag Vallat.
-.\"
-.\" Permission to use, copy, modify, and distribute this software for any
-.\" purpose with or without fee is hereby granted, provided that the above
-.\" copyright notice and this permission notice appear in all copies.
-.\"
-.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.\"
-.Dd $Mdocdate: June 18 2018 $
-.Dt MFOKCLOCK 4 loongson
-.Os
-.Sh NAME
-.Nm mfokclock
-.Nd M41T8x real-time clock
-.Sh SYNOPSIS
-.Cd "mfokclock* at iic? addr 0x68"
-.Sh DESCRIPTION
-The
-.Nm
-driver supports two-wire real-time clock chips of the M41T8x family.
-.Sh SEE ALSO
-.Xr iic 4 ,
-.Xr intro 4
diff --git a/share/man/man4/mfokrtc.4 b/share/man/man4/mfokrtc.4
new file mode 100644
index 000..487591817ec
--- /dev/null
+++ b/share/man/man4/mfokrtc.4
@@ -0,0 +1,31 @@
+.\"$OpenBSD: mfokclock.4,v 1.2 2018/06/18 06:06:52 jmc Exp $
+.\"
+.\" Copyright (c) 2010 Miodrag Vallat.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Re: utpms(4): fix geyser 2 y_sensors

2020-09-11 Thread Patrick Wildt
On Thu, Sep 10, 2020 at 10:13:30AM +0200, Tobias Heider wrote:
> Hi,
> 
> the newer Geyser 2 touchpad has only 9 sensors in the Y-direction instead
> of 16 like the other Apple touch pads.
> The driver sets sc_y_sensors correctly and then immediately overwrites
> it with the wrong default.
> I think we should first set the defaults and then treat the special
> cases.
> 
> ok?

*not* ok

> Index: utpms.c
> ===
> RCS file: /mount/openbsd/cvs/src/sys/dev/usb/utpms.c,v
> retrieving revision 1.9
> diff -u -p -r1.9 utpms.c
> --- utpms.c   25 Aug 2020 14:01:58 -  1.9
> +++ utpms.c   9 Sep 2020 22:45:42 -
> @@ -311,6 +311,13 @@ utpms_attach(struct device *parent, stru
>   for (i = 0; i < nitems(utpms_devices); i++) {
>   pd = _devices[i];
>   if (product == pd->product && vendor == pd->vendor) {
> + printf(" Trackpad\n");

You moved the printf, that's wrong.  I guess your dmesg will look like:

utpms0 Trackpad
: GeyserANOTHERDRIVER: lalala

but it is supposed to be:

utpms0: Geyser Trackpad
ANOTHERDRIVER: lalala

> + sc->sc_noise = pd->noise;
> + sc->sc_threshold = pd->threshold;
> + sc->sc_x_factor = pd->x_factor;
> + sc->sc_x_sensors = pd->x_sensors;
> + sc->sc_y_factor = pd->y_factor;
> + sc->sc_y_sensors = pd->y_sensors;
>   switch (pd->type) {
>   case FOUNTAIN:
>   printf(": Fountain");
> @@ -325,13 +332,6 @@ utpms_attach(struct device *parent, stru
>   printf(": Geyser 2");
>   break;
>   }
> - printf(" Trackpad\n");

So, the " Trackpad\n" printf *needs* to stay here while the rest can
happily move upstairs.

With that fixed, ok patrick@

> - sc->sc_noise = pd->noise;
> - sc->sc_threshold = pd->threshold;
> - sc->sc_x_factor = pd->x_factor;
> - sc->sc_x_sensors = pd->x_sensors;
> - sc->sc_y_factor = pd->y_factor;
> - sc->sc_y_sensors = pd->y_sensors;
>   break;
>   }
>   }
> 



Re: softintr.h comment tweak

2020-08-14 Thread Patrick Wildt
On Fri, Aug 14, 2020 at 02:33:10PM +0200, Mark Kettenis wrote:
> Miod noticed that the powerpc64 version talked about AArch64.  I don't
> think the "for all XXX platforms" makes sense so simply drop it from
> all three versions of this header.
> 
> ok?
> 

ok patrick@

> 
> Index: arch/arm/include/softintr.h
> ===
> RCS file: /cvs/src/sys/arch/arm/include/softintr.h,v
> retrieving revision 1.5
> diff -u -p -r1.5 softintr.h
> --- arch/arm/include/softintr.h   21 Dec 2010 14:56:23 -  1.5
> +++ arch/arm/include/softintr.h   14 Aug 2020 12:30:10 -
> @@ -44,7 +44,7 @@
>  #include 
>  
>  /*
> - * Generic software interrupt support for all ARM platforms.
> + * Generic software interrupt support.
>   *
>   * To use this code, include  from your platform's
>   * .
> Index: arch/arm64/include/softintr.h
> ===
> RCS file: /cvs/src/sys/arch/arm64/include/softintr.h,v
> retrieving revision 1.1
> diff -u -p -r1.1 softintr.h
> --- arch/arm64/include/softintr.h 17 Dec 2016 23:38:33 -  1.1
> +++ arch/arm64/include/softintr.h 14 Aug 2020 12:30:10 -
> @@ -39,7 +39,7 @@
>  #include 
>  
>  /*
> - * Generic software interrupt support for all AArch64 platforms.
> + * Generic software interrupt support.
>   *
>   * To use this code, include  from your platform's
>   * .
> Index: arch/powerpc64/include/softintr.h
> ===
> RCS file: /cvs/src/sys/arch/powerpc64/include/softintr.h,v
> retrieving revision 1.1
> diff -u -p -r1.1 softintr.h
> --- arch/powerpc64/include/softintr.h 16 May 2020 17:11:14 -  1.1
> +++ arch/powerpc64/include/softintr.h 14 Aug 2020 12:30:10 -
> @@ -38,7 +38,7 @@
>  #include 
>  
>  /*
> - * Generic software interrupt support for all AArch64 platforms.
> + * Generic software interrupt support.
>   *
>   * To use this code, include  from your platform's
>   * .
> 



Re: Enable arm64 PAN feature

2020-08-13 Thread Patrick Wildt
On Thu, Aug 13, 2020 at 09:17:41PM +0200, Mark Kettenis wrote:
> ARMv8.1 introduced PAN (Priviliged Access Never) which prevents the
> kernel from accessing userland data.  This can be bypassed by using
> special instructions which we already use in copyin(9) and friends.
> So we can simply turn this feature on if the CPU supports it.
> 
> Tested on an Odroid-C4 which has Cortex-A55 cores that have PAN
> support.
> 
> ok?
> 

So if I read this right, the SPAN bit makes that an exception to
kernel/hypervisor mode sets the PAN bit in the PSTATE.  Exception
also means "interrupt", or is this only syscall?  I think intrs
are also exceptions...

Essentially, everytime we switch to EL1/EL2 PAN will be enabled?
Sounds good to me, ok patrick@

> 
> Index: arch/arm64/arm64/cpu.c
> ===
> RCS file: /cvs/src/sys/arch/arm64/arm64/cpu.c,v
> retrieving revision 1.38
> diff -u -p -r1.38 cpu.c
> --- arch/arm64/arm64/cpu.c4 Jun 2020 21:18:16 -   1.38
> +++ arch/arm64/arm64/cpu.c13 Aug 2020 19:12:30 -
> @@ -321,6 +321,7 @@ cpu_attach(struct device *parent, struct
>   struct fdt_attach_args *faa = aux;
>   struct cpu_info *ci;
>   uint64_t mpidr = READ_SPECIALREG(mpidr_el1);
> + uint64_t id_aa64mmfr1, sctlr;
>   uint32_t opp;
>  
>   KASSERT(faa->fa_nreg > 0);
> @@ -393,6 +394,14 @@ cpu_attach(struct device *parent, struct
>   cpu_cpuspeed = cpu_clockspeed;
>   }
>  
> + /* Enable PAN. */
> + id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1);
> + if (ID_AA64MMFR1_PAN(id_aa64mmfr1) != ID_AA64MMFR1_PAN_NONE) {
> + sctlr = READ_SPECIALREG(sctlr_el1);
> + sctlr &= ~SCTLR_SPAN;
> + WRITE_SPECIALREG(sctlr_el1, sctlr);
> + }
> +
>   /* Initialize debug registers. */
>   WRITE_SPECIALREG(mdscr_el1, DBG_MDSCR_TDCC);
>   WRITE_SPECIALREG(oslar_el1, 0);
> @@ -522,6 +531,7 @@ cpu_boot_secondary(struct cpu_info *ci)
>  void
>  cpu_start_secondary(struct cpu_info *ci)
>  {
> + uint64_t id_aa64mmfr1, sctlr;
>   uint64_t tcr;
>   int s;
>  
> @@ -543,6 +553,14 @@ cpu_start_secondary(struct cpu_info *ci)
>   tcr |= TCR_T0SZ(64 - USER_SPACE_BITS);
>   tcr |= TCR_A1;
>   WRITE_SPECIALREG(tcr_el1, tcr);
> +
> + /* Enable PAN. */
> + id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1);
> + if (ID_AA64MMFR1_PAN(id_aa64mmfr1) != ID_AA64MMFR1_PAN_NONE) {
> + sctlr = READ_SPECIALREG(sctlr_el1);
> + sctlr &= ~SCTLR_SPAN;
> + WRITE_SPECIALREG(sctlr_el1, sctlr);
> + }
>  
>   /* Initialize debug registers. */
>   WRITE_SPECIALREG(mdscr_el1, DBG_MDSCR_TDCC);
> Index: arch/arm64/include/armreg.h
> ===
> RCS file: /cvs/src/sys/arch/arm64/include/armreg.h,v
> retrieving revision 1.11
> diff -u -p -r1.11 armreg.h
> --- arch/arm64/include/armreg.h   5 Jun 2020 22:14:25 -   1.11
> +++ arch/arm64/include/armreg.h   13 Aug 2020 19:12:30 -
> @@ -451,6 +451,7 @@
>  #define  SCTLR_nTWI  0x0001
>  #define  SCTLR_nTWE  0x0004
>  #define  SCTLR_WXN   0x0008
> +#define  SCTLR_SPAN  0x0080
>  #define  SCTLR_EOE   0x0100
>  #define  SCTLR_EE0x0200
>  #define  SCTLR_UCI   0x0400
> @@ -478,6 +479,7 @@
>  #define  PSR_D   0x0200
>  #define  PSR_IL  0x0010
>  #define  PSR_SS  0x0020
> +#define  PSR_PAN 0x0040
>  #define  PSR_V   0x1000
>  #define  PSR_C   0x2000
>  #define  PSR_Z   0x4000
> 



Re: xhci(4) isoc: fix bogus handling of chained TRBs

2020-07-10 Thread Patrick Wildt
On Fri, Jul 10, 2020 at 01:00:31PM +0200, Marcus Glocker wrote:
> Hi All,
> 
> Laurence Tratt was reporting about corrupted video images when using
> uvideo(4) on xhci(4) with MJPEG and higher resolutions, e.g. when using
> ffplay:
> 
> $ ffplay -f v4l2 -input_format mjpeg -video_size 1280x720 -f /dev/video1
> 
> When trying to re-produce the issue on my side, the video images were
> still OK, but I also could see a lot of errors returned by ffplay
> related to corrupted MJPEG data.
> 
> When debugging the error I noticed that the corruption only happens
> when TRBs are get chained due to hitting a 64k boundary, and therefore
> require to queue up two TRBs.  So, what happened?
> 
> In xhci.c:xhci_event_xfer_isoc() we do the accounting of the
> processed, chained TD:
> 
> /*
>  * If we queued two TRBs for a frame and this is the second TRB,
>  * check if the first TRB needs accounting since it might not have
>  * raised an interrupt in case of full data received.
>  */
> 
> If there was a zero length transfer with such a TD, and the 2. TRB
> receives the interrupt with len=0, it assumes that the 1. TRB was
> processed (but it wasn't), and adds the requested 1. TRB length to
> actlen, passing back that data has been received, which is obviously
> wrong, resulting in the seen data corruptions.
> 
> Instead, when the 2. TRB receives the IOC interrupt with len=0, we
> need to ignore the 1. TRB, considering this was a zero length transfer.
> 
> With the below diff Laurent is getting a clear video image now with
> high resolutions, and I could remove all the output errors from ffplay
> in my case.  I also tested with an uaudio(4) device.
> 
> Feedback, more testers, OKs?
> 
> Thanks,
> Marcus
> 

What if the first TRB was filled completely, but the second TRB
transferred 0?  Wouldn't we then need to add 1. TRB?  I think your
diff wouldn't do that.

I think what we actually need is some "processed" flag.  If you look
on bugs@ or so, there's a diff that tries to fix the same issue by
adding a "CHAINED" or so flag.  I'm not sure if that's the right way.

But, anyway, I think we need a way to say "this TRB got an interrupt"
or "this TRB was processed".

> 
> Index: xhci.c
> ===
> RCS file: /cvs/src/sys/dev/usb/xhci.c,v
> retrieving revision 1.116
> diff -u -p -u -p -r1.116 xhci.c
> --- xhci.c30 Jun 2020 10:21:59 -  1.116
> +++ xhci.c10 Jul 2020 05:57:11 -
> @@ -932,6 +932,7 @@ xhci_event_xfer_isoc(struct usbd_xfer *x
>   struct usbd_xfer *skipxfer;
>   struct xhci_xfer *xx = (struct xhci_xfer *)xfer;
>   int trb0_idx, frame_idx = 0;
> + uint32_t len;
>  
>   KASSERT(xx->index >= 0);
>   trb0_idx =
> @@ -945,6 +946,7 @@ xhci_event_xfer_isoc(struct usbd_xfer *x
>   if (trb0_idx++ == (xp->ring.ntrb - 1))
>   trb0_idx = 0;
>   }
> + len = XHCI_TRB_LEN(letoh32(xp->ring.trbs[trb_idx].trb_status)) - remain;
>  
>   /*
>* If we queued two TRBs for a frame and this is the second TRB,
> @@ -954,18 +956,17 @@ xhci_event_xfer_isoc(struct usbd_xfer *x
>   if ((letoh32(xp->ring.trbs[trb_idx].trb_flags) & XHCI_TRB_TYPE_MASK) ==
>   XHCI_TRB_TYPE_NORMAL) {
>   frame_idx--;
> - if (trb_idx == 0)
> - trb0_idx = xp->ring.ntrb - 2;
> - else
> - trb0_idx = trb_idx - 1;
> - if (xfer->frlengths[frame_idx] == 0) {
> + if (len > 0 && xfer->frlengths[frame_idx] == 0) {
> + if (trb_idx == 0)
> + trb0_idx = xp->ring.ntrb - 2;
> + else
> + trb0_idx = trb_idx - 1;
>   xfer->frlengths[frame_idx] = XHCI_TRB_LEN(letoh32(
>   xp->ring.trbs[trb0_idx].trb_status));
>   }
>   }
>  
> - xfer->frlengths[frame_idx] +=
> - XHCI_TRB_LEN(letoh32(xp->ring.trbs[trb_idx].trb_status)) - remain;
> + xfer->frlengths[frame_idx] += len;
>   xfer->actlen += xfer->frlengths[frame_idx];
>  
>   if (xx->index != trb_idx)
> 



replace IFQ_SET_MAXLEN and IFQ_IS_EMPTY

2020-07-10 Thread Patrick Wildt
Hi,

based on the previous diffs, this removes the last remaining users
of the compat API.  IFQ_SET_MAXLEN is simply now lowercase, and
IFQ_IS_EMPTY is lowercase and got its _IS removed.  Pretty mechanical
diff.

ok?

Patrick

diff --git a/sys/arch/armv7/omap/if_cpsw.c b/sys/arch/armv7/omap/if_cpsw.c
index 7aee2730989..829a061038c 100644
--- a/sys/arch/armv7/omap/if_cpsw.c
+++ b/sys/arch/armv7/omap/if_cpsw.c
@@ -448,7 +448,7 @@ cpsw_attach(struct device *parent, struct device *self, 
void *aux)
ifp->if_start = cpsw_start;
ifp->if_ioctl = cpsw_ioctl;
ifp->if_watchdog = cpsw_watchdog;
-   IFQ_SET_MAXLEN(>if_snd, CPSW_NTXDESCS - 1);
+   ifq_set_maxlen(>if_snd, CPSW_NTXDESCS - 1);
memcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
 
cpsw_stop(ifp);
@@ -520,7 +520,7 @@ cpsw_start(struct ifnet *ifp)
 
if (!ISSET(ifp->if_flags, IFF_RUNNING) ||
ifq_is_oactive(>if_snd) ||
-   IFQ_IS_EMPTY(>if_snd))
+   ifq_empty(>if_snd))
return;
 
if (sc->sc_txnext >= sc->sc_txhead)
diff --git a/sys/arch/armv7/sunxi/sxie.c b/sys/arch/armv7/sunxi/sxie.c
index c1c4259a783..4c4aa04a41d 100644
--- a/sys/arch/armv7/sunxi/sxie.c
+++ b/sys/arch/armv7/sunxi/sxie.c
@@ -267,7 +267,7 @@ sxie_attach(struct device *parent, struct device *self, 
void *aux)
ifp->if_watchdog = sxie_watchdog;
ifp->if_capabilities = IFCAP_VLAN_MTU; /* XXX status check in recv? */
 
-   IFQ_SET_MAXLEN(>if_snd, IFQ_MAXLEN);
+   ifq_set_maxlen(>if_snd, IFQ_MAXLEN);
 
/* Initialize MII/media info. */
mii = >sc_mii;
diff --git a/sys/arch/octeon/dev/if_cnmac.c b/sys/arch/octeon/dev/if_cnmac.c
index 4be44bf2c9e..194024eaec7 100644
--- a/sys/arch/octeon/dev/if_cnmac.c
+++ b/sys/arch/octeon/dev/if_cnmac.c
@@ -310,7 +310,7 @@ cnmac_attach(struct device *parent, struct device *self, 
void *aux)
ifp->if_qstart = cnmac_start;
ifp->if_watchdog = cnmac_watchdog;
ifp->if_hardmtu = CNMAC_MAX_MTU;
-   IFQ_SET_MAXLEN(>if_snd, max(GATHER_QUEUE_SIZE, IFQ_MAXLEN));
+   ifq_set_maxlen(>if_snd, max(GATHER_QUEUE_SIZE, IFQ_MAXLEN));
 
ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_CSUM_TCPv4 |
IFCAP_CSUM_UDPv4 | IFCAP_CSUM_TCPv6 | IFCAP_CSUM_UDPv6;
diff --git a/sys/arch/sgi/dev/if_iec.c b/sys/arch/sgi/dev/if_iec.c
index 6408f16b62e..44c76142fd9 100644
--- a/sys/arch/sgi/dev/if_iec.c
+++ b/sys/arch/sgi/dev/if_iec.c
@@ -408,7 +408,7 @@ iec_attach(struct device *parent, struct device *self, void 
*aux)
ifp->if_watchdog = iec_watchdog;
 
if_attach(ifp);
-   IFQ_SET_MAXLEN(>if_snd, IEC_NTXDESC - 1);
+   ifq_set_maxlen(>if_snd, IEC_NTXDESC - 1);
ether_ifattach(ifp);
 
/* Establish interrupt handler. */
diff --git a/sys/arch/sgi/dev/if_mec.c b/sys/arch/sgi/dev/if_mec.c
index f8b18abcc16..5ae63517f10 100644
--- a/sys/arch/sgi/dev/if_mec.c
+++ b/sys/arch/sgi/dev/if_mec.c
@@ -460,7 +460,7 @@ mec_attach(struct device *parent, struct device *self, void 
*aux)
ifp->if_watchdog = mec_watchdog;
 
if_attach(ifp);
-   IFQ_SET_MAXLEN(>if_snd, MEC_NTXDESC - 1);
+   ifq_set_maxlen(>if_snd, MEC_NTXDESC - 1);
ether_ifattach(ifp);
 
/* Establish interrupt handler. */
diff --git a/sys/arch/sgi/hpc/if_sq.c b/sys/arch/sgi/hpc/if_sq.c
index 65716393dce..0a9b94062ce 100644
--- a/sys/arch/sgi/hpc/if_sq.c
+++ b/sys/arch/sgi/hpc/if_sq.c
@@ -362,7 +362,7 @@ sq_attach(struct device *parent, struct device *self, void 
*aux)
ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST;
 
if_attach(ifp);
-   IFQ_SET_MAXLEN(>if_snd, SQ_NTXDESC - 1);
+   ifq_set_maxlen(>if_snd, SQ_NTXDESC - 1);
ether_ifattach(ifp);
 
if (haa->hpc_regs->revision == 3) {
diff --git a/sys/arch/sparc64/dev/vnet.c b/sys/arch/sparc64/dev/vnet.c
index a30b45dd2b6..084480151ff 100644
--- a/sys/arch/sparc64/dev/vnet.c
+++ b/sys/arch/sparc64/dev/vnet.c
@@ -314,7 +314,7 @@ vnet_attach(struct device *parent, struct device *self, 
void *aux)
ifp->if_start = vnet_start;
ifp->if_watchdog = vnet_watchdog;
strlcpy(ifp->if_xname, sc->sc_dv.dv_xname, IFNAMSIZ);
-   IFQ_SET_MAXLEN(>if_snd, 31); /* XXX */
+   ifq_set_maxlen(>if_snd, 31); /* XXX */
 
ifmedia_init(>sc_media, 0, vnet_media_change, vnet_media_status);
ifmedia_add(>sc_media, IFM_ETHER | IFM_AUTO, 0, NULL);
@@ -1087,7 +1087,7 @@ vnet_start(struct ifnet *ifp)
if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(>if_snd))
return;
 
-   if (IFQ_IS_EMPTY(>if_snd))
+   if (ifq_empty(>if_snd))
return;
 
/*
diff --git a/sys/dev/fdt/if_dwge.c b/sys/dev/fdt/if_dwge.c
index 0ca21490caf..f71ac4b5d85 100644
--- a/sys/dev/fdt/if_dwge.c
+++ b/sys/dev/fdt/if_dwge.c
@@ -392,7 +392,7 @@ dwge_attach(struct device *parent, struct device *self, 
void *aux)
ifp->if_ioctl = dwge_ioctl;
ifp->if_start = dwge_start;
 

Re: remove compat macros IFQ_ENQUEUE, IFQ_DEQUEUE and IFQ_LEN

2020-07-10 Thread Patrick Wildt
On Fri, Jul 10, 2020 at 12:20:53PM +0300, Vitaliy Makkoveev wrote:
> 
> 
> > On 10 Jul 2020, at 12:13, Patrick Wildt  wrote:
> > 
> > Hi,
> > 
> > this is a rather mechanical diff, done using vim and some regex,
> > to remove and replace IFQ_ENQUEUE, IFQ_DEQUEUE and IFQ_LEN.
> > 
> > There are more, but I didn't want the diff to get too big.  I'll
> > do that after this one is committed.
> > 
> > ok?
> > 
> > Patrick
> 
> I guess ifq_enqueue(9) should also have ???.Dt ifq_enqueue 9??? instead
> of ???.Dt IFQ_ENQUEUE 9???.

No.  .Dt is always uppercase.  Look at printf(9), it has .Dt PRINTF but
there is no PRINTF().

> > 
> > diff --git a/sys/arch/armv7/omap/if_cpsw.c b/sys/arch/armv7/omap/if_cpsw.c
> > index 3b380457e3f..7aee2730989 100644
> > --- a/sys/arch/armv7/omap/if_cpsw.c
> > +++ b/sys/arch/armv7/omap/if_cpsw.c
> > @@ -534,7 +534,7 @@ cpsw_start(struct ifnet *ifp)
> > break;
> > }
> > 
> > -   IFQ_DEQUEUE(>if_snd, m);
> > +   m = ifq_dequeue(>if_snd);
> > if (m == NULL)
> > break;
> > 
> > diff --git a/sys/arch/macppc/dev/if_bm.c b/sys/arch/macppc/dev/if_bm.c
> > index 348d97400cc..d65dcb879a1 100644
> > --- a/sys/arch/macppc/dev/if_bm.c
> > +++ b/sys/arch/macppc/dev/if_bm.c
> > @@ -615,7 +615,7 @@ bmac_start(struct ifnet *ifp)
> > if (ifq_is_oactive(>if_snd))
> > return;
> > 
> > -   IFQ_DEQUEUE(>if_snd, m);
> > +   m = ifq_dequeue(>if_snd);
> > if (m == NULL)
> > break;
> > #if NBPFILTER > 0
> > diff --git a/sys/arch/macppc/dev/if_mc.c b/sys/arch/macppc/dev/if_mc.c
> > index 4fd36fb5748..00b2cb0aa88 100644
> > --- a/sys/arch/macppc/dev/if_mc.c
> > +++ b/sys/arch/macppc/dev/if_mc.c
> > @@ -552,7 +552,7 @@ mc_start(struct ifnet *ifp)
> > if (ifq_is_oactive(>if_snd))
> > return;
> > 
> > -   IFQ_DEQUEUE(>if_snd, m);
> > +   m = ifq_dequeue(>if_snd);
> > if (m == NULL)
> > return;
> > 
> > diff --git a/sys/arch/sparc64/dev/vnet.c b/sys/arch/sparc64/dev/vnet.c
> > index 147caf1f2ec..a30b45dd2b6 100644
> > --- a/sys/arch/sparc64/dev/vnet.c
> > +++ b/sys/arch/sparc64/dev/vnet.c
> > @@ -1132,7 +1132,7 @@ vnet_start(struct ifnet *ifp)
> > break;
> > }
> > 
> > -   IFQ_DEQUEUE(>if_snd, m);
> > +   m = ifq_dequeue(>if_snd);
> > if (m == NULL) {
> > pool_put(>sc_pool, buf);
> > break;
> > @@ -1209,7 +1209,7 @@ vnet_start_desc(struct ifnet *ifp)
> > return;
> > }
> > 
> > -   IFQ_DEQUEUE(>if_snd, m);
> > +   m = ifq_dequeue(>if_snd);
> > if (m == NULL) {
> > pool_put(>sc_pool, buf);
> > return;
> > diff --git a/sys/dev/ic/acx.c b/sys/dev/ic/acx.c
> > index d758d837a0b..8643dddee4e 100644
> > --- a/sys/dev/ic/acx.c
> > +++ b/sys/dev/ic/acx.c
> > @@ -950,7 +950,7 @@ acx_start(struct ifnet *ifp)
> > ni = m->m_pkthdr.ph_cookie;
> > goto encapped;
> > } else {
> > -   IFQ_DEQUEUE(>if_snd, m);
> > +   m = ifq_dequeue(>if_snd);
> > if (m == NULL)
> > break;
> > }
> > diff --git a/sys/dev/ic/am7990.c b/sys/dev/ic/am7990.c
> > index ce092ebf5ac..08c10ada528 100644
> > --- a/sys/dev/ic/am7990.c
> > +++ b/sys/dev/ic/am7990.c
> > @@ -483,7 +483,7 @@ am7990_start(struct ifnet *ifp)
> > sc->sc_no_td, sc->sc_last_td);
> > }
> > 
> > -   IFQ_DEQUEUE(>if_snd, m);
> > +   m = ifq_dequeue(>if_snd);
> > if (m == NULL)
> > break;
> > 
> > diff --git a/sys/dev/ic/am79900.c b/sys/dev/ic/am79900.c
> > index 79e1c9e28cc..9af592e2f73 100644
> > --- a/sys/dev/ic/am79900.c
> > +++ b/sys/dev/ic/am79900.c
> > @@ -506,7 +506,7 @@ am79900_start(struct ifnet *ifp)
> > sc->sc_no_td, sc->sc_last_td);
> > }
> > 
> > -   IFQ_DEQUEUE(>if_s

replace IFQ_PURGE with ifq_purge

2020-07-10 Thread Patrick Wildt
Hi,

based on the previous diff, this rids the compat API from IFQ_PURGE.

ok?

Patrick

diff --git a/sys/dev/ic/ath.c b/sys/dev/ic/ath.c
index c469269eb4e..47505b6b733 100644
--- a/sys/dev/ic/ath.c
+++ b/sys/dev/ic/ath.c
@@ -737,7 +737,7 @@ ath_stop(struct ifnet *ifp)
} else {
sc->sc_rxlink = NULL;
}
-   IFQ_PURGE(>if_snd);
+   ifq_purge(>if_snd);
 #ifndef IEEE80211_STA_ONLY
ath_beacon_free(sc);
 #endif
diff --git a/sys/net/if.c b/sys/net/if.c
index a021c398026..642bb9eca2e 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1614,7 +1614,7 @@ if_down(struct ifnet *ifp)
 
ifp->if_flags &= ~IFF_UP;
getmicrotime(>if_lastchange);
-   IFQ_PURGE(>if_snd);
+   ifq_purge(>if_snd);
 
if_linkstate(ifp);
 }
diff --git a/sys/net/if_mpip.c b/sys/net/if_mpip.c
index 5f82da2f94a..36c9f090270 100644
--- a/sys/net/if_mpip.c
+++ b/sys/net/if_mpip.c
@@ -681,19 +681,19 @@ mpip_start(struct ifnet *ifp)
uint8_t tos, prio, ttl;
 
if (!ISSET(ifp->if_flags, IFF_RUNNING) || n == NULL) {
-   IFQ_PURGE(>if_snd);
+   ifq_purge(>if_snd);
return;
}
 
rt = rtalloc(sstosa(>n_nexthop), RT_RESOLVE, sc->sc_rdomain);
if (!rtisvalid(rt)) {
-   IFQ_PURGE(>if_snd);
+   ifq_purge(>if_snd);
goto rtfree;
}
 
ifp0 = if_get(rt->rt_ifidx);
if (ifp0 == NULL) {
-   IFQ_PURGE(>if_snd);
+   ifq_purge(>if_snd);
goto rtfree;
}
 
diff --git a/sys/net/if_mpw.c b/sys/net/if_mpw.c
index be8bdda2247..eb9c1c0888b 100644
--- a/sys/net/if_mpw.c
+++ b/sys/net/if_mpw.c
@@ -653,19 +653,19 @@ mpw_start(struct ifnet *ifp)
n = sc->sc_neighbor;
if (!ISSET(ifp->if_flags, IFF_RUNNING) ||
n == NULL) {
-   IFQ_PURGE(>if_snd);
+   ifq_purge(>if_snd);
return;
}
 
rt = rtalloc(sstosa(>n_nexthop), RT_RESOLVE, sc->sc_rdomain);
if (!rtisvalid(rt)) {
-   IFQ_PURGE(>if_snd);
+   ifq_purge(>if_snd);
goto rtfree;
}
 
ifp0 = if_get(rt->rt_ifidx);
if (ifp0 == NULL) {
-   IFQ_PURGE(>if_snd);
+   ifq_purge(>if_snd);
goto rtfree;
}
 
diff --git a/sys/net/if_pflog.c b/sys/net/if_pflog.c
index e894f412441..04bcb97ad83 100644
--- a/sys/net/if_pflog.c
+++ b/sys/net/if_pflog.c
@@ -192,7 +192,7 @@ pflog_clone_destroy(struct ifnet *ifp)
 void
 pflogstart(struct ifnet *ifp)
 {
-   IFQ_PURGE(>if_snd);
+   ifq_purge(>if_snd);
 }
 
 int
diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c
index 8a486abd97c..7fcd2ba63a7 100644
--- a/sys/net/if_pfsync.c
+++ b/sys/net/if_pfsync.c
@@ -418,7 +418,7 @@ pfsync_clone_destroy(struct ifnet *ifp)
 void
 pfsyncstart(struct ifnet *ifp)
 {
-   IFQ_PURGE(>if_snd);
+   ifq_purge(>if_snd);
 }
 
 void
diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c
index 7dd1bf1274c..0da09a3b6ec 100644
--- a/sys/net/if_spppsubr.c
+++ b/sys/net/if_spppsubr.c
@@ -768,7 +768,7 @@ sppp_flush(struct ifnet *ifp)
 {
struct sppp *sp = (struct sppp*) ifp;
 
-   IFQ_PURGE(>pp_if.if_snd);
+   ifq_purge(>pp_if.if_snd);
mq_purge(>pp_cpq);
 }
 
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index eb2b25ffad0..2f367b93b30 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -285,11 +285,6 @@ struct ifg_list {
  * IFQ compat on ifq API
  */
 
-#defineIFQ_PURGE(ifq)  
\
-do {   \
-   (void)ifq_purge(ifq);   \
-} while (/* CONSTCOND */0)
-
 #defineIFQ_IS_EMPTY(ifq)   ifq_empty(ifq)
 #defineIFQ_SET_MAXLEN(ifq, len)ifq_set_maxlen(ifq, len)
 



remove compat macros IFQ_ENQUEUE, IFQ_DEQUEUE and IFQ_LEN

2020-07-10 Thread Patrick Wildt
Hi,

this is a rather mechanical diff, done using vim and some regex,
to remove and replace IFQ_ENQUEUE, IFQ_DEQUEUE and IFQ_LEN.

There are more, but I didn't want the diff to get too big.  I'll
do that after this one is committed.

ok?

Patrick

diff --git a/sys/arch/armv7/omap/if_cpsw.c b/sys/arch/armv7/omap/if_cpsw.c
index 3b380457e3f..7aee2730989 100644
--- a/sys/arch/armv7/omap/if_cpsw.c
+++ b/sys/arch/armv7/omap/if_cpsw.c
@@ -534,7 +534,7 @@ cpsw_start(struct ifnet *ifp)
break;
}
 
-   IFQ_DEQUEUE(>if_snd, m);
+   m = ifq_dequeue(>if_snd);
if (m == NULL)
break;
 
diff --git a/sys/arch/macppc/dev/if_bm.c b/sys/arch/macppc/dev/if_bm.c
index 348d97400cc..d65dcb879a1 100644
--- a/sys/arch/macppc/dev/if_bm.c
+++ b/sys/arch/macppc/dev/if_bm.c
@@ -615,7 +615,7 @@ bmac_start(struct ifnet *ifp)
if (ifq_is_oactive(>if_snd))
return;
 
-   IFQ_DEQUEUE(>if_snd, m);
+   m = ifq_dequeue(>if_snd);
if (m == NULL)
break;
 #if NBPFILTER > 0
diff --git a/sys/arch/macppc/dev/if_mc.c b/sys/arch/macppc/dev/if_mc.c
index 4fd36fb5748..00b2cb0aa88 100644
--- a/sys/arch/macppc/dev/if_mc.c
+++ b/sys/arch/macppc/dev/if_mc.c
@@ -552,7 +552,7 @@ mc_start(struct ifnet *ifp)
if (ifq_is_oactive(>if_snd))
return;
 
-   IFQ_DEQUEUE(>if_snd, m);
+   m = ifq_dequeue(>if_snd);
if (m == NULL)
return;
 
diff --git a/sys/arch/sparc64/dev/vnet.c b/sys/arch/sparc64/dev/vnet.c
index 147caf1f2ec..a30b45dd2b6 100644
--- a/sys/arch/sparc64/dev/vnet.c
+++ b/sys/arch/sparc64/dev/vnet.c
@@ -1132,7 +1132,7 @@ vnet_start(struct ifnet *ifp)
break;
}
 
-   IFQ_DEQUEUE(>if_snd, m);
+   m = ifq_dequeue(>if_snd);
if (m == NULL) {
pool_put(>sc_pool, buf);
break;
@@ -1209,7 +1209,7 @@ vnet_start_desc(struct ifnet *ifp)
return;
}
 
-   IFQ_DEQUEUE(>if_snd, m);
+   m = ifq_dequeue(>if_snd);
if (m == NULL) {
pool_put(>sc_pool, buf);
return;
diff --git a/sys/dev/ic/acx.c b/sys/dev/ic/acx.c
index d758d837a0b..8643dddee4e 100644
--- a/sys/dev/ic/acx.c
+++ b/sys/dev/ic/acx.c
@@ -950,7 +950,7 @@ acx_start(struct ifnet *ifp)
ni = m->m_pkthdr.ph_cookie;
goto encapped;
} else {
-   IFQ_DEQUEUE(>if_snd, m);
+   m = ifq_dequeue(>if_snd);
if (m == NULL)
break;
}
diff --git a/sys/dev/ic/am7990.c b/sys/dev/ic/am7990.c
index ce092ebf5ac..08c10ada528 100644
--- a/sys/dev/ic/am7990.c
+++ b/sys/dev/ic/am7990.c
@@ -483,7 +483,7 @@ am7990_start(struct ifnet *ifp)
sc->sc_no_td, sc->sc_last_td);
}
 
-   IFQ_DEQUEUE(>if_snd, m);
+   m = ifq_dequeue(>if_snd);
if (m == NULL)
break;
 
diff --git a/sys/dev/ic/am79900.c b/sys/dev/ic/am79900.c
index 79e1c9e28cc..9af592e2f73 100644
--- a/sys/dev/ic/am79900.c
+++ b/sys/dev/ic/am79900.c
@@ -506,7 +506,7 @@ am79900_start(struct ifnet *ifp)
sc->sc_no_td, sc->sc_last_td);
}
 
-   IFQ_DEQUEUE(>if_snd, m);
+   m = ifq_dequeue(>if_snd);
if (m == NULL)
break;
 
diff --git a/sys/dev/ic/ath.c b/sys/dev/ic/ath.c
index aae0b2a87ff..c469269eb4e 100644
--- a/sys/dev/ic/ath.c
+++ b/sys/dev/ic/ath.c
@@ -845,7 +845,7 @@ ath_start(struct ifnet *ifp)
splx(s);
break;
}
-   IFQ_DEQUEUE(>if_snd, m);
+   m = ifq_dequeue(>if_snd);
if (m == NULL) {
s = splnet();
TAILQ_INSERT_TAIL(>sc_txbuf, bf, bf_list);
diff --git a/sys/dev/ic/athn.c b/sys/dev/ic/athn.c
index 5f84db0b1ea..8384f583934 100644
--- a/sys/dev/ic/athn.c
+++ b/sys/dev/ic/athn.c
@@ -2873,7 +2873,7 @@ athn_start(struct ifnet *ifp)
break;
 
/* Encapsulate and send data frames. */
-   IFQ_DEQUEUE(>if_snd, m);
+   m = ifq_dequeue(>if_snd);
if (m == NULL)
break;
 #if NBPFILTER > 0
diff --git a/sys/dev/ic/atw.c b/sys/dev/ic/atw.c
index cf80921d5d4..a6b676479ba 100644
--- a/sys/dev/ic/atw.c
+++ b/sys/dev/ic/atw.c
@@ -3603,7 +3603,7 @@ atw_start(struct ifnet *ifp)
/* 

Re: Add "Spleen 6x12" font to wsfont

2020-07-08 Thread Patrick Wildt
On Wed, Jul 08, 2020 at 12:19:35PM +0200, Frederic Cambus wrote:
> Hi tech@,
> 
> I created a new size for Spleen, to bridge the gap between the 5x8 and
> the 8x16 versions. The idea is to have something more readable than the
> 5x8 version while still being small enough to be usable on OLED displays.
> 
> Similar to "Spleen 5x8" it only contains the printable ASCII characters
> (96 glyphes).
> 
> In order to enable and test the font, this option should be added to the
> kernel configuration file: option FONT_SPLEEN6x12
> 
> Comments? OK?

Yay, finally!  Looks good to me, ok patrick@

> Index: sys/dev/wsfont/wsfont.c
> ===
> RCS file: /cvs/src/sys/dev/wsfont/wsfont.c,v
> retrieving revision 1.56
> diff -u -p -r1.56 wsfont.c
> --- sys/dev/wsfont/wsfont.c   11 Jul 2019 18:07:54 -  1.56
> +++ sys/dev/wsfont/wsfont.c   8 Jul 2020 10:16:31 -
> @@ -48,6 +48,11 @@
>  #include 
>  #endif
>  
> +#ifdef FONT_SPLEEN6x12
> +#define HAVE_FONT 1
> +#include 
> +#endif
> +
>  #ifdef FONT_SPLEEN8x16
>  #define HAVE_FONT 1
>  #endif
> @@ -150,17 +155,20 @@ static struct font builtin_fonts[] = {
>  #ifdef FONT_SPLEEN5x8
>   BUILTIN_FONT(spleen5x8, 4),
>  #endif
> +#ifdef FONT_SPLEEN6x12
> + BUILTIN_FONT(spleen6x12, 5),
> +#endif
>  #ifdef FONT_SPLEEN8x16
> - BUILTIN_FONT(spleen8x16, 5),
> + BUILTIN_FONT(spleen8x16, 6),
>  #endif
>  #ifdef FONT_SPLEEN12x24
> - BUILTIN_FONT(spleen12x24, 6),
> + BUILTIN_FONT(spleen12x24, 7),
>  #endif
>  #ifdef FONT_SPLEEN16x32
> - BUILTIN_FONT(spleen16x32, 7),
> + BUILTIN_FONT(spleen16x32, 8),
>  #endif
>  #ifdef FONT_SPLEEN32x64
> - BUILTIN_FONT(spleen32x64, 8),
> + BUILTIN_FONT(spleen32x64, 9),
>  #endif
>  #undef BUILTIN_FONT
>  };
> Index: sys/dev/wsfont/spleen6x12.h
> ===
> RCS file: sys/dev/wsfont/spleen6x12.h
> diff -N sys/dev/wsfont/spleen6x12.h
> --- /dev/null 1 Jan 1970 00:00:00 -
> +++ sys/dev/wsfont/spleen6x12.h   8 Jul 2020 10:16:31 -
> @@ -0,0 +1,1294 @@
> +/*   $OpenBSD$ */
> +
> +/*
> + * Copyright (c) 2018-2020 Frederic Cambus 
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *notice, this list of conditions and the following disclaimer in the
> + *documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +static u_char spleen6x12_data[];
> +
> +struct wsdisplay_font spleen6x12 = {
> + .name   = "Spleen 6x12",
> + .index  = 0,
> + .firstchar  = ' ',
> + .numchars   = 128 - ' ',
> + .encoding   = WSDISPLAY_FONTENC_ISO,
> + .fontwidth  = 6,
> + .fontheight = 12,
> + .stride = 1,
> + .bitorder   = WSDISPLAY_FONTORDER_L2R,
> + .byteorder  = WSDISPLAY_FONTORDER_L2R,
> + .cookie = NULL,
> + .data   = spleen6x12_data
> +};
> +
> +static u_char spleen6x12_data[] = {
> + 0x00,   /*  */
> + 0x00,   /*  */
> + 0x00,   /*  */
> + 0x00,   /*  */
> + 0x00,   /*  */
> + 0x00,   /*  */
> + 0x00,   /*  */
> + 0x00,   /*  */
> + 0x00,   /*  */
> + 0x00,   /*  */
> + 0x00,   /*  */
> + 0x00,   /*  */
> +
> + 0x00,   /*  */
> + 0x20,   /* ..*. */
> + 0x20,   /* ..*. */
> + 0x20,   /* ..*. */
> + 0x20,   /* ..*. */
> + 0x20,   /* ..*. */
> + 0x20,   /* ..*. */
> + 0x00,   /*  */
> + 0x20,   /* ..*. */
> + 0x00,   /*  */
> + 0x00,   /*  */
> + 0x00,   /*  */
> +
> + 0x00,   /*  */
> + 0x50,   /* .*.* */
> + 0x50,   /* .*.* */

Re: xhci: zero length multi-TRB inbound xfer does not work

2020-06-24 Thread Patrick Wildt
On Tue, Jun 16, 2020 at 06:55:27AM +, sc.dy...@gmail.com wrote:
> hi,
> 
> The function xhci_event_xfer_isoc() of sys/dev/usb/xhci.c at line 954
> does not work with zero length multi-TRB inbound transfer.
> 
>949/*
>950 * If we queued two TRBs for a frame and this is the 
> second TRB,
>951 * check if the first TRB needs accounting since it 
> might not have
>952 * raised an interrupt in case of full data received.
>953 */
>954if ((letoh32(xp->ring.trbs[trb_idx].trb_flags) & 
> XHCI_TRB_TYPE_MASK) ==
>955XHCI_TRB_TYPE_NORMAL) {
>956frame_idx--;
>957if (trb_idx == 0)
>958trb0_idx = xp->ring.ntrb - 2;
>959else
>960trb0_idx = trb_idx - 1;
>961if (xfer->frlengths[frame_idx] == 0) {
>962xfer->frlengths[frame_idx] = 
> XHCI_TRB_LEN(letoh32(
>963
> xp->ring.trbs[trb0_idx].trb_status));
>964}
>965}
>966
>967xfer->frlengths[frame_idx] +=
>968
> XHCI_TRB_LEN(letoh32(xp->ring.trbs[trb_idx].trb_status)) - remain;
>969xfer->actlen += xfer->frlengths[frame_idx];
> 
> When a multi-TRB inbound transfer TD completes with transfer length = 0,
> the HC should generate two events: 1st event for ISOCH TRB /w ISP|CHAIN
> and 2nd event for NORMAL TRB w/ ISP|IOC.
> Transfer Length field (it's remain length, actually) of each event is
> same as requested length is, i.e., transferred length is 0.
> So when the first event raises the frlengths is set to 0 at line 967.
> It's correct.
> On second event, as the comment describes, xhci.c tries to calculate
> the 1st TRB xfer length at lines 954-965. The requested length of
> 1st TRB is stored into frlengths -- even though the xfer len is 0.
> 
> If frlengths = 0, we cannot distinguish the case the first event is
> not raised from the case the transferred length is 0.
> The frlengths is already 0 so the requested length of 1st TRB is stored.

That's a really good find!  I actually do wonder if we could have the
same issue with the non-isoc transfers, when the first TRB throws a
short and then we get another event for the last TRB.

Maybe it would make sense to record the idx of the last TRB that we have
received an event for?  Then we could check if we already processed that
TRB.

Patrick

> For example, I applied debug printf [*1], and run
> mplayer tv:// for my webcam.
> I see...
> 
> #25 remain 1024 type 5 origlen 1024 frlengths[25] 0
> #25 (omitted) frlen[25] 1024
> #26 remain 2048 type 1 origlen 2048 frlengths[25] 1024
> 
> These console logs show a 3072 bytes frame is splitted into
> two TRBs and got 0 bytes. The first TRB transfers 0 bytes and
> the second TRB transfers 0, too, but it results 1024 bytes.
> 
> My proposal patch [*2] adds a flag to xhci_xfer that indicates the
> TRB processed by xhci.c previously has CHAIN bit, and updates the
> frlengths only when that flag is not set.
> 
> 
> 
> [*1]
> debug printf.
> It shows only splitted isochronous TDs.
> 
> --- sys/dev/usb/xhci.c.orig   Sun Apr  5 10:12:37 2020
> +++ sys/dev/usb/xhci.cFri May 29 04:13:36 2020
> @@ -961,12 +961,23 @@ xhci_event_xfer_isoc(struct usbd_xfer *xfer, struct xh
>   if (xfer->frlengths[frame_idx] == 0) {
>   xfer->frlengths[frame_idx] = XHCI_TRB_LEN(letoh32(
>   xp->ring.trbs[trb0_idx].trb_status));
> + printf("#%d (omitted) frlen[%d] %u\n",
> + trb0_idx, frame_idx, xfer->frlengths[frame_idx]);
>   }
>   }
>  
>   xfer->frlengths[frame_idx] +=
>   XHCI_TRB_LEN(letoh32(xp->ring.trbs[trb_idx].trb_status)) - remain;
>   xfer->actlen += xfer->frlengths[frame_idx];
> + uint32_t trb_flags = letoh32(xp->ring.trbs[trb_idx].trb_flags);
> + if ((trb_flags & XHCI_TRB_CHAIN) ||
> + (trb_flags & XHCI_TRB_TYPE_MASK) == XHCI_TRB_TYPE_NORMAL) {
> + printf("#%d remain %u type %u origlen %u frlengths[%d] %hu\n",
> + trb_idx, remain,
> + XHCI_TRB_TYPE(trb_flags),
> + XHCI_TRB_LEN(le32toh(xp->ring.trbs[trb_idx].trb_status)),
> + frame_idx, xfer->frlengths[frame_idx]);
> + }
>  
>   if (xx->index != trb_idx)
>   return (1);
> 
> [*2]
> patch
> 
> --- sys/dev/usb/xhcivar.h.origSun Oct  6 21:19:28 2019
> +++ sys/dev/usb/xhcivar.h Fri May 22 04:19:57 2020
> @@ -40,6 +40,7 @@ struct xhci_xfer {
>   struct usbd_xfer xfer;
>   int  index; /* Index of the last TRB */
>   size_t   

xhci(4): acknowledge interrupts before calling usb_schedsoftintr()

2020-06-23 Thread Patrick Wildt
Hi,

I had issues with a machine hanging on powerdown.  The issue is caused
by sd(4)'s suspend method trying to "power down" my umass(4) USB stick.

The symptom was that during powerdown, when running in "polling mode",
the first transaction (send command to power down to USB stick) works:
We enqueue a transfer, and then poll for an event in xhci(4).  On the
first transfer, we see an event.  On the second transfer, which is to
read the status from the USB stick, we get a timeout.  We poll for an
event, but we never see it.

"Polling" for an event in xhci(4) means checking its interrupt status
for *any* bit.  But, the interrupt status register never had one set
for the second transaction.  Using a USB debugger, one could see that
the second transaction actually completed, but we just did not get an
interrupt for that completed transfer.

The issue is actually in xhci(4)'s interrupt handler, which is also
called for the polling mode.  There we first acknowledge the pending
interrupts in the USB status register, then we call usb_schedsoftintr(),
and afterwards we acknowledge the interrupt manager regarding "level-
-triggered" interrupts.

In polling mode, usb_schedsoftintr() calls the xhci_softintr() method
right away, which will dequeue an event from the event queue and thus
complete transfers.  The important aspect there is that dequeuing an
event also means touching xhci's registers to inform it that we have
dequeued an event.

In non-polling mode, usb_schedsoftintr() will only schedule a soft-
interrupt, which means that in regards to "touching" the xhci hardware,
the first thing that happens is acknowledging the interrupt manager
bits.

Moving the call to usb_schedsoftintr() to be after the interrupt ACKs
resolves my problem.  With this change, the first thing that happens,
polling and non-polling, is acknowledge the interrupts, and no other
register touching.  And that's also what Linux is doing.  ACK first,
handle events later.

With this, the next xhci_poll() actually sees an interrupt and the
second transfer can succeed.  Thus my machine finally shuts down and
does not anymore hang indefinitely.

Comments?

Patrick

diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index 2d65208f3db..ba5ee56502c 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -624,13 +624,13 @@ xhci_intr1(struct xhci_softc *sc)
return (1);
}
 
-   XOWRITE4(sc, XHCI_USBSTS, intrs); /* Acknowledge */
-   usb_schedsoftintr(>sc_bus);
-
-   /* Acknowledge PCI interrupt */
+   /* Acknowledge interrupts */
+   XOWRITE4(sc, XHCI_USBSTS, intrs);
intrs = XRREAD4(sc, XHCI_IMAN(0));
XRWRITE4(sc, XHCI_IMAN(0), intrs | XHCI_IMAN_INTR_PEND);
 
+   usb_schedsoftintr(>sc_bus);
+
return (1);
 }
 



umass(4): consistently use sc_xfer_flags for polling mode

2020-06-23 Thread Patrick Wildt
Hi,

when powering down, sd(4) will trigger a powerdown on it's umass(4)
USB stick.  If the device fails to respond, for whatever reason, the
umass(4) code will do multiple reset mechanism, and one of those uses
a control transfer.  Unfortunately the control transfer is not passed
the sc_xfer_flags, which are *only* used to supply USBD_SYNCHRONOUS
to allow the polling mode to work.

Without USBD_SYNCHRONOUS, umass_polled_transfer()'s call to
usbd_transfer() will immediately return, and it will never complete.

The code will return to scsi, where it will wait until the "cookie"
is cleared.  Since this is polling mode, there's no asynchronous call-
back, and the cookie will never be cleared.  Thus we will msleep and
wait forever.

By also using sc->sc_xfer_flags on the control transfer, it will run
synchronously.  There's still another bug that happens when even more
transfers fail, since then umass_bbb_transfer()'s call to umass_bbb_
reset() will cause the SCSI done handler to be called a second time
resulting in a panic.

But that's a bug in the state machine for error handling, which can be
fixed later on.  Also a panic during powerdown is better than hanging
indefinitely.

ok?

Patrick

diff --git a/sys/dev/usb/umass.c b/sys/dev/usb/umass.c
index 53d783ff396..f871a3d9c41 100644
--- a/sys/dev/usb/umass.c
+++ b/sys/dev/usb/umass.c
@@ -789,18 +789,18 @@ umass_setup_ctrl_transfer(struct umass_softc *sc, 
usb_device_request_t *req,
/* Initialise a USB control transfer and then schedule it */
 
usbd_setup_default_xfer(xfer, sc->sc_udev, (void *) sc,
-   USBD_DEFAULT_TIMEOUT, req, buffer, buflen, flags,
-   sc->sc_methods->wire_state);
+   USBD_DEFAULT_TIMEOUT, req, buffer, buflen,
+   flags | sc->sc_xfer_flags, sc->sc_methods->wire_state);
 
if (sc->sc_udev->bus->use_polling) {
DPRINTF(UDMASS_XFER,("%s: start polled ctrl xfer buffer=%p "
"buflen=%d flags=0x%x\n", sc->sc_dev.dv_xname, buffer,
-   buflen, flags));
+   buflen, flags | sc->sc_xfer_flags));
err = umass_polled_transfer(sc, xfer);
} else {
DPRINTF(UDMASS_XFER,("%s: start ctrl xfer buffer=%p buflen=%d "
"flags=0x%x\n", sc->sc_dev.dv_xname, buffer, buflen,
-   flags));
+   flags | sc->sc_xfer_flags));
err = usbd_transfer(xfer);
}
if (err && err != USBD_IN_PROGRESS) {



Re: SSE in kernel?

2020-06-23 Thread Patrick Wildt
On Tue, Jun 23, 2020 at 06:51:20AM -0400, Bryan Steele wrote:
> On Mon, Jun 22, 2020 at 11:10:10PM -0700, jo...@armadilloaerospace.com wrote:
> > Are SSE instructions allowed in the AMD64 kernel?  Is #ifdef __SSE__
> > a sufficient guard?
> > 
> > I have a rasops32 putchar with SSE that is 2x faster.
> 
> No, in general you cannot using FP instructions in the kernel, also the
> kernel is often compiled with -msoft-float on platforms that support it.

Exceptions are being made for amdgpu drm, where some of the files are
compiled with sse enabled, though the code is guarded with
fpu_kernel_enter().  DC_FP_START() and DC_FP_END() to be precise, which
are macros pointing to the kernel functions.



Re: WireGuard patchset for OpenBSD, rev. 3

2020-06-21 Thread Patrick Wildt
On Sun, Jun 21, 2020 at 10:06:52AM -0400, Sonic wrote:
> Along that line, does wireguard have any problems using alias
> addresses? It's not a problem with IKEv1 but it is with IKEv2.
> 
> Thanks!
> 
> Chris

I still don't see how this is a problem with IKEv2, so don't spread any
rumours and instead have a look at my response to your mail on misc@.

Patrick



Re: sparc64 boot issue on qemu

2020-05-30 Thread Patrick Wildt
On Sat, May 30, 2020 at 07:21:15PM +, Miod Vallat wrote:
> Yet another case where the emulator does not match the real hardware.
> 
> Why bother with them?
> 
> Get qemu to fix their shit so that the frame buffer metrics variable are
> aligned on 64-bit boundaries. There might not be a written specification
> for this requirement, but that's the way real hardware behaves, and it
> makes complete sense (the variables are OFW cells, which are 64-bit
> values and 64-bit aligned).

I'm not sure if sparc's OFW is different, but in the device trees as
used on arm and probably mips as well, 64-bit values are represented
using two 32-bit cells.  So I think a requirement of 64-bit would not
be correct anyway, and it should be 32-bit instead.

I saw some mailthread on the U-Boot lists regarding some alignment
requirements of some payloads.  Even though they confused the diff-
erence between "alignment of payload that will be put somewhere"
and "alignment of where the payload actually ends up with", it seems
like they also only require 32-bit alignment.  The tools that create
the image with the payloads, which they discussed, also makes sure
all payloads are aligned to 32-bit.



powerpc64: Target Info in clang for __OpenBSD__

2020-05-19 Thread Patrick Wildt
Hi,

drahn@ was complaining to me that his cross-compiler wasn't defining
__OpenBSD__ or __ELF__, and I think the fix is pretty simple.  We're
just missing a case in a switch-case.

The .cpp file itself still compiles, but I haven't built a full clang
with it.  Please give it a go and report back.

I'll already ask for OKs though, but will only commit once I got
positive feedback.  :)

ok?

Patrick

diff --git a/gnu/llvm/tools/clang/lib/Basic/Targets.cpp 
b/gnu/llvm/tools/clang/lib/Basic/Targets.cpp
index 3c139d72479..5bff08ad70d 100644
--- a/gnu/llvm/tools/clang/lib/Basic/Targets.cpp
+++ b/gnu/llvm/tools/clang/lib/Basic/Targets.cpp
@@ -349,6 +349,8 @@ TargetInfo *AllocateTarget(const llvm::Triple ,
   return new FreeBSDTargetInfo(Triple, Opts);
 case llvm::Triple::NetBSD:
   return new NetBSDTargetInfo(Triple, Opts);
+case llvm::Triple::OpenBSD:
+  return new OpenBSDTargetInfo(Triple, Opts);
 default:
   return new PPC64TargetInfo(Triple, Opts);
 }
@@ -359,6 +361,8 @@ TargetInfo *AllocateTarget(const llvm::Triple ,
   return new LinuxTargetInfo(Triple, Opts);
 case llvm::Triple::NetBSD:
   return new NetBSDTargetInfo(Triple, Opts);
+case llvm::Triple::OpenBSD:
+  return new OpenBSDTargetInfo(Triple, Opts);
 default:
   return new PPC64TargetInfo(Triple, Opts);
 }



Re: libsa's in_cksum() cannot handle payload of odd-length?

2020-05-18 Thread Patrick Wildt
On Mon, May 18, 2020 at 10:16:27AM -0600, Theo de Raadt wrote:
> I suspect there are other inconsistancies in all these versions.
> 
> ./sys/arch/arm/arm/in_cksum_arm.S
> ./sys/arch/i386/i386/in_cksum.s
> ./sys/arch/sparc64/sparc64/in_cksum.S
> ./sys/arch/sh/sh/in_cksum.S

These are assembly and for the kernel, uses mbufs.

> ./sys/arch/alpha/alpha/in_cksum.c

Has quite a bit of magic.

> ./sys/arch/hppa/hppa/in_cksum.c

Uses assembly in macros.

> ./sys/arch/m88k/m88k/in_cksum.c

Similar to hppa, but less obscure

> ./sys/arch/powerpc/powerpc/in_cksum.c

Plenty of powerpc assembly.

> ./sys/netinet/in_cksum.c

The default for the kernel.

> ./usr.sbin/dvmrpd/in_cksum.c
> ./usr.sbin/ospfd/in_cksum.c

Finally some userland tools, so no mbufs.  These are the same files,
apart from dvmrpd.h/ospfd.h include.

> ./usr.sbin/eigrpd/in_cksum.c

This one uses unsigned char instead of u_char, but is otherwise the same
as dvmrpd/ospfd.

> ./usr.sbin/tcpdump/in_cksum.c

Similar but has different requirements.

> ./sys/lib/libsa/in_cksum.c

Bootloader, no mbufs.  Code best taken from one of the userland tools.
ospfd is still the best bet.



Re: libsa's in_cksum() cannot handle payload of odd-length?

2020-05-18 Thread Patrick Wildt
On Mon, May 18, 2020 at 05:50:28PM +0200, Claudio Jeker wrote:
> On Mon, May 18, 2020 at 03:50:05PM +0200, Patrick Wildt wrote:
> > Hi,
> > 
> > I was trying to tftpboot and had an issue with files of odd-length.
> > As it turns out, I think the in_cksum() that's called for UDP payload
> > cannot handle a payload length that's not aligned to 16 bytes.
> > 
> > I don't know how in_cksum() is supposed to work exactly, but it looks
> > like the first step is summing up all bytes.  The code is using 16-
> > byte blocks, apart from some oddbyte magic.
> > 
> > First of all, why is there a while loop around code that already
> > consumes the whole length?  That can be done in a single step
> > without the loop.  Why does it continue of there's an "oddbyte"?
> > 
> > If I simplify that whole construct, consuming in 16-bytes step
> > until there's only one left, then summing that one, in_cksum()
> > works for me.
> > 
> > Can someone please help me have a look?
> 
> There are other versions of in_cksum in our tree.
> Like: ./usr.sbin/ospfd/in_cksum.c
> 
> I'm surprised that the libsa code does no htons / ntohs conversions.
> Also after looking at the ospfd/in_cksum.c code I wonder if the htons /
> ntohs are actually reversed in that that code...

I copied ospfd's file, re-added the header includes, re-added const to
the pointer, adjusted the prototype for u_int16_t and size_t, and
replaced the fatal with a printf and return -1.  Why -1?  Well, the
checks always do if (in_cksum() != 0) { error(); }.  Unless they
create a packet, but I guess in that case I hope we don't create a
packet that's too big *in our bootloader*.

Since the implementation was replaced, taken from ospfd, I guess the
4th-clause can go as well?  I mean, there's no 4th-clause in ospfd and
I just copied the file.

This fixes my issue and works for me.

Opinions? ok?

Patrick

diff --git a/sys/lib/libsa/in_cksum.c b/sys/lib/libsa/in_cksum.c
index d3f2e6ac978..c4b12e01c04 100644
--- a/sys/lib/libsa/in_cksum.c
+++ b/sys/lib/libsa/in_cksum.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_cksum.c,v 1.5 2014/11/19 20:28:56 miod Exp $   */
+/* $OpenBSD: in_cksum.c,v 1.7 2014/07/20 20:27:19 tobias Exp $ */
 /* $NetBSD: in_cksum.c,v 1.3 1995/04/22 13:53:48 cgd Exp $ */
 
 /*
@@ -17,11 +17,7 @@
  * 2. Redistributions in binary form must reproduce the above copyright
  *notice, this list of conditions and the following disclaimer in the
  *documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Lawrence Berkeley Laboratory and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
+ * 3. Neither the name of the University nor the names of its contributors
  *may be used to endorse or promote products derived from this software
  *without specific prior written permission.
  *
@@ -56,35 +52,38 @@
  * code and should be modified for each CPU to be as fast as possible.
  * In particular, it should not be this one.
  */
-int
-in_cksum(const void *p, int len)
+u_int16_t
+in_cksum(const void *p, size_t l)
 {
-   int sum = 0, oddbyte = 0, v = 0;
+   unsigned int sum = 0;
+   int len;
const u_char *cp = p;
 
-   /* we assume < 2^16 bytes being summed */
-   while (len > 0) {
-   if (oddbyte) {
-   sum += v + *cp++;
-   len--;
+   /* ensure that < 2^16 bytes being summed */
+   if (l >= (1 << 16)) {
+   printf("in_cksum: packet too big\n");
+   return -1;
+   }
+   len = (int)l;
+
+   if (((long)cp & 1) == 0) {
+   while (len > 1) {
+   sum += htons(*(u_short *)cp);
+   cp += 2;
+   len -= 2;
}
-   if (((long)cp & 1) == 0) {
-   while ((len -= 2) >= 0) {
-   sum += *(const u_short *)cp;
-   cp += 2;
-   }
-   } else {
-   while ((len -= 2) >= 0) {
-   sum += *cp++ << 8;
-   sum += *cp++;
-   }
+   } else {
+   while (len > 1) {
+   sum += *cp++ << 8;
+   sum += *cp++;
+   len -= 2;
}
-   if ((oddbyte = len & 1) != 0)
-   v = *cp << 8;
}
-   if (oddbyte)
-   sum += v;
+   if (len == 1)
+

libsa's in_cksum() cannot handle payload of odd-length?

2020-05-18 Thread Patrick Wildt
Hi,

I was trying to tftpboot and had an issue with files of odd-length.
As it turns out, I think the in_cksum() that's called for UDP payload
cannot handle a payload length that's not aligned to 16 bytes.

I don't know how in_cksum() is supposed to work exactly, but it looks
like the first step is summing up all bytes.  The code is using 16-
byte blocks, apart from some oddbyte magic.

First of all, why is there a while loop around code that already
consumes the whole length?  That can be done in a single step
without the loop.  Why does it continue of there's an "oddbyte"?

If I simplify that whole construct, consuming in 16-bytes step
until there's only one left, then summing that one, in_cksum()
works for me.

Can someone please help me have a look?

Patrick

diff --git a/sys/lib/libsa/in_cksum.c b/sys/lib/libsa/in_cksum.c
index d3f2e6ac978..57ded38a7b7 100644
--- a/sys/lib/libsa/in_cksum.c
+++ b/sys/lib/libsa/in_cksum.c
@@ -59,31 +59,24 @@
 int
 in_cksum(const void *p, int len)
 {
-   int sum = 0, oddbyte = 0, v = 0;
const u_char *cp = p;
+   int sum = 0;
 
/* we assume < 2^16 bytes being summed */
-   while (len > 0) {
-   if (oddbyte) {
-   sum += v + *cp++;
-   len--;
-   }
+   while (len > 1) {
if (((long)cp & 1) == 0) {
-   while ((len -= 2) >= 0) {
-   sum += *(const u_short *)cp;
-   cp += 2;
-   }
+   sum += *(const u_short *)cp;
+   cp += 2;
} else {
-   while ((len -= 2) >= 0) {
-   sum += *cp++ << 8;
-   sum += *cp++;
-   }
+   sum += *cp++ << 8;
+   sum += *cp++;
}
-   if ((oddbyte = len & 1) != 0)
-   v = *cp << 8;
+   len -= 2;
+   }
+   if (len > 0) {
+   sum += *cp++;
+   len--;
}
-   if (oddbyte)
-   sum += v;
sum = (sum >> 16) + (sum & 0x); /* add in accumulated carries */
sum += sum >> 16;   /* add potential last carry */
return (0x & ~sum);



Re: sdmmc: CIS tuple can have empty body

2020-04-28 Thread Patrick Wildt
On Tue, Apr 28, 2020 at 11:16:43PM +0200, Patrick Wildt wrote:
> Hi,
> 
> on my i.MX8MM EVK there's a ath10k-based WiFi chip which we
> unfortunately do not support (yet?).  But the SD/MMC CIS parser
> complains:
> 
> sdmmc0: CIS parse error at 4136, tuple code 0x14, length 0
> manufacturer 0x0271, product 0x0701 at sdmmc0 function 1 not configured
> 
> It's not a transmission bug though, since I saw prints from a Linux
> dmesg on the web[0] stating something similar:
> 
> <4>mmc0: queuing unknown CIS tuple 0x01 (3 bytes)
> <4>mmc0: queuing unknown CIS tuple 0x1a (5 bytes)
> <4>mmc0: queuing unknown CIS tuple 0x1b (8 bytes)
> <4>mmc0: queuing unknown CIS tuple 0x14 (0 bytes)
> 
> I guess the ath10k-Chips use some vendor-specific tuples in the CIS
> structure.  The thing that our CIS parser complains about is the tuple
> without a length.
> 
> Section 16 of the SDIO Simplified Specification 3.0[1] describes the CIS
> formats, with Section 16.2 describing the Basic Tuple Format.  What our
> code calls "tpllen", the tuple body length, is called "link field" in
> the specification.
> 
> The specification explicitly says, that a empty tuple body is fine, by
> saying: "If the link field is 0, then the tuple body is empty."
> 
> Thus I propose that instead of complaining about that tuple, we just
> continue our job.  I guess sometimes the existance of a code is infor-
> mation enough.
> 
> ok?
> 
> Patrick
> 
> [0] 
> https://linuxlists.cc/l/9/linux-wireless/t/3226749/ath10k-sdio:_failed_to_load_firmware
> [1] 
> https://www.sdcard.org/downloads/pls/pdf/index.php?p=PartE1_SDIO_Simplified_Specification_Ver3.00.jpg=PartE1_SDIO_Simplified_Specification_Ver3.00.pdf=EN_SSE1

Actually it would be even better to just remove the check, since
then we would fall into the default case which, given SDMMC_DEBUG
is on, also lets us know of the unknown tuple:

sdmmc0: unknown tuple code 0x1, length 3
sdmmc0: unknown tuple code 0x22, length 4
sdmmc0: unknown tuple code 0x1a, length 5
sdmmc0: unknown tuple code 0x1b, length 8
sdmmc0: unknown tuple code 0x14, length 0
sdmmc0: unknown tuple code 0x22, length 42
sdmmc0: unknown tuple code 0x80, length 1
sdmmc0: unknown tuple code 0x81, length 1
sdmmc0: unknown tuple code 0x82, length 1

The individual switch-cases are checking tpllen properly, so there
is no harm.

ok?

Patrick

diff --git a/sys/dev/sdmmc/sdmmc_cis.c b/sys/dev/sdmmc/sdmmc_cis.c
index 21cf530b24f..70e5b6283a7 100644
--- a/sys/dev/sdmmc/sdmmc_cis.c
+++ b/sys/dev/sdmmc/sdmmc_cis.c
@@ -76,12 +76,6 @@ sdmmc_read_cis(struct sdmmc_function *sf, struct sdmmc_cis 
*cis)
continue;
 
tpllen = sdmmc_io_read_1(sf0, reg++);
-   if (tpllen == 0) {
-   printf("%s: CIS parse error at %d, "
-   "tuple code %#x, length %d\n",
-   DEVNAME(sf->sc), reg, tplcode, tpllen);
-   break;
-   }
 
switch (tplcode) {
case SD_IO_CISTPL_FUNCID:



sdmmc: CIS tuple can have empty body

2020-04-28 Thread Patrick Wildt
Hi,

on my i.MX8MM EVK there's a ath10k-based WiFi chip which we
unfortunately do not support (yet?).  But the SD/MMC CIS parser
complains:

sdmmc0: CIS parse error at 4136, tuple code 0x14, length 0
manufacturer 0x0271, product 0x0701 at sdmmc0 function 1 not configured

It's not a transmission bug though, since I saw prints from a Linux
dmesg on the web[0] stating something similar:

<4>mmc0: queuing unknown CIS tuple 0x01 (3 bytes)
<4>mmc0: queuing unknown CIS tuple 0x1a (5 bytes)
<4>mmc0: queuing unknown CIS tuple 0x1b (8 bytes)
<4>mmc0: queuing unknown CIS tuple 0x14 (0 bytes)

I guess the ath10k-Chips use some vendor-specific tuples in the CIS
structure.  The thing that our CIS parser complains about is the tuple
without a length.

Section 16 of the SDIO Simplified Specification 3.0[1] describes the CIS
formats, with Section 16.2 describing the Basic Tuple Format.  What our
code calls "tpllen", the tuple body length, is called "link field" in
the specification.

The specification explicitly says, that a empty tuple body is fine, by
saying: "If the link field is 0, then the tuple body is empty."

Thus I propose that instead of complaining about that tuple, we just
continue our job.  I guess sometimes the existance of a code is infor-
mation enough.

ok?

Patrick

[0] 
https://linuxlists.cc/l/9/linux-wireless/t/3226749/ath10k-sdio:_failed_to_load_firmware
[1] 
https://www.sdcard.org/downloads/pls/pdf/index.php?p=PartE1_SDIO_Simplified_Specification_Ver3.00.jpg=PartE1_SDIO_Simplified_Specification_Ver3.00.pdf=EN_SSE1

diff --git a/sys/dev/sdmmc/sdmmc_cis.c b/sys/dev/sdmmc/sdmmc_cis.c
index 21cf530b24f..09f3a70af40 100644
--- a/sys/dev/sdmmc/sdmmc_cis.c
+++ b/sys/dev/sdmmc/sdmmc_cis.c
@@ -76,12 +76,8 @@ sdmmc_read_cis(struct sdmmc_function *sf, struct sdmmc_cis 
*cis)
continue;
 
tpllen = sdmmc_io_read_1(sf0, reg++);
-   if (tpllen == 0) {
-   printf("%s: CIS parse error at %d, "
-   "tuple code %#x, length %d\n",
-   DEVNAME(sf->sc), reg, tplcode, tpllen);
-   break;
-   }
+   if (tpllen == 0)
+   continue;
 
switch (tplcode) {
case SD_IO_CISTPL_FUNCID:



Re: [patch] Check for -1 explicitly in getpeereid.c

2020-04-26 Thread Patrick Wildt
Hi,

I don't know userland very well, so I have a question.  In the middle of
2019 there have been plenty of changes in regards to changing checks of
syscalls from < 0 to a more strict == -1, like this one in isakmpd:


revision 1.26
date: 2019/06/28 13:32:44;  author: deraadt;  state: Exp;  lines: +2 -2;  
commitid: JJ6Ck4WTrgUiEjJp;
When system calls indicate an error they return -1, not some arbitrary
value < 0.  errno is only updated in this case.  Change all (most?)
callers of syscalls to follow this better, and let's see if this strictness
helps us in the future.


getsockopt(), I think, is also a system call.  And the manpage indicates
that a failure is always -1, and not some arbitrary number:

RETURN VALUES
 Upon successful completion, the value 0 is returned; otherwise the
 value -1 is returned and the global variable errno is set to indicate the
 error.

What is the difference between the diff in this mail, and the changes
done in the middle of last year?  getsockopt() isn't allowed to return
anything else but 0 and 1, right?  Though I guess the current check
(error != 0) is the one that also catches instances where getsockopt()
isn't behaving well, even though it shouldn't.  But then, with the -1
check, wouldn't we be catching more instances of syscalls misbehaving
if we checked for < -1?

Patrick

On Sun, Apr 26, 2020 at 02:45:54PM -0600, Theo de Raadt wrote:
> If it returns 50 then the creds structure is not valid, and can't be copied
> from.  It only returns valid creds *IF* success is indicated by 0.  But then
> you convert 50 to a return value of 0, and hide any indication that things
> went weird?
> 
> No way, I'm not buying your argument.   I think the code is making the
> correct choice now.
> 
> Martin Vahlensieck  wrote:
> 
> > Hi there
> > 
> > From the getsockopt(2) manual page says getsockopt(2) returns -1 on
> > error and 0 on success. Also getpeereid(3) only lists those 2 values.
> > This diff makes the return value check in getpeereid explicit. I guess
> > this is how it is done elsewhere in the tree (there is a commit turning
> > a bunch of "... < 0" to "== -1" I think this falls under that category).
> > 
> > Best,
> > 
> > Martin
> > 
> > Index: net/getpeereid.c
> > ===
> > RCS file: /cvs/src/lib/libc/net/getpeereid.c,v
> > retrieving revision 1.1
> > diff -u -p -r1.1 getpeereid.c
> > --- net/getpeereid.c1 Jul 2010 19:15:30 -   1.1
> > +++ net/getpeereid.c26 Apr 2020 20:28:50 -
> > @@ -28,7 +28,7 @@ getpeereid(int s, uid_t *euid, gid_t *eg
> >  
> > error = getsockopt(s, SOL_SOCKET, SO_PEERCRED,
> > , );
> > -   if (error)
> > +   if (error == -1)
> > return (error);
> > *euid = creds.uid;
> > *egid = creds.gid;
> > 
> 



coherent em(4) descriptor rings (to be able to run on my arm64 machine)

2020-04-26 Thread Patrick Wildt
Hi,

I have a HummingBoard Pulse, which is an NXP i.MX8MQ based board
featuring two ethernets, with the second ethernet being an em(4)
on a PCIe controller.

I had trouble getting it to work, but realized that the issue is the
descriptor ring coherency.  I looked into the code, tried to find if
there are incorrect flushes, or something else, but nothing worked.

Looking at the Linux driver I realized that their descriptor rings are
allocated coherent.  Some arm64 machines are fine with em(4), since the
PCIe controller is coherent, but on my machine it is not.  Explicitly
mapping the rings coherent made my machine happy, so I believe that
maybe the way that em(4) works, we need to make sure the rings are
coherent.

So I'd propose the following diff, which *only* makes the desciptor
rings coherent, the packets stay cached and fast.  This allows me to
push plenty of traffic through my machine!

This is a no-op on all x86, and on arm64-machines with coherent PCIe
controllers.

Opinions? ok?

Patrick

diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index aca6b4bb02f..27d0630bf9f 100644
--- a/sys/dev/pci/if_em.c
+++ b/sys/dev/pci/if_em.c
@@ -2113,7 +2113,7 @@ em_dma_malloc(struct em_softc *sc, bus_size_t size, 
struct em_dma_alloc *dma)
goto destroy;
 
r = bus_dmamem_map(sc->sc_dmat, >dma_seg, dma->dma_nseg, size,
-   >dma_vaddr, BUS_DMA_WAITOK);
+   >dma_vaddr, BUS_DMA_WAITOK | BUS_DMA_COHERENT);
if (r != 0)
goto free;
 



Re: usb(4): use cacheable buffers for data transfers (massive speedup)

2020-04-02 Thread Patrick Wildt
On Wed, Apr 01, 2020 at 12:23:53PM +0200, Patrick Wildt wrote:
> On Wed, Apr 01, 2020 at 12:04:25PM +0200, Patrick Wildt wrote:
> > On Wed, Apr 01, 2020 at 09:40:06AM +0200, Patrick Wildt wrote:
> > > On Wed, Apr 01, 2020 at 09:22:07AM +0200, Patrick Wildt wrote:
> > > > On Wed, Apr 01, 2020 at 04:47:10PM +1100, Jonathan Gray wrote:
> > > > > On Wed, Apr 01, 2020 at 12:58:23PM +1100, Jonathan Gray wrote:
> > > > > > On Wed, Mar 18, 2020 at 01:41:06PM +0100, Patrick Wildt wrote:
> > > > > > > On Wed, Mar 18, 2020 at 11:22:40AM +0100, Patrick Wildt wrote:
> > > > > > > > Hi,
> > > > > > > > 
> > > > > > > > I've spent a few days investigating why USB ethernet adapters 
> > > > > > > > are so
> > > > > > > > horribly slow on my ARMs.  Using dt(4) I realized that it was 
> > > > > > > > spending
> > > > > > > > most of its time in memcpy.  But, why?  As it turns out, all 
> > > > > > > > USB data
> > > > > > > > buffers are mapped COHERENT, which on some/most ARMs means 
> > > > > > > > uncached.
> > > > > > > > Using cached data buffers makes the performance rise from 20 
> > > > > > > > mbit/s to
> > > > > > > > 200 mbit/s.  Quite a difference.
> > > > > > > > 
> > > > > > > > sys/dev/usb/usb_mem.c:
> > > > > > > > error = bus_dmamem_map(tag, p->segs, p->nsegs, p->size,
> > > > > > > >>kaddr, 
> > > > > > > > BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
> > > > > > > > 
> > > > > > > > On x86, COHERENT is essentially a no-op.  On ARM, it depends on 
> > > > > > > > the SoC.
> > > > > > > > Some SoCs have cache-coherent USB controllers, some don't.  
> > > > > > > > Mine does
> > > > > > > > not, so mapping it COHERENT means uncached and thus slow.
> > > > > > > > 
> > > > > > > > Why do we do that?  Well, when the code was imported in 99, it 
> > > > > > > > was
> > > > > > > > already there.  Since then we have gained infrastructure for DMA
> > > > > > > > syncs in the USB stack, which I think are proper.
> > > > > > > > 
> > > > > > > > sys/dev/usb/usbdi.c - usbd_transfer() (before transfer)
> > > > > > > > 
> > > > > > > > if (!usbd_xfer_isread(xfer)) {
> > > > > > > > if ((xfer->flags & USBD_NO_COPY) == 0)
> > > > > > > > memcpy(KERNADDR(>dmabuf, 0), 
> > > > > > > > xfer->buffer,
> > > > > > > > xfer->length);
> > > > > > > > usb_syncmem(>dmabuf, 0, xfer->length,
> > > > > > > > BUS_DMASYNC_PREWRITE);
> > > > > > > > } else
> > > > > > > > usb_syncmem(>dmabuf, 0, xfer->length,
> > > > > > > > BUS_DMASYNC_PREREAD);
> > > > > > > > err = pipe->methods->transfer(xfer);
> > > > > > > > 
> > > > > > > > sys/dev/usb/usbdi.c - usb_transfer_complete() (after transfer)
> > > > > > > > 
> > > > > > > > if (xfer->actlen != 0) {
> > > > > > > > if (usbd_xfer_isread(xfer)) {
> > > > > > > > usb_syncmem(>dmabuf, 0, 
> > > > > > > > xfer->actlen,
> > > > > > > > BUS_DMASYNC_POSTREAD);
> > > > > > > > if (!(xfer->flags & USBD_NO_COPY))
> > > > > > > > memcpy(xfer->buffer, 
> > > > > > > > KERNADDR(>dmabuf, 0),
> > > > > > > > xfer->actlen);
> > > > > > > > } else
> > > > > > > > usb_syncmem(>dmabuf, 0, 
> 

Re: usb(4): use cacheable buffers for data transfers (massive speedup)

2020-04-01 Thread Patrick Wildt
On Wed, Apr 01, 2020 at 12:04:25PM +0200, Patrick Wildt wrote:
> On Wed, Apr 01, 2020 at 09:40:06AM +0200, Patrick Wildt wrote:
> > On Wed, Apr 01, 2020 at 09:22:07AM +0200, Patrick Wildt wrote:
> > > On Wed, Apr 01, 2020 at 04:47:10PM +1100, Jonathan Gray wrote:
> > > > On Wed, Apr 01, 2020 at 12:58:23PM +1100, Jonathan Gray wrote:
> > > > > On Wed, Mar 18, 2020 at 01:41:06PM +0100, Patrick Wildt wrote:
> > > > > > On Wed, Mar 18, 2020 at 11:22:40AM +0100, Patrick Wildt wrote:
> > > > > > > Hi,
> > > > > > > 
> > > > > > > I've spent a few days investigating why USB ethernet adapters are 
> > > > > > > so
> > > > > > > horribly slow on my ARMs.  Using dt(4) I realized that it was 
> > > > > > > spending
> > > > > > > most of its time in memcpy.  But, why?  As it turns out, all USB 
> > > > > > > data
> > > > > > > buffers are mapped COHERENT, which on some/most ARMs means 
> > > > > > > uncached.
> > > > > > > Using cached data buffers makes the performance rise from 20 
> > > > > > > mbit/s to
> > > > > > > 200 mbit/s.  Quite a difference.
> > > > > > > 
> > > > > > > sys/dev/usb/usb_mem.c:
> > > > > > >   error = bus_dmamem_map(tag, p->segs, p->nsegs, p->size,
> > > > > > >  >kaddr, 
> > > > > > > BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
> > > > > > > 
> > > > > > > On x86, COHERENT is essentially a no-op.  On ARM, it depends on 
> > > > > > > the SoC.
> > > > > > > Some SoCs have cache-coherent USB controllers, some don't.  Mine 
> > > > > > > does
> > > > > > > not, so mapping it COHERENT means uncached and thus slow.
> > > > > > > 
> > > > > > > Why do we do that?  Well, when the code was imported in 99, it was
> > > > > > > already there.  Since then we have gained infrastructure for DMA
> > > > > > > syncs in the USB stack, which I think are proper.
> > > > > > > 
> > > > > > > sys/dev/usb/usbdi.c - usbd_transfer() (before transfer)
> > > > > > > 
> > > > > > >   if (!usbd_xfer_isread(xfer)) {
> > > > > > >   if ((xfer->flags & USBD_NO_COPY) == 0)
> > > > > > >   memcpy(KERNADDR(>dmabuf, 0), xfer->buffer,
> > > > > > >   xfer->length);
> > > > > > >   usb_syncmem(>dmabuf, 0, xfer->length,
> > > > > > >   BUS_DMASYNC_PREWRITE);
> > > > > > >   } else
> > > > > > >   usb_syncmem(>dmabuf, 0, xfer->length,
> > > > > > >   BUS_DMASYNC_PREREAD);
> > > > > > >   err = pipe->methods->transfer(xfer);
> > > > > > > 
> > > > > > > sys/dev/usb/usbdi.c - usb_transfer_complete() (after transfer)
> > > > > > > 
> > > > > > >   if (xfer->actlen != 0) {
> > > > > > >   if (usbd_xfer_isread(xfer)) {
> > > > > > >   usb_syncmem(>dmabuf, 0, xfer->actlen,
> > > > > > >   BUS_DMASYNC_POSTREAD);
> > > > > > >   if (!(xfer->flags & USBD_NO_COPY))
> > > > > > >   memcpy(xfer->buffer, 
> > > > > > > KERNADDR(>dmabuf, 0),
> > > > > > >   xfer->actlen);
> > > > > > >   } else
> > > > > > >   usb_syncmem(>dmabuf, 0, xfer->actlen,
> > > > > > >   BUS_DMASYNC_POSTWRITE);
> > > > > > >   }
> > > > > > > 
> > > > > > > We cannot just remove COHERENT, since some drivers, like ehci(4), 
> > > > > > > use
> > > > > > > the same backend to allocate their rings.  And I can't vouch for 
> > > > > > > those
> > > > > > > drivers' sanity.
> > > > > > > 
> > > > > > > As a first step, I would like to go ahead with an

Re: usb(4): use cacheable buffers for data transfers (massive speedup)

2020-04-01 Thread Patrick Wildt
On Wed, Apr 01, 2020 at 09:40:06AM +0200, Patrick Wildt wrote:
> On Wed, Apr 01, 2020 at 09:22:07AM +0200, Patrick Wildt wrote:
> > On Wed, Apr 01, 2020 at 04:47:10PM +1100, Jonathan Gray wrote:
> > > On Wed, Apr 01, 2020 at 12:58:23PM +1100, Jonathan Gray wrote:
> > > > On Wed, Mar 18, 2020 at 01:41:06PM +0100, Patrick Wildt wrote:
> > > > > On Wed, Mar 18, 2020 at 11:22:40AM +0100, Patrick Wildt wrote:
> > > > > > Hi,
> > > > > > 
> > > > > > I've spent a few days investigating why USB ethernet adapters are so
> > > > > > horribly slow on my ARMs.  Using dt(4) I realized that it was 
> > > > > > spending
> > > > > > most of its time in memcpy.  But, why?  As it turns out, all USB 
> > > > > > data
> > > > > > buffers are mapped COHERENT, which on some/most ARMs means uncached.
> > > > > > Using cached data buffers makes the performance rise from 20 mbit/s 
> > > > > > to
> > > > > > 200 mbit/s.  Quite a difference.
> > > > > > 
> > > > > > sys/dev/usb/usb_mem.c:
> > > > > > error = bus_dmamem_map(tag, p->segs, p->nsegs, p->size,
> > > > > >>kaddr, 
> > > > > > BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
> > > > > > 
> > > > > > On x86, COHERENT is essentially a no-op.  On ARM, it depends on the 
> > > > > > SoC.
> > > > > > Some SoCs have cache-coherent USB controllers, some don't.  Mine 
> > > > > > does
> > > > > > not, so mapping it COHERENT means uncached and thus slow.
> > > > > > 
> > > > > > Why do we do that?  Well, when the code was imported in 99, it was
> > > > > > already there.  Since then we have gained infrastructure for DMA
> > > > > > syncs in the USB stack, which I think are proper.
> > > > > > 
> > > > > > sys/dev/usb/usbdi.c - usbd_transfer() (before transfer)
> > > > > > 
> > > > > > if (!usbd_xfer_isread(xfer)) {
> > > > > > if ((xfer->flags & USBD_NO_COPY) == 0)
> > > > > > memcpy(KERNADDR(>dmabuf, 0), xfer->buffer,
> > > > > > xfer->length);
> > > > > > usb_syncmem(>dmabuf, 0, xfer->length,
> > > > > > BUS_DMASYNC_PREWRITE);
> > > > > > } else
> > > > > > usb_syncmem(>dmabuf, 0, xfer->length,
> > > > > > BUS_DMASYNC_PREREAD);
> > > > > > err = pipe->methods->transfer(xfer);
> > > > > > 
> > > > > > sys/dev/usb/usbdi.c - usb_transfer_complete() (after transfer)
> > > > > > 
> > > > > > if (xfer->actlen != 0) {
> > > > > > if (usbd_xfer_isread(xfer)) {
> > > > > > usb_syncmem(>dmabuf, 0, xfer->actlen,
> > > > > > BUS_DMASYNC_POSTREAD);
> > > > > > if (!(xfer->flags & USBD_NO_COPY))
> > > > > > memcpy(xfer->buffer, 
> > > > > > KERNADDR(>dmabuf, 0),
> > > > > > xfer->actlen);
> > > > > > } else
> > > > > > usb_syncmem(>dmabuf, 0, xfer->actlen,
> > > > > > BUS_DMASYNC_POSTWRITE);
> > > > > > }
> > > > > > 
> > > > > > We cannot just remove COHERENT, since some drivers, like ehci(4), 
> > > > > > use
> > > > > > the same backend to allocate their rings.  And I can't vouch for 
> > > > > > those
> > > > > > drivers' sanity.
> > > > > > 
> > > > > > As a first step, I would like to go ahead with another solution, 
> > > > > > which
> > > > > > is based on a diff from Marius Strobl, who added those syncs in the
> > > > > > first place.  Essentially it splits the memory handling into 
> > > > > > cacheable
> > > > > > and non-cacheable blocks.  The USB data transfers and everyone who 
> > > > > > uses
> > > > >

Re: usb(4): use cacheable buffers for data transfers (massive speedup)

2020-04-01 Thread Patrick Wildt
On Wed, Apr 01, 2020 at 09:22:07AM +0200, Patrick Wildt wrote:
> On Wed, Apr 01, 2020 at 04:47:10PM +1100, Jonathan Gray wrote:
> > On Wed, Apr 01, 2020 at 12:58:23PM +1100, Jonathan Gray wrote:
> > > On Wed, Mar 18, 2020 at 01:41:06PM +0100, Patrick Wildt wrote:
> > > > On Wed, Mar 18, 2020 at 11:22:40AM +0100, Patrick Wildt wrote:
> > > > > Hi,
> > > > > 
> > > > > I've spent a few days investigating why USB ethernet adapters are so
> > > > > horribly slow on my ARMs.  Using dt(4) I realized that it was spending
> > > > > most of its time in memcpy.  But, why?  As it turns out, all USB data
> > > > > buffers are mapped COHERENT, which on some/most ARMs means uncached.
> > > > > Using cached data buffers makes the performance rise from 20 mbit/s to
> > > > > 200 mbit/s.  Quite a difference.
> > > > > 
> > > > > sys/dev/usb/usb_mem.c:
> > > > >   error = bus_dmamem_map(tag, p->segs, p->nsegs, p->size,
> > > > >  >kaddr, 
> > > > > BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
> > > > > 
> > > > > On x86, COHERENT is essentially a no-op.  On ARM, it depends on the 
> > > > > SoC.
> > > > > Some SoCs have cache-coherent USB controllers, some don't.  Mine does
> > > > > not, so mapping it COHERENT means uncached and thus slow.
> > > > > 
> > > > > Why do we do that?  Well, when the code was imported in 99, it was
> > > > > already there.  Since then we have gained infrastructure for DMA
> > > > > syncs in the USB stack, which I think are proper.
> > > > > 
> > > > > sys/dev/usb/usbdi.c - usbd_transfer() (before transfer)
> > > > > 
> > > > >   if (!usbd_xfer_isread(xfer)) {
> > > > >   if ((xfer->flags & USBD_NO_COPY) == 0)
> > > > >   memcpy(KERNADDR(>dmabuf, 0), xfer->buffer,
> > > > >   xfer->length);
> > > > >   usb_syncmem(>dmabuf, 0, xfer->length,
> > > > >   BUS_DMASYNC_PREWRITE);
> > > > >   } else
> > > > >   usb_syncmem(>dmabuf, 0, xfer->length,
> > > > >   BUS_DMASYNC_PREREAD);
> > > > >   err = pipe->methods->transfer(xfer);
> > > > > 
> > > > > sys/dev/usb/usbdi.c - usb_transfer_complete() (after transfer)
> > > > > 
> > > > >   if (xfer->actlen != 0) {
> > > > >   if (usbd_xfer_isread(xfer)) {
> > > > >   usb_syncmem(>dmabuf, 0, xfer->actlen,
> > > > >   BUS_DMASYNC_POSTREAD);
> > > > >   if (!(xfer->flags & USBD_NO_COPY))
> > > > >   memcpy(xfer->buffer, 
> > > > > KERNADDR(>dmabuf, 0),
> > > > >   xfer->actlen);
> > > > >   } else
> > > > >   usb_syncmem(>dmabuf, 0, xfer->actlen,
> > > > >   BUS_DMASYNC_POSTWRITE);
> > > > >   }
> > > > > 
> > > > > We cannot just remove COHERENT, since some drivers, like ehci(4), use
> > > > > the same backend to allocate their rings.  And I can't vouch for those
> > > > > drivers' sanity.
> > > > > 
> > > > > As a first step, I would like to go ahead with another solution, which
> > > > > is based on a diff from Marius Strobl, who added those syncs in the
> > > > > first place.  Essentially it splits the memory handling into cacheable
> > > > > and non-cacheable blocks.  The USB data transfers and everyone who 
> > > > > uses
> > > > > usbd_alloc_buffer() then use cacheable buffers, while code like 
> > > > > ehci(4)
> > > > > still don't.  This is a bit of a safer approach imho, since we don't
> > > > > hurt the controller drivers, but speed up the data buffers.
> > > > > 
> > > > > Once we have verified that there are no regressions, we can adjust
> > > > > ehci(4) and the like, add proper syncs, make sure they still work as
> > > > > well as before, and maybe then back this out again.
> > > > >

Re: usb(4): use cacheable buffers for data transfers (massive speedup)

2020-04-01 Thread Patrick Wildt
On Wed, Apr 01, 2020 at 04:47:10PM +1100, Jonathan Gray wrote:
> On Wed, Apr 01, 2020 at 12:58:23PM +1100, Jonathan Gray wrote:
> > On Wed, Mar 18, 2020 at 01:41:06PM +0100, Patrick Wildt wrote:
> > > On Wed, Mar 18, 2020 at 11:22:40AM +0100, Patrick Wildt wrote:
> > > > Hi,
> > > > 
> > > > I've spent a few days investigating why USB ethernet adapters are so
> > > > horribly slow on my ARMs.  Using dt(4) I realized that it was spending
> > > > most of its time in memcpy.  But, why?  As it turns out, all USB data
> > > > buffers are mapped COHERENT, which on some/most ARMs means uncached.
> > > > Using cached data buffers makes the performance rise from 20 mbit/s to
> > > > 200 mbit/s.  Quite a difference.
> > > > 
> > > > sys/dev/usb/usb_mem.c:
> > > > error = bus_dmamem_map(tag, p->segs, p->nsegs, p->size,
> > > >>kaddr, 
> > > > BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
> > > > 
> > > > On x86, COHERENT is essentially a no-op.  On ARM, it depends on the SoC.
> > > > Some SoCs have cache-coherent USB controllers, some don't.  Mine does
> > > > not, so mapping it COHERENT means uncached and thus slow.
> > > > 
> > > > Why do we do that?  Well, when the code was imported in 99, it was
> > > > already there.  Since then we have gained infrastructure for DMA
> > > > syncs in the USB stack, which I think are proper.
> > > > 
> > > > sys/dev/usb/usbdi.c - usbd_transfer() (before transfer)
> > > > 
> > > > if (!usbd_xfer_isread(xfer)) {
> > > > if ((xfer->flags & USBD_NO_COPY) == 0)
> > > > memcpy(KERNADDR(>dmabuf, 0), xfer->buffer,
> > > > xfer->length);
> > > > usb_syncmem(>dmabuf, 0, xfer->length,
> > > > BUS_DMASYNC_PREWRITE);
> > > > } else
> > > > usb_syncmem(>dmabuf, 0, xfer->length,
> > > > BUS_DMASYNC_PREREAD);
> > > > err = pipe->methods->transfer(xfer);
> > > > 
> > > > sys/dev/usb/usbdi.c - usb_transfer_complete() (after transfer)
> > > > 
> > > > if (xfer->actlen != 0) {
> > > > if (usbd_xfer_isread(xfer)) {
> > > > usb_syncmem(>dmabuf, 0, xfer->actlen,
> > > > BUS_DMASYNC_POSTREAD);
> > > > if (!(xfer->flags & USBD_NO_COPY))
> > > > memcpy(xfer->buffer, 
> > > > KERNADDR(>dmabuf, 0),
> > > > xfer->actlen);
> > > > } else
> > > > usb_syncmem(>dmabuf, 0, xfer->actlen,
> > > > BUS_DMASYNC_POSTWRITE);
> > > > }
> > > > 
> > > > We cannot just remove COHERENT, since some drivers, like ehci(4), use
> > > > the same backend to allocate their rings.  And I can't vouch for those
> > > > drivers' sanity.
> > > > 
> > > > As a first step, I would like to go ahead with another solution, which
> > > > is based on a diff from Marius Strobl, who added those syncs in the
> > > > first place.  Essentially it splits the memory handling into cacheable
> > > > and non-cacheable blocks.  The USB data transfers and everyone who uses
> > > > usbd_alloc_buffer() then use cacheable buffers, while code like ehci(4)
> > > > still don't.  This is a bit of a safer approach imho, since we don't
> > > > hurt the controller drivers, but speed up the data buffers.
> > > > 
> > > > Once we have verified that there are no regressions, we can adjust
> > > > ehci(4) and the like, add proper syncs, make sure they still work as
> > > > well as before, and maybe then back this out again.
> > > > 
> > > > Keep note that this is all a no-op on X86, but all the other archs will
> > > > profit from this.
> > > > 
> > > > ok?
> > > > 
> > > > Patrick
> > > 
> > > Update diff with inverted logic.  kettenis@ argues that we should
> > > invert the logic, and those who need COHERENT memory should ask
> > > for that explicitly, since for

Re: usb(4): use cacheable buffers for data transfers (massive speedup)

2020-03-18 Thread Patrick Wildt
On Wed, Mar 18, 2020 at 11:22:40AM +0100, Patrick Wildt wrote:
> Hi,
> 
> I've spent a few days investigating why USB ethernet adapters are so
> horribly slow on my ARMs.  Using dt(4) I realized that it was spending
> most of its time in memcpy.  But, why?  As it turns out, all USB data
> buffers are mapped COHERENT, which on some/most ARMs means uncached.
> Using cached data buffers makes the performance rise from 20 mbit/s to
> 200 mbit/s.  Quite a difference.
> 
> sys/dev/usb/usb_mem.c:
>   error = bus_dmamem_map(tag, p->segs, p->nsegs, p->size,
>  >kaddr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
> 
> On x86, COHERENT is essentially a no-op.  On ARM, it depends on the SoC.
> Some SoCs have cache-coherent USB controllers, some don't.  Mine does
> not, so mapping it COHERENT means uncached and thus slow.
> 
> Why do we do that?  Well, when the code was imported in 99, it was
> already there.  Since then we have gained infrastructure for DMA
> syncs in the USB stack, which I think are proper.
> 
> sys/dev/usb/usbdi.c - usbd_transfer() (before transfer)
> 
>   if (!usbd_xfer_isread(xfer)) {
>   if ((xfer->flags & USBD_NO_COPY) == 0)
>   memcpy(KERNADDR(>dmabuf, 0), xfer->buffer,
>   xfer->length);
>   usb_syncmem(>dmabuf, 0, xfer->length,
>   BUS_DMASYNC_PREWRITE);
>   } else
>   usb_syncmem(>dmabuf, 0, xfer->length,
>   BUS_DMASYNC_PREREAD);
>   err = pipe->methods->transfer(xfer);
> 
> sys/dev/usb/usbdi.c - usb_transfer_complete() (after transfer)
> 
>   if (xfer->actlen != 0) {
>   if (usbd_xfer_isread(xfer)) {
>   usb_syncmem(>dmabuf, 0, xfer->actlen,
>   BUS_DMASYNC_POSTREAD);
>   if (!(xfer->flags & USBD_NO_COPY))
>   memcpy(xfer->buffer, KERNADDR(>dmabuf, 0),
>   xfer->actlen);
>   } else
>   usb_syncmem(>dmabuf, 0, xfer->actlen,
>   BUS_DMASYNC_POSTWRITE);
>   }
> 
> We cannot just remove COHERENT, since some drivers, like ehci(4), use
> the same backend to allocate their rings.  And I can't vouch for those
> drivers' sanity.
> 
> As a first step, I would like to go ahead with another solution, which
> is based on a diff from Marius Strobl, who added those syncs in the
> first place.  Essentially it splits the memory handling into cacheable
> and non-cacheable blocks.  The USB data transfers and everyone who uses
> usbd_alloc_buffer() then use cacheable buffers, while code like ehci(4)
> still don't.  This is a bit of a safer approach imho, since we don't
> hurt the controller drivers, but speed up the data buffers.
> 
> Once we have verified that there are no regressions, we can adjust
> ehci(4) and the like, add proper syncs, make sure they still work as
> well as before, and maybe then back this out again.
> 
> Keep note that this is all a no-op on X86, but all the other archs will
> profit from this.
> 
> ok?
> 
> Patrick

Update diff with inverted logic.  kettenis@ argues that we should
invert the logic, and those who need COHERENT memory should ask
for that explicitly, since for bus_dmamem_map() it also needs to
be passed explicitly.  This also points out all those users that
use usb_allocmem() internally, where we might want to have a look
if COHERENT is actually needed or not, or if it can be refactored
in another way.

diff --git a/sys/dev/usb/dwc2/dwc2.c b/sys/dev/usb/dwc2/dwc2.c
index 6f035467213..099dfa26da1 100644
--- a/sys/dev/usb/dwc2/dwc2.c
+++ b/sys/dev/usb/dwc2/dwc2.c
@@ -473,6 +473,7 @@ dwc2_open(struct usbd_pipe *pipe)
switch (xfertype) {
case UE_CONTROL:
pipe->methods = _device_ctrl_methods;
+   dpipe->req_dma.flags |= USB_DMA_COHERENT;
err = usb_allocmem(>sc_bus, sizeof(usb_device_request_t),
0, >req_dma);
if (err)
diff --git a/sys/dev/usb/dwc2/dwc2_hcd.c b/sys/dev/usb/dwc2/dwc2_hcd.c
index 7e5c91481d5..d44e3196e61 100644
--- a/sys/dev/usb/dwc2/dwc2_hcd.c
+++ b/sys/dev/usb/dwc2/dwc2_hcd.c
@@ -679,6 +679,7 @@ STATIC int dwc2_hc_setup_align_buf(struct dwc2_hsotg 
*hsotg, struct dwc2_qh *qh,
 
qh->dw_align_buf = NULL;
qh->dw_align_buf_dma = 0;
+   qh->dw_align_buf_usbdma.flags |= USB_DMA_COHERENT;
err = usb_allocmem(>hsotg_sc->sc_bus, buf_size, buf_size,
   >dw_align_buf_usbdma);
if (!err) {
@@ -2267,6 +2268,7 @@ int dwc2_hcd_

usb(4): use cacheable buffers for data transfers (massive speedup)

2020-03-18 Thread Patrick Wildt
Hi,

I've spent a few days investigating why USB ethernet adapters are so
horribly slow on my ARMs.  Using dt(4) I realized that it was spending
most of its time in memcpy.  But, why?  As it turns out, all USB data
buffers are mapped COHERENT, which on some/most ARMs means uncached.
Using cached data buffers makes the performance rise from 20 mbit/s to
200 mbit/s.  Quite a difference.

sys/dev/usb/usb_mem.c:
error = bus_dmamem_map(tag, p->segs, p->nsegs, p->size,
   >kaddr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);

On x86, COHERENT is essentially a no-op.  On ARM, it depends on the SoC.
Some SoCs have cache-coherent USB controllers, some don't.  Mine does
not, so mapping it COHERENT means uncached and thus slow.

Why do we do that?  Well, when the code was imported in 99, it was
already there.  Since then we have gained infrastructure for DMA
syncs in the USB stack, which I think are proper.

sys/dev/usb/usbdi.c - usbd_transfer() (before transfer)

if (!usbd_xfer_isread(xfer)) {
if ((xfer->flags & USBD_NO_COPY) == 0)
memcpy(KERNADDR(>dmabuf, 0), xfer->buffer,
xfer->length);
usb_syncmem(>dmabuf, 0, xfer->length,
BUS_DMASYNC_PREWRITE);
} else
usb_syncmem(>dmabuf, 0, xfer->length,
BUS_DMASYNC_PREREAD);
err = pipe->methods->transfer(xfer);

sys/dev/usb/usbdi.c - usb_transfer_complete() (after transfer)

if (xfer->actlen != 0) {
if (usbd_xfer_isread(xfer)) {
usb_syncmem(>dmabuf, 0, xfer->actlen,
BUS_DMASYNC_POSTREAD);
if (!(xfer->flags & USBD_NO_COPY))
memcpy(xfer->buffer, KERNADDR(>dmabuf, 0),
xfer->actlen);
} else
usb_syncmem(>dmabuf, 0, xfer->actlen,
BUS_DMASYNC_POSTWRITE);
}

We cannot just remove COHERENT, since some drivers, like ehci(4), use
the same backend to allocate their rings.  And I can't vouch for those
drivers' sanity.

As a first step, I would like to go ahead with another solution, which
is based on a diff from Marius Strobl, who added those syncs in the
first place.  Essentially it splits the memory handling into cacheable
and non-cacheable blocks.  The USB data transfers and everyone who uses
usbd_alloc_buffer() then use cacheable buffers, while code like ehci(4)
still don't.  This is a bit of a safer approach imho, since we don't
hurt the controller drivers, but speed up the data buffers.

Once we have verified that there are no regressions, we can adjust
ehci(4) and the like, add proper syncs, make sure they still work as
well as before, and maybe then back this out again.

Keep note that this is all a no-op on X86, but all the other archs will
profit from this.

ok?

Patrick

diff --git a/sys/dev/usb/usb_mem.c b/sys/dev/usb/usb_mem.c
index c65906b43f4..95993093b5a 100644
--- a/sys/dev/usb/usb_mem.c
+++ b/sys/dev/usb/usb_mem.c
@@ -72,7 +72,7 @@ struct usb_frag_dma {
 };
 
 usbd_statususb_block_allocmem(bus_dma_tag_t, size_t, size_t,
-   struct usb_dma_block **);
+   struct usb_dma_block **, int);
 void   usb_block_freemem(struct usb_dma_block *);
 
 LIST_HEAD(, usb_dma_block) usb_blk_freelist =
@@ -84,7 +84,7 @@ LIST_HEAD(, usb_frag_dma) usb_frag_freelist =
 
 usbd_status
 usb_block_allocmem(bus_dma_tag_t tag, size_t size, size_t align,
-struct usb_dma_block **dmap)
+struct usb_dma_block **dmap, int cacheable)
 {
int error;
 struct usb_dma_block *p;
@@ -96,7 +96,8 @@ usb_block_allocmem(bus_dma_tag_t tag, size_t size, size_t 
align,
s = splusb();
/* First check the free list. */
for (p = LIST_FIRST(_blk_freelist); p; p = LIST_NEXT(p, next)) {
-   if (p->tag == tag && p->size >= size && p->align >= align) {
+   if (p->tag == tag && p->size >= size && p->align >= align &&
+   p->cacheable == cacheable) {
LIST_REMOVE(p, next);
usb_blk_nfree--;
splx(s);
@@ -116,6 +117,7 @@ usb_block_allocmem(bus_dma_tag_t tag, size_t size, size_t 
align,
p->tag = tag;
p->size = size;
p->align = align;
+   p->cacheable = cacheable;
error = bus_dmamem_alloc(tag, p->size, align, 0,
 p->segs, nitems(p->segs),
 >nsegs, BUS_DMA_NOWAIT);
@@ -123,7 +125,8 @@ usb_block_allocmem(bus_dma_tag_t tag, size_t size, size_t 
align,
goto free0;
 
error = bus_dmamem_map(tag, p->segs, p->nsegs, p->size,
-  >kaddr, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
+  >kaddr, BUS_DMA_NOWAIT | (cacheable ? 0 :
+  

Re: Fix brightness control on ASUS 1005PXD

2020-03-16 Thread Patrick Wildt
On Sat, Mar 14, 2020 at 04:28:26AM +0100, Alexandre Ratchov wrote:
> On ASUS 1001PXD, _BQC returns an out of range value which makes
> acpivout_get_brightness() return -1, in turn breaking the
> display.brightness control (wsconsctl displays a mangled value).
> 
> This diff ignores the out of range value and makes the brighness
> control just work again.
> 
> OK?

With the current code _BQC is only called on attach, where we
probably want a value higher than the lowest one.  I wonder if
maybe we should move this check into the attach functions, and
in case of an error like this, set a reasonable brightness?

Otherwise, if we want to do that in acpivout_get_brightness(),
I guess we can update acpivout_select_brightness() and its caller
to remove the check for -1, since there will be no -1 anymore?

> Index: acpivout.c
> ===
> RCS file: /cvs/src/sys/dev/acpi/acpivout.c,v
> retrieving revision 1.19
> diff -u -p -r1.19 acpivout.c
> --- acpivout.c8 Feb 2020 19:08:17 -   1.19
> +++ acpivout.c14 Mar 2020 03:19:02 -
> @@ -227,8 +227,10 @@ acpivout_get_brightness(struct acpivout_
>   aml_freevalue();
>   DPRINTF(("%s: BQC = %d\n", DEVNAME(sc), level));
>  
> - if (level < sc->sc_bcl[0] || level > sc->sc_bcl[sc->sc_bcl_len -1])
> - level = -1;
> + if (level < sc->sc_bcl[0])
> + level = sc->sc_bcl[0];
> + else if (level > sc->sc_bcl[sc->sc_bcl_len - 1])
> + level = sc->sc_bcl[sc->sc_bcl_len - 1];
>  
>   return (level);
>  }
> 



Re: New bwfm device (bcm43341)

2020-03-13 Thread Patrick Wildt
On Fri, Mar 13, 2020 at 05:54:01PM +0100, Rob Schmersel wrote:
> On Fri, 13 Mar 2020 16:31:18 +0100
> Patrick Wildt  wrote:
> > Thanks for the diff!  Since Linux uses the same firmware (43340) for
> > both 43340 and 43341, I commited the diff slightly differently to
> > follow their scheme.  Thus there's no need for a symbolic link.
> > 
> > Patrick
> 
> Reason I had it as a separate identifier is that the NVRAM file I
> found for the 43341 chip was different compared to the 43340 chip
> Might be a slump 
> 
> BR/Rob

Yeah, but the NVRAM is highly specific anyway, as I explained in your
NVRAM thread on misc. :)

Patrick



Re: New bwfm device (bcm43341)

2020-03-13 Thread Patrick Wildt
On Fri, Mar 13, 2020 at 02:49:33PM +0100, Rob Schmersel wrote:
> Hi,
> 
> I got a new toy to play with recently which uses a bcm43341 wireless
> chipset. This chipset is the same as the bcm43340 apart from an
> additional nfc mode and can re-use the brcmfmac43340-sdio.bin firmware.
> (I simply added a symbolic link from firmware supplied in the 
> bwfm-firmware package)
> 
> In order to get the chipset recognized however I needed to make some
> changes as attached

Thanks for the diff!  Since Linux uses the same firmware (43340) for
both 43340 and 43341, I commited the diff slightly differently to
follow their scheme.  Thus there's no need for a symbolic link.

Patrick

Index: ic/bwfmvar.h
===
RCS file: /cvs/src/sys/dev/ic/bwfmvar.h,v
retrieving revision 1.18
diff -u -p -u -r1.18 bwfmvar.h
--- ic/bwfmvar.h6 Mar 2020 08:41:57 -   1.18
+++ ic/bwfmvar.h13 Mar 2020 15:28:04 -
@@ -27,6 +27,7 @@
 #define BRCM_CC_4330_CHIP_ID   0x4330
 #define BRCM_CC_4334_CHIP_ID   0x4334
 #define BRCM_CC_43340_CHIP_ID  43340
+#define BRCM_CC_43341_CHIP_ID  43341
 #define BRCM_CC_43362_CHIP_ID  43362
 #define BRCM_CC_4335_CHIP_ID   0x4335
 #define BRCM_CC_4339_CHIP_ID   0x4339
Index: sdmmc/if_bwfm_sdio.c
===
RCS file: /cvs/src/sys/dev/sdmmc/if_bwfm_sdio.c,v
retrieving revision 1.33
diff -u -p -u -r1.33 if_bwfm_sdio.c
--- sdmmc/if_bwfm_sdio.c7 Mar 2020 09:56:46 -   1.33
+++ sdmmc/if_bwfm_sdio.c13 Mar 2020 15:28:04 -
@@ -372,6 +372,7 @@ bwfm_sdio_preinit(struct bwfm_softc *bwf
chip = "43455";
break;
case BRCM_CC_43340_CHIP_ID:
+   case BRCM_CC_43341_CHIP_ID:
chip = "43340";
break;
case BRCM_CC_4335_CHIP_ID:



com(4) at pci

2020-03-03 Thread Patrick Wildt
Hi,

I would like to use the serial ports on the Apollo Lake machine on
my desk.  My first attempt was adjusting puc(4), but then I realized
that this would bloat puc(4) too much.

Intel has been removing legacy I/O-Ports on recent machines.  I think
that started with the Skylake PCH, which added the LPSS (Low Power
Subsystem).  Now the LPSS is used for three different kind of con-
trollers:  I2C, UART, SPI.

Each LPSS controller contain the actual device, and some registers to
control clocks, resets, etc.  These private registers need to be saved
and restored upon suspend/resume.  Also we should read the current
clock settings to calculate the frequency supplied to the device.

So the dance for the LPSS is the same for all three types of contro-
llers, and not surprisingly our dwiic@pci attachment driver already
implements a less sophisticated version of what is in the attached
diff.  Anyway, dwiic@pci is also only for the Intel LPSS-based I2C.

The UART is also the Synopsys Designware version, which means we can
have com(4) attach to it with the same options as we use on all those
ARM boards with a Designware based com(4).

So my second attempt was writing dwuart(4) with com(4) attaching at
dwuart(4).  kettenis@ argued it might be better to just implement it
as com@pci, which is the third attempt that you can read here.

Feedback?

Patrick

diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
index e64388b5815..7312452c046 100644
--- a/sys/arch/amd64/conf/GENERIC
+++ b/sys/arch/amd64/conf/GENERIC
@@ -338,6 +338,7 @@ bwfm*   at uhub?# Broadcom FullMAC
 
 puc*   at pci? # PCI "universal" communication device
 com*   at cardbus?
+com*   at pci?
 
 sdhc*  at pci? # SD Host Controller
 sdmmc* at sdhc?# SD/MMC bus
diff --git a/sys/dev/pci/com_pci.c b/sys/dev/pci/com_pci.c
new file mode 100644
index 000..cfb6e238bea
--- /dev/null
+++ b/sys/dev/pci/com_pci.c
@@ -0,0 +1,242 @@
+/* $OpenBSD$ */
+/*
+ * Copyright (c) 2020 Patrick Wildt 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+#define com_usr 31 /* Synopsys DesignWare UART */
+
+/* Intel Low Power Subsystem */
+#define LPSS_CLK   0x200
+#define  LPSS_CLK_GATE (1 << 0)
+#define  LPSS_CLK_MDIV_SHIFT   1
+#define  LPSS_CLK_MDIV_MASK0x3fff
+#define  LPSS_CLK_NDIV_SHIFT   16
+#define  LPSS_CLK_NDIV_MASK0x3fff
+#define  LPSS_CLK_UPDATE   (1U << 31)
+#define LPSS_RESETS0x204
+#define  LPSS_RESETS_FUNC  (3 << 0)
+#define  LPSS_RESETS_IDMA  (1 << 2)
+#define LPSS_ACTIVELTR 0x210
+#define LPSS_IDLELTR   0x214
+#define  LPSS_LTR_VALUE_MASK   (0x3ff << 0)
+#define  LPSS_LTR_SCALE_MASK   (0x3 << 10)
+#define  LPSS_LTR_SCALE_1US(2 << 10)
+#define  LPSS_LTR_SCALE_32US   (3 << 10)
+#define  LPSS_LTR_REQ  (1 << 15)
+#define LPSS_SSP   0x220
+#define  LPSS_SSP_DIS_DMA_FIN  (1 << 0)
+#define LPSS_REMAP_ADDR0x240
+#define LPSS_CAPS  0x2fc
+#define  LPSS_CAPS_TYPE_I2C(0 << 4)
+#define  LPSS_CAPS_TYPE_UART   (1 << 4)
+#define  LPSS_CAPS_TYPE_SPI(2 << 4)
+#define  LPSS_CAPS_TYPE_MASK   (0xf << 4)
+#define  LPSS_CAPS_NO_IDMA (1 << 8)
+
+#define LPSS_REG_OFF   0x200
+#define LPSS_REG_SIZE  0x100
+#define LPSS_REG_NUM   (LPSS_REG_SIZE / sizeof(uint32_t))
+
+#define HREAD4(sc, reg)
\
+   (bus_space_read_4((sc)->sc.sc_iot, (sc)->sc.sc_ioh, (reg)))
+#define HWRITE4(sc, reg, val)  \
+   bus_space_write_4((sc)->sc.sc_iot, (sc)->sc.sc_ioh, (reg), (val))
+#define HSET4(sc, reg, bits)   \
+   HWRITE4((sc), (reg), HREAD4((sc), (reg)) | (bits))
+#define HCLR4(sc, reg, bits)

puc(4): 64-bit BARs

2020-03-02 Thread Patrick Wildt
Hi,

as it turns out, puc(4) has trouble with 64-bit BARs.  The issue is that
puc(4) tries to map every BAR before doing anything else.  While iter-
ating over the BARs it assumes the next BAR is always 4 bytes after the
other.  For 64-bit BARs that's wrong.  On a device with a 64-bit BAR, it
will map the BAR correctly, and then using the 0x4 offset try to map an-
other BAR, thus breaking the previously correctly mapped bar.

Now I'm not sure this is the best fix, but I think the easiest way is to
just skip that particular entry.  Thus, with two 64-bit BARs, sc->sc_bar
mappings[1] and [3] will be empty.  That's fine since the pucdata.c
entries reference the absolute BAR address, like 0x10 and 0x18, and the
mapping to the index of the array is done using that absolute value:

#define PUC_PORT_BAR_INDEX(bar) (((bar) - PCI_MAPREG_START) / 4)

bar = PUC_PORT_BAR_INDEX(desc->ports[i].bar);
if (!sc->sc_bar_mappings[bar].mapped) {
...

Feedback?

Patrick

diff --git a/sys/dev/pci/puc.c b/sys/dev/pci/puc.c
index 2c5f3065177..7ec25ecaad2 100644
--- a/sys/dev/pci/puc.c
+++ b/sys/dev/pci/puc.c
@@ -163,8 +163,11 @@ puc_pci_attach(struct device *parent, struct device *self, 
void *aux)
0, >sc_bar_mappings[i].t, >sc_bar_mappings[i].h,
>sc_bar_mappings[i].a, >sc_bar_mappings[i].s, 0)
  == 0);
-   if (sc->sc_bar_mappings[i].mapped)
+   if (sc->sc_bar_mappings[i].mapped) {
+   if (type == PCI_MAPREG_MEM_TYPE_64BIT)
+   i++;
continue;
+   }
 
 #if NCOM > 0
/*
@@ -184,6 +187,8 @@ puc_pci_attach(struct device *parent, struct device *self, 
void *aux)
sc->sc_bar_mappings[i].h = comconsioh;
sc->sc_bar_mappings[i].s = COM_NPORTS;
sc->sc_bar_mappings[i].mapped = 1;
+   if (type == PCI_MAPREG_MEM_TYPE_64BIT)
+   i++;
continue;
}
 #endif



Re: [PATCH] Gemini Lake SoC pcidevs and eMMC

2020-02-04 Thread Patrick Wildt
On Wed, Jan 02, 2019 at 08:11:25PM -0500, James Hastings wrote:
> Hello tech@
> 
> I would like to add PCI devices for latest Intel SoC (Gemini Lake).
> 
> Included a patch for sdhc(4) too that depends on this to enable eMMC.
> The Intel eMMC controller does not like bus power going to 0V. There
> may be other systems (Apollo Lake) that need this quirk too.
> 
> With both patches I am booting from internal eMMC on HP Stream 14.
> 
> Comments? ok?

Looks like we forgot this one year old diff.  I think the pcidevs
change is probably fine.  I will cross-check it and put it in.

For the sdhc change the diff doesn't apply anymore since we added
the same if-condition for 100series and apollo lake already.  I
guess it's time to add gemini lake there as well.

Patrick

> OpenBSD 6.4-current (GENERIC.MP) #22: Wed Jan  2 13:36:31 EST 2019
> ti...@sandisk.my.domain:/usr/src/sys/arch/amd64/compile/GENERIC.MP
> real mem = 4102090752 (3912MB)
> avail mem = 3968520192 (3784MB)
> mpath0 at root
> scsibus0 at mpath0: 256 targets
> mainbus0 at root
> bios0 at mainbus0: SMBIOS rev. 3.0 @ 0x75e02000 (36 entries)
> bios0: vendor Insyde version "F.02" date 05/23/2018
> bios0: HP HP Stream Laptop 14-cb1XX
> acpi0 at bios0: rev 2
> acpi0: sleep states S0 S3 S4 S5
> acpi0: tables DSDT FACP UEFI IHIS UEFI SSDT TPM2 SSDT SSDT MSDM BDAT
> DBG2 DBGP HPET LPIT APIC MCFG NPKT PRAM WSMT SSDT SSDT SSDT SSDT SSDT
> SSDT SSDT FPDT WDAT BGRT
> acpi0: wakeup devices PXSX(S4) RP01(S4) PXSX(S4) RP02(S4) PXSX(S4)
> RP03(S4) PXSX(S4) RP04(S4) PXSX(S4) RP05(S4) PXSX(S4) RP06(S4) XHC_(S4)
> HDAS(S3)
> acpitimer0 at acpi0: 3579545 Hz, 24 bits
> acpihpet0 at acpi0: 1920 Hz
> acpimadt0 at acpi0 addr 0xfee0: PC-AT compat
> cpu0 at mainbus0: apid 0 (boot processor)
> cpu0: Intel(R) Celeron(R) N4000 CPU @ 1.10GHz, 1097.30 MHz, 06-7a-01
> cpu0:
> FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,CX16,xTPR,PDCM,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,FSGSBASE,SGX,SMEP,ERMS,MPX,RDSEED,SMAP,CLFLUSHOPT,PT,SHA,UMIP,IBRS,IBPB,STIBP,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES,MELTDOWN
> cpu0: 4MB 64b/line 16-way L2 cache
> cpu0: smt 0, core 0, package 0
> mtrr: Pentium Pro MTRR support, 10 var ranges, 88 fixed ranges
> cpu0: apic clock running at 19MHz
> cpu0: mwait min=64, max=64, C-substates=0.2.0.2.4.2.1.1, IBE
> cpu1 at mainbus0: apid 2 (application processor)
> cpu1: Intel(R) Celeron(R) N4000 CPU @ 1.10GHz, 1096.98 MHz, 06-7a-01
> cpu1:
> FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,APIC,SEP,MTRR,PGE,MCA,CMOV,PAT,PSE36,CFLUSH,DS,ACPI,MMX,FXSR,SSE,SSE2,SS,HTT,TM,PBE,SSE3,PCLMUL,DTES64,MWAIT,DS-CPL,VMX,EST,TM2,SSSE3,SDBG,CX16,xTPR,PDCM,SSE4.1,SSE4.2,x2APIC,MOVBE,POPCNT,DEADLINE,AES,XSAVE,RDRAND,NXE,PAGE1GB,RDTSCP,LONG,LAHF,3DNOWP,PERF,ITSC,FSGSBASE,SGX,SMEP,ERMS,MPX,RDSEED,SMAP,CLFLUSHOPT,PT,SHA,UMIP,IBRS,IBPB,STIBP,SENSOR,ARAT,XSAVEOPT,XSAVEC,XGETBV1,XSAVES,MELTDOWN
> cpu1: 4MB 64b/line 16-way L2 cache
> cpu1: smt 0, core 1, package 0
> ioapic0 at mainbus0: apid 1 pa 0xfec0, version 20, 120 pins
> acpimcfg0 at acpi0
> acpimcfg0: addr 0xe000, bus 0-63
> acpiprt0 at acpi0: bus 0 (PCI0)
> acpiprt1 at acpi0: bus -1 (RP01)
> acpiprt2 at acpi0: bus -1 (RP02)
> acpiprt3 at acpi0: bus -1 (RP03)
> acpiprt4 at acpi0: bus -1 (RP04)
> acpiprt5 at acpi0: bus 1 (RP05)
> acpiprt6 at acpi0: bus -1 (RP06)
> acpiec0 at acpi0
> ### AML PARSE ERROR (0x4cd5): Undefined name: SMA4
> error evaluating: \\_SB_.PCI0.LPCB.EC0_._REG
> acpiec _REG failed, broken BIOS
> acpipwrres0 at acpi0: DRST
> acpipwrres1 at acpi0: DRST
> acpipwrres2 at acpi0: DRST
> acpipwrres3 at acpi0: DRST
> acpipwrres4 at acpi0: DRST
> acpipwrres5 at acpi0: DRST
> acpicpu0 at acpi0: C3(10@150 mwait.1@0x60), C2(10@50 mwait.1@0x21),
> C1(1000@1 mwait.1@0x1), PSS
> acpicpu1 at acpi0: C3(10@150 mwait.1@0x60), C2(10@50 mwait.1@0x21),
> C1(1000@1 mwait.1@0x1), PSS
> acpitz0 at acpi0: critical temperature is 210 degC
> acpiac0 at acpi0: AC unit offline
> acpibtn0 at acpi0: LID0
> acpibtn1 at acpi0: PWRB
> acpibat0 at acpi0: BAT0 model "Primary" serial   type LION oem "HP"
> acpipci0 at acpi0 PCI0: 0x 0x0011 0x0001
> "HPQ6001" at acpi0 not configured
> "HPIC0003" at acpi0 not configured
> "*ETD0742" at acpi0 not configured
> acpicmos0 at acpi0
> "INT3453" at acpi0 not configured
> "INT33A1" at acpi0 not configured
> "MSFT0101" at acpi0 not configured
> "PNP0C14" at acpi0 not configured
> "INT3400" at acpi0 not configured
> "INT3403" at acpi0 not configured
> acpivideo0 at acpi0: GFX0
> acpivout0 at acpivideo0: DD1F
> cpu0: Enhanced SpeedStep 1097 MHz: speeds: 1101, 1100, 1000, 900, 800 MHz
> pci0 at mainbus0 bus 0
> pchb0 at pci0 dev 0 function 0 "Intel Gemini Lake Host" rev 0x03
> "Intel Gemini Lake DPTF" rev 0x03 at pci0 dev 0 function 1 not configured
> "Intel Gemini Lake GNA" rev 0x03 at pci0 dev 0 

hidmt(4): only allow hid_input kind

2020-01-25 Thread Patrick Wildt
Hi,

on the Pinebook Pro the trackpad isn't working.  The reason is that the
Y-coordinate is extracted twice.  The first location has thevalue
correctly, the second location has it zeroed or garbage.  This is
because when we iterate over the report, the Y-coordinate usage
appears twice.  This shouldn't happen, so why does it?

Here's an excerpt of the report descriptor:

Item(Global): Logical Maximum, data= [ 0x92 0x03 ] 914
Item(Global): Physical Maximum, data= [ 0x40 0x01 ] 320
Item(Local ): Usage, data= [ 0x31 ] 49
Direction-Y
Item(Main  ): Input, data= [ 0x02 ] 2
Data Variable Absolute No_Wrap Linear
Preferred_State No_Null_Position Non_Volatile Bitfield
Item(Main  ): End Collection, data=none
Item(Main  ): Collection, data= [ 0x02 ] 2
Logical

Directly after the Y-coordinate a collection ends and another starts.
The end of the collection will make hid_get_item() return with an item
where h.kind is hid_endcollection and h.usage is zero.  The start of the
new collection will make hid_get_item() return, and it will return with
h.kind set to hid_collection and h.usage set to the last usage, which
in this case is "Direction-Y".

Since we don't filter out hid_(end)collection, we add this item to the
list.  So, by making sure we only add hid_input items, the Pinebook
Pro's trackpad works.

Now I'm not sure if the hid code is supposed to re-use the Y-coordi-
nates usage on the next collection.  If someone knows how that should
work, please let me down.

ok?

Patrick

diff --git a/sys/dev/hid/hidmt.c b/sys/dev/hid/hidmt.c
index ee8dcadcc31..67eea46f0c0 100644
--- a/sys/dev/hid/hidmt.c
+++ b/sys/dev/hid/hidmt.c
@@ -176,6 +176,8 @@ hidmt_setup(struct device *self, struct hidmt *mt, void 
*desc, int dlen)
 
if (h.report_ID != mt->sc_rep_input)
continue;
+   if (h.kind != hid_input)
+   continue;
 
switch (h.usage) {
/* contact level usages */



Re: acpivout(4): directly call ws_[gs]et_param

2020-01-24 Thread Patrick Wildt
On Fri, Jan 24, 2020 at 01:04:41AM +0100, Patrick Wildt wrote:
> On Thu, Jan 23, 2020 at 11:25:51PM +0100, Mark Kettenis wrote:
> > Since acpi_set_brightness() can be called from anywhere, it should really
> > use the acpi task queue to do its thing instead of calling AML directly.
> 
> I didn't know there's an acpi task queue, so that's awesome!  I just saw
> that acpithinkpad(4) also uses that.  Changing this diff to do it that
> way was also quite easy, so this should read much better.  Feel free to
> give it a go.
> 
> ok?
> 
> Patrick

Looking for some more testing on this.  Successful test results would
help to get this diff in, so I can start sending the next diffs to
finally enable X395 backlight keys support.

Expected behaviour:  Backlight keys continue to change the backlight
as well as they did before.

Machines:  All those where acpivout(4) attaches.

Patrick

> diff --git a/sys/dev/acpi/acpivout.c b/sys/dev/acpi/acpivout.c
> index 58e8e3d431c..89922f4723b 100644
> --- a/sys/dev/acpi/acpivout.c
> +++ b/sys/dev/acpi/acpivout.c
> @@ -60,14 +60,17 @@ struct acpivout_softc {
>  
>   int *sc_bcl;
>   size_t  sc_bcl_len;
> +
> + int sc_brightness;
>  };
>  
>  void acpivout_brightness_cycle(struct acpivout_softc *);
>  void acpivout_brightness_step(struct acpivout_softc *, int);
>  void acpivout_brightness_zero(struct acpivout_softc *);
>  int  acpivout_get_brightness(struct acpivout_softc *);
> +int  acpivout_select_brightness(struct acpivout_softc *, int);
>  int  acpivout_find_brightness(struct acpivout_softc *, int);
> -void acpivout_set_brightness(struct acpivout_softc *, int);
> +void acpivout_set_brightness(void *, int);
>  void acpivout_get_bcl(struct acpivout_softc *);
>  
>  /* wconsole hook functions */
> @@ -117,6 +120,8 @@ acpivout_attach(struct device *parent, struct device 
> *self, void *aux)
>   ws_set_param = acpivout_set_param;
>  
>   acpivout_get_bcl(sc);
> +
> + sc->sc_brightness = acpivout_get_brightness(sc);
>  }
>  
>  int
> @@ -124,6 +129,9 @@ acpivout_notify(struct aml_node *node, int notify, void 
> *arg)
>  {
>   struct acpivout_softc *sc = arg;
>  
> + if (ws_get_param == NULL || ws_set_param == NULL)
> + return (0);
> +
>   switch (notify) {
>   case NOTIFY_BRIGHTNESS_CYCLE:
>   acpivout_brightness_cycle(sc);
> @@ -151,12 +159,13 @@ acpivout_notify(struct aml_node *node, int notify, void 
> *arg)
>  void
>  acpivout_brightness_cycle(struct acpivout_softc *sc)
>  {
> - int cur_level;
> + struct wsdisplay_param dp;
>  
> - if (sc->sc_bcl_len == 0)
> + dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
> + if (ws_get_param())
>   return;
> - cur_level = acpivout_get_brightness(sc);
> - if (cur_level == sc->sc_bcl[sc->sc_bcl_len - 1])
> +
> + if (dp.curval == dp.max)
>   acpivout_brightness_zero(sc);
>   else
>   acpivout_brightness_step(sc, 1);
> @@ -165,33 +174,45 @@ acpivout_brightness_cycle(struct acpivout_softc *sc)
>  void
>  acpivout_brightness_step(struct acpivout_softc *sc, int dir)
>  {
> - int level, nindex;
> + struct wsdisplay_param dp;
> + int delta, new;
>  
> - if (sc->sc_bcl_len == 0)
> - return;
> - level = acpivout_get_brightness(sc);
> - if (level == -1)
> + dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
> + if (ws_get_param())
>   return;
>  
> - nindex = acpivout_find_brightness(sc, level + (dir * BRIGHTNESS_STEP));
> - if (sc->sc_bcl[nindex] == level) {
> - if (dir == 1 && (nindex + 1 < sc->sc_bcl_len))
> - nindex++;
> - else if (dir == -1 && (nindex - 1 >= 0))
> - nindex--;
> + new = dp.curval;
> + delta = ((dp.max - dp.min) * BRIGHTNESS_STEP) / 100;
> + if (dir > 0) {
> + if (delta > dp.max - dp.curval)
> + new = dp.max;
> + else
> + new += delta;
> + } else if (dir < 0) {
> + if (delta > dp.curval - dp.min)
> + new = dp.min;
> + else
> + new -= delta;
>   }
> - if (sc->sc_bcl[nindex] == level)
> +
> + if (dp.curval == new)
>   return;
>  
> - acpivout_set_brightness(sc, sc->sc_bcl[nindex]);
> + dp.curval = new;
> + ws_set_param();
>  }
>  
>  void
>  acpivout_brightness_zero(struct acpivout_softc *sc)
>  {
> - if (sc->sc_bcl_len == 0)
> + struct wsdisplay_param d

Re: acpivout(4): directly call ws_[gs]et_param

2020-01-23 Thread Patrick Wildt
On Thu, Jan 23, 2020 at 11:25:51PM +0100, Mark Kettenis wrote:
> Since acpi_set_brightness() can be called from anywhere, it should really
> use the acpi task queue to do its thing instead of calling AML directly.

I didn't know there's an acpi task queue, so that's awesome!  I just saw
that acpithinkpad(4) also uses that.  Changing this diff to do it that
way was also quite easy, so this should read much better.  Feel free to
give it a go.

ok?

Patrick

diff --git a/sys/dev/acpi/acpivout.c b/sys/dev/acpi/acpivout.c
index 58e8e3d431c..89922f4723b 100644
--- a/sys/dev/acpi/acpivout.c
+++ b/sys/dev/acpi/acpivout.c
@@ -60,14 +60,17 @@ struct acpivout_softc {
 
int *sc_bcl;
size_t  sc_bcl_len;
+
+   int sc_brightness;
 };
 
 void   acpivout_brightness_cycle(struct acpivout_softc *);
 void   acpivout_brightness_step(struct acpivout_softc *, int);
 void   acpivout_brightness_zero(struct acpivout_softc *);
 intacpivout_get_brightness(struct acpivout_softc *);
+intacpivout_select_brightness(struct acpivout_softc *, int);
 intacpivout_find_brightness(struct acpivout_softc *, int);
-void   acpivout_set_brightness(struct acpivout_softc *, int);
+void   acpivout_set_brightness(void *, int);
 void   acpivout_get_bcl(struct acpivout_softc *);
 
 /* wconsole hook functions */
@@ -117,6 +120,8 @@ acpivout_attach(struct device *parent, struct device *self, 
void *aux)
ws_set_param = acpivout_set_param;
 
acpivout_get_bcl(sc);
+
+   sc->sc_brightness = acpivout_get_brightness(sc);
 }
 
 int
@@ -124,6 +129,9 @@ acpivout_notify(struct aml_node *node, int notify, void 
*arg)
 {
struct acpivout_softc *sc = arg;
 
+   if (ws_get_param == NULL || ws_set_param == NULL)
+   return (0);
+
switch (notify) {
case NOTIFY_BRIGHTNESS_CYCLE:
acpivout_brightness_cycle(sc);
@@ -151,12 +159,13 @@ acpivout_notify(struct aml_node *node, int notify, void 
*arg)
 void
 acpivout_brightness_cycle(struct acpivout_softc *sc)
 {
-   int cur_level;
+   struct wsdisplay_param dp;
 
-   if (sc->sc_bcl_len == 0)
+   dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+   if (ws_get_param())
return;
-   cur_level = acpivout_get_brightness(sc);
-   if (cur_level == sc->sc_bcl[sc->sc_bcl_len - 1])
+
+   if (dp.curval == dp.max)
acpivout_brightness_zero(sc);
else
acpivout_brightness_step(sc, 1);
@@ -165,33 +174,45 @@ acpivout_brightness_cycle(struct acpivout_softc *sc)
 void
 acpivout_brightness_step(struct acpivout_softc *sc, int dir)
 {
-   int level, nindex;
+   struct wsdisplay_param dp;
+   int delta, new;
 
-   if (sc->sc_bcl_len == 0)
-   return;
-   level = acpivout_get_brightness(sc);
-   if (level == -1)
+   dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+   if (ws_get_param())
return;
 
-   nindex = acpivout_find_brightness(sc, level + (dir * BRIGHTNESS_STEP));
-   if (sc->sc_bcl[nindex] == level) {
-   if (dir == 1 && (nindex + 1 < sc->sc_bcl_len))
-   nindex++;
-   else if (dir == -1 && (nindex - 1 >= 0))
-   nindex--;
+   new = dp.curval;
+   delta = ((dp.max - dp.min) * BRIGHTNESS_STEP) / 100;
+   if (dir > 0) {
+   if (delta > dp.max - dp.curval)
+   new = dp.max;
+   else
+   new += delta;
+   } else if (dir < 0) {
+   if (delta > dp.curval - dp.min)
+   new = dp.min;
+   else
+   new -= delta;
}
-   if (sc->sc_bcl[nindex] == level)
+
+   if (dp.curval == new)
return;
 
-   acpivout_set_brightness(sc, sc->sc_bcl[nindex]);
+   dp.curval = new;
+   ws_set_param();
 }
 
 void
 acpivout_brightness_zero(struct acpivout_softc *sc)
 {
-   if (sc->sc_bcl_len == 0)
+   struct wsdisplay_param dp;
+
+   dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+   if (ws_get_param())
return;
-   acpivout_set_brightness(sc, sc->sc_bcl[0]);
+
+   dp.curval = dp.min;
+   ws_set_param();
 }
 
 int
@@ -211,6 +232,26 @@ acpivout_get_brightness(struct acpivout_softc *sc)
return (level);
 }
 
+int
+acpivout_select_brightness(struct acpivout_softc *sc, int nlevel)
+{
+   int nindex, level;
+
+   level = sc->sc_brightness;
+   if (level == -1)
+   return level;
+
+   nindex = acpivout_find_brightness(sc, nlevel);
+   if (sc->sc_bcl[nindex] == level) {
+   if (nlevel > level && (nindex + 1 < sc->sc_bcl_len))
+   nindex++;
+   else if (nlevel < level && (nindex - 1 >= 0))
+   nindex--;
+   }
+
+   return nindex;
+}
+
 int
 acpivout_find_brightness(struct acpivout_softc *sc, int level)
 {
@@ -230,15 +271,16 @@ 

Re: acpivout(4): directly call ws_[gs]et_param

2020-01-23 Thread Patrick Wildt
On Thu, Jan 23, 2020 at 05:03:01PM -0500, Ted Unangst wrote:
> Patrick Wildt wrote:
> > acpivout_[gs]et_param don't know if they are being called by itself
> > or by someone else.  I don't need to grab it again, I just need to
> > have it before calling an ACPI method.  But when acpivout(4) calls
> > itself, it already has it, so taking it again would break it, as it's
> > non recursive.
> > 
> > Since it's a global function pointer that hides the implementation, the
> > caller cannot just take the ACPI lock before calling ws_[gs]et_param.
> > The caller doesn't know that the implementation needs ACPI.  On my X395
> > the function set in ws_[gs]et_param have nothing to do with ACPI at all.
> 
> Can you release the lock before calling ws_set_param?

That's a good point, that would make it a lot easier.  I'm not sure,
maybe kettenis@ can shed a light on this?



Re: acpivout(4): directly call ws_[gs]et_param

2020-01-23 Thread Patrick Wildt
On Thu, Jan 23, 2020 at 09:51:11AM +0100, Martin Pieuchot wrote:
> On 23/01/20(Thu) 08:26, Patrick Wildt wrote:
> > Hi,
> > 
> > this is the second attempt of a diff that prepares acpivout(4) to work
> > with the X395.  The previous one broke due to recursive ACPI locking.
> > 
> > So apparently we cannot change the brightness using the acpivout(4) ACPI
> > methods.  Instead we need to call amdgpu(4) to change the brightness.
> > But the brightness key events are still reported by acpivout(4).  That
> > means that we need to seperate the keystroke events from the actual
> > brightness change.
> > 
> > This diff changes the code to always use ws_[gs]et_param instead of just
> > calling the ACPI methods.  This means that the function pointers can
> > point to acpivout(4) or amdgpu(4), it shouldn't matter.
> > 
> > Unfortunately there's an issue with acpivout(4) calling itself.  The
> > keystroke event handler runs with the ACPI lock, so if we call our own
> > function, we try to grab the ACPI lock again and panic.  So, in this
> > diff I check whether we already have it and skip taking it again.
> 
> Why do you need to grab the ACPI lock again?  Can't you assert the lock
> is always taken and use a wrapper in the code path where it isn't?

acpivout_[gs]et_param don't know if they are being called by itself
or by someone else.  I don't need to grab it again, I just need to
have it before calling an ACPI method.  But when acpivout(4) calls
itself, it already has it, so taking it again would break it, as it's
non recursive.

Since it's a global function pointer that hides the implementation, the
caller cannot just take the ACPI lock before calling ws_[gs]et_param.
The caller doesn't know that the implementation needs ACPI.  On my X395
the function set in ws_[gs]et_param have nothing to do with ACPI at all.

> > I'm sure this looks ugly, and I'm wondering if it's too ugly.  If it is
> > indeed too ugly, I hope you'll also provide another idea how we can work
> > around it.
> > More testing would be appreciated.
> > 
> > Thanks,
> > Patrick
> > 
> > diff --git a/sys/dev/acpi/acpivout.c b/sys/dev/acpi/acpivout.c
> > index 58e8e3d431c..f3de0c582fb 100644
> > --- a/sys/dev/acpi/acpivout.c
> > +++ b/sys/dev/acpi/acpivout.c
> > @@ -66,6 +66,7 @@ void  acpivout_brightness_cycle(struct acpivout_softc 
> > *);
> >  void   acpivout_brightness_step(struct acpivout_softc *, int);
> >  void   acpivout_brightness_zero(struct acpivout_softc *);
> >  intacpivout_get_brightness(struct acpivout_softc *);
> > +intacpivout_select_brightness(struct acpivout_softc *, int);
> >  intacpivout_find_brightness(struct acpivout_softc *, int);
> >  void   acpivout_set_brightness(struct acpivout_softc *, int);
> >  void   acpivout_get_bcl(struct acpivout_softc *);
> > @@ -124,6 +125,9 @@ acpivout_notify(struct aml_node *node, int notify, void 
> > *arg)
> >  {
> > struct acpivout_softc *sc = arg;
> >  
> > +   if (ws_get_param == NULL || ws_set_param == NULL)
> > +   return (0);
> > +
> > switch (notify) {
> > case NOTIFY_BRIGHTNESS_CYCLE:
> > acpivout_brightness_cycle(sc);
> > @@ -151,12 +155,13 @@ acpivout_notify(struct aml_node *node, int notify, 
> > void *arg)
> >  void
> >  acpivout_brightness_cycle(struct acpivout_softc *sc)
> >  {
> > -   int cur_level;
> > +   struct wsdisplay_param dp;
> >  
> > -   if (sc->sc_bcl_len == 0)
> > +   dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
> > +   if (ws_get_param())
> > return;
> > -   cur_level = acpivout_get_brightness(sc);
> > -   if (cur_level == sc->sc_bcl[sc->sc_bcl_len - 1])
> > +
> > +   if (dp.curval == dp.max)
> > acpivout_brightness_zero(sc);
> > else
> > acpivout_brightness_step(sc, 1);
> > @@ -165,33 +170,45 @@ acpivout_brightness_cycle(struct acpivout_softc *sc)
> >  void
> >  acpivout_brightness_step(struct acpivout_softc *sc, int dir)
> >  {
> > -   int level, nindex;
> > +   struct wsdisplay_param dp;
> > +   int delta, new;
> >  
> > -   if (sc->sc_bcl_len == 0)
> > -   return;
> > -   level = acpivout_get_brightness(sc);
> > -   if (level == -1)
> > +   dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
> > +   if (ws_get_param())
> > return;
> >  
> > -   nindex = acpivout_find_brightness(sc, level + (dir * BRIGHTNESS_STEP));
> > -   if (sc->sc_bcl[nindex] == level) {
> > -   i

acpivout(4): directly call ws_[gs]et_param

2020-01-22 Thread Patrick Wildt
Hi,

this is the second attempt of a diff that prepares acpivout(4) to work
with the X395.  The previous one broke due to recursive ACPI locking.

So apparently we cannot change the brightness using the acpivout(4) ACPI
methods.  Instead we need to call amdgpu(4) to change the brightness.
But the brightness key events are still reported by acpivout(4).  That
means that we need to seperate the keystroke events from the actual
brightness change.

This diff changes the code to always use ws_[gs]et_param instead of just
calling the ACPI methods.  This means that the function pointers can
point to acpivout(4) or amdgpu(4), it shouldn't matter.

Unfortunately there's an issue with acpivout(4) calling itself.  The
keystroke event handler runs with the ACPI lock, so if we call our own
function, we try to grab the ACPI lock again and panic.  So, in this
diff I check whether we already have it and skip taking it again.

I'm sure this looks ugly, and I'm wondering if it's too ugly.  If it is
indeed too ugly, I hope you'll also provide another idea how we can work
around it.

More testing would be appreciated.

Thanks,
Patrick

diff --git a/sys/dev/acpi/acpivout.c b/sys/dev/acpi/acpivout.c
index 58e8e3d431c..f3de0c582fb 100644
--- a/sys/dev/acpi/acpivout.c
+++ b/sys/dev/acpi/acpivout.c
@@ -66,6 +66,7 @@ void  acpivout_brightness_cycle(struct acpivout_softc *);
 void   acpivout_brightness_step(struct acpivout_softc *, int);
 void   acpivout_brightness_zero(struct acpivout_softc *);
 intacpivout_get_brightness(struct acpivout_softc *);
+intacpivout_select_brightness(struct acpivout_softc *, int);
 intacpivout_find_brightness(struct acpivout_softc *, int);
 void   acpivout_set_brightness(struct acpivout_softc *, int);
 void   acpivout_get_bcl(struct acpivout_softc *);
@@ -124,6 +125,9 @@ acpivout_notify(struct aml_node *node, int notify, void 
*arg)
 {
struct acpivout_softc *sc = arg;
 
+   if (ws_get_param == NULL || ws_set_param == NULL)
+   return (0);
+
switch (notify) {
case NOTIFY_BRIGHTNESS_CYCLE:
acpivout_brightness_cycle(sc);
@@ -151,12 +155,13 @@ acpivout_notify(struct aml_node *node, int notify, void 
*arg)
 void
 acpivout_brightness_cycle(struct acpivout_softc *sc)
 {
-   int cur_level;
+   struct wsdisplay_param dp;
 
-   if (sc->sc_bcl_len == 0)
+   dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+   if (ws_get_param())
return;
-   cur_level = acpivout_get_brightness(sc);
-   if (cur_level == sc->sc_bcl[sc->sc_bcl_len - 1])
+
+   if (dp.curval == dp.max)
acpivout_brightness_zero(sc);
else
acpivout_brightness_step(sc, 1);
@@ -165,33 +170,45 @@ acpivout_brightness_cycle(struct acpivout_softc *sc)
 void
 acpivout_brightness_step(struct acpivout_softc *sc, int dir)
 {
-   int level, nindex;
+   struct wsdisplay_param dp;
+   int delta, new;
 
-   if (sc->sc_bcl_len == 0)
-   return;
-   level = acpivout_get_brightness(sc);
-   if (level == -1)
+   dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+   if (ws_get_param())
return;
 
-   nindex = acpivout_find_brightness(sc, level + (dir * BRIGHTNESS_STEP));
-   if (sc->sc_bcl[nindex] == level) {
-   if (dir == 1 && (nindex + 1 < sc->sc_bcl_len))
-   nindex++;
-   else if (dir == -1 && (nindex - 1 >= 0))
-   nindex--;
+   new = dp.curval;
+   delta = ((dp.max - dp.min) * BRIGHTNESS_STEP) / 100;
+   if (dir > 0) {
+   if (delta > dp.max - dp.curval)
+   new = dp.max;
+   else
+   new += delta;
+   } else if (dir < 0) {
+   if (delta > dp.curval - dp.min)
+   new = dp.min;
+   else
+   new -= delta;
}
-   if (sc->sc_bcl[nindex] == level)
+
+   if (dp.curval == new)
return;
 
-   acpivout_set_brightness(sc, sc->sc_bcl[nindex]);
+   dp.curval = new;
+   ws_set_param();
 }
 
 void
 acpivout_brightness_zero(struct acpivout_softc *sc)
 {
-   if (sc->sc_bcl_len == 0)
+   struct wsdisplay_param dp;
+
+   dp.param = WSDISPLAYIO_PARAM_BRIGHTNESS;
+   if (ws_get_param())
return;
-   acpivout_set_brightness(sc, sc->sc_bcl[0]);
+
+   dp.curval = dp.min;
+   ws_set_param();
 }
 
 int
@@ -211,6 +228,26 @@ acpivout_get_brightness(struct acpivout_softc *sc)
return (level);
 }
 
+int
+acpivout_select_brightness(struct acpivout_softc *sc, int nlevel)
+{
+   int nindex, level;
+
+   level = acpivout_get_brightness(sc);
+   if (level == -1)
+   return level;
+
+   nindex = acpivout_find_brightness(sc, nlevel);
+   if (sc->sc_bcl[nindex] == level) {
+   if (nlevel > level && (nindex + 1 < sc->sc_bcl_len))
+   

Re: acpivout: try to consistently adjust brightness by 5%

2020-01-13 Thread Patrick Wildt
On Mon, Jan 13, 2020 at 11:58:11AM +0100, Klemens Nanni wrote:
> On Sun, Oct 13, 2019 at 09:28:26PM -0500, joshua stein wrote:
> > When responding to hardware keys to increment or decrement screen 
> > brightness, don't just adjust by 1 BCL level as there may be 100 
> > levels.  Find the next brightness level that is at least 5% up or 
> > down, and use that.
>   revision 1.14
>   date: 2019/10/21 16:32:51;  author: jcs;  state: Exp;  lines: +20 -33;
>   When incrementing or decrementing screen brightness, don't just
>   adjust by 1 BCL level as there may be 100 levels.  Find the next
>   brightness level that is at least 5% up or down and use that.
> 
>   ok kettenis
> 
> This diff broke backlight adjustment on my X230:  With 100% screen
> brightness, pressing the function keys to *de*crease it won't do
> anything.  Booting a kernel with ACPIVIDEO_DEBUG suggests that
> acpivout_find_brightness() is unable to find the next level below 100%
> that is at least 5% less than the full brightness, hence it returns
> something above 95% such that acpivout_brightness_step() gets stuck and
> will set brightness to 100% again.
> 
> `xbacklight -50' will properly decrease brightness to 50%, then the
> function keys also work and I can decrease to 44% as the immediate lower
> level, however increasing it again never works and is stuck at 44%.
> 
> In general, setting a lower brightness level with xbacklight(1) makes
> the function keys work but only ever in the range of [0, n) -- I can
> never reach a higher level than set with xbacklight.
> 
> `xbacklight +100' works and reverting avpivout.c revision 1.14 makes
> everything work again for me.
> 
> tobhe has the exact same issues on his T420.
> 
> Below is diff to show my X230 brightness levels, dmesg as well.

The problem is that the last two values are 67 and 100.  If you go
5% down, it's 95.  The nearest will still be 100.  The code then
realizes that it's the same level as before, and does nlevel--.
But nlevel-- is 99, and not 67, because nlevel is the value and
not the index of the bcl array.  So in essence the change needed
is to decrease the index, not the value, and then look up the value.

Patrick



Re: ublink(4), led(4) and ledctl(1)

2019-12-19 Thread Patrick Wildt
On Fri, Dec 13, 2019 at 10:34:59PM +0100, Patrick Wildt wrote:
> Hi,
> 
> I have a ThingM blink(1) USB RGB device that shows up as uhid(4).
> The tooling is "interesting", especially with all those libusb and
> HID libraries doing the abstraction.  This introduces ublink(4), a
> dedicated kernel driver for that device.  There are two LEDs on the
> device, which can be modified seperately.  The firmware is impress-
> ive and provides features like playing sequences and adjusting how
> long it should take to fade from one colour to another.  Obviously
> this also increases the complexity of the tools involved to toggle
> those RGB LEDs.  Thus, the driver is kept simple (for now).
> 
> In addition to providing a way to set RGB LEDs, we can also use it
> as a watchdog.  If we don't "tickle" it in a specific timeframe it
> will play a (unless otherwise programmed) random sequence, which for
> instance can be used to see that the machine has paniced.  This has
> been quite useful while debugging the USB stack, because once the
> magic sequence started you know that you're in deep trouble.  All
> other features are unimplemented.  Gamma correction would be nice
> to have.
> 
> Since there is no abstraction layer for LEDs yet, this also intro-
> duces led(4), which attaches to ublink(4), and provides /dev/ledX.
> 
> uhidev1 at uhub0 port 3 configuration 1 interface 0 "ThingM blink(1) mk2" rev 
> 2.00/0.02 addr 2
> uhidev1: iclass 3/0, 1 report id
> ublink0 at uhidev1 reportid 1
> led0 at ublink0: 2 LEDs
> 
> led(4) can be improved even further.  We can attach the ThinkPad
> LEDs to it to control it.  There are also plenty of mouses that
> have controllable RGBs. We could add "human readable descrip-
> tions", for instance "upper side LED" or "docking station LED",
> so that users can find out more easily which LED they have to
> toggle.  A fading or blinking mechanism, including hardware off-
> loading, can probably be added as well.
> 
> To be able to control those devices, there's ledctl(1), a simple
> program that can turn on/off /dev/ledX devices and also set RGB
> colours.
> 
> I only did the MAKEDEV stuff for amd64, and also there are no
> manpages yet.  Also I haven't run it through make build yet,
> sorry.  And I don't often do userland tools, so feel free to
> let me know how to improve it.
> 
> Thanks,
> Patrick

Updated diff, changes:

 * All the manpages!
 * /dev/led{0,1,2,...} are now by default 600.
 * Doesn't panic when you remove the stick, I think I
   might have already had that fixed in the first diff.
 * Some small improvements here and there, nothing special.

Thanks to jan for ledctl(1) manpage and review.  And thanks to
cheloha@!

Patrick

diff --git a/etc/MAKEDEV.common b/etc/MAKEDEV.common
index c187df748d6..dc67b54ec5a 100644
--- a/etc/MAKEDEV.common
+++ b/etc/MAKEDEV.common
@@ -521,6 +521,8 @@ __devitem(ipmi, ipmi*, IPMI BMC access)dnl
 _mkdev(ipmi, ipmi*, {-M ipmi$U c major_ipmi_c $U 600-})dnl
 __devitem(gpio, gpio*, General Purpose Input/Output)dnl
 _mcdev(gpio, gpio*, gpio, {-major_gpio_c-}, 600)dnl
+__devitem(led, led*, Generic LED devices)dnl
+_mcdev({-led-}, led*, {-led-}, {-major_led_c-}, 600)dnl
 __devitem(vmm, vmm, Virtual Machine Monitor)dnl
 _mkdev(vmm, vmm, {-M vmm c major_vmm_c 0 600-})dnl
 __devitem(pvbus, pvbus*, paravirtual device tree root)dnl
diff --git a/etc/etc.amd64/MAKEDEV b/etc/etc.amd64/MAKEDEV
index 543b0ec731b..50f7ac53acb 100644
--- a/etc/etc.amd64/MAKEDEV
+++ b/etc/etc.amd64/MAKEDEV
@@ -78,6 +78,7 @@
 #  gpio*   General Purpose Input/Output
 #  hotplug devices hot plugging
 #  ipmi*   IPMI BMC access
+#  led*Generic LED devices
 #  nvram   NVRAM access
 #  kcovKernel code coverage tracing
 #  pci*PCI bus devices
@@ -329,6 +330,10 @@ nvram)
M nvram c 85 0 440 kmem
;;
 
+led*)
+   M led$U c 55 $U 600
+   ;;
+
 ipmi*)
M ipmi$U c 96 $U 600
;;
diff --git a/etc/etc.amd64/MAKEDEV.md b/etc/etc.amd64/MAKEDEV.md
index f46b52bd7d6..66e85a16da8 100644
--- a/etc/etc.amd64/MAKEDEV.md
+++ b/etc/etc.amd64/MAKEDEV.md
@@ -76,6 +76,7 @@ _DEV(gpio, 88)
 _DEV(hotplug, 82)
 _DEV(ipmi, 96)
 dnl _DEV(joy, 26)
+_DEV(led, 55)
 _DEV(nvram, 85)
 _DEV(kcov, 19)
 _DEV(pci, 72)
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index 307bd44b66b..45ab7539c60 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -41,8 +41,8 @@ MAN=  aac.4 abcrtc.4 ac97.4 acphy.4 acrtc.4 \
ip.4 ip6.4 ipcomp.4 ipgphy.4 ipmi.4 ips.4 ipsec.4 ipw.4 \
isa.4 isagpio.4 isapnp.4 islrtc.4 it.4 itherm.4 iwi.4 iwn.4 iwm.4 \
ix.4 ixgb.4 ixl.4 jmb.4 jme.4 jmphy.4 \
-   kate.4 kcov.4 km.4 ksmn.4 ksyms.4 kubsan.4 kue.4 lc.4 lge.4 lii.4 \
-   lisa.4 lm.4 lmenv.4 lmn.4 lmtemp.4 lo.4 

Re: ublink(4), led(4) and ledctl(1)

2019-12-16 Thread Patrick Wildt
On Mon, Dec 16, 2019 at 01:57:41PM +, Stuart Henderson wrote:
> On 2019/12/13 22:34, Patrick Wildt wrote:
> > uhidev1 at uhub0 port 3 configuration 1 interface 0 "ThingM blink(1) mk2" 
> > rev 2.00/0.02 addr 2
> > uhidev1: iclass 3/0, 1 report id
> > ublink0 at uhidev1 reportid 1
> > led0 at ublink0: 2 LEDs
> 
> Does this attachment break the normal software used with these?
> (in ports as misc/blink1)

Of course it does!  This means that you can use the device only with
led(4), and that you can use all of the features provided by led(4),
and nothing else.  If you want to run it insecurely, with some external
tool accessing your USB devices, you will *have to* explicitly disable
the kernel driver.



Re: ublink(4), led(4) and ledctl(1)

2019-12-13 Thread Patrick Wildt
On Fri, Dec 13, 2019 at 02:43:25PM -0700, Theo de Raadt wrote:
> +__devitem(led, led*, Generic LED devices)dnl
> +_mcdev({-led-}, led*, {-led-}, {-major_led_c-}, 660)dnl
> 
> Mode 660 leads me to ask -- what is the group?

I don't know, I figured you could help me there.  I guess the
default can be 600 and then, like you wrote in the other mail,
people will have to chmod/chown it after every upgrade.



ublink(4), led(4) and ledctl(1)

2019-12-13 Thread Patrick Wildt
neric LED devices, see
+.Xr led 4 .
 .It Ar nvram
 NVRAM access, see
 .Xr nvram 4 .
diff --git a/sys/arch/amd64/amd64/conf.c b/sys/arch/amd64/amd64/conf.c
index a8c10783f11..307287ea096 100644
--- a/sys/arch/amd64/amd64/conf.c
+++ b/sys/arch/amd64/amd64/conf.c
@@ -163,6 +163,7 @@ cdev_decl(nvram);
 cdev_decl(drm);
 #include "viocon.h"
 cdev_decl(viocon);
+#include "led.h"
 
 #include "wsdisplay.h"
 #include "wskbd.h"
@@ -247,7 +248,7 @@ struct cdevsw   cdevsw[] =
cdev_midi_init(NMIDI,midi), /* 52: MIDI I/O */
cdev_notdef(),  /* 53 was: sequencer I/O */
cdev_notdef(),  /* 54 was: RAIDframe disk driver */
-   cdev_notdef(),  /* 55: */
+   cdev_led_init(NLED,led),/* 55: led(4) */
/* The following slots are reserved for isdn4bsd. */
cdev_notdef(),  /* 56: i4b main device */
cdev_notdef(),  /* 57: i4b control device */
diff --git a/sys/arch/amd64/conf/GENERIC b/sys/arch/amd64/conf/GENERIC
index 64d390905d9..1fd43d81507 100644
--- a/sys/arch/amd64/conf/GENERIC
+++ b/sys/arch/amd64/conf/GENERIC
@@ -280,6 +280,8 @@ ucom*   at ucycom?
 uslhcom* at uhidev?# Silicon Labs CP2110 USB HID UART
 ucom*  at uslhcom?
 uhid*  at uhidev?  # USB generic HID support
+ublink*at uhidev?  # ThingM blink(1)
+led*   at ublink?
 upd*   at uhidev?  # USB Power Devices sensors
 aue*   at uhub?# ADMtek AN986 Pegasus Ethernet
 atu*   at uhub?# Atmel AT76c50x based 802.11b
diff --git a/sys/conf/files b/sys/conf/files
index 0cef7842919..ab0db72178a 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -56,6 +56,11 @@ define   i2c_bitbang
 # 1-Wire bus bit-banging
 define onewire_bitbang
 
+define led {}
+device led
+file   dev/ic/led.cled needs-flag
+attach led at led
+
 # net device attributes - we have generic code for ether(net)
 define crypto
 define ether
diff --git a/sys/dev/ic/led.c b/sys/dev/ic/led.c
new file mode 100644
index 000..3bc8c214394
--- /dev/null
+++ b/sys/dev/ic/led.c
@@ -0,0 +1,139 @@
+/* $OpenBSD$   */
+/*
+ * Copyright (c) 2019 Patrick Wildt 
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#ifdef LED_DEBUG
+#define DPRINTF(x) do { if (leddebug) printf x; } while (0)
+#define DPRINTFN(n,x)  do { if (leddebug>(n)) printf x; } while (0)
+intleddebug = 0;
+#else
+#define DPRINTF(x)
+#define DPRINTFN(n,x)
+#endif
+
+struct led_softc {
+   struct devicesc_dev;
+   unsigned int sc_nled;
+
+   void*sc_cookie;
+   struct led_ctl  *sc_ctl;
+};
+
+#defineLEDUNIT(dev)(minor(dev))
+
+int led_match(struct device *, void *, void *);
+void led_attach(struct device *, struct device *, void *);
+int led_detach(struct device *, int);
+
+struct cfdriver led_cd = {
+   NULL, "led", DV_DULL
+};
+
+struct cfattach led_ca = {
+   sizeof(struct led_softc), led_match, led_attach, led_detach,
+};
+
+int
+led_match(struct device *parent, void *match, void *aux)
+{
+   return 1;
+}
+
+void
+led_attach(struct device *parent, struct device *self, void *aux)
+{
+   struct led_softc *sc = (struct led_softc *)self;
+   struct led_attach_args *laa = (struct led_attach_args *)aux;
+
+   sc->sc_cookie = laa->cookie;
+   sc->sc_ctl = laa->ctl;
+   sc->sc_nled = laa->nled;
+
+   printf(": %u LEDs\n", sc->sc_nled);
+}
+
+int
+led_detach(struct device *self, int flags)
+{
+   int maj, mn;
+
+   /* locate the major number */
+   for (maj = 0; maj < nchrdev; maj++)
+   if (cdevsw[maj].d_open == ledopen)
+   break;
+
+   /* Nuke the vnodes for any open instances (calls close). */
+   mn = self->dv_unit;
+   vdevgone(maj, mn, mn, VCHR);
+
+   return 0;
+}
+
+int
+ledopen(dev_t dev, int flag, int mode, struct proc *p)
+{
+   struct led_softc *sc;
+
+   if (LEDUNIT(dev) >= led_cd.cd_ndevs)
+   return ENXIO;
+   sc = led_cd.cd_devs[LEDUNIT(dev)];
+

xhci(4): correct short actlen for >64k transfers

2019-11-26 Thread Patrick Wildt
Hi,

I found another issue with the calculation of the actual length on short
xfers.  On e.g. bulk transfers with multiple TRBs the first short TRB
will give us a short event.  We will then calculate the actual length
and return.  So far this is good.

The last TRB in the TD is marked as IOC (Interrupt On Complete) and will
give us an additional event.  One one of my machine this is not a succ-
ess event, but also a short event.

In that case we would set xfer->actlen again, overwriting the actual
result.  It would sum all TRBs apart from the last one which will result
in a bigger and bogus number.

What we need to do is to make sure it's only set once, and that's when
we get a short event for the first time.  This is essentially the same
check that we have in the success event.

ok?

Patrick

diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index 064235b2841..eea7be1e5e3 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -856,8 +856,9 @@ xhci_event_xfer_generic(struct xhci_softc *sc, struct 
usbd_xfer *xfer,
/*
 * Use values from the transfer TRB instead of the status TRB.
 */
-   xfer->actlen = xhci_xfer_length_generic(xx, xp, trb_idx) -
-   remain;
+   if (xfer->actlen == 0)
+   xfer->actlen =
+   xhci_xfer_length_generic(xx, xp, trb_idx) - remain;
/*
 * If this is not the last TRB of a transfer, we should
 * theoretically clear the IOC at the end of the chain



Re: XHCI support for bulk xfers >64k

2019-11-21 Thread Patrick Wildt
On Thu, Nov 21, 2019 at 06:52:36AM +, sc.dy...@gmail.com wrote:
> Hi,
> 
> On 2019/11/18 20:34, Marcus Glocker wrote:
> > On Sun, Nov 17, 2019 at 12:36:49PM +0100, Marcus Glocker wrote:
> > 
> >> While recently testing UDL on XHCI I faced a lot of USB timeouts, and
> >> therefore screen rendering issues.
> >> The reason is that XHCI currently only supports single bulk transfers
> >> up to 64k, while UDL can schedule a bulk transfer up to 1m.
> >>
> >> The following diff adds XHCI bulk transfer support >64k and makes UDL
> >> work fine for me on XHCI.
> >>
> >> mpi@ already did an initial re-view, and I have adapted some of his
> >> comments already in this diff.
> >>
> >> More testing and comments welcome.
> > 
> > After patrick@ did feedback that the current bulk transfer code in
> > XHCI should also work for larger transfers as is, we have found the
> > bug which resulted in a much smaller diff :-)
> > 
> > Attached for your reference.  It just has been committed.
> > 
> > 
> > Index: xhci.c
> > ===
> > RCS file: /cvs/src/sys/dev/usb/xhci.c,v
> > retrieving revision 1.106
> > diff -u -p -u -p -r1.106 xhci.c
> > --- xhci.c  6 Oct 2019 17:30:00 -   1.106
> > +++ xhci.c  18 Nov 2019 19:32:30 -
> > @@ -2871,7 +2871,7 @@ xhci_device_generic_start(struct usbd_xf
> > /* If the buffer crosses a 64k boundary, we need one more. */
> > len = XHCI_TRB_MAXSIZE - (paddr & (XHCI_TRB_MAXSIZE - 1));
> > if (len < xfer->length)
> > -   ntrb++;
> > +   ntrb = howmany(xfer->length - len, XHCI_TRB_MAXSIZE) + 1;
> > else
> > len = xfer->length;
> >  
> > 
> 
> Should xhci_device_isoc_start also count up the chunks after boundary?
> 

We had discussed this as well, but since a frame cannot be bigger than
64k, a hard boundary which is visible when you realize frlengths is a
uint16_t *, that change would essentially be a no-op.

We could change it for the sake of having the same calculation in all
places.

Thanks,
Patrick

> 
> --- sys/dev/usb/xhci.c.orig   Mon Nov 18 22:47:25 2019
> +++ sys/dev/usb/xhci.cThu Nov 21 05:13:02 2019
> @@ -3049,7 +3049,8 @@ xhci_device_isoc_start(struct usbd_xfer *xfer)
>   /* If the buffer crosses a 64k boundary, we need one more. */
>   len = XHCI_TRB_MAXSIZE - (paddr & (XHCI_TRB_MAXSIZE - 1));
>   if (len < xfer->frlengths[i])
> - ntrb++;
> + ntrb = howmany(xfer->frlengths[i] - len,
> + XHCI_TRB_MAXSIZE) + 1;
>  
>   paddr += xfer->frlengths[i];
>   }
> @@ -3066,7 +3067,8 @@ xhci_device_isoc_start(struct usbd_xfer *xfer)
>   /* If the buffer crosses a 64k boundary, we need one more. */
>   len = XHCI_TRB_MAXSIZE - (paddr & (XHCI_TRB_MAXSIZE - 1));
>   if (len < xfer->frlengths[i])
> - ntrb++;
> + ntrb = howmany(xfer->frlengths[i] - len,
> + XHCI_TRB_MAXSIZE) + 1;
>   else
>   len = xfer->frlengths[i];
>  
> 



Re: acpivout(4): fix brightness not going up

2019-11-20 Thread Patrick Wildt
On Sat, Nov 02, 2019 at 10:09:43PM -0400, James Hastings wrote:
> Hi,
> 
> Backlight on multiple laptops will go down but not up when using brightness 
> keys.
> Compare new brightness level to min/max values in sc_bcl[] instead.
> Diff below restores backlight up function.

Since (n)level is based on the values in sc->sc_bcl, comparing the
minimum and maximum against the sorted list in sc->sc_bcl makes a
lot of sense.  Though maybe it should be

if (dir == 1 && (nlevel + 1 <= sc->sc_bcl[sc->sc_bcl_len - 1]))

(note: < changed to <=)

since sc->sc_bcl[sc->sc_bcl_len - 1] should be the maximum that
we can set, and nlevel++ is allowed to be the maximum?  The check
for the minimum is similar.

Anyone else wants to chime in?

Patrick

> Index: dev/acpi/acpivout.c
> ===
> RCS file: /cvs/src/sys/dev/acpi/acpivout.c,v
> retrieving revision 1.14
> diff -u -p -u -r1.14 acpivout.c
> --- dev/acpi/acpivout.c   21 Oct 2019 16:32:51 -  1.14
> +++ dev/acpi/acpivout.c   3 Nov 2019 01:04:27 -
> @@ -175,9 +175,9 @@ acpivout_brightness_step(struct acpivout
>  
>   nlevel = acpivout_find_brightness(sc, level + (dir * BRIGHTNESS_STEP));
>   if (nlevel == level) {
> - if (dir == 1 && (nlevel + 1 < sc->sc_bcl_len))
> + if (dir == 1 && (nlevel + 1 < sc->sc_bcl[sc->sc_bcl_len - 1]))
>   nlevel++;
> - else if (dir == -1 && (nlevel - 1 >= 0))
> + else if (dir == -1 && (nlevel - 1 >= sc->sc_bcl[0]))
>   nlevel--;
>   }
>   if (nlevel == level)
> 



Re: pci_sdhc: Intel eMMC controller fix

2019-11-20 Thread Patrick Wildt
On Fri, Mar 29, 2019 at 05:22:13AM -0400, James Hastings wrote:
> Index: dev/pci/pcidevs
> ===
> RCS file: /cvs/src/sys/dev/pci/pcidevs,v
> retrieving revision 1.1881
> diff -u -p -r1.1881 pcidevs
> --- dev/pci/pcidevs   20 Mar 2019 10:51:25 -  1.1881
> +++ dev/pci/pcidevs   29 Mar 2019 07:57:20 -
> @@ -4467,6 +4467,7 @@ product INTEL WL_3165_1 0x3165  Dual Ban
>  product INTEL WL_3165_2  0x3166  Dual Band Wireless AC 3165
>  product INTEL GLK_UHD_6050x3184  UHD Graphics 605
>  product INTEL GLK_UHD_6000x3185  UHD Graphics 600
> +product INTEL GLK_EMMC   0x31cc  Gemini Lake eMMC
>  product INTEL 31244  0x3200  31244 SATA
>  product INTEL 82855PM_HB 0x3340  82855PM Host
>  product INTEL 82855PM_AGP0x3341  82855PM AGP
> Index: dev/pci/sdhc_pci.c
> ===
> RCS file: /cvs/src/sys/dev/pci/sdhc_pci.c,v
> retrieving revision 1.20
> diff -u -p -r1.20 sdhc_pci.c
> --- dev/pci/sdhc_pci.c30 Apr 2016 11:32:23 -  1.20
> +++ dev/pci/sdhc_pci.c29 Mar 2019 07:57:20 -
> @@ -127,6 +127,12 @@ sdhc_pci_attach(struct device *parent, s
>   PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENE_SDCARD)
>   sc->sc.sc_flags |= SDHC_F_NOPWR0;
> 
> + /* Some Intel controllers break if set to 0V bus power. */
> + if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
> + (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_APOLLOLAKE_EMMC ||
> + PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_GLK_EMMC))
> + sc->sc.sc_flags |= SDHC_F_NOPWR0;
> +
>   /* Some RICOH controllers need to be bumped into the right mode. */
>   if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH &&
>   (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U822 ||
> 

A bit late, but committed, thanks!  By the way, now that we
have your glkgpio(4), does that make the SD controller work?

Patrick



Re: iwm: support 9260 devices

2019-11-20 Thread Patrick Wildt
On Wed, Nov 20, 2019 at 08:06:25AM -0800, Bryan Vyhmeister wrote:
> On Sat, Nov 16, 2019 at 10:01:44PM -0800, Philip Guenther wrote:
> > Looking good so far on my X1 extreme once I
> > added PCI_PRODUCT_INTEL_WL_9560_2 next to the _1 lines in if_iwm.c.
> > Awesome!
> 
> Could this change be committed as well? This allows the 9560 on my
> ThinkPad P1 to work as well. Thank you!
> 
> Bryan
> 

Oops.  Committed, thanks!

> 
> Index: sys/dev/pci/if_iwm.c
> ===
> RCS file: /cvs/src/sys/dev/pci/if_iwm.c,v
> retrieving revision 1.283
> diff -u -p -r1.283 if_iwm.c
> --- sys/dev/pci/if_iwm.c  18 Nov 2019 18:53:11 -  1.283
> +++ sys/dev/pci/if_iwm.c  20 Nov 2019 15:54:41 -
> @@ -8559,6 +8559,7 @@ iwm_attach(struct device *parent, struct
>   sc->sc_mqrx_supported = 1;
>   break;
>   case PCI_PRODUCT_INTEL_WL_9560_1:
> + case PCI_PRODUCT_INTEL_WL_9560_2:
>   sc->sc_fwname = "iwm-9000-34";
>   sc->host_interrupt_operation_mode = 0;
>   sc->sc_device_family = IWM_DEVICE_FAMILY_9000;
> 



iwm(4): support for MSI-X

2019-11-20 Thread Patrick Wildt
Hi,

on my Intel NUC 8i5BEHs that has a 9560 chip the current in-tree
support for the 9000 series does not work.  The issue seems to be
the interrupt delivery.  The first interrupt we wait for, which is
loading the firmware chunks, never appears.  Even disabling MSI
and relying on legacy interrupts only gives me a single interrupt.
It is not clear if this is a misconfiguration on our side, or if
it is the chip's/firmware's fault.

As it turns out, adding MSI-X support to iwm(4) fixes all my
problems on that machine so that I can use iwm(4) there reliably.
It also does not break my X395.

NUC 8i5BEH:
iwm0 at pci0 dev 20 function 3 "Intel Dual Band Wireless AC 9560" rev 0x30, msix
iwm0: hw rev 0x310, fw ver 34.3125811985.0, address xx:xx:xx:xx:xx:xx

X395:
iwm0 at pci1 dev 0 function 0 "Intel Dual Band Wireless-AC 9260" rev 0x29, msix
iwm0: hw rev 0x320, fw ver 34.3125811985.0, address xx:xx:xx:xx:xx:xx

With MSI-X it is possible to allocate multiple vectors and assign
them to different CPUs.  Linux actually tries to get at least 3
vectors.  They would like to have the command/mgmt queue, the data
queue and non-RX events on different vectors.  For this you have
a table that maps events to vectors.  And then there's a single
mask where you can enable/disable those events.

For us this diff uses a single vector, a single interrupt, and we
map all events to this.  Thus it tries to behave the same as if we
were simply using MSI.

Still, we need a new interrupt handler for MSI-X, for instance
because the registers for "what event happened?" changed, and
more.  I have tried modeling it so it should behave similarly
to the other interrupt handler.  Unfortunately I neither know a
way to control the rfkill or trigger a software/hardware error,
so these cases are untested.

It would be nice to get this tested, to make sure that there are
no regressions on older hardware.  If we don't want to risk it,
we could also try enabling msix only for 9000 series chips, but
I'd rather see if this also works on the older variants.

So, essentially, apply the diff and tell me if it still works as
well as it did before. :)  In theory this could lead the way to
having RX processed in parallel, so there's something to gain in
the future and it's worth testing.

Patrick

diff --git a/sys/dev/pci/if_iwm.c b/sys/dev/pci/if_iwm.c
index 9e4f9562f7f..ee6492f8730 100644
--- a/sys/dev/pci/if_iwm.c
+++ b/sys/dev/pci/if_iwm.c
@@ -288,6 +288,8 @@ voidiwm_apm_config(struct iwm_softc *);
 intiwm_apm_init(struct iwm_softc *);
 void   iwm_apm_stop(struct iwm_softc *);
 intiwm_allow_mcast(struct iwm_softc *);
+void   iwm_init_msix_hw(struct iwm_softc *);
+void   iwm_conf_msix_hw(struct iwm_softc *, int);
 intiwm_start_hw(struct iwm_softc *);
 void   iwm_stop_device(struct iwm_softc *);
 void   iwm_nic_config(struct iwm_softc *);
@@ -479,6 +481,7 @@ voidiwm_nic_umac_error(struct iwm_softc *);
 #endif
 void   iwm_notif_intr(struct iwm_softc *);
 intiwm_intr(void *);
+intiwm_intr_msix(void *);
 intiwm_match(struct device *, void *, void *);
 intiwm_preinit(struct iwm_softc *);
 void   iwm_attach_hook(struct device *);
@@ -1397,8 +1400,16 @@ iwm_free_tx_ring(struct iwm_softc *sc, struct 
iwm_tx_ring *ring)
 void
 iwm_enable_rfkill_int(struct iwm_softc *sc)
 {
-   sc->sc_intmask = IWM_CSR_INT_BIT_RF_KILL;
-   IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
+   if (!sc->sc_msix) {
+   sc->sc_intmask = IWM_CSR_INT_BIT_RF_KILL;
+   IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
+   } else {
+   IWM_WRITE(sc, IWM_CSR_MSIX_FH_INT_MASK_AD,
+   sc->sc_fh_init_mask);
+   IWM_WRITE(sc, IWM_CSR_MSIX_HW_INT_MASK_AD,
+   ~IWM_MSIX_HW_INT_CAUSES_REG_RF_KILL);
+   sc->sc_hw_mask = IWM_MSIX_HW_INT_CAUSES_REG_RF_KILL;
+   }
 
if (sc->sc_device_family >= IWM_DEVICE_FAMILY_9000)
IWM_SETBITS(sc, IWM_CSR_GP_CNTRL,
@@ -1436,15 +1447,36 @@ iwm_check_rfkill(struct iwm_softc *sc)
 void
 iwm_enable_interrupts(struct iwm_softc *sc)
 {
-   sc->sc_intmask = IWM_CSR_INI_SET_MASK;
-   IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
+   if (!sc->sc_msix) {
+   sc->sc_intmask = IWM_CSR_INI_SET_MASK;
+   IWM_WRITE(sc, IWM_CSR_INT_MASK, sc->sc_intmask);
+   } else {
+   /*
+* fh/hw_mask keeps all the unmasked causes.
+* Unlike msi, in msix cause is enabled when it is unset.
+*/
+   sc->sc_hw_mask = sc->sc_hw_init_mask;
+   sc->sc_fh_mask = sc->sc_fh_init_mask;
+   IWM_WRITE(sc, IWM_CSR_MSIX_FH_INT_MASK_AD,
+   ~sc->sc_fh_mask);
+   IWM_WRITE(sc, IWM_CSR_MSIX_HW_INT_MASK_AD,
+   ~sc->sc_hw_mask);
+   }
 }
 
 void
 iwm_enable_fwload_interrupt(struct iwm_softc *sc)
 {
-   sc->sc_intmask = IWM_CSR_INT_BIT_FH_TX;
-   

sdhc(4): no 0V one some Intel

2019-11-19 Thread Patrick Wildt
Hi,

on some GPD Pocket mlarkin@ has the eMMC doesn't come up.  One issue
is that we shouldn't go to 0V on some/most(?) Intel controllers.  This
only adds it for his machine, but I know that the Appollo Lake versions
might also work if added to this check.  But unless verified I'll not
add it.  This makes mlarkin@'s machine work, even though it's utterly
slow.  That would be the next thing to fix... probably low clocks or
doesn't use 8-bit.

ok?

Patrick

diff --git a/sys/dev/pci/sdhc_pci.c b/sys/dev/pci/sdhc_pci.c
index d1b6688f573..dd6bc79c29c 100644
--- a/sys/dev/pci/sdhc_pci.c
+++ b/sys/dev/pci/sdhc_pci.c
@@ -127,6 +127,11 @@ sdhc_pci_attach(struct device *parent, struct device 
*self, void *aux)
PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ENE_SDCARD)
sc->sc.sc_flags |= SDHC_F_NOPWR0;
 
+   /* Some Intel controllers break if set to 0V bus power. */
+   if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_INTEL &&
+   PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_INTEL_100SERIES_LP_EMMC)
+   sc->sc.sc_flags |= SDHC_F_NOPWR0;
+
/* Some RICOH controllers need to be bumped into the right mode. */
if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_RICOH &&
(PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_RICOH_R5U822 ||



Re: Remove NetChip from cdce

2019-11-13 Thread Patrick Wildt
On Wed, Nov 13, 2019 at 06:40:00PM -0700, Aaron Bieber wrote:
> Hi,
> 
> I have a raspberry pi 0 that attaches as:
>   cdce0 at uhub0 port 3 configuration 2 interface 0 "Linux 4.19.75+ with \
> 2098.usb RNDIS/Ethernet Gadget" rev 2.00/4.19 addr 10
> 
> Unfortunately the cdce interface does not work with this particular device.
> 
> On the linux end, it turns out that cdc and rndis are being presented. When
> NetChip is removed from the cdce driver, urndis(4) picks up the slack and
> things work as expected! Linux also has the product id defined as RNDIS.

The thing is that Linux provides multiple "configurations" (as in:
urndis(4), cdce(4), ...) over the same device.  Hardcoding this
combination of vendor/product id will make cdce(4) always attach,
even though the configuration is actually urndis(4).  In this case
Linux improved well enough so that our match function checking for
class/subclass should be the right thing to do.

Thus, ok patrick@

> Debugged with patrick@ who is awesome and I now owe a beer or two for his
> help! :D
> 
> OK?
> 
> Cheers,
> Aaron
> 
> diff --git a/sys/dev/usb/if_cdce.c b/sys/dev/usb/if_cdce.c
> index abf0521ccd6..816bdc29c10 100644
> --- a/sys/dev/usb/if_cdce.c
> +++ b/sys/dev/usb/if_cdce.c
> @@ -100,7 +100,6 @@ const struct cdce_type cdce_devs[] = {
>  {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN }, CDCE_CRC32 },
>  {{ USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2 }, CDCE_CRC32 },
>  {{ USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00 }, 0 },
> -{{ USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_ETHERNETGADGET }, 0 },
>  {{ USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX }, 0 },
>  {{ USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250 }, CDCE_SWAPUNION },
>  };
> 
> -- 
> PGP: 0x1F81112D62A9ADCE / 3586 3350 BFEA C101 DB1A  4AF0 1F81 112D 62A9 ADCE
> 



Re: fix xhci 'actlen' calculation

2019-11-12 Thread Patrick Wildt
On Tue, Nov 12, 2019 at 07:00:00PM +0100, Patrick Wildt wrote:
> On Tue, Nov 12, 2019 at 01:43:28PM +0100, Patrick Wildt wrote:
> > On Tue, Nov 12, 2019 at 10:45:39AM +0100, Gerhard Roth wrote:
> > > Hi,
> > > 
> > > xhci's calculation of 'xfer->actlen' is wrong if the xfer was split into
> > > multiple TRBs. That's because the code just looks at the remainder
> > > reported by the status TRB. However, this remainder only refers to the
> > > total size of this single TRB; not to the total size of the xfer.
> > > 
> > > Example: assume a 16 kb xfer is split into two TRBs for 8 kb each.
> > >   Then we get a short read of 6 kb. The status TRB will refer
> > >   to the first TRB with remainder set to 2 kb. Currently xhci
> > >   would assume that actlen is 'xfer->length' (16 kb) minus the
> > >   remainder (2 kb). That yields a wrong actlen of 14 kb instead
> > >   of 6 kb.
> > > 
> > > The patch below fixes this by adding up all the remainders of all the
> > > transfer TRBs up to the current one.
> > > 
> > > Gerhard
> > > 
> > 
> > Very goood catch, this is very similar to the issue we had with isoc
> > transfers.  Diff looks good to me!
> 
> Unfortunately this is *not* ok.  It turns out that this doesn't work
> for short ctrl transfers.  Compared to bulk/intr transfers, ctrl xfers
> have a setup, data and status trb.  Now your diff will sum all TRBs,
> but the thing is that only the data TRB is actually short. :(  But I
> think this should be easily fixable, I'll have a look.

This changes the diff so that it only sums actual data TRBs (NORMAL and
DATA).

That makes my umb(4) device behave again.

Patrick

diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index f9d7eb3a401..c801bd96ad1 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -810,6 +810,29 @@ xhci_event_xfer(struct xhci_softc *sc, uint64_t paddr, 
uint32_t status,
xhci_xfer_done(xfer);
 }
 
+uint32_t
+xhci_xfer_length_generic(struct xhci_xfer *xx, struct xhci_pipe *xp,
+int trb_idx)
+{
+   int  trb0_idx;
+   uint32_t len = 0, type;
+
+   trb0_idx =
+   ((xx->index + xp->ring.ntrb) - xx->ntrb) % (xp->ring.ntrb - 1);
+
+   while (1) {
+   type = xp->ring.trbs[trb0_idx].trb_flags & XHCI_TRB_TYPE_MASK;
+   if (type == XHCI_TRB_TYPE_NORMAL || type == XHCI_TRB_TYPE_DATA)
+   len += le32toh(XHCI_TRB_LEN(
+   xp->ring.trbs[trb0_idx].trb_status));
+   if (trb0_idx == trb_idx)
+   break;
+   if (++trb0_idx == xp->ring.ntrb)
+   trb0_idx = 0;
+   }
+   return len;
+}
+
 int
 xhci_event_xfer_generic(struct xhci_softc *sc, struct usbd_xfer *xfer,
 struct xhci_pipe *xp, uint32_t remain, int trb_idx,
@@ -819,16 +842,22 @@ xhci_event_xfer_generic(struct xhci_softc *sc, struct 
usbd_xfer *xfer,
 
switch (code) {
case XHCI_CODE_SUCCESS:
-   /*
-* This might be the last TRB of a TD that ended up
-* with a Short Transfer condition, see below.
-*/
-   if (xfer->actlen == 0)
-   xfer->actlen = xfer->length - remain;
+   if (xfer->actlen == 0) {
+   if (remain)
+   xfer->actlen =
+   xhci_xfer_length_generic(xx, xp, trb_idx) -
+   remain;
+   else
+   xfer->actlen = xfer->length;
+   }
xfer->status = USBD_NORMAL_COMPLETION;
break;
case XHCI_CODE_SHORT_XFER:
-   xfer->actlen = xfer->length - remain;
+   /*
+* Use values from the transfer TRB instead of the status TRB.
+*/
+   xfer->actlen = xhci_xfer_length_generic(xx, xp, trb_idx) -
+   remain;
/*
 * If this is not the last TRB of a transfer, we should
 * theoretically clear the IOC at the end of the chain



Re: fix xhci 'actlen' calculation

2019-11-12 Thread Patrick Wildt
On Tue, Nov 12, 2019 at 01:43:28PM +0100, Patrick Wildt wrote:
> On Tue, Nov 12, 2019 at 10:45:39AM +0100, Gerhard Roth wrote:
> > Hi,
> > 
> > xhci's calculation of 'xfer->actlen' is wrong if the xfer was split into
> > multiple TRBs. That's because the code just looks at the remainder
> > reported by the status TRB. However, this remainder only refers to the
> > total size of this single TRB; not to the total size of the xfer.
> > 
> > Example: assume a 16 kb xfer is split into two TRBs for 8 kb each.
> > Then we get a short read of 6 kb. The status TRB will refer
> > to the first TRB with remainder set to 2 kb. Currently xhci
> > would assume that actlen is 'xfer->length' (16 kb) minus the
> > remainder (2 kb). That yields a wrong actlen of 14 kb instead
> > of 6 kb.
> > 
> > The patch below fixes this by adding up all the remainders of all the
> > transfer TRBs up to the current one.
> > 
> > Gerhard
> > 
> 
> Very goood catch, this is very similar to the issue we had with isoc
> transfers.  Diff looks good to me!

Unfortunately this is *not* ok.  It turns out that this doesn't work
for short ctrl transfers.  Compared to bulk/intr transfers, ctrl xfers
have a setup, data and status trb.  Now your diff will sum all TRBs,
but the thing is that only the data TRB is actually short. :(  But I
think this should be easily fixable, I'll have a look.



Re: fix xhci 'actlen' calculation

2019-11-12 Thread Patrick Wildt
On Tue, Nov 12, 2019 at 10:45:39AM +0100, Gerhard Roth wrote:
> Hi,
> 
> xhci's calculation of 'xfer->actlen' is wrong if the xfer was split into
> multiple TRBs. That's because the code just looks at the remainder
> reported by the status TRB. However, this remainder only refers to the
> total size of this single TRB; not to the total size of the xfer.
> 
> Example: assume a 16 kb xfer is split into two TRBs for 8 kb each.
>   Then we get a short read of 6 kb. The status TRB will refer
>   to the first TRB with remainder set to 2 kb. Currently xhci
>   would assume that actlen is 'xfer->length' (16 kb) minus the
>   remainder (2 kb). That yields a wrong actlen of 14 kb instead
>   of 6 kb.
> 
> The patch below fixes this by adding up all the remainders of all the
> transfer TRBs up to the current one.
> 
> Gerhard
> 

Very goood catch, this is very similar to the issue we had with isoc
transfers.  Diff looks good to me!

> 
> Index: sys/dev/usb/xhci.c
> ===
> RCS file: /cvs/src/sys/dev/usb/xhci.c,v
> retrieving revision 1.106
> diff -u -p -u -p -r1.106 xhci.c
> --- sys/dev/usb/xhci.c6 Oct 2019 17:30:00 -   1.106
> +++ sys/dev/usb/xhci.c12 Nov 2019 09:29:47 -
> @@ -810,6 +810,28 @@ xhci_event_xfer(struct xhci_softc *sc, u
>   xhci_xfer_done(xfer);
>  }
>  
> +uint32_t
> +xhci_xfer_length_generic(struct xhci_xfer *xx, struct xhci_pipe *xp,
> +int trb_idx)
> +{
> + int  trb0_idx;
> + uint32_t len = 0;
> +
> + KASSERT(xx->index >= 0);
> + trb0_idx =
> + ((xx->index + xp->ring.ntrb) - xx->ntrb) % (xp->ring.ntrb - 1);
> +
> + while (1) {
> + len +=
> + le32toh(XHCI_TRB_LEN(xp->ring.trbs[trb0_idx].trb_status));
> + if (trb0_idx == trb_idx)
> + break;
> + if (++trb0_idx == xp->ring.ntrb)
> + trb0_idx = 0;
> + }
> + return len;
> +}
> +
>  int
>  xhci_event_xfer_generic(struct xhci_softc *sc, struct usbd_xfer *xfer,
>  struct xhci_pipe *xp, uint32_t remain, int trb_idx,
> @@ -823,12 +845,22 @@ xhci_event_xfer_generic(struct xhci_soft
>* This might be the last TRB of a TD that ended up
>* with a Short Transfer condition, see below.
>*/
> - if (xfer->actlen == 0)
> - xfer->actlen = xfer->length - remain;
> + if (xfer->actlen == 0) {
> + if (remain)
> + xfer->actlen =
> + xhci_xfer_length_generic(xx, xp, trb_idx) -
> + remain;
> + else
> + xfer->actlen = xfer->length;
> + }
>   xfer->status = USBD_NORMAL_COMPLETION;
>   break;
>   case XHCI_CODE_SHORT_XFER:
> - xfer->actlen = xfer->length - remain;
> + /*
> +  * Use values from the transfer TRB instead of the status TRB.
> +  */
> + xfer->actlen = xhci_xfer_length_generic(xx, xp, trb_idx) -
> + remain;
>   /*
>* If this is not the last TRB of a transfer, we should
>* theoretically clear the IOC at the end of the chain
> 



acpivout(4): backlights without method to query current level

2019-10-31 Thread Patrick Wildt
Hi,

some machines have no _BQC method, which is used to query the
current display backlight level.  We can still work on those by
starting with the highest level (when there's no _BQC method)
and keeping track of the current level.

Patrick

diff --git a/sys/dev/acpi/acpivideo.c b/sys/dev/acpi/acpivideo.c
index 9498465a418..a46a99a67f7 100644
--- a/sys/dev/acpi/acpivideo.c
+++ b/sys/dev/acpi/acpivideo.c
@@ -149,7 +149,7 @@ acpi_foundvout(struct aml_node *node, void *arg)
if (node->parent != sc->sc_devnode)
return (0);
 
-   if (aml_searchname(node, "_BCM") && aml_searchname(node, "_BQC")) {
+   if (aml_searchname(node, "_BCM")) {
memset(, 0, sizeof(aaa));
aaa.aaa_iot = sc->sc_acpi->sc_iot;
aaa.aaa_memt = sc->sc_acpi->sc_memt;
diff --git a/sys/dev/acpi/acpivout.c b/sys/dev/acpi/acpivout.c
index 5fb6973f595..b63ab5a08f3 100644
--- a/sys/dev/acpi/acpivout.c
+++ b/sys/dev/acpi/acpivout.c
@@ -60,6 +60,7 @@ struct acpivout_softc {
 
int *sc_bcl;
size_t  sc_bcl_len;
+   int sc_bcl_cur;
 };
 
 void   acpivout_brightness_cycle(struct acpivout_softc *);
@@ -113,10 +114,16 @@ acpivout_attach(struct device *parent, struct device 
*self, void *aux)
aml_register_notify(sc->sc_devnode, aaa->aaa_dev,
acpivout_notify, sc, ACPIDEV_NOPOLL);
 
+   acpivout_get_bcl(sc);
+   if (!sc->sc_bcl_len)
+   return;
+
+   sc->sc_bcl_cur = sc->sc_bcl[sc->sc_bcl_len - 1];
+   sc->sc_bcl_cur = acpivout_get_brightness(sc);
+   acpivout_set_brightness(sc, sc->sc_bcl_cur);
+
ws_get_param = acpivout_get_param;
ws_set_param = acpivout_set_param;
-
-   acpivout_get_bcl(sc);
 }
 
 int
@@ -200,7 +207,9 @@ acpivout_get_brightness(struct acpivout_softc *sc)
struct aml_value res;
int level;
 
-   aml_evalname(sc->sc_acpi, sc->sc_devnode, "_BQC", 0, NULL, );
+   if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_BQC", 0, NULL, ))
+   return sc->sc_bcl_cur;
+
level = aml_val2int();
aml_freevalue();
DPRINTF(("%s: BQC = %d\n", DEVNAME(sc), level));
@@ -242,6 +251,7 @@ acpivout_set_brightness(struct acpivout_softc *sc, int 
level)
aml_evalname(sc->sc_acpi, sc->sc_devnode, "_BCM", 1, , );
 
aml_freevalue();
+   sc->sc_bcl_cur = level;
 }
 
 void



Re: HID devices without numbered reports

2019-10-29 Thread Patrick Wildt
On Wed, Oct 30, 2019 at 08:07:06AM +1100, Damien Miller wrote:
> On Tue, 29 Oct 2019, Patrick Wildt wrote:
> 
> > Ok, so it turns out that this is related with opening/closing
> > the uhid(4) device.  Because every open(2) and close(2) also
> > opens and closes the pipe.  I think for ehci we somehow can
> > save the toggle and restore it on re-open, and for xhci we
> > somehow don't?
> 
> uhci isn't saving/restoring it either. Someone else reported no problems
> using ohci.

Actually, I think it does.  Look for "nexttoggle".  And "savedtoggle" in
ohci.

> > So I'm wondering if a) we should just keep the output pipe
> > open or b) there's some way to save/restore the... endpoint
> > context?  I'm looking into b) obviously.
> 
> Yeah, I spent some time reading xhci.c but couldn't figure out how
> interrupt transfers actually get sent - I could see them get enqueud
> but not where the got dequeued...

Interrupt transfers are just normal TRBs that are enqueued.  I think
that the state is saved by the controller in the endpoint context, and
then if you close the pipe you can "drop" the endpoint, while keeping
the state in the endpoint context, so an "add endpoint" restores that
context?  So I think the toggle is actually kept track of by the xHC
itself, in the endpoint context.  So maybe we clear to much of that
endpoint context when we re-open the pipe?

Patrick



Re: HID devices without numbered reports

2019-10-29 Thread Patrick Wildt
On Tue, Oct 29, 2019 at 05:41:55PM +0100, Patrick Wildt wrote:
> On Mon, Oct 28, 2019 at 12:07:20PM +1100, Damien Miller wrote:
> > On Mon, 28 Oct 2019, Damien Miller wrote:
> > 
> > > On Fri, 25 Oct 2019, Patrick Wildt wrote:
> > > 
> > > > > So from what I understood the Yubikey expects the transfer to happen
> > > > > on the Interrupt OUT pipe instead of doing a control transfer.  Read-
> > > > > ing some code and documentation, it looks like that we should by de-
> > > > > fault send our reports on the interrupt pipe, and only if it does not
> > > > > exist fall back to control transfers.  Linux seems to do exactly that.
> > > > > 
> > > > > I tried to come up with the following diff, which appeard to make a
> > > > > test program work for me.  Though I'm not sure I got all the specifics
> > > > > right.
> > > > > 
> > > > > Can you give this a go with your test progam?
> > > > > 
> > > > > Patrick
> > > > 
> > > > Oops, obvious error.  Though I still cannot write/read multiple times
> > > > in a row, so there is probably still something wrong (unless my test
> > > > is as well).
> > > 
> > > It didn't work for me - I think because uhidev_set_report() (and _async)
> > > is still prepending a report ID. If I modify uhid.c to send writes
> > > without a report ID, then it does work:
> > 
> > BTW, the token still becomes unresponsive after the first transaction,
> > but looking at a sniff (using an OpenViszla), it seems we're getting the
> > DATA0/DATA1 flipping incorrect on the wire.
> > 
> > On OpenBSD, this is the last rx of the transaction with the card:
> > 
> > []  12.992349 d=  0.001951 [154.0 +  3.500] [  3] IN   : 8.4
> > []  12.992352 d=  0.03 [154.0 +  6.667] [ 67] DATA0: 00 10 00 
> > 01 0e 1b 4a 78 ec 87 06 bd 47 d4 a0 49 d9 c7 2d 89 d9 7e 2c c5 62 87 53 92 
> > 9b 90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> > 00 00 00 00 00 00 00 00 00 00 00 3a e8
> > 
> > and this is the first tx of the first packet of the subsequent transaction
> > that hangs:
> > 
> > []  22.201067 d=  0.001998 [146.0 +  4.333] [  3] OUT  : 8.4
> > []  22.201070 d=  0.03 [146.0 +  7.583] [ 67] DATA0: ff ff ff 
> > ff 86 00 08 c0 65 eb 53 9a 48 04 7d 00 00 00 00 00 00 00 00 00 00 00 00 00 
> > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> > 00 00 00 00 00 00 00 00 00 00 00 d6 1d
> > 
> > On Linux, the sequence bit does get flipped between the last rx:
> > 
> > []  14.174783 d=  0.001951 [214.0 +  3.417] [  3] IN   : 24.4
> > []  14.174786 d=  0.03 [214.0 +  6.583] [ 67] DATA0: 00 12 00 
> > 01 0e 2e 25 14 32 f4 a4 68 d1 81 d1 29 e1 47 6f 4c 7d e2 69 dc b9 96 e5 f5 
> > 23 90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> > 00 00 00 00 00 00 00 00 00 00 00 be 67
> > 
> > and the tx of the next attempt:
> > 
> > []  20.057155 d=  0.001997 [208.0 +  3.417] [  3] OUT  : 24.4
> > []  20.057158 d=  0.03 [208.0 +  6.667] [ 67] DATA1: ff ff ff 
> > ff 86 00 08 82 40 e5 bf c6 94 7e e8 00 00 00 00 00 00 00 00 00 00 00 00 00 
> > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> > 00 00 00 00 00 00 00 00 00 00 00 22 8b
> > 
> > I think it's losing the sequence bit state across open/close of
> > /dev/uhidX - If I try to do two transactions without an intervening
> > close/open then it seems to work...
> > 
> > -d
> 
> I have also sniffed this on both OpenBSD with xhci(4) and some
> Linux.  Turns out, yes, we're always doing DATA0 instead of
> toggling to DATA1 and back.  But I'm not sure where exactly
> this happens.  I'll investigate.
> 
> Patrick

Ok, so it turns out that this is related with opening/closing
the uhid(4) device.  Because every open(2) and close(2) also
opens and closes the pipe.  I think for ehci we somehow can
save the toggle and restore it on re-open, and for xhci we
somehow don't?

So I'm wondering if a) we should just keep the output pipe
open or b) there's some way to save/restore the... endpoint
context?  I'm looking into b) obviously.

Patrick



Re: HID devices without numbered reports

2019-10-29 Thread Patrick Wildt
On Mon, Oct 28, 2019 at 12:07:20PM +1100, Damien Miller wrote:
> On Mon, 28 Oct 2019, Damien Miller wrote:
> 
> > On Fri, 25 Oct 2019, Patrick Wildt wrote:
> > 
> > > > So from what I understood the Yubikey expects the transfer to happen
> > > > on the Interrupt OUT pipe instead of doing a control transfer.  Read-
> > > > ing some code and documentation, it looks like that we should by de-
> > > > fault send our reports on the interrupt pipe, and only if it does not
> > > > exist fall back to control transfers.  Linux seems to do exactly that.
> > > > 
> > > > I tried to come up with the following diff, which appeard to make a
> > > > test program work for me.  Though I'm not sure I got all the specifics
> > > > right.
> > > > 
> > > > Can you give this a go with your test progam?
> > > > 
> > > > Patrick
> > > 
> > > Oops, obvious error.  Though I still cannot write/read multiple times
> > > in a row, so there is probably still something wrong (unless my test
> > > is as well).
> > 
> > It didn't work for me - I think because uhidev_set_report() (and _async)
> > is still prepending a report ID. If I modify uhid.c to send writes
> > without a report ID, then it does work:
> 
> BTW, the token still becomes unresponsive after the first transaction,
> but looking at a sniff (using an OpenViszla), it seems we're getting the
> DATA0/DATA1 flipping incorrect on the wire.
> 
> On OpenBSD, this is the last rx of the transaction with the card:
> 
> []  12.992349 d=  0.001951 [154.0 +  3.500] [  3] IN   : 8.4
> []  12.992352 d=  0.03 [154.0 +  6.667] [ 67] DATA0: 00 10 00 01 
> 0e 1b 4a 78 ec 87 06 bd 47 d4 a0 49 d9 c7 2d 89 d9 7e 2c c5 62 87 53 92 9b 90 
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> 00 00 00 00 00 00 00 00 3a e8
> 
> and this is the first tx of the first packet of the subsequent transaction
> that hangs:
> 
> []  22.201067 d=  0.001998 [146.0 +  4.333] [  3] OUT  : 8.4
> []  22.201070 d=  0.03 [146.0 +  7.583] [ 67] DATA0: ff ff ff ff 
> 86 00 08 c0 65 eb 53 9a 48 04 7d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> 00 00 00 00 00 00 00 00 d6 1d
> 
> On Linux, the sequence bit does get flipped between the last rx:
> 
> []  14.174783 d=  0.001951 [214.0 +  3.417] [  3] IN   : 24.4
> []  14.174786 d=  0.03 [214.0 +  6.583] [ 67] DATA0: 00 12 00 01 
> 0e 2e 25 14 32 f4 a4 68 d1 81 d1 29 e1 47 6f 4c 7d e2 69 dc b9 96 e5 f5 23 90 
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> 00 00 00 00 00 00 00 00 be 67
> 
> and the tx of the next attempt:
> 
> []  20.057155 d=  0.001997 [208.0 +  3.417] [  3] OUT  : 24.4
> []  20.057158 d=  0.03 [208.0 +  6.667] [ 67] DATA1: ff ff ff ff 
> 86 00 08 82 40 e5 bf c6 94 7e e8 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> 00 00 00 00 00 00 00 00 22 8b
> 
> I think it's losing the sequence bit state across open/close of
> /dev/uhidX - If I try to do two transactions without an intervening
> close/open then it seems to work...
> 
> -d

I have also sniffed this on both OpenBSD with xhci(4) and some
Linux.  Turns out, yes, we're always doing DATA0 instead of
toggling to DATA1 and back.  But I'm not sure where exactly
this happens.  I'll investigate.

Patrick



Re: HID devices without numbered reports

2019-10-28 Thread Patrick Wildt
On Mon, Oct 28, 2019 at 03:14:22PM +1100, Damien Miller wrote:
> On Mon, 28 Oct 2019, Damien Miller wrote:
> 
> > BTW, the token still becomes unresponsive after the first transaction,
> > but looking at a sniff (using an OpenViszla), it seems we're getting the
> > DATA0/DATA1 flipping incorrect on the wire.
> > 
> > On OpenBSD, this is the last rx of the transaction with the card:
> > 
> > []  12.992349 d=  0.001951 [154.0 +  3.500] [  3] IN   : 8.4
> > []  12.992352 d=  0.03 [154.0 +  6.667] [ 67] DATA0: 00 10 00 
> > 01 0e 1b 4a 78 ec 87 06 bd 47 d4 a0 49 d9 c7 2d 89 d9 7e 2c c5 62 87 53 92 
> > 9b 90 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> > 00 00 00 00 00 00 00 00 00 00 00 3a e8
> > 
> > and this is the first tx of the first packet of the subsequent transaction
> > that hangs:
> > 
> > []  22.201067 d=  0.001998 [146.0 +  4.333] [  3] OUT  : 8.4
> > []  22.201070 d=  0.03 [146.0 +  7.583] [ 67] DATA0: ff ff ff 
> > ff 86 00 08 c0 65 eb 53 9a 48 04 7d 00 00 00 00 00 00 00 00 00 00 00 00 00 
> > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> > 00 00 00 00 00 00 00 00 00 00 00 d6 1d
> 
> Since I don't really understand how USB sequence numbers work, it just
> occurred to me to check the sequence bit on the last sent packet.
> It too is a DATA0, so the sequence is definitiely getting lost across
> close+open.
> 
> Here's an annotated trace - starting with the last command sent to
> a Yk5 token during key enrollment:
> 
> []   9.212345 d=  0.001992 [  2   +  4.333] [  3] OUT  : 10.4 
> []   9.212349 d=  0.03 [  2   +  7.583] [ 67] DATA1: 00 13 00 01 
> 83 00 47 00 01 00 00 00 00 40 a9 dc 95 51 0e ec 44 6d 7a b1 14 88 d1 84 93 b4 
> aa d2 e5 10 11 db 9c fa b4 b3 0b 89 2c ea 3f b9 e3 06 10 e8 a1 62 11 59 60 fe 
> 1e c2 23 e6 52 9c 9f 4b 8a c8 
> []   9.212395 d=  0.46 [  2   + 53.750] [  1] ACK 
> []   9.212397 d=  0.02 [  2   + 55.667] [  3] IN   : 10.4 
> []   9.212400 d=  0.03 [  2   + 58.833] [  1] NAK 
> []   9.214346 d=  0.001946 [  4   +  4.500] [  3] OUT  : 10.4 
> []   9.214349 d=  0.03 [  4   +  7.750] [ 67] DATA0: 00 13 00 01 
> 00 6e 80 20 0d cb 5e 5c 32 1c 8a f1 e2 b1 bf 00 00 00 00 00 00 00 00 00 00 00 
> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
> 00 00 00 00 00 00 00 00 11 7c 
> []   9.214395 d=  0.46 [  4   + 53.750] [  1] ACK 
> []   9.214397 d=  0.02 [  4   + 55.667] [  3] IN   : 10.4 
> []   9.214400 d=  0.03 [  4   + 58.833] [  1] NAK 
> []   9.216345 d=  0.001945 [  6   +  4.000] [  3] IN   : 10.4 
> []   9.216349 d=  0.03 [  6   +  7.167] [  1] NAK 
> 
> Note that the last OUT was a DATA0.
> 
> The token replies with a bunch of data:
> 
> []   9.350355 d=  0.001997 [140   +  3.250] [  3] IN   : 10.4 
> []   9.350358 d=  0.03 [140   +  6.417] [ 67] DATA1: 00 13 00 01 
> 83 03 8d 05 04 f6 80 b1 df 4d 8e fe 30 cd a0 2c 42 e1 a1 46 52 9f 8a 06 80 21 
> 78 7a 73 71 e3 f3 0a e6 f6 e0 74 54 ef df 0c 74 ed be 3f 35 1d dd 35 cf 33 14 
> fc 33 6e b6 45 11 bd f5 79 99 
> []   9.350404 d=  0.46 [140   + 52.417] [  1] ACK 
> []   9.352356 d=  0.001951 [142   +  3.750] [  3] IN   : 10.4 
> []   9.352359 d=  0.03 [142   +  6.917] [ 67] DATA0: 00 13 00 01 
> 00 61 98 66 2c 14 5f 65 e5 4c 40 df 01 56 e8 d8 2b e8 f7 a8 ff 00 96 a6 f3 95 
> 00 d9 93 87 cb c8 b1 02 23 ec 8f 38 37 b8 cf da 73 62 18 90 ff 8b 01 cf a1 78 
> 61 3e cc 48 ac 7b 45 4f b0 6b 
> []   9.352405 d=  0.46 [142   + 53.167] [  1] ACK 
> []   9.354356 d=  0.001950 [144   +  3.500] [  3] IN   : 10.4 
> []   9.354359 d=  0.03 [144   +  6.667] [ 67] DATA1: 00 13 00 01 
> 01 4a 0d 3a 6d d7 ca fc 00 e1 ad 7e 78 b1 9d 88 30 82 02 bd 30 82 01 a5 a0 03 
> 02 01 02 02 04 18 ac 46 c0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05 00 30 2e 
> 31 2c 30 2a 06 03 55 04 83 af 
> []   9.354405 d=  0.46 [144   + 52.833] [  1] ACK 
> []   9.356356 d=  0.001951 [146   +  3.583] [  3] IN   : 10.4 
> []   9.356359 d=  0.03 [146   +  6.750] [ 67] DATA0: 00 13 00 01 
> 02 03 13 23 59 75 62 69 63 6f 20 55 32 46 20 52 6f 6f 74 20 43 41 20 53 65 72 
> 69 61 6c 20 34 35 37 32 30 30 36 33 31 30 20 17 0d 31 34 30 38 30 31 30 30 30 
> 30 30 30 5a 18 0f 32 30 98 68 
> []   9.356405 d=  0.46 [146   + 52.667] [  1] ACK 
> []   9.358356 d=  0.001951 [148   +  3.583] [  3] IN   : 10.4 
> []   9.358359 d=  0.03 [148   +  6.750] [ 67] DATA1: 00 13 00 01 
> 03 35 30 30 39 30 34 30 30 30 30 30 30 5a 30 6e 31 0b 30 09 06 03 55 04 06 13 
> 02 53 45 31 12 30 10 06 03 55 04 0a 0c 09 59 75 62 69 63 6f 20 41 42 31 22 30 
> 20 06 03 55 04 0b 0c 19 69 76 
> []   9.358405 d=  0.46 [148   + 52.667] [  1] ACK 
> []   9.360357 d=  0.001952 [150   +  4.833] [  

Re: HID devices without numbered reports

2019-10-25 Thread Patrick Wildt
On Fri, Oct 25, 2019 at 03:59:25PM +0200, Patrick Wildt wrote:
> On Fri, Oct 25, 2019 at 03:10:48PM +1100, Damien Miller wrote:
> > Hi,
> > 
> > Some HID devices do not list any report IDs for communication, e.g. my
> > Yubikey5:
> > 
> > > uhidev0: iclass 3/0
> > > uhid0 at uhidev0: input=64, output=64, feature=0
> > > ugen0 at uhub0 port 2 configuration 1 "Yubico YubiKey FIDO+CCID" rev 
> > > 2.00/5.12 addr 2
> > 
> > on Linux, these can be talked to by sending to report ID 0. This AFAIK
> > causes the write(2)'d data to be sent to the interrupt pipe.
> > 
> > Our uhid(4) devices already consider write(2) operations to be
> > equivalent to USB_SET_REPORT to the UHID_OUTPUT_REPORT, so we can't
> > use that. So this patch allows USB_SET_REPORT with ucr_report=0
> > to do something similar to what Linux does.
> > 
> > Caveat: this is literally my first attempt at writing USB code, and
> > I ended up futzing with the kernel.
> 
> So from what I understood the Yubikey expects the transfer to happen
> on the Interrupt OUT pipe instead of doing a control transfer.  Read-
> ing some code and documentation, it looks like that we should by de-
> fault send our reports on the interrupt pipe, and only if it does not
> exist fall back to control transfers.  Linux seems to do exactly that.
> 
> I tried to come up with the following diff, which appeard to make a
> test program work for me.  Though I'm not sure I got all the specifics
> right.
> 
> Can you give this a go with your test progam?
> 
> Patrick

Oops, obvious error.  Though I still cannot write/read multiple times
in a row, so there is probably still something wrong (unless my test
is as well).

diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c
index 7c02c82f7d5..73de7aeaf56 100644
--- a/sys/dev/usb/uhidev.c
+++ b/sys/dev/usb/uhidev.c
@@ -97,6 +97,7 @@ int uhidev_detach(struct device *, int);
 int uhidev_activate(struct device *, int);
 
 void uhidev_get_report_async_cb(struct usbd_xfer *, void *, usbd_status);
+void uhidev_set_report_async_cb(struct usbd_xfer *, void *, usbd_status);
 
 struct cfdriver uhidev_cd = {
NULL, "uhidev", DV_DULL
@@ -670,14 +671,23 @@ uhidev_set_report(struct uhidev_softc *sc, int type, int 
id, void *data,
memcpy(buf + 1, data, len - 1);
}
 
-   req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
-   req.bRequest = UR_SET_REPORT;
-   USETW2(req.wValue, type, id);
-   USETW(req.wIndex, sc->sc_ifaceno);
-   USETW(req.wLength, len);
+   if (sc->sc_opipe != NULL) {
+   usbd_setup_xfer(sc->sc_owxfer, sc->sc_opipe, 0, buf, len,
+   USBD_SYNCHRONOUS | USBD_CATCH, 0, NULL);
+   if (usbd_transfer(sc->sc_owxfer)) {
+   usbd_clear_endpoint_stall(sc->sc_opipe);
+   actlen = -1;
+   }
+   } else {
+   req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
+   req.bRequest = UR_SET_REPORT;
+   USETW2(req.wValue, type, id);
+   USETW(req.wIndex, sc->sc_ifaceno);
+   USETW(req.wLength, len);
 
-   if (usbd_do_request(sc->sc_udev, , buf))
-   actlen = -1;
+   if (usbd_do_request(sc->sc_udev, , buf))
+   actlen = -1;
+   }
 
if (id > 0)
free(buf, M_TEMP, len);
@@ -685,6 +695,16 @@ uhidev_set_report(struct uhidev_softc *sc, int type, int 
id, void *data,
return (actlen);
 }
 
+void
+uhidev_set_report_async_cb(struct usbd_xfer *xfer, void *priv, usbd_status err)
+{
+   struct uhidev_softc *sc = priv;
+
+   if (err == USBD_STALLED)
+   usbd_clear_endpoint_stall_async(sc->sc_opipe);
+   usbd_free_xfer(xfer);
+}
+
 int
 uhidev_set_report_async(struct uhidev_softc *sc, int type, int id, void *data,
 int len)
@@ -715,14 +735,23 @@ uhidev_set_report_async(struct uhidev_softc *sc, int 
type, int id, void *data,
memcpy(buf, data, len);
}
 
-   req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
-   req.bRequest = UR_SET_REPORT;
-   USETW2(req.wValue, type, id);
-   USETW(req.wIndex, sc->sc_ifaceno);
-   USETW(req.wLength, len);
-
-   if (usbd_request_async(xfer, , NULL, NULL))
-   actlen = -1;
+   if (sc->sc_opipe != NULL) {
+   usbd_setup_xfer(xfer, sc->sc_opipe, sc, buf, len,
+   USBD_NO_COPY, USBD_DEFAULT_TIMEOUT,
+   uhidev_set_report_async_cb);
+   if (usbd_transfer(xfer)) {
+   usbd_clear_endpoint_stall_async(sc->sc_opipe);
+   actlen = -1;
+   }
+   } else {
+   req.bmRequestType = UT_WRITE_CLASS_INTERFACE;

Re: HID devices without numbered reports

2019-10-25 Thread Patrick Wildt
On Fri, Oct 25, 2019 at 03:10:48PM +1100, Damien Miller wrote:
> Hi,
> 
> Some HID devices do not list any report IDs for communication, e.g. my
> Yubikey5:
> 
> > uhidev0: iclass 3/0
> > uhid0 at uhidev0: input=64, output=64, feature=0
> > ugen0 at uhub0 port 2 configuration 1 "Yubico YubiKey FIDO+CCID" rev 
> > 2.00/5.12 addr 2
> 
> on Linux, these can be talked to by sending to report ID 0. This AFAIK
> causes the write(2)'d data to be sent to the interrupt pipe.
> 
> Our uhid(4) devices already consider write(2) operations to be
> equivalent to USB_SET_REPORT to the UHID_OUTPUT_REPORT, so we can't
> use that. So this patch allows USB_SET_REPORT with ucr_report=0
> to do something similar to what Linux does.
> 
> Caveat: this is literally my first attempt at writing USB code, and
> I ended up futzing with the kernel.

So from what I understood the Yubikey expects the transfer to happen
on the Interrupt OUT pipe instead of doing a control transfer.  Read-
ing some code and documentation, it looks like that we should by de-
fault send our reports on the interrupt pipe, and only if it does not
exist fall back to control transfers.  Linux seems to do exactly that.

I tried to come up with the following diff, which appeard to make a
test program work for me.  Though I'm not sure I got all the specifics
right.

Can you give this a go with your test progam?

Patrick

diff --git a/sys/dev/usb/uhidev.c b/sys/dev/usb/uhidev.c
index 7c02c82f7d5..6f30f11855c 100644
--- a/sys/dev/usb/uhidev.c
+++ b/sys/dev/usb/uhidev.c
@@ -97,6 +97,7 @@ int uhidev_detach(struct device *, int);
 int uhidev_activate(struct device *, int);
 
 void uhidev_get_report_async_cb(struct usbd_xfer *, void *, usbd_status);
+void uhidev_set_report_async_cb(struct usbd_xfer *, void *, usbd_status);
 
 struct cfdriver uhidev_cd = {
NULL, "uhidev", DV_DULL
@@ -670,14 +671,23 @@ uhidev_set_report(struct uhidev_softc *sc, int type, int 
id, void *data,
memcpy(buf + 1, data, len - 1);
}
 
-   req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
-   req.bRequest = UR_SET_REPORT;
-   USETW2(req.wValue, type, id);
-   USETW(req.wIndex, sc->sc_ifaceno);
-   USETW(req.wLength, len);
+   if (sc->sc_opipe != NULL) {
+   usbd_setup_xfer(sc->sc_owxfer, sc->sc_opipe, 0, buf, len,
+   USBD_SYNCHRONOUS | USBD_CATCH, 0, NULL);
+   if (usbd_transfer(sc->sc_owxfer)) {
+   usbd_clear_endpoint_stall(sc->sc_opipe);
+   actlen = -1;
+   }
+   } else {
+   req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
+   req.bRequest = UR_SET_REPORT;
+   USETW2(req.wValue, type, id);
+   USETW(req.wIndex, sc->sc_ifaceno);
+   USETW(req.wLength, len);
 
-   if (usbd_do_request(sc->sc_udev, , buf))
-   actlen = -1;
+   if (usbd_do_request(sc->sc_udev, , buf))
+   actlen = -1;
+   }
 
if (id > 0)
free(buf, M_TEMP, len);
@@ -685,6 +695,16 @@ uhidev_set_report(struct uhidev_softc *sc, int type, int 
id, void *data,
return (actlen);
 }
 
+void
+uhidev_set_report_async_cb(struct usbd_xfer *xfer, void *priv, usbd_status err)
+{
+   struct uhidev_softc *sc = priv;
+
+   if (err == USBD_STALLED)
+   usbd_clear_endpoint_stall_async(sc->sc_opipe);
+   usbd_free_xfer(xfer);
+}
+
 int
 uhidev_set_report_async(struct uhidev_softc *sc, int type, int id, void *data,
 int len)
@@ -715,11 +735,21 @@ uhidev_set_report_async(struct uhidev_softc *sc, int 
type, int id, void *data,
memcpy(buf, data, len);
}
 
-   req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
-   req.bRequest = UR_SET_REPORT;
-   USETW2(req.wValue, type, id);
-   USETW(req.wIndex, sc->sc_ifaceno);
-   USETW(req.wLength, len);
+   if (sc->sc_opipe != NULL) {
+   usbd_setup_xfer(xfer, sc->sc_opipe, sc, buf, len,
+   USBD_NO_COPY, USBD_DEFAULT_TIMEOUT,
+   uhidev_set_report_async_cb);
+   if (usbd_transfer(xfer)) {
+   usbd_clear_endpoint_stall(sc->sc_opipe);
+   actlen = -1;
+   }
+   } else {
+   req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
+   req.bRequest = UR_SET_REPORT;
+   USETW2(req.wValue, type, id);
+   USETW(req.wIndex, sc->sc_ifaceno);
+   USETW(req.wLength, len);
+   }
 
if (usbd_request_async(xfer, , NULL, NULL))
actlen = -1;



Re: Fix libcompiler_rt __clear_cache() on armv7

2019-09-28 Thread Patrick Wildt
Committed, thanks!

On Wed, Sep 25, 2019 at 09:45:41AM -0700, Josh Elsasser wrote:
> I came across some code which uses __clear_cache() from
> libgcc/libcompiler_rt on 32-bit arm. Currently that just falls through
> to abort(), but enabling the existing sysarch() code works for me.
> 
> diff --git a/lib/libcompiler_rt/clear_cache.c 
> b/lib/libcompiler_rt/clear_cache.c
> index 451f1c0b124..4902d761b81 100644
> --- a/lib/libcompiler_rt/clear_cache.c
> +++ b/lib/libcompiler_rt/clear_cache.c
> @@ -33,7 +33,7 @@ uintptr_t GetCurrentProcess(void);
>#include 
>  #endif
>  
> -#if defined(__OpenBSD__) && defined(__mips__)
> +#if defined(__OpenBSD__) && (defined(__mips__) || defined(__arm__))
>#include 
>#include 
>  #endif
> @@ -102,7 +102,7 @@ void __clear_cache(void *start, void *end) {
>   * so there is nothing to do
>   */
>  #elif defined(__arm__) && !defined(__APPLE__)
> -#if defined(__FreeBSD__) || defined(__NetBSD__)
> +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
>  struct arm_sync_icache_args arg;
>  
>  arg.addr = (uintptr_t)start;
> 



Re: wsmouse(4): reverse scroll directions

2019-08-19 Thread Patrick Wildt
On Sun, Aug 18, 2019 at 08:36:28PM +0200, Ulf Brosziewski wrote:
> With the introduction of precision scrolling, it is no longer possible to
> reverse scroll directions for touchpads by means of button mappings in X.
> This patch adds a configuration option to wsmouse and a boolean field
> named
> 
> wsmouse*.reverse_scrolling
> 
> to wsconsctl.  The option is valid for both mice and touchpads; if it has
> a non-zero value, wsmouse inverts the sign of the values of wheel events
> and of the scroll events generated by touchpads.
> 
> Apple has made the inverted mapping popular as "natural scrolling", and
> some people may even attribute the opposite meaning to the field name.
> However, I couldn't persuade myself to declare that the classical way of
> scrolling is less "natural".
> 
> OK?
> 

I think you added the wsconsctl diff two times in your mail.

Anyway, the diff works great for me, and I'm fine with it being
called "reverse_scrolling".  Diff looks good to me, ok patrick@.
Thanks!



Re: arm64: softraid boot

2019-08-02 Thread Patrick Wildt
On Fri, Aug 02, 2019 at 03:16:55PM -0400, sven falempin wrote:
> Dear ARM gurus,
> 
> I m trying to tftp boot last snaphots on pine64+.
> Not sure if it s possible.
> So far I tried loading minitroot like an idiot and then, a boolader,
> now I cant get the efi bootloader to do some tftp ( which I guess is normal  )
> But maybe I am just missing a small pieces.

Hi,

our efiboot/BOOTAA64.EFI checks for the DHCP ack received bit to see
if we should look at the the contents of the DHCP ack for the address
information.

U-Boot unfortunately does not set it, and I have been trying to up-
stream that change on and off a few times:

https://marc.info/?l=u-boot=155488833610034=2

Thus, my bet is that it doesn't work because of the missing bit.

Patrick

> I also created etc/boot.conf in the tftp directory.. just in case.
> 
> getting some bsd code to boot :
> 
> => dhcp
> BOOTP broadcast 1
> DHCP client bound to address 172.16.65.55 (1445 ms)
> Using ethernet@01c3 device
> TFTP from server 172.16.65.1; our IP address is 172.16.65.55
> Filename 'BOOTAA64.EFI'.
> Load address: 0x4200
> Loading: ###
>  5.1 MiB/s
> done
> => bootefi 0x4200
> ## Starting EFI application at 4200 ...
> Scanning disks on usb...
> Disk usb0 not ready
> Disk usb1 not ready
> Disk usb2 not ready
> Disk usb3 not ready
> Scanning disks on mmc...
> MMC Device 1 not found
> MMC Device 2 not found
> MMC Device 3 not found
> Found 3 disks
> WARNING: Invalid device tree, expect boot to fail
> disks: sd0
> >> OpenBSD/arm64 BOOTAA64 0.16
> open(tftp0a:/etc/boot.conf): Operation not permitted
> boot>
> booting tftp0a:/bsd: open tftp0a:/bsd: Operation not permitted
>  failed(1). will try /bsd
> boot>
> booting tftp0a:/bsd: open tftp0a:/bsd: Operation not permitted
>  failed(1). will try /bsd
> Turning timeout off.
> boot> l
> stat(tftp0a:/.): Operation not permitted
> boot> l
> stat(tftp0a:/.): Operation not permitted
> boot> l
> stat(tftp0a:/.): Operation not permitted
> boot> boot tftp:bsd.rd
> cannot open tftp:/etc/random.seed: bad drive number
> booting tftp:bsd.rd: open tftp:bsd.rd: bad drive number
>  failed(98). will try /bsd
> boot> boot 172.16.65.1:/bsd.rd
> boot> boot tftp:/bsd.rd
> cannot open tftp:/etc/random.seed: bad drive number
> booting tftp:/bsd.rd: open tftp:/bsd.rd: bad drive number
>  failed(98). will try /bsd
> boot> boot tftp0a:/bsd.rd
> booting tftp0a:/bsd.rd: open tftp0a:/bsd.rd: Operation not permitted
>  failed(1). will try /bsd
> 
> is there some kind of trick to boot this ?
> 
> 
> On Thu, Jan 31, 2019 at 7:54 AM Mark Kettenis  wrote:
> >
> > > Date: Wed, 30 Jan 2019 22:31:31 +0100
> > > From: Patrick Wildt 
> > >
> > > Hi,
> > >
> > > to boot a pinebook with softraid crypto there are three parts that need
> > > to be implemented, which this diff hopefully does well enough.
> > >
> > > First, our EFI bootloader so far only supports one disk, so we need to
> > > extend this so we can see all connected block devices.  The second part
> > > is adding the softraid code, which probes for softraid partitions on the
> > > block devices and "spawns" its own block device.  At last, we need to
> > > push the softraid uuid and key up to the kernel.
> > >
> > > Pushing the informaton to the kernel is the easiest part.  We can add
> > > another openbsd-specific property in the device tree which we read out
> > > early on, so that we can zero the space in the device tree so it can not
> > > be read by anyone else.
> > >
> > > For the other part there's a bit more to do.  Very early on efiboot
> > > looks for the boot device.  While doing that, we create a list of block
> > > devices.  While there, already try to read the disklabel because after
> > > this the softraid probing needs to know the partition table.
> > >
> > > We then call srprobe() which will go over the disklist to look for a
> > > disk that contains RAID volumes, but calling the disk's diskio and
> > > strategy function to read from the device.  This creates the sr_volumes
> > > list of softraid volumes.  The MI boot code will then look for the boot
> > > device name by calling devboot().  If we don't have the device path for
> > > the boot device, it's a PXE boot.  Otherwise we will find it in either
> > > the disklist or sr_volumes list.
> > >
> > > The next part is the MI code opening the device, looking for a file-
> > > system.  The boot device name now is e.g. sr0a, which will th

uvideo(4): support IR video format

2019-07-05 Thread Patrick Wildt
Hi,

the second camrea on my Lenovo X395 is an "IR" camera that produces some
greyscale picture.  video(1) doesn't support that format, but with this
patch I can use

 $ ffmpeg -f v4l2 -i /dev/video1 test.mp4
 $ mplayer test.mp4

to record and show the video correctly.

Patrick

diff --git a/sys/dev/usb/uvideo.c b/sys/dev/usb/uvideo.c
index 0c382b39071..fbf058073ad 100644
--- a/sys/dev/usb/uvideo.c
+++ b/sys/dev/usb/uvideo.c
@@ -989,6 +1067,7 @@ uvideo_vs_parse_desc_format_uncompressed(struct 
uvideo_softc *sc,
 const usb_descriptor_t *desc)
 {
struct usb_video_format_uncompressed_desc *d;
+   uint8_t format_ir_8bit[16] = UVIDEO_FORMAT_GUID_KSMEDIA_L8_IR;
int i;
 
d = (struct usb_video_format_uncompressed_desc *)(uint8_t *)desc;
@@ -1021,6 +1100,9 @@ uvideo_vs_parse_desc_format_uncompressed(struct 
uvideo_softc *sc,
sc->sc_fmtgrp[i].pixelformat = V4L2_PIX_FMT_NV12;
} else if (!strcmp(sc->sc_fmtgrp[i].format->u.uc.guidFormat, "UYVY")) {
sc->sc_fmtgrp[i].pixelformat = V4L2_PIX_FMT_UYVY;
+   } else if (!memcmp(sc->sc_fmtgrp[i].format->u.uc.guidFormat,
+   format_ir_8bit, 16)) {
+   sc->sc_fmtgrp[i].pixelformat = V4L2_PIX_FMT_GREY;
} else {
sc->sc_fmtgrp[i].pixelformat = 0;
}
diff --git a/sys/dev/usb/uvideo.h b/sys/dev/usb/uvideo.h
index dbc089e7e21..a952c829fef 100644
--- a/sys/dev/usb/uvideo.h
+++ b/sys/dev/usb/uvideo.h
@@ -308,6 +308,10 @@ struct usb_video_probe_commit {
 0x55, 0x59, 0x56, 0x59, 0x00, 0x00, 0x10, 0x00,\
 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38,0x9b, 0x71 }
 
+#defineUVIDEO_FORMAT_GUID_KSMEDIA_L8_IR{   \
+0x32, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00,\
+0x80, 0x00, 0x00, 0xaa, 0x00, 0x38,0x9b, 0x71 }
+
 /*
  * USB Video Payload MJPEG
  */



uvideo(4): dynamic max ctrl size

2019-07-04 Thread Patrick Wildt
Hi,

on my Lenovo X395 the uvideo(4) follows the current UVC 1.5 spec.  The
message length was increased with each specification, so now the buffer
for probe messages is up to 48 bytes.  On that particular device the
camera sends a USB stall if we only supply the 26 bytes from the
original UVC 1.0 spec.  By increasing the length depending on the UVC
version, and the other diff I sent, my webcam works fine.

Patrick

diff --git a/sys/dev/usb/uvideo.c b/sys/dev/usb/uvideo.c
index 1a9dfc733fa..3cb93158955 100644
--- a/sys/dev/usb/uvideo.c
+++ b/sys/dev/usb/uvideo.c
@@ -67,6 +67,7 @@ struct uvideo_softc {
struct device   *sc_videodev;
 
int  sc_enabled;
+   int  sc_max_ctrl_size;
int  sc_max_fbuf_size;
int  sc_negotiated_flag;
int  sc_frame_rate;
@@ -725,6 +726,12 @@ uvideo_vc_parse_desc_header(struct uvideo_softc *sc,

sc->sc_desc_vc_header.fix = d;
sc->sc_desc_vc_header.baInterfaceNr = (uByte *)(d + 1);
+   if (UGETW(d->bcdUVC) < 0x0110)
+   sc->sc_max_ctrl_size = 26;
+   else if (UGETW(d->bcdUVC) < 0x0150)
+   sc->sc_max_ctrl_size = 34;
+   else
+   sc->sc_max_ctrl_size = 48;
 
return (USBD_NORMAL_COMPLETION);
 }
@@ -1438,7 +1445,7 @@ uvideo_vs_negotiation(struct uvideo_softc *sc, int commit)
struct usb_video_header_desc *hd;
struct usb_video_frame_desc *frame;
uint8_t *p, *cur;
-   uint8_t probe_data[34];
+   uint8_t probe_data[48];
uint32_t frame_ival, nivals, min, max, step, diff;
usbd_status error;
int i, ival_bytes, changed = 0;
@@ -1622,7 +1629,7 @@ uvideo_vs_set_probe(struct uvideo_softc *sc, uint8_t 
*probe_data)
tmp = tmp << 8;
USETW(req.wValue, tmp);
USETW(req.wIndex, sc->sc_vs_cur->iface);
-   USETW(req.wLength, 26);
+   USETW(req.wLength, sc->sc_max_ctrl_size);
 
pc = (struct usb_video_probe_commit *)probe_data;
 
@@ -1667,7 +1674,7 @@ uvideo_vs_get_probe(struct uvideo_softc *sc, uint8_t 
*probe_data,
tmp = tmp << 8;
USETW(req.wValue, tmp);
USETW(req.wIndex, sc->sc_vs_cur->iface);
-   USETW(req.wLength, 26);
+   USETW(req.wLength, sc->sc_max_ctrl_size);
 
pc = (struct usb_video_probe_commit *)probe_data;
 
@@ -1710,7 +1717,7 @@ uvideo_vs_set_commit(struct uvideo_softc *sc, uint8_t 
*probe_data)
tmp = tmp << 8;
USETW(req.wValue, tmp);
USETW(req.wIndex, sc->sc_vs_cur->iface);
-   USETW(req.wLength, 26);
+   USETW(req.wLength, sc->sc_max_ctrl_size);
 
error = usbd_do_request(sc->sc_udev, , probe_data);
if (error) {



uvideo(4): dump interface association descriptor

2019-07-04 Thread Patrick Wildt
Hi,

since we already dump most of the descriptors, also dump the interface
association descriptor, which helped me debug the previous issue.

Patrick

diff --git a/sys/dev/usb/uvideo.c b/sys/dev/usb/uvideo.c
index c990c899c45..1a9dfc733fa 100644
--- a/sys/dev/usb/uvideo.c
+++ b/sys/dev/usb/uvideo.c
@@ -198,6 +198,8 @@ voiduvideo_dump_desc_output(struct 
uvideo_softc *,
const usb_descriptor_t *);
 void   uvideo_dump_desc_endpoint(struct uvideo_softc *,
const usb_descriptor_t *);
+void   uvideo_dump_desc_iface_assoc(struct uvideo_softc *,
+   const usb_descriptor_t *);
 void   uvideo_dump_desc_interface(struct uvideo_softc *,
const usb_descriptor_t *);
 void   uvideo_dump_desc_config(struct uvideo_softc *,
@@ -2487,6 +2489,11 @@ uvideo_dump_desc_all(struct uvideo_softc *sc)
printf("|\n");
uvideo_dump_desc_interface(sc, desc);
break;
+   case UDESC_IFACE_ASSOC:
+   printf(" (UDESC_IFACE_ASSOC)\n");
+   printf("|\n");
+   uvideo_dump_desc_iface_assoc(sc, desc);
+   break;
default:
printf(" (unknown)\n");
break;
@@ -2608,6 +2615,24 @@ uvideo_dump_desc_endpoint(struct uvideo_softc *sc,
printf("bInterval=0x%02x\n", d->bInterval);
 }
 
+void
+uvideo_dump_desc_iface_assoc(struct uvideo_softc *sc,
+const usb_descriptor_t *desc)
+{
+   usb_interface_assoc_descriptor_t *d;
+
+   d = (usb_interface_assoc_descriptor_t *)(uint8_t *)desc;
+
+   printf("bLength=%d\n", d->bLength);
+   printf("bDescriptorType=0x%02x\n", d->bDescriptorType);
+   printf("bFirstInterface=0x%02x\n", d->bFirstInterface);
+   printf("bInterfaceCount=%d\n", d->bInterfaceCount);
+   printf("bFunctionClass=0x%02x\n", d->bFunctionClass);
+   printf("bFunctionSubClass=0x%02x\n", d->bFunctionSubClass);
+   printf("bFunctionProtocol=0x%02x\n", d->bFunctionProtocol);
+   printf("iFunction=0x%02x\n", d->iFunction);
+}
+
 void
 uvideo_dump_desc_interface(struct uvideo_softc *sc,
 const usb_descriptor_t *desc)



uvideo(4): handle interface associations

2019-07-04 Thread Patrick Wildt
Hi,

newer laptops can have more than one camera.  For instance the Lenovo
X395 ships with a normal camera and an infrared camera.  These cameras
are behind a single USB device and their "functions" are separated
using interface association descriptors.  This means that there are
USB descriptors that tell us which USB interfaces belong to a single
function.  Note that the interface association descriptor is always
before its interfaces.

Unfortunately uvideo(4) currently can't handle that.  It goes through
all interfaces looking for VC or VS headers and realizes... there are
too many!  Because it doesn't know where to look, and when to stop.
Thus, it reports

uvideo0: too many VC_HEADERs!

Also since it claims all interfaces of the device, only one uvideo(4)
attaches and not two.

To fix this first of all when we attach, we should look for the first
unclaimed video class interface.  Then, go through all descriptors and
look for the function we belong to (using the interface association
descriptor).  Then, claim all the interfaces belonging to that function
and leave the rest.  This allows the second uvideo(4) to attach.

uvideo(4) contains more code that goes through every USB descriptor
looking for information.  In all these functions we should restrict it
so that it only looks inside its function's descriptors.  Thus, skip all
descriptors until we find our first interface and only then start
parsing.  Once we cross the function by reaching the next interface
association descriptor break out, because there's nothing left for us.

With this, and another small diff that follows, I can use the normal
camera on my Lenovo X395.

Patrick

diff --git a/sys/dev/usb/uvideo.c b/sys/dev/usb/uvideo.c
index 0c382b39071..c990c899c45 100644
--- a/sys/dev/usb/uvideo.c
+++ b/sys/dev/usb/uvideo.c
@@ -61,8 +61,8 @@ int uvideo_debug = 1;
 struct uvideo_softc {
struct devicesc_dev;
struct usbd_device  *sc_udev;
+   int  sc_iface;
int  sc_nifaces;
-   struct usbd_interface   **sc_ifaces;
 
struct device   *sc_videodev;
 
@@ -500,25 +500,56 @@ uvideo_attach(struct device *parent, struct device *self, 
void *aux)
 {
struct uvideo_softc *sc = (struct uvideo_softc *)self;
struct usb_attach_arg *uaa = aux;
+   usb_interface_assoc_descriptor_t *iad;
usb_interface_descriptor_t *id;
+   const usb_descriptor_t *desc;
+   struct usbd_desc_iter iter;
int i;
 
sc->sc_udev = uaa->device;
-   sc->sc_nifaces = uaa->nifaces;
-   /*
-* Claim all video interfaces.  Interfaces must be claimed during
-* attach, during attach hooks is too late.
-*/
-   for (i = 0; i < sc->sc_nifaces; i++) {
+
+   /* Find the first unclaimed video interface. */
+   for (i = 0; i < uaa->nifaces; i++) {
if (usbd_iface_claimed(sc->sc_udev, i))
continue;
id = usbd_get_interface_descriptor(>sc_udev->ifaces[i]);
if (id == NULL)
continue;
if (id->bInterfaceClass == UICLASS_VIDEO)
-   usbd_claim_iface(sc->sc_udev, i);
+   break;
+   }
+   KASSERT(i != uaa->nifaces);
+
+   /* Find out which interface association we belong to. */
+   usbd_desc_iter_init(sc->sc_udev, );
+   desc = usbd_desc_iter_next();
+   while (desc) {
+   if (desc->bDescriptorType != UDESC_IFACE_ASSOC) {
+   desc = usbd_desc_iter_next();
+   continue;
+   }
+   iad = (usb_interface_assoc_descriptor_t *)desc;
+   if (i >= iad->bFirstInterface &&
+   i < iad->bFirstInterface + iad->bInterfaceCount)
+   break;
+   desc = usbd_desc_iter_next();
+   }
+   KASSERT(desc != NULL);
+
+   /*
+* Claim all interfaces of our association.  Interfaces must be
+* claimed during attach, during attach hooks is too late.
+*/
+   for (i = iad->bFirstInterface;
+   i < iad->bFirstInterface + iad->bInterfaceCount; i++) {
+   KASSERT(!usbd_iface_claimed(sc->sc_udev, i));
+   usbd_claim_iface(sc->sc_udev, i);
}
 
+   /* Remember our association by saving the first interface. */
+   sc->sc_iface = iad->bFirstInterface;
+   sc->sc_nifaces = iad->bInterfaceCount;
+
/* maybe the device has quirks */
sc->sc_quirk = uvideo_lookup(uaa->vendor, uaa->product);
 
@@ -612,6 +643,7 @@ uvideo_vc_parse_desc(struct uvideo_softc *sc)
 {
struct usbd_desc_iter iter;
const usb_descriptor_t *desc;
+   usb_interface_descriptor_t *id;
int vc_header_found;
usbd_status error;
 
@@ -622,6 +654,18 @@ 

ahci: don't wait for CR to come on

2019-06-25 Thread Patrick Wildt
Hi,

on some hardware I see a "failed to start command DMA on port N,
disabling" during attach.  Apparently AHCI spec. rev 1.3 only
requires that a HBA clears AHCI_PREG_CMD_CR when AHCI_PREG_CMD_ST
gets cleared by software/driver, but not the inverse.  Actually
neither the FreeBSD, Linux nor NetBSD counterpart of ahci(4) has
an analogous check.  With this my hardware works totally fine.

Originally found and debugged by Marius Strobl on a completely
different hardware, so now there are two instances of those.
jmatthew@ is fine with this as well.

ok?

Patrick

diff --git a/sys/dev/ic/ahci.c b/sys/dev/ic/ahci.c
index 39adbaa563c..00e4300ffb3 100644
--- a/sys/dev/ic/ahci.c
+++ b/sys/dev/ic/ahci.c
@@ -922,11 +922,6 @@ ahci_default_port_start(struct ahci_port *ap, int fre_only)
}
 #endif
 
-   /* Wait for CR to come on */
-   if (!fre_only &&
-   ahci_pwait_set(ap, AHCI_PREG_CMD, AHCI_PREG_CMD_CR, 1))
-   return (1);
-
return (0);
 }
 



Re: libcrypto: recognize HW acceleration support on arm64

2019-06-24 Thread Patrick Wildt
On Thu, Jun 20, 2019 at 11:21:20AM +0200, Remco wrote:
> On 19-06-19 07:13, Patrick Wildt wrote:
> > Hi,
> > 
> > this diff adds the necessary helpers to arm64 so that libcrypto knows
> > which of the hardware crypto features are available on the machine.
> > Those helpers are used by the existing and matching armv7 code.
> > 
> > ok?
> > 
> > Patrick
> > 
> 
> Does it make sense to query the ID_AA64PFR0_EL1 and ID_AA64ISAR0_EL1 system
> registers for that using the mrs instruction ?

It looks like those indeed encode enough information to figure it out,
but apparently the registers are not readable from userland, only from
EL1 and above.

The armv7 code works the same like this diff for arm64, where the
instruction is executed and if it traps we know it's not supported.
This way it fits right in.

Patrick



Re: libcrypto: recognize HW acceleration support on arm64

2019-06-19 Thread Patrick Wildt
On Wed, Jun 19, 2019 at 09:25:27AM +0200, Mark Kettenis wrote:
> > Date: Wed, 19 Jun 2019 07:13:19 +0200
> > From: Patrick Wildt 
> > 
> > Hi,
> > 
> > this diff adds the necessary helpers to arm64 so that libcrypto knows
> > which of the hardware crypto features are available on the machine.
> > Those helpers are used by the existing and matching armv7 code.
> > 
> > ok?
> 
> No objections to the diff per se, but unless I'm missing something,
> there currently isn't any assembly code that takes advantage of this
> for arm64.  The armv7 code is 32-bit code so I don't think you can use
> any of it in 64-bit mode.

No, you're right, at the moment there's no acceleration support for
arm64 in our tree.  But OpenSSL has more of that, even before their
license change, so I can easily pull that in step by step.



libcrypto: recognize HW acceleration support on arm64

2019-06-18 Thread Patrick Wildt
Hi,

this diff adds the necessary helpers to arm64 so that libcrypto knows
which of the hardware crypto features are available on the machine.
Those helpers are used by the existing and matching armv7 code.

ok?

Patrick

diff --git a/lib/libcrypto/arch/aarch64/Makefile.inc 
b/lib/libcrypto/arch/aarch64/Makefile.inc
index 8742504f2d4..972e5536b5e 100644
--- a/lib/libcrypto/arch/aarch64/Makefile.inc
+++ b/lib/libcrypto/arch/aarch64/Makefile.inc
@@ -26,3 +26,6 @@ ${f}.S: ${LCRYPTO_SRC}/${dir}/asm/${f}.pl
/usr/bin/perl \
${LCRYPTO_SRC}/${dir}/asm/${f}.pl void ${.TARGET} > ${.TARGET}
 .endfor
+
+CFLAGS+= -DOPENSSL_CPUID_OBJ
+SRCS+= arm64cpuid.S armcap.c
diff --git a/lib/libcrypto/arm64cpuid.S b/lib/libcrypto/arm64cpuid.S
new file mode 100644
index 000..5eeff91c6ea
--- /dev/null
+++ b/lib/libcrypto/arm64cpuid.S
@@ -0,0 +1,47 @@
+#include "arm_arch.h"
+
+.text
+.arch  armv8-a+crypto+sha3
+
+.align 5
+.globl _armv7_neon_probe
+.type  _armv7_neon_probe,%function
+_armv7_neon_probe:
+   orr v15.16b, v15.16b, v15.16b
+   ret
+.size  _armv7_neon_probe,.-_armv7_neon_probe
+
+.globl _armv8_aes_probe
+.type  _armv8_aes_probe,%function
+_armv8_aes_probe:
+   aesev0.16b, v0.16b
+   ret
+.size  _armv8_aes_probe,.-_armv8_aes_probe
+
+.globl _armv8_sha1_probe
+.type  _armv8_sha1_probe,%function
+_armv8_sha1_probe:
+   sha1h   s0, s0
+   ret
+.size  _armv8_sha1_probe,.-_armv8_sha1_probe
+
+.globl _armv8_sha256_probe
+.type  _armv8_sha256_probe,%function
+_armv8_sha256_probe:
+   sha256su0   v0.4s, v0.4s
+   ret
+.size  _armv8_sha256_probe,.-_armv8_sha256_probe
+
+.globl _armv8_pmull_probe
+.type  _armv8_pmull_probe,%function
+_armv8_pmull_probe:
+   pmull   v0.1q, v0.1d, v0.1d
+   ret
+.size  _armv8_pmull_probe,.-_armv8_pmull_probe
+
+.globl _armv8_sha512_probe
+.type  _armv8_sha512_probe,%function
+_armv8_sha512_probe:
+   sha512su0   v0.2d,v0.2d
+   ret
+.size  _armv8_sha512_probe,.-_armv8_sha512_probe
diff --git a/lib/libcrypto/arm_arch.h b/lib/libcrypto/arm_arch.h
index a64c6da46eb..bb137e6a48e 100644
--- a/lib/libcrypto/arm_arch.h
+++ b/lib/libcrypto/arm_arch.h
@@ -17,7 +17,11 @@
* gcc/config/arm/arm.c. On a side note it defines
* __ARMEL__/__ARMEB__ for little-/big-endian.
*/
-#  if  defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
+#  if  defined(__ARM_ARCH)
+#   define __ARM_ARCH__ __ARM_ARCH
+#  elifdefined(__ARM_ARCH_8A__)
+#   define __ARM_ARCH__ 8
+#  elifdefined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
defined(__ARM_ARCH_7R__)|| defined(__ARM_ARCH_7M__) || \
defined(__ARM_ARCH_7EM__)
 #   define __ARM_ARCH__ 7



Re: apollo lake gpio

2019-06-17 Thread Patrick Wildt
Committed, thanks!

On Mon, Jun 17, 2019 at 07:53:50PM +0200, Mark Kettenis wrote:
> > From: James Hastings 
> > Date: Mon, 17 Jun 2019 13:24:36 -0400 (EDT)
> 
> This diff is ok kettenis@
> 
> It might take a few days for me to commit this.  If anybody else wants
> to do it based on my ok, go ahead.
> 
> 
> > Index: share/man/man4/Makefile
> > ===
> > RCS file: /cvs/src/share/man/man4/Makefile,v
> > retrieving revision 1.713
> > diff -u -p -u -r1.713 Makefile
> > --- share/man/man4/Makefile 7 Jun 2019 16:06:59 -   1.713
> > +++ share/man/man4/Makefile 17 Jun 2019 16:18:15 -
> > @@ -10,7 +10,7 @@ MAN=  aac.4 abcrtc.4 ac97.4 acphy.4 acrtc
> > admtm.4 admtmp.4 admtt.4 adt.4 adtfsm.4 adv.4 age.4 alc.4 ale.4 agp.4 \
> > ahc.4 ahci.4 ahd.4 aibs.4 aic.4 \
> > akbd.4 alipm.4 amas.4 amdiic.4 amdpm.4 ami.4 amphy.4 \
> > -   ams.4 an.4 andl.4 aps.4 arc.4 arcofi.4 \
> > +   ams.4 an.4 andl.4 aplgpio.4 aps.4 arc.4 arcofi.4 \
> > asbtm.4 asmc.4 ast.4 atapiscsi.4 atphy.4 ath.4 athn.4 atu.4 atw.4 \
> > auacer.4 audio.4 aue.4 auglx.4 auich.4 auixp.4 autri.4 auvia.4 \
> > axe.4 axen.4 axppmic.4 azalia.4 \
> > Index: share/man/man4/acpi.4
> > ===
> > RCS file: /cvs/src/share/man/man4/acpi.4,v
> > retrieving revision 1.57
> > diff -u -p -u -r1.57 acpi.4
> > --- share/man/man4/acpi.4   23 Apr 2019 20:23:36 -  1.57
> > +++ share/man/man4/acpi.4   17 Jun 2019 16:18:15 -
> > @@ -90,6 +90,8 @@ ACPI video
> >  ACPI video output
> >  .It Xr aibs 4
> >  ASUSTeK AI Booster ACPI ATK0110 temperature, voltage, and fan sensor
> > +.It Xr aplgpio 4
> > +Intel Apollo Lake GPIO controller
> >  .It Xr bytgpio 4
> >  Intel Bay Trail GPIO controller
> >  .It Xr ccp 4
> > Index: share/man/man4/aplgpio.4
> > ===
> > RCS file: share/man/man4/aplgpio.4
> > diff -N share/man/man4/aplgpio.4
> > --- /dev/null   1 Jan 1970 00:00:00 -
> > +++ share/man/man4/aplgpio.417 Jun 2019 16:18:15 -
> > @@ -0,0 +1,50 @@
> > +.\"$OpenBSD$
> > +.\"
> > +.\" Copyright (c) 2019 James Hastings
> > +.\"
> > +.\" Permission to use, copy, modify, and distribute this software for any
> > +.\" purpose with or without fee is hereby granted, provided that the above
> > +.\" copyright notice and this permission notice appear in all copies.
> > +.\"
> > +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 
> > WARRANTIES
> > +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
> > +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
> > +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> > +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
> > +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
> > +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
> > +.\"
> > +.Dd $Mdocdate$
> > +.Dt APLGPIO 4
> > +.Os
> > +.Sh NAME
> > +.Nm aplgpio
> > +.Nd Intel Apollo Lake GPIO controller
> > +.Sh SYNOPSIS
> > +.Cd "aplgpio* at acpi?"
> > +.Sh DESCRIPTION
> > +The
> > +.Nm
> > +driver provides support for the GPIO controllers found on Intel's Apollo 
> > +Lake SoC.
> > +It does not provide direct device driver entry points but makes its
> > +functions available to
> > +.Xr acpi 4 .
> > +.Sh SEE ALSO
> > +.Xr acpi 4 ,
> > +.Xr intro 4
> > +.Sh HISTORY
> > +The
> > +.Nm
> > +driver first appeared in
> > +.Ox 6.6 .
> > +.Sh AUTHORS
> > +.An -nosplit
> > +The
> > +.Nm
> > +driver was written by
> > +.An James Hastings
> > +based on the
> > +.Xr bytgpio 4
> > +driver by
> > +.An Mark Kettenis Aq Mt kette...@openbsd.org .
> > Index: sys/arch/amd64/conf/GENERIC
> > ===
> > RCS file: /cvs/src/sys/arch/amd64/conf/GENERIC,v
> > retrieving revision 1.473
> > diff -u -p -u -r1.473 GENERIC
> > --- sys/arch/amd64/conf/GENERIC 7 Jun 2019 16:06:59 -   1.473
> > +++ sys/arch/amd64/conf/GENERIC 17 Jun 2019 16:18:16 -
> > @@ -61,6 +61,7 @@ acpivideo*at acpi?
> >  acpivout*  at acpivideo?
> >  acpipwrres*at acpi?
> >  aibs*  at acpi?
> > +aplgpio*   at acpi?
> >  bytgpio*   at acpi?
> >  chvgpio*   at acpi?
> >  sdhc*  at acpi?
> > Index: sys/arch/amd64/conf/RAMDISK_CD
> > ===
> > RCS file: /cvs/src/sys/arch/amd64/conf/RAMDISK_CD,v
> > retrieving revision 1.179
> > diff -u -p -u -r1.179 RAMDISK_CD
> > --- sys/arch/amd64/conf/RAMDISK_CD  4 May 2019 17:59:40 -   1.179
> > +++ sys/arch/amd64/conf/RAMDISK_CD  17 Jun 2019 16:18:16 -
> > @@ -42,6 +42,7 @@ acpiec*   at acpi?
> >  acpiprt*   at acpi?
> >  acpimadt0  at acpi?
> >  #acpitz*   at acpi?
> > +aplgpio*   at acpi?
> >  bytgpio*   at acpi?
> 

arm: cleanup cpuid assembly

2019-06-11 Thread Patrick Wildt
Hi,

in a recent discussion I was told we can throw out all the !ARMv7
architecture code and !OpenBSD and if portable needs it they can
add it back.

With this in mind we can throw out quite a bit of ifdefs.

ok?

Patrick

diff --git a/lib/libcrypto/armv4cpuid.S b/lib/libcrypto/armv4cpuid.S
index bb9abafebe5..24d2b4b2b45 100644
--- a/lib/libcrypto/armv4cpuid.S
+++ b/lib/libcrypto/armv4cpuid.S
@@ -1,19 +1,12 @@
 #include "arm_arch.h"
 
 .text
-#if defined(__thumb2__) && !defined(__APPLE__)
-.syntaxunified
-.thumb
-#else
 .code  32
-#undef __thumb2__
-#endif
 
 .align 5
 .globl OPENSSL_atomic_add
 .type  OPENSSL_atomic_add,%function
 OPENSSL_atomic_add:
-#if __ARM_ARCH__>=6
 .Ladd: ldrex   r2,[r0]
add r3,r2,r1
strex   r2,r3,[r0]
@@ -21,32 +14,8 @@ OPENSSL_atomic_add:
bne .Ladd
mov r0,r3
bx  lr
-#else
-   stmdb   sp!,{r4,r5,r6,lr}
-   ldr r2,.Lspinlock
-   adr r3,.Lspinlock
-   mov r4,r0
-   mov r5,r1
-   add r6,r3,r2@ 
-   b   .+8
-.Lspin:bl  sched_yield
-   mov r0,#-1
-   swp r0,r0,[r6]
-   cmp r0,#0
-   bne .Lspin
-
-   ldr r2,[r4]
-   add r2,r2,r5
-   str r2,[r4]
-   str r0,[r6] @ release spinlock
-   ldmia   sp!,{r4,r5,r6,lr}
-   tst lr,#1
-   moveq   pc,lr
-.word  0xe12fff1e  @ bxlr
-#endif
 .size  OPENSSL_atomic_add,.-OPENSSL_atomic_add
 
-#if __ARM_ARCH__>=7
 .arch  armv7-a
 .fpu   neon
 
@@ -61,62 +30,40 @@ _armv7_neon_probe:
 .globl _armv8_aes_probe
 .type  _armv8_aes_probe,%function
 _armv8_aes_probe:
-#if defined(__thumb2__) && !defined(__APPLE__)
-.byte  0xb0,0xff,0x00,0x03 @ aese.8q0,q0
-#else
 .byte  0x00,0x03,0xb0,0xf3 @ aese.8q0,q0
-#endif
bx  lr
 .size  _armv8_aes_probe,.-_armv8_aes_probe
 
 .globl _armv8_sha1_probe
 .type  _armv8_sha1_probe,%function
 _armv8_sha1_probe:
-#if defined(__thumb2__) && !defined(__APPLE__)
-.byte  0x00,0xef,0x40,0x0c @ sha1c.32  q0,q0,q0
-#else
 .byte  0x40,0x0c,0x00,0xf2 @ sha1c.32  q0,q0,q0
-#endif
bx  lr
 .size  _armv8_sha1_probe,.-_armv8_sha1_probe
 
 .globl _armv8_sha256_probe
 .type  _armv8_sha256_probe,%function
 _armv8_sha256_probe:
-#if defined(__thumb2__) && !defined(__APPLE__)
-.byte  0x00,0xff,0x40,0x0c @ sha256h.32q0,q0,q0
-#else
 .byte  0x40,0x0c,0x00,0xf3 @ sha256h.32q0,q0,q0
-#endif
bx  lr
 .size  _armv8_sha256_probe,.-_armv8_sha256_probe
+
 .globl _armv8_pmull_probe
 .type  _armv8_pmull_probe,%function
 _armv8_pmull_probe:
-#if defined(__thumb2__) && !defined(__APPLE__)
-.byte  0xa0,0xef,0x00,0x0e @ vmull.p64 q0,d0,d0
-#else
 .byte  0x00,0x0e,0xa0,0xf2 @ vmull.p64 q0,d0,d0
-#endif
bx  lr
 .size  _armv8_pmull_probe,.-_armv8_pmull_probe
-#endif
 
 .globl OPENSSL_wipe_cpu
 .type  OPENSSL_wipe_cpu,%function
 OPENSSL_wipe_cpu:
-#if __ARM_ARCH__>=7
ldr r0,.LOPENSSL_armcap
adr r1,.LOPENSSL_armcap
ldr r0,[r1,r0]
-#ifdef __APPLE__
-   ldr r0,[r0]
-#endif
-#endif
eor r2,r2,r2
eor r3,r3,r3
eor ip,ip,ip
-#if __ARM_ARCH__>=7
tst r0,#1
beq .Lwipe_done
veorq0, q0, q0
@@ -132,34 +79,14 @@ OPENSSL_wipe_cpu:
veorq14, q14, q14
veorq15, q15, q15
 .Lwipe_done:
-#endif
mov r0,sp
-#if __ARM_ARCH__>=5
bx  lr
-#else
-   tst lr,#1
-   moveq   pc,lr
-.word  0xe12fff1e  @ bxlr
-#endif
 .size  OPENSSL_wipe_cpu,.-OPENSSL_wipe_cpu
 
 .align 5
-#if __ARM_ARCH__>=7
 .LOPENSSL_armcap:
 .word  OPENSSL_armcap_P-.
-#endif
-#if __ARM_ARCH__>=6
 .align 5
-#else
-.Lspinlock:
-.word  atomic_add_spinlock-.Lspinlock
-.align 5
-
-.data
-.align 2
-atomic_add_spinlock:
-.word  0
-#endif
 
 .comm  OPENSSL_armcap_P,4,4
 .hiddenOPENSSL_armcap_P



Re: Makefile.cross typo

2019-05-21 Thread Patrick Wildt
On Wed, May 22, 2019 at 02:38:04AM +0200, Krystian Lewandowski wrote:
> I tried to rebuild cross tools recently and it seems there is a typo
> in Makefile.cross.

Thanks, committed!



efiboot: allow bigger ucodes

2019-05-17 Thread Patrick Wildt
Hi,

claudio@ has a Kaby Lake that exceeds the 128 kB limit, being as big as
190 kB.  So, for him the ucode isn't being loaded.

On EFI systems we can simply ask EFI to allocate some memory for us.
I'm not sure why this file is duplicated 4 times, but it looks like
for efiboot this one is currently the file to patch.

This diff works for claudio@'s EFI booted system.  Since I don't know
how much space is available on legacy systems I will not attempt to
fix this for the legacy bootloader.  Someone that knows more than me
about x86 can attempt that.

Feedback? ok?

Patrick

diff --git a/sys/arch/amd64/stand/efiboot/exec_i386.c 
b/sys/arch/amd64/stand/efiboot/exec_i386.c
index e4b39d6cd0c..ea1d301f1d8 100644
--- a/sys/arch/amd64/stand/efiboot/exec_i386.c
+++ b/sys/arch/amd64/stand/efiboot/exec_i386.c
@@ -46,8 +46,13 @@
 #include "softraid_amd64.h"
 #endif
 
+#include 
+#include 
+#include "eficall.h"
 #include "efiboot.h"
 
+extern EFI_BOOT_SERVICES   *BS;
+
 typedef void (*startfuncp)(int, int, int, int, int, int, int, int)
 __attribute__ ((noreturn));
 
@@ -165,6 +170,7 @@ run_loadfile(uint64_t *marks, int howto)
 void
 ucode_load(void)
 {
+   EFI_PHYSICAL_ADDRESS addr;
uint32_t model, family, stepping;
uint32_t dummy, signature;
uint32_t vendor[4];
@@ -200,12 +206,12 @@ ucode_load(void)
return;
 
buflen = sb.st_size;
-   if (buflen > 128*1024) {
-   printf("ucode too large\n");
+   if (EFI_CALL(BS->AllocatePages, AllocateAnyPages, EfiLoaderData,
+   EFI_SIZE_TO_PAGES(buflen), ) != EFI_SUCCESS) {
+   printf("cannot allocate memory for ucode\n");
return;
}
-
-   buf = (char *)(1*1024*1024);
+   buf = (char *)((paddr_t)addr);
 
if (read(fd, buf, buflen) != buflen) {
close(fd);



Re: ppb(4): free dynamically allocated bus

2019-04-16 Thread Patrick Wildt
On Tue, Apr 16, 2019 at 03:23:37PM +0200, Mark Kettenis wrote:
> > Date: Mon, 15 Apr 2019 08:50:04 +0200
> > From: Patrick Wildt 
> > Content-Type: text/plain; charset="utf-8"
> > Content-Disposition: inline
> > 
> > Hi,
> > 
> > with kettenis' change from 2015(?) we are able to configure ppb(4)'s
> > that are hotplugged.  I think on detach we should make sure to free the
> > bus range that was allocated for that device dynamically.  Otherwise
> > plug and pull can starve the extent.
> > 
> > Feedback?
> 
> The only thing I can think of is that the name sc_pbusex is a
> bitconfusing since we already have sc_pmemex where the "p" stands for
> prefetchable.  Maybe just call it sc_parent_busex?

Heh, true, you're right.  That better?  ok?

diff --git a/sys/dev/pci/ppb.c b/sys/dev/pci/ppb.c
index 34e3697dd51..b4894926bd0 100644
--- a/sys/dev/pci/ppb.c
+++ b/sys/dev/pci/ppb.c
@@ -66,6 +66,7 @@ struct ppb_softc {
pcitag_t sc_tag;/* ...and tag. */
pci_intr_handle_t sc_ih[4];
void *sc_intrhand;
+   struct extent *sc_parent_busex;
struct extent *sc_busex;
struct extent *sc_ioex;
struct extent *sc_memex;
@@ -77,6 +78,9 @@ struct ppb_softc {
struct task sc_remove_task;
struct timeout sc_to;
 
+   u_long sc_busnum;
+   u_long sc_busrange;
+
bus_addr_t sc_iobase, sc_iolimit;
bus_addr_t sc_membase, sc_memlimit;
bus_addr_t sc_pmembase, sc_pmemlimit;
@@ -390,6 +394,10 @@ ppbdetach(struct device *self, int flags)
free(name, M_DEVBUF, PPB_EXNAMLEN);
}
 
+   if (sc->sc_parent_busex)
+   extent_free(sc->sc_parent_busex, sc->sc_busnum,
+   sc->sc_busrange, EX_NOWAIT);
+
return (rv);
 }
 
@@ -529,6 +537,9 @@ ppb_alloc_busrange(struct ppb_softc *sc, struct 
pci_attach_args *pa,
if (extent_alloc(pa->pa_busex, busrange, 1, 0, 0, 
EX_NOWAIT, ))
continue;
+   sc->sc_parent_busex = pa->pa_busex;
+   sc->sc_busnum = busnum;
+   sc->sc_busrange = busrange;
*busdata |= pa->pa_bus;
*busdata |= (busnum << 8);
*busdata |= ((busnum + busrange - 1) << 16);



ppb(4): remove hotplug fixup

2019-04-15 Thread Patrick Wildt
Hi,

with kettenis' change from 2015(?) we can configure a ppb(4)'s bus
information.  Unfortunately the hotplug fixup code runs before that
change has a chance, and it will program a single bus (with no amount
of children) below it.  I think that part of the hotplug fixup can go
away.

The hotplug fixup also contains code for fixing up interrupt lines.  On
my todays machine it uses MSIs, so a missing interrupt line does not
hurt me.  I'm not sure if this is still needed for yesterday's machines.

Apparently that code was for some ExpressCards?

Patrick

diff --git a/sys/dev/pci/ppb.c b/sys/dev/pci/ppb.c
index a9ff32ce33c..22ff8ca2b5f 100644
--- a/sys/dev/pci/ppb.c
+++ b/sys/dev/pci/ppb.c
@@ -117,9 +117,6 @@ voidppb_alloc_resources(struct ppb_softc *, struct 
pci_attach_args *);
 intppb_intr(void *);
 void   ppb_hotplug_insert(void *);
 void   ppb_hotplug_insert_finish(void *);
-intppb_hotplug_fixup(struct pci_attach_args *);
-intppb_hotplug_fixup_type0(pci_chipset_tag_t, pcitag_t, pcitag_t);
-intppb_hotplug_fixup_type1(pci_chipset_tag_t, pcitag_t, pcitag_t);
 void   ppb_hotplug_rescan(void *);
 void   ppb_hotplug_remove(void *);
 intppbprint(void *, const char *pnp);
@@ -776,108 +773,14 @@ ppb_hotplug_insert_finish(void *arg)
task_add(systq, >sc_rescan_task);
 }
 
-int
-ppb_hotplug_fixup(struct pci_attach_args *pa)
-{
-   pcireg_t bhlcr;
-
-   bhlcr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
-   switch (PCI_HDRTYPE_TYPE(bhlcr)) {
-   case 0:
-   return ppb_hotplug_fixup_type0(pa->pa_pc,
-   pa->pa_tag, *pa->pa_bridgetag);
-   case 1:
-   return ppb_hotplug_fixup_type1(pa->pa_pc,
-   pa->pa_tag, *pa->pa_bridgetag);
-   default:
-   return (0);
-   }
-}
-
-int
-ppb_hotplug_fixup_type0(pci_chipset_tag_t pc, pcitag_t tag, pcitag_t bridgetag)
-{
-   pcireg_t intr;
-   int line;
-
-   /*
-* Fill in the interrupt line for platforms that need it.
-*
-* XXX We assume that the interrupt line matches the line used
-* by the PCI Express bridge.  This may not be true.
-*/
-   intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
-   if (PCI_INTERRUPT_PIN(intr) != PCI_INTERRUPT_PIN_NONE &&
-   PCI_INTERRUPT_LINE(intr) == 0) {
-   /* Get the interrupt line from our parent. */
-   intr = pci_conf_read(pc, bridgetag, PCI_INTERRUPT_REG);
-   line = PCI_INTERRUPT_LINE(intr);
-
-   intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
-   intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
-   intr |= line << PCI_INTERRUPT_LINE_SHIFT;
-   pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
-   }
-
-   return (0);
-}
-
-int
-ppb_hotplug_fixup_type1(pci_chipset_tag_t pc, pcitag_t tag, pcitag_t bridgetag)
-{
-   pcireg_t bhlcr, bir, csr, val;
-   int bus, dev, reg;
-
-   bir = pci_conf_read(pc, bridgetag, PPB_REG_BUSINFO);
-   if (PPB_BUSINFO_SUBORDINATE(bir) <= PPB_BUSINFO_SECONDARY(bir))
-   return (0);
-
-   bus = PPB_BUSINFO_SECONDARY(bir);
-   bir = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
-   bir &= (0xff << 24);
-   bir |= bus++;
-   bir |= (bus << 8);
-   bir |= (bus << 16);
-   pci_conf_write(pc, tag, PPB_REG_BUSINFO, bir);
-
-   for (reg = PPB_REG_IOSTATUS; reg < PPB_REG_BRIDGECONTROL; reg += 4) {
-   val = pci_conf_read(pc, bridgetag, reg);
-   pci_conf_write(pc, tag, reg, val);
-   }
-
-   csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
-   csr |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE;
-   csr |= PCI_COMMAND_MASTER_ENABLE;
-   csr |= PCI_COMMAND_INVALIDATE_ENABLE;
-   csr |= PCI_COMMAND_SERR_ENABLE;
-   pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, csr);
-
-   for (dev = 0; dev < pci_bus_maxdevs(pc, bus); dev++) {
-   tag = pci_make_tag(pc, bus, dev, 0);
-
-   bhlcr = pci_conf_read(pc, tag, PCI_BHLC_REG);
-   if (PCI_HDRTYPE_TYPE(bhlcr) != 0)
-   continue;
-
-   ppb_hotplug_fixup_type0(pc, tag, bridgetag);
-   }
-
-   return (0);
-}
-
 void
 ppb_hotplug_rescan(void *xsc)
 {
struct ppb_softc *sc = xsc;
struct pci_softc *psc = (struct pci_softc *)sc->sc_psc;
 
-   if (psc) {
-   /* Assign resources. */
-   pci_enumerate_bus(psc, ppb_hotplug_fixup, NULL);
-
-   /* Attach devices. */
+   if (psc)
pci_enumerate_bus(psc, NULL, NULL);
-   }
 }
 
 void



ppb(4): free dynamically allocated bus

2019-04-15 Thread Patrick Wildt
Hi,

with kettenis' change from 2015(?) we are able to configure ppb(4)'s
that are hotplugged.  I think on detach we should make sure to free the
bus range that was allocated for that device dynamically.  Otherwise
plug and pull can starve the extent.

Feedback?

Patrick

diff --git a/sys/dev/pci/ppb.c b/sys/dev/pci/ppb.c
index 34e3697dd51..a9ff32ce33c 100644
--- a/sys/dev/pci/ppb.c
+++ b/sys/dev/pci/ppb.c
@@ -67,6 +67,7 @@ struct ppb_softc {
pci_intr_handle_t sc_ih[4];
void *sc_intrhand;
struct extent *sc_busex;
+   struct extent *sc_pbusex;
struct extent *sc_ioex;
struct extent *sc_memex;
struct extent *sc_pmemex;
@@ -77,6 +78,9 @@ struct ppb_softc {
struct task sc_remove_task;
struct timeout sc_to;
 
+   u_long sc_busnum;
+   u_long sc_busrange;
+
bus_addr_t sc_iobase, sc_iolimit;
bus_addr_t sc_membase, sc_memlimit;
bus_addr_t sc_pmembase, sc_pmemlimit;
@@ -390,6 +394,10 @@ ppbdetach(struct device *self, int flags)
free(name, M_DEVBUF, PPB_EXNAMLEN);
}
 
+   if (sc->sc_pbusex)
+   extent_free(sc->sc_pbusex, sc->sc_busnum,
+   sc->sc_busrange, EX_NOWAIT);
+
return (rv);
 }
 
@@ -529,6 +537,9 @@ ppb_alloc_busrange(struct ppb_softc *sc, struct 
pci_attach_args *pa,
if (extent_alloc(pa->pa_busex, busrange, 1, 0, 0, 
EX_NOWAIT, ))
continue;
+   sc->sc_pbusex = pa->pa_busex;
+   sc->sc_busnum = busnum;
+   sc->sc_busrange = busrange;
*busdata |= pa->pa_bus;
*busdata |= (busnum << 8);
*busdata |= ((busnum + busrange - 1) << 16);



Re: iked(8): add support for IKEv2 Message Fragmentation

2019-02-27 Thread Patrick Wildt
On Wed, Feb 27, 2019 at 01:01:37PM +, Stuart Henderson wrote:
> On 2019/02/26 16:34, Tobias Heider wrote:
> > Hi,
> > 
> > this diff adds support for IKEv2 Message Fragmentation as defined in
> > RFC 7383 (https://tools.ietf.org/html/rfc7383) to iked(8).
> 
> Thank you, I know there are quite a few additions in the genua tree and
> splitting them out is not easy. I'm running this in a few places now,
> have tested both with and without fragmentation, no problems seen.

Actually, this is not even part of the genua tree.  He implemented it
here the last two weeks and tested it using bluhm@'s test machines. :)

Patrick

> A couple of nits - manpage part is missing, I propose this:
> 
> Index: iked.conf.5
> ===
> RCS file: /cvs/src/sbin/iked/iked.conf.5,v
> retrieving revision 1.53
> diff -u -p -r1.53 iked.conf.5
> --- iked.conf.5   31 Jan 2018 13:25:55 -  1.53
> +++ iked.conf.5   27 Feb 2019 12:45:46 -
> @@ -136,6 +136,12 @@ This is the default.
>  .It Ic set decouple
>  Don't load the negotiated SAs and flows from the kernel.
>  This mode is only useful for testing and debugging.
> +.It Ic set fragmentation
> +Enable IKEv2 Message Fragmentation (RFC 7383) support.
> +This allows IKEv2 to operate in environments that might block IP fragments.
> +.It Ic set nofragmentation
> +Disables IKEv2 Message Fragmentation support.
> +This is the default.
>  .It Ic set mobike
>  Enable MOBIKE (RFC 4555) support.
>  This is the default.
> 
> There are some over-long lines - it's not fair to require <=80 for
> everything in this diff when big parts of iked already exceed this,
> but some of the longer ones need reining in e.g.
> 
> > Index: sbin/iked/iked.h
> ..
>
> |--|
> > +#define IKED_FRAG_TOTAL_MAX111 /* upper limit 
> > of frag_total (64kB / 576B) */
> ...#define IKED_FRAG_TOTAL_MAX111 /* upper limit of frag_total 
> (64kB / 576B) */
> 
> >  struct iked_message *
> >  ikev2_msg_lookup(struct iked *, struct iked_msgqueue *,
> > struct iked_message *, struct ike_header *);
> > +voidikev2_msg_lookup_dispose_all(struct iked *env, struct 
> > iked_msgqueue *queue,
> > +   struct iked_message *msg, struct ike_header *hdr);
> > +int ikev2_msg_lookup_retransmit_all(struct iked *env, struct 
> > iked_msgqueue *queue,
> > +   struct iked_message *msg, struct ike_header *hdr, struct iked_sa 
> > *sa);
> ...(split onto another line)
> 
> > Index: sbin/iked/ikev2.c
> ..
> > -   if ((m = ikev2_msg_lookup(env, >sa_responses, msg, hdr))) {
> > -   if (ikev2_msg_retransmit_response(env, sa, m)) {
> > +   if ((r = ikev2_msg_lookup_retransmit_all(env, 
> > >sa_responses, msg, hdr, sa)) != 0) {
> > +   if (r == -1) {
> ...(and here)
> 
> I've done that in my tree.
> 
> Are there comments from anyone else?
> 



Re: iked(8): fix the sending of certain IPv6 addresses in the configuration payload

2019-02-26 Thread Patrick Wildt
On Tue, Feb 26, 2019 at 06:45:38PM +0100, Patrick Wildt wrote:
> On Thu, Feb 21, 2019 at 06:29:15PM +0100, Aram Hăvărneanu wrote:
> > This change fixes the sending of INTERNAL_IP6_DNS, INTERNAL_IP6_DHCP
> > (RFC5996); INTERNAL_IP6_NBNS (RFC4306); and INTERNAL_IP6_SERVER
> > (MS-IKEE).
> > 
> > Prior to this fix the data sent to clients was garbled.
> 
> Oh, good catch!  That looks fine to me.

Thanks, committed!

> > Index: ikev2.c
> > ===
> > RCS file: /cvs/src/sbin/iked/ikev2.c,v
> > retrieving revision 1.166
> > diff -u -p -u -p -r1.166 ikev2.c
> > --- ikev2.c 5 Mar 2018 14:30:30 -   1.166
> > +++ ikev2.c 21 Feb 2019 17:19:21 -
> > @@ -1935,7 +1935,7 @@ ikev2_add_cp(struct iked *env, struct ik
> > case IKEV2_CFG_INTERNAL_IP6_DHCP:
> > case IKEV2_CFG_INTERNAL_IP6_SERVER:
> > /* 16 bytes IPv6 address */
> > -   in6 = (struct sockaddr_in6 *)>cfg.address;
> > +   in6 = (struct sockaddr_in6 *)>cfg.address.addr;
> > cfg->cfg_length = htobe16(16);
> > if (ibuf_add(buf, >sin6_addr.s6_addr, 16) == -1)
> > return (-1);
> > 



Re: iked(8): fix the sending of certain IPv6 addresses in the configuration payload

2019-02-26 Thread Patrick Wildt
On Thu, Feb 21, 2019 at 06:29:15PM +0100, Aram Hăvărneanu wrote:
> This change fixes the sending of INTERNAL_IP6_DNS, INTERNAL_IP6_DHCP
> (RFC5996); INTERNAL_IP6_NBNS (RFC4306); and INTERNAL_IP6_SERVER
> (MS-IKEE).
> 
> Prior to this fix the data sent to clients was garbled.

Oh, good catch!  That looks fine to me.

> Index: ikev2.c
> ===
> RCS file: /cvs/src/sbin/iked/ikev2.c,v
> retrieving revision 1.166
> diff -u -p -u -p -r1.166 ikev2.c
> --- ikev2.c   5 Mar 2018 14:30:30 -   1.166
> +++ ikev2.c   21 Feb 2019 17:19:21 -
> @@ -1935,7 +1935,7 @@ ikev2_add_cp(struct iked *env, struct ik
>   case IKEV2_CFG_INTERNAL_IP6_DHCP:
>   case IKEV2_CFG_INTERNAL_IP6_SERVER:
>   /* 16 bytes IPv6 address */
> - in6 = (struct sockaddr_in6 *)>cfg.address;
> + in6 = (struct sockaddr_in6 *)>cfg.address.addr;
>   cfg->cfg_length = htobe16(16);
>   if (ibuf_add(buf, >sin6_addr.s6_addr, 16) == -1)
>   return (-1);
> 



  1   2   3   4   5   >