diff options
Diffstat (limited to 'drivers/char')
40 files changed, 574 insertions, 380 deletions
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 8b3317fd46c9..1d59e2a5b9aa 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h | |||
@@ -225,6 +225,10 @@ struct agp_bridge_data { | |||
225 | #define I810_GMS_DISABLE 0x00000000 | 225 | #define I810_GMS_DISABLE 0x00000000 |
226 | #define I810_PGETBL_CTL 0x2020 | 226 | #define I810_PGETBL_CTL 0x2020 |
227 | #define I810_PGETBL_ENABLED 0x00000001 | 227 | #define I810_PGETBL_ENABLED 0x00000001 |
228 | #define I965_PGETBL_SIZE_MASK 0x0000000e | ||
229 | #define I965_PGETBL_SIZE_512KB (0 << 1) | ||
230 | #define I965_PGETBL_SIZE_256KB (1 << 1) | ||
231 | #define I965_PGETBL_SIZE_128KB (2 << 1) | ||
228 | #define I810_DRAM_CTL 0x3000 | 232 | #define I810_DRAM_CTL 0x3000 |
229 | #define I810_DRAM_ROW_0 0x00000001 | 233 | #define I810_DRAM_ROW_0 0x00000001 |
230 | #define I810_DRAM_ROW_0_SDRAM 0x00000001 | 234 | #define I810_DRAM_ROW_0_SDRAM 0x00000001 |
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 51d0d562d01e..c85c8cadb6df 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c | |||
@@ -101,6 +101,11 @@ static int amd_create_gatt_pages(int nr_tables) | |||
101 | for (i = 0; i < nr_tables; i++) { | 101 | for (i = 0; i < nr_tables; i++) { |
102 | entry = kzalloc(sizeof(struct amd_page_map), GFP_KERNEL); | 102 | entry = kzalloc(sizeof(struct amd_page_map), GFP_KERNEL); |
103 | if (entry == NULL) { | 103 | if (entry == NULL) { |
104 | while (i > 0) { | ||
105 | kfree(tables[i-1]); | ||
106 | i--; | ||
107 | } | ||
108 | kfree(tables); | ||
104 | retval = -ENOMEM; | 109 | retval = -ENOMEM; |
105 | break; | 110 | break; |
106 | } | 111 | } |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 2f2c4efff8a3..93d2209fee4c 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -650,6 +650,15 @@ static struct pci_device_id agp_amd64_pci_table[] = { | |||
650 | .subvendor = PCI_ANY_ID, | 650 | .subvendor = PCI_ANY_ID, |
651 | .subdevice = PCI_ANY_ID, | 651 | .subdevice = PCI_ANY_ID, |
652 | }, | 652 | }, |
653 | /* VIA K8M890 / K8N890 */ | ||
654 | { | ||
655 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | ||
656 | .class_mask = ~0, | ||
657 | .vendor = PCI_VENDOR_ID_VIA, | ||
658 | .device = PCI_DEVICE_ID_VIA_VT3336, | ||
659 | .subvendor = PCI_ANY_ID, | ||
660 | .subdevice = PCI_ANY_ID, | ||
661 | }, | ||
653 | /* VIA K8T890 */ | 662 | /* VIA K8T890 */ |
654 | { | 663 | { |
655 | .class = (PCI_CLASS_BRIDGE_HOST << 8), | 664 | .class = (PCI_CLASS_BRIDGE_HOST << 8), |
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index f244c6682738..9987dc2e0c3f 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c | |||
@@ -41,18 +41,18 @@ static struct gatt_mask ati_generic_masks[] = | |||
41 | }; | 41 | }; |
42 | 42 | ||
43 | 43 | ||
44 | typedef struct _ati_page_map { | 44 | struct ati_page_map { |
45 | unsigned long *real; | 45 | unsigned long *real; |
46 | unsigned long __iomem *remapped; | 46 | unsigned long __iomem *remapped; |
47 | } ati_page_map; | 47 | }; |
48 | 48 | ||
49 | static struct _ati_generic_private { | 49 | static struct _ati_generic_private { |
50 | volatile u8 __iomem *registers; | 50 | volatile u8 __iomem *registers; |
51 | ati_page_map **gatt_pages; | 51 | struct ati_page_map **gatt_pages; |
52 | int num_tables; | 52 | int num_tables; |
53 | } ati_generic_private; | 53 | } ati_generic_private; |
54 | 54 | ||
55 | static int ati_create_page_map(ati_page_map *page_map) | 55 | static int ati_create_page_map(struct ati_page_map *page_map) |
56 | { | 56 | { |
57 | int i, err = 0; | 57 | int i, err = 0; |
58 | 58 | ||
@@ -82,7 +82,7 @@ static int ati_create_page_map(ati_page_map *page_map) | |||
82 | } | 82 | } |
83 | 83 | ||
84 | 84 | ||
85 | static void ati_free_page_map(ati_page_map *page_map) | 85 | static void ati_free_page_map(struct ati_page_map *page_map) |
86 | { | 86 | { |
87 | unmap_page_from_agp(virt_to_page(page_map->real)); | 87 | unmap_page_from_agp(virt_to_page(page_map->real)); |
88 | iounmap(page_map->remapped); | 88 | iounmap(page_map->remapped); |
@@ -94,8 +94,8 @@ static void ati_free_page_map(ati_page_map *page_map) | |||
94 | static void ati_free_gatt_pages(void) | 94 | static void ati_free_gatt_pages(void) |
95 | { | 95 | { |
96 | int i; | 96 | int i; |
97 | ati_page_map **tables; | 97 | struct ati_page_map **tables; |
98 | ati_page_map *entry; | 98 | struct ati_page_map *entry; |
99 | 99 | ||
100 | tables = ati_generic_private.gatt_pages; | 100 | tables = ati_generic_private.gatt_pages; |
101 | for (i = 0; i < ati_generic_private.num_tables; i++) { | 101 | for (i = 0; i < ati_generic_private.num_tables; i++) { |
@@ -112,30 +112,30 @@ static void ati_free_gatt_pages(void) | |||
112 | 112 | ||
113 | static int ati_create_gatt_pages(int nr_tables) | 113 | static int ati_create_gatt_pages(int nr_tables) |
114 | { | 114 | { |
115 | ati_page_map **tables; | 115 | struct ati_page_map **tables; |
116 | ati_page_map *entry; | 116 | struct ati_page_map *entry; |
117 | int retval = 0; | 117 | int retval = 0; |
118 | int i; | 118 | int i; |
119 | 119 | ||
120 | tables = kzalloc((nr_tables + 1) * sizeof(ati_page_map *),GFP_KERNEL); | 120 | tables = kzalloc((nr_tables + 1) * sizeof(struct ati_page_map *),GFP_KERNEL); |
121 | if (tables == NULL) | 121 | if (tables == NULL) |
122 | return -ENOMEM; | 122 | return -ENOMEM; |
123 | 123 | ||
124 | for (i = 0; i < nr_tables; i++) { | 124 | for (i = 0; i < nr_tables; i++) { |
125 | entry = kzalloc(sizeof(ati_page_map), GFP_KERNEL); | 125 | entry = kzalloc(sizeof(struct ati_page_map), GFP_KERNEL); |
126 | if (entry == NULL) { | 126 | if (entry == NULL) { |
127 | while (i>0) { | 127 | while (i > 0) { |
128 | kfree (tables[i-1]); | 128 | kfree(tables[i-1]); |
129 | i--; | 129 | i--; |
130 | } | 130 | } |
131 | kfree (tables); | 131 | kfree(tables); |
132 | tables = NULL; | ||
133 | retval = -ENOMEM; | 132 | retval = -ENOMEM; |
134 | break; | 133 | break; |
135 | } | 134 | } |
136 | tables[i] = entry; | 135 | tables[i] = entry; |
137 | retval = ati_create_page_map(entry); | 136 | retval = ati_create_page_map(entry); |
138 | if (retval != 0) break; | 137 | if (retval != 0) |
138 | break; | ||
139 | } | 139 | } |
140 | ati_generic_private.num_tables = nr_tables; | 140 | ati_generic_private.num_tables = nr_tables; |
141 | ati_generic_private.gatt_pages = tables; | 141 | ati_generic_private.gatt_pages = tables; |
@@ -340,7 +340,7 @@ static int ati_remove_memory(struct agp_memory * mem, off_t pg_start, | |||
340 | static int ati_create_gatt_table(struct agp_bridge_data *bridge) | 340 | static int ati_create_gatt_table(struct agp_bridge_data *bridge) |
341 | { | 341 | { |
342 | struct aper_size_info_lvl2 *value; | 342 | struct aper_size_info_lvl2 *value; |
343 | ati_page_map page_dir; | 343 | struct ati_page_map page_dir; |
344 | unsigned long addr; | 344 | unsigned long addr; |
345 | int retval; | 345 | int retval; |
346 | u32 temp; | 346 | u32 temp; |
@@ -400,7 +400,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge) | |||
400 | 400 | ||
401 | static int ati_free_gatt_table(struct agp_bridge_data *bridge) | 401 | static int ati_free_gatt_table(struct agp_bridge_data *bridge) |
402 | { | 402 | { |
403 | ati_page_map page_dir; | 403 | struct ati_page_map page_dir; |
404 | 404 | ||
405 | page_dir.real = (unsigned long *)agp_bridge->gatt_table_real; | 405 | page_dir.real = (unsigned long *)agp_bridge->gatt_table_real; |
406 | page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table; | 406 | page_dir.remapped = (unsigned long __iomem *)agp_bridge->gatt_table; |
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 883a36a27833..3491d6f84bc6 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
@@ -965,6 +965,9 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) | |||
965 | if (!bridge) | 965 | if (!bridge) |
966 | return -EINVAL; | 966 | return -EINVAL; |
967 | 967 | ||
968 | if (mem->page_count == 0) | ||
969 | return 0; | ||
970 | |||
968 | temp = bridge->current_size; | 971 | temp = bridge->current_size; |
969 | 972 | ||
970 | switch (bridge->driver->size_type) { | 973 | switch (bridge->driver->size_type) { |
@@ -1016,8 +1019,8 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) | |||
1016 | 1019 | ||
1017 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | 1020 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { |
1018 | writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j); | 1021 | writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j); |
1019 | readl(bridge->gatt_table+j); /* PCI Posting. */ | ||
1020 | } | 1022 | } |
1023 | readl(bridge->gatt_table+j-1); /* PCI Posting. */ | ||
1021 | 1024 | ||
1022 | bridge->driver->tlb_flush(mem); | 1025 | bridge->driver->tlb_flush(mem); |
1023 | return 0; | 1026 | return 0; |
@@ -1034,6 +1037,9 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) | |||
1034 | if (!bridge) | 1037 | if (!bridge) |
1035 | return -EINVAL; | 1038 | return -EINVAL; |
1036 | 1039 | ||
1040 | if (mem->page_count == 0) | ||
1041 | return 0; | ||
1042 | |||
1037 | if (type != 0 || mem->type != 0) { | 1043 | if (type != 0 || mem->type != 0) { |
1038 | /* The generic routines know nothing of memory types */ | 1044 | /* The generic routines know nothing of memory types */ |
1039 | return -EINVAL; | 1045 | return -EINVAL; |
@@ -1042,10 +1048,9 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type) | |||
1042 | /* AK: bogus, should encode addresses > 4GB */ | 1048 | /* AK: bogus, should encode addresses > 4GB */ |
1043 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | 1049 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { |
1044 | writel(bridge->scratch_page, bridge->gatt_table+i); | 1050 | writel(bridge->scratch_page, bridge->gatt_table+i); |
1045 | readl(bridge->gatt_table+i); /* PCI Posting. */ | ||
1046 | } | 1051 | } |
1052 | readl(bridge->gatt_table+i-1); /* PCI Posting. */ | ||
1047 | 1053 | ||
1048 | global_cache_flush(); | ||
1049 | bridge->driver->tlb_flush(mem); | 1054 | bridge->driver->tlb_flush(mem); |
1050 | return 0; | 1055 | return 0; |
1051 | } | 1056 | } |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 555b3a8ab49c..a3011de51f7c 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
@@ -207,6 +207,9 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, | |||
207 | int i, j, num_entries; | 207 | int i, j, num_entries; |
208 | void *temp; | 208 | void *temp; |
209 | 209 | ||
210 | if (mem->page_count == 0) | ||
211 | return 0; | ||
212 | |||
210 | temp = agp_bridge->current_size; | 213 | temp = agp_bridge->current_size; |
211 | num_entries = A_SIZE_FIX(temp)->num_entries; | 214 | num_entries = A_SIZE_FIX(temp)->num_entries; |
212 | 215 | ||
@@ -221,12 +224,16 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, | |||
221 | if (type != 0 || mem->type != 0) { | 224 | if (type != 0 || mem->type != 0) { |
222 | if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) { | 225 | if ((type == AGP_DCACHE_MEMORY) && (mem->type == AGP_DCACHE_MEMORY)) { |
223 | /* special insert */ | 226 | /* special insert */ |
224 | global_cache_flush(); | 227 | if (!mem->is_flushed) { |
228 | global_cache_flush(); | ||
229 | mem->is_flushed = TRUE; | ||
230 | } | ||
231 | |||
225 | for (i = pg_start; i < (pg_start + mem->page_count); i++) { | 232 | for (i = pg_start; i < (pg_start + mem->page_count); i++) { |
226 | writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4)); | 233 | writel((i*4096)|I810_PTE_LOCAL|I810_PTE_VALID, intel_i810_private.registers+I810_PTE_BASE+(i*4)); |
227 | readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ | ||
228 | } | 234 | } |
229 | global_cache_flush(); | 235 | readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); /* PCI Posting. */ |
236 | |||
230 | agp_bridge->driver->tlb_flush(mem); | 237 | agp_bridge->driver->tlb_flush(mem); |
231 | return 0; | 238 | return 0; |
232 | } | 239 | } |
@@ -236,14 +243,17 @@ static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start, | |||
236 | } | 243 | } |
237 | 244 | ||
238 | insert: | 245 | insert: |
239 | global_cache_flush(); | 246 | if (!mem->is_flushed) { |
247 | global_cache_flush(); | ||
248 | mem->is_flushed = TRUE; | ||
249 | } | ||
250 | |||
240 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | 251 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { |
241 | writel(agp_bridge->driver->mask_memory(agp_bridge, | 252 | writel(agp_bridge->driver->mask_memory(agp_bridge, |
242 | mem->memory[i], mem->type), | 253 | mem->memory[i], mem->type), |
243 | intel_i810_private.registers+I810_PTE_BASE+(j*4)); | 254 | intel_i810_private.registers+I810_PTE_BASE+(j*4)); |
244 | readl(intel_i810_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */ | ||
245 | } | 255 | } |
246 | global_cache_flush(); | 256 | readl(intel_i810_private.registers+I810_PTE_BASE+((j-1)*4)); /* PCI Posting. */ |
247 | 257 | ||
248 | agp_bridge->driver->tlb_flush(mem); | 258 | agp_bridge->driver->tlb_flush(mem); |
249 | return 0; | 259 | return 0; |
@@ -254,12 +264,14 @@ static int intel_i810_remove_entries(struct agp_memory *mem, off_t pg_start, | |||
254 | { | 264 | { |
255 | int i; | 265 | int i; |
256 | 266 | ||
267 | if (mem->page_count == 0) | ||
268 | return 0; | ||
269 | |||
257 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | 270 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { |
258 | writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4)); | 271 | writel(agp_bridge->scratch_page, intel_i810_private.registers+I810_PTE_BASE+(i*4)); |
259 | readl(intel_i810_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ | ||
260 | } | 272 | } |
273 | readl(intel_i810_private.registers+I810_PTE_BASE+((i-1)*4)); | ||
261 | 274 | ||
262 | global_cache_flush(); | ||
263 | agp_bridge->driver->tlb_flush(mem); | 275 | agp_bridge->driver->tlb_flush(mem); |
264 | return 0; | 276 | return 0; |
265 | } | 277 | } |
@@ -370,6 +382,11 @@ static struct _intel_i830_private { | |||
370 | struct pci_dev *i830_dev; /* device one */ | 382 | struct pci_dev *i830_dev; /* device one */ |
371 | volatile u8 __iomem *registers; | 383 | volatile u8 __iomem *registers; |
372 | volatile u32 __iomem *gtt; /* I915G */ | 384 | volatile u32 __iomem *gtt; /* I915G */ |
385 | /* gtt_entries is the number of gtt entries that are already mapped | ||
386 | * to stolen memory. Stolen memory is larger than the memory mapped | ||
387 | * through gtt_entries, as it includes some reserved space for the BIOS | ||
388 | * popup and for the GTT. | ||
389 | */ | ||
373 | int gtt_entries; | 390 | int gtt_entries; |
374 | } intel_i830_private; | 391 | } intel_i830_private; |
375 | 392 | ||
@@ -380,14 +397,41 @@ static void intel_i830_init_gtt_entries(void) | |||
380 | u8 rdct; | 397 | u8 rdct; |
381 | int local = 0; | 398 | int local = 0; |
382 | static const int ddt[4] = { 0, 16, 32, 64 }; | 399 | static const int ddt[4] = { 0, 16, 32, 64 }; |
383 | int size; | 400 | int size; /* reserved space (in kb) at the top of stolen memory */ |
384 | 401 | ||
385 | pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl); | 402 | pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl); |
386 | 403 | ||
387 | /* We obtain the size of the GTT, which is also stored (for some | 404 | if (IS_I965) { |
388 | * reason) at the top of stolen memory. Then we add 4KB to that | 405 | u32 pgetbl_ctl; |
389 | * for the video BIOS popup, which is also stored in there. */ | 406 | |
390 | size = agp_bridge->driver->fetch_size() + 4; | 407 | pci_read_config_dword(agp_bridge->dev, I810_PGETBL_CTL, |
408 | &pgetbl_ctl); | ||
409 | /* The 965 has a field telling us the size of the GTT, | ||
410 | * which may be larger than what is necessary to map the | ||
411 | * aperture. | ||
412 | */ | ||
413 | switch (pgetbl_ctl & I965_PGETBL_SIZE_MASK) { | ||
414 | case I965_PGETBL_SIZE_128KB: | ||
415 | size = 128; | ||
416 | break; | ||
417 | case I965_PGETBL_SIZE_256KB: | ||
418 | size = 256; | ||
419 | break; | ||
420 | case I965_PGETBL_SIZE_512KB: | ||
421 | size = 512; | ||
422 | break; | ||
423 | default: | ||
424 | printk(KERN_INFO PFX "Unknown page table size, " | ||
425 | "assuming 512KB\n"); | ||
426 | size = 512; | ||
427 | } | ||
428 | size += 4; /* add in BIOS popup space */ | ||
429 | } else { | ||
430 | /* On previous hardware, the GTT size was just what was | ||
431 | * required to map the aperture. | ||
432 | */ | ||
433 | size = agp_bridge->driver->fetch_size() + 4; | ||
434 | } | ||
391 | 435 | ||
392 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB || | 436 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB || |
393 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { | 437 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) { |
@@ -576,6 +620,9 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int | |||
576 | int i,j,num_entries; | 620 | int i,j,num_entries; |
577 | void *temp; | 621 | void *temp; |
578 | 622 | ||
623 | if (mem->page_count == 0) | ||
624 | return 0; | ||
625 | |||
579 | temp = agp_bridge->current_size; | 626 | temp = agp_bridge->current_size; |
580 | num_entries = A_SIZE_FIX(temp)->num_entries; | 627 | num_entries = A_SIZE_FIX(temp)->num_entries; |
581 | 628 | ||
@@ -598,16 +645,18 @@ static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start, int | |||
598 | (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) | 645 | (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) |
599 | return -EINVAL; | 646 | return -EINVAL; |
600 | 647 | ||
601 | global_cache_flush(); /* FIXME: Necessary ?*/ | 648 | if (!mem->is_flushed) { |
649 | global_cache_flush(); | ||
650 | mem->is_flushed = TRUE; | ||
651 | } | ||
602 | 652 | ||
603 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | 653 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { |
604 | writel(agp_bridge->driver->mask_memory(agp_bridge, | 654 | writel(agp_bridge->driver->mask_memory(agp_bridge, |
605 | mem->memory[i], mem->type), | 655 | mem->memory[i], mem->type), |
606 | intel_i830_private.registers+I810_PTE_BASE+(j*4)); | 656 | intel_i830_private.registers+I810_PTE_BASE+(j*4)); |
607 | readl(intel_i830_private.registers+I810_PTE_BASE+(j*4)); /* PCI Posting. */ | ||
608 | } | 657 | } |
658 | readl(intel_i830_private.registers+I810_PTE_BASE+((j-1)*4)); | ||
609 | 659 | ||
610 | global_cache_flush(); | ||
611 | agp_bridge->driver->tlb_flush(mem); | 660 | agp_bridge->driver->tlb_flush(mem); |
612 | return 0; | 661 | return 0; |
613 | } | 662 | } |
@@ -617,7 +666,8 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start, | |||
617 | { | 666 | { |
618 | int i; | 667 | int i; |
619 | 668 | ||
620 | global_cache_flush(); | 669 | if (mem->page_count == 0) |
670 | return 0; | ||
621 | 671 | ||
622 | if (pg_start < intel_i830_private.gtt_entries) { | 672 | if (pg_start < intel_i830_private.gtt_entries) { |
623 | printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); | 673 | printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); |
@@ -626,10 +676,9 @@ static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start, | |||
626 | 676 | ||
627 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | 677 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { |
628 | writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4)); | 678 | writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4)); |
629 | readl(intel_i830_private.registers+I810_PTE_BASE+(i*4)); /* PCI Posting. */ | ||
630 | } | 679 | } |
680 | readl(intel_i830_private.registers+I810_PTE_BASE+((i-1)*4)); | ||
631 | 681 | ||
632 | global_cache_flush(); | ||
633 | agp_bridge->driver->tlb_flush(mem); | 682 | agp_bridge->driver->tlb_flush(mem); |
634 | return 0; | 683 | return 0; |
635 | } | 684 | } |
@@ -686,6 +735,9 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, | |||
686 | int i,j,num_entries; | 735 | int i,j,num_entries; |
687 | void *temp; | 736 | void *temp; |
688 | 737 | ||
738 | if (mem->page_count == 0) | ||
739 | return 0; | ||
740 | |||
689 | temp = agp_bridge->current_size; | 741 | temp = agp_bridge->current_size; |
690 | num_entries = A_SIZE_FIX(temp)->num_entries; | 742 | num_entries = A_SIZE_FIX(temp)->num_entries; |
691 | 743 | ||
@@ -708,15 +760,17 @@ static int intel_i915_insert_entries(struct agp_memory *mem,off_t pg_start, | |||
708 | (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) | 760 | (mem->type != 0 && mem->type != AGP_PHYS_MEMORY)) |
709 | return -EINVAL; | 761 | return -EINVAL; |
710 | 762 | ||
711 | global_cache_flush(); | 763 | if (!mem->is_flushed) { |
764 | global_cache_flush(); | ||
765 | mem->is_flushed = TRUE; | ||
766 | } | ||
712 | 767 | ||
713 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | 768 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { |
714 | writel(agp_bridge->driver->mask_memory(agp_bridge, | 769 | writel(agp_bridge->driver->mask_memory(agp_bridge, |
715 | mem->memory[i], mem->type), intel_i830_private.gtt+j); | 770 | mem->memory[i], mem->type), intel_i830_private.gtt+j); |
716 | readl(intel_i830_private.gtt+j); /* PCI Posting. */ | ||
717 | } | 771 | } |
772 | readl(intel_i830_private.gtt+j-1); | ||
718 | 773 | ||
719 | global_cache_flush(); | ||
720 | agp_bridge->driver->tlb_flush(mem); | 774 | agp_bridge->driver->tlb_flush(mem); |
721 | return 0; | 775 | return 0; |
722 | } | 776 | } |
@@ -726,7 +780,8 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start, | |||
726 | { | 780 | { |
727 | int i; | 781 | int i; |
728 | 782 | ||
729 | global_cache_flush(); | 783 | if (mem->page_count == 0) |
784 | return 0; | ||
730 | 785 | ||
731 | if (pg_start < intel_i830_private.gtt_entries) { | 786 | if (pg_start < intel_i830_private.gtt_entries) { |
732 | printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); | 787 | printk (KERN_INFO PFX "Trying to disable local/stolen memory\n"); |
@@ -735,30 +790,34 @@ static int intel_i915_remove_entries(struct agp_memory *mem,off_t pg_start, | |||
735 | 790 | ||
736 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | 791 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { |
737 | writel(agp_bridge->scratch_page, intel_i830_private.gtt+i); | 792 | writel(agp_bridge->scratch_page, intel_i830_private.gtt+i); |
738 | readl(intel_i830_private.gtt+i); | ||
739 | } | 793 | } |
794 | readl(intel_i830_private.gtt+i-1); | ||
740 | 795 | ||
741 | global_cache_flush(); | ||
742 | agp_bridge->driver->tlb_flush(mem); | 796 | agp_bridge->driver->tlb_flush(mem); |
743 | return 0; | 797 | return 0; |
744 | } | 798 | } |
745 | 799 | ||
746 | static int intel_i915_fetch_size(void) | 800 | /* Return the aperture size by just checking the resource length. The effect |
801 | * described in the spec of the MSAC registers is just changing of the | ||
802 | * resource size. | ||
803 | */ | ||
804 | static int intel_i9xx_fetch_size(void) | ||
747 | { | 805 | { |
748 | struct aper_size_info_fixed *values; | 806 | int num_sizes = sizeof(intel_i830_sizes) / sizeof(*intel_i830_sizes); |
749 | u32 temp, offset; | 807 | int aper_size; /* size in megabytes */ |
808 | int i; | ||
750 | 809 | ||
751 | #define I915_256MB_ADDRESS_MASK (1<<27) | 810 | aper_size = pci_resource_len(intel_i830_private.i830_dev, 2) / MB(1); |
752 | 811 | ||
753 | values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); | 812 | for (i = 0; i < num_sizes; i++) { |
813 | if (aper_size == intel_i830_sizes[i].size) { | ||
814 | agp_bridge->current_size = intel_i830_sizes + i; | ||
815 | agp_bridge->previous_size = agp_bridge->current_size; | ||
816 | return aper_size; | ||
817 | } | ||
818 | } | ||
754 | 819 | ||
755 | pci_read_config_dword(intel_i830_private.i830_dev, I915_GMADDR, &temp); | 820 | return 0; |
756 | if (temp & I915_256MB_ADDRESS_MASK) | ||
757 | offset = 0; /* 128MB aperture */ | ||
758 | else | ||
759 | offset = 2; /* 256MB aperture */ | ||
760 | agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset); | ||
761 | return values[offset].size; | ||
762 | } | 821 | } |
763 | 822 | ||
764 | /* The intel i915 automatically initializes the agp aperture during POST. | 823 | /* The intel i915 automatically initializes the agp aperture during POST. |
@@ -821,40 +880,9 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, | |||
821 | return addr | bridge->driver->masks[type].mask; | 880 | return addr | bridge->driver->masks[type].mask; |
822 | } | 881 | } |
823 | 882 | ||
824 | static int intel_i965_fetch_size(void) | ||
825 | { | ||
826 | struct aper_size_info_fixed *values; | ||
827 | u32 offset = 0; | ||
828 | u8 temp; | ||
829 | |||
830 | #define I965_512MB_ADDRESS_MASK (3<<1) | ||
831 | |||
832 | values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); | ||
833 | |||
834 | pci_read_config_byte(intel_i830_private.i830_dev, I965_MSAC, &temp); | ||
835 | temp &= I965_512MB_ADDRESS_MASK; | ||
836 | switch (temp) { | ||
837 | case 0x00: | ||
838 | offset = 0; /* 128MB */ | ||
839 | break; | ||
840 | case 0x06: | ||
841 | offset = 3; /* 512MB */ | ||
842 | break; | ||
843 | default: | ||
844 | case 0x02: | ||
845 | offset = 2; /* 256MB */ | ||
846 | break; | ||
847 | } | ||
848 | |||
849 | agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset); | ||
850 | |||
851 | /* The i965 GTT is always sized as if it had a 512kB aperture size */ | ||
852 | return 512; | ||
853 | } | ||
854 | |||
855 | /* The intel i965 automatically initializes the agp aperture during POST. | 883 | /* The intel i965 automatically initializes the agp aperture during POST. |
856 | + * Use the memory already set aside for in the GTT. | 884 | * Use the memory already set aside for in the GTT. |
857 | + */ | 885 | */ |
858 | static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) | 886 | static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge) |
859 | { | 887 | { |
860 | int page_order; | 888 | int page_order; |
@@ -1574,7 +1602,7 @@ static struct agp_bridge_driver intel_915_driver = { | |||
1574 | .num_aperture_sizes = 4, | 1602 | .num_aperture_sizes = 4, |
1575 | .needs_scratch_page = TRUE, | 1603 | .needs_scratch_page = TRUE, |
1576 | .configure = intel_i915_configure, | 1604 | .configure = intel_i915_configure, |
1577 | .fetch_size = intel_i915_fetch_size, | 1605 | .fetch_size = intel_i9xx_fetch_size, |
1578 | .cleanup = intel_i915_cleanup, | 1606 | .cleanup = intel_i915_cleanup, |
1579 | .tlb_flush = intel_i810_tlbflush, | 1607 | .tlb_flush = intel_i810_tlbflush, |
1580 | .mask_memory = intel_i810_mask_memory, | 1608 | .mask_memory = intel_i810_mask_memory, |
@@ -1598,7 +1626,7 @@ static struct agp_bridge_driver intel_i965_driver = { | |||
1598 | .num_aperture_sizes = 4, | 1626 | .num_aperture_sizes = 4, |
1599 | .needs_scratch_page = TRUE, | 1627 | .needs_scratch_page = TRUE, |
1600 | .configure = intel_i915_configure, | 1628 | .configure = intel_i915_configure, |
1601 | .fetch_size = intel_i965_fetch_size, | 1629 | .fetch_size = intel_i9xx_fetch_size, |
1602 | .cleanup = intel_i915_cleanup, | 1630 | .cleanup = intel_i915_cleanup, |
1603 | .tlb_flush = intel_i810_tlbflush, | 1631 | .tlb_flush = intel_i810_tlbflush, |
1604 | .mask_memory = intel_i965_mask_memory, | 1632 | .mask_memory = intel_i965_mask_memory, |
@@ -1927,6 +1955,15 @@ static int agp_intel_resume(struct pci_dev *pdev) | |||
1927 | 1955 | ||
1928 | pci_restore_state(pdev); | 1956 | pci_restore_state(pdev); |
1929 | 1957 | ||
1958 | /* We should restore our graphics device's config space, | ||
1959 | * as host bridge (00:00) resumes before graphics device (02:00), | ||
1960 | * then our access to its pci space can work right. | ||
1961 | */ | ||
1962 | if (intel_i810_private.i810_dev) | ||
1963 | pci_restore_state(intel_i810_private.i810_dev); | ||
1964 | if (intel_i830_private.i830_dev) | ||
1965 | pci_restore_state(intel_i830_private.i830_dev); | ||
1966 | |||
1930 | if (bridge->driver == &intel_generic_driver) | 1967 | if (bridge->driver == &intel_generic_driver) |
1931 | intel_configure(); | 1968 | intel_configure(); |
1932 | else if (bridge->driver == &intel_850_driver) | 1969 | else if (bridge->driver == &intel_850_driver) |
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index d73be4c2db8a..902648db7efa 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c | |||
@@ -281,10 +281,11 @@ static int __devinit agp_sgi_init(void) | |||
281 | else | 281 | else |
282 | return 0; | 282 | return 0; |
283 | 283 | ||
284 | sgi_tioca_agp_bridges = | 284 | sgi_tioca_agp_bridges = kmalloc(tioca_gart_found * |
285 | (struct agp_bridge_data **)kmalloc(tioca_gart_found * | 285 | sizeof(struct agp_bridge_data *), |
286 | sizeof(struct agp_bridge_data *), | 286 | GFP_KERNEL); |
287 | GFP_KERNEL); | 287 | if (!sgi_tioca_agp_bridges) |
288 | return -ENOMEM; | ||
288 | 289 | ||
289 | j = 0; | 290 | j = 0; |
290 | list_for_each_entry(info, &tioca_list, ca_list) { | 291 | list_for_each_entry(info, &tioca_list, ca_list) { |
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index c149ac9ce9a7..2ded7a280d7f 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c | |||
@@ -380,9 +380,23 @@ static struct agp_device_ids via_agp_device_ids[] __devinitdata = | |||
380 | /* P4M800CE */ | 380 | /* P4M800CE */ |
381 | { | 381 | { |
382 | .device_id = PCI_DEVICE_ID_VIA_P4M800CE, | 382 | .device_id = PCI_DEVICE_ID_VIA_P4M800CE, |
383 | .chipset_name = "P4M800CE", | 383 | .chipset_name = "VT3314", |
384 | }, | ||
385 | /* CX700 */ | ||
386 | { | ||
387 | .device_id = PCI_DEVICE_ID_VIA_CX700, | ||
388 | .chipset_name = "CX700", | ||
389 | }, | ||
390 | /* VT3336 */ | ||
391 | { | ||
392 | .device_id = PCI_DEVICE_ID_VIA_VT3336, | ||
393 | .chipset_name = "VT3336", | ||
394 | }, | ||
395 | /* P4M890 */ | ||
396 | { | ||
397 | .device_id = PCI_DEVICE_ID_VIA_P4M890, | ||
398 | .chipset_name = "P4M890", | ||
384 | }, | 399 | }, |
385 | |||
386 | { }, /* dummy final entry, always present */ | 400 | { }, /* dummy final entry, always present */ |
387 | }; | 401 | }; |
388 | 402 | ||
@@ -524,6 +538,9 @@ static const struct pci_device_id agp_via_pci_table[] = { | |||
524 | ID(PCI_DEVICE_ID_VIA_83_87XX_1), | 538 | ID(PCI_DEVICE_ID_VIA_83_87XX_1), |
525 | ID(PCI_DEVICE_ID_VIA_3296_0), | 539 | ID(PCI_DEVICE_ID_VIA_3296_0), |
526 | ID(PCI_DEVICE_ID_VIA_P4M800CE), | 540 | ID(PCI_DEVICE_ID_VIA_P4M800CE), |
541 | ID(PCI_DEVICE_ID_VIA_CX700), | ||
542 | ID(PCI_DEVICE_ID_VIA_VT3336), | ||
543 | ID(PCI_DEVICE_ID_VIA_P4M890), | ||
527 | { } | 544 | { } |
528 | }; | 545 | }; |
529 | 546 | ||
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 0bbb04f2390f..6dcdceb81203 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -561,8 +561,7 @@ struct drm_driver { | |||
561 | int (*context_dtor) (struct drm_device * dev, int context); | 561 | int (*context_dtor) (struct drm_device * dev, int context); |
562 | int (*kernel_context_switch) (struct drm_device * dev, int old, | 562 | int (*kernel_context_switch) (struct drm_device * dev, int old, |
563 | int new); | 563 | int new); |
564 | void (*kernel_context_switch_unlock) (struct drm_device * dev, | 564 | void (*kernel_context_switch_unlock) (struct drm_device * dev); |
565 | drm_lock_t *lock); | ||
566 | int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence); | 565 | int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence); |
567 | int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence); | 566 | int (*vblank_wait2) (struct drm_device * dev, unsigned int *sequence); |
568 | int (*dri_library_name) (struct drm_device *dev, char *buf); | 567 | int (*dri_library_name) (struct drm_device *dev, char *buf); |
@@ -1143,9 +1142,5 @@ extern void *drm_calloc(size_t nmemb, size_t size, int area); | |||
1143 | extern unsigned long drm_core_get_map_ofs(drm_map_t * map); | 1142 | extern unsigned long drm_core_get_map_ofs(drm_map_t * map); |
1144 | extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev); | 1143 | extern unsigned long drm_core_get_reg_ofs(struct drm_device *dev); |
1145 | 1144 | ||
1146 | #ifndef pci_pretty_name | ||
1147 | #define pci_pretty_name(dev) "" | ||
1148 | #endif | ||
1149 | |||
1150 | #endif /* __KERNEL__ */ | 1145 | #endif /* __KERNEL__ */ |
1151 | #endif | 1146 | #endif |
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c index 116ed0f2ac09..e9993ba461a2 100644 --- a/drivers/char/drm/drm_lock.c +++ b/drivers/char/drm/drm_lock.c | |||
@@ -182,7 +182,7 @@ int drm_unlock(struct inode *inode, struct file *filp, | |||
182 | * modules but is required by the Sparc driver. | 182 | * modules but is required by the Sparc driver. |
183 | */ | 183 | */ |
184 | if (dev->driver->kernel_context_switch_unlock) | 184 | if (dev->driver->kernel_context_switch_unlock) |
185 | dev->driver->kernel_context_switch_unlock(dev, &lock); | 185 | dev->driver->kernel_context_switch_unlock(dev); |
186 | else { | 186 | else { |
187 | drm_lock_transfer(dev, &dev->lock.hw_lock->lock, | 187 | drm_lock_transfer(dev, &dev->lock.hw_lock->lock, |
188 | DRM_KERNEL_CONTEXT); | 188 | DRM_KERNEL_CONTEXT); |
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 5fd6dc0870cf..120d10256feb 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c | |||
@@ -211,14 +211,16 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | |||
211 | if (!dev) | 211 | if (!dev) |
212 | return -ENOMEM; | 212 | return -ENOMEM; |
213 | 213 | ||
214 | pci_enable_device(pdev); | 214 | ret = pci_enable_device(pdev); |
215 | if (ret) | ||
216 | goto err_g1; | ||
215 | 217 | ||
216 | if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) { | 218 | if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) { |
217 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); | 219 | printk(KERN_ERR "DRM: Fill_in_dev failed.\n"); |
218 | goto err_g1; | 220 | goto err_g2; |
219 | } | 221 | } |
220 | if ((ret = drm_get_head(dev, &dev->primary))) | 222 | if ((ret = drm_get_head(dev, &dev->primary))) |
221 | goto err_g1; | 223 | goto err_g2; |
222 | 224 | ||
223 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", | 225 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", |
224 | driver->name, driver->major, driver->minor, driver->patchlevel, | 226 | driver->name, driver->major, driver->minor, driver->patchlevel, |
@@ -226,7 +228,9 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | |||
226 | 228 | ||
227 | return 0; | 229 | return 0; |
228 | 230 | ||
229 | err_g1: | 231 | err_g2: |
232 | pci_disable_device(pdev); | ||
233 | err_g1: | ||
230 | drm_free(dev, sizeof(*dev), DRM_MEM_STUB); | 234 | drm_free(dev, sizeof(*dev), DRM_MEM_STUB); |
231 | return ret; | 235 | return ret; |
232 | } | 236 | } |
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index ba4b8de83cf0..cc8e2ebe128c 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c | |||
@@ -45,8 +45,8 @@ struct class *drm_sysfs_create(struct module *owner, char *name) | |||
45 | int err; | 45 | int err; |
46 | 46 | ||
47 | class = class_create(owner, name); | 47 | class = class_create(owner, name); |
48 | if (!class) { | 48 | if (IS_ERR(class)) { |
49 | err = -ENOMEM; | 49 | err = PTR_ERR(class); |
50 | goto err_out; | 50 | goto err_out; |
51 | } | 51 | } |
52 | 52 | ||
@@ -113,8 +113,8 @@ struct class_device *drm_sysfs_device_add(struct class *cs, drm_head_t *head) | |||
113 | MKDEV(DRM_MAJOR, head->minor), | 113 | MKDEV(DRM_MAJOR, head->minor), |
114 | &(head->dev->pdev)->dev, | 114 | &(head->dev->pdev)->dev, |
115 | "card%d", head->minor); | 115 | "card%d", head->minor); |
116 | if (!class_dev) { | 116 | if (IS_ERR(class_dev)) { |
117 | err = -ENOMEM; | 117 | err = PTR_ERR(class_dev); |
118 | goto err_out; | 118 | goto err_out; |
119 | } | 119 | } |
120 | 120 | ||
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index e5463b111fc0..78c1ae28f17c 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c | |||
@@ -46,88 +46,167 @@ static void i915_vblank_tasklet(drm_device_t *dev) | |||
46 | { | 46 | { |
47 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 47 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
48 | unsigned long irqflags; | 48 | unsigned long irqflags; |
49 | struct list_head *list, *tmp; | 49 | struct list_head *list, *tmp, hits, *hit; |
50 | int nhits, nrects, slice[2], upper[2], lower[2], i; | ||
51 | unsigned counter[2] = { atomic_read(&dev->vbl_received), | ||
52 | atomic_read(&dev->vbl_received2) }; | ||
53 | drm_drawable_info_t *drw; | ||
54 | drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv; | ||
55 | u32 cpp = dev_priv->cpp; | ||
56 | u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD | | ||
57 | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||
58 | XY_SRC_COPY_BLT_WRITE_RGB) | ||
59 | : XY_SRC_COPY_BLT_CMD; | ||
60 | u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) | | ||
61 | (cpp << 23) | (1 << 24); | ||
62 | RING_LOCALS; | ||
50 | 63 | ||
51 | DRM_DEBUG("\n"); | 64 | DRM_DEBUG("\n"); |
52 | 65 | ||
66 | INIT_LIST_HEAD(&hits); | ||
67 | |||
68 | nhits = nrects = 0; | ||
69 | |||
53 | spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); | 70 | spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); |
54 | 71 | ||
72 | /* Find buffer swaps scheduled for this vertical blank */ | ||
55 | list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { | 73 | list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) { |
56 | drm_i915_vbl_swap_t *vbl_swap = | 74 | drm_i915_vbl_swap_t *vbl_swap = |
57 | list_entry(list, drm_i915_vbl_swap_t, head); | 75 | list_entry(list, drm_i915_vbl_swap_t, head); |
58 | atomic_t *counter = vbl_swap->pipe ? &dev->vbl_received2 : | ||
59 | &dev->vbl_received; | ||
60 | |||
61 | if ((atomic_read(counter) - vbl_swap->sequence) <= (1<<23)) { | ||
62 | drm_drawable_info_t *drw; | ||
63 | |||
64 | spin_unlock(&dev_priv->swaps_lock); | ||
65 | |||
66 | spin_lock(&dev->drw_lock); | ||
67 | |||
68 | drw = drm_get_drawable_info(dev, vbl_swap->drw_id); | ||
69 | |||
70 | if (drw) { | ||
71 | int i, num_rects = drw->num_rects; | ||
72 | drm_clip_rect_t *rect = drw->rects; | ||
73 | drm_i915_sarea_t *sarea_priv = | ||
74 | dev_priv->sarea_priv; | ||
75 | u32 cpp = dev_priv->cpp; | ||
76 | u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD | | ||
77 | XY_SRC_COPY_BLT_WRITE_ALPHA | | ||
78 | XY_SRC_COPY_BLT_WRITE_RGB) | ||
79 | : XY_SRC_COPY_BLT_CMD; | ||
80 | u32 pitchropcpp = (sarea_priv->pitch * cpp) | | ||
81 | (0xcc << 16) | (cpp << 23) | | ||
82 | (1 << 24); | ||
83 | RING_LOCALS; | ||
84 | |||
85 | i915_kernel_lost_context(dev); | ||
86 | |||
87 | BEGIN_LP_RING(6); | ||
88 | |||
89 | OUT_RING(GFX_OP_DRAWRECT_INFO); | ||
90 | OUT_RING(0); | ||
91 | OUT_RING(0); | ||
92 | OUT_RING(sarea_priv->width | | ||
93 | sarea_priv->height << 16); | ||
94 | OUT_RING(sarea_priv->width | | ||
95 | sarea_priv->height << 16); | ||
96 | OUT_RING(0); | ||
97 | 76 | ||
98 | ADVANCE_LP_RING(); | 77 | if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23)) |
78 | continue; | ||
79 | |||
80 | list_del(list); | ||
81 | dev_priv->swaps_pending--; | ||
99 | 82 | ||
100 | sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT; | 83 | spin_unlock(&dev_priv->swaps_lock); |
84 | spin_lock(&dev->drw_lock); | ||
101 | 85 | ||
102 | for (i = 0; i < num_rects; i++, rect++) { | 86 | drw = drm_get_drawable_info(dev, vbl_swap->drw_id); |
103 | BEGIN_LP_RING(8); | 87 | |
88 | if (!drw) { | ||
89 | spin_unlock(&dev->drw_lock); | ||
90 | drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); | ||
91 | spin_lock(&dev_priv->swaps_lock); | ||
92 | continue; | ||
93 | } | ||
104 | 94 | ||
105 | OUT_RING(cmd); | 95 | list_for_each(hit, &hits) { |
106 | OUT_RING(pitchropcpp); | 96 | drm_i915_vbl_swap_t *swap_cmp = |
107 | OUT_RING((rect->y1 << 16) | rect->x1); | 97 | list_entry(hit, drm_i915_vbl_swap_t, head); |
108 | OUT_RING((rect->y2 << 16) | rect->x2); | 98 | drm_drawable_info_t *drw_cmp = |
109 | OUT_RING(sarea_priv->front_offset); | 99 | drm_get_drawable_info(dev, swap_cmp->drw_id); |
110 | OUT_RING((rect->y1 << 16) | rect->x1); | ||
111 | OUT_RING(pitchropcpp & 0xffff); | ||
112 | OUT_RING(sarea_priv->back_offset); | ||
113 | 100 | ||
114 | ADVANCE_LP_RING(); | 101 | if (drw_cmp && |
115 | } | 102 | drw_cmp->rects[0].y1 > drw->rects[0].y1) { |
103 | list_add_tail(list, hit); | ||
104 | break; | ||
116 | } | 105 | } |
106 | } | ||
117 | 107 | ||
118 | spin_unlock(&dev->drw_lock); | 108 | spin_unlock(&dev->drw_lock); |
119 | 109 | ||
120 | spin_lock(&dev_priv->swaps_lock); | 110 | /* List of hits was empty, or we reached the end of it */ |
111 | if (hit == &hits) | ||
112 | list_add_tail(list, hits.prev); | ||
121 | 113 | ||
122 | list_del(list); | 114 | nhits++; |
123 | 115 | ||
124 | drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER); | 116 | spin_lock(&dev_priv->swaps_lock); |
117 | } | ||
118 | |||
119 | if (nhits == 0) { | ||
120 | spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); | ||
121 | return; | ||
122 | } | ||
123 | |||
124 | spin_unlock(&dev_priv->swaps_lock); | ||
125 | 125 | ||
126 | dev_priv->swaps_pending--; | 126 | i915_kernel_lost_context(dev); |
127 | |||
128 | BEGIN_LP_RING(6); | ||
129 | |||
130 | OUT_RING(GFX_OP_DRAWRECT_INFO); | ||
131 | OUT_RING(0); | ||
132 | OUT_RING(0); | ||
133 | OUT_RING(sarea_priv->width | sarea_priv->height << 16); | ||
134 | OUT_RING(sarea_priv->width | sarea_priv->height << 16); | ||
135 | OUT_RING(0); | ||
136 | |||
137 | ADVANCE_LP_RING(); | ||
138 | |||
139 | sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT; | ||
140 | |||
141 | upper[0] = upper[1] = 0; | ||
142 | slice[0] = max(sarea_priv->pipeA_h / nhits, 1); | ||
143 | slice[1] = max(sarea_priv->pipeB_h / nhits, 1); | ||
144 | lower[0] = sarea_priv->pipeA_y + slice[0]; | ||
145 | lower[1] = sarea_priv->pipeB_y + slice[0]; | ||
146 | |||
147 | spin_lock(&dev->drw_lock); | ||
148 | |||
149 | /* Emit blits for buffer swaps, partitioning both outputs into as many | ||
150 | * slices as there are buffer swaps scheduled in order to avoid tearing | ||
151 | * (based on the assumption that a single buffer swap would always | ||
152 | * complete before scanout starts). | ||
153 | */ | ||
154 | for (i = 0; i++ < nhits; | ||
155 | upper[0] = lower[0], lower[0] += slice[0], | ||
156 | upper[1] = lower[1], lower[1] += slice[1]) { | ||
157 | if (i == nhits) | ||
158 | lower[0] = lower[1] = sarea_priv->height; | ||
159 | |||
160 | list_for_each(hit, &hits) { | ||
161 | drm_i915_vbl_swap_t *swap_hit = | ||
162 | list_entry(hit, drm_i915_vbl_swap_t, head); | ||
163 | drm_clip_rect_t *rect; | ||
164 | int num_rects, pipe; | ||
165 | unsigned short top, bottom; | ||
166 | |||
167 | drw = drm_get_drawable_info(dev, swap_hit->drw_id); | ||
168 | |||
169 | if (!drw) | ||
170 | continue; | ||
171 | |||
172 | rect = drw->rects; | ||
173 | pipe = swap_hit->pipe; | ||
174 | top = upper[pipe]; | ||
175 | bottom = lower[pipe]; | ||
176 | |||
177 | for (num_rects = drw->num_rects; num_rects--; rect++) { | ||
178 | int y1 = max(rect->y1, top); | ||
179 | int y2 = min(rect->y2, bottom); | ||
180 | |||
181 | if (y1 >= y2) | ||
182 | continue; | ||
183 | |||
184 | BEGIN_LP_RING(8); | ||
185 | |||
186 | OUT_RING(cmd); | ||
187 | OUT_RING(pitchropcpp); | ||
188 | OUT_RING((y1 << 16) | rect->x1); | ||
189 | OUT_RING((y2 << 16) | rect->x2); | ||
190 | OUT_RING(sarea_priv->front_offset); | ||
191 | OUT_RING((y1 << 16) | rect->x1); | ||
192 | OUT_RING(pitchropcpp & 0xffff); | ||
193 | OUT_RING(sarea_priv->back_offset); | ||
194 | |||
195 | ADVANCE_LP_RING(); | ||
196 | } | ||
127 | } | 197 | } |
128 | } | 198 | } |
129 | 199 | ||
130 | spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); | 200 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); |
201 | |||
202 | list_for_each_safe(hit, tmp, &hits) { | ||
203 | drm_i915_vbl_swap_t *swap_hit = | ||
204 | list_entry(hit, drm_i915_vbl_swap_t, head); | ||
205 | |||
206 | list_del(hit); | ||
207 | |||
208 | drm_free(swap_hit, sizeof(*swap_hit), DRM_MEM_DRIVER); | ||
209 | } | ||
131 | } | 210 | } |
132 | 211 | ||
133 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | 212 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) |
@@ -421,7 +500,7 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) | |||
421 | 500 | ||
422 | if (!drm_get_drawable_info(dev, swap.drawable)) { | 501 | if (!drm_get_drawable_info(dev, swap.drawable)) { |
423 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); | 502 | spin_unlock_irqrestore(&dev->drw_lock, irqflags); |
424 | DRM_ERROR("Invalid drawable ID %d\n", swap.drawable); | 503 | DRM_DEBUG("Invalid drawable ID %d\n", swap.drawable); |
425 | return DRM_ERR(EINVAL); | 504 | return DRM_ERR(EINVAL); |
426 | } | 505 | } |
427 | 506 | ||
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h index 5d835b006f55..6e8af313f2b4 100644 --- a/drivers/char/drm/r128_drm.h +++ b/drivers/char/drm/r128_drm.h | |||
@@ -1,7 +1,8 @@ | |||
1 | /* r128_drm.h -- Public header for the r128 driver -*- linux-c -*- | 1 | /* r128_drm.h -- Public header for the r128 driver -*- linux-c -*- |
2 | * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com | 2 | * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com |
3 | */ | 3 | */ |
4 | /* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. | 4 | /* |
5 | * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. | ||
5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | 6 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
6 | * All rights reserved. | 7 | * All rights reserved. |
7 | * | 8 | * |
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h index 94abffb2cca5..f1efb49de8df 100644 --- a/drivers/char/drm/r128_drv.h +++ b/drivers/char/drm/r128_drv.h | |||
@@ -1,7 +1,8 @@ | |||
1 | /* r128_drv.h -- Private header for r128 driver -*- linux-c -*- | 1 | /* r128_drv.h -- Private header for r128 driver -*- linux-c -*- |
2 | * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com | 2 | * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com |
3 | */ | 3 | */ |
4 | /* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | 4 | /* |
5 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | 6 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
6 | * All rights reserved. | 7 | * All rights reserved. |
7 | * | 8 | * |
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c index a080cdd6081e..17b11e7d8f32 100644 --- a/drivers/char/drm/r128_state.c +++ b/drivers/char/drm/r128_state.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* r128_state.c -- State support for r128 -*- linux-c -*- | 1 | /* r128_state.c -- State support for r128 -*- linux-c -*- |
2 | * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com | 2 | * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com |
3 | */ | 3 | */ |
4 | /* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | 4 | /* |
5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
5 | * All Rights Reserved. | 6 | * All Rights Reserved. |
6 | * | 7 | * |
7 | * Permission is hereby granted, free of charge, to any person obtaining a | 8 | * Permission is hereby granted, free of charge, to any person obtaining a |
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index d14477ba3679..032a022ec6a8 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c | |||
@@ -242,26 +242,6 @@ static __inline__ int r300_check_range(unsigned reg, int count) | |||
242 | return 0; | 242 | return 0; |
243 | } | 243 | } |
244 | 244 | ||
245 | /* | ||
246 | * we expect offsets passed to the framebuffer to be either within video | ||
247 | * memory or within AGP space | ||
248 | */ | ||
249 | static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, | ||
250 | u32 offset) | ||
251 | { | ||
252 | /* we realy want to check against end of video aperture | ||
253 | but this value is not being kept. | ||
254 | This code is correct for now (does the same thing as the | ||
255 | code that sets MC_FB_LOCATION) in radeon_cp.c */ | ||
256 | if (offset >= dev_priv->fb_location && | ||
257 | offset < (dev_priv->fb_location + dev_priv->fb_size)) | ||
258 | return 0; | ||
259 | if (offset >= dev_priv->gart_vm_start && | ||
260 | offset < (dev_priv->gart_vm_start + dev_priv->gart_size)) | ||
261 | return 0; | ||
262 | return 1; | ||
263 | } | ||
264 | |||
265 | static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * | 245 | static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * |
266 | dev_priv, | 246 | dev_priv, |
267 | drm_radeon_kcmd_buffer_t | 247 | drm_radeon_kcmd_buffer_t |
@@ -290,7 +270,7 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * | |||
290 | case MARK_SAFE: | 270 | case MARK_SAFE: |
291 | break; | 271 | break; |
292 | case MARK_CHECK_OFFSET: | 272 | case MARK_CHECK_OFFSET: |
293 | if (r300_check_offset(dev_priv, (u32) values[i])) { | 273 | if (!radeon_check_offset(dev_priv, (u32) values[i])) { |
294 | DRM_ERROR | 274 | DRM_ERROR |
295 | ("Offset failed range check (reg=%04x sz=%d)\n", | 275 | ("Offset failed range check (reg=%04x sz=%d)\n", |
296 | reg, sz); | 276 | reg, sz); |
@@ -452,7 +432,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, | |||
452 | i = 1; | 432 | i = 1; |
453 | while ((k < narrays) && (i < (count + 1))) { | 433 | while ((k < narrays) && (i < (count + 1))) { |
454 | i++; /* skip attribute field */ | 434 | i++; /* skip attribute field */ |
455 | if (r300_check_offset(dev_priv, payload[i])) { | 435 | if (!radeon_check_offset(dev_priv, payload[i])) { |
456 | DRM_ERROR | 436 | DRM_ERROR |
457 | ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", | 437 | ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", |
458 | k, i); | 438 | k, i); |
@@ -463,7 +443,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, | |||
463 | if (k == narrays) | 443 | if (k == narrays) |
464 | break; | 444 | break; |
465 | /* have one more to process, they come in pairs */ | 445 | /* have one more to process, they come in pairs */ |
466 | if (r300_check_offset(dev_priv, payload[i])) { | 446 | if (!radeon_check_offset(dev_priv, payload[i])) { |
467 | DRM_ERROR | 447 | DRM_ERROR |
468 | ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", | 448 | ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", |
469 | k, i); | 449 | k, i); |
@@ -508,7 +488,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, | |||
508 | if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 488 | if (cmd[1] & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
509 | | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { | 489 | | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { |
510 | offset = cmd[2] << 10; | 490 | offset = cmd[2] << 10; |
511 | ret = r300_check_offset(dev_priv, offset); | 491 | ret = !radeon_check_offset(dev_priv, offset); |
512 | if (ret) { | 492 | if (ret) { |
513 | DRM_ERROR("Invalid bitblt first offset is %08X\n", offset); | 493 | DRM_ERROR("Invalid bitblt first offset is %08X\n", offset); |
514 | return DRM_ERR(EINVAL); | 494 | return DRM_ERR(EINVAL); |
@@ -518,7 +498,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, | |||
518 | if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && | 498 | if ((cmd[1] & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && |
519 | (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { | 499 | (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { |
520 | offset = cmd[3] << 10; | 500 | offset = cmd[3] << 10; |
521 | ret = r300_check_offset(dev_priv, offset); | 501 | ret = !radeon_check_offset(dev_priv, offset); |
522 | if (ret) { | 502 | if (ret) { |
523 | DRM_ERROR("Invalid bitblt second offset is %08X\n", offset); | 503 | DRM_ERROR("Invalid bitblt second offset is %08X\n", offset); |
524 | return DRM_ERR(EINVAL); | 504 | return DRM_ERR(EINVAL); |
@@ -551,7 +531,7 @@ static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, | |||
551 | DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); | 531 | DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); |
552 | return DRM_ERR(EINVAL); | 532 | return DRM_ERR(EINVAL); |
553 | } | 533 | } |
554 | ret = r300_check_offset(dev_priv, cmd[2]); | 534 | ret = !radeon_check_offset(dev_priv, cmd[2]); |
555 | if (ret) { | 535 | if (ret) { |
556 | DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); | 536 | DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); |
557 | return DRM_ERR(EINVAL); | 537 | return DRM_ERR(EINVAL); |
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index f45cd7f147a5..8b105f1460a7 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h | |||
@@ -303,6 +303,21 @@ extern int radeon_no_wb; | |||
303 | extern drm_ioctl_desc_t radeon_ioctls[]; | 303 | extern drm_ioctl_desc_t radeon_ioctls[]; |
304 | extern int radeon_max_ioctl; | 304 | extern int radeon_max_ioctl; |
305 | 305 | ||
306 | /* Check whether the given hardware address is inside the framebuffer or the | ||
307 | * GART area. | ||
308 | */ | ||
309 | static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv, | ||
310 | u64 off) | ||
311 | { | ||
312 | u32 fb_start = dev_priv->fb_location; | ||
313 | u32 fb_end = fb_start + dev_priv->fb_size - 1; | ||
314 | u32 gart_start = dev_priv->gart_vm_start; | ||
315 | u32 gart_end = gart_start + dev_priv->gart_size - 1; | ||
316 | |||
317 | return ((off >= fb_start && off <= fb_end) || | ||
318 | (off >= gart_start && off <= gart_end)); | ||
319 | } | ||
320 | |||
306 | /* radeon_cp.c */ | 321 | /* radeon_cp.c */ |
307 | extern int radeon_cp_init(DRM_IOCTL_ARGS); | 322 | extern int radeon_cp_init(DRM_IOCTL_ARGS); |
308 | extern int radeon_cp_start(DRM_IOCTL_ARGS); | 323 | extern int radeon_cp_start(DRM_IOCTL_ARGS); |
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c index d60519de887b..3ff0baa2fbfa 100644 --- a/drivers/char/drm/radeon_irq.c +++ b/drivers/char/drm/radeon_irq.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- | 1 | /* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */ |
2 | * | 2 | /* |
3 | * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | 3 | * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
4 | * | 4 | * |
5 | * The Weather Channel (TM) funded Tungsten Graphics to develop the | 5 | * The Weather Channel (TM) funded Tungsten Graphics to develop the |
diff --git a/drivers/char/drm/radeon_mem.c b/drivers/char/drm/radeon_mem.c index 030a6fad0d86..517cad8b6e3a 100644 --- a/drivers/char/drm/radeon_mem.c +++ b/drivers/char/drm/radeon_mem.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- | 1 | /* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- */ |
2 | * | 2 | /* |
3 | * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. | 3 | * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
4 | * | 4 | * |
5 | * The Weather Channel (TM) funded Tungsten Graphics to develop the | 5 | * The Weather Channel (TM) funded Tungsten Graphics to develop the |
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 6e04fdd732ac..938eccb78cc0 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c | |||
@@ -43,10 +43,7 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * | |||
43 | u32 *offset) | 43 | u32 *offset) |
44 | { | 44 | { |
45 | u64 off = *offset; | 45 | u64 off = *offset; |
46 | u32 fb_start = dev_priv->fb_location; | 46 | u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1; |
47 | u32 fb_end = fb_start + dev_priv->fb_size - 1; | ||
48 | u32 gart_start = dev_priv->gart_vm_start; | ||
49 | u32 gart_end = gart_start + dev_priv->gart_size - 1; | ||
50 | struct drm_radeon_driver_file_fields *radeon_priv; | 47 | struct drm_radeon_driver_file_fields *radeon_priv; |
51 | 48 | ||
52 | /* Hrm ... the story of the offset ... So this function converts | 49 | /* Hrm ... the story of the offset ... So this function converts |
@@ -66,8 +63,7 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * | |||
66 | /* First, the best case, the offset already lands in either the | 63 | /* First, the best case, the offset already lands in either the |
67 | * framebuffer or the GART mapped space | 64 | * framebuffer or the GART mapped space |
68 | */ | 65 | */ |
69 | if ((off >= fb_start && off <= fb_end) || | 66 | if (radeon_check_offset(dev_priv, off)) |
70 | (off >= gart_start && off <= gart_end)) | ||
71 | return 0; | 67 | return 0; |
72 | 68 | ||
73 | /* Ok, that didn't happen... now check if we have a zero based | 69 | /* Ok, that didn't happen... now check if we have a zero based |
@@ -81,11 +77,10 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * | |||
81 | 77 | ||
82 | /* Finally, assume we aimed at a GART offset if beyond the fb */ | 78 | /* Finally, assume we aimed at a GART offset if beyond the fb */ |
83 | if (off > fb_end) | 79 | if (off > fb_end) |
84 | off = off - fb_end - 1 + gart_start; | 80 | off = off - fb_end - 1 + dev_priv->gart_vm_start; |
85 | 81 | ||
86 | /* Now recheck and fail if out of bounds */ | 82 | /* Now recheck and fail if out of bounds */ |
87 | if ((off >= fb_start && off <= fb_end) || | 83 | if (radeon_check_offset(dev_priv, off)) { |
88 | (off >= gart_start && off <= gart_end)) { | ||
89 | DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off); | 84 | DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off); |
90 | *offset = off; | 85 | *offset = off; |
91 | return 0; | 86 | return 0; |
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c index a9a84f88df5e..b94fab556809 100644 --- a/drivers/char/drm/savage_bci.c +++ b/drivers/char/drm/savage_bci.c | |||
@@ -963,8 +963,8 @@ static int savage_bci_event_emit(DRM_IOCTL_ARGS) | |||
963 | 963 | ||
964 | event.count = savage_bci_emit_event(dev_priv, event.flags); | 964 | event.count = savage_bci_emit_event(dev_priv, event.flags); |
965 | event.count |= dev_priv->event_wrap << 16; | 965 | event.count |= dev_priv->event_wrap << 16; |
966 | DRM_COPY_TO_USER_IOCTL(&((drm_savage_event_emit_t __user *) data)-> | 966 | DRM_COPY_TO_USER_IOCTL((drm_savage_event_emit_t __user *) data, |
967 | count, event.count, sizeof(event.count)); | 967 | event, sizeof(event)); |
968 | return 0; | 968 | return 0; |
969 | } | 969 | } |
970 | 970 | ||
diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c index 71e4e0f3fd54..556fd81fa815 100644 --- a/drivers/char/hw_random/amd-rng.c +++ b/drivers/char/hw_random/amd-rng.c | |||
@@ -144,7 +144,7 @@ static void __exit mod_exit(void) | |||
144 | hwrng_unregister(&amd_rng); | 144 | hwrng_unregister(&amd_rng); |
145 | } | 145 | } |
146 | 146 | ||
147 | subsys_initcall(mod_init); | 147 | module_init(mod_init); |
148 | module_exit(mod_exit); | 148 | module_exit(mod_exit); |
149 | 149 | ||
150 | MODULE_AUTHOR("The Linux Kernel team"); | 150 | MODULE_AUTHOR("The Linux Kernel team"); |
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c index d37ced0d132b..8e8658dcd2e3 100644 --- a/drivers/char/hw_random/geode-rng.c +++ b/drivers/char/hw_random/geode-rng.c | |||
@@ -125,7 +125,7 @@ static void __exit mod_exit(void) | |||
125 | iounmap(mem); | 125 | iounmap(mem); |
126 | } | 126 | } |
127 | 127 | ||
128 | subsys_initcall(mod_init); | 128 | module_init(mod_init); |
129 | module_exit(mod_exit); | 129 | module_exit(mod_exit); |
130 | 130 | ||
131 | MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs"); | 131 | MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs"); |
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 8efbc9c0e545..f22e78e3c70f 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c | |||
@@ -143,6 +143,11 @@ static const struct pci_device_id pci_tbl[] = { | |||
143 | }; | 143 | }; |
144 | MODULE_DEVICE_TABLE(pci, pci_tbl); | 144 | MODULE_DEVICE_TABLE(pci, pci_tbl); |
145 | 145 | ||
146 | static __initdata int no_fwh_detect; | ||
147 | module_param(no_fwh_detect, int, 0); | ||
148 | MODULE_PARM_DESC(no_fwh_detect, "Skip FWH detection:\n" | ||
149 | " positive value - skip if FWH space locked read-only\n" | ||
150 | " negative value - skip always"); | ||
146 | 151 | ||
147 | static inline u8 hwstatus_get(void __iomem *mem) | 152 | static inline u8 hwstatus_get(void __iomem *mem) |
148 | { | 153 | { |
@@ -240,6 +245,11 @@ static int __init mod_init(void) | |||
240 | if (!dev) | 245 | if (!dev) |
241 | goto out; /* Device not found. */ | 246 | goto out; /* Device not found. */ |
242 | 247 | ||
248 | if (no_fwh_detect < 0) { | ||
249 | pci_dev_put(dev); | ||
250 | goto fwh_done; | ||
251 | } | ||
252 | |||
243 | /* Check for Intel 82802 */ | 253 | /* Check for Intel 82802 */ |
244 | if (dev->device < 0x2640) { | 254 | if (dev->device < 0x2640) { |
245 | fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD; | 255 | fwh_dec_en1_off = FWH_DEC_EN1_REG_OLD; |
@@ -252,6 +262,23 @@ static int __init mod_init(void) | |||
252 | pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val); | 262 | pci_read_config_byte(dev, fwh_dec_en1_off, &fwh_dec_en1_val); |
253 | pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val); | 263 | pci_read_config_byte(dev, bios_cntl_off, &bios_cntl_val); |
254 | 264 | ||
265 | if ((bios_cntl_val & | ||
266 | (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK)) | ||
267 | == BIOS_CNTL_LOCK_ENABLE_MASK) { | ||
268 | static __initdata /*const*/ char warning[] = | ||
269 | KERN_WARNING PFX "Firmware space is locked read-only. If you can't or\n" | ||
270 | KERN_WARNING PFX "don't want to disable this in firmware setup, and if\n" | ||
271 | KERN_WARNING PFX "you are certain that your system has a functional\n" | ||
272 | KERN_WARNING PFX "RNG, try using the 'no_fwh_detect' option.\n"; | ||
273 | |||
274 | pci_dev_put(dev); | ||
275 | if (no_fwh_detect) | ||
276 | goto fwh_done; | ||
277 | printk(warning); | ||
278 | err = -EBUSY; | ||
279 | goto out; | ||
280 | } | ||
281 | |||
255 | mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); | 282 | mem = ioremap_nocache(INTEL_FWH_ADDR, INTEL_FWH_ADDR_LEN); |
256 | if (mem == NULL) { | 283 | if (mem == NULL) { |
257 | pci_dev_put(dev); | 284 | pci_dev_put(dev); |
@@ -280,8 +307,7 @@ static int __init mod_init(void) | |||
280 | pci_write_config_byte(dev, | 307 | pci_write_config_byte(dev, |
281 | fwh_dec_en1_off, | 308 | fwh_dec_en1_off, |
282 | fwh_dec_en1_val | FWH_F8_EN_MASK); | 309 | fwh_dec_en1_val | FWH_F8_EN_MASK); |
283 | if (!(bios_cntl_val & | 310 | if (!(bios_cntl_val & BIOS_CNTL_WRITE_ENABLE_MASK)) |
284 | (BIOS_CNTL_LOCK_ENABLE_MASK|BIOS_CNTL_WRITE_ENABLE_MASK))) | ||
285 | pci_write_config_byte(dev, | 311 | pci_write_config_byte(dev, |
286 | bios_cntl_off, | 312 | bios_cntl_off, |
287 | bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK); | 313 | bios_cntl_val | BIOS_CNTL_WRITE_ENABLE_MASK); |
@@ -315,6 +341,8 @@ static int __init mod_init(void) | |||
315 | goto out; | 341 | goto out; |
316 | } | 342 | } |
317 | 343 | ||
344 | fwh_done: | ||
345 | |||
318 | err = -ENOMEM; | 346 | err = -ENOMEM; |
319 | mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); | 347 | mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN); |
320 | if (!mem) | 348 | if (!mem) |
@@ -350,7 +378,7 @@ static void __exit mod_exit(void) | |||
350 | iounmap(mem); | 378 | iounmap(mem); |
351 | } | 379 | } |
352 | 380 | ||
353 | subsys_initcall(mod_init); | 381 | module_init(mod_init); |
354 | module_exit(mod_exit); | 382 | module_exit(mod_exit); |
355 | 383 | ||
356 | MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets"); | 384 | MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets"); |
diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c index c9caff57db85..bab43ca32ac1 100644 --- a/drivers/char/hw_random/ixp4xx-rng.c +++ b/drivers/char/hw_random/ixp4xx-rng.c | |||
@@ -64,7 +64,7 @@ static void __exit ixp4xx_rng_exit(void) | |||
64 | iounmap(rng_base); | 64 | iounmap(rng_base); |
65 | } | 65 | } |
66 | 66 | ||
67 | subsys_initcall(ixp4xx_rng_init); | 67 | module_init(ixp4xx_rng_init); |
68 | module_exit(ixp4xx_rng_exit); | 68 | module_exit(ixp4xx_rng_exit); |
69 | 69 | ||
70 | MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>"); | 70 | MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>"); |
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c index 0e786b617bb8..9ebf84d18655 100644 --- a/drivers/char/hw_random/via-rng.c +++ b/drivers/char/hw_random/via-rng.c | |||
@@ -176,7 +176,7 @@ static void __exit mod_exit(void) | |||
176 | hwrng_unregister(&via_rng); | 176 | hwrng_unregister(&via_rng); |
177 | } | 177 | } |
178 | 178 | ||
179 | subsys_initcall(mod_init); | 179 | module_init(mod_init); |
180 | module_exit(mod_exit); | 180 | module_exit(mod_exit); |
181 | 181 | ||
182 | MODULE_DESCRIPTION("H/W RNG driver for VIA chipsets"); | 182 | MODULE_DESCRIPTION("H/W RNG driver for VIA chipsets"); |
diff --git a/drivers/char/ip2/i2ellis.h b/drivers/char/ip2/i2ellis.h index 5eabe47b0bc8..433305062fb8 100644 --- a/drivers/char/ip2/i2ellis.h +++ b/drivers/char/ip2/i2ellis.h | |||
@@ -606,9 +606,9 @@ static int iiDownloadAll(i2eBordStrPtr, loadHdrStrPtr, int, int); | |||
606 | // code and returning. | 606 | // code and returning. |
607 | // | 607 | // |
608 | #define COMPLETE(pB,code) \ | 608 | #define COMPLETE(pB,code) \ |
609 | if(1){ \ | 609 | do { \ |
610 | pB->i2eError = code; \ | 610 | pB->i2eError = code; \ |
611 | return (code == I2EE_GOOD);\ | 611 | return (code == I2EE_GOOD);\ |
612 | } | 612 | } while (0) |
613 | 613 | ||
614 | #endif // I2ELLIS_H | 614 | #endif // I2ELLIS_H |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 4e4691a53890..53582b53da95 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -3649,8 +3649,6 @@ static void ipmi_timeout_handler(long timeout_period) | |||
3649 | unsigned long flags; | 3649 | unsigned long flags; |
3650 | int i; | 3650 | int i; |
3651 | 3651 | ||
3652 | INIT_LIST_HEAD(&timeouts); | ||
3653 | |||
3654 | rcu_read_lock(); | 3652 | rcu_read_lock(); |
3655 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { | 3653 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { |
3656 | /* See if any waiting messages need to be processed. */ | 3654 | /* See if any waiting messages need to be processed. */ |
@@ -3671,6 +3669,7 @@ static void ipmi_timeout_handler(long timeout_period) | |||
3671 | /* Go through the seq table and find any messages that | 3669 | /* Go through the seq table and find any messages that |
3672 | have timed out, putting them in the timeouts | 3670 | have timed out, putting them in the timeouts |
3673 | list. */ | 3671 | list. */ |
3672 | INIT_LIST_HEAD(&timeouts); | ||
3674 | spin_lock_irqsave(&intf->seq_lock, flags); | 3673 | spin_lock_irqsave(&intf->seq_lock, flags); |
3675 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) | 3674 | for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) |
3676 | check_msg_timeout(intf, &(intf->seq_table[i]), | 3675 | check_msg_timeout(intf, &(intf->seq_table[i]), |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 78280380a905..6b634e8d9519 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -216,13 +216,13 @@ static int set_param_str(const char *val, struct kernel_param *kp) | |||
216 | { | 216 | { |
217 | action_fn fn = (action_fn) kp->arg; | 217 | action_fn fn = (action_fn) kp->arg; |
218 | int rv = 0; | 218 | int rv = 0; |
219 | char *dup, *s; | 219 | char valcp[16]; |
220 | char *s; | ||
220 | 221 | ||
221 | dup = kstrdup(val, GFP_KERNEL); | 222 | strncpy(valcp, val, 16); |
222 | if (!dup) | 223 | valcp[15] = '\0'; |
223 | return -ENOMEM; | ||
224 | 224 | ||
225 | s = strstrip(dup); | 225 | s = strstrip(valcp); |
226 | 226 | ||
227 | down_read(®ister_sem); | 227 | down_read(®ister_sem); |
228 | rv = fn(s, NULL); | 228 | rv = fn(s, NULL); |
@@ -235,7 +235,6 @@ static int set_param_str(const char *val, struct kernel_param *kp) | |||
235 | 235 | ||
236 | out_unlock: | 236 | out_unlock: |
237 | up_read(®ister_sem); | 237 | up_read(®ister_sem); |
238 | kfree(dup); | ||
239 | return rv; | 238 | return rv; |
240 | } | 239 | } |
241 | 240 | ||
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index 5a747e685993..01084abffddf 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
@@ -230,6 +230,20 @@ static struct isi_port isi_ports[PORT_COUNT]; | |||
230 | * it wants to talk. | 230 | * it wants to talk. |
231 | */ | 231 | */ |
232 | 232 | ||
233 | static inline int WaitTillCardIsFree(u16 base) | ||
234 | { | ||
235 | unsigned int count = 0; | ||
236 | unsigned int a = in_atomic(); /* do we run under spinlock? */ | ||
237 | |||
238 | while (!(inw(base + 0xe) & 0x1) && count++ < 100) | ||
239 | if (a) | ||
240 | mdelay(1); | ||
241 | else | ||
242 | msleep(1); | ||
243 | |||
244 | return !(inw(base + 0xe) & 0x1); | ||
245 | } | ||
246 | |||
233 | static int lock_card(struct isi_board *card) | 247 | static int lock_card(struct isi_board *card) |
234 | { | 248 | { |
235 | char retries; | 249 | char retries; |
@@ -276,69 +290,71 @@ static void unlock_card(struct isi_board *card) | |||
276 | * ISI Card specific ops ... | 290 | * ISI Card specific ops ... |
277 | */ | 291 | */ |
278 | 292 | ||
293 | /* card->lock HAS to be held */ | ||
279 | static void raise_dtr(struct isi_port *port) | 294 | static void raise_dtr(struct isi_port *port) |
280 | { | 295 | { |
281 | struct isi_board *card = port->card; | 296 | struct isi_board *card = port->card; |
282 | unsigned long base = card->base; | 297 | unsigned long base = card->base; |
283 | u16 channel = port->channel; | 298 | u16 channel = port->channel; |
284 | 299 | ||
285 | if (!lock_card(card)) | 300 | if (WaitTillCardIsFree(base)) |
286 | return; | 301 | return; |
287 | 302 | ||
288 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); | 303 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); |
289 | outw(0x0504, base); | 304 | outw(0x0504, base); |
290 | InterruptTheCard(base); | 305 | InterruptTheCard(base); |
291 | port->status |= ISI_DTR; | 306 | port->status |= ISI_DTR; |
292 | unlock_card(card); | ||
293 | } | 307 | } |
294 | 308 | ||
309 | /* card->lock HAS to be held */ | ||
295 | static inline void drop_dtr(struct isi_port *port) | 310 | static inline void drop_dtr(struct isi_port *port) |
296 | { | 311 | { |
297 | struct isi_board *card = port->card; | 312 | struct isi_board *card = port->card; |
298 | unsigned long base = card->base; | 313 | unsigned long base = card->base; |
299 | u16 channel = port->channel; | 314 | u16 channel = port->channel; |
300 | 315 | ||
301 | if (!lock_card(card)) | 316 | if (WaitTillCardIsFree(base)) |
302 | return; | 317 | return; |
303 | 318 | ||
304 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); | 319 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); |
305 | outw(0x0404, base); | 320 | outw(0x0404, base); |
306 | InterruptTheCard(base); | 321 | InterruptTheCard(base); |
307 | port->status &= ~ISI_DTR; | 322 | port->status &= ~ISI_DTR; |
308 | unlock_card(card); | ||
309 | } | 323 | } |
310 | 324 | ||
325 | /* card->lock HAS to be held */ | ||
311 | static inline void raise_rts(struct isi_port *port) | 326 | static inline void raise_rts(struct isi_port *port) |
312 | { | 327 | { |
313 | struct isi_board *card = port->card; | 328 | struct isi_board *card = port->card; |
314 | unsigned long base = card->base; | 329 | unsigned long base = card->base; |
315 | u16 channel = port->channel; | 330 | u16 channel = port->channel; |
316 | 331 | ||
317 | if (!lock_card(card)) | 332 | if (WaitTillCardIsFree(base)) |
318 | return; | 333 | return; |
319 | 334 | ||
320 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); | 335 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); |
321 | outw(0x0a04, base); | 336 | outw(0x0a04, base); |
322 | InterruptTheCard(base); | 337 | InterruptTheCard(base); |
323 | port->status |= ISI_RTS; | 338 | port->status |= ISI_RTS; |
324 | unlock_card(card); | ||
325 | } | 339 | } |
340 | |||
341 | /* card->lock HAS to be held */ | ||
326 | static inline void drop_rts(struct isi_port *port) | 342 | static inline void drop_rts(struct isi_port *port) |
327 | { | 343 | { |
328 | struct isi_board *card = port->card; | 344 | struct isi_board *card = port->card; |
329 | unsigned long base = card->base; | 345 | unsigned long base = card->base; |
330 | u16 channel = port->channel; | 346 | u16 channel = port->channel; |
331 | 347 | ||
332 | if (!lock_card(card)) | 348 | if (WaitTillCardIsFree(base)) |
333 | return; | 349 | return; |
334 | 350 | ||
335 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); | 351 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); |
336 | outw(0x0804, base); | 352 | outw(0x0804, base); |
337 | InterruptTheCard(base); | 353 | InterruptTheCard(base); |
338 | port->status &= ~ISI_RTS; | 354 | port->status &= ~ISI_RTS; |
339 | unlock_card(card); | ||
340 | } | 355 | } |
341 | 356 | ||
357 | /* card->lock MUST NOT be held */ | ||
342 | static inline void raise_dtr_rts(struct isi_port *port) | 358 | static inline void raise_dtr_rts(struct isi_port *port) |
343 | { | 359 | { |
344 | struct isi_board *card = port->card; | 360 | struct isi_board *card = port->card; |
@@ -355,35 +371,20 @@ static inline void raise_dtr_rts(struct isi_port *port) | |||
355 | unlock_card(card); | 371 | unlock_card(card); |
356 | } | 372 | } |
357 | 373 | ||
374 | /* card->lock HAS to be held */ | ||
358 | static void drop_dtr_rts(struct isi_port *port) | 375 | static void drop_dtr_rts(struct isi_port *port) |
359 | { | 376 | { |
360 | struct isi_board *card = port->card; | 377 | struct isi_board *card = port->card; |
361 | unsigned long base = card->base; | 378 | unsigned long base = card->base; |
362 | u16 channel = port->channel; | 379 | u16 channel = port->channel; |
363 | 380 | ||
364 | if (!lock_card(card)) | 381 | if (WaitTillCardIsFree(base)) |
365 | return; | 382 | return; |
366 | 383 | ||
367 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); | 384 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); |
368 | outw(0x0c04, base); | 385 | outw(0x0c04, base); |
369 | InterruptTheCard(base); | 386 | InterruptTheCard(base); |
370 | port->status &= ~(ISI_RTS | ISI_DTR); | 387 | port->status &= ~(ISI_RTS | ISI_DTR); |
371 | unlock_card(card); | ||
372 | } | ||
373 | |||
374 | static inline void kill_queue(struct isi_port *port, short queue) | ||
375 | { | ||
376 | struct isi_board *card = port->card; | ||
377 | unsigned long base = card->base; | ||
378 | u16 channel = port->channel; | ||
379 | |||
380 | if (!lock_card(card)) | ||
381 | return; | ||
382 | |||
383 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); | ||
384 | outw((queue << 8) | 0x06, base); | ||
385 | InterruptTheCard(base); | ||
386 | unlock_card(card); | ||
387 | } | 388 | } |
388 | 389 | ||
389 | /* | 390 | /* |
@@ -744,7 +745,7 @@ static void isicom_config_port(struct isi_port *port) | |||
744 | else | 745 | else |
745 | raise_dtr(port); | 746 | raise_dtr(port); |
746 | 747 | ||
747 | if (lock_card(card)) { | 748 | if (WaitTillCardIsFree(base) == 0) { |
748 | outw(0x8000 | (channel << shift_count) |0x03, base); | 749 | outw(0x8000 | (channel << shift_count) |0x03, base); |
749 | outw(linuxb_to_isib[baud] << 8 | 0x03, base); | 750 | outw(linuxb_to_isib[baud] << 8 | 0x03, base); |
750 | channel_setup = 0; | 751 | channel_setup = 0; |
@@ -772,7 +773,6 @@ static void isicom_config_port(struct isi_port *port) | |||
772 | } | 773 | } |
773 | outw(channel_setup, base); | 774 | outw(channel_setup, base); |
774 | InterruptTheCard(base); | 775 | InterruptTheCard(base); |
775 | unlock_card(card); | ||
776 | } | 776 | } |
777 | if (C_CLOCAL(tty)) | 777 | if (C_CLOCAL(tty)) |
778 | port->flags &= ~ASYNC_CHECK_CD; | 778 | port->flags &= ~ASYNC_CHECK_CD; |
@@ -791,12 +791,11 @@ static void isicom_config_port(struct isi_port *port) | |||
791 | if (I_IXOFF(tty)) | 791 | if (I_IXOFF(tty)) |
792 | flow_ctrl |= ISICOM_INITIATE_XONXOFF; | 792 | flow_ctrl |= ISICOM_INITIATE_XONXOFF; |
793 | 793 | ||
794 | if (lock_card(card)) { | 794 | if (WaitTillCardIsFree(base) == 0) { |
795 | outw(0x8000 | (channel << shift_count) |0x04, base); | 795 | outw(0x8000 | (channel << shift_count) |0x04, base); |
796 | outw(flow_ctrl << 8 | 0x05, base); | 796 | outw(flow_ctrl << 8 | 0x05, base); |
797 | outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base); | 797 | outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base); |
798 | InterruptTheCard(base); | 798 | InterruptTheCard(base); |
799 | unlock_card(card); | ||
800 | } | 799 | } |
801 | 800 | ||
802 | /* rx enabled -> enable port for rx on the card */ | 801 | /* rx enabled -> enable port for rx on the card */ |
@@ -821,10 +820,9 @@ static inline void isicom_setup_board(struct isi_board *bp) | |||
821 | } | 820 | } |
822 | port = bp->ports; | 821 | port = bp->ports; |
823 | bp->status |= BOARD_ACTIVE; | 822 | bp->status |= BOARD_ACTIVE; |
824 | spin_unlock_irqrestore(&bp->card_lock, flags); | ||
825 | for (channel = 0; channel < bp->port_count; channel++, port++) | 823 | for (channel = 0; channel < bp->port_count; channel++, port++) |
826 | drop_dtr_rts(port); | 824 | drop_dtr_rts(port); |
827 | return; | 825 | spin_unlock_irqrestore(&bp->card_lock, flags); |
828 | } | 826 | } |
829 | 827 | ||
830 | static int isicom_setup_port(struct isi_port *port) | 828 | static int isicom_setup_port(struct isi_port *port) |
@@ -857,7 +855,12 @@ static int isicom_setup_port(struct isi_port *port) | |||
857 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; | 855 | port->xmit_cnt = port->xmit_head = port->xmit_tail = 0; |
858 | 856 | ||
859 | /* discard any residual data */ | 857 | /* discard any residual data */ |
860 | kill_queue(port, ISICOM_KILLTX | ISICOM_KILLRX); | 858 | if (WaitTillCardIsFree(card->base) == 0) { |
859 | outw(0x8000 | (port->channel << card->shift_count) | 0x02, | ||
860 | card->base); | ||
861 | outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base); | ||
862 | InterruptTheCard(card->base); | ||
863 | } | ||
861 | 864 | ||
862 | isicom_config_port(port); | 865 | isicom_config_port(port); |
863 | port->flags |= ASYNC_INITIALIZED; | 866 | port->flags |= ASYNC_INITIALIZED; |
@@ -983,28 +986,22 @@ static int isicom_open(struct tty_struct *tty, struct file *filp) | |||
983 | 986 | ||
984 | static inline void isicom_shutdown_board(struct isi_board *bp) | 987 | static inline void isicom_shutdown_board(struct isi_board *bp) |
985 | { | 988 | { |
986 | unsigned long flags; | ||
987 | |||
988 | spin_lock_irqsave(&bp->card_lock, flags); | ||
989 | if (bp->status & BOARD_ACTIVE) { | 989 | if (bp->status & BOARD_ACTIVE) { |
990 | bp->status &= ~BOARD_ACTIVE; | 990 | bp->status &= ~BOARD_ACTIVE; |
991 | } | 991 | } |
992 | spin_unlock_irqrestore(&bp->card_lock, flags); | ||
993 | } | 992 | } |
994 | 993 | ||
994 | /* card->lock HAS to be held */ | ||
995 | static void isicom_shutdown_port(struct isi_port *port) | 995 | static void isicom_shutdown_port(struct isi_port *port) |
996 | { | 996 | { |
997 | struct isi_board *card = port->card; | 997 | struct isi_board *card = port->card; |
998 | struct tty_struct *tty; | 998 | struct tty_struct *tty; |
999 | unsigned long flags; | ||
1000 | 999 | ||
1001 | tty = port->tty; | 1000 | tty = port->tty; |
1002 | 1001 | ||
1003 | spin_lock_irqsave(&card->card_lock, flags); | 1002 | if (!(port->flags & ASYNC_INITIALIZED)) |
1004 | if (!(port->flags & ASYNC_INITIALIZED)) { | ||
1005 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
1006 | return; | 1003 | return; |
1007 | } | 1004 | |
1008 | if (port->xmit_buf) { | 1005 | if (port->xmit_buf) { |
1009 | free_page((unsigned long) port->xmit_buf); | 1006 | free_page((unsigned long) port->xmit_buf); |
1010 | port->xmit_buf = NULL; | 1007 | port->xmit_buf = NULL; |
@@ -1012,7 +1009,6 @@ static void isicom_shutdown_port(struct isi_port *port) | |||
1012 | port->flags &= ~ASYNC_INITIALIZED; | 1009 | port->flags &= ~ASYNC_INITIALIZED; |
1013 | /* 3rd October 2000 : Vinayak P Risbud */ | 1010 | /* 3rd October 2000 : Vinayak P Risbud */ |
1014 | port->tty = NULL; | 1011 | port->tty = NULL; |
1015 | spin_unlock_irqrestore(&card->card_lock, flags); | ||
1016 | 1012 | ||
1017 | /*Fix done by Anil .S on 30-04-2001 | 1013 | /*Fix done by Anil .S on 30-04-2001 |
1018 | remote login through isi port has dtr toggle problem | 1014 | remote login through isi port has dtr toggle problem |
@@ -1258,10 +1254,12 @@ static int isicom_tiocmset(struct tty_struct *tty, struct file *file, | |||
1258 | unsigned int set, unsigned int clear) | 1254 | unsigned int set, unsigned int clear) |
1259 | { | 1255 | { |
1260 | struct isi_port *port = tty->driver_data; | 1256 | struct isi_port *port = tty->driver_data; |
1257 | unsigned long flags; | ||
1261 | 1258 | ||
1262 | if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) | 1259 | if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) |
1263 | return -ENODEV; | 1260 | return -ENODEV; |
1264 | 1261 | ||
1262 | spin_lock_irqsave(&port->card->card_lock, flags); | ||
1265 | if (set & TIOCM_RTS) | 1263 | if (set & TIOCM_RTS) |
1266 | raise_rts(port); | 1264 | raise_rts(port); |
1267 | if (set & TIOCM_DTR) | 1265 | if (set & TIOCM_DTR) |
@@ -1271,6 +1269,7 @@ static int isicom_tiocmset(struct tty_struct *tty, struct file *file, | |||
1271 | drop_rts(port); | 1269 | drop_rts(port); |
1272 | if (clear & TIOCM_DTR) | 1270 | if (clear & TIOCM_DTR) |
1273 | drop_dtr(port); | 1271 | drop_dtr(port); |
1272 | spin_unlock_irqrestore(&port->card->card_lock, flags); | ||
1274 | 1273 | ||
1275 | return 0; | 1274 | return 0; |
1276 | } | 1275 | } |
@@ -1303,7 +1302,10 @@ static int isicom_set_serial_info(struct isi_port *port, | |||
1303 | (newinfo.flags & ASYNC_FLAGS)); | 1302 | (newinfo.flags & ASYNC_FLAGS)); |
1304 | } | 1303 | } |
1305 | if (reconfig_port) { | 1304 | if (reconfig_port) { |
1305 | unsigned long flags; | ||
1306 | spin_lock_irqsave(&port->card->card_lock, flags); | ||
1306 | isicom_config_port(port); | 1307 | isicom_config_port(port); |
1308 | spin_unlock_irqrestore(&port->card->card_lock, flags); | ||
1307 | } | 1309 | } |
1308 | return 0; | 1310 | return 0; |
1309 | } | 1311 | } |
@@ -1384,6 +1386,7 @@ static void isicom_set_termios(struct tty_struct *tty, | |||
1384 | struct ktermios *old_termios) | 1386 | struct ktermios *old_termios) |
1385 | { | 1387 | { |
1386 | struct isi_port *port = tty->driver_data; | 1388 | struct isi_port *port = tty->driver_data; |
1389 | unsigned long flags; | ||
1387 | 1390 | ||
1388 | if (isicom_paranoia_check(port, tty->name, "isicom_set_termios")) | 1391 | if (isicom_paranoia_check(port, tty->name, "isicom_set_termios")) |
1389 | return; | 1392 | return; |
@@ -1392,7 +1395,9 @@ static void isicom_set_termios(struct tty_struct *tty, | |||
1392 | tty->termios->c_iflag == old_termios->c_iflag) | 1395 | tty->termios->c_iflag == old_termios->c_iflag) |
1393 | return; | 1396 | return; |
1394 | 1397 | ||
1398 | spin_lock_irqsave(&port->card->card_lock, flags); | ||
1395 | isicom_config_port(port); | 1399 | isicom_config_port(port); |
1400 | spin_unlock_irqrestore(&port->card->card_lock, flags); | ||
1396 | 1401 | ||
1397 | if ((old_termios->c_cflag & CRTSCTS) && | 1402 | if ((old_termios->c_cflag & CRTSCTS) && |
1398 | !(tty->termios->c_cflag & CRTSCTS)) { | 1403 | !(tty->termios->c_cflag & CRTSCTS)) { |
@@ -1469,11 +1474,15 @@ static void do_isicom_hangup(struct work_struct *work) | |||
1469 | static void isicom_hangup(struct tty_struct *tty) | 1474 | static void isicom_hangup(struct tty_struct *tty) |
1470 | { | 1475 | { |
1471 | struct isi_port *port = tty->driver_data; | 1476 | struct isi_port *port = tty->driver_data; |
1477 | unsigned long flags; | ||
1472 | 1478 | ||
1473 | if (isicom_paranoia_check(port, tty->name, "isicom_hangup")) | 1479 | if (isicom_paranoia_check(port, tty->name, "isicom_hangup")) |
1474 | return; | 1480 | return; |
1475 | 1481 | ||
1482 | spin_lock_irqsave(&port->card->card_lock, flags); | ||
1476 | isicom_shutdown_port(port); | 1483 | isicom_shutdown_port(port); |
1484 | spin_unlock_irqrestore(&port->card->card_lock, flags); | ||
1485 | |||
1477 | port->count = 0; | 1486 | port->count = 0; |
1478 | port->flags &= ~ASYNC_NORMAL_ACTIVE; | 1487 | port->flags &= ~ASYNC_NORMAL_ACTIVE; |
1479 | port->tty = NULL; | 1488 | port->tty = NULL; |
@@ -1578,16 +1587,6 @@ end: | |||
1578 | return retval; | 1587 | return retval; |
1579 | } | 1588 | } |
1580 | 1589 | ||
1581 | static inline int WaitTillCardIsFree(u16 base) | ||
1582 | { | ||
1583 | unsigned long count = 0; | ||
1584 | |||
1585 | while (!(inw(base + 0xe) & 0x1) && count++ < 100) | ||
1586 | msleep(5); | ||
1587 | |||
1588 | return !(inw(base + 0xe) & 0x1); | ||
1589 | } | ||
1590 | |||
1591 | static int __devinit load_firmware(struct pci_dev *pdev, | 1590 | static int __devinit load_firmware(struct pci_dev *pdev, |
1592 | const unsigned int index, const unsigned int signature) | 1591 | const unsigned int index, const unsigned int signature) |
1593 | { | 1592 | { |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 4f1813e04754..f5c160caf9f4 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -293,8 +293,8 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma) | |||
293 | { | 293 | { |
294 | unsigned long pfn; | 294 | unsigned long pfn; |
295 | 295 | ||
296 | /* Turn a pfn offset into an absolute pfn */ | 296 | /* Turn a kernel-virtual address into a physical page frame */ |
297 | pfn = PFN_DOWN(virt_to_phys((void *)PAGE_OFFSET)) + vma->vm_pgoff; | 297 | pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT; |
298 | 298 | ||
299 | /* | 299 | /* |
300 | * RED-PEN: on some architectures there is more mapped memory | 300 | * RED-PEN: on some architectures there is more mapped memory |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index c063359baf78..83f604b19290 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -717,6 +717,7 @@ static int mxser_init(void) | |||
717 | 717 | ||
718 | /* Initialize the tty_driver structure */ | 718 | /* Initialize the tty_driver structure */ |
719 | memset(mxvar_sdriver, 0, sizeof(struct tty_driver)); | 719 | memset(mxvar_sdriver, 0, sizeof(struct tty_driver)); |
720 | mxvar_sdriver->owner = THIS_MODULE; | ||
720 | mxvar_sdriver->magic = TTY_DRIVER_MAGIC; | 721 | mxvar_sdriver->magic = TTY_DRIVER_MAGIC; |
721 | mxvar_sdriver->name = "ttyMI"; | 722 | mxvar_sdriver->name = "ttyMI"; |
722 | mxvar_sdriver->major = ttymajor; | 723 | mxvar_sdriver->major = ttymajor; |
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c index cd989dce7c53..1bb030b3a51a 100644 --- a/drivers/char/mxser_new.c +++ b/drivers/char/mxser_new.c | |||
@@ -2690,6 +2690,7 @@ static int __init mxser_module_init(void) | |||
2690 | MXSER_VERSION); | 2690 | MXSER_VERSION); |
2691 | 2691 | ||
2692 | /* Initialize the tty_driver structure */ | 2692 | /* Initialize the tty_driver structure */ |
2693 | mxvar_sdriver->owner = THIS_MODULE; | ||
2693 | mxvar_sdriver->magic = TTY_DRIVER_MAGIC; | 2694 | mxvar_sdriver->magic = TTY_DRIVER_MAGIC; |
2694 | mxvar_sdriver->name = "ttyMI"; | 2695 | mxvar_sdriver->name = "ttyMI"; |
2695 | mxvar_sdriver->major = ttymajor; | 2696 | mxvar_sdriver->major = ttymajor; |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index e1d70e8b6268..664f36c98e6a 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -113,7 +113,12 @@ static int rtc_has_irq = 1; | |||
113 | #define hpet_set_rtc_irq_bit(arg) 0 | 113 | #define hpet_set_rtc_irq_bit(arg) 0 |
114 | #define hpet_rtc_timer_init() do { } while (0) | 114 | #define hpet_rtc_timer_init() do { } while (0) |
115 | #define hpet_rtc_dropped_irq() 0 | 115 | #define hpet_rtc_dropped_irq() 0 |
116 | static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) {return 0;} | 116 | #ifdef RTC_IRQ |
117 | static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) | ||
118 | { | ||
119 | return 0; | ||
120 | } | ||
121 | #endif | ||
117 | #else | 122 | #else |
118 | extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); | 123 | extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); |
119 | #endif | 124 | #endif |
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 13935235e066..7fd3cd5ddf21 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
@@ -215,7 +215,7 @@ static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty) | |||
215 | } | 215 | } |
216 | static struct sysrq_key_op sysrq_showstate_blocked_op = { | 216 | static struct sysrq_key_op sysrq_showstate_blocked_op = { |
217 | .handler = sysrq_handle_showstate_blocked, | 217 | .handler = sysrq_handle_showstate_blocked, |
218 | .help_msg = "showBlockedTasks", | 218 | .help_msg = "shoW-blocked-tasks", |
219 | .action_msg = "Show Blocked State", | 219 | .action_msg = "Show Blocked State", |
220 | .enable_mask = SYSRQ_ENABLE_DUMP, | 220 | .enable_mask = SYSRQ_ENABLE_DUMP, |
221 | }; | 221 | }; |
@@ -315,15 +315,16 @@ static struct sysrq_key_op *sysrq_key_table[36] = { | |||
315 | &sysrq_loglevel_op, /* 9 */ | 315 | &sysrq_loglevel_op, /* 9 */ |
316 | 316 | ||
317 | /* | 317 | /* |
318 | * Don't use for system provided sysrqs, it is handled specially on | 318 | * a: Don't use for system provided sysrqs, it is handled specially on |
319 | * sparc and will never arrive | 319 | * sparc and will never arrive. |
320 | */ | 320 | */ |
321 | NULL, /* a */ | 321 | NULL, /* a */ |
322 | &sysrq_reboot_op, /* b */ | 322 | &sysrq_reboot_op, /* b */ |
323 | &sysrq_crashdump_op, /* c */ | 323 | &sysrq_crashdump_op, /* c & ibm_emac driver debug */ |
324 | &sysrq_showlocks_op, /* d */ | 324 | &sysrq_showlocks_op, /* d */ |
325 | &sysrq_term_op, /* e */ | 325 | &sysrq_term_op, /* e */ |
326 | &sysrq_moom_op, /* f */ | 326 | &sysrq_moom_op, /* f */ |
327 | /* g: May be registered by ppc for kgdb */ | ||
327 | NULL, /* g */ | 328 | NULL, /* g */ |
328 | NULL, /* h */ | 329 | NULL, /* h */ |
329 | &sysrq_kill_op, /* i */ | 330 | &sysrq_kill_op, /* i */ |
@@ -332,18 +333,19 @@ static struct sysrq_key_op *sysrq_key_table[36] = { | |||
332 | NULL, /* l */ | 333 | NULL, /* l */ |
333 | &sysrq_showmem_op, /* m */ | 334 | &sysrq_showmem_op, /* m */ |
334 | &sysrq_unrt_op, /* n */ | 335 | &sysrq_unrt_op, /* n */ |
335 | /* This will often be registered as 'Off' at init time */ | 336 | /* o: This will often be registered as 'Off' at init time */ |
336 | NULL, /* o */ | 337 | NULL, /* o */ |
337 | &sysrq_showregs_op, /* p */ | 338 | &sysrq_showregs_op, /* p */ |
338 | NULL, /* q */ | 339 | NULL, /* q */ |
339 | &sysrq_unraw_op, /* r */ | 340 | &sysrq_unraw_op, /* r */ |
340 | &sysrq_sync_op, /* s */ | 341 | &sysrq_sync_op, /* s */ |
341 | &sysrq_showstate_op, /* t */ | 342 | &sysrq_showstate_op, /* t */ |
342 | &sysrq_mountro_op, /* u */ | 343 | &sysrq_mountro_op, /* u */ |
343 | /* May be assigned at init time by SMP VOYAGER */ | 344 | /* v: May be registered at init time by SMP VOYAGER */ |
344 | NULL, /* v */ | 345 | NULL, /* v */ |
345 | NULL, /* w */ | 346 | &sysrq_showstate_blocked_op, /* w */ |
346 | &sysrq_showstate_blocked_op, /* x */ | 347 | /* x: May be registered on ppc/powerpc for xmon */ |
348 | NULL, /* x */ | ||
347 | NULL, /* y */ | 349 | NULL, /* y */ |
348 | NULL /* z */ | 350 | NULL /* z */ |
349 | }; | 351 | }; |
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index 244d30a03fef..4fac2bdf6215 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c | |||
@@ -186,6 +186,7 @@ static int got_event; /* if events processing have been done */ | |||
186 | static void switchover_timeout(unsigned long data); | 186 | static void switchover_timeout(unsigned long data); |
187 | static struct timer_list switchover_timer = | 187 | static struct timer_list switchover_timer = |
188 | TIMER_INITIALIZER(switchover_timeout , 0, 0); | 188 | TIMER_INITIALIZER(switchover_timeout , 0, 0); |
189 | static unsigned long tlclk_timer_data; | ||
189 | 190 | ||
190 | static struct tlclk_alarms *alarm_events; | 191 | static struct tlclk_alarms *alarm_events; |
191 | 192 | ||
@@ -197,10 +198,19 @@ static irqreturn_t tlclk_interrupt(int irq, void *dev_id); | |||
197 | 198 | ||
198 | static DECLARE_WAIT_QUEUE_HEAD(wq); | 199 | static DECLARE_WAIT_QUEUE_HEAD(wq); |
199 | 200 | ||
201 | static unsigned long useflags; | ||
202 | static DEFINE_MUTEX(tlclk_mutex); | ||
203 | |||
200 | static int tlclk_open(struct inode *inode, struct file *filp) | 204 | static int tlclk_open(struct inode *inode, struct file *filp) |
201 | { | 205 | { |
202 | int result; | 206 | int result; |
203 | 207 | ||
208 | if (test_and_set_bit(0, &useflags)) | ||
209 | return -EBUSY; | ||
210 | /* this legacy device is always one per system and it doesn't | ||
211 | * know how to handle multiple concurrent clients. | ||
212 | */ | ||
213 | |||
204 | /* Make sure there is no interrupt pending while | 214 | /* Make sure there is no interrupt pending while |
205 | * initialising interrupt handler */ | 215 | * initialising interrupt handler */ |
206 | inb(TLCLK_REG6); | 216 | inb(TLCLK_REG6); |
@@ -221,6 +231,7 @@ static int tlclk_open(struct inode *inode, struct file *filp) | |||
221 | static int tlclk_release(struct inode *inode, struct file *filp) | 231 | static int tlclk_release(struct inode *inode, struct file *filp) |
222 | { | 232 | { |
223 | free_irq(telclk_interrupt, tlclk_interrupt); | 233 | free_irq(telclk_interrupt, tlclk_interrupt); |
234 | clear_bit(0, &useflags); | ||
224 | 235 | ||
225 | return 0; | 236 | return 0; |
226 | } | 237 | } |
@@ -230,26 +241,25 @@ static ssize_t tlclk_read(struct file *filp, char __user *buf, size_t count, | |||
230 | { | 241 | { |
231 | if (count < sizeof(struct tlclk_alarms)) | 242 | if (count < sizeof(struct tlclk_alarms)) |
232 | return -EIO; | 243 | return -EIO; |
244 | if (mutex_lock_interruptible(&tlclk_mutex)) | ||
245 | return -EINTR; | ||
246 | |||
233 | 247 | ||
234 | wait_event_interruptible(wq, got_event); | 248 | wait_event_interruptible(wq, got_event); |
235 | if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms))) | 249 | if (copy_to_user(buf, alarm_events, sizeof(struct tlclk_alarms))) { |
250 | mutex_unlock(&tlclk_mutex); | ||
236 | return -EFAULT; | 251 | return -EFAULT; |
252 | } | ||
237 | 253 | ||
238 | memset(alarm_events, 0, sizeof(struct tlclk_alarms)); | 254 | memset(alarm_events, 0, sizeof(struct tlclk_alarms)); |
239 | got_event = 0; | 255 | got_event = 0; |
240 | 256 | ||
257 | mutex_unlock(&tlclk_mutex); | ||
241 | return sizeof(struct tlclk_alarms); | 258 | return sizeof(struct tlclk_alarms); |
242 | } | 259 | } |
243 | 260 | ||
244 | static ssize_t tlclk_write(struct file *filp, const char __user *buf, size_t count, | ||
245 | loff_t *f_pos) | ||
246 | { | ||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | static const struct file_operations tlclk_fops = { | 261 | static const struct file_operations tlclk_fops = { |
251 | .read = tlclk_read, | 262 | .read = tlclk_read, |
252 | .write = tlclk_write, | ||
253 | .open = tlclk_open, | 263 | .open = tlclk_open, |
254 | .release = tlclk_release, | 264 | .release = tlclk_release, |
255 | 265 | ||
@@ -540,7 +550,7 @@ static ssize_t store_select_amcb1_transmit_clock(struct device *d, | |||
540 | SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7); | 550 | SET_PORT_BITS(TLCLK_REG3, 0xf8, 0x7); |
541 | switch (val) { | 551 | switch (val) { |
542 | case CLK_8_592MHz: | 552 | case CLK_8_592MHz: |
543 | SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); | 553 | SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); |
544 | break; | 554 | break; |
545 | case CLK_11_184MHz: | 555 | case CLK_11_184MHz: |
546 | SET_PORT_BITS(TLCLK_REG0, 0xfc, 0); | 556 | SET_PORT_BITS(TLCLK_REG0, 0xfc, 0); |
@@ -549,7 +559,7 @@ static ssize_t store_select_amcb1_transmit_clock(struct device *d, | |||
549 | SET_PORT_BITS(TLCLK_REG0, 0xfc, 3); | 559 | SET_PORT_BITS(TLCLK_REG0, 0xfc, 3); |
550 | break; | 560 | break; |
551 | case CLK_44_736MHz: | 561 | case CLK_44_736MHz: |
552 | SET_PORT_BITS(TLCLK_REG0, 0xfc, 2); | 562 | SET_PORT_BITS(TLCLK_REG0, 0xfc, 1); |
553 | break; | 563 | break; |
554 | } | 564 | } |
555 | } else | 565 | } else |
@@ -807,8 +817,6 @@ static int __init tlclk_init(void) | |||
807 | &tlclk_attribute_group); | 817 | &tlclk_attribute_group); |
808 | if (ret) { | 818 | if (ret) { |
809 | printk(KERN_ERR "tlclk: failed to create sysfs device attributes.\n"); | 819 | printk(KERN_ERR "tlclk: failed to create sysfs device attributes.\n"); |
810 | sysfs_remove_group(&tlclk_device->dev.kobj, | ||
811 | &tlclk_attribute_group); | ||
812 | goto out5; | 820 | goto out5; |
813 | } | 821 | } |
814 | 822 | ||
@@ -841,11 +849,13 @@ static void __exit tlclk_cleanup(void) | |||
841 | 849 | ||
842 | static void switchover_timeout(unsigned long data) | 850 | static void switchover_timeout(unsigned long data) |
843 | { | 851 | { |
844 | if ((data & 1)) { | 852 | unsigned long flags = *(unsigned long *) data; |
845 | if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08)) | 853 | |
854 | if ((flags & 1)) { | ||
855 | if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08)) | ||
846 | alarm_events->switchover_primary++; | 856 | alarm_events->switchover_primary++; |
847 | } else { | 857 | } else { |
848 | if ((inb(TLCLK_REG1) & 0x08) != (data & 0x08)) | 858 | if ((inb(TLCLK_REG1) & 0x08) != (flags & 0x08)) |
849 | alarm_events->switchover_secondary++; | 859 | alarm_events->switchover_secondary++; |
850 | } | 860 | } |
851 | 861 | ||
@@ -903,8 +913,9 @@ static irqreturn_t tlclk_interrupt(int irq, void *dev_id) | |||
903 | 913 | ||
904 | /* TIMEOUT in ~10ms */ | 914 | /* TIMEOUT in ~10ms */ |
905 | switchover_timer.expires = jiffies + msecs_to_jiffies(10); | 915 | switchover_timer.expires = jiffies + msecs_to_jiffies(10); |
906 | switchover_timer.data = inb(TLCLK_REG1); | 916 | tlclk_timer_data = inb(TLCLK_REG1); |
907 | add_timer(&switchover_timer); | 917 | switchover_timer.data = (unsigned long) &tlclk_timer_data; |
918 | mod_timer(&switchover_timer, switchover_timer.expires); | ||
908 | } else { | 919 | } else { |
909 | got_event = 1; | 920 | got_event = 1; |
910 | wake_up(&wq); | 921 | wake_up(&wq); |
diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index 0e0da443cbd5..8de6b95aeb84 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/tty_flip.h> | 42 | #include <linux/tty_flip.h> |
43 | #include <linux/sysrq.h> | 43 | #include <linux/sysrq.h> |
44 | 44 | ||
45 | #include <asm/firmware.h> | ||
45 | #include <asm/iseries/vio.h> | 46 | #include <asm/iseries/vio.h> |
46 | #include <asm/iseries/hv_lp_event.h> | 47 | #include <asm/iseries/hv_lp_event.h> |
47 | #include <asm/iseries/hv_call_event.h> | 48 | #include <asm/iseries/hv_call_event.h> |
@@ -1060,6 +1061,9 @@ static int __init viocons_init2(void) | |||
1060 | atomic_t wait_flag; | 1061 | atomic_t wait_flag; |
1061 | int rc; | 1062 | int rc; |
1062 | 1063 | ||
1064 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||
1065 | return -ENODEV; | ||
1066 | |||
1063 | /* +2 for fudge */ | 1067 | /* +2 for fudge */ |
1064 | rc = viopath_open(HvLpConfig_getPrimaryLpIndex(), | 1068 | rc = viopath_open(HvLpConfig_getPrimaryLpIndex(), |
1065 | viomajorsubtype_chario, VIOCHAR_WINDOW + 2); | 1069 | viomajorsubtype_chario, VIOCHAR_WINDOW + 2); |
@@ -1145,6 +1149,9 @@ static int __init viocons_init(void) | |||
1145 | { | 1149 | { |
1146 | int i; | 1150 | int i; |
1147 | 1151 | ||
1152 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||
1153 | return -ENODEV; | ||
1154 | |||
1148 | printk(VIOCONS_KERN_INFO "registering console\n"); | 1155 | printk(VIOCONS_KERN_INFO "registering console\n"); |
1149 | for (i = 0; i < VTTY_PORTS; i++) { | 1156 | for (i = 0; i < VTTY_PORTS; i++) { |
1150 | port_info[i].lp = HvLpIndexInvalid; | 1157 | port_info[i].lp = HvLpIndexInvalid; |
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 94d79cb8ce8d..9438512b17f1 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c | |||
@@ -49,7 +49,7 @@ | |||
49 | 49 | ||
50 | #include <asm/uaccess.h> | 50 | #include <asm/uaccess.h> |
51 | #include <asm/ioctls.h> | 51 | #include <asm/ioctls.h> |
52 | 52 | #include <asm/firmware.h> | |
53 | #include <asm/vio.h> | 53 | #include <asm/vio.h> |
54 | #include <asm/iseries/vio.h> | 54 | #include <asm/iseries/vio.h> |
55 | #include <asm/iseries/hv_lp_event.h> | 55 | #include <asm/iseries/hv_lp_event.h> |
@@ -997,6 +997,9 @@ int __init viotap_init(void) | |||
997 | int ret; | 997 | int ret; |
998 | struct proc_dir_entry *e; | 998 | struct proc_dir_entry *e; |
999 | 999 | ||
1000 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) | ||
1001 | return -ENODEV; | ||
1002 | |||
1000 | op_struct_list = NULL; | 1003 | op_struct_list = NULL; |
1001 | if ((ret = add_op_structs(VIOTAPE_MAXREQ)) < 0) { | 1004 | if ((ret = add_op_structs(VIOTAPE_MAXREQ)) < 0) { |
1002 | printk(VIOTAPE_KERN_WARN "couldn't allocate op structs\n"); | 1005 | printk(VIOTAPE_KERN_WARN "couldn't allocate op structs\n"); |
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c index a744dad9cf45..0cea8d4907df 100644 --- a/drivers/char/vr41xx_giu.c +++ b/drivers/char/vr41xx_giu.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2002 MontaVista Software Inc. | 4 | * Copyright (C) 2002 MontaVista Software Inc. |
5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> | 5 | * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> |
6 | * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 6 | * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -125,30 +125,17 @@ static inline uint16_t giu_clear(uint16_t offset, uint16_t clear) | |||
125 | return data; | 125 | return data; |
126 | } | 126 | } |
127 | 127 | ||
128 | static unsigned int startup_giuint_low_irq(unsigned int irq) | 128 | static void ack_giuint_low(unsigned int irq) |
129 | { | 129 | { |
130 | unsigned int pin; | 130 | giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); |
131 | |||
132 | pin = GPIO_PIN_OF_IRQ(irq); | ||
133 | giu_write(GIUINTSTATL, 1 << pin); | ||
134 | giu_set(GIUINTENL, 1 << pin); | ||
135 | |||
136 | return 0; | ||
137 | } | 131 | } |
138 | 132 | ||
139 | static void shutdown_giuint_low_irq(unsigned int irq) | 133 | static void mask_giuint_low(unsigned int irq) |
140 | { | 134 | { |
141 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | 135 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); |
142 | } | 136 | } |
143 | 137 | ||
144 | static void enable_giuint_low_irq(unsigned int irq) | 138 | static void mask_ack_giuint_low(unsigned int irq) |
145 | { | ||
146 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
147 | } | ||
148 | |||
149 | #define disable_giuint_low_irq shutdown_giuint_low_irq | ||
150 | |||
151 | static void ack_giuint_low_irq(unsigned int irq) | ||
152 | { | 139 | { |
153 | unsigned int pin; | 140 | unsigned int pin; |
154 | 141 | ||
@@ -157,46 +144,30 @@ static void ack_giuint_low_irq(unsigned int irq) | |||
157 | giu_write(GIUINTSTATL, 1 << pin); | 144 | giu_write(GIUINTSTATL, 1 << pin); |
158 | } | 145 | } |
159 | 146 | ||
160 | static void end_giuint_low_irq(unsigned int irq) | 147 | static void unmask_giuint_low(unsigned int irq) |
161 | { | 148 | { |
162 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) | 149 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); |
163 | giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
164 | } | 150 | } |
165 | 151 | ||
166 | static struct hw_interrupt_type giuint_low_irq_type = { | 152 | static struct irq_chip giuint_low_irq_chip = { |
167 | .typename = "GIUINTL", | 153 | .name = "GIUINTL", |
168 | .startup = startup_giuint_low_irq, | 154 | .ack = ack_giuint_low, |
169 | .shutdown = shutdown_giuint_low_irq, | 155 | .mask = mask_giuint_low, |
170 | .enable = enable_giuint_low_irq, | 156 | .mask_ack = mask_ack_giuint_low, |
171 | .disable = disable_giuint_low_irq, | 157 | .unmask = unmask_giuint_low, |
172 | .ack = ack_giuint_low_irq, | ||
173 | .end = end_giuint_low_irq, | ||
174 | }; | 158 | }; |
175 | 159 | ||
176 | static unsigned int startup_giuint_high_irq(unsigned int irq) | 160 | static void ack_giuint_high(unsigned int irq) |
177 | { | 161 | { |
178 | unsigned int pin; | 162 | giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); |
179 | |||
180 | pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; | ||
181 | giu_write(GIUINTSTATH, 1 << pin); | ||
182 | giu_set(GIUINTENH, 1 << pin); | ||
183 | |||
184 | return 0; | ||
185 | } | 163 | } |
186 | 164 | ||
187 | static void shutdown_giuint_high_irq(unsigned int irq) | 165 | static void mask_giuint_high(unsigned int irq) |
188 | { | 166 | { |
189 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | 167 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); |
190 | } | 168 | } |
191 | 169 | ||
192 | static void enable_giuint_high_irq(unsigned int irq) | 170 | static void mask_ack_giuint_high(unsigned int irq) |
193 | { | ||
194 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
195 | } | ||
196 | |||
197 | #define disable_giuint_high_irq shutdown_giuint_high_irq | ||
198 | |||
199 | static void ack_giuint_high_irq(unsigned int irq) | ||
200 | { | 171 | { |
201 | unsigned int pin; | 172 | unsigned int pin; |
202 | 173 | ||
@@ -205,20 +176,17 @@ static void ack_giuint_high_irq(unsigned int irq) | |||
205 | giu_write(GIUINTSTATH, 1 << pin); | 176 | giu_write(GIUINTSTATH, 1 << pin); |
206 | } | 177 | } |
207 | 178 | ||
208 | static void end_giuint_high_irq(unsigned int irq) | 179 | static void unmask_giuint_high(unsigned int irq) |
209 | { | 180 | { |
210 | if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) | 181 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); |
211 | giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
212 | } | 182 | } |
213 | 183 | ||
214 | static struct hw_interrupt_type giuint_high_irq_type = { | 184 | static struct irq_chip giuint_high_irq_chip = { |
215 | .typename = "GIUINTH", | 185 | .name = "GIUINTH", |
216 | .startup = startup_giuint_high_irq, | 186 | .ack = ack_giuint_high, |
217 | .shutdown = shutdown_giuint_high_irq, | 187 | .mask = mask_giuint_high, |
218 | .enable = enable_giuint_high_irq, | 188 | .mask_ack = mask_ack_giuint_high, |
219 | .disable = disable_giuint_high_irq, | 189 | .unmask = unmask_giuint_high, |
220 | .ack = ack_giuint_high_irq, | ||
221 | .end = end_giuint_high_irq, | ||
222 | }; | 190 | }; |
223 | 191 | ||
224 | static int giu_get_irq(unsigned int irq) | 192 | static int giu_get_irq(unsigned int irq) |
@@ -282,9 +250,15 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ | |||
282 | break; | 250 | break; |
283 | } | 251 | } |
284 | } | 252 | } |
253 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
254 | &giuint_low_irq_chip, | ||
255 | handle_edge_irq); | ||
285 | } else { | 256 | } else { |
286 | giu_clear(GIUINTTYPL, mask); | 257 | giu_clear(GIUINTTYPL, mask); |
287 | giu_clear(GIUINTHTSELL, mask); | 258 | giu_clear(GIUINTHTSELL, mask); |
259 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
260 | &giuint_low_irq_chip, | ||
261 | handle_level_irq); | ||
288 | } | 262 | } |
289 | giu_write(GIUINTSTATL, mask); | 263 | giu_write(GIUINTSTATL, mask); |
290 | } else if (pin < GIUINT_HIGH_MAX) { | 264 | } else if (pin < GIUINT_HIGH_MAX) { |
@@ -311,9 +285,15 @@ void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_ | |||
311 | break; | 285 | break; |
312 | } | 286 | } |
313 | } | 287 | } |
288 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
289 | &giuint_high_irq_chip, | ||
290 | handle_edge_irq); | ||
314 | } else { | 291 | } else { |
315 | giu_clear(GIUINTTYPH, mask); | 292 | giu_clear(GIUINTTYPH, mask); |
316 | giu_clear(GIUINTHTSELH, mask); | 293 | giu_clear(GIUINTHTSELH, mask); |
294 | set_irq_chip_and_handler(GIU_IRQ(pin), | ||
295 | &giuint_high_irq_chip, | ||
296 | handle_level_irq); | ||
317 | } | 297 | } |
318 | giu_write(GIUINTSTATH, mask); | 298 | giu_write(GIUINTSTATH, mask); |
319 | } | 299 | } |
@@ -617,10 +597,11 @@ static const struct file_operations gpio_fops = { | |||
617 | static int __devinit giu_probe(struct platform_device *dev) | 597 | static int __devinit giu_probe(struct platform_device *dev) |
618 | { | 598 | { |
619 | unsigned long start, size, flags = 0; | 599 | unsigned long start, size, flags = 0; |
620 | unsigned int nr_pins = 0; | 600 | unsigned int nr_pins = 0, trigger, i, pin; |
621 | struct resource *res1, *res2 = NULL; | 601 | struct resource *res1, *res2 = NULL; |
622 | void *base; | 602 | void *base; |
623 | int retval, i; | 603 | struct irq_chip *chip; |
604 | int retval; | ||
624 | 605 | ||
625 | switch (current_cpu_data.cputype) { | 606 | switch (current_cpu_data.cputype) { |
626 | case CPU_VR4111: | 607 | case CPU_VR4111: |
@@ -688,11 +669,20 @@ static int __devinit giu_probe(struct platform_device *dev) | |||
688 | giu_write(GIUINTENL, 0); | 669 | giu_write(GIUINTENL, 0); |
689 | giu_write(GIUINTENH, 0); | 670 | giu_write(GIUINTENH, 0); |
690 | 671 | ||
672 | trigger = giu_read(GIUINTTYPH) << 16; | ||
673 | trigger |= giu_read(GIUINTTYPL); | ||
691 | for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { | 674 | for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { |
692 | if (i < GIU_IRQ(GIUINT_HIGH_OFFSET)) | 675 | pin = GPIO_PIN_OF_IRQ(i); |
693 | irq_desc[i].chip = &giuint_low_irq_type; | 676 | if (pin < GIUINT_HIGH_OFFSET) |
677 | chip = &giuint_low_irq_chip; | ||
694 | else | 678 | else |
695 | irq_desc[i].chip = &giuint_high_irq_type; | 679 | chip = &giuint_high_irq_chip; |
680 | |||
681 | if (trigger & (1 << pin)) | ||
682 | set_irq_chip_and_handler(i, chip, handle_edge_irq); | ||
683 | else | ||
684 | set_irq_chip_and_handler(i, chip, handle_level_irq); | ||
685 | |||
696 | } | 686 | } |
697 | 687 | ||
698 | return cascade_irq(GIUINT_IRQ, giu_get_irq); | 688 | return cascade_irq(GIUINT_IRQ, giu_get_irq); |