Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.29 417 lines 9.4 kB view raw
1/* 2 Copyright (C) 2004 - 2008 rt2x00 SourceForge Project 3 <http://rt2x00.serialmonkey.com> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the 17 Free Software Foundation, Inc., 18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 */ 20 21/* 22 Module: rt2x00pci 23 Abstract: rt2x00 generic pci device routines. 24 */ 25 26#include <linux/dma-mapping.h> 27#include <linux/kernel.h> 28#include <linux/module.h> 29#include <linux/pci.h> 30 31#include "rt2x00.h" 32#include "rt2x00pci.h" 33 34/* 35 * Register access. 36 */ 37int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, 38 const unsigned int offset, 39 const struct rt2x00_field32 field, 40 u32 *reg) 41{ 42 unsigned int i; 43 44 for (i = 0; i < REGISTER_BUSY_COUNT; i++) { 45 rt2x00pci_register_read(rt2x00dev, offset, reg); 46 if (!rt2x00_get_field32(*reg, field)) 47 return 1; 48 udelay(REGISTER_BUSY_DELAY); 49 } 50 51 ERROR(rt2x00dev, "Indirect register access failed: " 52 "offset=0x%.08x, value=0x%.08x\n", offset, *reg); 53 *reg = ~0; 54 55 return 0; 56} 57EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); 58 59/* 60 * TX data handlers. 61 */ 62int rt2x00pci_write_tx_data(struct queue_entry *entry) 63{ 64 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; 65 struct queue_entry_priv_pci *entry_priv = entry->priv_data; 66 struct skb_frame_desc *skbdesc; 67 68 /* 69 * This should not happen, we already checked the entry 70 * was ours. When the hardware disagrees there has been 71 * a queue corruption! 72 */ 73 if (unlikely(rt2x00dev->ops->lib->get_entry_state(entry))) { 74 ERROR(rt2x00dev, 75 "Corrupt queue %d, accessing entry which is not ours.\n" 76 "Please file bug report to %s.\n", 77 entry->queue->qid, DRV_PROJECT); 78 return -EINVAL; 79 } 80 81 /* 82 * Fill in skb descriptor 83 */ 84 skbdesc = get_skb_frame_desc(entry->skb); 85 skbdesc->desc = entry_priv->desc; 86 skbdesc->desc_len = entry->queue->desc_size; 87 88 return 0; 89} 90EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); 91 92/* 93 * TX/RX data handlers. 94 */ 95void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) 96{ 97 struct data_queue *queue = rt2x00dev->rx; 98 struct queue_entry *entry; 99 struct queue_entry_priv_pci *entry_priv; 100 struct skb_frame_desc *skbdesc; 101 102 while (1) { 103 entry = rt2x00queue_get_entry(queue, Q_INDEX); 104 entry_priv = entry->priv_data; 105 106 if (rt2x00dev->ops->lib->get_entry_state(entry)) 107 break; 108 109 /* 110 * Fill in desc fields of the skb descriptor 111 */ 112 skbdesc = get_skb_frame_desc(entry->skb); 113 skbdesc->desc = entry_priv->desc; 114 skbdesc->desc_len = entry->queue->desc_size; 115 116 /* 117 * Send the frame to rt2x00lib for further processing. 118 */ 119 rt2x00lib_rxdone(rt2x00dev, entry); 120 } 121} 122EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); 123 124/* 125 * Device initialization handlers. 126 */ 127static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, 128 struct data_queue *queue) 129{ 130 struct queue_entry_priv_pci *entry_priv; 131 void *addr; 132 dma_addr_t dma; 133 unsigned int i; 134 135 /* 136 * Allocate DMA memory for descriptor and buffer. 137 */ 138 addr = dma_alloc_coherent(rt2x00dev->dev, 139 queue->limit * queue->desc_size, 140 &dma, GFP_KERNEL | GFP_DMA); 141 if (!addr) 142 return -ENOMEM; 143 144 memset(addr, 0, queue->limit * queue->desc_size); 145 146 /* 147 * Initialize all queue entries to contain valid addresses. 148 */ 149 for (i = 0; i < queue->limit; i++) { 150 entry_priv = queue->entries[i].priv_data; 151 entry_priv->desc = addr + i * queue->desc_size; 152 entry_priv->desc_dma = dma + i * queue->desc_size; 153 } 154 155 return 0; 156} 157 158static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, 159 struct data_queue *queue) 160{ 161 struct queue_entry_priv_pci *entry_priv = 162 queue->entries[0].priv_data; 163 164 if (entry_priv->desc) 165 dma_free_coherent(rt2x00dev->dev, 166 queue->limit * queue->desc_size, 167 entry_priv->desc, entry_priv->desc_dma); 168 entry_priv->desc = NULL; 169} 170 171int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) 172{ 173 struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev); 174 struct data_queue *queue; 175 int status; 176 177 /* 178 * Allocate DMA 179 */ 180 queue_for_each(rt2x00dev, queue) { 181 status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue); 182 if (status) 183 goto exit; 184 } 185 186 /* 187 * Register interrupt handler. 188 */ 189 status = request_irq(pci_dev->irq, rt2x00dev->ops->lib->irq_handler, 190 IRQF_SHARED, pci_name(pci_dev), rt2x00dev); 191 if (status) { 192 ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", 193 pci_dev->irq, status); 194 goto exit; 195 } 196 197 return 0; 198 199exit: 200 queue_for_each(rt2x00dev, queue) 201 rt2x00pci_free_queue_dma(rt2x00dev, queue); 202 203 return status; 204} 205EXPORT_SYMBOL_GPL(rt2x00pci_initialize); 206 207void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) 208{ 209 struct data_queue *queue; 210 211 /* 212 * Free irq line. 213 */ 214 free_irq(to_pci_dev(rt2x00dev->dev)->irq, rt2x00dev); 215 216 /* 217 * Free DMA 218 */ 219 queue_for_each(rt2x00dev, queue) 220 rt2x00pci_free_queue_dma(rt2x00dev, queue); 221} 222EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize); 223 224/* 225 * PCI driver handlers. 226 */ 227static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev) 228{ 229 kfree(rt2x00dev->rf); 230 rt2x00dev->rf = NULL; 231 232 kfree(rt2x00dev->eeprom); 233 rt2x00dev->eeprom = NULL; 234 235 if (rt2x00dev->csr.base) { 236 iounmap(rt2x00dev->csr.base); 237 rt2x00dev->csr.base = NULL; 238 } 239} 240 241static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev) 242{ 243 struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev); 244 245 rt2x00dev->csr.base = pci_ioremap_bar(pci_dev, 0); 246 if (!rt2x00dev->csr.base) 247 goto exit; 248 249 rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL); 250 if (!rt2x00dev->eeprom) 251 goto exit; 252 253 rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL); 254 if (!rt2x00dev->rf) 255 goto exit; 256 257 return 0; 258 259exit: 260 ERROR_PROBE("Failed to allocate registers.\n"); 261 262 rt2x00pci_free_reg(rt2x00dev); 263 264 return -ENOMEM; 265} 266 267int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) 268{ 269 struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data; 270 struct ieee80211_hw *hw; 271 struct rt2x00_dev *rt2x00dev; 272 int retval; 273 274 retval = pci_request_regions(pci_dev, pci_name(pci_dev)); 275 if (retval) { 276 ERROR_PROBE("PCI request regions failed.\n"); 277 return retval; 278 } 279 280 retval = pci_enable_device(pci_dev); 281 if (retval) { 282 ERROR_PROBE("Enable device failed.\n"); 283 goto exit_release_regions; 284 } 285 286 pci_set_master(pci_dev); 287 288 if (pci_set_mwi(pci_dev)) 289 ERROR_PROBE("MWI not available.\n"); 290 291 if (dma_set_mask(&pci_dev->dev, DMA_32BIT_MASK)) { 292 ERROR_PROBE("PCI DMA not supported.\n"); 293 retval = -EIO; 294 goto exit_disable_device; 295 } 296 297 hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw); 298 if (!hw) { 299 ERROR_PROBE("Failed to allocate hardware.\n"); 300 retval = -ENOMEM; 301 goto exit_disable_device; 302 } 303 304 pci_set_drvdata(pci_dev, hw); 305 306 rt2x00dev = hw->priv; 307 rt2x00dev->dev = &pci_dev->dev; 308 rt2x00dev->ops = ops; 309 rt2x00dev->hw = hw; 310 311 retval = rt2x00pci_alloc_reg(rt2x00dev); 312 if (retval) 313 goto exit_free_device; 314 315 retval = rt2x00lib_probe_dev(rt2x00dev); 316 if (retval) 317 goto exit_free_reg; 318 319 return 0; 320 321exit_free_reg: 322 rt2x00pci_free_reg(rt2x00dev); 323 324exit_free_device: 325 ieee80211_free_hw(hw); 326 327exit_disable_device: 328 if (retval != -EBUSY) 329 pci_disable_device(pci_dev); 330 331exit_release_regions: 332 pci_release_regions(pci_dev); 333 334 pci_set_drvdata(pci_dev, NULL); 335 336 return retval; 337} 338EXPORT_SYMBOL_GPL(rt2x00pci_probe); 339 340void rt2x00pci_remove(struct pci_dev *pci_dev) 341{ 342 struct ieee80211_hw *hw = pci_get_drvdata(pci_dev); 343 struct rt2x00_dev *rt2x00dev = hw->priv; 344 345 /* 346 * Free all allocated data. 347 */ 348 rt2x00lib_remove_dev(rt2x00dev); 349 rt2x00pci_free_reg(rt2x00dev); 350 ieee80211_free_hw(hw); 351 352 /* 353 * Free the PCI device data. 354 */ 355 pci_set_drvdata(pci_dev, NULL); 356 pci_disable_device(pci_dev); 357 pci_release_regions(pci_dev); 358} 359EXPORT_SYMBOL_GPL(rt2x00pci_remove); 360 361#ifdef CONFIG_PM 362int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state) 363{ 364 struct ieee80211_hw *hw = pci_get_drvdata(pci_dev); 365 struct rt2x00_dev *rt2x00dev = hw->priv; 366 int retval; 367 368 retval = rt2x00lib_suspend(rt2x00dev, state); 369 if (retval) 370 return retval; 371 372 rt2x00pci_free_reg(rt2x00dev); 373 374 pci_save_state(pci_dev); 375 pci_disable_device(pci_dev); 376 return pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); 377} 378EXPORT_SYMBOL_GPL(rt2x00pci_suspend); 379 380int rt2x00pci_resume(struct pci_dev *pci_dev) 381{ 382 struct ieee80211_hw *hw = pci_get_drvdata(pci_dev); 383 struct rt2x00_dev *rt2x00dev = hw->priv; 384 int retval; 385 386 if (pci_set_power_state(pci_dev, PCI_D0) || 387 pci_enable_device(pci_dev) || 388 pci_restore_state(pci_dev)) { 389 ERROR(rt2x00dev, "Failed to resume device.\n"); 390 return -EIO; 391 } 392 393 retval = rt2x00pci_alloc_reg(rt2x00dev); 394 if (retval) 395 return retval; 396 397 retval = rt2x00lib_resume(rt2x00dev); 398 if (retval) 399 goto exit_free_reg; 400 401 return 0; 402 403exit_free_reg: 404 rt2x00pci_free_reg(rt2x00dev); 405 406 return retval; 407} 408EXPORT_SYMBOL_GPL(rt2x00pci_resume); 409#endif /* CONFIG_PM */ 410 411/* 412 * rt2x00pci module information. 413 */ 414MODULE_AUTHOR(DRV_PROJECT); 415MODULE_VERSION(DRV_VERSION); 416MODULE_DESCRIPTION("rt2x00 pci library"); 417MODULE_LICENSE("GPL");