From: Zhang Haitao <zhanght@netpower.com.cn>
To: netdev <netdev@oss.sgi.com>
Subject: Re: Re: Hi, this is my patch for broadcom sb1250-mac.c
Date: Fri, 30 May 2003 15:55:01 +0800 [thread overview]
Message-ID: <3ED70E55.3020202@netpower.com.cn> (raw)
Hi all!
and Dear YOSHIFUJI Hideaki
i've corrected some bugs in my last broken driver,
now the driver work properly both under copper mode and fiber mode.
so this time i resend it in a more clear style :-)
and hope you all will glad to review it.
(you can turn off/on the NAPI options to do some contrast test
for both original mode and NAPI mode, even the parameters for original mode
have been modified for better performance)
Thanks
Zhang Haitao
----------------------
--- ./sb1250-broadcom.c 2003-05-30 00:48:36.000000000 +0800
+++ ./sb1250-mac.debug.c 2003-05-30 00:48:36.000000000 +0800
@@ -44,8 +44,8 @@
static int full_duplex[MAX_UNITS] = {-1, -1, -1};
#endif
-static int int_pktcnt = 0;
-static int int_timeout = 0;
+static int int_pktcnt = 32;
+static int int_timeout = 1024;
/* Operational parameters that usually are not changed. */
@@ -91,7 +91,8 @@
static char version1[] __devinitdata =
"sb1250-mac.c:1.00 1/11/2001 Written by Mitch Lichtenberg
(mpl@broadcom.com)\n";
#endif
-
+#define CONFIG_SB1250_NAPI
+#define NAPI_LOP_MAX 10
MODULE_AUTHOR("Mitch Lichtenberg (mpl@broadcom.com)");
@@ -154,8 +155,8 @@
#define PKSEG1(x) ((sbmac_port_t) KSEG1ADDR(x))
-#define SBMAC_MAX_TXDESCR 32
-#define SBMAC_MAX_RXDESCR 32
+#define SBMAC_MAX_TXDESCR 128
+#define SBMAC_MAX_RXDESCR 128
#define ETHER_ALIGN 2
#define ETHER_ADDR_LEN 6
@@ -190,8 +191,8 @@
int
sbdma_txdir; /* direction (1=transmit) */
int
sbdma_maxdescr;
/* total # of descriptors in ring */
#ifdef CONFIG_SBMAC_COALESCE
- int sbdma_int_pktcnt; /* # descriptors rx/tx
before interrupt*/
- int sbdma_int_timeout; /* # usec rx/tx interrupt */
+ int sbdma_int_pktcnt; /* # descriptors rx before
interrupt*/
+ int sbdma_int_timeout; /* # usec rx interrupt */
#endif
sbmac_port_t sbdma_config0; /* DMA config register 0 */
@@ -262,11 +263,13 @@
u_char sbm_hwaddr[ETHER_ADDR_LEN];
-
sbmacdma_t sbm_txdma; /* for now, only use channel 0 */
+
sbmacdma_t sbm_txdma; /* for now, use channel 0 */
sbmacdma_t sbm_rxdma;
int rx_hw_checksum;
int sbe_idx;
+
int sbm_fibermode;
+
int sbm_phy_oldsignaldetect;
};
@@ -288,7 +291,6 @@
static int sbdma_add_txbuffer(sbmacdma_t *d,struct sk_buff *m);
static void sbdma_emptyring(sbmacdma_t *d);
static void sbdma_fillring(sbmacdma_t *d);
-static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d);
static void sbdma_tx_process(struct sbmac_softc *sc,sbmacdma_t *d);
static int sbmac_initctx(struct sbmac_softc *s);
static void sbmac_channel_start(struct sbmac_softc *s);
@@ -299,6 +301,13 @@
static uint64_t sbmac_addr2reg(unsigned char *ptr);
static void sbmac_intr(int irq,void *dev_instance,struct pt_regs *rgs);
static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev);
+#ifdef CONFIG_SB1250_NAPI
+static int sbmac_poll(struct net_device *dev_instance, int *budget);
+static inline void sbmac_irq_disable(struct sbmac_softc *s);
+static inline void sbmac_irq_enable(struct sbmac_softc *s);
+#else
+static void sbdma_rx_process(struct sbmac_softc *sc,sbmacdma_t *d);
+#endif
static void sbmac_setmulti(struct sbmac_softc *sc);
static int sbmac_init(struct net_device *dev);
static int sbmac_set_speed(struct sbmac_softc *s,sbmac_speed_t speed);
@@ -448,6 +457,15 @@
#define PHYSUP_LINKUP 0x04
#define PHYSUP_FDX 0x02
+/* Added for Fiber mode detection
+just read Signal Detect alternation */
+
+#define MII_AUXCTL 0x18 /* Auxiliary Control Register */
+
+#define MII_SGMIISR 0x0C /* SGMII/100-X Status Register */
+
+#define SGMIISR_FIBERSDS 0x2000
+
#define MII_BMCR
0x00 /* Basic mode control register (rw) */
#define MII_BMSR
0x01
/* Basic mode status register (ro) */
#define MII_K1STSR 0x0A /* 1K Status Register (ro) */
@@ -459,6 +477,17 @@
#define ENABLE 1
#define DISABLE 0
+#ifdef CONFIG_SB1250_NAPI
+static inline void sbmac_irq_disable(struct sbmac_softc *s){
+ SBMAC_WRITECSR(s->sbm_imr,
+
((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0));
+}
+static inline void sbmac_irq_enable(struct sbmac_softc *s){
+
SBMAC_WRITECSR(s->sbm_imr,
+
((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
+
((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0));
+}
+#endif
/**********************************************************************
* SBMAC_MII_SYNC(s)
*
@@ -759,7 +788,7 @@
#ifdef CONFIG_SBMAC_COALESCE
/*
- * Setup Rx/Tx DMA coalescing defaults
+ * Setup RxTx DMA coalescing defaults
*/
if ( int_pktcnt ) {
@@ -944,7 +973,7 @@
sb_new = sb;
/*
* nothing special to reinit buffer, it's already aligned
-
* and sb->data already points to a good place.
+
* and sb->tail already points to a good place.
*/
}
@@ -956,11 +985,11 @@
/*
* Do not interrupt per DMA transfer.
*/
- dsc->dscr_a = KVTOPHYS(sb_new->data) |
+ dsc->dscr_a = KVTOPHYS(sb_new->tail) |
V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
0;
#else
-
dsc->dscr_a = KVTOPHYS(sb_new->data) |
+
dsc->dscr_a = KVTOPHYS(sb_new->tail) |
V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize+ETHER_ALIGN)) |
M_DMA_DSCRA_INTERRUPT;
#endif
@@ -1045,16 +1074,17 @@
phys = KVTOPHYS(sb->data);
ncb = NUMCACHEBLKS(length+(phys & (CACHELINESIZE-1)));
-
+#ifdef CONFIG_SBMAC_COALESCE
+
/* do not interript per DMA transfer*/
dsc->dscr_a = phys |
V_DMA_DSCRA_A_SIZE(ncb) |
-#ifdef CONFIG_SBMAC_COALESCE
- 0 |
+
M_DMA_ETHTX_SOP;
#else
+
dsc->dscr_a = phys |
+
V_DMA_DSCRA_A_SIZE(ncb) |
M_DMA_DSCRA_INTERRUPT |
-#endif
M_DMA_ETHTX_SOP;
-
+#endif
/* transmitting: set outbound options and length */
dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) |
@@ -1133,7 +1163,7 @@
}
}
-
+#ifndef CONFIG_SB1250_NAPI
/**********************************************************************
* SBDMA_RX_PROCESS(sc,d)
*
@@ -1181,6 +1211,14 @@
*/
if (curidx == hwidx) break;
+
/*{
+
int i;
+
for (i=0;;i++) {
+
if ((dsc->dscr_a & M_DMA_ETHRX_SOP) != 0)
+
break;
+
if (i >= NAPI_LOP_MAX) goto ret;
+
}
+
}*/
/*
* Otherwise, get the packet's sk_buff ptr back
@@ -1236,7 +1274,6 @@
sb->ip_summed = CHECKSUM_UNNECESSARY;
}
} /*rx_hw_checksum */
-
netif_rx(sb);
}
}
@@ -1258,7 +1295,7 @@
}
}
-
+#endif
/**********************************************************************
@@ -1352,6 +1389,7 @@
*/
dev_kfree_skb_irq(sb);
+
//__kfree_skb(sb); //try free fast
/*
* .. and advance to the next buffer.
@@ -1393,6 +1431,7 @@
static int sbmac_initctx(struct sbmac_softc *s)
{
+
int auxctl;
/*
* figure out the addresses of some ports
*/
@@ -1414,6 +1453,8 @@
s->sbm_phy_oldk1stsr = 0;
s->sbm_phy_oldlinkstat = 0;
+
s->sbm_phy_oldsignaldetect =0;
+
/*
* Initialize the DMA channels. Right now, only one per MAC is used
* Note: Only do this _once_, as it allocates memory from the kernel!
@@ -1421,7 +1462,6 @@
sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR);
sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR);
-
/*
* initial state is OFF
*/
@@ -1436,6 +1476,17 @@
s->sbm_duplex = sbmac_duplex_half;
s->sbm_fc = sbmac_fc_disabled;
+
/*
+
* Fiber/Copper Mode AutoDetection
+
*/
+
+
sbmac_mii_write(s,1,MII_AUXCTL,0x2007);
+
auxctl = sbmac_mii_read(s,1,MII_AUXCTL);
+
if(auxctl)
+
{
+
s->sbm_fibermode=1;
+
}
+
else s->sbm_fibermode=0;
return 0;
}
@@ -1632,6 +1683,8 @@
SBMAC_WRITECSR(s->sbm_macenable,
M_MAC_RXDMA_EN0 |
M_MAC_TXDMA_EN0 |
+
M_MAC_RXDMA_EN1 |
+
M_MAC_TXDMA_EN1 |
M_MAC_RX_ENABLE |
M_MAC_TX_ENABLE);
@@ -1645,6 +1698,7 @@
SBMAC_WRITECSR(s->sbm_imr,
((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0));
+
#else
/*
* Accept any kind of interrupt on TX and RX DMA channel 0
@@ -1967,7 +2021,7 @@
V_MAC_IFG_TX_1000 |
V_MAC_IFG_THRSH_1000 |
V_MAC_SLOT_SIZE_1000;
-
cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
+cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
break;
case sbmac_speed_auto: /* XXX not implemented */
@@ -2102,6 +2156,7 @@
{
struct net_device *dev = (struct net_device *) dev_instance;
struct sbmac_softc *sc = (struct sbmac_softc *) (dev->priv);
+
uint64_t isr;
for (;;) {
@@ -2124,7 +2179,7 @@
}
/*
-
* Receives on channel 0
+
* Receives on channel 0,1
*/
/*
@@ -2145,40 +2200,43 @@
if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
-
sbdma_rx_process(sc,&(sc->sbm_rxdma));
+#ifdef CONFIG_SB1250_NAPI
+
if (netif_rx_schedule_prep(dev)) {
+
sbmac_irq_disable(sc);
+
__netif_rx_schedule(dev);
}
+#else
+
sbdma_rx_process(sc,&(sc->sbm_rxdma));
+#endif
}
-
+}
}
static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
{
-
struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv;
-
-
/* lock eth irq */
-
spin_lock_irq (&sc->sbm_lock);
-
-
/*
+struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv;
+spin_lock_irq (&sc->sbm_lock);
+/*
* Put the buffer on the transmit ring. If we
* don't have room, stop the queue.
*/
-
if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
-
/* XXX save skb that we could not send */
+if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
+
/* XXX save skb that we could not send, then test 1 channel */
netif_stop_queue(dev);
spin_unlock_irq(&sc->sbm_lock);
@@ -2186,12 +2244,142 @@
}
dev->trans_start = jiffies;
-
spin_unlock_irq (&sc->sbm_lock);
return 0;
}
+#ifdef CONFIG_SB1250_NAPI
+//#define NAPI_POL_MAX 100
+static int sbmac_poll(struct net_device *dev_instance, int *budget) {
+
struct net_device *dev = (struct net_device *) dev_instance;
+ struct sbmac_softc *sc = (struct sbmac_softc *) (dev_instance->priv);
+ sbmacdma_t *d = &(sc->sbm_rxdma);
+ int rx_work_limit = *budget;
+
unsigned long flags;
+
long int receive=0;
+
int curidx;
+
int hwidx;
+
+
sbdmadscr_t *dsc;
+
struct sk_buff *sb;
+
int len;
+
+ if(rx_work_limit > dev->quota)
+ rx_work_limit = dev->quota;
+
+ for (;;) {
+
/*
+
* figure out where we are (as an index) and where
+
* the hardware is (also as an index)
+
*
+
* This could be done faster if (for example) the
+
* descriptor table was page-aligned and contiguous in
+
* both virtual and physical memory -- you could then
+
* just compare the low-order bits of the virtual address
+
* (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
+
*/
+
if(--rx_work_limit < 0) goto not_done;
+
curidx = d->sbdma_remptr - d->sbdma_dscrtable;
+
hwidx = (int) (((SBMAC_READCSR(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
+
d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
+
+
/*
+
* If they're the same, that means we've processed all
+
* of the descriptors up to (but not including) the one that
+
* the hardware is working on right now.
+
*/
+
+
if (curidx == hwidx) break;
+
+
/*
+
* Otherwise, get the packet's sk_buff ptr back
+
*/
+
+
dsc = &(d->sbdma_dscrtable[curidx]);
+
sb = d->sbdma_ctxtable[curidx];
+
d->sbdma_ctxtable[curidx] = NULL;
+
+
len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4;
+
/*
+
* Check packet status. If good, process it.
+
* If not, silently drop it and put it back on the
+
* receive ring.
+
*/
+
+
if (!(dsc->dscr_a & M_DMA_ETHRX_BAD)) {
+
+ /*
+
* Add a new buffer to replace the old one. If we fail
+
* to allocate a buffer, we're going to drop this
+
* packet and put it right back on the receive ring.
+
*/
+
+
if (sbdma_add_rcvbuffer(d,NULL) == -ENOBUFS) {
+
sc->sbm_stats.rx_dropped++;
+
sbdma_add_rcvbuffer(d,sb); /* re-add old buffer */
+
}
+
else {
+
/*
+
* Set length into the packet
+
*/
+
skb_put(sb,len);
+
+
/*
+
* Buffer has been replaced on the receive ring.
+
* Pass the buffer to the kernel
+
*/
+
sc->sbm_stats.rx_bytes += len;
+
sc->sbm_stats.rx_packets++;receive++;
+
sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev);
+ if (sc->rx_hw_checksum == ENABLE) {
+
/* if the ip checksum is good indicate in skb.
+
else set CHECKSUM_NONE as device failed to
+
checksum the packet */
+
+
if (((dsc->dscr_b) |M_DMA_ETHRX_BADTCPCS) ||
+
((dsc->dscr_a)| M_DMA_ETHRX_BADIP4CS)){
+
sb->ip_summed = CHECKSUM_NONE;
+
} else {
+
printk(KERN_DEBUG "hw checksum fail .\n");
+
sb->ip_summed = CHECKSUM_UNNECESSARY;
+
}
+
} /*rx_hw_checksum */
+ netif_receive_skb(sb);
+
}
+
}
+
else {
+
/*
+
* Packet was mangled somehow. Just drop it and
+
* put it back on the receive ring.
+
*/
+
sc->sbm_stats.rx_errors++;
+
sbdma_add_rcvbuffer(d,sb);
+
}
+
+
+
/*
+
* .. and advance to the next buffer.
+
*/
+
+
d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
+
+
}
+
if (!receive) receive = 1;
+
dev->quota -= receive;
+
*budget -= receive;
+
+
spin_lock_irqsave(&sc->sbm_lock,flags);
+
netif_rx_complete(dev);
+ sbmac_irq_enable(sc);
+
spin_unlock_irqrestore(&sc->sbm_lock,flags);
+
return 0;
+not_done:
+
dev->quota -= receive;
+
*budget -= receive;
+
return 1;
+}
+#endif
/**********************************************************************
* SBMAC_SETMULTI(sc)
*
@@ -2448,6 +2636,10 @@
dev->do_ioctl = sbmac_mii_ioctl;
dev->tx_timeout = sbmac_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+#ifdef CONFIG_SB1250_NAPI
+ dev->poll = sbmac_poll;
+ dev->weight =dev->quota = 80;
+#endif
dev->change_mtu = sb1250_change_mtu;
@@ -2525,6 +2717,10 @@
char buffer[100];
char *p = buffer;
+
int signaldetect;
+
+
if(s->sbm_fibermode == 0)
+
{
/* Read the mode status and mode control registers. */
bmsr = sbmac_mii_read(s,s->sbm_phys[0],MII_BMSR);
bmcr = sbmac_mii_read(s,s->sbm_phys[0],MII_BMCR);
@@ -2539,7 +2735,6 @@
else {
k1stsr = 0;
}
-
chg = 0;
if ((bmsr & BMSR_LINKSTAT) == 0) {
@@ -2620,6 +2815,41 @@
printk(KERN_INFO "s: s\n",s->sbm_dev->name,buffer);
}
+ }
+ else
+ { //fiber mode
+
+ chg=0;
+ printk("sbm_phy_oldsignaldetect:d\n",s->sbm_phy_oldsignaldetect);
+
+
signaldetect = (SGMIISR_FIBERSDS &
sbmac_mii_read(s,s->sbm_phys[0],MII_SGMIISR));
+
+ printk("current signaldetect:d\n",signaldetect);
+
+ if (signaldetect == 0)
+ {
+ printk("link state is DOWN!\n");
+
s->sbm_phy_oldsignaldetect = 0;
+
return 0;
+
}
+ else
+
{
+
if(s->sbm_phy_oldsignaldetect != signaldetect)
+ {
+ s->sbm_phy_oldsignaldetect = signaldetect;
+ chg = 1;
+ printk("link state has been changed\n");
+ }
+
}
+ if (chg==0) return 0;
+ printk("Link is up\n");
+ s->sbm_speed = sbmac_speed_1000;
+ s->sbm_duplex = sbmac_duplex_full;
+ s->sbm_fc = sbmac_fc_frame;
+ s->sbm_state = sbmac_state_on;
+
noisy =0;
+ printk("fiber mode.\t");
+ }
return 1;
}
@@ -2632,9 +2862,12 @@
struct sbmac_softc *sc = (struct sbmac_softc *)dev->priv;
int next_tick = HZ;
int mii_status;
+
int signaldetect;
spin_lock_irq (&sc->sbm_lock);
+ if(sc->sbm_fibermode == 0)
+ {
/* make IFF_RUNNING follow the MII status bit "Link established" */
mii_status = sbmac_mii_read(sc, sc->sbm_phys[0], MII_BMSR);
@@ -2647,6 +2880,23 @@
netif_carrier_off(dev);
}
}
+ }
+ else
+ {
+
signaldetect = (SGMIISR_FIBERSDS &
sbmac_mii_read(sc,sc->sbm_phys[0],MII_SGMIISR));
+ if(sc->sbm_phy_oldsignaldetect != signaldetect)
+ {
+ sc->sbm_phy_oldsignaldetect = signaldetect;
+
if (signaldetect) {
+ printk("netif_carrier_on. \n");
+
netif_carrier_on(dev);
+ }
+ else {
+
netif_carrier_off(dev);
+ }
+ printk("link state has been changed\n");
+ }
+ }
/*
* Poll the PHY to see what speed we should be running at
----------------------
>In article <3ED58DBA.6000506@netpower.com.cn> (at Thu, 29 May 2003
12:34:02 +0800), Zhang Haitao <zhanght@netpower.com.cn> says:
>
>> i'm very glad to let all of you to review this patch
>> or give me some advice from the oops message!
>
>Please don't try to make cosmetic changes
>including indentation, and/or new lines etc.
>
>Thank you.
>
>--
>Hideaki YOSHIFUJI @ USAGI Project <yoshfuji@linux-ipv6.org>
>GPG FP: 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA
---------------------------
next reply other threads:[~2003-05-30 7:55 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-05-30 7:55 Zhang Haitao [this message]
-- strict thread matches above, loose matches on Subject: below --
2003-05-29 17:44 Re: Hi, this is my patch for broadcom sb1250-mac.c Zhang Haitao
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3ED70E55.3020202@netpower.com.cn \
--to=zhanght@netpower.com.cn \
--cc=netdev@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).