Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 26 Feb 2016 16:25:53 +0000
From:      "Meyer, Wolfgang" <wolfgang.meyer@hob.de>
To:        "'freebsd-ia64@FreeBSD.org'" <freebsd-ia64@FreeBSD.org>
Subject:   Running FreeBSD 10 on HP Integrity rx2800-i4
Message-ID:  <EC88118611AE564AB0B10C6A4569004D0137D5877A@HOBEX11.hob.de>

next in thread | raw e-mail | index | archive | help
Hello,

as the release of FreeBSD 10.3 is prepared, I thought I could share some pa=
tches that are necessary for running FreeBSD 10 on HP Integrity rx2800-i4 s=
ervers. I'll also try to explain what the patches are trying to fix (from t=
he top of my head as it has been some time since the creation of the patche=
s).

The original efi_md_find function assumes that the efi memory descriptors a=
re sorted by physical addresses. This is not the case for the EFI of the HP=
 Integrity rx2800-i4 servers and hence some memory regions occupied by efi =
memory descriptors are not found which leads to a boot failure (not sure if=
 machine check or hang). The following patch fixes this behaviour.

efi.patch:
--- sys/ia64/ia64/efi.c.orig    2015-07-31 14:18:37.000000000 +0200
+++ sys/ia64/ia64/efi.c 2015-08-13 16:15:53.631602000 +0200
@@ -205,21 +205,28 @@
 efi_md_find(vm_paddr_t pa)
 {
        static struct efi_md *last =3D NULL;
-       struct efi_md *md, *p0, *p1;
+       struct efi_md *md, *md0;
+       int up =3D 0;

        md =3D (last !=3D NULL) ? last : efi_md_first();
-       p1 =3D p0 =3D NULL;
-       while (md !=3D NULL && md !=3D p1) {
+       if (md =3D=3D NULL) {
+               return (NULL);
+       }
+       md0 =3D md;
+       up =3D (pa > md->md_phys) ? 1 : 0;
+
+       do {
                if (pa >=3D md->md_phys &&
-                   pa < md->md_phys + md->md_pages * EFI_PAGE_SIZE) {
+                       pa < md->md_phys + md->md_pages * EFI_PAGE_SIZE) {
                        last =3D md;
                        return (md);
                }

-               p1 =3D p0;
-               p0 =3D md;
-               md =3D (pa < md->md_phys) ? efi_md_prev(md) : efi_md_next(m=
d);
-       }
+               md =3D up ? efi_md_next(md) : efi_md_prev(md);
+               if (md =3D=3D NULL) {
+                       md =3D up ? efi_md_first() : efi_md_last();
+               }
+       } while (md !=3D md0);

        return (NULL);
 }

The firmware of the HP Integrity rx2800-i4 contains a myriad of small memor=
y descriptors of the type EFI_MD_TYPE_BS_CODE and EFI_MD_TYPE_BS_DATA. Tryi=
ng to use them f=FCr the physmem map overburdens the structures holding the=
 descriptors. Increasing the size of the structures doesn't help. The solut=
ion is not to use them for the physmem map. Furthermore the mapping pagesiz=
e shift should not be odd (as is the case for the rx2800 firmware).

machdep.patch:
--- sys/ia64/ia64/machdep.c.orig        2015-07-31 14:18:23.000000000 +0200
+++ sys/ia64/ia64/machdep.c     2015-08-13 15:59:29.624985000 +0200
@@ -622,6 +622,9 @@
                shft++;
                sz >>=3D 1;
        }
+       if (shft & 1) {
+               shft++;
+       }

        pte =3D PTE_PRESENT | PTE_MA_WB | PTE_ACCESSED | PTE_DIRTY |
            PTE_PL_KERN | PTE_AR_RWX;
@@ -761,11 +764,11 @@
                case EFI_MD_TYPE_RECLAIM:
                case EFI_MD_TYPE_RT_CODE:
                case EFI_MD_TYPE_RT_DATA:
+               case EFI_MD_TYPE_BS_CODE:
+               case EFI_MD_TYPE_BS_DATA:
                        /* Don't use these memory regions. */
                        ia64_physmem_track(md->md_phys, mdlen);
                        break;
-               case EFI_MD_TYPE_BS_CODE:
-               case EFI_MD_TYPE_BS_DATA:
                case EFI_MD_TYPE_CODE:
                case EFI_MD_TYPE_DATA:
                case EFI_MD_TYPE_FREE:
--- sys/ia64/ia64/dump_machdep.c.orig   2015-08-13 07:59:43.000000000 +0200
+++ sys/ia64/ia64/dump_machdep.c        2015-08-13 15:59:04.582524000 +0200
@@ -203,9 +203,7 @@
        while (mdp !=3D NULL) {
                if (mdp->md_type =3D=3D EFI_MD_TYPE_FREE ||
                    mdp->md_type =3D=3D EFI_MD_TYPE_DATA ||
-                   mdp->md_type =3D=3D EFI_MD_TYPE_CODE ||
-                   mdp->md_type =3D=3D EFI_MD_TYPE_BS_DATA ||
-                   mdp->md_type =3D=3D EFI_MD_TYPE_BS_CODE) {
+                   mdp->md_type =3D=3D EFI_MD_TYPE_CODE) {
                        error =3D (*cb)(mdp, seqnr++, arg);
                        if (error)
                                return (-error);

The igb driver has alignment issues that lead to kernel panics. Furthermore=
 watchdog timeouts drag the network interface down regularily and are also =
causing kernel panics. The following patch fixes this. Alas the network dri=
ver still has some severe issues that hampers the usage (for example remote=
 access via ssh). Ping rtts on the local network are on average in the orde=
r of hundreds of milliseconds. On FreeBSD 9 the igb driver also needs fixin=
g due to alignment issues and watchdog timeouts but there the network perfo=
rmance in the end is satisfying with ping rtts in the sub-millisecond regim=
e.

if_igb.patch:
--- sys/dev/e1000/if_igb.h.orig 2016-02-26 13:10:58.344796000 +0100
+++ sys/dev/e1000/if_igb.h      2016-02-26 13:55:00.420598000 +0100
@@ -599,6 +599,8 @@
 #define        IGB_RX_UNLOCK(_sc)              mtx_unlock(&(_sc)->rx_mtx)
 #define        IGB_RX_LOCK_ASSERT(_sc)         mtx_assert(&(_sc)->rx_mtx, =
MA_OWNED)

+#define        IGB_RXBUF_ALIGN         (sizeof(uint32_t))
+
 #define UPDATE_VF_REG(reg, last, cur)          \
 {                                              \
        u32 new =3D E1000_READ_REG(hw, reg);      \
--- sys/dev/e1000/if_igb.c.orig 2016-02-26 13:11:36.634944000 +0100
+++ sys/dev/e1000/if_igb.c      2016-02-26 14:19:43.271194000 +0100
@@ -171,6 +171,9 @@
 static __inline        void igb_rx_discard(struct rx_ring *, int);
 static __inline void igb_rx_input(struct rx_ring *,
                    struct ifnet *, struct mbuf *, u32);
+#ifndef __NO_STRICT_ALIGNMENT
+static __inline void igb_fixup_rx(struct mbuf *);
+#endif

 static bool    igb_rxeof(struct igb_queue *, int, int *);
 static void    igb_rx_checksum(u32, struct mbuf *, u32);
@@ -3993,7 +3996,8 @@
        ** would have been taken, so none processed
        ** for too long indicates a hang.
        */
-       if ((!processed) && ((ticks - txr->watchdog_time) > IGB_WATCHDOG))
+       if ((!processed) && ((ticks - txr->watchdog_time) > IGB_WATCHDOG) &=
&
+               txr->queue_status =3D=3D IGB_QUEUE_WORKING)
                txr->queue_status |=3D IGB_QUEUE_HUNG;

        if (txr->tx_avail >=3D IGB_QUEUE_THRESHOLD)
@@ -4051,6 +4055,9 @@
                mh->m_pkthdr.len =3D mh->m_len =3D MHLEN;
                mh->m_len =3D MHLEN;
                mh->m_flags |=3D M_PKTHDR;
+#ifndef __NO_STRICT_ALIGNMENT
+               m_adj(mh, IGB_RXBUF_ALIGN);
+#endif
                /* Get the memory mapping */
                error =3D bus_dmamap_load_mbuf_sg(rxr->htag,
                    rxbuf->hmap, mh, hseg, &nsegs, BUS_DMA_NOWAIT);
@@ -4076,6 +4083,9 @@
                        mp =3D rxbuf->m_pack;

                mp->m_pkthdr.len =3D mp->m_len =3D adapter->rx_mbuf_sz;
+#ifndef __NO_STRICT_ALIGNMENT
+               m_adj(mp, IGB_RXBUF_ALIGN);
+#endif
                /* Get the memory mapping */
                error =3D bus_dmamap_load_mbuf_sg(rxr->ptag,
                    rxbuf->pmap, mp, pseg, &nsegs, BUS_DMA_NOWAIT);
@@ -4291,6 +4301,9 @@
                mh =3D rxbuf->m_head;
                mh->m_len =3D mh->m_pkthdr.len =3D MHLEN;
                mh->m_flags |=3D M_PKTHDR;
+#ifndef __NO_STRICT_ALIGNMENT
+               m_adj(mh, IGB_RXBUF_ALIGN);
+#endif
                /* Get the memory mapping */
                error =3D bus_dmamap_load_mbuf_sg(rxr->htag,
                    rxbuf->hmap, rxbuf->m_head, hseg,
@@ -4312,6 +4325,9 @@
                }
                mp =3D rxbuf->m_pack;
                mp->m_pkthdr.len =3D mp->m_len =3D adapter->rx_mbuf_sz;
+#ifndef __NO_STRICT_ALIGNMENT
+               m_adj(mp, IGB_RXBUF_ALIGN);
+#endif
                /* Get the memory mapping */
                error =3D bus_dmamap_load_mbuf_sg(rxr->ptag,
                    rxbuf->pmap, mp, pseg,
@@ -4747,6 +4763,23 @@
        IGB_RX_LOCK(rxr);
 }

+#ifndef __NO_STRICT_ALIGNMENT
+static __inline void
+igb_fixup_rx(struct mbuf *m)
+{
+       int i;
+       uint16_t *src, *dst;
+
+       src =3D mtod(m, uint16_t *);
+       dst =3D src - (IGB_RXBUF_ALIGN - ETHER_ALIGN) / sizeof *src;
+
+       for (i =3D 0; i < (m->m_len / sizeof(uint16_t) + 1); i++)
+               *dst++ =3D *src++;
+
+       m->m_data -=3D IGB_RXBUF_ALIGN - ETHER_ALIGN;
+}
+#endif
+
 /*********************************************************************
  *
  *  This routine executes in interrupt context. It replenishes
@@ -4893,6 +4926,9 @@

                if (eop) {
                        rxr->fmp->m_pkthdr.rcvif =3D ifp;
+#ifndef __NO_STRICT_ALIGNMENT
+                       igb_fixup_rx(rxr->fmp);
+#endif
                        ifp->if_ipackets++;
                        rxr->rx_packets++;
                        /* capture data for AIM */

Maybe these patches  are of use for someone.

Regards,
Wolfgang Meyer


________________________________

Follow HOB:

- HOB: http://www.hob.de/redirect/hob.html
- Xing: http://www.hob.de/redirect/xing.html
- LinkedIn: http://www.hob.de/redirect/linkedin.html
- HOBLink Mobile: http://www.hob.de/redirect/hoblinkmobile.html
- Facebook: http://www.hob.de/redirect/facebook.html
- Twitter: http://www.hob.de/redirect/twitter.html
- YouTube: http://www.hob.de/redirect/youtube.html
- E-Mail: http://www.hob.de/redirect/mail.html


HOB GmbH & Co. KG
Schwadermuehlstr. 3
D-90556 Cadolzburg

Geschaeftsfuehrung: Klaus Brandstaetter, Zoran Adamovic

AG Fuerth, HRA 5180
Steuer-Nr. 218/163/00107
USt-ID-Nr. DE 132747002

Komplementaerin HOB electronic Beteiligungs GmbH
AG Fuerth, HRB 3416



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?EC88118611AE564AB0B10C6A4569004D0137D5877A>