Annotation of /trunk/kernel26-tinyalx/patches-2.6.21-r14/0302-2.6.21-natsemi-wyse-hack.patch
Parent Directory | Revision Log
Revision 453 -
(hide annotations)
(download)
Fri Jan 25 23:34:48 2008 UTC (16 years, 8 months ago) by niro
File size: 5811 byte(s)
Fri Jan 25 23:34:48 2008 UTC (16 years, 8 months ago) by niro
File size: 5811 byte(s)
-tiny-alx 2.6.21-tinyalx-r14
1 | niro | 453 | Date Wed, 2 May 2007 22:41:29 +0100 |
2 | From Mark Brown <> | ||
3 | Subject Re: Natsemi DP83815 driver spaming | ||
4 | |||
5 | |||
6 | On Wed, May 02, 2007 at 10:05:31PM +0200, Rafal Bilski wrote: | ||
7 | |||
8 | > What about module option? | ||
9 | |||
10 | That would work, though you crossed in the post with me writing a patch | ||
11 | adding a sysfs file; I merged the two for overkill (below). I also have | ||
12 | a patch which changes the log message for the workaround so that it is | ||
13 | displayed by default in order to make this easier to diagnose. | ||
14 | |||
15 | diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c | ||
16 | index 109e802..b9f3ab3 100644 | ||
17 | --- a/drivers/net/natsemi.c | ||
18 | +++ b/drivers/net/natsemi.c | ||
19 | @@ -81,6 +81,8 @@ static const int multicast_filter_limit = 100; | ||
20 | Setting to > 1518 effectively disables this feature. */ | ||
21 | static int rx_copybreak; | ||
22 | |||
23 | +static int dspcfg_workaround = 1; | ||
24 | + | ||
25 | /* Used to pass the media type, etc. | ||
26 | Both 'options[]' and 'full_duplex[]' should exist for driver | ||
27 | interoperability. | ||
28 | @@ -139,12 +141,14 @@ MODULE_LICENSE("GPL"); | ||
29 | module_param(mtu, int, 0); | ||
30 | module_param(debug, int, 0); | ||
31 | module_param(rx_copybreak, int, 0); | ||
32 | +module_param(dspcfg_workaround, int, 1); | ||
33 | module_param_array(options, int, NULL, 0); | ||
34 | module_param_array(full_duplex, int, NULL, 0); | ||
35 | MODULE_PARM_DESC(mtu, "DP8381x MTU (all boards)"); | ||
36 | MODULE_PARM_DESC(debug, "DP8381x default debug level"); | ||
37 | MODULE_PARM_DESC(rx_copybreak, | ||
38 | "DP8381x copy breakpoint for copy-only-tiny-frames"); | ||
39 | +MODULE_PARM_DESC(dspcfg_workaround, "DP8381x: control DspCfg workaround"); | ||
40 | MODULE_PARM_DESC(options, | ||
41 | "DP8381x: Bits 0-3: media type, bit 17: full duplex"); | ||
42 | MODULE_PARM_DESC(full_duplex, "DP8381x full duplex setting(s) (1)"); | ||
43 | @@ -590,6 +594,7 @@ struct netdev_private { | ||
44 | u32 srr; | ||
45 | /* expected DSPCFG value */ | ||
46 | u16 dspcfg; | ||
47 | + int dspcfg_workaround; | ||
48 | /* parms saved in ethtool format */ | ||
49 | u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */ | ||
50 | u8 duplex; /* Duplex, half or full */ | ||
51 | @@ -656,6 +661,56 @@ static int netdev_get_regs(struct net_device *dev, u8 *buf); | ||
52 | static int netdev_get_eeprom(struct net_device *dev, u8 *buf); | ||
53 | static const struct ethtool_ops ethtool_ops; | ||
54 | |||
55 | +#define NATSEMI_ATTR(_name) \ | ||
56 | +static ssize_t natsemi_show_##_name(struct device *dev, \ | ||
57 | + struct device_attribute *attr, char *buf); \ | ||
58 | + static ssize_t natsemi_set_##_name(struct device *dev, \ | ||
59 | + struct device_attribute *attr, \ | ||
60 | + const char *buf, size_t count); \ | ||
61 | + static DEVICE_ATTR(_name, 0644, natsemi_show_##_name, natsemi_set_##_name) | ||
62 | + | ||
63 | +#define NATSEMI_CREATE_FILE(_dev, _name) \ | ||
64 | + device_create_file(&_dev->dev, &dev_attr_##_name) | ||
65 | +#define NATSEMI_REMOVE_FILE(_dev, _name) \ | ||
66 | + device_create_file(&_dev->dev, &dev_attr_##_name) | ||
67 | + | ||
68 | +NATSEMI_ATTR(dspcfg_workaround); | ||
69 | + | ||
70 | +static ssize_t natsemi_show_dspcfg_workaround(struct device *dev, | ||
71 | + struct device_attribute *attr, | ||
72 | + char *buf) | ||
73 | +{ | ||
74 | + struct netdev_private *np = netdev_priv(to_net_dev(dev)); | ||
75 | + | ||
76 | + return sprintf(buf, "%s\n", np->dspcfg_workaround ? "on" : "off"); | ||
77 | +} | ||
78 | + | ||
79 | +static ssize_t natsemi_set_dspcfg_workaround(struct device *dev, | ||
80 | + struct device_attribute *attr, | ||
81 | + const char *buf, size_t count) | ||
82 | +{ | ||
83 | + struct netdev_private *np = netdev_priv(to_net_dev(dev)); | ||
84 | + int new_setting; | ||
85 | + u32 flags; | ||
86 | + | ||
87 | + /* Find out the new setting */ | ||
88 | + if (!strncmp("on", buf, count - 1) || !strncmp("1", buf, count - 1)) | ||
89 | + new_setting = 1; | ||
90 | + else if (!strncmp("off", buf, count - 1) | ||
91 | + || !strncmp("0", buf, count - 1)) | ||
92 | + new_setting = 0; | ||
93 | + else | ||
94 | + return count; | ||
95 | + | ||
96 | + spin_lock_irqsave(&np->lock, flags); | ||
97 | + | ||
98 | + np->dspcfg_workaround = new_setting; | ||
99 | + | ||
100 | + spin_unlock_irqrestore(&np->lock, flags); | ||
101 | + | ||
102 | + return count; | ||
103 | +} | ||
104 | + | ||
105 | static inline void __iomem *ns_ioaddr(struct net_device *dev) | ||
106 | { | ||
107 | return (void __iomem *) dev->base_addr; | ||
108 | @@ -820,6 +875,7 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, | ||
109 | np->ignore_phy = 1; | ||
110 | else | ||
111 | np->ignore_phy = 0; | ||
112 | + np->dspcfg_workaround = dspcfg_workaround; | ||
113 | |||
114 | /* Initial port: | ||
115 | * - If configured to ignore the PHY set up for external. | ||
116 | @@ -899,6 +955,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, | ||
117 | if (i) | ||
118 | goto err_register_netdev; | ||
119 | |||
120 | + if (!NATSEMI_CREATE_FILE(pdev, dspcfg_workaround)) | ||
121 | + goto err_create_file; | ||
122 | + | ||
123 | if (netif_msg_drv(np)) { | ||
124 | printk(KERN_INFO "natsemi %s: %s at %#08lx (%s), ", | ||
125 | dev->name, natsemi_pci_info[chip_idx].name, iostart, | ||
126 | @@ -915,6 +974,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev, | ||
127 | } | ||
128 | return 0; | ||
129 | |||
130 | + err_create_file: | ||
131 | + unregister_netdev(dev); | ||
132 | + | ||
133 | err_register_netdev: | ||
134 | iounmap(ioaddr); | ||
135 | |||
136 | @@ -1727,7 +1789,8 @@ static void init_registers(struct net_device *dev) | ||
137 | * It seems that a reference set for this chip went out with incorrect info, | ||
138 | * and there exist boards that aren't quite right. An unexpected voltage | ||
139 | * drop can cause the PHY to get itself in a weird state (basically reset). | ||
140 | - * NOTE: this only seems to affect revC chips. | ||
141 | + * NOTE: this only seems to affect revC chips. The user can disable | ||
142 | + * this check via dspcfg_workaround sysfs option. | ||
143 | * 3) check of death of the RX path due to OOM | ||
144 | */ | ||
145 | static void netdev_timer(unsigned long data) | ||
146 | @@ -1753,7 +1816,7 @@ static void netdev_timer(unsigned long data) | ||
147 | writew(1, ioaddr+PGSEL); | ||
148 | dspcfg = readw(ioaddr+DSPCFG); | ||
149 | writew(0, ioaddr+PGSEL); | ||
150 | - if (dspcfg != np->dspcfg) { | ||
151 | + if (np->dspcfg_workaround && dspcfg != np->dspcfg) { | ||
152 | if (!netif_queue_stopped(dev)) { | ||
153 | spin_unlock_irq(&np->lock); | ||
154 | if (netif_msg_hw(np)) | ||
155 | @@ -3157,6 +3220,7 @@ static void __devexit natsemi_remove1 (struct pci_dev *pdev) | ||
156 | struct net_device *dev = pci_get_drvdata(pdev); | ||
157 | void __iomem * ioaddr = ns_ioaddr(dev); | ||
158 | |||
159 | + NATSEMI_REMOVE_FILE(pdev, dspcfg_workaround); | ||
160 | unregister_netdev (dev); | ||
161 | pci_release_regions (pdev); | ||
162 | iounmap(ioaddr); |