~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/char/agp/alpha-agp.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <linux/module.h>
 
2
#include <linux/pci.h>
 
3
#include <linux/init.h>
 
4
#include <linux/agp_backend.h>
 
5
#include <linux/mm.h>
 
6
#include <linux/slab.h>
 
7
 
 
8
#include <asm/machvec.h>
 
9
#include <asm/agp_backend.h>
 
10
#include "../../../arch/alpha/kernel/pci_impl.h"
 
11
 
 
12
#include "agp.h"
 
13
 
 
14
static int alpha_core_agp_vm_fault(struct vm_area_struct *vma,
 
15
                                        struct vm_fault *vmf)
 
16
{
 
17
        alpha_agp_info *agp = agp_bridge->dev_private_data;
 
18
        dma_addr_t dma_addr;
 
19
        unsigned long pa;
 
20
        struct page *page;
 
21
 
 
22
        dma_addr = (unsigned long)vmf->virtual_address - vma->vm_start
 
23
                                                + agp->aperture.bus_base;
 
24
        pa = agp->ops->translate(agp, dma_addr);
 
25
 
 
26
        if (pa == (unsigned long)-EINVAL)
 
27
                return VM_FAULT_SIGBUS; /* no translation */
 
28
 
 
29
        /*
 
30
         * Get the page, inc the use count, and return it
 
31
         */
 
32
        page = virt_to_page(__va(pa));
 
33
        get_page(page);
 
34
        vmf->page = page;
 
35
        return 0;
 
36
}
 
37
 
 
38
static struct aper_size_info_fixed alpha_core_agp_sizes[] =
 
39
{
 
40
        { 0, 0, 0 }, /* filled in by alpha_core_agp_setup */
 
41
};
 
42
 
 
43
static const struct vm_operations_struct alpha_core_agp_vm_ops = {
 
44
        .fault = alpha_core_agp_vm_fault,
 
45
};
 
46
 
 
47
 
 
48
static int alpha_core_agp_fetch_size(void)
 
49
{
 
50
        return alpha_core_agp_sizes[0].size;
 
51
}
 
52
 
 
53
static int alpha_core_agp_configure(void)
 
54
{
 
55
        alpha_agp_info *agp = agp_bridge->dev_private_data;
 
56
        agp_bridge->gart_bus_addr = agp->aperture.bus_base;
 
57
        return 0;
 
58
}
 
59
 
 
60
static void alpha_core_agp_cleanup(void)
 
61
{
 
62
        alpha_agp_info *agp = agp_bridge->dev_private_data;
 
63
 
 
64
        agp->ops->cleanup(agp);
 
65
}
 
66
 
 
67
static void alpha_core_agp_tlbflush(struct agp_memory *mem)
 
68
{
 
69
        alpha_agp_info *agp = agp_bridge->dev_private_data;
 
70
        alpha_mv.mv_pci_tbi(agp->hose, 0, -1);
 
71
}
 
72
 
 
73
static void alpha_core_agp_enable(struct agp_bridge_data *bridge, u32 mode)
 
74
{
 
75
        alpha_agp_info *agp = bridge->dev_private_data;
 
76
 
 
77
        agp->mode.lw = agp_collect_device_status(bridge, mode,
 
78
                                        agp->capability.lw);
 
79
 
 
80
        agp->mode.bits.enable = 1;
 
81
        agp->ops->configure(agp);
 
82
 
 
83
        agp_device_command(agp->mode.lw, false);
 
84
}
 
85
 
 
86
static int alpha_core_agp_insert_memory(struct agp_memory *mem, off_t pg_start,
 
87
                                        int type)
 
88
{
 
89
        alpha_agp_info *agp = agp_bridge->dev_private_data;
 
90
        int num_entries, status;
 
91
        void *temp;
 
92
 
 
93
        if (type >= AGP_USER_TYPES || mem->type >= AGP_USER_TYPES)
 
94
                return -EINVAL;
 
95
 
 
96
        temp = agp_bridge->current_size;
 
97
        num_entries = A_SIZE_FIX(temp)->num_entries;
 
98
        if ((pg_start + mem->page_count) > num_entries)
 
99
                return -EINVAL;
 
100
 
 
101
        status = agp->ops->bind(agp, pg_start, mem);
 
102
        mb();
 
103
        alpha_core_agp_tlbflush(mem);
 
104
 
 
105
        return status;
 
106
}
 
107
 
 
108
static int alpha_core_agp_remove_memory(struct agp_memory *mem, off_t pg_start,
 
109
                                        int type)
 
110
{
 
111
        alpha_agp_info *agp = agp_bridge->dev_private_data;
 
112
        int status;
 
113
 
 
114
        status = agp->ops->unbind(agp, pg_start, mem);
 
115
        alpha_core_agp_tlbflush(mem);
 
116
        return status;
 
117
}
 
118
 
 
119
static int alpha_core_agp_create_free_gatt_table(struct agp_bridge_data *a)
 
120
{
 
121
        return 0;
 
122
}
 
123
 
 
124
struct agp_bridge_driver alpha_core_agp_driver = {
 
125
        .owner                  = THIS_MODULE,
 
126
        .aperture_sizes         = alpha_core_agp_sizes,
 
127
        .num_aperture_sizes     = 1,
 
128
        .size_type              = FIXED_APER_SIZE,
 
129
        .cant_use_aperture      = true,
 
130
        .masks                  = NULL,
 
131
 
 
132
        .fetch_size             = alpha_core_agp_fetch_size,
 
133
        .configure              = alpha_core_agp_configure,
 
134
        .agp_enable             = alpha_core_agp_enable,
 
135
        .cleanup                = alpha_core_agp_cleanup,
 
136
        .tlb_flush              = alpha_core_agp_tlbflush,
 
137
        .mask_memory            = agp_generic_mask_memory,
 
138
        .cache_flush            = global_cache_flush,
 
139
        .create_gatt_table      = alpha_core_agp_create_free_gatt_table,
 
140
        .free_gatt_table        = alpha_core_agp_create_free_gatt_table,
 
141
        .insert_memory          = alpha_core_agp_insert_memory,
 
142
        .remove_memory          = alpha_core_agp_remove_memory,
 
143
        .alloc_by_type          = agp_generic_alloc_by_type,
 
144
        .free_by_type           = agp_generic_free_by_type,
 
145
        .agp_alloc_page         = agp_generic_alloc_page,
 
146
        .agp_alloc_pages        = agp_generic_alloc_pages,
 
147
        .agp_destroy_page       = agp_generic_destroy_page,
 
148
        .agp_destroy_pages      = agp_generic_destroy_pages,
 
149
        .agp_type_to_mask_type  = agp_generic_type_to_mask_type,
 
150
};
 
151
 
 
152
struct agp_bridge_data *alpha_bridge;
 
153
 
 
154
int __init
 
155
alpha_core_agp_setup(void)
 
156
{
 
157
        alpha_agp_info *agp = alpha_mv.agp_info();
 
158
        struct pci_dev *pdev;   /* faked */
 
159
        struct aper_size_info_fixed *aper_size;
 
160
 
 
161
        if (!agp)
 
162
                return -ENODEV;
 
163
        if (agp->ops->setup(agp))
 
164
                return -ENODEV;
 
165
 
 
166
        /*
 
167
         * Build the aperture size descriptor
 
168
         */
 
169
        aper_size = alpha_core_agp_sizes;
 
170
        aper_size->size = agp->aperture.size / (1024 * 1024);
 
171
        aper_size->num_entries = agp->aperture.size / PAGE_SIZE;
 
172
        aper_size->page_order = __ffs(aper_size->num_entries / 1024);
 
173
 
 
174
        /*
 
175
         * Build a fake pci_dev struct
 
176
         */
 
177
        pdev = alloc_pci_dev();
 
178
        if (!pdev)
 
179
                return -ENOMEM;
 
180
        pdev->vendor = 0xffff;
 
181
        pdev->device = 0xffff;
 
182
        pdev->sysdata = agp->hose;
 
183
 
 
184
        alpha_bridge = agp_alloc_bridge();
 
185
        if (!alpha_bridge)
 
186
                goto fail;
 
187
 
 
188
        alpha_bridge->driver = &alpha_core_agp_driver;
 
189
        alpha_bridge->vm_ops = &alpha_core_agp_vm_ops;
 
190
        alpha_bridge->current_size = aper_size; /* only 1 size */
 
191
        alpha_bridge->dev_private_data = agp;
 
192
        alpha_bridge->dev = pdev;
 
193
        alpha_bridge->mode = agp->capability.lw;
 
194
 
 
195
        printk(KERN_INFO PFX "Detected AGP on hose %d\n", agp->hose->index);
 
196
        return agp_add_bridge(alpha_bridge);
 
197
 
 
198
 fail:
 
199
        kfree(pdev);
 
200
        return -ENOMEM;
 
201
}
 
202
 
 
203
static int __init agp_alpha_core_init(void)
 
204
{
 
205
        if (agp_off)
 
206
                return -EINVAL;
 
207
        if (alpha_mv.agp_info)
 
208
                return alpha_core_agp_setup();
 
209
        return -ENODEV;
 
210
}
 
211
 
 
212
static void __exit agp_alpha_core_cleanup(void)
 
213
{
 
214
        agp_remove_bridge(alpha_bridge);
 
215
        agp_put_bridge(alpha_bridge);
 
216
}
 
217
 
 
218
module_init(agp_alpha_core_init);
 
219
module_exit(agp_alpha_core_cleanup);
 
220
 
 
221
MODULE_AUTHOR("Jeff Wiedemeier <Jeff.Wiedemeier@hp.com>");
 
222
MODULE_LICENSE("GPL and additional rights");