Hi Greg,
The discussion with David yielded the attached cset. The credit goes for David, who did most of the patch and Mike who put a good deal of testing.
Please apply, Petko
You can import this changeset into BK by piping this whole message to: '| bk receive [path to repository]' or apply the patch as usual.
===================================================================
[EMAIL PROTECTED], 2005-01-13 13:04:06+02:00, [EMAIL PROTECTED]
Various fixes to the 'pegasus' driver, notably fixing OSDL bugid #3978
so this can be used with bridges again (or for that matter, other
normal usage).
* Bugfixes in the status urb completion handler:
- Never use garbage that happens to be sitting in the URB
data buffer to change the carrier status.
- There are two bits which claim to report parts of carrier
detect bit. This switches to the one that works sometimes;
monitoring through MII might be the best solution.
- Stop log spamming ... at least some of these chips seem
to get confused about data toggle, no point in warning
about each packet error as it's detected.
* Report the normal Ethernet MTU.
* Better ethtool support:
- Save the message level set by userspace
- Basic WOL support
* Add USB suspend() and resume() methods, to go with WOL.
Modeled on what stir4200 does.
Also, some of the messages are converted to the more conventional
style: "ethN: message text", or driver model style before the
device is registered.
Signed-off-by: David Brownell <[EMAIL PROTECTED]>
* removed redundant MII code since CONFIG_MII is always set by Kconfig;
* updated the version string;
Signed-off-by: Petko Manolov <[EMAIL PROTECTED]>
pegasus.c | 204 ++++++++++++++++++++++++++++++++++----------------------------
pegasus.h | 3
2 files changed, 117 insertions(+), 90 deletions(-)
diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
--- a/drivers/usb/net/pegasus.c 2005-01-13 13:04:59 +02:00
+++ b/drivers/usb/net/pegasus.c 2005-01-13 13:04:59 +02:00
@@ -28,6 +28,8 @@
* is out of the interrupt routine.
*/
+#undef DEBUG
+
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/init.h>
@@ -45,7 +47,7 @@
/*
* Version Information
*/
-#define DRIVER_VERSION "v0.5.12 (2003/06/06)"
+#define DRIVER_VERSION "v0.5.12 (2005/01/13)"
#define DRIVER_AUTHOR "Petko Manolov <[EMAIL PROTECTED]>"
#define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
@@ -712,11 +714,11 @@
{
pegasus_t *pegasus = urb->context;
struct net_device *net;
- __u8 *d;
int status;
if (!pegasus)
return;
+ net = pegasus->net;
switch (urb->status) {
case 0:
@@ -726,36 +728,50 @@
case -ESHUTDOWN:
return;
default:
- info("intr status %d", urb->status);
+ /* some Pegasus-I products report LOTS of data
+ * toggle errors... avoid log spamming
+ */
+ pr_debug("%s: intr status %d\n", net->name, urb->status);
}
- d = urb->transfer_buffer;
- net = pegasus->net;
- if (d[0] & 0xfc) {
- pegasus->stats.tx_errors++;
- if (d[0] & TX_UNDERRUN)
- pegasus->stats.tx_fifo_errors++;
- if (d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT))
- pegasus->stats.tx_aborted_errors++;
- if (d[0] & LATE_COL)
- pegasus->stats.tx_window_errors++;
- if (d[5] & LINK_STATUS) {
- netif_carrier_on(net);
- } else {
- pegasus->stats.tx_carrier_errors++;
- netif_carrier_off(net);
+ if (urb->actual_length >= 6) {
+ u8 * d = urb->transfer_buffer;
+
+ /* byte 0 == tx_status1, reg 2B */
+ if (d[0] & (TX_UNDERRUN|EXCESSIVE_COL
+ |LATE_COL|JABBER_TIMEOUT)) {
+ pegasus->stats.tx_errors++;
+ if (d[0] & TX_UNDERRUN)
+ pegasus->stats.tx_fifo_errors++;
+ if (d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT))
+ pegasus->stats.tx_aborted_errors++;
+ if (d[0] & LATE_COL)
+ pegasus->stats.tx_window_errors++;
}
+
+ /* d[5].LINK_STATUS lies on some adapters.
+ * d[0].NO_CARRIER kicks in only with failed TX.
+ * ... so monitoring with MII may be safest.
+ */
+ if (d[0] & NO_CARRIER)
+ netif_carrier_off(net);
+ else
+ netif_carrier_on(net);
+
+ /* bytes 3-4 == rx_lostpkt, reg 2E/2F */
+ pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4];
}
status = usb_submit_urb(urb, SLAB_ATOMIC);
if (status)
- err("%s: can't resubmit interrupt urb, %d", net->name, status);
+ printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n",
+ net->name, status);
}
static void pegasus_tx_timeout(struct net_device *net)
{
pegasus_t *pegasus = netdev_priv(net);
- warn("%s: Tx timed out.", net->name);
+ printk(KERN_WARNING "%s: tx timeout\n", net->name);
pegasus->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
usb_unlink_urb(pegasus->tx_urb);
pegasus->stats.tx_errors++;
@@ -948,14 +964,57 @@
usb_make_path(pegasus->usb, info->bus_info, sizeof (info->bus_info));
}
-#ifdef CONFIG_MII
-static int pegasus_get_settings(struct net_device *dev, struct ethtool_cmd
*ecmd)
+/* also handles three patterns of some kind in hardware */
+#define WOL_SUPPORTED (WAKE_MAGIC|WAKE_PHY)
+
+static void
+pegasus_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ pegasus_t *pegasus = netdev_priv(dev);
+
+ wol->supported = WAKE_MAGIC | WAKE_PHY;
+ wol->wolopts = pegasus->wolopts;
+}
+
+static int
+pegasus_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+ pegasus_t *pegasus = netdev_priv(dev);
+ u8 reg78 = 0x04;
+
+ if (wol->wolopts & ~WOL_SUPPORTED)
+ return -EINVAL;
+
+ if (wol->wolopts & WAKE_MAGIC)
+ reg78 |= 0x80;
+ if (wol->wolopts & WAKE_PHY)
+ reg78 |= 0x40;
+ if (wol->wolopts)
+ pegasus->eth_regs[0] |= 0x10;
+ else
+ pegasus->eth_regs[0] &= ~0x10;
+ pegasus->wolopts = wol->wolopts;
+ return set_register(pegasus, WakeupControl, reg78);
+}
+
+static inline void
+pegasus_reset_wol(struct net_device *dev)
+{
+ struct ethtool_wolinfo wol;
+
+ memset(&wol, 0, sizeof wol);
+ (void) pegasus_set_wol(dev, &wol);
+}
+
+static int
+pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
pegasus_t *pegasus = netdev_priv(dev);
mii_ethtool_gset(&pegasus->mii, ecmd);
return 0;
}
-static int pegasus_set_settings(struct net_device *dev, struct ethtool_cmd
*ecmd)
+static int
+pegasus_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
pegasus_t *pegasus = netdev_priv(dev);
return mii_ethtool_sset(&pegasus->mii, ecmd);
@@ -975,19 +1034,14 @@
static u32 pegasus_get_msglevel(struct net_device *dev)
{
- /*
- * pegasus_t *pegasus = netdev_priv(dev);
- * return pegasus->msg_enable; FIXME
- */
- return 0;
+ pegasus_t *pegasus = netdev_priv(dev);
+ return pegasus->msg_level;
}
static void pegasus_set_msglevel(struct net_device *dev, u32 v)
{
- /*
- * pegasus_t *pegasus = netdev_priv(dev);
- * pegasus->msg_enable = edata.data; FIXME
- */
+ pegasus_t *pegasus = netdev_priv(dev);
+ pegasus->msg_level = v;
}
static struct ethtool_ops ops = {
@@ -998,58 +1052,10 @@
.get_link = pegasus_get_link,
.get_msglevel = pegasus_get_msglevel,
.set_msglevel = pegasus_set_msglevel,
+ .get_wol = pegasus_get_wol,
+ .set_wol = pegasus_set_wol,
};
-#else
-
-static int pegasus_get_settings(struct net_device *dev, struct ethtool_cmd
*ecmd)
-{
- pegasus_t *pegasus = netdev_priv(dev);
- short lpa, bmcr;
- u8 port;
-
- ecmd->supported = (SUPPORTED_10baseT_Half |
- SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half |
- SUPPORTED_100baseT_Full |
- SUPPORTED_Autoneg |
- SUPPORTED_TP | SUPPORTED_MII);
- get_registers(pegasus, Reg7b, 1, &port);
- if (port == 0)
- ecmd->port = PORT_MII;
- else
- ecmd->port = PORT_TP;
- ecmd->transceiver = XCVR_INTERNAL;
- ecmd->phy_address = pegasus->phy;
- read_mii_word(pegasus, pegasus->phy, MII_BMCR, &bmcr);
- read_mii_word(pegasus, pegasus->phy, MII_LPA, &lpa);
- if (bmcr & BMCR_ANENABLE) {
- ecmd->autoneg = AUTONEG_ENABLE;
- ecmd->speed = lpa & (LPA_100HALF | LPA_100FULL) ?
- SPEED_100 : SPEED_10;
- if (ecmd->speed == SPEED_100)
- ecmd->duplex = lpa & LPA_100FULL ?
- DUPLEX_FULL : DUPLEX_HALF;
- else
- ecmd->duplex = lpa & LPA_10FULL ?
- DUPLEX_FULL : DUPLEX_HALF;
- } else {
- ecmd->autoneg = AUTONEG_DISABLE;
- ecmd->speed = bmcr & BMCR_SPEED100 ?
- SPEED_100 : SPEED_10;
- ecmd->duplex = bmcr & BMCR_FULLDPLX ?
- DUPLEX_FULL : DUPLEX_HALF;
- }
- return 0;
-}
-
-static struct ethtool_ops ops = {
- .get_drvinfo = pegasus_get_drvinfo,
- .get_settings = pegasus_get_settings,
- .get_link = ethtool_op_get_link,
-};
-#endif
-
static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
{
__u16 *data = (__u16 *) & rq->ifr_ifru;
@@ -1081,12 +1087,12 @@
if (net->flags & IFF_PROMISC) {
pegasus->eth_regs[EthCtrl2] |= RX_PROMISCUOUS;
- info("%s: Promiscuous mode enabled", net->name);
+ pr_info("%s: Promiscuous mode enabled.\n", net->name);
} else if ((net->mc_count > multicast_filter_limit) ||
(net->flags & IFF_ALLMULTI)) {
pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
- info("%s set allmulti", net->name);
+ pr_info("%s: set allmulti\n", net->name);
} else {
pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
@@ -1180,7 +1186,6 @@
net->hard_start_xmit = pegasus_start_xmit;
net->set_multicast_list = pegasus_set_multicast;
net->get_stats = pegasus_netdev_stats;
- net->mtu = PEGASUS_MTU;
SET_ETHTOOL_OPS(net, &ops);
pegasus->mii.dev = net;
pegasus->mii.mdio_read = mdio_read;
@@ -1192,27 +1197,28 @@
pegasus->features = usb_dev_id[dev_index].private;
get_interrupt_interval(pegasus);
if (reset_mac(pegasus)) {
- err("can't reset MAC");
+ dev_err(&intf->dev, "can't reset MAC\n");
res = -EIO;
goto out2;
}
set_ethernet_addr(pegasus);
fill_skb_pool(pegasus);
if (pegasus->features & PEGASUS_II) {
- info("setup Pegasus II specific registers");
+ dev_info(&intf->dev, "setup Pegasus II specific registers\n");
setup_pegasus_II(pegasus);
}
pegasus->phy = mii_phy_probe(pegasus);
if (pegasus->phy == 0xff) {
- warn("can't locate MII phy, using default");
+ dev_warn(&intf->dev, "can't locate MII phy, using default\n");
pegasus->phy = 1;
}
usb_set_intfdata(intf, pegasus);
SET_NETDEV_DEV(net, &intf->dev);
+ pegasus_reset_wol(net);
res = register_netdev(net);
if (res)
goto out3;
- printk("%s: %s\n", net->name, usb_dev_id[dev_index].name);
+ pr_info("%s: %s\n", net->name, usb_dev_id[dev_index].name);
return 0;
out3:
@@ -1247,16 +1253,34 @@
free_netdev(pegasus->net);
}
+static int pegasus_suspend (struct usb_interface *intf, u32 state)
+{
+ struct pegasus *pegasus = usb_get_intfdata(intf);
+
+ netif_device_detach (pegasus->net);
+ return 0;
+}
+
+static int pegasus_resume (struct usb_interface *intf)
+{
+ struct pegasus *pegasus = usb_get_intfdata(intf);
+
+ netif_device_attach (pegasus->net);
+ return 0;
+}
+
static struct usb_driver pegasus_driver = {
.name = driver_name,
.probe = pegasus_probe,
.disconnect = pegasus_disconnect,
.id_table = pegasus_ids,
+ .suspend = pegasus_suspend,
+ .resume = pegasus_resume,
};
static int __init pegasus_init(void)
{
- info(DRIVER_VERSION ":" DRIVER_DESC);
+ pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION);
return usb_register(&pegasus_driver);
}
diff -Nru a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
--- a/drivers/usb/net/pegasus.h 2005-01-13 13:04:59 +02:00
+++ b/drivers/usb/net/pegasus.h 2005-01-13 13:04:59 +02:00
@@ -76,6 +76,7 @@
EthTxStat0 = 0x2b,
EthTxStat1 = 0x2c,
EthRxStat = 0x2d,
+ WakeupControl = 0x78,
Reg7b = 0x7b,
Gpio0 = 0x7e,
Gpio1 = 0x7f,
@@ -90,6 +91,8 @@
struct mii_if_info mii;
unsigned flags;
unsigned features;
+ u32 msg_level;
+ u32 wolopts;
int dev_index;
int intr_interval;
struct tasklet_struct rx_tl;
===================================================================
This BitKeeper patch contains the following changesets:
1.4139
## Wrapped with gzip_uu ##
M'XL( -M5YD$ [U9:T_;R!K^'/^*$57;A(*Q$^<&!95+MIM3"BB!;8^Z532Q
M)XF%XXD\8P)[<O:WG^<=.R'F4K'=U4$0.YYY[\][&?.*72F1[)9F0E_SV'K%
M?I5*[Y:&(@Y$8L>I'XE4W2G;EU,L]J3$XLY$3L5.1K&C$G]GG(CQ]62[:C<L
M;[EMAIL PROTECTED]&Y&HW9)KUU9/]-U,[)9ZG8]7IX<]R]K?9\<3'H]%7VBVOV\-KS\$
[EMAIL PROTECTED];I3JS?<^J+:[EMAIL PROTECTED]@VJS/1HVVA:I
M\2$CA[I%\CH85)UFU:VU%^#BM:T3YMH>OC*GON.X.VZ-N;5=Q]MU&N^<ZJ[C
ML,S [EMAIL PROTECTED]'.F)_7^ECRV>_\224J6*C\%8HIB73$\'>SL28JU2]94$2
MPIM;+)::#Z,[VA;&8W;>/SEEPW0<[EMAIL PROTECTED] QG\=L*%BJ1,#FH9ZP
M81(&8_#F8Q[&K"P3-L*?GG#-IEQKXBXA- &/6"93'H&6CT7%Q@/\TL\F.TK'
[EMAIL PROTECTED],[EMAIL PROTECTED]"AC!GL#R) ZIZ2?K;9F8 1I!(;\V0(YIGX"9_-
M1&RLAL8JU)ILRR5<]8[6># 6<,[EMAIL PROTECTED]:[EMAIL PROTECTED]/
M,(X_/8>L4"LVGX3 I1_Q<$KL$C&3B68SGF!-CI8\BQH(+7Q-Y#8#2_A:P<'^
MY#YN,LXMF\OD&LO(%1U.A=HK\)G*.-0R(5OU))'I>,(^=[ML&HXGFAQ!G(9"
M:=!'*?G5?FA/7\L9B^28J1F?3HF1;=L,<B/[EMAIL PROTECTED])?[DW &7828%K2
MRF-DGR_CD<$*'\I49U[6<CR.!(&.S608:PK)G"<Q!!589"2"[EMAIL PROTECTED]
M8(L#)OJMRATF@@*2>IFGR<@<;AU"7PSJSY=71= )@B<3>J*EC)A*9T3Z"%U]
M?I,Y#9XFY,(+-P+;P7%X1ZA+X"9?%&B.N I]]N7\=,EU7>YA$+"K_A&6%/ 9
ME"L,N 9$5#H5^([EMAIL PROTECTED]@MHP+999DX&2O!'[EMAIL PROTECTED]@4F3$G-"@=)AX*
DLD&*)
MS\-(R:WU2"VU5P:G" M2!KY;0FLJET]C@@2/*.7U721V&=N 0F>[*_.UN-4;
[EMAIL PROTECTED]<@?M!O &A$GL 2#0-R$OF! ,LIGJ.#L5;[EMAIL PROTECTED];8<C;:'=[OL
[EMAIL PROTECTED]<AZ+*&[EMAIL PROTECTED]'XUU8R37QB/18V0GF0,[EMAIL
PROTECTED]@CR7I#& 0>8
M".L^-$+"QQ!^?'[V2_?C@)Y"#Q[-^9U:QNX3H3,<[V6LTAG021Z!.ZC%4,51
MFO)H[TF=+U#$)?O,8QG)&[EMAIL PROTECTED]<-R=K^BS^6Y7#'.GBB
M(63^5SNI&N[D)=WV[YN#Y[3=QL)U:TUW46W6/+_E^UY;.*U1T/I1"RKPA;>+
MO*G=U5R76L_":3BMVHM5FQ15:^)KW:TM6O6F&[EMAIL PROTECTED]:/5*O5
MZHX9!9ZUYNG1X&\X]>&8\$,_>F!7=5M(7'<!K9LU,S:TF\6AH;9;?]'0X+H>
MVV[_<W/#6NDB]"L>(]&C,[EMAIL PROTECTED](ZF4?,7F$="#$G+/M
M9&Y^ >^+YR/T$[G2K3FL:KV".F)4.ND<77VT?K=.O!9SK:[Y?(6%$(WTI-?]
MK=,;X*_?/3]C&S>.7;?=*BL3D+((5#:LDZ9;)]*FV\:E1&UDG^7Z;[EMAIL PROTECTED]
M5-MF"RZ>52KM;&9U]R+?U66S1 :[EMAIL PROTECTED]:9N" *TA*PE9OU-F69;
M\!TYSVS<P><L&00"PUEYX[7:1>_4R]&$O0Y^CU&9H154XU.T6 Q0VP?9:H4T
MK5696X>J7@/HLDKAB)7-%N[KE$>#2,1C=)N#?=:HL/] 5MI"[EMAIL PROTECTED]
M#$B#;$[:@V>-N<,[+9B#=&+Z=I!)<[>HYK/J4:8S"0J^.=_9&U:^_#JX.COI
M]'I79XO.U^-.OX] #([/3[$//XO3PTOS=?&OPZ,C1.BR^[ES?G59R30JK9Q/
[EMAIL PROTECTED];H^4U26N"*H;W8])1.)+/TI<+VK$%>ZC0,TPQMU!K?9;OTL#G
MZ.=A',CY&CGBU61N=>GNX%O]NWW:/?LTZ%\>7E[UD9=HZ]2M"'8\X#--/3-#
M%LFTS\X'QX>]7K?38]>A?VW&;!ECWC?#Q8B'-$Y<?LU)"'\8]]?F2+/-#)'\
MSLS2?(0!TEY!<LVX>U'&/& Q' WR<7> UEG&D\I>"6LB4N*)+7&V8QU;BM6V
M/8)7<CN(<(B<7>L<7IV=ZB]Y5A3=B)W34*E5%-B[?5:&CC72T;EMCBKL_7O6
MJB"JP3?O.^5&O6JR&)>JR3)DUG7Y4Z=W-@"$F$DV''[>:C.I#:<AS:UP=)+.
M-*7'5IY^)JAK*;B6??56)H$N!0%?#GMGW;./F1!]RVBJQ^Q;S&9BT:Z[T*[;
MAI*>9\$]''->[EMAIL PROTECTED],,(JZ!)XKXA"?!G*8_."[EMAIL PROTECTED]'_
MZN+BO'[EMAIL PROTECTED]'W[L'B_,[<[EMAIL PROTECTED];NZ &F^\%<1F6,
[EMAIL PROTECTED]<V<26[S?-\NJ:M83R2;!,W%0N9O.2C2YOY+<H,N(!X -_<E'&3
MP0 4"&O6C 05HWLM$;ZEGGOY1GS(F5;K93I_M&?]]]X6.']EBOK_F$+5M 38
M-EM8=FX=#X^R&EQ0_ W[LQ 5RJ-$Z#2)V7:G>_;;X:GQRA-T]W[):[EMAIL PROTECTED]
MG+WG"4R,"]N]I[97UI,,KAB 0%'.&Q*72/*,[EMAIL PROTECTED])&;
M2W%9GAS*.=46^\*O13H[EFA\,C)UH-FJ/(AM1!V^ %<D[0^C; +Y3*!Q-:&:
MBBF8E-_,2:X#7(1_""09P0#K99)780]!91#T)MOS#/XHE;"=7D^HEX+0GP9L
M4^"S0E7!%!:Z5)_#]]_B#V!@:FBW3&E<H9W]&.UY$%?1GJKQP!R=J8ZUFIB5
MNNVV\U<X/F:%?3?HCZ[C&$9V7I3NDW]9IE"6;?5H42T73\"[EMAIL PROTECTED](V?F
M5S-N$0BR:>[EMAIL PROTECTED],AVB>]N-2#0;MG%'[,2,[EMAIL PROTECTED](HFJ:1#I^@
M=5L8_^G:-M-G?BV5R"-H.>4W".]H^\ $;F/5E>@=Q^$QV!D>5<<TM/R:T1H%
M"[EMAIL PROTECTED]:N9\,-1Z*_.[.J>83-GV%PQI/<V3VD321^':3,SS"9W&$05
MS1%H.AP69PS!R'5-)WR4HMD$ (G9\)U?BQY\K1X-NVHX,$8&WS); W'[W<Y]
M"B8>XM!8RX][&&[EMAIL PROTECTED]>TC3NE!UH$[9F>B%>[EMAIL PROTECTED],8&.J&C
M+]--Q=2/;-+)[EMAIL PROTECTED]"W8FIM2=/4?*/N3&O[^0$/,$2_0
M$(ZM>R;YEF[<?^A82KY<Z_T'9E#J5>M9HF37AU$&I)9GM9-._YAMF+!G1\9!
M%OCB40XJ_NC8/WGYL?^%+RQ>>NPW[#RG [EMAIL PROTECTED];='/OKM9\[]M?^
MR?\5%,[EMAIL PROTECTED]"D_KD9T[J33,'%]JY&8R:K2VT!M-KD'28IM<Z1_YD-2JL
:[EMAIL PROTECTED]>JPO7:=>M_[O-W.8 :
