aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco_pci.c
diff options
context:
space:
mode:
authorPavel Roskin <proski@gnu.org>2006-04-07 04:10:57 -0400
committerJohn W. Linville <linville@tuxdriver.com>2006-04-24 16:15:52 -0400
commitb884c872fa1917614b42a39020ffcca7fa9302b1 (patch)
tree82f5ba67f6b38c96804fb449e018d83fbdce65a1 /drivers/net/wireless/orinoco_pci.c
parentc6fb2e9abef894efc4870e4c1e3aa4365b830a11 (diff)
[PATCH] orinoco: reduce differences between PCI drivers, create orinoco_pci.h
Make all Orinoco PCI drivers (orinoco_pci, orinoco_plx, orinoco_tmd and orinoco_nortel) as similar as possible. Use the best implementation of error handling, the best error messages, the best comments. Put common code to orinoco_pci.h. For now, it's suspend and resume functions and function for registering the network device. Signed-off-by: Pavel Roskin <proski@gnu.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/orinoco_pci.c')
-rw-r--r--drivers/net/wireless/orinoco_pci.c144
1 files changed, 24 insertions, 120 deletions
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
index 75df90ff1dc9..41efac22ba6a 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco_pci.c
@@ -100,6 +100,7 @@
100#include <linux/pci.h> 100#include <linux/pci.h>
101 101
102#include "orinoco.h" 102#include "orinoco.h"
103#include "orinoco_pci.h"
103 104
104/* All the magic there is from wlan-ng */ 105/* All the magic there is from wlan-ng */
105/* Magic offset of the reset register of the PCI card */ 106/* Magic offset of the reset register of the PCI card */
@@ -113,11 +114,6 @@
113#define HERMES_PCI_COR_OFFT (500) /* ms */ 114#define HERMES_PCI_COR_OFFT (500) /* ms */
114#define HERMES_PCI_COR_BUSYT (500) /* ms */ 115#define HERMES_PCI_COR_BUSYT (500) /* ms */
115 116
116/* Orinoco PCI specific data */
117struct orinoco_pci_card {
118 void __iomem *pci_ioaddr;
119};
120
121/* 117/*
122 * Do a soft reset of the PCI card using the Configuration Option Register 118 * Do a soft reset of the PCI card using the Configuration Option Register
123 * We need this to get going... 119 * We need this to get going...
@@ -131,12 +127,11 @@ struct orinoco_pci_card {
131 * Note bis : Don't try to access HERMES_CMD during the reset phase. 127 * Note bis : Don't try to access HERMES_CMD during the reset phase.
132 * It just won't work ! 128 * It just won't work !
133 */ 129 */
134static int 130static int orinoco_pci_cor_reset(struct orinoco_private *priv)
135orinoco_pci_cor_reset(struct orinoco_private *priv)
136{ 131{
137 hermes_t *hw = &priv->hw; 132 hermes_t *hw = &priv->hw;
138 unsigned long timeout; 133 unsigned long timeout;
139 u16 reg; 134 u16 reg;
140 135
141 /* Assert the reset until the card notice */ 136 /* Assert the reset until the card notice */
142 hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK); 137 hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK);
@@ -163,17 +158,14 @@ orinoco_pci_cor_reset(struct orinoco_private *priv)
163 return 0; 158 return 0;
164} 159}
165 160
166/*
167 * Initialise a card. Mostly similar to PLX code.
168 */
169static int orinoco_pci_init_one(struct pci_dev *pdev, 161static int orinoco_pci_init_one(struct pci_dev *pdev,
170 const struct pci_device_id *ent) 162 const struct pci_device_id *ent)
171{ 163{
172 int err = 0; 164 int err;
173 void __iomem *pci_ioaddr = NULL; 165 struct orinoco_private *priv;
174 struct orinoco_private *priv = NULL;
175 struct orinoco_pci_card *card; 166 struct orinoco_pci_card *card;
176 struct net_device *dev = NULL; 167 struct net_device *dev;
168 void __iomem *hermes_io;
177 169
178 err = pci_enable_device(pdev); 170 err = pci_enable_device(pdev);
179 if (err) { 171 if (err) {
@@ -182,38 +174,32 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
182 } 174 }
183 175
184 err = pci_request_regions(pdev, DRIVER_NAME); 176 err = pci_request_regions(pdev, DRIVER_NAME);
185 if (err != 0) { 177 if (err) {
186 printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); 178 printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
187 goto fail_resources; 179 goto fail_resources;
188 } 180 }
189 181
190 /* Resource 0 is mapped to the hermes registers */ 182 hermes_io = pci_iomap(pdev, 0, 0);
191 pci_ioaddr = pci_iomap(pdev, 0, 0); 183 if (!hermes_io) {
192 if (!pci_ioaddr) { 184 printk(KERN_ERR PFX "Cannot remap chipset registers\n");
193 err = -EIO; 185 err = -EIO;
194 printk(KERN_ERR PFX "Cannot remap hardware registers\n"); 186 goto fail_map_hermes;
195 goto fail_map;
196 } 187 }
197 188
198 /* Allocate network device */ 189 /* Allocate network device */
199 dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset); 190 dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset);
200 if (! dev) { 191 if (!dev) {
192 printk(KERN_ERR PFX "Cannot allocate network device\n");
201 err = -ENOMEM; 193 err = -ENOMEM;
202 goto fail_alloc; 194 goto fail_alloc;
203 } 195 }
204 196
205 priv = netdev_priv(dev); 197 priv = netdev_priv(dev);
206 card = priv->card; 198 card = priv->card;
207 card->pci_ioaddr = pci_ioaddr;
208 dev->mem_start = pci_resource_start(pdev, 0);
209 dev->mem_end = dev->mem_start + pci_resource_len(pdev, 0) - 1;
210 SET_MODULE_OWNER(dev); 199 SET_MODULE_OWNER(dev);
211 SET_NETDEV_DEV(dev, &pdev->dev); 200 SET_NETDEV_DEV(dev, &pdev->dev);
212 201
213 hermes_struct_init(&priv->hw, pci_ioaddr, HERMES_32BIT_REGSPACING); 202 hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING);
214
215 printk(KERN_DEBUG PFX "Detected device %s, mem:0x%lx-0x%lx, irq %d\n",
216 pci_name(pdev), dev->mem_start, dev->mem_end, pdev->irq);
217 203
218 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ, 204 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
219 dev->name, dev); 205 dev->name, dev);
@@ -222,9 +208,8 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
222 err = -EBUSY; 208 err = -EBUSY;
223 goto fail_irq; 209 goto fail_irq;
224 } 210 }
225 dev->irq = pdev->irq; 211 orinoco_pci_setup_netdev(dev, pdev, 0);
226 212
227 /* Perform a COR reset to start the card */
228 err = orinoco_pci_cor_reset(priv); 213 err = orinoco_pci_cor_reset(priv);
229 if (err) { 214 if (err) {
230 printk(KERN_ERR PFX "Initial reset failed\n"); 215 printk(KERN_ERR PFX "Initial reset failed\n");
@@ -233,7 +218,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
233 218
234 err = register_netdev(dev); 219 err = register_netdev(dev);
235 if (err) { 220 if (err) {
236 printk(KERN_ERR PFX "Failed to register net device\n"); 221 printk(KERN_ERR PFX "Cannot register network device\n");
237 goto fail; 222 goto fail;
238 } 223 }
239 224
@@ -249,9 +234,9 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
249 free_orinocodev(dev); 234 free_orinocodev(dev);
250 235
251 fail_alloc: 236 fail_alloc:
252 iounmap(pci_ioaddr); 237 pci_iounmap(pdev, hermes_io);
253 238
254 fail_map: 239 fail_map_hermes:
255 pci_release_regions(pdev); 240 pci_release_regions(pdev);
256 241
257 fail_resources: 242 fail_resources:
@@ -264,98 +249,17 @@ static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
264{ 249{
265 struct net_device *dev = pci_get_drvdata(pdev); 250 struct net_device *dev = pci_get_drvdata(pdev);
266 struct orinoco_private *priv = netdev_priv(dev); 251 struct orinoco_private *priv = netdev_priv(dev);
267 struct orinoco_pci_card *card = priv->card;
268 252
269 unregister_netdev(dev); 253 unregister_netdev(dev);
270 free_irq(dev->irq, dev); 254 free_irq(dev->irq, dev);
271 pci_set_drvdata(pdev, NULL); 255 pci_set_drvdata(pdev, NULL);
272 free_orinocodev(dev); 256 free_orinocodev(dev);
273 iounmap(card->pci_ioaddr); 257 pci_iounmap(pdev, priv->hw.iobase);
274 pci_release_regions(pdev); 258 pci_release_regions(pdev);
275 pci_disable_device(pdev); 259 pci_disable_device(pdev);
276} 260}
277 261
278static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) 262static struct pci_device_id orinoco_pci_id_table[] = {
279{
280 struct net_device *dev = pci_get_drvdata(pdev);
281 struct orinoco_private *priv = netdev_priv(dev);
282 unsigned long flags;
283 int err;
284
285
286 err = orinoco_lock(priv, &flags);
287 if (err) {
288 printk(KERN_ERR "%s: hw_unavailable on orinoco_pci_suspend\n",
289 dev->name);
290 return err;
291 }
292
293 err = __orinoco_down(dev);
294 if (err)
295 printk(KERN_WARNING "%s: orinoco_pci_suspend(): Error %d downing interface\n",
296 dev->name, err);
297
298 netif_device_detach(dev);
299
300 priv->hw_unavailable++;
301
302 orinoco_unlock(priv, &flags);
303
304 free_irq(pdev->irq, dev);
305 pci_save_state(pdev);
306 pci_disable_device(pdev);
307 pci_set_power_state(pdev, PCI_D3hot);
308
309 return 0;
310}
311
312static int orinoco_pci_resume(struct pci_dev *pdev)
313{
314 struct net_device *dev = pci_get_drvdata(pdev);
315 struct orinoco_private *priv = netdev_priv(dev);
316 unsigned long flags;
317 int err;
318
319 printk(KERN_DEBUG "%s: Orinoco-PCI waking up\n", dev->name);
320
321 pci_set_power_state(pdev, 0);
322 pci_enable_device(pdev);
323 pci_restore_state(pdev);
324
325 err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
326 dev->name, dev);
327 if (err) {
328 printk(KERN_ERR "%s: Cannot re-allocate IRQ\n", dev->name);
329 pci_disable_device(pdev);
330 return -EBUSY;
331 }
332
333 err = orinoco_reinit_firmware(dev);
334 if (err) {
335 printk(KERN_ERR "%s: Error %d re-initializing firmware on orinoco_pci_resume()\n",
336 dev->name, err);
337 return err;
338 }
339
340 spin_lock_irqsave(&priv->lock, flags);
341
342 netif_device_attach(dev);
343
344 priv->hw_unavailable--;
345
346 if (priv->open && (! priv->hw_unavailable)) {
347 err = __orinoco_up(dev);
348 if (err)
349 printk(KERN_ERR "%s: Error %d restarting card on orinoco_pci_resume()\n",
350 dev->name, err);
351 }
352
353 spin_unlock_irqrestore(&priv->lock, flags);
354
355 return 0;
356}
357
358static struct pci_device_id orinoco_pci_pci_id_table[] = {
359 /* Intersil Prism 3 */ 263 /* Intersil Prism 3 */
360 {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,}, 264 {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
361 /* Intersil Prism 2.5 */ 265 /* Intersil Prism 2.5 */
@@ -365,11 +269,11 @@ static struct pci_device_id orinoco_pci_pci_id_table[] = {
365 {0,}, 269 {0,},
366}; 270};
367 271
368MODULE_DEVICE_TABLE(pci, orinoco_pci_pci_id_table); 272MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table);
369 273
370static struct pci_driver orinoco_pci_driver = { 274static struct pci_driver orinoco_pci_driver = {
371 .name = DRIVER_NAME, 275 .name = DRIVER_NAME,
372 .id_table = orinoco_pci_pci_id_table, 276 .id_table = orinoco_pci_id_table,
373 .probe = orinoco_pci_init_one, 277 .probe = orinoco_pci_init_one,
374 .remove = __devexit_p(orinoco_pci_remove_one), 278 .remove = __devexit_p(orinoco_pci_remove_one),
375 .suspend = orinoco_pci_suspend, 279 .suspend = orinoco_pci_suspend,