From f0613ab15b5d3060331332a023e1fc862817fd7a Mon Sep 17 00:00:00 2001 From: "Jayachandran C." Date: Thu, 16 Sep 2010 19:13:55 +0000 Subject: [PATCH] Network driver updates. - Move RMI MIPS extension to atomic increment word (LDADDWU) to common header file sys/mips/rmi/rmi_mips_exts.h - Fix xlr_ldaddwu() for 64 bit, it is a 32 bit operation, use unsigned int* instead of unsigned long* argument - Provide dummy xlr_enable_kx/xlr_restore_kx for n32 and n64. - Provide xlr_paddr_ld() instead of xlr_paddr_lw(), so that the descriptor formats are same for 32 and 64 bit - update nlge and rge for the changes These changes are also needed by the security driver which will be added later. --- sys/mips/rmi/dev/nlge/if_nlge.c | 85 ++++++++++---------------- sys/mips/rmi/dev/xlr/rge.c | 66 ++++---------------- sys/mips/rmi/rmi_mips_exts.h | 104 ++++++++++++++++++++++++-------- 3 files changed, 124 insertions(+), 131 deletions(-) diff --git a/sys/mips/rmi/dev/nlge/if_nlge.c b/sys/mips/rmi/dev/nlge/if_nlge.c index a80b26745396..1a217c0445b8 100644 --- a/sys/mips/rmi/dev/nlge/if_nlge.c +++ b/sys/mips/rmi/dev/nlge/if_nlge.c @@ -300,31 +300,13 @@ DRIVER_MODULE(miibus, nlge, miibus_driver, miibus_devclass, 0, 0); static uma_zone_t nl_tx_desc_zone; -/* Function to atomically increment an integer with the given value. */ -static __inline__ unsigned int -ldadd_wu(unsigned int value, unsigned long *addr) +static __inline void +atomic_incr_long(unsigned long *addr) { - __asm__ __volatile__( ".set push\n" - ".set noreorder\n" - "move $8, %2\n" - "move $9, %3\n" - /* "ldaddwu $8, $9\n" */ - ".word 0x71280011\n" - "move %0, $8\n" - ".set pop\n" - : "=&r"(value), "+m"(*addr) - : "0"(value), "r" ((unsigned long)addr) - : "$8", "$9"); - return value; -} + /* XXX: fix for 64 bit */ + unsigned int *iaddr = (unsigned int *)addr; -static __inline__ uint32_t -xlr_enable_kx(void) -{ - uint32_t sr = mips_rd_status(); - - mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX); - return sr; + xlr_ldaddwu(1, iaddr); } static int @@ -683,7 +665,7 @@ nlge_msgring_handler(int bucket, int size, int code, int stid, if (ifp->if_drv_flags & IFF_DRV_OACTIVE){ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; } - ldadd_wu(1, (tx_error) ? &ifp->if_oerrors: &ifp->if_opackets); + atomic_incr_long((tx_error) ? &ifp->if_oerrors: &ifp->if_opackets); } else if (ctrl == CTRL_SNGL || ctrl == CTRL_START) { /* Rx Packet */ @@ -766,7 +748,7 @@ nlge_start_locked(struct ifnet *ifp, struct nlge_softc *sc) //ifp->if_drv_flags |= IFF_DRV_OACTIVE; //IF_PREPEND(&ifp->if_snd, m); m_freem(m); - ldadd_wu(1, &ifp->if_iqdrops); + atomic_incr_long(&ifp->if_iqdrops); } return; } @@ -774,14 +756,15 @@ nlge_start_locked(struct ifnet *ifp, struct nlge_softc *sc) static void nlge_rx(struct nlge_softc *sc, vm_paddr_t paddr, int len) { - struct ifnet *ifp; - struct mbuf *m; - uint32_t tm, mag, sr; + struct ifnet *ifp; + struct mbuf *m; + uint64_t tm, mag; + uint32_t sr; sr = xlr_enable_kx(); - tm = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE); - mag = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + sizeof(uint32_t)); - mips_wr_status(sr); + tm = xlr_paddr_ld(paddr - XLR_CACHELINE_SIZE); + mag = xlr_paddr_ld(paddr - XLR_CACHELINE_SIZE + sizeof(uint64_t)); + xlr_restore_kx(sr); m = (struct mbuf *)(intptr_t)tm; if (mag != 0xf00bad) { @@ -797,7 +780,7 @@ nlge_rx(struct nlge_softc *sc, vm_paddr_t paddr, int len) m->m_pkthdr.len = m->m_len = len; m->m_pkthdr.rcvif = ifp; - ldadd_wu(1, &ifp->if_ipackets); + atomic_incr_long(&ifp->if_ipackets); (*ifp->if_input)(ifp, m); } @@ -1895,15 +1878,11 @@ prepare_fmn_message(struct nlge_softc *sc, struct msgrng_msg *fmn_msg, return 2; } /* - * As we currently use xlr_paddr_lw on a 32-bit - * OS, both the pointers are laid out in one - * 64-bit location - this makes it easy to - * retrieve the pointers when processing the - * tx free-back descriptor. + * Save the virtual address in the descriptor, + * it makes freeing easy. */ p2p->frag[XLR_MAX_TX_FRAGS] = - (((uint64_t) (vm_offset_t) p2p) << 32) | - ((vm_offset_t) mbuf_chain); + (uint64_t)(vm_offset_t)p2p; cur_p2d = &p2p->frag[0]; is_p2p = 1; } else if (msg_sz == (FMN_SZ - 2 + XLR_MAX_TX_FRAGS)) { @@ -1932,7 +1911,7 @@ prepare_fmn_message(struct nlge_softc *sc, struct msgrng_msg *fmn_msg, cur_p2d[-1] |= (1ULL << 63); /* set eop in most-recent p2d */ *cur_p2d = (1ULL << 63) | ((uint64_t)fb_stn_id << 54) | - (vm_offset_t) mbuf_chain; + (vm_offset_t) mbuf_chain; /* XXX: fix 64 bit */ *tx_desc = p2p; if (is_p2p) { @@ -1973,39 +1952,41 @@ release_tx_desc(vm_paddr_t paddr) { struct nlge_tx_desc *tx_desc; uint32_t sr; - uint32_t val1, val2; + uint64_t vaddr; paddr += (XLR_MAX_TX_FRAGS * sizeof(uint64_t)); sr = xlr_enable_kx(); - val1 = xlr_paddr_lw(paddr); - paddr += sizeof(void *); - val2 = xlr_paddr_lw(paddr); - mips_wr_status(sr); + vaddr = xlr_paddr_ld(paddr); + xlr_restore_kx(sr); - tx_desc = (struct nlge_tx_desc*)(intptr_t) val1; + tx_desc = (struct nlge_tx_desc*)(intptr_t)vaddr; uma_zfree(nl_tx_desc_zone, tx_desc); } static void * get_buf(void) { - struct mbuf *m_new; - vm_paddr_t temp1, temp2; - unsigned int *md; + struct mbuf *m_new; + uint64_t *md; +#ifdef INVARIANTS + vm_paddr_t temp1, temp2; +#endif if ((m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR)) == NULL) - return NULL; + return (NULL); m_new->m_len = m_new->m_pkthdr.len = MCLBYTES; m_adj(m_new, XLR_CACHELINE_SIZE - ((unsigned int)m_new->m_data & 0x1f)); - md = (unsigned int *)m_new->m_data; - md[0] = (unsigned int)m_new; /* Back Ptr */ + md = (uint64_t *)m_new->m_data; + md[0] = (intptr_t)m_new; /* Back Ptr */ md[1] = 0xf00bad; m_adj(m_new, XLR_CACHELINE_SIZE); +#ifdef INVARIANTS temp1 = vtophys((vm_offset_t) m_new->m_data); temp2 = vtophys((vm_offset_t) m_new->m_data + 1536); if ((temp1 + 1536) != temp2) panic("ALLOCED BUFFER IS NOT CONTIGUOUS\n"); +#endif return ((void *)m_new->m_data); } diff --git a/sys/mips/rmi/dev/xlr/rge.c b/sys/mips/rmi/dev/xlr/rge.c index c7a02c261d13..09045f4bdcf3 100644 --- a/sys/mips/rmi/dev/xlr/rge.c +++ b/sys/mips/rmi/dev/xlr/rge.c @@ -184,35 +184,8 @@ int xlr_rge_tx_ok_done[MAXCPU]; int xlr_rge_rx_done[MAXCPU]; int xlr_rge_repl_done[MAXCPU]; -static __inline__ unsigned int -ldadd_wu(unsigned int value, unsigned long *addr) -{ - __asm__ __volatile__(".set push\n" - ".set noreorder\n" - "move $8, %2\n" - "move $9, %3\n" - /* "ldaddwu $8, $9\n" */ - ".word 0x71280011\n" - "move %0, $8\n" - ".set pop\n" - : "=&r"(value), "+m"(*addr) - : "0"(value), "r"((unsigned long)addr) - : "$8", "$9"); - - return value; -} - -static __inline__ uint32_t -xlr_enable_kx(void) -{ - uint32_t sr = mips_rd_status(); - - mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX); - return sr; -} - /* #define mac_stats_add(x, val) ({(x) += (val);}) */ -#define mac_stats_add(x, val) ldadd_wu(val, &x) +#define mac_stats_add(x, val) xlr_ldaddwu(val, &x) #define XLR_MAX_CORE 8 #define RGE_LOCK_INIT(_sc, _name) \ @@ -611,25 +584,16 @@ static void free_buf(vm_paddr_t paddr) { struct mbuf *m; - uint32_t mag; -#ifdef __mips_n64 - uint64_t *vaddr; - - vaddr = (uint64_t *)MIPS_PHYS_TO_XKPHYS_CACHED(paddr); - m = (struct mbuf *)vaddr[0]; - mag = (uint32_t)vaddr[1]; -#else + uint64_t mag; uint32_t sr; sr = xlr_enable_kx(); - m = (struct mbuf *)(intptr_t)xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + sizeof(uint32_t)); - mag = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + 3 * sizeof(uint32_t)); - mips_wr_status(sr); -#endif - + m = (struct mbuf *)(intptr_t)xlr_paddr_ld(paddr - XLR_CACHELINE_SIZE); + mag = xlr_paddr_ld(paddr - XLR_CACHELINE_SIZE + sizeof(uint64_t)); + xlr_restore_kx(sr); if (mag != 0xf00bad) { - printf("Something is wrong kseg:%lx found mag:%x not 0xf00bad\n", - (u_long)paddr, mag); + printf("Something is wrong kseg:%lx found mag:%lx not 0xf00bad\n", + (u_long)paddr, (u_long)mag); return; } if (m != NULL) @@ -2022,15 +1986,8 @@ static void rge_rx(struct rge_softc *sc, vm_paddr_t paddr, int len) { struct mbuf *m; - uint32_t mag; struct ifnet *ifp = sc->rge_ifp; -#ifdef __mips_n64 - uint64_t *vaddr; - - vaddr =(uint64_t *)MIPS_PHYS_TO_XKPHYS_CACHED(paddr - XLR_CACHELINE_SIZE); - m = (struct mbuf *)vaddr[0]; - mag = (uint32_t)vaddr[1]; -#else + uint64_t mag; uint32_t sr; /* * On 32 bit machines we use XKPHYS to get the values stores with @@ -2038,10 +1995,9 @@ rge_rx(struct rge_softc *sc, vm_paddr_t paddr, int len) * KX is enabled to prevent this setting leaking to other code. */ sr = xlr_enable_kx(); - m = (struct mbuf *)(intptr_t)xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + sizeof(uint32_t)); - mag = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + 3 * sizeof(uint32_t)); - mips_wr_status(sr); -#endif + m = (struct mbuf *)(intptr_t)xlr_paddr_ld(paddr - XLR_CACHELINE_SIZE); + mag = xlr_paddr_ld(paddr - XLR_CACHELINE_SIZE + sizeof(uint64_t)); + xlr_restore_kx(sr); if (mag != 0xf00bad) { /* somebody else packet Error - FIXME in intialization */ printf("cpu %d: *ERROR* Not my packet paddr %p\n", diff --git a/sys/mips/rmi/rmi_mips_exts.h b/sys/mips/rmi/rmi_mips_exts.h index 6f86ed257bff..a21f5e020f26 100644 --- a/sys/mips/rmi/rmi_mips_exts.h +++ b/sys/mips/rmi/rmi_mips_exts.h @@ -348,7 +348,7 @@ write_c0_eimr64(uint64_t val) write_c0_register64(9, 7, val); } -static __inline__ int +static __inline int xlr_test_and_set(int *lock) { int oldval = 0; @@ -367,10 +367,10 @@ xlr_test_and_set(int *lock) : "$8", "$9" ); - return (oldval == 0 ? 1 /* success */ : 0 /* failure */ ); + return (oldval == 0 ? 1 /* success */ : 0 /* failure */); } -static __inline__ uint32_t +static __inline uint32_t xlr_mfcr(uint32_t reg) { uint32_t val; @@ -385,7 +385,7 @@ xlr_mfcr(uint32_t reg) return val; } -static __inline__ void +static __inline void xlr_mtcr(uint32_t reg, uint32_t val) { __asm__ __volatile__( @@ -396,26 +396,47 @@ xlr_mtcr(uint32_t reg, uint32_t val) : "$8", "$9"); } +/* + * Atomic increment a unsigned int + */ +static __inline unsigned int +xlr_ldaddwu(unsigned int value, unsigned int *addr) +{ + __asm__ __volatile__( + ".set push\n" + ".set noreorder\n" + "move $8, %2\n" + "move $9, %3\n" + ".word 0x71280011\n" /* ldaddwu $8, $9 */ + "move %0, $8\n" + ".set pop\n" + : "=&r"(value), "+m"(*addr) + : "0"(value), "r" ((unsigned long)addr) + : "$8", "$9"); + + return (value); +} + #if defined(__mips_n64) -static __inline__ uint32_t -xlr_paddr_lw(uint64_t paddr) +static __inline uint64_t +xlr_paddr_ld(uint64_t paddr) { paddr |= 0x9800000000000000ULL; - return (*(uint32_t *)(uintptr_t)paddr); + return (*(uint64_t *)(uintptr_t)paddr); } #elif defined(__mips_n32) -static __inline__ uint32_t -xlr_paddr_lw(uint64_t paddr) +static __inline uint64_t +xlr_paddr_ld(uint64_t paddr) { - uint32_t val; + uint64_t val; paddr |= 0x9800000000000000ULL; __asm__ __volatile__( ".set push \n\t" ".set mips64 \n\t" - "lw %0, 0(%1) \n\t" + "ld %0, 0(%1) \n\t" ".set pop \n" : "=r"(val) : "r"(paddr)); @@ -423,27 +444,62 @@ xlr_paddr_lw(uint64_t paddr) return (val); } #else -static __inline__ uint32_t -xlr_paddr_lw(uint64_t paddr) +static __inline uint32_t +xlr_paddr_ld(uint64_t paddr) { - uint32_t high, low, tmp; + uint32_t addrh, addrl; + uint32_t valh, vall; - high = 0x98000000 | (paddr >> 32); - low = paddr & 0xffffffff; + addrh = 0x98000000 | (paddr >> 32); + addrl = paddr & 0xffffffff; __asm__ __volatile__( ".set push \n\t" ".set mips64 \n\t" - "dsll32 %1, %1, 0 \n\t" - "dsll32 %2, %2, 0 \n\t" /* get rid of the */ - "dsrl32 %2, %2, 0 \n\t" /* sign extend */ - "or %1, %1, %2 \n\t" - "lw %0, 0(%1) \n\t" + "dsll32 %2, %2, 0 \n\t" + "dsll32 %3, %3, 0 \n\t" /* get rid of the */ + "dsrl32 %3, %3, 0 \n\t" /* sign extend */ + "or %2, %2, %3 \n\t" + "lw %0, 0(%2) \n\t" + "lw %1, 4(%2) \n\t" ".set pop \n" - : "=r"(tmp) - : "r"(high), "r"(low)); + : "=&r"(valh), "=r"(vall) + : "r"(addrh), "r"(addrl)); - return tmp; + return (((uint64_t)valh << 32) | vall); +} +#endif + +/* + * XXX: Not really needed in n32 or n64, retain for now + */ +#if defined(__mips_n64) || defined(__mips_n32) +static __inline uint32_t +xlr_enable_kx(void) +{ + + return (0); +} + +static __inline void +xlr_restore_kx(uint32_t sr) +{ +} +#else +static __inline uint32_t +xlr_enable_kx(void) +{ + uint32_t sr = mips_rd_status(); + + mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX); + return (sr); +} + +static __inline void +xlr_restore_kx(uint32_t sr) +{ + + mips_wr_status(sr); } #endif