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.
This commit is contained in:
Jayachandran C. 2010-09-16 19:13:55 +00:00
parent d0d7bcdf92
commit f0613ab15b
3 changed files with 124 additions and 131 deletions

View File

@ -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);
}

View File

@ -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",

View File

@ -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