diff options
Diffstat (limited to 'drivers')
227 files changed, 9010 insertions, 2752 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 48f446d3c671..283c089537bc 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
@@ -44,6 +44,8 @@ source "drivers/char/Kconfig" | |||
44 | 44 | ||
45 | source "drivers/i2c/Kconfig" | 45 | source "drivers/i2c/Kconfig" |
46 | 46 | ||
47 | source "drivers/spi/Kconfig" | ||
48 | |||
47 | source "drivers/w1/Kconfig" | 49 | source "drivers/w1/Kconfig" |
48 | 50 | ||
49 | source "drivers/hwmon/Kconfig" | 51 | source "drivers/hwmon/Kconfig" |
diff --git a/drivers/Makefile b/drivers/Makefile index 7fc3f0f08b29..7c45050ecd03 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -41,6 +41,7 @@ obj-$(CONFIG_FUSION) += message/ | |||
41 | obj-$(CONFIG_IEEE1394) += ieee1394/ | 41 | obj-$(CONFIG_IEEE1394) += ieee1394/ |
42 | obj-y += cdrom/ | 42 | obj-y += cdrom/ |
43 | obj-$(CONFIG_MTD) += mtd/ | 43 | obj-$(CONFIG_MTD) += mtd/ |
44 | obj-$(CONFIG_SPI) += spi/ | ||
44 | obj-$(CONFIG_PCCARD) += pcmcia/ | 45 | obj-$(CONFIG_PCCARD) += pcmcia/ |
45 | obj-$(CONFIG_DIO) += dio/ | 46 | obj-$(CONFIG_DIO) += dio/ |
46 | obj-$(CONFIG_SBUS) += sbus/ | 47 | obj-$(CONFIG_SBUS) += sbus/ |
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 2b905016664d..730a9ce0a14a 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
@@ -78,7 +78,13 @@ int driver_probe_device(struct device_driver * drv, struct device * dev) | |||
78 | pr_debug("%s: Matched Device %s with Driver %s\n", | 78 | pr_debug("%s: Matched Device %s with Driver %s\n", |
79 | drv->bus->name, dev->bus_id, drv->name); | 79 | drv->bus->name, dev->bus_id, drv->name); |
80 | dev->driver = drv; | 80 | dev->driver = drv; |
81 | if (drv->probe) { | 81 | if (dev->bus->probe) { |
82 | ret = dev->bus->probe(dev); | ||
83 | if (ret) { | ||
84 | dev->driver = NULL; | ||
85 | goto ProbeFailed; | ||
86 | } | ||
87 | } else if (drv->probe) { | ||
82 | ret = drv->probe(dev); | 88 | ret = drv->probe(dev); |
83 | if (ret) { | 89 | if (ret) { |
84 | dev->driver = NULL; | 90 | dev->driver = NULL; |
@@ -203,7 +209,9 @@ static void __device_release_driver(struct device * dev) | |||
203 | sysfs_remove_link(&dev->kobj, "driver"); | 209 | sysfs_remove_link(&dev->kobj, "driver"); |
204 | klist_remove(&dev->knode_driver); | 210 | klist_remove(&dev->knode_driver); |
205 | 211 | ||
206 | if (drv->remove) | 212 | if (dev->bus->remove) |
213 | dev->bus->remove(dev); | ||
214 | else if (drv->remove) | ||
207 | drv->remove(dev); | 215 | drv->remove(dev); |
208 | dev->driver = NULL; | 216 | dev->driver = NULL; |
209 | put_driver(drv); | 217 | put_driver(drv); |
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 161f3a390d90..b400314e1c62 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
@@ -171,6 +171,11 @@ static void klist_devices_put(struct klist_node *n) | |||
171 | */ | 171 | */ |
172 | int driver_register(struct device_driver * drv) | 172 | int driver_register(struct device_driver * drv) |
173 | { | 173 | { |
174 | if ((drv->bus->probe && drv->probe) || | ||
175 | (drv->bus->remove && drv->remove) || | ||
176 | (drv->bus->shutdown && drv->shutdown)) { | ||
177 | printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name); | ||
178 | } | ||
174 | klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put); | 179 | klist_init(&drv->klist_devices, klist_devices_get, klist_devices_put); |
175 | init_completion(&drv->unloaded); | 180 | init_completion(&drv->unloaded); |
176 | return bus_add_driver(drv); | 181 | return bus_add_driver(drv); |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 0f81731bdfa8..461554a02517 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -327,7 +327,7 @@ EXPORT_SYMBOL_GPL(platform_device_register); | |||
327 | * @pdev: platform device we're unregistering | 327 | * @pdev: platform device we're unregistering |
328 | * | 328 | * |
329 | * Unregistration is done in 2 steps. Fisrt we release all resources | 329 | * Unregistration is done in 2 steps. Fisrt we release all resources |
330 | * and remove it from the sybsystem, then we drop reference count by | 330 | * and remove it from the subsystem, then we drop reference count by |
331 | * calling platform_device_put(). | 331 | * calling platform_device_put(). |
332 | */ | 332 | */ |
333 | void platform_device_unregister(struct platform_device * pdev) | 333 | void platform_device_unregister(struct platform_device * pdev) |
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c index f50a08be424b..c2475f3134ea 100644 --- a/drivers/base/power/shutdown.c +++ b/drivers/base/power/shutdown.c | |||
@@ -35,12 +35,15 @@ extern int sysdev_shutdown(void); | |||
35 | */ | 35 | */ |
36 | void device_shutdown(void) | 36 | void device_shutdown(void) |
37 | { | 37 | { |
38 | struct device * dev; | 38 | struct device * dev, *devn; |
39 | 39 | ||
40 | down_write(&devices_subsys.rwsem); | 40 | down_write(&devices_subsys.rwsem); |
41 | list_for_each_entry_reverse(dev, &devices_subsys.kset.list, | 41 | list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list, |
42 | kobj.entry) { | 42 | kobj.entry) { |
43 | if (dev->driver && dev->driver->shutdown) { | 43 | if (dev->bus && dev->bus->shutdown) { |
44 | dev_dbg(dev, "shutdown\n"); | ||
45 | dev->bus->shutdown(dev); | ||
46 | } else if (dev->driver && dev->driver->shutdown) { | ||
44 | dev_dbg(dev, "shutdown\n"); | 47 | dev_dbg(dev, "shutdown\n"); |
45 | dev->driver->shutdown(dev); | 48 | dev->driver->shutdown(dev); |
46 | } | 49 | } |
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 3c679d30b698..b6e290956214 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c | |||
@@ -194,6 +194,8 @@ static DECLARE_WAIT_QUEUE_HEAD(ms_wait); | |||
194 | */ | 194 | */ |
195 | #define MAX_ERRORS 12 | 195 | #define MAX_ERRORS 12 |
196 | 196 | ||
197 | #define custom amiga_custom | ||
198 | |||
197 | /* Prevent "aliased" accesses. */ | 199 | /* Prevent "aliased" accesses. */ |
198 | static int fd_ref[4] = { 0,0,0,0 }; | 200 | static int fd_ref[4] = { 0,0,0,0 }; |
199 | static int fd_device[4] = { 0, 0, 0, 0 }; | 201 | static int fd_device[4] = { 0, 0, 0, 0 }; |
@@ -1439,6 +1441,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, | |||
1439 | { | 1441 | { |
1440 | int drive = iminor(inode) & 3; | 1442 | int drive = iminor(inode) & 3; |
1441 | static struct floppy_struct getprm; | 1443 | static struct floppy_struct getprm; |
1444 | void __user *argp = (void __user *)param; | ||
1442 | 1445 | ||
1443 | switch(cmd){ | 1446 | switch(cmd){ |
1444 | case FDFMTBEG: | 1447 | case FDFMTBEG: |
@@ -1484,9 +1487,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, | |||
1484 | getprm.head=unit[drive].type->heads; | 1487 | getprm.head=unit[drive].type->heads; |
1485 | getprm.sect=unit[drive].dtype->sects * unit[drive].type->sect_mult; | 1488 | getprm.sect=unit[drive].dtype->sects * unit[drive].type->sect_mult; |
1486 | getprm.size=unit[drive].blocks; | 1489 | getprm.size=unit[drive].blocks; |
1487 | if (copy_to_user((void *)param, | 1490 | if (copy_to_user(argp, &getprm, sizeof(struct floppy_struct))) |
1488 | (void *)&getprm, | ||
1489 | sizeof(struct floppy_struct))) | ||
1490 | return -EFAULT; | 1491 | return -EFAULT; |
1491 | break; | 1492 | break; |
1492 | case FDSETPRM: | 1493 | case FDSETPRM: |
@@ -1498,8 +1499,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, | |||
1498 | break; | 1499 | break; |
1499 | #ifdef RAW_IOCTL | 1500 | #ifdef RAW_IOCTL |
1500 | case IOCTL_RAW_TRACK: | 1501 | case IOCTL_RAW_TRACK: |
1501 | if (copy_to_user((void *)param, raw_buf, | 1502 | if (copy_to_user(argp, raw_buf, unit[drive].type->read_size)) |
1502 | unit[drive].type->read_size)) | ||
1503 | return -EFAULT; | 1503 | return -EFAULT; |
1504 | else | 1504 | else |
1505 | return unit[drive].type->read_size; | 1505 | return unit[drive].type->read_size; |
@@ -1654,12 +1654,6 @@ static struct block_device_operations floppy_fops = { | |||
1654 | .media_changed = amiga_floppy_change, | 1654 | .media_changed = amiga_floppy_change, |
1655 | }; | 1655 | }; |
1656 | 1656 | ||
1657 | void __init amiga_floppy_setup (char *str, int *ints) | ||
1658 | { | ||
1659 | printk (KERN_INFO "amiflop: Setting default df0 to %x\n", ints[1]); | ||
1660 | fd_def_df0 = ints[1]; | ||
1661 | } | ||
1662 | |||
1663 | static int __init fd_probe_drives(void) | 1657 | static int __init fd_probe_drives(void) |
1664 | { | 1658 | { |
1665 | int drive,drives,nomem; | 1659 | int drive,drives,nomem; |
@@ -1845,4 +1839,18 @@ void cleanup_module(void) | |||
1845 | unregister_blkdev(FLOPPY_MAJOR, "fd"); | 1839 | unregister_blkdev(FLOPPY_MAJOR, "fd"); |
1846 | } | 1840 | } |
1847 | #endif | 1841 | #endif |
1842 | |||
1843 | #else | ||
1844 | static int __init amiga_floppy_setup (char *str) | ||
1845 | { | ||
1846 | int n; | ||
1847 | if (!MACH_IS_AMIGA) | ||
1848 | return 0; | ||
1849 | if (!get_option(&str, &n)) | ||
1850 | return 0; | ||
1851 | printk (KERN_INFO "amiflop: Setting default df0 to %x\n", n); | ||
1852 | fd_def_df0 = n; | ||
1853 | } | ||
1854 | |||
1855 | __setup("floppy=", amiga_floppy_setup); | ||
1848 | #endif | 1856 | #endif |
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 3aa68a5447d6..f8ce235ccfc3 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c | |||
@@ -1361,7 +1361,7 @@ static int floppy_revalidate(struct gendisk *disk) | |||
1361 | formats, for 'permanent user-defined' parameter: | 1361 | formats, for 'permanent user-defined' parameter: |
1362 | restore default_params[] here if flagged valid! */ | 1362 | restore default_params[] here if flagged valid! */ |
1363 | if (default_params[drive].blocks == 0) | 1363 | if (default_params[drive].blocks == 0) |
1364 | UDT = 0; | 1364 | UDT = NULL; |
1365 | else | 1365 | else |
1366 | UDT = &default_params[drive]; | 1366 | UDT = &default_params[drive]; |
1367 | } | 1367 | } |
@@ -1495,6 +1495,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, | |||
1495 | struct floppy_struct getprm; | 1495 | struct floppy_struct getprm; |
1496 | int settype; | 1496 | int settype; |
1497 | struct floppy_struct setprm; | 1497 | struct floppy_struct setprm; |
1498 | void __user *argp = (void __user *)param; | ||
1498 | 1499 | ||
1499 | switch (cmd) { | 1500 | switch (cmd) { |
1500 | case FDGETPRM: | 1501 | case FDGETPRM: |
@@ -1521,7 +1522,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, | |||
1521 | getprm.head = 2; | 1522 | getprm.head = 2; |
1522 | getprm.track = dtp->blocks/dtp->spt/2; | 1523 | getprm.track = dtp->blocks/dtp->spt/2; |
1523 | getprm.stretch = dtp->stretch; | 1524 | getprm.stretch = dtp->stretch; |
1524 | if (copy_to_user((void *)param, &getprm, sizeof(getprm))) | 1525 | if (copy_to_user(argp, &getprm, sizeof(getprm))) |
1525 | return -EFAULT; | 1526 | return -EFAULT; |
1526 | return 0; | 1527 | return 0; |
1527 | } | 1528 | } |
@@ -1540,7 +1541,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, | |||
1540 | /* get the parameters from user space */ | 1541 | /* get the parameters from user space */ |
1541 | if (floppy->ref != 1 && floppy->ref != -1) | 1542 | if (floppy->ref != 1 && floppy->ref != -1) |
1542 | return -EBUSY; | 1543 | return -EBUSY; |
1543 | if (copy_from_user(&setprm, (void *) param, sizeof(setprm))) | 1544 | if (copy_from_user(&setprm, argp, sizeof(setprm))) |
1544 | return -EFAULT; | 1545 | return -EFAULT; |
1545 | /* | 1546 | /* |
1546 | * first of all: check for floppy change and revalidate, | 1547 | * first of all: check for floppy change and revalidate, |
@@ -1647,7 +1648,7 @@ static int fd_ioctl(struct inode *inode, struct file *filp, | |||
1647 | case FDFMTTRK: | 1648 | case FDFMTTRK: |
1648 | if (floppy->ref != 1 && floppy->ref != -1) | 1649 | if (floppy->ref != 1 && floppy->ref != -1) |
1649 | return -EBUSY; | 1650 | return -EBUSY; |
1650 | if (copy_from_user(&fmt_desc, (void *) param, sizeof(fmt_desc))) | 1651 | if (copy_from_user(&fmt_desc, argp, sizeof(fmt_desc))) |
1651 | return -EFAULT; | 1652 | return -EFAULT; |
1652 | return do_format(drive, type, &fmt_desc); | 1653 | return do_format(drive, type, &fmt_desc); |
1653 | case FDCLRPRM: | 1654 | case FDCLRPRM: |
@@ -1950,14 +1951,20 @@ Enomem: | |||
1950 | return -ENOMEM; | 1951 | return -ENOMEM; |
1951 | } | 1952 | } |
1952 | 1953 | ||
1953 | 1954 | #ifndef MODULE | |
1954 | void __init atari_floppy_setup( char *str, int *ints ) | 1955 | static int __init atari_floppy_setup(char *str) |
1955 | { | 1956 | { |
1957 | int ints[3 + FD_MAX_UNITS]; | ||
1956 | int i; | 1958 | int i; |
1959 | |||
1960 | if (!MACH_IS_ATARI) | ||
1961 | return 0; | ||
1962 | |||
1963 | str = get_options(str, 3 + FD_MAX_UNITS, ints); | ||
1957 | 1964 | ||
1958 | if (ints[0] < 1) { | 1965 | if (ints[0] < 1) { |
1959 | printk(KERN_ERR "ataflop_setup: no arguments!\n" ); | 1966 | printk(KERN_ERR "ataflop_setup: no arguments!\n" ); |
1960 | return; | 1967 | return 0; |
1961 | } | 1968 | } |
1962 | else if (ints[0] > 2+FD_MAX_UNITS) { | 1969 | else if (ints[0] > 2+FD_MAX_UNITS) { |
1963 | printk(KERN_ERR "ataflop_setup: too many arguments\n" ); | 1970 | printk(KERN_ERR "ataflop_setup: too many arguments\n" ); |
@@ -1977,9 +1984,13 @@ void __init atari_floppy_setup( char *str, int *ints ) | |||
1977 | else | 1984 | else |
1978 | UserSteprate[i-3] = ints[i]; | 1985 | UserSteprate[i-3] = ints[i]; |
1979 | } | 1986 | } |
1987 | return 1; | ||
1980 | } | 1988 | } |
1981 | 1989 | ||
1982 | static void atari_floppy_exit(void) | 1990 | __setup("floppy=", atari_floppy_setup); |
1991 | #endif | ||
1992 | |||
1993 | static void __exit atari_floppy_exit(void) | ||
1983 | { | 1994 | { |
1984 | int i; | 1995 | int i; |
1985 | blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); | 1996 | blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); |
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index d1aaf31bd97e..f63e07bd9f9c 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c | |||
@@ -293,6 +293,7 @@ static int send_request(struct request *req) | |||
293 | u16 viocmd; | 293 | u16 viocmd; |
294 | HvLpEvent_Rc hvrc; | 294 | HvLpEvent_Rc hvrc; |
295 | struct vioblocklpevent *bevent; | 295 | struct vioblocklpevent *bevent; |
296 | struct HvLpEvent *hev; | ||
296 | struct scatterlist sg[VIOMAXBLOCKDMA]; | 297 | struct scatterlist sg[VIOMAXBLOCKDMA]; |
297 | int sgindex; | 298 | int sgindex; |
298 | int statindex; | 299 | int statindex; |
@@ -347,22 +348,19 @@ static int send_request(struct request *req) | |||
347 | * token so we can match the response up later | 348 | * token so we can match the response up later |
348 | */ | 349 | */ |
349 | memset(bevent, 0, sizeof(struct vioblocklpevent)); | 350 | memset(bevent, 0, sizeof(struct vioblocklpevent)); |
350 | bevent->event.xFlags.xValid = 1; | 351 | hev = &bevent->event; |
351 | bevent->event.xFlags.xFunction = HvLpEvent_Function_Int; | 352 | hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DO_ACK | |
352 | bevent->event.xFlags.xAckInd = HvLpEvent_AckInd_DoAck; | 353 | HV_LP_EVENT_INT; |
353 | bevent->event.xFlags.xAckType = HvLpEvent_AckType_ImmediateAck; | 354 | hev->xType = HvLpEvent_Type_VirtualIo; |
354 | bevent->event.xType = HvLpEvent_Type_VirtualIo; | 355 | hev->xSubtype = viocmd; |
355 | bevent->event.xSubtype = viocmd; | 356 | hev->xSourceLp = HvLpConfig_getLpIndex(); |
356 | bevent->event.xSourceLp = HvLpConfig_getLpIndex(); | 357 | hev->xTargetLp = viopath_hostLp; |
357 | bevent->event.xTargetLp = viopath_hostLp; | 358 | hev->xSizeMinus1 = |
358 | bevent->event.xSizeMinus1 = | ||
359 | offsetof(struct vioblocklpevent, u.rw_data.dma_info) + | 359 | offsetof(struct vioblocklpevent, u.rw_data.dma_info) + |
360 | (sizeof(bevent->u.rw_data.dma_info[0]) * nsg) - 1; | 360 | (sizeof(bevent->u.rw_data.dma_info[0]) * nsg) - 1; |
361 | bevent->event.xSourceInstanceId = | 361 | hev->xSourceInstanceId = viopath_sourceinst(viopath_hostLp); |
362 | viopath_sourceinst(viopath_hostLp); | 362 | hev->xTargetInstanceId = viopath_targetinst(viopath_hostLp); |
363 | bevent->event.xTargetInstanceId = | 363 | hev->xCorrelationToken = (u64)req; |
364 | viopath_targetinst(viopath_hostLp); | ||
365 | bevent->event.xCorrelationToken = (u64)req; | ||
366 | bevent->version = VIOVERSION; | 364 | bevent->version = VIOVERSION; |
367 | bevent->disk = DEVICE_NO(d); | 365 | bevent->disk = DEVICE_NO(d); |
368 | bevent->u.rw_data.offset = start; | 366 | bevent->u.rw_data.offset = start; |
@@ -649,10 +647,10 @@ static void handle_block_event(struct HvLpEvent *event) | |||
649 | /* Notification that a partition went away! */ | 647 | /* Notification that a partition went away! */ |
650 | return; | 648 | return; |
651 | /* First, we should NEVER get an int here...only acks */ | 649 | /* First, we should NEVER get an int here...only acks */ |
652 | if (event->xFlags.xFunction == HvLpEvent_Function_Int) { | 650 | if (hvlpevent_is_int(event)) { |
653 | printk(VIOD_KERN_WARNING | 651 | printk(VIOD_KERN_WARNING |
654 | "Yikes! got an int in viodasd event handler!\n"); | 652 | "Yikes! got an int in viodasd event handler!\n"); |
655 | if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { | 653 | if (hvlpevent_need_ack(event)) { |
656 | event->xRc = HvLpEvent_Rc_InvalidSubtype; | 654 | event->xRc = HvLpEvent_Rc_InvalidSubtype; |
657 | HvCallEvent_ackLpEvent(event); | 655 | HvCallEvent_ackLpEvent(event); |
658 | } | 656 | } |
@@ -695,7 +693,7 @@ static void handle_block_event(struct HvLpEvent *event) | |||
695 | 693 | ||
696 | default: | 694 | default: |
697 | printk(VIOD_KERN_WARNING "invalid subtype!"); | 695 | printk(VIOD_KERN_WARNING "invalid subtype!"); |
698 | if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { | 696 | if (hvlpevent_need_ack(event)) { |
699 | event->xRc = HvLpEvent_Rc_InvalidSubtype; | 697 | event->xRc = HvLpEvent_Rc_InvalidSubtype; |
700 | HvCallEvent_ackLpEvent(event); | 698 | HvCallEvent_ackLpEvent(event); |
701 | } | 699 | } |
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index b5191780ecca..193446e6a08a 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c | |||
@@ -542,10 +542,10 @@ static void vio_handle_cd_event(struct HvLpEvent *event) | |||
542 | /* Notification that a partition went away! */ | 542 | /* Notification that a partition went away! */ |
543 | return; | 543 | return; |
544 | /* First, we should NEVER get an int here...only acks */ | 544 | /* First, we should NEVER get an int here...only acks */ |
545 | if (event->xFlags.xFunction == HvLpEvent_Function_Int) { | 545 | if (hvlpevent_is_int(event)) { |
546 | printk(VIOCD_KERN_WARNING | 546 | printk(VIOCD_KERN_WARNING |
547 | "Yikes! got an int in viocd event handler!\n"); | 547 | "Yikes! got an int in viocd event handler!\n"); |
548 | if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { | 548 | if (hvlpevent_need_ack(event)) { |
549 | event->xRc = HvLpEvent_Rc_InvalidSubtype; | 549 | event->xRc = HvLpEvent_Rc_InvalidSubtype; |
550 | HvCallEvent_ackLpEvent(event); | 550 | HvCallEvent_ackLpEvent(event); |
551 | } | 551 | } |
@@ -616,7 +616,7 @@ return_complete: | |||
616 | printk(VIOCD_KERN_WARNING | 616 | printk(VIOCD_KERN_WARNING |
617 | "message with invalid subtype %0x04X!\n", | 617 | "message with invalid subtype %0x04X!\n", |
618 | event->xSubtype & VIOMINOR_SUBTYPE_MASK); | 618 | event->xSubtype & VIOMINOR_SUBTYPE_MASK); |
619 | if (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck) { | 619 | if (hvlpevent_need_ack(event)) { |
620 | event->xRc = HvLpEvent_Rc_InvalidSubtype; | 620 | event->xRc = HvLpEvent_Rc_InvalidSubtype; |
621 | HvCallEvent_ackLpEvent(event); | 621 | HvCallEvent_ackLpEvent(event); |
622 | } | 622 | } |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 869518e4035f..7ac365b5d9ec 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -99,6 +99,7 @@ static char *serial_version = "4.30"; | |||
99 | #define _INLINE_ inline | 99 | #define _INLINE_ inline |
100 | #endif | 100 | #endif |
101 | 101 | ||
102 | #define custom amiga_custom | ||
102 | static char *serial_name = "Amiga-builtin serial driver"; | 103 | static char *serial_name = "Amiga-builtin serial driver"; |
103 | 104 | ||
104 | static struct tty_driver *serial_driver; | 105 | static struct tty_driver *serial_driver; |
@@ -128,7 +129,6 @@ static struct serial_state rs_table[1]; | |||
128 | * memory if large numbers of serial ports are open. | 129 | * memory if large numbers of serial ports are open. |
129 | */ | 130 | */ |
130 | static unsigned char *tmp_buf; | 131 | static unsigned char *tmp_buf; |
131 | static DECLARE_MUTEX(tmp_buf_sem); | ||
132 | 132 | ||
133 | #include <asm/uaccess.h> | 133 | #include <asm/uaccess.h> |
134 | 134 | ||
@@ -1088,7 +1088,7 @@ static void rs_unthrottle(struct tty_struct * tty) | |||
1088 | */ | 1088 | */ |
1089 | 1089 | ||
1090 | static int get_serial_info(struct async_struct * info, | 1090 | static int get_serial_info(struct async_struct * info, |
1091 | struct serial_struct * retinfo) | 1091 | struct serial_struct __user * retinfo) |
1092 | { | 1092 | { |
1093 | struct serial_struct tmp; | 1093 | struct serial_struct tmp; |
1094 | struct serial_state *state = info->state; | 1094 | struct serial_state *state = info->state; |
@@ -1112,7 +1112,7 @@ static int get_serial_info(struct async_struct * info, | |||
1112 | } | 1112 | } |
1113 | 1113 | ||
1114 | static int set_serial_info(struct async_struct * info, | 1114 | static int set_serial_info(struct async_struct * info, |
1115 | struct serial_struct * new_info) | 1115 | struct serial_struct __user * new_info) |
1116 | { | 1116 | { |
1117 | struct serial_struct new_serial; | 1117 | struct serial_struct new_serial; |
1118 | struct serial_state old_state, *state; | 1118 | struct serial_state old_state, *state; |
@@ -1193,7 +1193,7 @@ check_and_exit: | |||
1193 | * transmit holding register is empty. This functionality | 1193 | * transmit holding register is empty. This functionality |
1194 | * allows an RS485 driver to be written in user space. | 1194 | * allows an RS485 driver to be written in user space. |
1195 | */ | 1195 | */ |
1196 | static int get_lsr_info(struct async_struct * info, unsigned int *value) | 1196 | static int get_lsr_info(struct async_struct * info, unsigned int __user *value) |
1197 | { | 1197 | { |
1198 | unsigned char status; | 1198 | unsigned char status; |
1199 | unsigned int result; | 1199 | unsigned int result; |
@@ -1284,6 +1284,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, | |||
1284 | struct async_struct * info = (struct async_struct *)tty->driver_data; | 1284 | struct async_struct * info = (struct async_struct *)tty->driver_data; |
1285 | struct async_icount cprev, cnow; /* kernel counter temps */ | 1285 | struct async_icount cprev, cnow; /* kernel counter temps */ |
1286 | struct serial_icounter_struct icount; | 1286 | struct serial_icounter_struct icount; |
1287 | void __user *argp = (void __user *)arg; | ||
1287 | unsigned long flags; | 1288 | unsigned long flags; |
1288 | 1289 | ||
1289 | if (serial_paranoia_check(info, tty->name, "rs_ioctl")) | 1290 | if (serial_paranoia_check(info, tty->name, "rs_ioctl")) |
@@ -1298,19 +1299,17 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, | |||
1298 | 1299 | ||
1299 | switch (cmd) { | 1300 | switch (cmd) { |
1300 | case TIOCGSERIAL: | 1301 | case TIOCGSERIAL: |
1301 | return get_serial_info(info, | 1302 | return get_serial_info(info, argp); |
1302 | (struct serial_struct *) arg); | ||
1303 | case TIOCSSERIAL: | 1303 | case TIOCSSERIAL: |
1304 | return set_serial_info(info, | 1304 | return set_serial_info(info, argp); |
1305 | (struct serial_struct *) arg); | ||
1306 | case TIOCSERCONFIG: | 1305 | case TIOCSERCONFIG: |
1307 | return 0; | 1306 | return 0; |
1308 | 1307 | ||
1309 | case TIOCSERGETLSR: /* Get line status register */ | 1308 | case TIOCSERGETLSR: /* Get line status register */ |
1310 | return get_lsr_info(info, (unsigned int *) arg); | 1309 | return get_lsr_info(info, argp); |
1311 | 1310 | ||
1312 | case TIOCSERGSTRUCT: | 1311 | case TIOCSERGSTRUCT: |
1313 | if (copy_to_user((struct async_struct *) arg, | 1312 | if (copy_to_user(argp, |
1314 | info, sizeof(struct async_struct))) | 1313 | info, sizeof(struct async_struct))) |
1315 | return -EFAULT; | 1314 | return -EFAULT; |
1316 | return 0; | 1315 | return 0; |
@@ -1369,7 +1368,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file, | |||
1369 | icount.brk = cnow.brk; | 1368 | icount.brk = cnow.brk; |
1370 | icount.buf_overrun = cnow.buf_overrun; | 1369 | icount.buf_overrun = cnow.buf_overrun; |
1371 | 1370 | ||
1372 | if (copy_to_user((void *)arg, &icount, sizeof(icount))) | 1371 | if (copy_to_user(argp, &icount, sizeof(icount))) |
1373 | return -EFAULT; | 1372 | return -EFAULT; |
1374 | return 0; | 1373 | return 0; |
1375 | case TIOCSERGWILD: | 1374 | case TIOCSERGWILD: |
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile index e41060c76226..9d180c42816c 100644 --- a/drivers/char/drm/Makefile +++ b/drivers/char/drm/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. | 3 | # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. |
4 | 4 | ||
5 | drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \ | 5 | drm-objs := drm_auth.o drm_bufs.o drm_context.o drm_dma.o drm_drawable.o \ |
6 | drm_drv.o drm_fops.o drm_init.o drm_ioctl.o drm_irq.o \ | 6 | drm_drv.o drm_fops.o drm_ioctl.o drm_irq.o \ |
7 | drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ | 7 | drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \ |
8 | drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ | 8 | drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \ |
9 | drm_sysfs.o | 9 | drm_sysfs.o |
@@ -18,7 +18,7 @@ radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o | |||
18 | ffb-objs := ffb_drv.o ffb_context.o | 18 | ffb-objs := ffb_drv.o ffb_context.o |
19 | sis-objs := sis_drv.o sis_ds.o sis_mm.o | 19 | sis-objs := sis_drv.o sis_ds.o sis_mm.o |
20 | savage-objs := savage_drv.o savage_bci.o savage_state.o | 20 | savage-objs := savage_drv.o savage_bci.o savage_state.o |
21 | via-objs := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o | 21 | via-objs := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o via_dmablit.o |
22 | 22 | ||
23 | ifeq ($(CONFIG_COMPAT),y) | 23 | ifeq ($(CONFIG_COMPAT),y) |
24 | drm-objs += drm_ioc32.o | 24 | drm-objs += drm_ioc32.o |
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c index efff0eec618c..5485382cadec 100644 --- a/drivers/char/drm/ati_pcigart.c +++ b/drivers/char/drm/ati_pcigart.c | |||
@@ -52,7 +52,7 @@ | |||
52 | # define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */ | 52 | # define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */ |
53 | # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ | 53 | # define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ |
54 | 54 | ||
55 | static unsigned long drm_ati_alloc_pcigart_table(void) | 55 | static void *drm_ati_alloc_pcigart_table(void) |
56 | { | 56 | { |
57 | unsigned long address; | 57 | unsigned long address; |
58 | struct page *page; | 58 | struct page *page; |
@@ -72,27 +72,26 @@ static unsigned long drm_ati_alloc_pcigart_table(void) | |||
72 | } | 72 | } |
73 | 73 | ||
74 | DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address); | 74 | DRM_DEBUG("%s: returning 0x%08lx\n", __FUNCTION__, address); |
75 | return address; | 75 | return (void *)address; |
76 | } | 76 | } |
77 | 77 | ||
78 | static void drm_ati_free_pcigart_table(unsigned long address) | 78 | static void drm_ati_free_pcigart_table(void *address) |
79 | { | 79 | { |
80 | struct page *page; | 80 | struct page *page; |
81 | int i; | 81 | int i; |
82 | DRM_DEBUG("%s\n", __FUNCTION__); | 82 | DRM_DEBUG("%s\n", __FUNCTION__); |
83 | 83 | ||
84 | page = virt_to_page(address); | 84 | page = virt_to_page((unsigned long)address); |
85 | 85 | ||
86 | for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) { | 86 | for (i = 0; i < ATI_PCIGART_TABLE_PAGES; i++, page++) { |
87 | __put_page(page); | 87 | __put_page(page); |
88 | ClearPageReserved(page); | 88 | ClearPageReserved(page); |
89 | } | 89 | } |
90 | 90 | ||
91 | free_pages(address, ATI_PCIGART_TABLE_ORDER); | 91 | free_pages((unsigned long)address, ATI_PCIGART_TABLE_ORDER); |
92 | } | 92 | } |
93 | 93 | ||
94 | int drm_ati_pcigart_cleanup(drm_device_t * dev, | 94 | int drm_ati_pcigart_cleanup(drm_device_t *dev, drm_ati_pcigart_info *gart_info) |
95 | drm_ati_pcigart_info * gart_info) | ||
96 | { | 95 | { |
97 | drm_sg_mem_t *entry = dev->sg; | 96 | drm_sg_mem_t *entry = dev->sg; |
98 | unsigned long pages; | 97 | unsigned long pages; |
@@ -136,10 +135,10 @@ int drm_ati_pcigart_cleanup(drm_device_t * dev, | |||
136 | 135 | ||
137 | EXPORT_SYMBOL(drm_ati_pcigart_cleanup); | 136 | EXPORT_SYMBOL(drm_ati_pcigart_cleanup); |
138 | 137 | ||
139 | int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info) | 138 | int drm_ati_pcigart_init(drm_device_t *dev, drm_ati_pcigart_info *gart_info) |
140 | { | 139 | { |
141 | drm_sg_mem_t *entry = dev->sg; | 140 | drm_sg_mem_t *entry = dev->sg; |
142 | unsigned long address = 0; | 141 | void *address = NULL; |
143 | unsigned long pages; | 142 | unsigned long pages; |
144 | u32 *pci_gart, page_base, bus_address = 0; | 143 | u32 *pci_gart, page_base, bus_address = 0; |
145 | int i, j, ret = 0; | 144 | int i, j, ret = 0; |
@@ -163,7 +162,7 @@ int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info) | |||
163 | goto done; | 162 | goto done; |
164 | } | 163 | } |
165 | 164 | ||
166 | bus_address = pci_map_single(dev->pdev, (void *)address, | 165 | bus_address = pci_map_single(dev->pdev, address, |
167 | ATI_PCIGART_TABLE_PAGES * | 166 | ATI_PCIGART_TABLE_PAGES * |
168 | PAGE_SIZE, PCI_DMA_TODEVICE); | 167 | PAGE_SIZE, PCI_DMA_TODEVICE); |
169 | if (bus_address == 0) { | 168 | if (bus_address == 0) { |
@@ -176,7 +175,7 @@ int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info) | |||
176 | address = gart_info->addr; | 175 | address = gart_info->addr; |
177 | bus_address = gart_info->bus_addr; | 176 | bus_address = gart_info->bus_addr; |
178 | DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n", | 177 | DRM_DEBUG("PCI: Gart Table: VRAM %08X mapped at %08lX\n", |
179 | bus_address, address); | 178 | bus_address, (unsigned long)address); |
180 | } | 179 | } |
181 | 180 | ||
182 | pci_gart = (u32 *) address; | 181 | pci_gart = (u32 *) address; |
@@ -195,7 +194,7 @@ int drm_ati_pcigart_init(drm_device_t * dev, drm_ati_pcigart_info * gart_info) | |||
195 | if (entry->busaddr[i] == 0) { | 194 | if (entry->busaddr[i] == 0) { |
196 | DRM_ERROR("unable to map PCIGART pages!\n"); | 195 | DRM_ERROR("unable to map PCIGART pages!\n"); |
197 | drm_ati_pcigart_cleanup(dev, gart_info); | 196 | drm_ati_pcigart_cleanup(dev, gart_info); |
198 | address = 0; | 197 | address = NULL; |
199 | bus_address = 0; | 198 | bus_address = 0; |
200 | goto done; | 199 | goto done; |
201 | } | 200 | } |
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h index 64d6237fdd0b..9da0ddb892b5 100644 --- a/drivers/char/drm/drm.h +++ b/drivers/char/drm/drm.h | |||
@@ -90,8 +90,8 @@ | |||
90 | #define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */ | 90 | #define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */ |
91 | #define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */ | 91 | #define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */ |
92 | 92 | ||
93 | #define _DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */ | 93 | #define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */ |
94 | #define _DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */ | 94 | #define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */ |
95 | #define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD) | 95 | #define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD) |
96 | #define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT) | 96 | #define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT) |
97 | #define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) | 97 | #define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT)) |
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 3dc3c9d79ae4..54b561e69486 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h | |||
@@ -144,20 +144,6 @@ | |||
144 | /** \name Backward compatibility section */ | 144 | /** \name Backward compatibility section */ |
145 | /*@{*/ | 145 | /*@{*/ |
146 | 146 | ||
147 | #ifndef MODULE_LICENSE | ||
148 | #define MODULE_LICENSE(x) | ||
149 | #endif | ||
150 | |||
151 | #ifndef preempt_disable | ||
152 | #define preempt_disable() | ||
153 | #define preempt_enable() | ||
154 | #endif | ||
155 | |||
156 | #ifndef pte_offset_map | ||
157 | #define pte_offset_map pte_offset | ||
158 | #define pte_unmap(pte) | ||
159 | #endif | ||
160 | |||
161 | #define DRM_RPR_ARG(vma) vma, | 147 | #define DRM_RPR_ARG(vma) vma, |
162 | 148 | ||
163 | #define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT) | 149 | #define VM_OFFSET(vma) ((vma)->vm_pgoff << PAGE_SHIFT) |
@@ -286,10 +272,13 @@ typedef int drm_ioctl_t(struct inode *inode, struct file *filp, | |||
286 | typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, | 272 | typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, |
287 | unsigned long arg); | 273 | unsigned long arg); |
288 | 274 | ||
275 | #define DRM_AUTH 0x1 | ||
276 | #define DRM_MASTER 0x2 | ||
277 | #define DRM_ROOT_ONLY 0x4 | ||
278 | |||
289 | typedef struct drm_ioctl_desc { | 279 | typedef struct drm_ioctl_desc { |
290 | drm_ioctl_t *func; | 280 | drm_ioctl_t *func; |
291 | int auth_needed; | 281 | int flags; |
292 | int root_only; | ||
293 | } drm_ioctl_desc_t; | 282 | } drm_ioctl_desc_t; |
294 | 283 | ||
295 | typedef struct drm_devstate { | 284 | typedef struct drm_devstate { |
@@ -384,6 +373,7 @@ typedef struct drm_buf_entry { | |||
384 | /** File private data */ | 373 | /** File private data */ |
385 | typedef struct drm_file { | 374 | typedef struct drm_file { |
386 | int authenticated; | 375 | int authenticated; |
376 | int master; | ||
387 | int minor; | 377 | int minor; |
388 | pid_t pid; | 378 | pid_t pid; |
389 | uid_t uid; | 379 | uid_t uid; |
@@ -532,8 +522,9 @@ typedef struct drm_vbl_sig { | |||
532 | typedef struct ati_pcigart_info { | 522 | typedef struct ati_pcigart_info { |
533 | int gart_table_location; | 523 | int gart_table_location; |
534 | int is_pcie; | 524 | int is_pcie; |
535 | unsigned long addr; | 525 | void *addr; |
536 | dma_addr_t bus_addr; | 526 | dma_addr_t bus_addr; |
527 | drm_local_map_t mapping; | ||
537 | } drm_ati_pcigart_info; | 528 | } drm_ati_pcigart_info; |
538 | 529 | ||
539 | /** | 530 | /** |
@@ -544,16 +535,14 @@ typedef struct ati_pcigart_info { | |||
544 | struct drm_device; | 535 | struct drm_device; |
545 | 536 | ||
546 | struct drm_driver { | 537 | struct drm_driver { |
547 | int (*preinit) (struct drm_device *, unsigned long flags); | 538 | int (*load) (struct drm_device *, unsigned long flags); |
548 | void (*prerelease) (struct drm_device *, struct file * filp); | 539 | int (*firstopen) (struct drm_device *); |
549 | void (*pretakedown) (struct drm_device *); | 540 | int (*open) (struct drm_device *, drm_file_t *); |
550 | int (*postcleanup) (struct drm_device *); | 541 | void (*preclose) (struct drm_device *, struct file * filp); |
551 | int (*presetup) (struct drm_device *); | 542 | void (*postclose) (struct drm_device *, drm_file_t *); |
552 | int (*postsetup) (struct drm_device *); | 543 | void (*lastclose) (struct drm_device *); |
544 | int (*unload) (struct drm_device *); | ||
553 | int (*dma_ioctl) (DRM_IOCTL_ARGS); | 545 | int (*dma_ioctl) (DRM_IOCTL_ARGS); |
554 | int (*open_helper) (struct drm_device *, drm_file_t *); | ||
555 | void (*free_filp_priv) (struct drm_device *, drm_file_t *); | ||
556 | void (*release) (struct drm_device *, struct file * filp); | ||
557 | void (*dma_ready) (struct drm_device *); | 546 | void (*dma_ready) (struct drm_device *); |
558 | int (*dma_quiescent) (struct drm_device *); | 547 | int (*dma_quiescent) (struct drm_device *); |
559 | int (*context_ctor) (struct drm_device * dev, int context); | 548 | int (*context_ctor) (struct drm_device * dev, int context); |
@@ -561,8 +550,9 @@ struct drm_driver { | |||
561 | int (*kernel_context_switch) (struct drm_device * dev, int old, | 550 | int (*kernel_context_switch) (struct drm_device * dev, int old, |
562 | int new); | 551 | int new); |
563 | void (*kernel_context_switch_unlock) (struct drm_device * dev, | 552 | void (*kernel_context_switch_unlock) (struct drm_device * dev, |
564 | drm_lock_t * lock); | 553 | drm_lock_t *lock); |
565 | int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence); | 554 | int (*vblank_wait) (struct drm_device * dev, unsigned int *sequence); |
555 | int (*dri_library_name) (struct drm_device *dev, char *buf); | ||
566 | 556 | ||
567 | /** | 557 | /** |
568 | * Called by \c drm_device_is_agp. Typically used to determine if a | 558 | * Called by \c drm_device_is_agp. Typically used to determine if a |
@@ -579,16 +569,24 @@ struct drm_driver { | |||
579 | 569 | ||
580 | /* these have to be filled in */ | 570 | /* these have to be filled in */ |
581 | 571 | ||
582 | int (*postinit) (struct drm_device *, unsigned long flags); | 572 | irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); |
583 | irqreturn_t(*irq_handler) (DRM_IRQ_ARGS); | ||
584 | void (*irq_preinstall) (struct drm_device * dev); | 573 | void (*irq_preinstall) (struct drm_device * dev); |
585 | void (*irq_postinstall) (struct drm_device * dev); | 574 | void (*irq_postinstall) (struct drm_device * dev); |
586 | void (*irq_uninstall) (struct drm_device * dev); | 575 | void (*irq_uninstall) (struct drm_device * dev); |
587 | void (*reclaim_buffers) (struct drm_device * dev, struct file * filp); | 576 | void (*reclaim_buffers) (struct drm_device * dev, struct file * filp); |
577 | void (*reclaim_buffers_locked) (struct drm_device *dev, | ||
578 | struct file *filp); | ||
588 | unsigned long (*get_map_ofs) (drm_map_t * map); | 579 | unsigned long (*get_map_ofs) (drm_map_t * map); |
589 | unsigned long (*get_reg_ofs) (struct drm_device * dev); | 580 | unsigned long (*get_reg_ofs) (struct drm_device * dev); |
590 | void (*set_version) (struct drm_device * dev, drm_set_version_t * sv); | 581 | void (*set_version) (struct drm_device * dev, drm_set_version_t * sv); |
591 | int (*version) (drm_version_t * version); | 582 | |
583 | int major; | ||
584 | int minor; | ||
585 | int patchlevel; | ||
586 | char *name; | ||
587 | char *desc; | ||
588 | char *date; | ||
589 | |||
592 | u32 driver_features; | 590 | u32 driver_features; |
593 | int dev_priv_size; | 591 | int dev_priv_size; |
594 | drm_ioctl_desc_t *ioctls; | 592 | drm_ioctl_desc_t *ioctls; |
@@ -752,19 +750,43 @@ static inline int drm_core_has_MTRR(struct drm_device *dev) | |||
752 | { | 750 | { |
753 | return drm_core_check_feature(dev, DRIVER_USE_MTRR); | 751 | return drm_core_check_feature(dev, DRIVER_USE_MTRR); |
754 | } | 752 | } |
753 | |||
754 | #define DRM_MTRR_WC MTRR_TYPE_WRCOMB | ||
755 | |||
756 | static inline int drm_mtrr_add(unsigned long offset, unsigned long size, | ||
757 | unsigned int flags) | ||
758 | { | ||
759 | return mtrr_add(offset, size, flags, 1); | ||
760 | } | ||
761 | |||
762 | static inline int drm_mtrr_del(int handle, unsigned long offset, | ||
763 | unsigned long size, unsigned int flags) | ||
764 | { | ||
765 | return mtrr_del(handle, offset, size); | ||
766 | } | ||
767 | |||
755 | #else | 768 | #else |
756 | #define drm_core_has_MTRR(dev) (0) | 769 | #define drm_core_has_MTRR(dev) (0) |
770 | |||
771 | #define DRM_MTRR_WC 0 | ||
772 | |||
773 | static inline int drm_mtrr_add(unsigned long offset, unsigned long size, | ||
774 | unsigned int flags) | ||
775 | { | ||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | static inline int drm_mtrr_del(int handle, unsigned long offset, | ||
780 | unsigned long size, unsigned int flags) | ||
781 | { | ||
782 | return 0; | ||
783 | } | ||
757 | #endif | 784 | #endif |
758 | 785 | ||
759 | /******************************************************************/ | 786 | /******************************************************************/ |
760 | /** \name Internal function definitions */ | 787 | /** \name Internal function definitions */ |
761 | /*@{*/ | 788 | /*@{*/ |
762 | 789 | ||
763 | /* Misc. support (drm_init.h) */ | ||
764 | extern int drm_flags; | ||
765 | extern void drm_parse_options(char *s); | ||
766 | extern int drm_cpu_valid(void); | ||
767 | |||
768 | /* Driver support (drm_drv.h) */ | 790 | /* Driver support (drm_drv.h) */ |
769 | extern int drm_init(struct drm_driver *driver); | 791 | extern int drm_init(struct drm_driver *driver); |
770 | extern void drm_exit(struct drm_driver *driver); | 792 | extern void drm_exit(struct drm_driver *driver); |
@@ -772,12 +794,11 @@ extern int drm_ioctl(struct inode *inode, struct file *filp, | |||
772 | unsigned int cmd, unsigned long arg); | 794 | unsigned int cmd, unsigned long arg); |
773 | extern long drm_compat_ioctl(struct file *filp, | 795 | extern long drm_compat_ioctl(struct file *filp, |
774 | unsigned int cmd, unsigned long arg); | 796 | unsigned int cmd, unsigned long arg); |
775 | extern int drm_takedown(drm_device_t * dev); | 797 | extern int drm_lastclose(drm_device_t *dev); |
776 | 798 | ||
777 | /* Device support (drm_fops.h) */ | 799 | /* Device support (drm_fops.h) */ |
778 | extern int drm_open(struct inode *inode, struct file *filp); | 800 | extern int drm_open(struct inode *inode, struct file *filp); |
779 | extern int drm_stub_open(struct inode *inode, struct file *filp); | 801 | extern int drm_stub_open(struct inode *inode, struct file *filp); |
780 | extern int drm_flush(struct file *filp); | ||
781 | extern int drm_fasync(int fd, struct file *filp, int on); | 802 | extern int drm_fasync(int fd, struct file *filp, int on); |
782 | extern int drm_release(struct inode *inode, struct file *filp); | 803 | extern int drm_release(struct inode *inode, struct file *filp); |
783 | 804 | ||
@@ -819,6 +840,8 @@ extern int drm_getstats(struct inode *inode, struct file *filp, | |||
819 | unsigned int cmd, unsigned long arg); | 840 | unsigned int cmd, unsigned long arg); |
820 | extern int drm_setversion(struct inode *inode, struct file *filp, | 841 | extern int drm_setversion(struct inode *inode, struct file *filp, |
821 | unsigned int cmd, unsigned long arg); | 842 | unsigned int cmd, unsigned long arg); |
843 | extern int drm_noop(struct inode *inode, struct file *filp, | ||
844 | unsigned int cmd, unsigned long arg); | ||
822 | 845 | ||
823 | /* Context IOCTL support (drm_context.h) */ | 846 | /* Context IOCTL support (drm_context.h) */ |
824 | extern int drm_resctx(struct inode *inode, struct file *filp, | 847 | extern int drm_resctx(struct inode *inode, struct file *filp, |
@@ -857,10 +880,6 @@ extern int drm_getmagic(struct inode *inode, struct file *filp, | |||
857 | extern int drm_authmagic(struct inode *inode, struct file *filp, | 880 | extern int drm_authmagic(struct inode *inode, struct file *filp, |
858 | unsigned int cmd, unsigned long arg); | 881 | unsigned int cmd, unsigned long arg); |
859 | 882 | ||
860 | /* Placeholder for ioctls past */ | ||
861 | extern int drm_noop(struct inode *inode, struct file *filp, | ||
862 | unsigned int cmd, unsigned long arg); | ||
863 | |||
864 | /* Locking IOCTL support (drm_lock.h) */ | 883 | /* Locking IOCTL support (drm_lock.h) */ |
865 | extern int drm_lock(struct inode *inode, struct file *filp, | 884 | extern int drm_lock(struct inode *inode, struct file *filp, |
866 | unsigned int cmd, unsigned long arg); | 885 | unsigned int cmd, unsigned long arg); |
@@ -873,6 +892,7 @@ extern int drm_lock_free(drm_device_t * dev, | |||
873 | /* Buffer management support (drm_bufs.h) */ | 892 | /* Buffer management support (drm_bufs.h) */ |
874 | extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request); | 893 | extern int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request); |
875 | extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request); | 894 | extern int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request); |
895 | extern int drm_addbufs_fb(drm_device_t *dev, drm_buf_desc_t *request); | ||
876 | extern int drm_addmap(drm_device_t * dev, unsigned int offset, | 896 | extern int drm_addmap(drm_device_t * dev, unsigned int offset, |
877 | unsigned int size, drm_map_type_t type, | 897 | unsigned int size, drm_map_type_t type, |
878 | drm_map_flags_t flags, drm_local_map_t ** map_ptr); | 898 | drm_map_flags_t flags, drm_local_map_t ** map_ptr); |
@@ -908,8 +928,8 @@ extern void drm_core_reclaim_buffers(drm_device_t * dev, struct file *filp); | |||
908 | /* IRQ support (drm_irq.h) */ | 928 | /* IRQ support (drm_irq.h) */ |
909 | extern int drm_control(struct inode *inode, struct file *filp, | 929 | extern int drm_control(struct inode *inode, struct file *filp, |
910 | unsigned int cmd, unsigned long arg); | 930 | unsigned int cmd, unsigned long arg); |
911 | extern int drm_irq_uninstall(drm_device_t * dev); | ||
912 | extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS); | 931 | extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS); |
932 | extern int drm_irq_uninstall(drm_device_t * dev); | ||
913 | extern void drm_driver_irq_preinstall(drm_device_t * dev); | 933 | extern void drm_driver_irq_preinstall(drm_device_t * dev); |
914 | extern void drm_driver_irq_postinstall(drm_device_t * dev); | 934 | extern void drm_driver_irq_postinstall(drm_device_t * dev); |
915 | extern void drm_driver_irq_uninstall(drm_device_t * dev); | 935 | extern void drm_driver_irq_uninstall(drm_device_t * dev); |
@@ -933,13 +953,17 @@ extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp, | |||
933 | extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info); | 953 | extern int drm_agp_info(drm_device_t * dev, drm_agp_info_t * info); |
934 | extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp, | 954 | extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp, |
935 | unsigned int cmd, unsigned long arg); | 955 | unsigned int cmd, unsigned long arg); |
936 | extern int drm_agp_alloc(struct inode *inode, struct file *filp, | 956 | extern int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request); |
957 | extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp, | ||
937 | unsigned int cmd, unsigned long arg); | 958 | unsigned int cmd, unsigned long arg); |
938 | extern int drm_agp_free(struct inode *inode, struct file *filp, | 959 | extern int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request); |
960 | extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp, | ||
939 | unsigned int cmd, unsigned long arg); | 961 | unsigned int cmd, unsigned long arg); |
940 | extern int drm_agp_unbind(struct inode *inode, struct file *filp, | 962 | extern int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request); |
963 | extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp, | ||
941 | unsigned int cmd, unsigned long arg); | 964 | unsigned int cmd, unsigned long arg); |
942 | extern int drm_agp_bind(struct inode *inode, struct file *filp, | 965 | extern int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request); |
966 | extern int drm_agp_bind_ioctl(struct inode *inode, struct file *filp, | ||
943 | unsigned int cmd, unsigned long arg); | 967 | unsigned int cmd, unsigned long arg); |
944 | extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, | 968 | extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, |
945 | size_t pages, u32 type); | 969 | size_t pages, u32 type); |
@@ -991,10 +1015,8 @@ extern struct drm_sysfs_class *drm_sysfs_create(struct module *owner, | |||
991 | char *name); | 1015 | char *name); |
992 | extern void drm_sysfs_destroy(struct drm_sysfs_class *cs); | 1016 | extern void drm_sysfs_destroy(struct drm_sysfs_class *cs); |
993 | extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, | 1017 | extern struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, |
994 | dev_t dev, | 1018 | drm_head_t *head); |
995 | struct device *device, | 1019 | extern void drm_sysfs_device_remove(struct class_device *class_dev); |
996 | const char *fmt, ...); | ||
997 | extern void drm_sysfs_device_remove(dev_t dev); | ||
998 | 1020 | ||
999 | /* Inline replacements for DRM_IOREMAP macros */ | 1021 | /* Inline replacements for DRM_IOREMAP macros */ |
1000 | static __inline__ void drm_core_ioremap(struct drm_map *map, | 1022 | static __inline__ void drm_core_ioremap(struct drm_map *map, |
diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c index 2b6453a9ffce..fabc930c67a2 100644 --- a/drivers/char/drm/drm_agpsupport.c +++ b/drivers/char/drm/drm_agpsupport.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * \file drm_agpsupport.h | 2 | * \file drm_agpsupport.c |
3 | * DRM support for AGP/GART backend | 3 | * DRM support for AGP/GART backend |
4 | * | 4 | * |
5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> | 5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> |
@@ -91,7 +91,7 @@ int drm_agp_info_ioctl(struct inode *inode, struct file *filp, | |||
91 | /** | 91 | /** |
92 | * Acquire the AGP device. | 92 | * Acquire the AGP device. |
93 | * | 93 | * |
94 | * \param dev DRM device that is to acquire AGP | 94 | * \param dev DRM device that is to acquire AGP. |
95 | * \return zero on success or a negative number on failure. | 95 | * \return zero on success or a negative number on failure. |
96 | * | 96 | * |
97 | * Verifies the AGP device hasn't been acquired before and calls | 97 | * Verifies the AGP device hasn't been acquired before and calls |
@@ -134,7 +134,7 @@ int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp, | |||
134 | /** | 134 | /** |
135 | * Release the AGP device. | 135 | * Release the AGP device. |
136 | * | 136 | * |
137 | * \param dev DRM device that is to release AGP | 137 | * \param dev DRM device that is to release AGP. |
138 | * \return zero on success or a negative number on failure. | 138 | * \return zero on success or a negative number on failure. |
139 | * | 139 | * |
140 | * Verifies the AGP device has been acquired and calls \c agp_backend_release. | 140 | * Verifies the AGP device has been acquired and calls \c agp_backend_release. |
@@ -147,7 +147,6 @@ int drm_agp_release(drm_device_t * dev) | |||
147 | dev->agp->acquired = 0; | 147 | dev->agp->acquired = 0; |
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | |||
151 | EXPORT_SYMBOL(drm_agp_release); | 150 | EXPORT_SYMBOL(drm_agp_release); |
152 | 151 | ||
153 | int drm_agp_release_ioctl(struct inode *inode, struct file *filp, | 152 | int drm_agp_release_ioctl(struct inode *inode, struct file *filp, |
@@ -208,30 +207,22 @@ int drm_agp_enable_ioctl(struct inode *inode, struct file *filp, | |||
208 | * Verifies the AGP device is present and has been acquired, allocates the | 207 | * Verifies the AGP device is present and has been acquired, allocates the |
209 | * memory via alloc_agp() and creates a drm_agp_mem entry for it. | 208 | * memory via alloc_agp() and creates a drm_agp_mem entry for it. |
210 | */ | 209 | */ |
211 | int drm_agp_alloc(struct inode *inode, struct file *filp, | 210 | int drm_agp_alloc(drm_device_t *dev, drm_agp_buffer_t *request) |
212 | unsigned int cmd, unsigned long arg) | ||
213 | { | 211 | { |
214 | drm_file_t *priv = filp->private_data; | ||
215 | drm_device_t *dev = priv->head->dev; | ||
216 | drm_agp_buffer_t request; | ||
217 | drm_agp_mem_t *entry; | 212 | drm_agp_mem_t *entry; |
218 | DRM_AGP_MEM *memory; | 213 | DRM_AGP_MEM *memory; |
219 | unsigned long pages; | 214 | unsigned long pages; |
220 | u32 type; | 215 | u32 type; |
221 | drm_agp_buffer_t __user *argp = (void __user *)arg; | ||
222 | 216 | ||
223 | if (!dev->agp || !dev->agp->acquired) | 217 | if (!dev->agp || !dev->agp->acquired) |
224 | return -EINVAL; | 218 | return -EINVAL; |
225 | if (copy_from_user(&request, argp, sizeof(request))) | ||
226 | return -EFAULT; | ||
227 | if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS))) | 219 | if (!(entry = drm_alloc(sizeof(*entry), DRM_MEM_AGPLISTS))) |
228 | return -ENOMEM; | 220 | return -ENOMEM; |
229 | 221 | ||
230 | memset(entry, 0, sizeof(*entry)); | 222 | memset(entry, 0, sizeof(*entry)); |
231 | 223 | ||
232 | pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; | 224 | pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE; |
233 | type = (u32) request.type; | 225 | type = (u32) request->type; |
234 | |||
235 | if (!(memory = drm_alloc_agp(dev, pages, type))) { | 226 | if (!(memory = drm_alloc_agp(dev, pages, type))) { |
236 | drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); | 227 | drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); |
237 | return -ENOMEM; | 228 | return -ENOMEM; |
@@ -247,16 +238,39 @@ int drm_agp_alloc(struct inode *inode, struct file *filp, | |||
247 | dev->agp->memory->prev = entry; | 238 | dev->agp->memory->prev = entry; |
248 | dev->agp->memory = entry; | 239 | dev->agp->memory = entry; |
249 | 240 | ||
250 | request.handle = entry->handle; | 241 | request->handle = entry->handle; |
251 | request.physical = memory->physical; | 242 | request->physical = memory->physical; |
243 | |||
244 | return 0; | ||
245 | } | ||
246 | EXPORT_SYMBOL(drm_agp_alloc); | ||
247 | |||
248 | int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp, | ||
249 | unsigned int cmd, unsigned long arg) | ||
250 | { | ||
251 | drm_file_t *priv = filp->private_data; | ||
252 | drm_device_t *dev = priv->head->dev; | ||
253 | drm_agp_buffer_t request; | ||
254 | drm_agp_buffer_t __user *argp = (void __user *)arg; | ||
255 | int err; | ||
256 | |||
257 | if (copy_from_user(&request, argp, sizeof(request))) | ||
258 | return -EFAULT; | ||
259 | |||
260 | err = drm_agp_alloc(dev, &request); | ||
261 | if (err) | ||
262 | return err; | ||
252 | 263 | ||
253 | if (copy_to_user(argp, &request, sizeof(request))) { | 264 | if (copy_to_user(argp, &request, sizeof(request))) { |
265 | drm_agp_mem_t *entry = dev->agp->memory; | ||
266 | |||
254 | dev->agp->memory = entry->next; | 267 | dev->agp->memory = entry->next; |
255 | dev->agp->memory->prev = NULL; | 268 | dev->agp->memory->prev = NULL; |
256 | drm_free_agp(memory, pages); | 269 | drm_free_agp(entry->memory, entry->pages); |
257 | drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); | 270 | drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); |
258 | return -EFAULT; | 271 | return -EFAULT; |
259 | } | 272 | } |
273 | |||
260 | return 0; | 274 | return 0; |
261 | } | 275 | } |
262 | 276 | ||
@@ -293,21 +307,14 @@ static drm_agp_mem_t *drm_agp_lookup_entry(drm_device_t * dev, | |||
293 | * Verifies the AGP device is present and acquired, looks-up the AGP memory | 307 | * Verifies the AGP device is present and acquired, looks-up the AGP memory |
294 | * entry and passes it to the unbind_agp() function. | 308 | * entry and passes it to the unbind_agp() function. |
295 | */ | 309 | */ |
296 | int drm_agp_unbind(struct inode *inode, struct file *filp, | 310 | int drm_agp_unbind(drm_device_t *dev, drm_agp_binding_t *request) |
297 | unsigned int cmd, unsigned long arg) | ||
298 | { | 311 | { |
299 | drm_file_t *priv = filp->private_data; | ||
300 | drm_device_t *dev = priv->head->dev; | ||
301 | drm_agp_binding_t request; | ||
302 | drm_agp_mem_t *entry; | 312 | drm_agp_mem_t *entry; |
303 | int ret; | 313 | int ret; |
304 | 314 | ||
305 | if (!dev->agp || !dev->agp->acquired) | 315 | if (!dev->agp || !dev->agp->acquired) |
306 | return -EINVAL; | 316 | return -EINVAL; |
307 | if (copy_from_user | 317 | if (!(entry = drm_agp_lookup_entry(dev, request->handle))) |
308 | (&request, (drm_agp_binding_t __user *) arg, sizeof(request))) | ||
309 | return -EFAULT; | ||
310 | if (!(entry = drm_agp_lookup_entry(dev, request.handle))) | ||
311 | return -EINVAL; | 318 | return -EINVAL; |
312 | if (!entry->bound) | 319 | if (!entry->bound) |
313 | return -EINVAL; | 320 | return -EINVAL; |
@@ -316,6 +323,21 @@ int drm_agp_unbind(struct inode *inode, struct file *filp, | |||
316 | entry->bound = 0; | 323 | entry->bound = 0; |
317 | return ret; | 324 | return ret; |
318 | } | 325 | } |
326 | EXPORT_SYMBOL(drm_agp_unbind); | ||
327 | |||
328 | int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp, | ||
329 | unsigned int cmd, unsigned long arg) | ||
330 | { | ||
331 | drm_file_t *priv = filp->private_data; | ||
332 | drm_device_t *dev = priv->head->dev; | ||
333 | drm_agp_binding_t request; | ||
334 | |||
335 | if (copy_from_user | ||
336 | (&request, (drm_agp_binding_t __user *) arg, sizeof(request))) | ||
337 | return -EFAULT; | ||
338 | |||
339 | return drm_agp_unbind(dev, &request); | ||
340 | } | ||
319 | 341 | ||
320 | /** | 342 | /** |
321 | * Bind AGP memory into the GATT (ioctl) | 343 | * Bind AGP memory into the GATT (ioctl) |
@@ -330,26 +352,19 @@ int drm_agp_unbind(struct inode *inode, struct file *filp, | |||
330 | * is currently bound into the GATT. Looks-up the AGP memory entry and passes | 352 | * is currently bound into the GATT. Looks-up the AGP memory entry and passes |
331 | * it to bind_agp() function. | 353 | * it to bind_agp() function. |
332 | */ | 354 | */ |
333 | int drm_agp_bind(struct inode *inode, struct file *filp, | 355 | int drm_agp_bind(drm_device_t *dev, drm_agp_binding_t *request) |
334 | unsigned int cmd, unsigned long arg) | ||
335 | { | 356 | { |
336 | drm_file_t *priv = filp->private_data; | ||
337 | drm_device_t *dev = priv->head->dev; | ||
338 | drm_agp_binding_t request; | ||
339 | drm_agp_mem_t *entry; | 357 | drm_agp_mem_t *entry; |
340 | int retcode; | 358 | int retcode; |
341 | int page; | 359 | int page; |
342 | 360 | ||
343 | if (!dev->agp || !dev->agp->acquired) | 361 | if (!dev->agp || !dev->agp->acquired) |
344 | return -EINVAL; | 362 | return -EINVAL; |
345 | if (copy_from_user | 363 | if (!(entry = drm_agp_lookup_entry(dev, request->handle))) |
346 | (&request, (drm_agp_binding_t __user *) arg, sizeof(request))) | ||
347 | return -EFAULT; | ||
348 | if (!(entry = drm_agp_lookup_entry(dev, request.handle))) | ||
349 | return -EINVAL; | 364 | return -EINVAL; |
350 | if (entry->bound) | 365 | if (entry->bound) |
351 | return -EINVAL; | 366 | return -EINVAL; |
352 | page = (request.offset + PAGE_SIZE - 1) / PAGE_SIZE; | 367 | page = (request->offset + PAGE_SIZE - 1) / PAGE_SIZE; |
353 | if ((retcode = drm_bind_agp(entry->memory, page))) | 368 | if ((retcode = drm_bind_agp(entry->memory, page))) |
354 | return retcode; | 369 | return retcode; |
355 | entry->bound = dev->agp->base + (page << PAGE_SHIFT); | 370 | entry->bound = dev->agp->base + (page << PAGE_SHIFT); |
@@ -357,6 +372,21 @@ int drm_agp_bind(struct inode *inode, struct file *filp, | |||
357 | dev->agp->base, entry->bound); | 372 | dev->agp->base, entry->bound); |
358 | return 0; | 373 | return 0; |
359 | } | 374 | } |
375 | EXPORT_SYMBOL(drm_agp_bind); | ||
376 | |||
377 | int drm_agp_bind_ioctl(struct inode *inode, struct file *filp, | ||
378 | unsigned int cmd, unsigned long arg) | ||
379 | { | ||
380 | drm_file_t *priv = filp->private_data; | ||
381 | drm_device_t *dev = priv->head->dev; | ||
382 | drm_agp_binding_t request; | ||
383 | |||
384 | if (copy_from_user | ||
385 | (&request, (drm_agp_binding_t __user *) arg, sizeof(request))) | ||
386 | return -EFAULT; | ||
387 | |||
388 | return drm_agp_bind(dev, &request); | ||
389 | } | ||
360 | 390 | ||
361 | /** | 391 | /** |
362 | * Free AGP memory (ioctl). | 392 | * Free AGP memory (ioctl). |
@@ -372,20 +402,13 @@ int drm_agp_bind(struct inode *inode, struct file *filp, | |||
372 | * unbind_agp(). Frees it via free_agp() as well as the entry itself | 402 | * unbind_agp(). Frees it via free_agp() as well as the entry itself |
373 | * and unlinks from the doubly linked list it's inserted in. | 403 | * and unlinks from the doubly linked list it's inserted in. |
374 | */ | 404 | */ |
375 | int drm_agp_free(struct inode *inode, struct file *filp, | 405 | int drm_agp_free(drm_device_t *dev, drm_agp_buffer_t *request) |
376 | unsigned int cmd, unsigned long arg) | ||
377 | { | 406 | { |
378 | drm_file_t *priv = filp->private_data; | ||
379 | drm_device_t *dev = priv->head->dev; | ||
380 | drm_agp_buffer_t request; | ||
381 | drm_agp_mem_t *entry; | 407 | drm_agp_mem_t *entry; |
382 | 408 | ||
383 | if (!dev->agp || !dev->agp->acquired) | 409 | if (!dev->agp || !dev->agp->acquired) |
384 | return -EINVAL; | 410 | return -EINVAL; |
385 | if (copy_from_user | 411 | if (!(entry = drm_agp_lookup_entry(dev, request->handle))) |
386 | (&request, (drm_agp_buffer_t __user *) arg, sizeof(request))) | ||
387 | return -EFAULT; | ||
388 | if (!(entry = drm_agp_lookup_entry(dev, request.handle))) | ||
389 | return -EINVAL; | 412 | return -EINVAL; |
390 | if (entry->bound) | 413 | if (entry->bound) |
391 | drm_unbind_agp(entry->memory); | 414 | drm_unbind_agp(entry->memory); |
@@ -402,12 +425,30 @@ int drm_agp_free(struct inode *inode, struct file *filp, | |||
402 | drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); | 425 | drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); |
403 | return 0; | 426 | return 0; |
404 | } | 427 | } |
428 | EXPORT_SYMBOL(drm_agp_free); | ||
429 | |||
430 | int drm_agp_free_ioctl(struct inode *inode, struct file *filp, | ||
431 | unsigned int cmd, unsigned long arg) | ||
432 | { | ||
433 | drm_file_t *priv = filp->private_data; | ||
434 | drm_device_t *dev = priv->head->dev; | ||
435 | drm_agp_buffer_t request; | ||
436 | |||
437 | if (copy_from_user | ||
438 | (&request, (drm_agp_buffer_t __user *) arg, sizeof(request))) | ||
439 | return -EFAULT; | ||
440 | |||
441 | return drm_agp_free(dev, &request); | ||
442 | } | ||
405 | 443 | ||
406 | /** | 444 | /** |
407 | * Initialize the AGP resources. | 445 | * Initialize the AGP resources. |
408 | * | 446 | * |
409 | * \return pointer to a drm_agp_head structure. | 447 | * \return pointer to a drm_agp_head structure. |
410 | * | 448 | * |
449 | * Gets the drm_agp_t structure which is made available by the agpgart module | ||
450 | * via the inter_module_* functions. Creates and initializes a drm_agp_head | ||
451 | * structure. | ||
411 | */ | 452 | */ |
412 | drm_agp_head_t *drm_agp_init(drm_device_t * dev) | 453 | drm_agp_head_t *drm_agp_init(drm_device_t * dev) |
413 | { | 454 | { |
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 319bdea8de8a..1db12dcb6802 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c | |||
@@ -36,22 +36,21 @@ | |||
36 | #include <linux/vmalloc.h> | 36 | #include <linux/vmalloc.h> |
37 | #include "drmP.h" | 37 | #include "drmP.h" |
38 | 38 | ||
39 | unsigned long drm_get_resource_start(drm_device_t * dev, unsigned int resource) | 39 | unsigned long drm_get_resource_start(drm_device_t *dev, unsigned int resource) |
40 | { | 40 | { |
41 | return pci_resource_start(dev->pdev, resource); | 41 | return pci_resource_start(dev->pdev, resource); |
42 | } | 42 | } |
43 | |||
44 | EXPORT_SYMBOL(drm_get_resource_start); | 43 | EXPORT_SYMBOL(drm_get_resource_start); |
45 | 44 | ||
46 | unsigned long drm_get_resource_len(drm_device_t * dev, unsigned int resource) | 45 | unsigned long drm_get_resource_len(drm_device_t *dev, unsigned int resource) |
47 | { | 46 | { |
48 | return pci_resource_len(dev->pdev, resource); | 47 | return pci_resource_len(dev->pdev, resource); |
49 | } | 48 | } |
50 | 49 | ||
51 | EXPORT_SYMBOL(drm_get_resource_len); | 50 | EXPORT_SYMBOL(drm_get_resource_len); |
52 | 51 | ||
53 | static drm_map_list_t *drm_find_matching_map(drm_device_t * dev, | 52 | static drm_map_list_t *drm_find_matching_map(drm_device_t *dev, |
54 | drm_local_map_t * map) | 53 | drm_local_map_t *map) |
55 | { | 54 | { |
56 | struct list_head *list; | 55 | struct list_head *list; |
57 | 56 | ||
@@ -74,7 +73,7 @@ static drm_map_list_t *drm_find_matching_map(drm_device_t * dev, | |||
74 | 73 | ||
75 | #ifdef _LP64 | 74 | #ifdef _LP64 |
76 | static __inline__ unsigned int HandleID(unsigned long lhandle, | 75 | static __inline__ unsigned int HandleID(unsigned long lhandle, |
77 | drm_device_t * dev) | 76 | drm_device_t *dev) |
78 | { | 77 | { |
79 | static unsigned int map32_handle = START_RANGE; | 78 | static unsigned int map32_handle = START_RANGE; |
80 | unsigned int hash; | 79 | unsigned int hash; |
@@ -155,7 +154,7 @@ static int drm_addmap_core(drm_device_t * dev, unsigned int offset, | |||
155 | case _DRM_REGISTERS: | 154 | case _DRM_REGISTERS: |
156 | case _DRM_FRAME_BUFFER: | 155 | case _DRM_FRAME_BUFFER: |
157 | #if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__) | 156 | #if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__) |
158 | if (map->offset + map->size < map->offset || | 157 | if (map->offset + (map->size-1) < map->offset || |
159 | map->offset < virt_to_phys(high_memory)) { | 158 | map->offset < virt_to_phys(high_memory)) { |
160 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); | 159 | drm_free(map, sizeof(*map), DRM_MEM_MAPS); |
161 | return -EINVAL; | 160 | return -EINVAL; |
@@ -301,6 +300,9 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp, | |||
301 | return -EFAULT; | 300 | return -EFAULT; |
302 | } | 301 | } |
303 | 302 | ||
303 | if (!(capable(CAP_SYS_ADMIN) || map.type == _DRM_AGP)) | ||
304 | return -EPERM; | ||
305 | |||
304 | err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags, | 306 | err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags, |
305 | &maplist); | 307 | &maplist); |
306 | 308 | ||
@@ -332,7 +334,7 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp, | |||
332 | * | 334 | * |
333 | * \sa drm_addmap | 335 | * \sa drm_addmap |
334 | */ | 336 | */ |
335 | int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map) | 337 | int drm_rmmap_locked(drm_device_t *dev, drm_local_map_t *map) |
336 | { | 338 | { |
337 | struct list_head *list; | 339 | struct list_head *list; |
338 | drm_map_list_t *r_list = NULL; | 340 | drm_map_list_t *r_list = NULL; |
@@ -384,10 +386,9 @@ int drm_rmmap_locked(drm_device_t * dev, drm_local_map_t * map) | |||
384 | 386 | ||
385 | return 0; | 387 | return 0; |
386 | } | 388 | } |
387 | |||
388 | EXPORT_SYMBOL(drm_rmmap_locked); | 389 | EXPORT_SYMBOL(drm_rmmap_locked); |
389 | 390 | ||
390 | int drm_rmmap(drm_device_t * dev, drm_local_map_t * map) | 391 | int drm_rmmap(drm_device_t *dev, drm_local_map_t *map) |
391 | { | 392 | { |
392 | int ret; | 393 | int ret; |
393 | 394 | ||
@@ -397,7 +398,6 @@ int drm_rmmap(drm_device_t * dev, drm_local_map_t * map) | |||
397 | 398 | ||
398 | return ret; | 399 | return ret; |
399 | } | 400 | } |
400 | |||
401 | EXPORT_SYMBOL(drm_rmmap); | 401 | EXPORT_SYMBOL(drm_rmmap); |
402 | 402 | ||
403 | /* The rmmap ioctl appears to be unnecessary. All mappings are torn down on | 403 | /* The rmmap ioctl appears to be unnecessary. All mappings are torn down on |
@@ -548,7 +548,7 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) | |||
548 | DRM_DEBUG("count: %d\n", count); | 548 | DRM_DEBUG("count: %d\n", count); |
549 | DRM_DEBUG("order: %d\n", order); | 549 | DRM_DEBUG("order: %d\n", order); |
550 | DRM_DEBUG("size: %d\n", size); | 550 | DRM_DEBUG("size: %d\n", size); |
551 | DRM_DEBUG("agp_offset: %lu\n", agp_offset); | 551 | DRM_DEBUG("agp_offset: %lx\n", agp_offset); |
552 | DRM_DEBUG("alignment: %d\n", alignment); | 552 | DRM_DEBUG("alignment: %d\n", alignment); |
553 | DRM_DEBUG("page_order: %d\n", page_order); | 553 | DRM_DEBUG("page_order: %d\n", page_order); |
554 | DRM_DEBUG("total: %d\n", total); | 554 | DRM_DEBUG("total: %d\n", total); |
@@ -649,6 +649,8 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) | |||
649 | } | 649 | } |
650 | 650 | ||
651 | dma->buf_count += entry->buf_count; | 651 | dma->buf_count += entry->buf_count; |
652 | dma->seg_count += entry->seg_count; | ||
653 | dma->page_count += byte_count >> PAGE_SHIFT; | ||
652 | dma->byte_count += byte_count; | 654 | dma->byte_count += byte_count; |
653 | 655 | ||
654 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); | 656 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); |
@@ -664,7 +666,6 @@ int drm_addbufs_agp(drm_device_t * dev, drm_buf_desc_t * request) | |||
664 | atomic_dec(&dev->buf_alloc); | 666 | atomic_dec(&dev->buf_alloc); |
665 | return 0; | 667 | return 0; |
666 | } | 668 | } |
667 | |||
668 | EXPORT_SYMBOL(drm_addbufs_agp); | 669 | EXPORT_SYMBOL(drm_addbufs_agp); |
669 | #endif /* __OS_HAS_AGP */ | 670 | #endif /* __OS_HAS_AGP */ |
670 | 671 | ||
@@ -689,9 +690,13 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
689 | 690 | ||
690 | if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) | 691 | if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) |
691 | return -EINVAL; | 692 | return -EINVAL; |
693 | |||
692 | if (!dma) | 694 | if (!dma) |
693 | return -EINVAL; | 695 | return -EINVAL; |
694 | 696 | ||
697 | if (!capable(CAP_SYS_ADMIN)) | ||
698 | return -EPERM; | ||
699 | |||
695 | count = request->count; | 700 | count = request->count; |
696 | order = drm_order(request->size); | 701 | order = drm_order(request->size); |
697 | size = 1 << order; | 702 | size = 1 << order; |
@@ -882,7 +887,6 @@ int drm_addbufs_pci(drm_device_t * dev, drm_buf_desc_t * request) | |||
882 | return 0; | 887 | return 0; |
883 | 888 | ||
884 | } | 889 | } |
885 | |||
886 | EXPORT_SYMBOL(drm_addbufs_pci); | 890 | EXPORT_SYMBOL(drm_addbufs_pci); |
887 | 891 | ||
888 | static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) | 892 | static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) |
@@ -908,6 +912,9 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) | |||
908 | if (!dma) | 912 | if (!dma) |
909 | return -EINVAL; | 913 | return -EINVAL; |
910 | 914 | ||
915 | if (!capable(CAP_SYS_ADMIN)) | ||
916 | return -EPERM; | ||
917 | |||
911 | count = request->count; | 918 | count = request->count; |
912 | order = drm_order(request->size); | 919 | order = drm_order(request->size); |
913 | size = 1 << order; | 920 | size = 1 << order; |
@@ -1026,6 +1033,8 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) | |||
1026 | } | 1033 | } |
1027 | 1034 | ||
1028 | dma->buf_count += entry->buf_count; | 1035 | dma->buf_count += entry->buf_count; |
1036 | dma->seg_count += entry->seg_count; | ||
1037 | dma->page_count += byte_count >> PAGE_SHIFT; | ||
1029 | dma->byte_count += byte_count; | 1038 | dma->byte_count += byte_count; |
1030 | 1039 | ||
1031 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); | 1040 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); |
@@ -1042,7 +1051,7 @@ static int drm_addbufs_sg(drm_device_t * dev, drm_buf_desc_t * request) | |||
1042 | return 0; | 1051 | return 0; |
1043 | } | 1052 | } |
1044 | 1053 | ||
1045 | static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | 1054 | int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) |
1046 | { | 1055 | { |
1047 | drm_device_dma_t *dma = dev->dma; | 1056 | drm_device_dma_t *dma = dev->dma; |
1048 | drm_buf_entry_t *entry; | 1057 | drm_buf_entry_t *entry; |
@@ -1065,6 +1074,9 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | |||
1065 | if (!dma) | 1074 | if (!dma) |
1066 | return -EINVAL; | 1075 | return -EINVAL; |
1067 | 1076 | ||
1077 | if (!capable(CAP_SYS_ADMIN)) | ||
1078 | return -EPERM; | ||
1079 | |||
1068 | count = request->count; | 1080 | count = request->count; |
1069 | order = drm_order(request->size); | 1081 | order = drm_order(request->size); |
1070 | size = 1 << order; | 1082 | size = 1 << order; |
@@ -1181,6 +1193,8 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | |||
1181 | } | 1193 | } |
1182 | 1194 | ||
1183 | dma->buf_count += entry->buf_count; | 1195 | dma->buf_count += entry->buf_count; |
1196 | dma->seg_count += entry->seg_count; | ||
1197 | dma->page_count += byte_count >> PAGE_SHIFT; | ||
1184 | dma->byte_count += byte_count; | 1198 | dma->byte_count += byte_count; |
1185 | 1199 | ||
1186 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); | 1200 | DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); |
@@ -1196,6 +1210,8 @@ static int drm_addbufs_fb(drm_device_t * dev, drm_buf_desc_t * request) | |||
1196 | atomic_dec(&dev->buf_alloc); | 1210 | atomic_dec(&dev->buf_alloc); |
1197 | return 0; | 1211 | return 0; |
1198 | } | 1212 | } |
1213 | EXPORT_SYMBOL(drm_addbufs_fb); | ||
1214 | |||
1199 | 1215 | ||
1200 | /** | 1216 | /** |
1201 | * Add buffers for DMA transfers (ioctl). | 1217 | * Add buffers for DMA transfers (ioctl). |
@@ -1577,5 +1593,6 @@ int drm_order(unsigned long size) | |||
1577 | 1593 | ||
1578 | return order; | 1594 | return order; |
1579 | } | 1595 | } |
1580 | |||
1581 | EXPORT_SYMBOL(drm_order); | 1596 | EXPORT_SYMBOL(drm_order); |
1597 | |||
1598 | |||
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c index bd958d69a2ac..f84254526949 100644 --- a/drivers/char/drm/drm_context.c +++ b/drivers/char/drm/drm_context.c | |||
@@ -433,7 +433,7 @@ int drm_addctx(struct inode *inode, struct file *filp, | |||
433 | if (ctx.handle != DRM_KERNEL_CONTEXT) { | 433 | if (ctx.handle != DRM_KERNEL_CONTEXT) { |
434 | if (dev->driver->context_ctor) | 434 | if (dev->driver->context_ctor) |
435 | if (!dev->driver->context_ctor(dev, ctx.handle)) { | 435 | if (!dev->driver->context_ctor(dev, ctx.handle)) { |
436 | DRM_DEBUG( "Running out of ctxs or memory.\n"); | 436 | DRM_DEBUG("Running out of ctxs or memory.\n"); |
437 | return -ENOMEM; | 437 | return -ENOMEM; |
438 | } | 438 | } |
439 | } | 439 | } |
diff --git a/drivers/char/drm/drm_core.h b/drivers/char/drm/drm_core.h index cc97bb906dda..f4f9db6c7ed4 100644 --- a/drivers/char/drm/drm_core.h +++ b/drivers/char/drm/drm_core.h | |||
@@ -24,11 +24,11 @@ | |||
24 | 24 | ||
25 | #define CORE_NAME "drm" | 25 | #define CORE_NAME "drm" |
26 | #define CORE_DESC "DRM shared core routines" | 26 | #define CORE_DESC "DRM shared core routines" |
27 | #define CORE_DATE "20040925" | 27 | #define CORE_DATE "20051102" |
28 | 28 | ||
29 | #define DRM_IF_MAJOR 1 | 29 | #define DRM_IF_MAJOR 1 |
30 | #define DRM_IF_MINOR 2 | 30 | #define DRM_IF_MINOR 2 |
31 | 31 | ||
32 | #define CORE_MAJOR 1 | 32 | #define CORE_MAJOR 1 |
33 | #define CORE_MINOR 0 | 33 | #define CORE_MINOR 0 |
34 | #define CORE_PATCHLEVEL 0 | 34 | #define CORE_PATCHLEVEL 1 |
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index 4dff7554eb08..c4fa5a29582b 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c | |||
@@ -56,66 +56,66 @@ static int drm_version(struct inode *inode, struct file *filp, | |||
56 | 56 | ||
57 | /** Ioctl table */ | 57 | /** Ioctl table */ |
58 | static drm_ioctl_desc_t drm_ioctls[] = { | 58 | static drm_ioctl_desc_t drm_ioctls[] = { |
59 | [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0, 0}, | 59 | [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0}, |
60 | [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0, 0}, | 60 | [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0}, |
61 | [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0, 0}, | 61 | [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0}, |
62 | [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, 0, 1}, | 62 | [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY}, |
63 | [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0, 0}, | 63 | [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0}, |
64 | [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0, 0}, | 64 | [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0}, |
65 | [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0, 0}, | 65 | [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0}, |
66 | [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, 0, 1}, | 66 | [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, DRM_MASTER|DRM_ROOT_ONLY}, |
67 | 67 | [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | |
68 | [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, 1, 1}, | 68 | [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
69 | [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, 1, 1}, | 69 | [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
70 | [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = {drm_noop, 1, 1}, | 70 | [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = {drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
71 | [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = {drm_authmagic, 1, 1}, | 71 | |
72 | 72 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = {drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | |
73 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = {drm_addmap_ioctl, 1, 1}, | 73 | [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = {drm_rmmap_ioctl, DRM_AUTH}, |
74 | [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = {drm_rmmap_ioctl, 1, 0}, | 74 | |
75 | 75 | [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | |
76 | [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, 1, 1}, | 76 | [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH}, |
77 | [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, 1, 0}, | 77 | |
78 | 78 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | |
79 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, 1, 1}, | 79 | [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
80 | [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, 1, 1}, | 80 | [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
81 | [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, 1, 1}, | 81 | [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH}, |
82 | [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, 1, 0}, | 82 | [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
83 | [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, 1, 1}, | 83 | [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
84 | [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, 1, 1}, | 84 | [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, DRM_AUTH}, |
85 | [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, 1, 0}, | 85 | |
86 | 86 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | |
87 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, 1, 1}, | 87 | [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
88 | [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, 1, 1}, | 88 | |
89 | 89 | [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, DRM_AUTH}, | |
90 | [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, 1, 0}, | 90 | [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, DRM_AUTH}, |
91 | [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, 1, 0}, | 91 | |
92 | 92 | [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, DRM_AUTH}, | |
93 | [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, 1, 0}, | 93 | |
94 | 94 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, | |
95 | [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, 1, 1}, | 95 | [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
96 | [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, 1, 1}, | 96 | [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, DRM_AUTH}, |
97 | [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, 1, 0}, | 97 | [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, DRM_AUTH}, |
98 | [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, 1, 0}, | 98 | [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, DRM_AUTH}, |
99 | [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, 1, 0}, | ||
100 | /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */ | 99 | /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */ |
100 | [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = {NULL, DRM_AUTH}, | ||
101 | 101 | ||
102 | [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, 1, 1}, | 102 | [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
103 | 103 | ||
104 | #if __OS_HAS_AGP | 104 | #if __OS_HAS_AGP |
105 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire_ioctl, 1, 1}, | 105 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
106 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release_ioctl, 1, 1}, | 106 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
107 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable_ioctl, 1, 1}, | 107 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
108 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info_ioctl, 1, 0}, | 108 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info_ioctl, DRM_AUTH}, |
109 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc, 1, 1}, | 109 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
110 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free, 1, 1}, | 110 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
111 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_bind, 1, 1}, | 111 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
112 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind, 1, 1}, | 112 | [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
113 | #endif | 113 | #endif |
114 | 114 | ||
115 | [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = {drm_sg_alloc, 1, 1}, | 115 | [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = {drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
116 | [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, 1, 1}, | 116 | [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
117 | 117 | ||
118 | [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0, 0}, | 118 | [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0}, |
119 | }; | 119 | }; |
120 | 120 | ||
121 | #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls ) | 121 | #define DRIVER_IOCTL_COUNT DRM_ARRAY_SIZE( drm_ioctls ) |
@@ -129,7 +129,7 @@ static drm_ioctl_desc_t drm_ioctls[] = { | |||
129 | * | 129 | * |
130 | * \sa drm_device | 130 | * \sa drm_device |
131 | */ | 131 | */ |
132 | int drm_takedown(drm_device_t * dev) | 132 | int drm_lastclose(drm_device_t * dev) |
133 | { | 133 | { |
134 | drm_magic_entry_t *pt, *next; | 134 | drm_magic_entry_t *pt, *next; |
135 | drm_map_list_t *r_list; | 135 | drm_map_list_t *r_list; |
@@ -138,9 +138,9 @@ int drm_takedown(drm_device_t * dev) | |||
138 | 138 | ||
139 | DRM_DEBUG("\n"); | 139 | DRM_DEBUG("\n"); |
140 | 140 | ||
141 | if (dev->driver->pretakedown) | 141 | if (dev->driver->lastclose) |
142 | dev->driver->pretakedown(dev); | 142 | dev->driver->lastclose(dev); |
143 | DRM_DEBUG("driver pretakedown completed\n"); | 143 | DRM_DEBUG("driver lastclose completed\n"); |
144 | 144 | ||
145 | if (dev->unique) { | 145 | if (dev->unique) { |
146 | drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); | 146 | drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER); |
@@ -233,7 +233,7 @@ int drm_takedown(drm_device_t * dev) | |||
233 | } | 233 | } |
234 | up(&dev->struct_sem); | 234 | up(&dev->struct_sem); |
235 | 235 | ||
236 | DRM_DEBUG("takedown completed\n"); | 236 | DRM_DEBUG("lastclose completed\n"); |
237 | return 0; | 237 | return 0; |
238 | } | 238 | } |
239 | 239 | ||
@@ -281,7 +281,7 @@ EXPORT_SYMBOL(drm_init); | |||
281 | /** | 281 | /** |
282 | * Called via cleanup_module() at module unload time. | 282 | * Called via cleanup_module() at module unload time. |
283 | * | 283 | * |
284 | * Cleans up all DRM device, calling takedown(). | 284 | * Cleans up all DRM device, calling drm_lastclose(). |
285 | * | 285 | * |
286 | * \sa drm_init | 286 | * \sa drm_init |
287 | */ | 287 | */ |
@@ -294,7 +294,7 @@ static void drm_cleanup(drm_device_t * dev) | |||
294 | return; | 294 | return; |
295 | } | 295 | } |
296 | 296 | ||
297 | drm_takedown(dev); | 297 | drm_lastclose(dev); |
298 | 298 | ||
299 | if (dev->maplist) { | 299 | if (dev->maplist) { |
300 | drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); | 300 | drm_free(dev->maplist, sizeof(*dev->maplist), DRM_MEM_MAPS); |
@@ -317,8 +317,8 @@ static void drm_cleanup(drm_device_t * dev) | |||
317 | dev->agp = NULL; | 317 | dev->agp = NULL; |
318 | } | 318 | } |
319 | 319 | ||
320 | if (dev->driver->postcleanup) | 320 | if (dev->driver->unload) |
321 | dev->driver->postcleanup(dev); | 321 | dev->driver->unload(dev); |
322 | 322 | ||
323 | drm_put_head(&dev->primary); | 323 | drm_put_head(&dev->primary); |
324 | if (drm_put_dev(dev)) | 324 | if (drm_put_dev(dev)) |
@@ -342,12 +342,12 @@ void drm_exit(struct drm_driver *driver) | |||
342 | if (head->dev->driver != driver) | 342 | if (head->dev->driver != driver) |
343 | continue; | 343 | continue; |
344 | dev = head->dev; | 344 | dev = head->dev; |
345 | } | 345 | if (dev) { |
346 | if (dev) { | 346 | /* release the pci driver */ |
347 | /* release the pci driver */ | 347 | if (dev->pdev) |
348 | if (dev->pdev) | 348 | pci_dev_put(dev->pdev); |
349 | pci_dev_put(dev->pdev); | 349 | drm_cleanup(dev); |
350 | drm_cleanup(dev); | 350 | } |
351 | } | 351 | } |
352 | DRM_INFO("Module unloaded\n"); | 352 | DRM_INFO("Module unloaded\n"); |
353 | } | 353 | } |
@@ -432,14 +432,17 @@ static int drm_version(struct inode *inode, struct file *filp, | |||
432 | drm_device_t *dev = priv->head->dev; | 432 | drm_device_t *dev = priv->head->dev; |
433 | drm_version_t __user *argp = (void __user *)arg; | 433 | drm_version_t __user *argp = (void __user *)arg; |
434 | drm_version_t version; | 434 | drm_version_t version; |
435 | int ret; | 435 | int len; |
436 | 436 | ||
437 | if (copy_from_user(&version, argp, sizeof(version))) | 437 | if (copy_from_user(&version, argp, sizeof(version))) |
438 | return -EFAULT; | 438 | return -EFAULT; |
439 | 439 | ||
440 | /* version is a required function to return the personality module version */ | 440 | version.version_major = dev->driver->major; |
441 | if ((ret = dev->driver->version(&version))) | 441 | version.version_minor = dev->driver->minor; |
442 | return ret; | 442 | version.version_patchlevel = dev->driver->patchlevel; |
443 | DRM_COPY(version.name, dev->driver->name); | ||
444 | DRM_COPY(version.date, dev->driver->date); | ||
445 | DRM_COPY(version.desc, dev->driver->desc); | ||
443 | 446 | ||
444 | if (copy_to_user(argp, &version, sizeof(version))) | 447 | if (copy_to_user(argp, &version, sizeof(version))) |
445 | return -EFAULT; | 448 | return -EFAULT; |
@@ -493,8 +496,9 @@ int drm_ioctl(struct inode *inode, struct file *filp, | |||
493 | if (!func) { | 496 | if (!func) { |
494 | DRM_DEBUG("no function\n"); | 497 | DRM_DEBUG("no function\n"); |
495 | retcode = -EINVAL; | 498 | retcode = -EINVAL; |
496 | } else if ((ioctl->root_only && !capable(CAP_SYS_ADMIN)) || | 499 | } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) || |
497 | (ioctl->auth_needed && !priv->authenticated)) { | 500 | ((ioctl->flags & DRM_AUTH) && !priv->authenticated) || |
501 | ((ioctl->flags & DRM_MASTER) && !priv->master)) { | ||
498 | retcode = -EACCES; | 502 | retcode = -EACCES; |
499 | } else { | 503 | } else { |
500 | retcode = func(inode, filp, cmd, arg); | 504 | retcode = func(inode, filp, cmd, arg); |
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index bf0a740122bf..403f44a1bf01 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c | |||
@@ -35,6 +35,7 @@ | |||
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include "drmP.h" | 37 | #include "drmP.h" |
38 | #include "drm_sarea.h" | ||
38 | #include <linux/poll.h> | 39 | #include <linux/poll.h> |
39 | 40 | ||
40 | static int drm_open_helper(struct inode *inode, struct file *filp, | 41 | static int drm_open_helper(struct inode *inode, struct file *filp, |
@@ -42,15 +43,21 @@ static int drm_open_helper(struct inode *inode, struct file *filp, | |||
42 | 43 | ||
43 | static int drm_setup(drm_device_t * dev) | 44 | static int drm_setup(drm_device_t * dev) |
44 | { | 45 | { |
46 | drm_local_map_t *map; | ||
45 | int i; | 47 | int i; |
46 | int ret; | 48 | int ret; |
47 | 49 | ||
48 | if (dev->driver->presetup) { | 50 | if (dev->driver->firstopen) { |
49 | ret = dev->driver->presetup(dev); | 51 | ret = dev->driver->firstopen(dev); |
50 | if (ret != 0) | 52 | if (ret != 0) |
51 | return ret; | 53 | return ret; |
52 | } | 54 | } |
53 | 55 | ||
56 | /* prebuild the SAREA */ | ||
57 | i = drm_addmap(dev, 0, SAREA_MAX, _DRM_SHM, _DRM_CONTAINS_LOCK, &map); | ||
58 | if (i != 0) | ||
59 | return i; | ||
60 | |||
54 | atomic_set(&dev->ioctl_count, 0); | 61 | atomic_set(&dev->ioctl_count, 0); |
55 | atomic_set(&dev->vma_count, 0); | 62 | atomic_set(&dev->vma_count, 0); |
56 | dev->buf_use = 0; | 63 | dev->buf_use = 0; |
@@ -109,8 +116,6 @@ static int drm_setup(drm_device_t * dev) | |||
109 | * drm_select_queue fails between the time the interrupt is | 116 | * drm_select_queue fails between the time the interrupt is |
110 | * initialized and the time the queues are initialized. | 117 | * initialized and the time the queues are initialized. |
111 | */ | 118 | */ |
112 | if (dev->driver->postsetup) | ||
113 | dev->driver->postsetup(dev); | ||
114 | 119 | ||
115 | return 0; | 120 | return 0; |
116 | } | 121 | } |
@@ -154,10 +159,168 @@ int drm_open(struct inode *inode, struct file *filp) | |||
154 | 159 | ||
155 | return retcode; | 160 | return retcode; |
156 | } | 161 | } |
157 | |||
158 | EXPORT_SYMBOL(drm_open); | 162 | EXPORT_SYMBOL(drm_open); |
159 | 163 | ||
160 | /** | 164 | /** |
165 | * File \c open operation. | ||
166 | * | ||
167 | * \param inode device inode. | ||
168 | * \param filp file pointer. | ||
169 | * | ||
170 | * Puts the dev->fops corresponding to the device minor number into | ||
171 | * \p filp, call the \c open method, and restore the file operations. | ||
172 | */ | ||
173 | int drm_stub_open(struct inode *inode, struct file *filp) | ||
174 | { | ||
175 | drm_device_t *dev = NULL; | ||
176 | int minor = iminor(inode); | ||
177 | int err = -ENODEV; | ||
178 | struct file_operations *old_fops; | ||
179 | |||
180 | DRM_DEBUG("\n"); | ||
181 | |||
182 | if (!((minor >= 0) && (minor < drm_cards_limit))) | ||
183 | return -ENODEV; | ||
184 | |||
185 | if (!drm_heads[minor]) | ||
186 | return -ENODEV; | ||
187 | |||
188 | if (!(dev = drm_heads[minor]->dev)) | ||
189 | return -ENODEV; | ||
190 | |||
191 | old_fops = filp->f_op; | ||
192 | filp->f_op = fops_get(&dev->driver->fops); | ||
193 | if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) { | ||
194 | fops_put(filp->f_op); | ||
195 | filp->f_op = fops_get(old_fops); | ||
196 | } | ||
197 | fops_put(old_fops); | ||
198 | |||
199 | return err; | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * Check whether DRI will run on this CPU. | ||
204 | * | ||
205 | * \return non-zero if the DRI will run on this CPU, or zero otherwise. | ||
206 | */ | ||
207 | static int drm_cpu_valid(void) | ||
208 | { | ||
209 | #if defined(__i386__) | ||
210 | if (boot_cpu_data.x86 == 3) | ||
211 | return 0; /* No cmpxchg on a 386 */ | ||
212 | #endif | ||
213 | #if defined(__sparc__) && !defined(__sparc_v9__) | ||
214 | return 0; /* No cmpxchg before v9 sparc. */ | ||
215 | #endif | ||
216 | return 1; | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * Called whenever a process opens /dev/drm. | ||
221 | * | ||
222 | * \param inode device inode. | ||
223 | * \param filp file pointer. | ||
224 | * \param dev device. | ||
225 | * \return zero on success or a negative number on failure. | ||
226 | * | ||
227 | * Creates and initializes a drm_file structure for the file private data in \p | ||
228 | * filp and add it into the double linked list in \p dev. | ||
229 | */ | ||
230 | static int drm_open_helper(struct inode *inode, struct file *filp, | ||
231 | drm_device_t * dev) | ||
232 | { | ||
233 | int minor = iminor(inode); | ||
234 | drm_file_t *priv; | ||
235 | int ret; | ||
236 | |||
237 | if (filp->f_flags & O_EXCL) | ||
238 | return -EBUSY; /* No exclusive opens */ | ||
239 | if (!drm_cpu_valid()) | ||
240 | return -EINVAL; | ||
241 | |||
242 | DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor); | ||
243 | |||
244 | priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES); | ||
245 | if (!priv) | ||
246 | return -ENOMEM; | ||
247 | |||
248 | memset(priv, 0, sizeof(*priv)); | ||
249 | filp->private_data = priv; | ||
250 | priv->uid = current->euid; | ||
251 | priv->pid = current->pid; | ||
252 | priv->minor = minor; | ||
253 | priv->head = drm_heads[minor]; | ||
254 | priv->ioctl_count = 0; | ||
255 | /* for compatibility root is always authenticated */ | ||
256 | priv->authenticated = capable(CAP_SYS_ADMIN); | ||
257 | priv->lock_count = 0; | ||
258 | |||
259 | if (dev->driver->open) { | ||
260 | ret = dev->driver->open(dev, priv); | ||
261 | if (ret < 0) | ||
262 | goto out_free; | ||
263 | } | ||
264 | |||
265 | down(&dev->struct_sem); | ||
266 | if (!dev->file_last) { | ||
267 | priv->next = NULL; | ||
268 | priv->prev = NULL; | ||
269 | dev->file_first = priv; | ||
270 | dev->file_last = priv; | ||
271 | /* first opener automatically becomes master */ | ||
272 | priv->master = 1; | ||
273 | } else { | ||
274 | priv->next = NULL; | ||
275 | priv->prev = dev->file_last; | ||
276 | dev->file_last->next = priv; | ||
277 | dev->file_last = priv; | ||
278 | } | ||
279 | up(&dev->struct_sem); | ||
280 | |||
281 | #ifdef __alpha__ | ||
282 | /* | ||
283 | * Default the hose | ||
284 | */ | ||
285 | if (!dev->hose) { | ||
286 | struct pci_dev *pci_dev; | ||
287 | pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL); | ||
288 | if (pci_dev) { | ||
289 | dev->hose = pci_dev->sysdata; | ||
290 | pci_dev_put(pci_dev); | ||
291 | } | ||
292 | if (!dev->hose) { | ||
293 | struct pci_bus *b = pci_bus_b(pci_root_buses.next); | ||
294 | if (b) | ||
295 | dev->hose = b->sysdata; | ||
296 | } | ||
297 | } | ||
298 | #endif | ||
299 | |||
300 | return 0; | ||
301 | out_free: | ||
302 | drm_free(priv, sizeof(*priv), DRM_MEM_FILES); | ||
303 | filp->private_data = NULL; | ||
304 | return ret; | ||
305 | } | ||
306 | |||
307 | /** No-op. */ | ||
308 | int drm_fasync(int fd, struct file *filp, int on) | ||
309 | { | ||
310 | drm_file_t *priv = filp->private_data; | ||
311 | drm_device_t *dev = priv->head->dev; | ||
312 | int retcode; | ||
313 | |||
314 | DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, | ||
315 | (long)old_encode_dev(priv->head->device)); | ||
316 | retcode = fasync_helper(fd, filp, on, &dev->buf_async); | ||
317 | if (retcode < 0) | ||
318 | return retcode; | ||
319 | return 0; | ||
320 | } | ||
321 | EXPORT_SYMBOL(drm_fasync); | ||
322 | |||
323 | /** | ||
161 | * Release file. | 324 | * Release file. |
162 | * | 325 | * |
163 | * \param inode device inode | 326 | * \param inode device inode |
@@ -167,7 +330,7 @@ EXPORT_SYMBOL(drm_open); | |||
167 | * If the hardware lock is held then free it, and take it again for the kernel | 330 | * If the hardware lock is held then free it, and take it again for the kernel |
168 | * context since it's necessary to reclaim buffers. Unlink the file private | 331 | * context since it's necessary to reclaim buffers. Unlink the file private |
169 | * data from its list and free it. Decreases the open count and if it reaches | 332 | * data from its list and free it. Decreases the open count and if it reaches |
170 | * zero calls takedown(). | 333 | * zero calls drm_lastclose(). |
171 | */ | 334 | */ |
172 | int drm_release(struct inode *inode, struct file *filp) | 335 | int drm_release(struct inode *inode, struct file *filp) |
173 | { | 336 | { |
@@ -180,8 +343,8 @@ int drm_release(struct inode *inode, struct file *filp) | |||
180 | 343 | ||
181 | DRM_DEBUG("open_count = %d\n", dev->open_count); | 344 | DRM_DEBUG("open_count = %d\n", dev->open_count); |
182 | 345 | ||
183 | if (dev->driver->prerelease) | 346 | if (dev->driver->preclose) |
184 | dev->driver->prerelease(dev, filp); | 347 | dev->driver->preclose(dev, filp); |
185 | 348 | ||
186 | /* ======================================================== | 349 | /* ======================================================== |
187 | * Begin inline drm_release | 350 | * Begin inline drm_release |
@@ -197,8 +360,8 @@ int drm_release(struct inode *inode, struct file *filp) | |||
197 | DRM_DEBUG("File %p released, freeing lock for context %d\n", | 360 | DRM_DEBUG("File %p released, freeing lock for context %d\n", |
198 | filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); | 361 | filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); |
199 | 362 | ||
200 | if (dev->driver->release) | 363 | if (dev->driver->reclaim_buffers_locked) |
201 | dev->driver->release(dev, filp); | 364 | dev->driver->reclaim_buffers_locked(dev, filp); |
202 | 365 | ||
203 | drm_lock_free(dev, &dev->lock.hw_lock->lock, | 366 | drm_lock_free(dev, &dev->lock.hw_lock->lock, |
204 | _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); | 367 | _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); |
@@ -207,7 +370,7 @@ int drm_release(struct inode *inode, struct file *filp) | |||
207 | hardware at this point, possibly | 370 | hardware at this point, possibly |
208 | processed via a callback to the X | 371 | processed via a callback to the X |
209 | server. */ | 372 | server. */ |
210 | } else if (dev->driver->release && priv->lock_count | 373 | } else if (dev->driver->reclaim_buffers_locked && priv->lock_count |
211 | && dev->lock.hw_lock) { | 374 | && dev->lock.hw_lock) { |
212 | /* The lock is required to reclaim buffers */ | 375 | /* The lock is required to reclaim buffers */ |
213 | DECLARE_WAITQUEUE(entry, current); | 376 | DECLARE_WAITQUEUE(entry, current); |
@@ -237,15 +400,14 @@ int drm_release(struct inode *inode, struct file *filp) | |||
237 | __set_current_state(TASK_RUNNING); | 400 | __set_current_state(TASK_RUNNING); |
238 | remove_wait_queue(&dev->lock.lock_queue, &entry); | 401 | remove_wait_queue(&dev->lock.lock_queue, &entry); |
239 | if (!retcode) { | 402 | if (!retcode) { |
240 | if (dev->driver->release) | 403 | dev->driver->reclaim_buffers_locked(dev, filp); |
241 | dev->driver->release(dev, filp); | ||
242 | drm_lock_free(dev, &dev->lock.hw_lock->lock, | 404 | drm_lock_free(dev, &dev->lock.hw_lock->lock, |
243 | DRM_KERNEL_CONTEXT); | 405 | DRM_KERNEL_CONTEXT); |
244 | } | 406 | } |
245 | } | 407 | } |
246 | 408 | ||
247 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) | 409 | if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && |
248 | && !dev->driver->release) { | 410 | !dev->driver->reclaim_buffers_locked) { |
249 | dev->driver->reclaim_buffers(dev, filp); | 411 | dev->driver->reclaim_buffers(dev, filp); |
250 | } | 412 | } |
251 | 413 | ||
@@ -292,9 +454,8 @@ int drm_release(struct inode *inode, struct file *filp) | |||
292 | } | 454 | } |
293 | up(&dev->struct_sem); | 455 | up(&dev->struct_sem); |
294 | 456 | ||
295 | if (dev->driver->free_filp_priv) | 457 | if (dev->driver->postclose) |
296 | dev->driver->free_filp_priv(dev, priv); | 458 | dev->driver->postclose(dev, priv); |
297 | |||
298 | drm_free(priv, sizeof(*priv), DRM_MEM_FILES); | 459 | drm_free(priv, sizeof(*priv), DRM_MEM_FILES); |
299 | 460 | ||
300 | /* ======================================================== | 461 | /* ======================================================== |
@@ -313,7 +474,7 @@ int drm_release(struct inode *inode, struct file *filp) | |||
313 | } | 474 | } |
314 | spin_unlock(&dev->count_lock); | 475 | spin_unlock(&dev->count_lock); |
315 | unlock_kernel(); | 476 | unlock_kernel(); |
316 | return drm_takedown(dev); | 477 | return drm_lastclose(dev); |
317 | } | 478 | } |
318 | spin_unlock(&dev->count_lock); | 479 | spin_unlock(&dev->count_lock); |
319 | 480 | ||
@@ -321,129 +482,11 @@ int drm_release(struct inode *inode, struct file *filp) | |||
321 | 482 | ||
322 | return retcode; | 483 | return retcode; |
323 | } | 484 | } |
324 | |||
325 | EXPORT_SYMBOL(drm_release); | 485 | EXPORT_SYMBOL(drm_release); |
326 | 486 | ||
327 | /** | ||
328 | * Called whenever a process opens /dev/drm. | ||
329 | * | ||
330 | * \param inode device inode. | ||
331 | * \param filp file pointer. | ||
332 | * \param dev device. | ||
333 | * \return zero on success or a negative number on failure. | ||
334 | * | ||
335 | * Creates and initializes a drm_file structure for the file private data in \p | ||
336 | * filp and add it into the double linked list in \p dev. | ||
337 | */ | ||
338 | static int drm_open_helper(struct inode *inode, struct file *filp, | ||
339 | drm_device_t * dev) | ||
340 | { | ||
341 | int minor = iminor(inode); | ||
342 | drm_file_t *priv; | ||
343 | int ret; | ||
344 | |||
345 | if (filp->f_flags & O_EXCL) | ||
346 | return -EBUSY; /* No exclusive opens */ | ||
347 | if (!drm_cpu_valid()) | ||
348 | return -EINVAL; | ||
349 | |||
350 | DRM_DEBUG("pid = %d, minor = %d\n", current->pid, minor); | ||
351 | |||
352 | priv = drm_alloc(sizeof(*priv), DRM_MEM_FILES); | ||
353 | if (!priv) | ||
354 | return -ENOMEM; | ||
355 | |||
356 | memset(priv, 0, sizeof(*priv)); | ||
357 | filp->private_data = priv; | ||
358 | priv->uid = current->euid; | ||
359 | priv->pid = current->pid; | ||
360 | priv->minor = minor; | ||
361 | priv->head = drm_heads[minor]; | ||
362 | priv->ioctl_count = 0; | ||
363 | priv->authenticated = capable(CAP_SYS_ADMIN); | ||
364 | priv->lock_count = 0; | ||
365 | |||
366 | if (dev->driver->open_helper) { | ||
367 | ret = dev->driver->open_helper(dev, priv); | ||
368 | if (ret < 0) | ||
369 | goto out_free; | ||
370 | } | ||
371 | |||
372 | down(&dev->struct_sem); | ||
373 | if (!dev->file_last) { | ||
374 | priv->next = NULL; | ||
375 | priv->prev = NULL; | ||
376 | dev->file_first = priv; | ||
377 | dev->file_last = priv; | ||
378 | } else { | ||
379 | priv->next = NULL; | ||
380 | priv->prev = dev->file_last; | ||
381 | dev->file_last->next = priv; | ||
382 | dev->file_last = priv; | ||
383 | } | ||
384 | up(&dev->struct_sem); | ||
385 | |||
386 | #ifdef __alpha__ | ||
387 | /* | ||
388 | * Default the hose | ||
389 | */ | ||
390 | if (!dev->hose) { | ||
391 | struct pci_dev *pci_dev; | ||
392 | pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL); | ||
393 | if (pci_dev) { | ||
394 | dev->hose = pci_dev->sysdata; | ||
395 | pci_dev_put(pci_dev); | ||
396 | } | ||
397 | if (!dev->hose) { | ||
398 | struct pci_bus *b = pci_bus_b(pci_root_buses.next); | ||
399 | if (b) | ||
400 | dev->hose = b->sysdata; | ||
401 | } | ||
402 | } | ||
403 | #endif | ||
404 | |||
405 | return 0; | ||
406 | out_free: | ||
407 | drm_free(priv, sizeof(*priv), DRM_MEM_FILES); | ||
408 | filp->private_data = NULL; | ||
409 | return ret; | ||
410 | } | ||
411 | |||
412 | /** No-op. */ | ||
413 | int drm_flush(struct file *filp) | ||
414 | { | ||
415 | drm_file_t *priv = filp->private_data; | ||
416 | drm_device_t *dev = priv->head->dev; | ||
417 | |||
418 | DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", | ||
419 | current->pid, (long)old_encode_dev(priv->head->device), | ||
420 | dev->open_count); | ||
421 | return 0; | ||
422 | } | ||
423 | |||
424 | EXPORT_SYMBOL(drm_flush); | ||
425 | |||
426 | /** No-op. */ | ||
427 | int drm_fasync(int fd, struct file *filp, int on) | ||
428 | { | ||
429 | drm_file_t *priv = filp->private_data; | ||
430 | drm_device_t *dev = priv->head->dev; | ||
431 | int retcode; | ||
432 | |||
433 | DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, | ||
434 | (long)old_encode_dev(priv->head->device)); | ||
435 | retcode = fasync_helper(fd, filp, on, &dev->buf_async); | ||
436 | if (retcode < 0) | ||
437 | return retcode; | ||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | EXPORT_SYMBOL(drm_fasync); | ||
442 | |||
443 | /** No-op. */ | 487 | /** No-op. */ |
444 | unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) | 488 | unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait) |
445 | { | 489 | { |
446 | return 0; | 490 | return 0; |
447 | } | 491 | } |
448 | |||
449 | EXPORT_SYMBOL(drm_poll); | 492 | EXPORT_SYMBOL(drm_poll); |
diff --git a/drivers/char/drm/drm_init.c b/drivers/char/drm/drm_init.c deleted file mode 100644 index 754b934715c4..000000000000 --- a/drivers/char/drm/drm_init.c +++ /dev/null | |||
@@ -1,53 +0,0 @@ | |||
1 | /** | ||
2 | * \file drm_init.c | ||
3 | * Setup/Cleanup for DRM | ||
4 | * | ||
5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> | ||
6 | * \author Gareth Hughes <gareth@valinux.com> | ||
7 | */ | ||
8 | |||
9 | /* | ||
10 | * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com | ||
11 | * | ||
12 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | ||
13 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | ||
14 | * All Rights Reserved. | ||
15 | * | ||
16 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
17 | * copy of this software and associated documentation files (the "Software"), | ||
18 | * to deal in the Software without restriction, including without limitation | ||
19 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
20 | * and/or sell copies of the Software, and to permit persons to whom the | ||
21 | * Software is furnished to do so, subject to the following conditions: | ||
22 | * | ||
23 | * The above copyright notice and this permission notice (including the next | ||
24 | * paragraph) shall be included in all copies or substantial portions of the | ||
25 | * Software. | ||
26 | * | ||
27 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
28 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
29 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
30 | * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
31 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
32 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
33 | * OTHER DEALINGS IN THE SOFTWARE. | ||
34 | */ | ||
35 | |||
36 | #include "drmP.h" | ||
37 | |||
38 | /** | ||
39 | * Check whether DRI will run on this CPU. | ||
40 | * | ||
41 | * \return non-zero if the DRI will run on this CPU, or zero otherwise. | ||
42 | */ | ||
43 | int drm_cpu_valid(void) | ||
44 | { | ||
45 | #if defined(__i386__) | ||
46 | if (boot_cpu_data.x86 == 3) | ||
47 | return 0; /* No cmpxchg on a 386 */ | ||
48 | #endif | ||
49 | #if defined(__sparc__) && !defined(__sparc_v9__) | ||
50 | return 0; /* No cmpxchg before v9 sparc. */ | ||
51 | #endif | ||
52 | return 1; | ||
53 | } | ||
diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c index 9b0feba6b063..bcd4e604d3ec 100644 --- a/drivers/char/drm/drm_ioctl.c +++ b/drivers/char/drm/drm_ioctl.c | |||
@@ -137,17 +137,22 @@ int drm_setunique(struct inode *inode, struct file *filp, | |||
137 | 137 | ||
138 | static int drm_set_busid(drm_device_t * dev) | 138 | static int drm_set_busid(drm_device_t * dev) |
139 | { | 139 | { |
140 | int len; | ||
141 | |||
140 | if (dev->unique != NULL) | 142 | if (dev->unique != NULL) |
141 | return EBUSY; | 143 | return EBUSY; |
142 | 144 | ||
143 | dev->unique_len = 20; | 145 | dev->unique_len = 40; |
144 | dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER); | 146 | dev->unique = drm_alloc(dev->unique_len + 1, DRM_MEM_DRIVER); |
145 | if (dev->unique == NULL) | 147 | if (dev->unique == NULL) |
146 | return ENOMEM; | 148 | return ENOMEM; |
147 | 149 | ||
148 | snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d", | 150 | len = snprintf(dev->unique, dev->unique_len, "pci:%04x:%02x:%02x.%d", |
149 | dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func); | 151 | dev->pci_domain, dev->pci_bus, dev->pci_slot, dev->pci_func); |
150 | 152 | ||
153 | if (len > dev->unique_len) | ||
154 | DRM_ERROR("Unique buffer overflowed\n"); | ||
155 | |||
151 | dev->devname = | 156 | dev->devname = |
152 | drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + | 157 | drm_alloc(strlen(dev->driver->pci_driver.name) + dev->unique_len + |
153 | 2, DRM_MEM_DRIVER); | 158 | 2, DRM_MEM_DRIVER); |
@@ -239,7 +244,7 @@ int drm_getclient(struct inode *inode, struct file *filp, | |||
239 | { | 244 | { |
240 | drm_file_t *priv = filp->private_data; | 245 | drm_file_t *priv = filp->private_data; |
241 | drm_device_t *dev = priv->head->dev; | 246 | drm_device_t *dev = priv->head->dev; |
242 | drm_client_t __user *argp = (void __user *)arg; | 247 | drm_client_t __user *argp = (drm_client_t __user *)arg; |
243 | drm_client_t client; | 248 | drm_client_t client; |
244 | drm_file_t *pt; | 249 | drm_file_t *pt; |
245 | int idx; | 250 | int idx; |
@@ -262,7 +267,7 @@ int drm_getclient(struct inode *inode, struct file *filp, | |||
262 | client.iocs = pt->ioctl_count; | 267 | client.iocs = pt->ioctl_count; |
263 | up(&dev->struct_sem); | 268 | up(&dev->struct_sem); |
264 | 269 | ||
265 | if (copy_to_user((drm_client_t __user *) arg, &client, sizeof(client))) | 270 | if (copy_to_user(argp, &client, sizeof(client))) |
266 | return -EFAULT; | 271 | return -EFAULT; |
267 | return 0; | 272 | return 0; |
268 | } | 273 | } |
@@ -325,17 +330,13 @@ int drm_setversion(DRM_IOCTL_ARGS) | |||
325 | drm_set_version_t retv; | 330 | drm_set_version_t retv; |
326 | int if_version; | 331 | int if_version; |
327 | drm_set_version_t __user *argp = (void __user *)data; | 332 | drm_set_version_t __user *argp = (void __user *)data; |
328 | drm_version_t version; | ||
329 | 333 | ||
330 | DRM_COPY_FROM_USER_IOCTL(sv, argp, sizeof(sv)); | 334 | DRM_COPY_FROM_USER_IOCTL(sv, argp, sizeof(sv)); |
331 | 335 | ||
332 | memset(&version, 0, sizeof(version)); | ||
333 | |||
334 | dev->driver->version(&version); | ||
335 | retv.drm_di_major = DRM_IF_MAJOR; | 336 | retv.drm_di_major = DRM_IF_MAJOR; |
336 | retv.drm_di_minor = DRM_IF_MINOR; | 337 | retv.drm_di_minor = DRM_IF_MINOR; |
337 | retv.drm_dd_major = version.version_major; | 338 | retv.drm_dd_major = dev->driver->major; |
338 | retv.drm_dd_minor = version.version_minor; | 339 | retv.drm_dd_minor = dev->driver->minor; |
339 | 340 | ||
340 | DRM_COPY_TO_USER_IOCTL(argp, retv, sizeof(sv)); | 341 | DRM_COPY_TO_USER_IOCTL(argp, retv, sizeof(sv)); |
341 | 342 | ||
@@ -343,7 +344,7 @@ int drm_setversion(DRM_IOCTL_ARGS) | |||
343 | if (sv.drm_di_major != DRM_IF_MAJOR || | 344 | if (sv.drm_di_major != DRM_IF_MAJOR || |
344 | sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR) | 345 | sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR) |
345 | return EINVAL; | 346 | return EINVAL; |
346 | if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_dd_minor); | 347 | if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_di_minor); |
347 | dev->if_version = DRM_MAX(if_version, dev->if_version); | 348 | dev->if_version = DRM_MAX(if_version, dev->if_version); |
348 | if (sv.drm_di_minor >= 1) { | 349 | if (sv.drm_di_minor >= 1) { |
349 | /* | 350 | /* |
@@ -354,9 +355,9 @@ int drm_setversion(DRM_IOCTL_ARGS) | |||
354 | } | 355 | } |
355 | 356 | ||
356 | if (sv.drm_dd_major != -1) { | 357 | if (sv.drm_dd_major != -1) { |
357 | if (sv.drm_dd_major != version.version_major || | 358 | if (sv.drm_dd_major != dev->driver->major || |
358 | sv.drm_dd_minor < 0 | 359 | sv.drm_dd_minor < 0 |
359 | || sv.drm_dd_minor > version.version_minor) | 360 | || sv.drm_dd_minor > dev->driver->minor) |
360 | return EINVAL; | 361 | return EINVAL; |
361 | 362 | ||
362 | if (dev->driver->set_version) | 363 | if (dev->driver->set_version) |
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c index b48a595d54ec..f9e45303498d 100644 --- a/drivers/char/drm/drm_lock.c +++ b/drivers/char/drm/drm_lock.c | |||
@@ -130,7 +130,6 @@ int drm_lock(struct inode *inode, struct file *filp, | |||
130 | /* dev->driver->kernel_context_switch isn't used by any of the x86 | 130 | /* dev->driver->kernel_context_switch isn't used by any of the x86 |
131 | * drivers but is used by the Sparc driver. | 131 | * drivers but is used by the Sparc driver. |
132 | */ | 132 | */ |
133 | |||
134 | if (dev->driver->kernel_context_switch && | 133 | if (dev->driver->kernel_context_switch && |
135 | dev->last_context != lock.context) { | 134 | dev->last_context != lock.context) { |
136 | dev->driver->kernel_context_switch(dev, dev->last_context, | 135 | dev->driver->kernel_context_switch(dev, dev->last_context, |
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c index abef2acf99f5..8074771e348f 100644 --- a/drivers/char/drm/drm_memory.c +++ b/drivers/char/drm/drm_memory.c | |||
@@ -145,30 +145,22 @@ DRM_AGP_MEM *drm_alloc_agp(drm_device_t * dev, int pages, u32 type) | |||
145 | return drm_agp_allocate_memory(dev->agp->bridge, pages, type); | 145 | return drm_agp_allocate_memory(dev->agp->bridge, pages, type); |
146 | } | 146 | } |
147 | 147 | ||
148 | EXPORT_SYMBOL(drm_alloc_agp); | ||
149 | |||
150 | /** Wrapper around agp_free_memory() */ | 148 | /** Wrapper around agp_free_memory() */ |
151 | int drm_free_agp(DRM_AGP_MEM * handle, int pages) | 149 | int drm_free_agp(DRM_AGP_MEM * handle, int pages) |
152 | { | 150 | { |
153 | return drm_agp_free_memory(handle) ? 0 : -EINVAL; | 151 | return drm_agp_free_memory(handle) ? 0 : -EINVAL; |
154 | } | 152 | } |
155 | 153 | ||
156 | EXPORT_SYMBOL(drm_free_agp); | ||
157 | |||
158 | /** Wrapper around agp_bind_memory() */ | 154 | /** Wrapper around agp_bind_memory() */ |
159 | int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start) | 155 | int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start) |
160 | { | 156 | { |
161 | return drm_agp_bind_memory(handle, start); | 157 | return drm_agp_bind_memory(handle, start); |
162 | } | 158 | } |
163 | 159 | ||
164 | EXPORT_SYMBOL(drm_bind_agp); | ||
165 | |||
166 | /** Wrapper around agp_unbind_memory() */ | 160 | /** Wrapper around agp_unbind_memory() */ |
167 | int drm_unbind_agp(DRM_AGP_MEM * handle) | 161 | int drm_unbind_agp(DRM_AGP_MEM * handle) |
168 | { | 162 | { |
169 | return drm_agp_unbind_memory(handle); | 163 | return drm_agp_unbind_memory(handle); |
170 | } | 164 | } |
171 | |||
172 | EXPORT_SYMBOL(drm_unbind_agp); | ||
173 | #endif /* agp */ | 165 | #endif /* agp */ |
174 | #endif /* debug_memory */ | 166 | #endif /* debug_memory */ |
diff --git a/drivers/char/drm/drm_memory_debug.h b/drivers/char/drm/drm_memory_debug.h index b370aca718d2..e84605fc54af 100644 --- a/drivers/char/drm/drm_memory_debug.h +++ b/drivers/char/drm/drm_memory_debug.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /** | 1 | /** |
2 | * \file drm_memory.h | 2 | * \file drm_memory_debug.h |
3 | * Memory management wrappers for DRM. | 3 | * Memory management wrappers for DRM. |
4 | * | 4 | * |
5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> | 5 | * \author Rickard E. (Rik) Faith <faith@valinux.com> |
@@ -43,42 +43,41 @@ typedef struct drm_mem_stats { | |||
43 | unsigned long bytes_freed; | 43 | unsigned long bytes_freed; |
44 | } drm_mem_stats_t; | 44 | } drm_mem_stats_t; |
45 | 45 | ||
46 | static DEFINE_SPINLOCK(DRM(mem_lock)); | 46 | static spinlock_t drm_mem_lock = SPIN_LOCK_UNLOCKED; |
47 | static unsigned long DRM(ram_available) = 0; /* In pages */ | 47 | static unsigned long drm_ram_available = 0; /* In pages */ |
48 | static unsigned long DRM(ram_used) = 0; | 48 | static unsigned long drm_ram_used = 0; |
49 | static drm_mem_stats_t DRM(mem_stats)[] = | 49 | static drm_mem_stats_t drm_mem_stats[] = |
50 | { | 50 | { |
51 | [DRM_MEM_DMA] = { | 51 | [DRM_MEM_DMA] = {"dmabufs"}, |
52 | "dmabufs"},[DRM_MEM_SAREA] = { | 52 | [DRM_MEM_SAREA] = {"sareas"}, |
53 | "sareas"},[DRM_MEM_DRIVER] = { | 53 | [DRM_MEM_DRIVER] = {"driver"}, |
54 | "driver"},[DRM_MEM_MAGIC] = { | 54 | [DRM_MEM_MAGIC] = {"magic"}, |
55 | "magic"},[DRM_MEM_IOCTLS] = { | 55 | [DRM_MEM_IOCTLS] = {"ioctltab"}, |
56 | "ioctltab"},[DRM_MEM_MAPS] = { | 56 | [DRM_MEM_MAPS] = {"maplist"}, |
57 | "maplist"},[DRM_MEM_VMAS] = { | 57 | [DRM_MEM_VMAS] = {"vmalist"}, |
58 | "vmalist"},[DRM_MEM_BUFS] = { | 58 | [DRM_MEM_BUFS] = {"buflist"}, |
59 | "buflist"},[DRM_MEM_SEGS] = { | 59 | [DRM_MEM_SEGS] = {"seglist"}, |
60 | "seglist"},[DRM_MEM_PAGES] = { | 60 | [DRM_MEM_PAGES] = {"pagelist"}, |
61 | "pagelist"},[DRM_MEM_FILES] = { | 61 | [DRM_MEM_FILES] = {"files"}, |
62 | "files"},[DRM_MEM_QUEUES] = { | 62 | [DRM_MEM_QUEUES] = {"queues"}, |
63 | "queues"},[DRM_MEM_CMDS] = { | 63 | [DRM_MEM_CMDS] = {"commands"}, |
64 | "commands"},[DRM_MEM_MAPPINGS] = { | 64 | [DRM_MEM_MAPPINGS] = {"mappings"}, |
65 | "mappings"},[DRM_MEM_BUFLISTS] = { | 65 | [DRM_MEM_BUFLISTS] = {"buflists"}, |
66 | "buflists"},[DRM_MEM_AGPLISTS] = { | 66 | [DRM_MEM_AGPLISTS] = {"agplist"}, |
67 | "agplist"},[DRM_MEM_SGLISTS] = { | 67 | [DRM_MEM_SGLISTS] = {"sglist"}, |
68 | "sglist"},[DRM_MEM_TOTALAGP] = { | 68 | [DRM_MEM_TOTALAGP] = {"totalagp"}, |
69 | "totalagp"},[DRM_MEM_BOUNDAGP] = { | 69 | [DRM_MEM_BOUNDAGP] = {"boundagp"}, |
70 | "boundagp"},[DRM_MEM_CTXBITMAP] = { | 70 | [DRM_MEM_CTXBITMAP] = {"ctxbitmap"}, |
71 | "ctxbitmap"},[DRM_MEM_CTXLIST] = { | 71 | [DRM_MEM_CTXLIST] = {"ctxlist"}, |
72 | "ctxlist"},[DRM_MEM_STUB] = { | 72 | [DRM_MEM_STUB] = {"stub"}, |
73 | "stub"}, { | 73 | {NULL, 0,} /* Last entry must be null */ |
74 | NULL, 0,} /* Last entry must be null */ | ||
75 | }; | 74 | }; |
76 | 75 | ||
77 | void DRM(mem_init) (void) { | 76 | void drm_mem_init (void) { |
78 | drm_mem_stats_t *mem; | 77 | drm_mem_stats_t *mem; |
79 | struct sysinfo si; | 78 | struct sysinfo si; |
80 | 79 | ||
81 | for (mem = DRM(mem_stats); mem->name; ++mem) { | 80 | for (mem = drm_mem_stats; mem->name; ++mem) { |
82 | mem->succeed_count = 0; | 81 | mem->succeed_count = 0; |
83 | mem->free_count = 0; | 82 | mem->free_count = 0; |
84 | mem->fail_count = 0; | 83 | mem->fail_count = 0; |
@@ -87,13 +86,13 @@ void DRM(mem_init) (void) { | |||
87 | } | 86 | } |
88 | 87 | ||
89 | si_meminfo(&si); | 88 | si_meminfo(&si); |
90 | DRM(ram_available) = si.totalram; | 89 | drm_ram_available = si.totalram; |
91 | DRM(ram_used) = 0; | 90 | drm_ram_used = 0; |
92 | } | 91 | } |
93 | 92 | ||
94 | /* drm_mem_info is called whenever a process reads /dev/drm/mem. */ | 93 | /* drm_mem_info is called whenever a process reads /dev/drm/mem. */ |
95 | 94 | ||
96 | static int DRM(_mem_info) (char *buf, char **start, off_t offset, | 95 | static int drm__mem_info (char *buf, char **start, off_t offset, |
97 | int request, int *eof, void *data) { | 96 | int request, int *eof, void *data) { |
98 | drm_mem_stats_t *pt; | 97 | drm_mem_stats_t *pt; |
99 | int len = 0; | 98 | int len = 0; |
@@ -112,11 +111,11 @@ static int DRM(_mem_info) (char *buf, char **start, off_t offset, | |||
112 | " | allocs bytes\n\n"); | 111 | " | allocs bytes\n\n"); |
113 | DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n", | 112 | DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n", |
114 | "system", 0, 0, 0, | 113 | "system", 0, 0, 0, |
115 | DRM(ram_available) << (PAGE_SHIFT - 10)); | 114 | drm_ram_available << (PAGE_SHIFT - 10)); |
116 | DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n", | 115 | DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu kB |\n", |
117 | "locked", 0, 0, 0, DRM(ram_used) >> 10); | 116 | "locked", 0, 0, 0, drm_ram_used >> 10); |
118 | DRM_PROC_PRINT("\n"); | 117 | DRM_PROC_PRINT("\n"); |
119 | for (pt = DRM(mem_stats); pt->name; pt++) { | 118 | for (pt = drm_mem_stats; pt->name; pt++) { |
120 | DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n", | 119 | DRM_PROC_PRINT("%-9.9s %5d %5d %4d %10lu %10lu | %6d %10ld\n", |
121 | pt->name, | 120 | pt->name, |
122 | pt->succeed_count, | 121 | pt->succeed_count, |
@@ -135,17 +134,17 @@ static int DRM(_mem_info) (char *buf, char **start, off_t offset, | |||
135 | return len - offset; | 134 | return len - offset; |
136 | } | 135 | } |
137 | 136 | ||
138 | int DRM(mem_info) (char *buf, char **start, off_t offset, | 137 | int drm_mem_info (char *buf, char **start, off_t offset, |
139 | int len, int *eof, void *data) { | 138 | int len, int *eof, void *data) { |
140 | int ret; | 139 | int ret; |
141 | 140 | ||
142 | spin_lock(&DRM(mem_lock)); | 141 | spin_lock(&drm_mem_lock); |
143 | ret = DRM(_mem_info) (buf, start, offset, len, eof, data); | 142 | ret = drm__mem_info (buf, start, offset, len, eof, data); |
144 | spin_unlock(&DRM(mem_lock)); | 143 | spin_unlock(&drm_mem_lock); |
145 | return ret; | 144 | return ret; |
146 | } | 145 | } |
147 | 146 | ||
148 | void *DRM(alloc) (size_t size, int area) { | 147 | void *drm_alloc (size_t size, int area) { |
149 | void *pt; | 148 | void *pt; |
150 | 149 | ||
151 | if (!size) { | 150 | if (!size) { |
@@ -154,41 +153,41 @@ void *DRM(alloc) (size_t size, int area) { | |||
154 | } | 153 | } |
155 | 154 | ||
156 | if (!(pt = kmalloc(size, GFP_KERNEL))) { | 155 | if (!(pt = kmalloc(size, GFP_KERNEL))) { |
157 | spin_lock(&DRM(mem_lock)); | 156 | spin_lock(&drm_mem_lock); |
158 | ++DRM(mem_stats)[area].fail_count; | 157 | ++drm_mem_stats[area].fail_count; |
159 | spin_unlock(&DRM(mem_lock)); | 158 | spin_unlock(&drm_mem_lock); |
160 | return NULL; | 159 | return NULL; |
161 | } | 160 | } |
162 | spin_lock(&DRM(mem_lock)); | 161 | spin_lock(&drm_mem_lock); |
163 | ++DRM(mem_stats)[area].succeed_count; | 162 | ++drm_mem_stats[area].succeed_count; |
164 | DRM(mem_stats)[area].bytes_allocated += size; | 163 | drm_mem_stats[area].bytes_allocated += size; |
165 | spin_unlock(&DRM(mem_lock)); | 164 | spin_unlock(&drm_mem_lock); |
166 | return pt; | 165 | return pt; |
167 | } | 166 | } |
168 | 167 | ||
169 | void *DRM(calloc) (size_t nmemb, size_t size, int area) { | 168 | void *drm_calloc (size_t nmemb, size_t size, int area) { |
170 | void *addr; | 169 | void *addr; |
171 | 170 | ||
172 | addr = DRM(alloc) (nmemb * size, area); | 171 | addr = drm_alloc (nmemb * size, area); |
173 | if (addr != NULL) | 172 | if (addr != NULL) |
174 | memset((void *)addr, 0, size * nmemb); | 173 | memset((void *)addr, 0, size * nmemb); |
175 | 174 | ||
176 | return addr; | 175 | return addr; |
177 | } | 176 | } |
178 | 177 | ||
179 | void *DRM(realloc) (void *oldpt, size_t oldsize, size_t size, int area) { | 178 | void *drm_realloc (void *oldpt, size_t oldsize, size_t size, int area) { |
180 | void *pt; | 179 | void *pt; |
181 | 180 | ||
182 | if (!(pt = DRM(alloc) (size, area))) | 181 | if (!(pt = drm_alloc (size, area))) |
183 | return NULL; | 182 | return NULL; |
184 | if (oldpt && oldsize) { | 183 | if (oldpt && oldsize) { |
185 | memcpy(pt, oldpt, oldsize); | 184 | memcpy(pt, oldpt, oldsize); |
186 | DRM(free) (oldpt, oldsize, area); | 185 | drm_free (oldpt, oldsize, area); |
187 | } | 186 | } |
188 | return pt; | 187 | return pt; |
189 | } | 188 | } |
190 | 189 | ||
191 | void DRM(free) (void *pt, size_t size, int area) { | 190 | void drm_free (void *pt, size_t size, int area) { |
192 | int alloc_count; | 191 | int alloc_count; |
193 | int free_count; | 192 | int free_count; |
194 | 193 | ||
@@ -196,43 +195,43 @@ void DRM(free) (void *pt, size_t size, int area) { | |||
196 | DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n"); | 195 | DRM_MEM_ERROR(area, "Attempt to free NULL pointer\n"); |
197 | else | 196 | else |
198 | kfree(pt); | 197 | kfree(pt); |
199 | spin_lock(&DRM(mem_lock)); | 198 | spin_lock(&drm_mem_lock); |
200 | DRM(mem_stats)[area].bytes_freed += size; | 199 | drm_mem_stats[area].bytes_freed += size; |
201 | free_count = ++DRM(mem_stats)[area].free_count; | 200 | free_count = ++drm_mem_stats[area].free_count; |
202 | alloc_count = DRM(mem_stats)[area].succeed_count; | 201 | alloc_count = drm_mem_stats[area].succeed_count; |
203 | spin_unlock(&DRM(mem_lock)); | 202 | spin_unlock(&drm_mem_lock); |
204 | if (free_count > alloc_count) { | 203 | if (free_count > alloc_count) { |
205 | DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n", | 204 | DRM_MEM_ERROR(area, "Excess frees: %d frees, %d allocs\n", |
206 | free_count, alloc_count); | 205 | free_count, alloc_count); |
207 | } | 206 | } |
208 | } | 207 | } |
209 | 208 | ||
210 | unsigned long DRM(alloc_pages) (int order, int area) { | 209 | unsigned long drm_alloc_pages (int order, int area) { |
211 | unsigned long address; | 210 | unsigned long address; |
212 | unsigned long bytes = PAGE_SIZE << order; | 211 | unsigned long bytes = PAGE_SIZE << order; |
213 | unsigned long addr; | 212 | unsigned long addr; |
214 | unsigned int sz; | 213 | unsigned int sz; |
215 | 214 | ||
216 | spin_lock(&DRM(mem_lock)); | 215 | spin_lock(&drm_mem_lock); |
217 | if ((DRM(ram_used) >> PAGE_SHIFT) | 216 | if ((drm_ram_used >> PAGE_SHIFT) |
218 | > (DRM_RAM_PERCENT * DRM(ram_available)) / 100) { | 217 | > (DRM_RAM_PERCENT * drm_ram_available) / 100) { |
219 | spin_unlock(&DRM(mem_lock)); | 218 | spin_unlock(&drm_mem_lock); |
220 | return 0; | 219 | return 0; |
221 | } | 220 | } |
222 | spin_unlock(&DRM(mem_lock)); | 221 | spin_unlock(&drm_mem_lock); |
223 | 222 | ||
224 | address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); | 223 | address = __get_free_pages(GFP_KERNEL|__GFP_COMP, order); |
225 | if (!address) { | 224 | if (!address) { |
226 | spin_lock(&DRM(mem_lock)); | 225 | spin_lock(&drm_mem_lock); |
227 | ++DRM(mem_stats)[area].fail_count; | 226 | ++drm_mem_stats[area].fail_count; |
228 | spin_unlock(&DRM(mem_lock)); | 227 | spin_unlock(&drm_mem_lock); |
229 | return 0; | 228 | return 0; |
230 | } | 229 | } |
231 | spin_lock(&DRM(mem_lock)); | 230 | spin_lock(&drm_mem_lock); |
232 | ++DRM(mem_stats)[area].succeed_count; | 231 | ++drm_mem_stats[area].succeed_count; |
233 | DRM(mem_stats)[area].bytes_allocated += bytes; | 232 | drm_mem_stats[area].bytes_allocated += bytes; |
234 | DRM(ram_used) += bytes; | 233 | drm_ram_used += bytes; |
235 | spin_unlock(&DRM(mem_lock)); | 234 | spin_unlock(&drm_mem_lock); |
236 | 235 | ||
237 | /* Zero outside the lock */ | 236 | /* Zero outside the lock */ |
238 | memset((void *)address, 0, bytes); | 237 | memset((void *)address, 0, bytes); |
@@ -246,7 +245,7 @@ unsigned long DRM(alloc_pages) (int order, int area) { | |||
246 | return address; | 245 | return address; |
247 | } | 246 | } |
248 | 247 | ||
249 | void DRM(free_pages) (unsigned long address, int order, int area) { | 248 | void drm_free_pages (unsigned long address, int order, int area) { |
250 | unsigned long bytes = PAGE_SIZE << order; | 249 | unsigned long bytes = PAGE_SIZE << order; |
251 | int alloc_count; | 250 | int alloc_count; |
252 | int free_count; | 251 | int free_count; |
@@ -264,12 +263,12 @@ void DRM(free_pages) (unsigned long address, int order, int area) { | |||
264 | free_pages(address, order); | 263 | free_pages(address, order); |
265 | } | 264 | } |
266 | 265 | ||
267 | spin_lock(&DRM(mem_lock)); | 266 | spin_lock(&drm_mem_lock); |
268 | free_count = ++DRM(mem_stats)[area].free_count; | 267 | free_count = ++drm_mem_stats[area].free_count; |
269 | alloc_count = DRM(mem_stats)[area].succeed_count; | 268 | alloc_count = drm_mem_stats[area].succeed_count; |
270 | DRM(mem_stats)[area].bytes_freed += bytes; | 269 | drm_mem_stats[area].bytes_freed += bytes; |
271 | DRM(ram_used) -= bytes; | 270 | drm_ram_used -= bytes; |
272 | spin_unlock(&DRM(mem_lock)); | 271 | spin_unlock(&drm_mem_lock); |
273 | if (free_count > alloc_count) { | 272 | if (free_count > alloc_count) { |
274 | DRM_MEM_ERROR(area, | 273 | DRM_MEM_ERROR(area, |
275 | "Excess frees: %d frees, %d allocs\n", | 274 | "Excess frees: %d frees, %d allocs\n", |
@@ -277,7 +276,7 @@ void DRM(free_pages) (unsigned long address, int order, int area) { | |||
277 | } | 276 | } |
278 | } | 277 | } |
279 | 278 | ||
280 | void *DRM(ioremap) (unsigned long offset, unsigned long size, | 279 | void *drm_ioremap (unsigned long offset, unsigned long size, |
281 | drm_device_t * dev) { | 280 | drm_device_t * dev) { |
282 | void *pt; | 281 | void *pt; |
283 | 282 | ||
@@ -288,19 +287,19 @@ void *DRM(ioremap) (unsigned long offset, unsigned long size, | |||
288 | } | 287 | } |
289 | 288 | ||
290 | if (!(pt = drm_ioremap(offset, size, dev))) { | 289 | if (!(pt = drm_ioremap(offset, size, dev))) { |
291 | spin_lock(&DRM(mem_lock)); | 290 | spin_lock(&drm_mem_lock); |
292 | ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; | 291 | ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count; |
293 | spin_unlock(&DRM(mem_lock)); | 292 | spin_unlock(&drm_mem_lock); |
294 | return NULL; | 293 | return NULL; |
295 | } | 294 | } |
296 | spin_lock(&DRM(mem_lock)); | 295 | spin_lock(&drm_mem_lock); |
297 | ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; | 296 | ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; |
298 | DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size; | 297 | drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size; |
299 | spin_unlock(&DRM(mem_lock)); | 298 | spin_unlock(&drm_mem_lock); |
300 | return pt; | 299 | return pt; |
301 | } | 300 | } |
302 | 301 | ||
303 | void *DRM(ioremap_nocache) (unsigned long offset, unsigned long size, | 302 | void *drm_ioremap_nocache (unsigned long offset, unsigned long size, |
304 | drm_device_t * dev) { | 303 | drm_device_t * dev) { |
305 | void *pt; | 304 | void *pt; |
306 | 305 | ||
@@ -311,19 +310,19 @@ void *DRM(ioremap_nocache) (unsigned long offset, unsigned long size, | |||
311 | } | 310 | } |
312 | 311 | ||
313 | if (!(pt = drm_ioremap_nocache(offset, size, dev))) { | 312 | if (!(pt = drm_ioremap_nocache(offset, size, dev))) { |
314 | spin_lock(&DRM(mem_lock)); | 313 | spin_lock(&drm_mem_lock); |
315 | ++DRM(mem_stats)[DRM_MEM_MAPPINGS].fail_count; | 314 | ++drm_mem_stats[DRM_MEM_MAPPINGS].fail_count; |
316 | spin_unlock(&DRM(mem_lock)); | 315 | spin_unlock(&drm_mem_lock); |
317 | return NULL; | 316 | return NULL; |
318 | } | 317 | } |
319 | spin_lock(&DRM(mem_lock)); | 318 | spin_lock(&drm_mem_lock); |
320 | ++DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; | 319 | ++drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; |
321 | DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_allocated += size; | 320 | drm_mem_stats[DRM_MEM_MAPPINGS].bytes_allocated += size; |
322 | spin_unlock(&DRM(mem_lock)); | 321 | spin_unlock(&drm_mem_lock); |
323 | return pt; | 322 | return pt; |
324 | } | 323 | } |
325 | 324 | ||
326 | void DRM(ioremapfree) (void *pt, unsigned long size, drm_device_t * dev) { | 325 | void drm_ioremapfree (void *pt, unsigned long size, drm_device_t * dev) { |
327 | int alloc_count; | 326 | int alloc_count; |
328 | int free_count; | 327 | int free_count; |
329 | 328 | ||
@@ -333,11 +332,11 @@ void DRM(ioremapfree) (void *pt, unsigned long size, drm_device_t * dev) { | |||
333 | else | 332 | else |
334 | drm_ioremapfree(pt, size, dev); | 333 | drm_ioremapfree(pt, size, dev); |
335 | 334 | ||
336 | spin_lock(&DRM(mem_lock)); | 335 | spin_lock(&drm_mem_lock); |
337 | DRM(mem_stats)[DRM_MEM_MAPPINGS].bytes_freed += size; | 336 | drm_mem_stats[DRM_MEM_MAPPINGS].bytes_freed += size; |
338 | free_count = ++DRM(mem_stats)[DRM_MEM_MAPPINGS].free_count; | 337 | free_count = ++drm_mem_stats[DRM_MEM_MAPPINGS].free_count; |
339 | alloc_count = DRM(mem_stats)[DRM_MEM_MAPPINGS].succeed_count; | 338 | alloc_count = drm_mem_stats[DRM_MEM_MAPPINGS].succeed_count; |
340 | spin_unlock(&DRM(mem_lock)); | 339 | spin_unlock(&drm_mem_lock); |
341 | if (free_count > alloc_count) { | 340 | if (free_count > alloc_count) { |
342 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, | 341 | DRM_MEM_ERROR(DRM_MEM_MAPPINGS, |
343 | "Excess frees: %d frees, %d allocs\n", | 342 | "Excess frees: %d frees, %d allocs\n", |
@@ -347,7 +346,7 @@ void DRM(ioremapfree) (void *pt, unsigned long size, drm_device_t * dev) { | |||
347 | 346 | ||
348 | #if __OS_HAS_AGP | 347 | #if __OS_HAS_AGP |
349 | 348 | ||
350 | DRM_AGP_MEM *DRM(alloc_agp) (int pages, u32 type) { | 349 | DRM_AGP_MEM *drm_alloc_agp (drm_device_t *dev, int pages, u32 type) { |
351 | DRM_AGP_MEM *handle; | 350 | DRM_AGP_MEM *handle; |
352 | 351 | ||
353 | if (!pages) { | 352 | if (!pages) { |
@@ -355,21 +354,21 @@ DRM_AGP_MEM *DRM(alloc_agp) (int pages, u32 type) { | |||
355 | return NULL; | 354 | return NULL; |
356 | } | 355 | } |
357 | 356 | ||
358 | if ((handle = DRM(agp_allocate_memory) (pages, type))) { | 357 | if ((handle = drm_agp_allocate_memory (pages, type))) { |
359 | spin_lock(&DRM(mem_lock)); | 358 | spin_lock(&drm_mem_lock); |
360 | ++DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count; | 359 | ++drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count; |
361 | DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_allocated | 360 | drm_mem_stats[DRM_MEM_TOTALAGP].bytes_allocated |
362 | += pages << PAGE_SHIFT; | 361 | += pages << PAGE_SHIFT; |
363 | spin_unlock(&DRM(mem_lock)); | 362 | spin_unlock(&drm_mem_lock); |
364 | return handle; | 363 | return handle; |
365 | } | 364 | } |
366 | spin_lock(&DRM(mem_lock)); | 365 | spin_lock(&drm_mem_lock); |
367 | ++DRM(mem_stats)[DRM_MEM_TOTALAGP].fail_count; | 366 | ++drm_mem_stats[DRM_MEM_TOTALAGP].fail_count; |
368 | spin_unlock(&DRM(mem_lock)); | 367 | spin_unlock(&drm_mem_lock); |
369 | return NULL; | 368 | return NULL; |
370 | } | 369 | } |
371 | 370 | ||
372 | int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) { | 371 | int drm_free_agp (DRM_AGP_MEM * handle, int pages) { |
373 | int alloc_count; | 372 | int alloc_count; |
374 | int free_count; | 373 | int free_count; |
375 | int retval = -EINVAL; | 374 | int retval = -EINVAL; |
@@ -380,13 +379,13 @@ int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) { | |||
380 | return retval; | 379 | return retval; |
381 | } | 380 | } |
382 | 381 | ||
383 | if (DRM(agp_free_memory) (handle)) { | 382 | if (drm_agp_free_memory (handle)) { |
384 | spin_lock(&DRM(mem_lock)); | 383 | spin_lock(&drm_mem_lock); |
385 | free_count = ++DRM(mem_stats)[DRM_MEM_TOTALAGP].free_count; | 384 | free_count = ++drm_mem_stats[DRM_MEM_TOTALAGP].free_count; |
386 | alloc_count = DRM(mem_stats)[DRM_MEM_TOTALAGP].succeed_count; | 385 | alloc_count = drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count; |
387 | DRM(mem_stats)[DRM_MEM_TOTALAGP].bytes_freed | 386 | drm_mem_stats[DRM_MEM_TOTALAGP].bytes_freed |
388 | += pages << PAGE_SHIFT; | 387 | += pages << PAGE_SHIFT; |
389 | spin_unlock(&DRM(mem_lock)); | 388 | spin_unlock(&drm_mem_lock); |
390 | if (free_count > alloc_count) { | 389 | if (free_count > alloc_count) { |
391 | DRM_MEM_ERROR(DRM_MEM_TOTALAGP, | 390 | DRM_MEM_ERROR(DRM_MEM_TOTALAGP, |
392 | "Excess frees: %d frees, %d allocs\n", | 391 | "Excess frees: %d frees, %d allocs\n", |
@@ -397,7 +396,7 @@ int DRM(free_agp) (DRM_AGP_MEM * handle, int pages) { | |||
397 | return retval; | 396 | return retval; |
398 | } | 397 | } |
399 | 398 | ||
400 | int DRM(bind_agp) (DRM_AGP_MEM * handle, unsigned int start) { | 399 | int drm_bind_agp (DRM_AGP_MEM * handle, unsigned int start) { |
401 | int retcode = -EINVAL; | 400 | int retcode = -EINVAL; |
402 | 401 | ||
403 | if (!handle) { | 402 | if (!handle) { |
@@ -406,21 +405,21 @@ int DRM(bind_agp) (DRM_AGP_MEM * handle, unsigned int start) { | |||
406 | return retcode; | 405 | return retcode; |
407 | } | 406 | } |
408 | 407 | ||
409 | if (!(retcode = DRM(agp_bind_memory) (handle, start))) { | 408 | if (!(retcode = drm_agp_bind_memory (handle, start))) { |
410 | spin_lock(&DRM(mem_lock)); | 409 | spin_lock(&drm_mem_lock); |
411 | ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count; | 410 | ++drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count; |
412 | DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_allocated | 411 | drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_allocated |
413 | += handle->page_count << PAGE_SHIFT; | 412 | += handle->page_count << PAGE_SHIFT; |
414 | spin_unlock(&DRM(mem_lock)); | 413 | spin_unlock(&drm_mem_lock); |
415 | return retcode; | 414 | return retcode; |
416 | } | 415 | } |
417 | spin_lock(&DRM(mem_lock)); | 416 | spin_lock(&drm_mem_lock); |
418 | ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].fail_count; | 417 | ++drm_mem_stats[DRM_MEM_BOUNDAGP].fail_count; |
419 | spin_unlock(&DRM(mem_lock)); | 418 | spin_unlock(&drm_mem_lock); |
420 | return retcode; | 419 | return retcode; |
421 | } | 420 | } |
422 | 421 | ||
423 | int DRM(unbind_agp) (DRM_AGP_MEM * handle) { | 422 | int drm_unbind_agp (DRM_AGP_MEM * handle) { |
424 | int alloc_count; | 423 | int alloc_count; |
425 | int free_count; | 424 | int free_count; |
426 | int retcode = -EINVAL; | 425 | int retcode = -EINVAL; |
@@ -431,14 +430,14 @@ int DRM(unbind_agp) (DRM_AGP_MEM * handle) { | |||
431 | return retcode; | 430 | return retcode; |
432 | } | 431 | } |
433 | 432 | ||
434 | if ((retcode = DRM(agp_unbind_memory) (handle))) | 433 | if ((retcode = drm_agp_unbind_memory (handle))) |
435 | return retcode; | 434 | return retcode; |
436 | spin_lock(&DRM(mem_lock)); | 435 | spin_lock(&drm_mem_lock); |
437 | free_count = ++DRM(mem_stats)[DRM_MEM_BOUNDAGP].free_count; | 436 | free_count = ++drm_mem_stats[DRM_MEM_BOUNDAGP].free_count; |
438 | alloc_count = DRM(mem_stats)[DRM_MEM_BOUNDAGP].succeed_count; | 437 | alloc_count = drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count; |
439 | DRM(mem_stats)[DRM_MEM_BOUNDAGP].bytes_freed | 438 | drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_freed |
440 | += handle->page_count << PAGE_SHIFT; | 439 | += handle->page_count << PAGE_SHIFT; |
441 | spin_unlock(&DRM(mem_lock)); | 440 | spin_unlock(&drm_mem_lock); |
442 | if (free_count > alloc_count) { | 441 | if (free_count > alloc_count) { |
443 | DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, | 442 | DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, |
444 | "Excess frees: %d frees, %d allocs\n", | 443 | "Excess frees: %d frees, %d allocs\n", |
diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h index d51aeb4966f4..695115d70382 100644 --- a/drivers/char/drm/drm_os_linux.h +++ b/drivers/char/drm/drm_os_linux.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #define DRM_ERR(d) -(d) | 13 | #define DRM_ERR(d) -(d) |
14 | /** Current process ID */ | 14 | /** Current process ID */ |
15 | #define DRM_CURRENTPID current->pid | 15 | #define DRM_CURRENTPID current->pid |
16 | #define DRM_SUSER(p) capable(CAP_SYS_ADMIN) | ||
16 | #define DRM_UDELAY(d) udelay(d) | 17 | #define DRM_UDELAY(d) udelay(d) |
17 | /** Read a byte from a MMIO region */ | 18 | /** Read a byte from a MMIO region */ |
18 | #define DRM_READ8(map, offset) readb(((void __iomem *)(map)->handle) + (offset)) | 19 | #define DRM_READ8(map, offset) readb(((void __iomem *)(map)->handle) + (offset)) |
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index d66dc55e29a0..5b1d3a04458d 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h | |||
@@ -46,6 +46,7 @@ | |||
46 | {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 46 | {0x1002, 0x4E50, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ |
47 | {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 47 | {0x1002, 0x4E51, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ |
48 | {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | 48 | {0x1002, 0x4E54, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ |
49 | {0x1002, 0x4E56, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350|CHIP_IS_MOBILITY}, \ | ||
49 | {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ | 50 | {0x1002, 0x5144, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ |
50 | {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ | 51 | {0x1002, 0x5145, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ |
51 | {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ | 52 | {0x1002, 0x5146, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R100|CHIP_SINGLE_CRTC}, \ |
@@ -69,6 +70,7 @@ | |||
69 | {0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 70 | {0x1002, 0x516B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ |
70 | {0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ | 71 | {0x1002, 0x516C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R200}, \ |
71 | {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | 72 | {0x1002, 0x5460, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ |
73 | {0x1002, 0x554F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | ||
72 | {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ | 74 | {0x1002, 0x5834, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ |
73 | {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ | 75 | {0x1002, 0x5835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP|CHIP_IS_MOBILITY}, \ |
74 | {0x1002, 0x5836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ | 76 | {0x1002, 0x5836, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS300|CHIP_IS_IGP}, \ |
@@ -82,10 +84,13 @@ | |||
82 | {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ | 84 | {0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \ |
83 | {0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 85 | {0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
84 | {0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 86 | {0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
87 | {0x1002, 0x5b60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV350}, \ | ||
85 | {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ | 88 | {0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ |
86 | {0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 89 | {0x1002, 0x5c62, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
87 | {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ | 90 | {0x1002, 0x5c63, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \ |
88 | {0x1002, 0x5c64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ | 91 | {0x1002, 0x5c64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \ |
92 | {0x1002, 0x5d4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R350}, \ | ||
93 | {0x1002, 0x5e4b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R420}, \ | ||
89 | {0, 0, 0} | 94 | {0, 0, 0} |
90 | 95 | ||
91 | #define r128_PCI_IDS \ | 96 | #define r128_PCI_IDS \ |
@@ -176,7 +181,7 @@ | |||
176 | 181 | ||
177 | #define viadrv_PCI_IDS \ | 182 | #define viadrv_PCI_IDS \ |
178 | {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 183 | {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
179 | {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 184 | {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \ |
180 | {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 185 | {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
181 | {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 186 | {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
182 | {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 187 | {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
@@ -196,6 +201,10 @@ | |||
196 | {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 201 | {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
197 | {0, 0, 0} | 202 | {0, 0, 0} |
198 | 203 | ||
204 | #define gamma_PCI_IDS \ | ||
205 | {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | ||
206 | {0, 0, 0} | ||
207 | |||
199 | #define savage_PCI_IDS \ | 208 | #define savage_PCI_IDS \ |
200 | {0x5333, 0x8a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \ | 209 | {0x5333, 0x8a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \ |
201 | {0x5333, 0x8a21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \ | 210 | {0x5333, 0x8a21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \ |
@@ -234,3 +243,4 @@ | |||
234 | {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 243 | {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
235 | {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ | 244 | {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
236 | {0, 0, 0} | 245 | {0, 0, 0} |
246 | |||
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c index 3f452f763f0f..6f943e3309ef 100644 --- a/drivers/char/drm/drm_proc.c +++ b/drivers/char/drm/drm_proc.c | |||
@@ -61,16 +61,14 @@ static struct drm_proc_list { | |||
61 | const char *name; /**< file name */ | 61 | const char *name; /**< file name */ |
62 | int (*f) (char *, char **, off_t, int, int *, void *); /**< proc callback*/ | 62 | int (*f) (char *, char **, off_t, int, int *, void *); /**< proc callback*/ |
63 | } drm_proc_list[] = { | 63 | } drm_proc_list[] = { |
64 | { | 64 | {"name", drm_name_info}, |
65 | "name", drm_name_info}, { | 65 | {"mem", drm_mem_info}, |
66 | "mem", drm_mem_info}, { | 66 | {"vm", drm_vm_info}, |
67 | "vm", drm_vm_info}, { | 67 | {"clients", drm_clients_info}, |
68 | "clients", drm_clients_info}, { | 68 | {"queues", drm_queues_info}, |
69 | "queues", drm_queues_info}, { | 69 | {"bufs", drm_bufs_info}, |
70 | "bufs", drm_bufs_info}, | ||
71 | #if DRM_DEBUG_CODE | 70 | #if DRM_DEBUG_CODE |
72 | { | 71 | {"vma", drm_vma_info}, |
73 | "vma", drm_vma_info}, | ||
74 | #endif | 72 | #endif |
75 | }; | 73 | }; |
76 | 74 | ||
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c index 60b6f8e8bf69..42d766359caa 100644 --- a/drivers/char/drm/drm_stub.c +++ b/drivers/char/drm/drm_stub.c | |||
@@ -93,8 +93,8 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, | |||
93 | 93 | ||
94 | dev->driver = driver; | 94 | dev->driver = driver; |
95 | 95 | ||
96 | if (dev->driver->preinit) | 96 | if (dev->driver->load) |
97 | if ((retcode = dev->driver->preinit(dev, ent->driver_data))) | 97 | if ((retcode = dev->driver->load(dev, ent->driver_data))) |
98 | goto error_out_unreg; | 98 | goto error_out_unreg; |
99 | 99 | ||
100 | if (drm_core_has_AGP(dev)) { | 100 | if (drm_core_has_AGP(dev)) { |
@@ -124,47 +124,10 @@ static int drm_fill_in_dev(drm_device_t * dev, struct pci_dev *pdev, | |||
124 | return 0; | 124 | return 0; |
125 | 125 | ||
126 | error_out_unreg: | 126 | error_out_unreg: |
127 | drm_takedown(dev); | 127 | drm_lastclose(dev); |
128 | return retcode; | 128 | return retcode; |
129 | } | 129 | } |
130 | 130 | ||
131 | /** | ||
132 | * File \c open operation. | ||
133 | * | ||
134 | * \param inode device inode. | ||
135 | * \param filp file pointer. | ||
136 | * | ||
137 | * Puts the dev->fops corresponding to the device minor number into | ||
138 | * \p filp, call the \c open method, and restore the file operations. | ||
139 | */ | ||
140 | int drm_stub_open(struct inode *inode, struct file *filp) | ||
141 | { | ||
142 | drm_device_t *dev = NULL; | ||
143 | int minor = iminor(inode); | ||
144 | int err = -ENODEV; | ||
145 | struct file_operations *old_fops; | ||
146 | |||
147 | DRM_DEBUG("\n"); | ||
148 | |||
149 | if (!((minor >= 0) && (minor < drm_cards_limit))) | ||
150 | return -ENODEV; | ||
151 | |||
152 | if (!drm_heads[minor]) | ||
153 | return -ENODEV; | ||
154 | |||
155 | if (!(dev = drm_heads[minor]->dev)) | ||
156 | return -ENODEV; | ||
157 | |||
158 | old_fops = filp->f_op; | ||
159 | filp->f_op = fops_get(&dev->driver->fops); | ||
160 | if (filp->f_op->open && (err = filp->f_op->open(inode, filp))) { | ||
161 | fops_put(filp->f_op); | ||
162 | filp->f_op = fops_get(old_fops); | ||
163 | } | ||
164 | fops_put(old_fops); | ||
165 | |||
166 | return err; | ||
167 | } | ||
168 | 131 | ||
169 | /** | 132 | /** |
170 | * Get a secondary minor number. | 133 | * Get a secondary minor number. |
@@ -200,11 +163,7 @@ static int drm_get_head(drm_device_t * dev, drm_head_t * head) | |||
200 | goto err_g1; | 163 | goto err_g1; |
201 | } | 164 | } |
202 | 165 | ||
203 | head->dev_class = drm_sysfs_device_add(drm_class, | 166 | head->dev_class = drm_sysfs_device_add(drm_class, head); |
204 | MKDEV(DRM_MAJOR, | ||
205 | minor), | ||
206 | &dev->pdev->dev, | ||
207 | "card%d", minor); | ||
208 | if (IS_ERR(head->dev_class)) { | 167 | if (IS_ERR(head->dev_class)) { |
209 | printk(KERN_ERR | 168 | printk(KERN_ERR |
210 | "DRM: Error sysfs_device_add.\n"); | 169 | "DRM: Error sysfs_device_add.\n"); |
@@ -258,11 +217,10 @@ int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | |||
258 | } | 217 | } |
259 | if ((ret = drm_get_head(dev, &dev->primary))) | 218 | if ((ret = drm_get_head(dev, &dev->primary))) |
260 | goto err_g1; | 219 | goto err_g1; |
261 | 220 | ||
262 | /* postinit is a required function to display the signon banner */ | 221 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n", |
263 | /* drivers add secondary heads here if needed */ | 222 | driver->name, driver->major, driver->minor, driver->patchlevel, |
264 | if ((ret = dev->driver->postinit(dev, ent->driver_data))) | 223 | driver->date, dev->primary.minor); |
265 | goto err_g1; | ||
266 | 224 | ||
267 | return 0; | 225 | return 0; |
268 | 226 | ||
@@ -318,10 +276,9 @@ int drm_put_head(drm_head_t * head) | |||
318 | DRM_DEBUG("release secondary minor %d\n", minor); | 276 | DRM_DEBUG("release secondary minor %d\n", minor); |
319 | 277 | ||
320 | drm_proc_cleanup(minor, drm_proc_root, head->dev_root); | 278 | drm_proc_cleanup(minor, drm_proc_root, head->dev_root); |
321 | drm_sysfs_device_remove(MKDEV(DRM_MAJOR, head->minor)); | 279 | drm_sysfs_device_remove(head->dev_class); |
322 | 280 | ||
323 | *head = (drm_head_t) { | 281 | *head = (drm_head_t) {.dev = NULL}; |
324 | .dev = NULL}; | ||
325 | 282 | ||
326 | drm_heads[minor] = NULL; | 283 | drm_heads[minor] = NULL; |
327 | 284 | ||
diff --git a/drivers/char/drm/drm_sysfs.c b/drivers/char/drm/drm_sysfs.c index 6d3449761914..68e43ddc16ae 100644 --- a/drivers/char/drm/drm_sysfs.c +++ b/drivers/char/drm/drm_sysfs.c | |||
@@ -15,8 +15,6 @@ | |||
15 | #include <linux/device.h> | 15 | #include <linux/device.h> |
16 | #include <linux/kdev_t.h> | 16 | #include <linux/kdev_t.h> |
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/slab.h> | ||
19 | #include <linux/string.h> | ||
20 | 18 | ||
21 | #include "drm_core.h" | 19 | #include "drm_core.h" |
22 | #include "drmP.h" | 20 | #include "drmP.h" |
@@ -28,15 +26,11 @@ struct drm_sysfs_class { | |||
28 | #define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class) | 26 | #define to_drm_sysfs_class(d) container_of(d, struct drm_sysfs_class, class) |
29 | 27 | ||
30 | struct simple_dev { | 28 | struct simple_dev { |
31 | struct list_head node; | ||
32 | dev_t dev; | 29 | dev_t dev; |
33 | struct class_device class_dev; | 30 | struct class_device class_dev; |
34 | }; | 31 | }; |
35 | #define to_simple_dev(d) container_of(d, struct simple_dev, class_dev) | 32 | #define to_simple_dev(d) container_of(d, struct simple_dev, class_dev) |
36 | 33 | ||
37 | static LIST_HEAD(simple_dev_list); | ||
38 | static DEFINE_SPINLOCK(simple_dev_list_lock); | ||
39 | |||
40 | static void release_simple_dev(struct class_device *class_dev) | 34 | static void release_simple_dev(struct class_device *class_dev) |
41 | { | 35 | { |
42 | struct simple_dev *s_dev = to_simple_dev(class_dev); | 36 | struct simple_dev *s_dev = to_simple_dev(class_dev); |
@@ -124,6 +118,18 @@ void drm_sysfs_destroy(struct drm_sysfs_class *cs) | |||
124 | class_unregister(&cs->class); | 118 | class_unregister(&cs->class); |
125 | } | 119 | } |
126 | 120 | ||
121 | static ssize_t show_dri(struct class_device *class_device, char *buf) | ||
122 | { | ||
123 | drm_device_t * dev = ((drm_head_t *)class_get_devdata(class_device))->dev; | ||
124 | if (dev->driver->dri_library_name) | ||
125 | return dev->driver->dri_library_name(dev, buf); | ||
126 | return snprintf(buf, PAGE_SIZE, "%s\n", dev->driver->pci_driver.name); | ||
127 | } | ||
128 | |||
129 | static struct class_device_attribute class_device_attrs[] = { | ||
130 | __ATTR(dri_library_name, S_IRUGO, show_dri, NULL), | ||
131 | }; | ||
132 | |||
127 | /** | 133 | /** |
128 | * drm_sysfs_device_add - adds a class device to sysfs for a character driver | 134 | * drm_sysfs_device_add - adds a class device to sysfs for a character driver |
129 | * @cs: pointer to the struct drm_sysfs_class that this device should be registered to. | 135 | * @cs: pointer to the struct drm_sysfs_class that this device should be registered to. |
@@ -138,13 +144,11 @@ void drm_sysfs_destroy(struct drm_sysfs_class *cs) | |||
138 | * Note: the struct drm_sysfs_class passed to this function must have previously been | 144 | * Note: the struct drm_sysfs_class passed to this function must have previously been |
139 | * created with a call to drm_sysfs_create(). | 145 | * created with a call to drm_sysfs_create(). |
140 | */ | 146 | */ |
141 | struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, dev_t dev, | 147 | struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, |
142 | struct device *device, | 148 | drm_head_t *head) |
143 | const char *fmt, ...) | ||
144 | { | 149 | { |
145 | va_list args; | ||
146 | struct simple_dev *s_dev = NULL; | 150 | struct simple_dev *s_dev = NULL; |
147 | int retval; | 151 | int i, retval; |
148 | 152 | ||
149 | if ((cs == NULL) || (IS_ERR(cs))) { | 153 | if ((cs == NULL) || (IS_ERR(cs))) { |
150 | retval = -ENODEV; | 154 | retval = -ENODEV; |
@@ -158,26 +162,23 @@ struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, dev_t dev, | |||
158 | } | 162 | } |
159 | memset(s_dev, 0x00, sizeof(*s_dev)); | 163 | memset(s_dev, 0x00, sizeof(*s_dev)); |
160 | 164 | ||
161 | s_dev->dev = dev; | 165 | s_dev->dev = MKDEV(DRM_MAJOR, head->minor); |
162 | s_dev->class_dev.dev = device; | 166 | s_dev->class_dev.dev = &(head->dev->pdev)->dev; |
163 | s_dev->class_dev.class = &cs->class; | 167 | s_dev->class_dev.class = &cs->class; |
164 | 168 | ||
165 | va_start(args, fmt); | 169 | snprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, "card%d", head->minor); |
166 | vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args); | ||
167 | va_end(args); | ||
168 | retval = class_device_register(&s_dev->class_dev); | 170 | retval = class_device_register(&s_dev->class_dev); |
169 | if (retval) | 171 | if (retval) |
170 | goto error; | 172 | goto error; |
171 | 173 | ||
172 | class_device_create_file(&s_dev->class_dev, &cs->attr); | 174 | class_device_create_file(&s_dev->class_dev, &cs->attr); |
175 | class_set_devdata(&s_dev->class_dev, head); | ||
173 | 176 | ||
174 | spin_lock(&simple_dev_list_lock); | 177 | for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) |
175 | list_add(&s_dev->node, &simple_dev_list); | 178 | class_device_create_file(&s_dev->class_dev, &class_device_attrs[i]); |
176 | spin_unlock(&simple_dev_list_lock); | ||
177 | |||
178 | return &s_dev->class_dev; | 179 | return &s_dev->class_dev; |
179 | 180 | ||
180 | error: | 181 | error: |
181 | kfree(s_dev); | 182 | kfree(s_dev); |
182 | return ERR_PTR(retval); | 183 | return ERR_PTR(retval); |
183 | } | 184 | } |
@@ -189,23 +190,12 @@ struct class_device *drm_sysfs_device_add(struct drm_sysfs_class *cs, dev_t dev, | |||
189 | * This call unregisters and cleans up a class device that was created with a | 190 | * This call unregisters and cleans up a class device that was created with a |
190 | * call to drm_sysfs_device_add() | 191 | * call to drm_sysfs_device_add() |
191 | */ | 192 | */ |
192 | void drm_sysfs_device_remove(dev_t dev) | 193 | void drm_sysfs_device_remove(struct class_device *class_dev) |
193 | { | 194 | { |
194 | struct simple_dev *s_dev = NULL; | 195 | struct simple_dev *s_dev = to_simple_dev(class_dev); |
195 | int found = 0; | 196 | int i; |
196 | 197 | ||
197 | spin_lock(&simple_dev_list_lock); | 198 | for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) |
198 | list_for_each_entry(s_dev, &simple_dev_list, node) { | 199 | class_device_remove_file(&s_dev->class_dev, &class_device_attrs[i]); |
199 | if (s_dev->dev == dev) { | 200 | class_device_unregister(&s_dev->class_dev); |
200 | found = 1; | ||
201 | break; | ||
202 | } | ||
203 | } | ||
204 | if (found) { | ||
205 | list_del(&s_dev->node); | ||
206 | spin_unlock(&simple_dev_list_lock); | ||
207 | class_device_unregister(&s_dev->class_dev); | ||
208 | } else { | ||
209 | spin_unlock(&simple_dev_list_lock); | ||
210 | } | ||
211 | } | 201 | } |
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index dba502373da1..cc1b89086876 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c | |||
@@ -114,7 +114,6 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) | |||
114 | 114 | ||
115 | static struct file_operations i810_buffer_fops = { | 115 | static struct file_operations i810_buffer_fops = { |
116 | .open = drm_open, | 116 | .open = drm_open, |
117 | .flush = drm_flush, | ||
118 | .release = drm_release, | 117 | .release = drm_release, |
119 | .ioctl = drm_ioctl, | 118 | .ioctl = drm_ioctl, |
120 | .mmap = i810_mmap_buffers, | 119 | .mmap = i810_mmap_buffers, |
@@ -1319,12 +1318,24 @@ static int i810_flip_bufs(struct inode *inode, struct file *filp, | |||
1319 | return 0; | 1318 | return 0; |
1320 | } | 1319 | } |
1321 | 1320 | ||
1322 | void i810_driver_pretakedown(drm_device_t * dev) | 1321 | int i810_driver_load(drm_device_t *dev, unsigned long flags) |
1322 | { | ||
1323 | /* i810 has 4 more counters */ | ||
1324 | dev->counters += 4; | ||
1325 | dev->types[6] = _DRM_STAT_IRQ; | ||
1326 | dev->types[7] = _DRM_STAT_PRIMARY; | ||
1327 | dev->types[8] = _DRM_STAT_SECONDARY; | ||
1328 | dev->types[9] = _DRM_STAT_DMA; | ||
1329 | |||
1330 | return 0; | ||
1331 | } | ||
1332 | |||
1333 | void i810_driver_lastclose(drm_device_t * dev) | ||
1323 | { | 1334 | { |
1324 | i810_dma_cleanup(dev); | 1335 | i810_dma_cleanup(dev); |
1325 | } | 1336 | } |
1326 | 1337 | ||
1327 | void i810_driver_prerelease(drm_device_t * dev, DRMFILE filp) | 1338 | void i810_driver_preclose(drm_device_t * dev, DRMFILE filp) |
1328 | { | 1339 | { |
1329 | if (dev->dev_private) { | 1340 | if (dev->dev_private) { |
1330 | drm_i810_private_t *dev_priv = dev->dev_private; | 1341 | drm_i810_private_t *dev_priv = dev->dev_private; |
@@ -1334,7 +1345,7 @@ void i810_driver_prerelease(drm_device_t * dev, DRMFILE filp) | |||
1334 | } | 1345 | } |
1335 | } | 1346 | } |
1336 | 1347 | ||
1337 | void i810_driver_release(drm_device_t * dev, struct file *filp) | 1348 | void i810_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp) |
1338 | { | 1349 | { |
1339 | i810_reclaim_buffers(dev, filp); | 1350 | i810_reclaim_buffers(dev, filp); |
1340 | } | 1351 | } |
@@ -1346,21 +1357,21 @@ int i810_driver_dma_quiescent(drm_device_t * dev) | |||
1346 | } | 1357 | } |
1347 | 1358 | ||
1348 | drm_ioctl_desc_t i810_ioctls[] = { | 1359 | drm_ioctl_desc_t i810_ioctls[] = { |
1349 | [DRM_IOCTL_NR(DRM_I810_INIT)] = {i810_dma_init, 1, 1}, | 1360 | [DRM_IOCTL_NR(DRM_I810_INIT)] = {i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
1350 | [DRM_IOCTL_NR(DRM_I810_VERTEX)] = {i810_dma_vertex, 1, 0}, | 1361 | [DRM_IOCTL_NR(DRM_I810_VERTEX)] = {i810_dma_vertex, DRM_AUTH}, |
1351 | [DRM_IOCTL_NR(DRM_I810_CLEAR)] = {i810_clear_bufs, 1, 0}, | 1362 | [DRM_IOCTL_NR(DRM_I810_CLEAR)] = {i810_clear_bufs, DRM_AUTH}, |
1352 | [DRM_IOCTL_NR(DRM_I810_FLUSH)] = {i810_flush_ioctl, 1, 0}, | 1363 | [DRM_IOCTL_NR(DRM_I810_FLUSH)] = {i810_flush_ioctl, DRM_AUTH}, |
1353 | [DRM_IOCTL_NR(DRM_I810_GETAGE)] = {i810_getage, 1, 0}, | 1364 | [DRM_IOCTL_NR(DRM_I810_GETAGE)] = {i810_getage, DRM_AUTH}, |
1354 | [DRM_IOCTL_NR(DRM_I810_GETBUF)] = {i810_getbuf, 1, 0}, | 1365 | [DRM_IOCTL_NR(DRM_I810_GETBUF)] = {i810_getbuf, DRM_AUTH}, |
1355 | [DRM_IOCTL_NR(DRM_I810_SWAP)] = {i810_swap_bufs, 1, 0}, | 1366 | [DRM_IOCTL_NR(DRM_I810_SWAP)] = {i810_swap_bufs, DRM_AUTH}, |
1356 | [DRM_IOCTL_NR(DRM_I810_COPY)] = {i810_copybuf, 1, 0}, | 1367 | [DRM_IOCTL_NR(DRM_I810_COPY)] = {i810_copybuf, DRM_AUTH}, |
1357 | [DRM_IOCTL_NR(DRM_I810_DOCOPY)] = {i810_docopy, 1, 0}, | 1368 | [DRM_IOCTL_NR(DRM_I810_DOCOPY)] = {i810_docopy, DRM_AUTH}, |
1358 | [DRM_IOCTL_NR(DRM_I810_OV0INFO)] = {i810_ov0_info, 1, 0}, | 1369 | [DRM_IOCTL_NR(DRM_I810_OV0INFO)] = {i810_ov0_info, DRM_AUTH}, |
1359 | [DRM_IOCTL_NR(DRM_I810_FSTATUS)] = {i810_fstatus, 1, 0}, | 1370 | [DRM_IOCTL_NR(DRM_I810_FSTATUS)] = {i810_fstatus, DRM_AUTH}, |
1360 | [DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = {i810_ov0_flip, 1, 0}, | 1371 | [DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = {i810_ov0_flip, DRM_AUTH}, |
1361 | [DRM_IOCTL_NR(DRM_I810_MC)] = {i810_dma_mc, 1, 1}, | 1372 | [DRM_IOCTL_NR(DRM_I810_MC)] = {i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
1362 | [DRM_IOCTL_NR(DRM_I810_RSTATUS)] = {i810_rstatus, 1, 0}, | 1373 | [DRM_IOCTL_NR(DRM_I810_RSTATUS)] = {i810_rstatus, DRM_AUTH}, |
1363 | [DRM_IOCTL_NR(DRM_I810_FLIP)] = {i810_flip_bufs, 1, 0} | 1374 | [DRM_IOCTL_NR(DRM_I810_FLIP)] = {i810_flip_bufs, DRM_AUTH} |
1364 | }; | 1375 | }; |
1365 | 1376 | ||
1366 | int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls); | 1377 | int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls); |
diff --git a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c index 070cef6c2b46..dfe6ad2b6a6e 100644 --- a/drivers/char/drm/i810_drv.c +++ b/drivers/char/drm/i810_drv.c | |||
@@ -38,38 +38,6 @@ | |||
38 | 38 | ||
39 | #include "drm_pciids.h" | 39 | #include "drm_pciids.h" |
40 | 40 | ||
41 | static int postinit(struct drm_device *dev, unsigned long flags) | ||
42 | { | ||
43 | /* i810 has 4 more counters */ | ||
44 | dev->counters += 4; | ||
45 | dev->types[6] = _DRM_STAT_IRQ; | ||
46 | dev->types[7] = _DRM_STAT_PRIMARY; | ||
47 | dev->types[8] = _DRM_STAT_SECONDARY; | ||
48 | dev->types[9] = _DRM_STAT_DMA; | ||
49 | |||
50 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n", | ||
51 | DRIVER_NAME, | ||
52 | DRIVER_MAJOR, | ||
53 | DRIVER_MINOR, | ||
54 | DRIVER_PATCHLEVEL, | ||
55 | DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev) | ||
56 | ); | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int version(drm_version_t * version) | ||
61 | { | ||
62 | int len; | ||
63 | |||
64 | version->version_major = DRIVER_MAJOR; | ||
65 | version->version_minor = DRIVER_MINOR; | ||
66 | version->version_patchlevel = DRIVER_PATCHLEVEL; | ||
67 | DRM_COPY(version->name, DRIVER_NAME); | ||
68 | DRM_COPY(version->date, DRIVER_DATE); | ||
69 | DRM_COPY(version->desc, DRIVER_DESC); | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static struct pci_device_id pciidlist[] = { | 41 | static struct pci_device_id pciidlist[] = { |
74 | i810_PCI_IDS | 42 | i810_PCI_IDS |
75 | }; | 43 | }; |
@@ -79,16 +47,14 @@ static struct drm_driver driver = { | |||
79 | DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | | 47 | DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | |
80 | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE, | 48 | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE, |
81 | .dev_priv_size = sizeof(drm_i810_buf_priv_t), | 49 | .dev_priv_size = sizeof(drm_i810_buf_priv_t), |
82 | .pretakedown = i810_driver_pretakedown, | 50 | .load = i810_driver_load, |
83 | .prerelease = i810_driver_prerelease, | 51 | .lastclose = i810_driver_lastclose, |
52 | .preclose = i810_driver_preclose, | ||
84 | .device_is_agp = i810_driver_device_is_agp, | 53 | .device_is_agp = i810_driver_device_is_agp, |
85 | .release = i810_driver_release, | 54 | .reclaim_buffers_locked = i810_driver_reclaim_buffers_locked, |
86 | .dma_quiescent = i810_driver_dma_quiescent, | 55 | .dma_quiescent = i810_driver_dma_quiescent, |
87 | .reclaim_buffers = i810_reclaim_buffers, | ||
88 | .get_map_ofs = drm_core_get_map_ofs, | 56 | .get_map_ofs = drm_core_get_map_ofs, |
89 | .get_reg_ofs = drm_core_get_reg_ofs, | 57 | .get_reg_ofs = drm_core_get_reg_ofs, |
90 | .postinit = postinit, | ||
91 | .version = version, | ||
92 | .ioctls = i810_ioctls, | 58 | .ioctls = i810_ioctls, |
93 | .fops = { | 59 | .fops = { |
94 | .owner = THIS_MODULE, | 60 | .owner = THIS_MODULE, |
@@ -98,13 +64,19 @@ static struct drm_driver driver = { | |||
98 | .mmap = drm_mmap, | 64 | .mmap = drm_mmap, |
99 | .poll = drm_poll, | 65 | .poll = drm_poll, |
100 | .fasync = drm_fasync, | 66 | .fasync = drm_fasync, |
101 | } | 67 | }, |
102 | , | 68 | |
103 | .pci_driver = { | 69 | .pci_driver = { |
104 | .name = DRIVER_NAME, | 70 | .name = DRIVER_NAME, |
105 | .id_table = pciidlist, | 71 | .id_table = pciidlist, |
106 | } | 72 | }, |
107 | , | 73 | |
74 | .name = DRIVER_NAME, | ||
75 | .desc = DRIVER_DESC, | ||
76 | .date = DRIVER_DATE, | ||
77 | .major = DRIVER_MAJOR, | ||
78 | .minor = DRIVER_MINOR, | ||
79 | .patchlevel = DRIVER_PATCHLEVEL, | ||
108 | }; | 80 | }; |
109 | 81 | ||
110 | static int __init i810_init(void) | 82 | static int __init i810_init(void) |
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h index c78f36aaa2f0..a18b80d91920 100644 --- a/drivers/char/drm/i810_drv.h +++ b/drivers/char/drm/i810_drv.h | |||
@@ -116,9 +116,13 @@ typedef struct drm_i810_private { | |||
116 | extern void i810_reclaim_buffers(drm_device_t * dev, struct file *filp); | 116 | extern void i810_reclaim_buffers(drm_device_t * dev, struct file *filp); |
117 | 117 | ||
118 | extern int i810_driver_dma_quiescent(drm_device_t * dev); | 118 | extern int i810_driver_dma_quiescent(drm_device_t * dev); |
119 | extern void i810_driver_release(drm_device_t * dev, struct file *filp); | 119 | extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev, |
120 | extern void i810_driver_pretakedown(drm_device_t * dev); | 120 | struct file *filp); |
121 | extern void i810_driver_prerelease(drm_device_t * dev, DRMFILE filp); | 121 | extern int i810_driver_load(struct drm_device *, unsigned long flags); |
122 | extern void i810_driver_lastclose(drm_device_t * dev); | ||
123 | extern void i810_driver_preclose(drm_device_t * dev, DRMFILE filp); | ||
124 | extern void i810_driver_reclaim_buffers_locked(drm_device_t * dev, | ||
125 | struct file *filp); | ||
122 | extern int i810_driver_device_is_agp(drm_device_t * dev); | 126 | extern int i810_driver_device_is_agp(drm_device_t * dev); |
123 | 127 | ||
124 | extern drm_ioctl_desc_t i810_ioctls[]; | 128 | extern drm_ioctl_desc_t i810_ioctls[]; |
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index dc94f1914425..4fea32aed6d2 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c | |||
@@ -116,7 +116,6 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) | |||
116 | 116 | ||
117 | static struct file_operations i830_buffer_fops = { | 117 | static struct file_operations i830_buffer_fops = { |
118 | .open = drm_open, | 118 | .open = drm_open, |
119 | .flush = drm_flush, | ||
120 | .release = drm_release, | 119 | .release = drm_release, |
121 | .ioctl = drm_ioctl, | 120 | .ioctl = drm_ioctl, |
122 | .mmap = i830_mmap_buffers, | 121 | .mmap = i830_mmap_buffers, |
@@ -1517,12 +1516,24 @@ static int i830_setparam(struct inode *inode, struct file *filp, | |||
1517 | return 0; | 1516 | return 0; |
1518 | } | 1517 | } |
1519 | 1518 | ||
1520 | void i830_driver_pretakedown(drm_device_t * dev) | 1519 | int i830_driver_load(drm_device_t *dev, unsigned long flags) |
1520 | { | ||
1521 | /* i830 has 4 more counters */ | ||
1522 | dev->counters += 4; | ||
1523 | dev->types[6] = _DRM_STAT_IRQ; | ||
1524 | dev->types[7] = _DRM_STAT_PRIMARY; | ||
1525 | dev->types[8] = _DRM_STAT_SECONDARY; | ||
1526 | dev->types[9] = _DRM_STAT_DMA; | ||
1527 | |||
1528 | return 0; | ||
1529 | } | ||
1530 | |||
1531 | void i830_driver_lastclose(drm_device_t * dev) | ||
1521 | { | 1532 | { |
1522 | i830_dma_cleanup(dev); | 1533 | i830_dma_cleanup(dev); |
1523 | } | 1534 | } |
1524 | 1535 | ||
1525 | void i830_driver_prerelease(drm_device_t * dev, DRMFILE filp) | 1536 | void i830_driver_preclose(drm_device_t * dev, DRMFILE filp) |
1526 | { | 1537 | { |
1527 | if (dev->dev_private) { | 1538 | if (dev->dev_private) { |
1528 | drm_i830_private_t *dev_priv = dev->dev_private; | 1539 | drm_i830_private_t *dev_priv = dev->dev_private; |
@@ -1532,7 +1543,7 @@ void i830_driver_prerelease(drm_device_t * dev, DRMFILE filp) | |||
1532 | } | 1543 | } |
1533 | } | 1544 | } |
1534 | 1545 | ||
1535 | void i830_driver_release(drm_device_t * dev, struct file *filp) | 1546 | void i830_driver_reclaim_buffers_locked(drm_device_t * dev, struct file *filp) |
1536 | { | 1547 | { |
1537 | i830_reclaim_buffers(dev, filp); | 1548 | i830_reclaim_buffers(dev, filp); |
1538 | } | 1549 | } |
@@ -1544,20 +1555,20 @@ int i830_driver_dma_quiescent(drm_device_t * dev) | |||
1544 | } | 1555 | } |
1545 | 1556 | ||
1546 | drm_ioctl_desc_t i830_ioctls[] = { | 1557 | drm_ioctl_desc_t i830_ioctls[] = { |
1547 | [DRM_IOCTL_NR(DRM_I830_INIT)] = {i830_dma_init, 1, 1}, | 1558 | [DRM_IOCTL_NR(DRM_I830_INIT)] = {i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
1548 | [DRM_IOCTL_NR(DRM_I830_VERTEX)] = {i830_dma_vertex, 1, 0}, | 1559 | [DRM_IOCTL_NR(DRM_I830_VERTEX)] = {i830_dma_vertex, DRM_AUTH}, |
1549 | [DRM_IOCTL_NR(DRM_I830_CLEAR)] = {i830_clear_bufs, 1, 0}, | 1560 | [DRM_IOCTL_NR(DRM_I830_CLEAR)] = {i830_clear_bufs, DRM_AUTH}, |
1550 | [DRM_IOCTL_NR(DRM_I830_FLUSH)] = {i830_flush_ioctl, 1, 0}, | 1561 | [DRM_IOCTL_NR(DRM_I830_FLUSH)] = {i830_flush_ioctl, DRM_AUTH}, |
1551 | [DRM_IOCTL_NR(DRM_I830_GETAGE)] = {i830_getage, 1, 0}, | 1562 | [DRM_IOCTL_NR(DRM_I830_GETAGE)] = {i830_getage, DRM_AUTH}, |
1552 | [DRM_IOCTL_NR(DRM_I830_GETBUF)] = {i830_getbuf, 1, 0}, | 1563 | [DRM_IOCTL_NR(DRM_I830_GETBUF)] = {i830_getbuf, DRM_AUTH}, |
1553 | [DRM_IOCTL_NR(DRM_I830_SWAP)] = {i830_swap_bufs, 1, 0}, | 1564 | [DRM_IOCTL_NR(DRM_I830_SWAP)] = {i830_swap_bufs, DRM_AUTH}, |
1554 | [DRM_IOCTL_NR(DRM_I830_COPY)] = {i830_copybuf, 1, 0}, | 1565 | [DRM_IOCTL_NR(DRM_I830_COPY)] = {i830_copybuf, DRM_AUTH}, |
1555 | [DRM_IOCTL_NR(DRM_I830_DOCOPY)] = {i830_docopy, 1, 0}, | 1566 | [DRM_IOCTL_NR(DRM_I830_DOCOPY)] = {i830_docopy, DRM_AUTH}, |
1556 | [DRM_IOCTL_NR(DRM_I830_FLIP)] = {i830_flip_bufs, 1, 0}, | 1567 | [DRM_IOCTL_NR(DRM_I830_FLIP)] = {i830_flip_bufs, DRM_AUTH}, |
1557 | [DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = {i830_irq_emit, 1, 0}, | 1568 | [DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = {i830_irq_emit, DRM_AUTH}, |
1558 | [DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = {i830_irq_wait, 1, 0}, | 1569 | [DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = {i830_irq_wait, DRM_AUTH}, |
1559 | [DRM_IOCTL_NR(DRM_I830_GETPARAM)] = {i830_getparam, 1, 0}, | 1570 | [DRM_IOCTL_NR(DRM_I830_GETPARAM)] = {i830_getparam, DRM_AUTH}, |
1560 | [DRM_IOCTL_NR(DRM_I830_SETPARAM)] = {i830_setparam, 1, 0} | 1571 | [DRM_IOCTL_NR(DRM_I830_SETPARAM)] = {i830_setparam, DRM_AUTH} |
1561 | }; | 1572 | }; |
1562 | 1573 | ||
1563 | int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); | 1574 | int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); |
diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c index acd821e8fe4d..722658188f5f 100644 --- a/drivers/char/drm/i830_drv.c +++ b/drivers/char/drm/i830_drv.c | |||
@@ -40,37 +40,6 @@ | |||
40 | 40 | ||
41 | #include "drm_pciids.h" | 41 | #include "drm_pciids.h" |
42 | 42 | ||
43 | static int postinit(struct drm_device *dev, unsigned long flags) | ||
44 | { | ||
45 | dev->counters += 4; | ||
46 | dev->types[6] = _DRM_STAT_IRQ; | ||
47 | dev->types[7] = _DRM_STAT_PRIMARY; | ||
48 | dev->types[8] = _DRM_STAT_SECONDARY; | ||
49 | dev->types[9] = _DRM_STAT_DMA; | ||
50 | |||
51 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n", | ||
52 | DRIVER_NAME, | ||
53 | DRIVER_MAJOR, | ||
54 | DRIVER_MINOR, | ||
55 | DRIVER_PATCHLEVEL, | ||
56 | DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev) | ||
57 | ); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static int version(drm_version_t * version) | ||
62 | { | ||
63 | int len; | ||
64 | |||
65 | version->version_major = DRIVER_MAJOR; | ||
66 | version->version_minor = DRIVER_MINOR; | ||
67 | version->version_patchlevel = DRIVER_PATCHLEVEL; | ||
68 | DRM_COPY(version->name, DRIVER_NAME); | ||
69 | DRM_COPY(version->date, DRIVER_DATE); | ||
70 | DRM_COPY(version->desc, DRIVER_DESC); | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | static struct pci_device_id pciidlist[] = { | 43 | static struct pci_device_id pciidlist[] = { |
75 | i830_PCI_IDS | 44 | i830_PCI_IDS |
76 | }; | 45 | }; |
@@ -83,12 +52,12 @@ static struct drm_driver driver = { | |||
83 | .driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ, | 52 | .driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ, |
84 | #endif | 53 | #endif |
85 | .dev_priv_size = sizeof(drm_i830_buf_priv_t), | 54 | .dev_priv_size = sizeof(drm_i830_buf_priv_t), |
86 | .pretakedown = i830_driver_pretakedown, | 55 | .load = i830_driver_load, |
87 | .prerelease = i830_driver_prerelease, | 56 | .lastclose = i830_driver_lastclose, |
57 | .preclose = i830_driver_preclose, | ||
88 | .device_is_agp = i830_driver_device_is_agp, | 58 | .device_is_agp = i830_driver_device_is_agp, |
89 | .release = i830_driver_release, | 59 | .reclaim_buffers_locked = i830_driver_reclaim_buffers_locked, |
90 | .dma_quiescent = i830_driver_dma_quiescent, | 60 | .dma_quiescent = i830_driver_dma_quiescent, |
91 | .reclaim_buffers = i830_reclaim_buffers, | ||
92 | .get_map_ofs = drm_core_get_map_ofs, | 61 | .get_map_ofs = drm_core_get_map_ofs, |
93 | .get_reg_ofs = drm_core_get_reg_ofs, | 62 | .get_reg_ofs = drm_core_get_reg_ofs, |
94 | #if USE_IRQS | 63 | #if USE_IRQS |
@@ -97,8 +66,6 @@ static struct drm_driver driver = { | |||
97 | .irq_uninstall = i830_driver_irq_uninstall, | 66 | .irq_uninstall = i830_driver_irq_uninstall, |
98 | .irq_handler = i830_driver_irq_handler, | 67 | .irq_handler = i830_driver_irq_handler, |
99 | #endif | 68 | #endif |
100 | .postinit = postinit, | ||
101 | .version = version, | ||
102 | .ioctls = i830_ioctls, | 69 | .ioctls = i830_ioctls, |
103 | .fops = { | 70 | .fops = { |
104 | .owner = THIS_MODULE, | 71 | .owner = THIS_MODULE, |
@@ -108,13 +75,19 @@ static struct drm_driver driver = { | |||
108 | .mmap = drm_mmap, | 75 | .mmap = drm_mmap, |
109 | .poll = drm_poll, | 76 | .poll = drm_poll, |
110 | .fasync = drm_fasync, | 77 | .fasync = drm_fasync, |
111 | } | 78 | }, |
112 | , | 79 | |
113 | .pci_driver = { | 80 | .pci_driver = { |
114 | .name = DRIVER_NAME, | 81 | .name = DRIVER_NAME, |
115 | .id_table = pciidlist, | 82 | .id_table = pciidlist, |
116 | } | 83 | }, |
117 | 84 | ||
85 | .name = DRIVER_NAME, | ||
86 | .desc = DRIVER_DESC, | ||
87 | .date = DRIVER_DATE, | ||
88 | .major = DRIVER_MAJOR, | ||
89 | .minor = DRIVER_MINOR, | ||
90 | .patchlevel = DRIVER_PATCHLEVEL, | ||
118 | }; | 91 | }; |
119 | 92 | ||
120 | static int __init i830_init(void) | 93 | static int __init i830_init(void) |
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h index bc4bd49fb0cc..bf9075b576bd 100644 --- a/drivers/char/drm/i830_drv.h +++ b/drivers/char/drm/i830_drv.h | |||
@@ -136,10 +136,12 @@ extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS); | |||
136 | extern void i830_driver_irq_preinstall(drm_device_t * dev); | 136 | extern void i830_driver_irq_preinstall(drm_device_t * dev); |
137 | extern void i830_driver_irq_postinstall(drm_device_t * dev); | 137 | extern void i830_driver_irq_postinstall(drm_device_t * dev); |
138 | extern void i830_driver_irq_uninstall(drm_device_t * dev); | 138 | extern void i830_driver_irq_uninstall(drm_device_t * dev); |
139 | extern void i830_driver_pretakedown(drm_device_t * dev); | 139 | extern int i830_driver_load(struct drm_device *, unsigned long flags); |
140 | extern void i830_driver_release(drm_device_t * dev, struct file *filp); | 140 | extern void i830_driver_preclose(drm_device_t * dev, DRMFILE filp); |
141 | extern void i830_driver_lastclose(drm_device_t * dev); | ||
142 | extern void i830_driver_reclaim_buffers_locked(drm_device_t * dev, | ||
143 | struct file *filp); | ||
141 | extern int i830_driver_dma_quiescent(drm_device_t * dev); | 144 | extern int i830_driver_dma_quiescent(drm_device_t * dev); |
142 | extern void i830_driver_prerelease(drm_device_t * dev, DRMFILE filp); | ||
143 | extern int i830_driver_device_is_agp(drm_device_t * dev); | 145 | extern int i830_driver_device_is_agp(drm_device_t * dev); |
144 | 146 | ||
145 | #define I830_READ(reg) DRM_READ32(dev_priv->mmio_map, reg) | 147 | #define I830_READ(reg) DRM_READ32(dev_priv->mmio_map, reg) |
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index f3aa0c370127..9140703da1ba 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c | |||
@@ -1,7 +1,6 @@ | |||
1 | /* i915_dma.c -- DMA support for the I915 -*- linux-c -*- | 1 | /* i915_dma.c -- DMA support for the I915 -*- linux-c -*- |
2 | */ | 2 | */ |
3 | /************************************************************************** | 3 | /* |
4 | * | ||
5 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | 4 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. |
6 | * All Rights Reserved. | 5 | * All Rights Reserved. |
7 | * | 6 | * |
@@ -25,7 +24,7 @@ | |||
25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | 24 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 25 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
27 | * | 26 | * |
28 | **************************************************************************/ | 27 | */ |
29 | 28 | ||
30 | #include "drmP.h" | 29 | #include "drmP.h" |
31 | #include "drm.h" | 30 | #include "drm.h" |
@@ -196,7 +195,7 @@ static int i915_initialize(drm_device_t * dev, | |||
196 | return 0; | 195 | return 0; |
197 | } | 196 | } |
198 | 197 | ||
199 | static int i915_resume(drm_device_t * dev) | 198 | static int i915_dma_resume(drm_device_t * dev) |
200 | { | 199 | { |
201 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 200 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
202 | 201 | ||
@@ -253,7 +252,7 @@ static int i915_dma_init(DRM_IOCTL_ARGS) | |||
253 | retcode = i915_dma_cleanup(dev); | 252 | retcode = i915_dma_cleanup(dev); |
254 | break; | 253 | break; |
255 | case I915_RESUME_DMA: | 254 | case I915_RESUME_DMA: |
256 | retcode = i915_resume(dev); | 255 | retcode = i915_dma_resume(dev); |
257 | break; | 256 | break; |
258 | default: | 257 | default: |
259 | retcode = -EINVAL; | 258 | retcode = -EINVAL; |
@@ -654,6 +653,9 @@ static int i915_getparam(DRM_IOCTL_ARGS) | |||
654 | case I915_PARAM_ALLOW_BATCHBUFFER: | 653 | case I915_PARAM_ALLOW_BATCHBUFFER: |
655 | value = dev_priv->allow_batchbuffer ? 1 : 0; | 654 | value = dev_priv->allow_batchbuffer ? 1 : 0; |
656 | break; | 655 | break; |
656 | case I915_PARAM_LAST_DISPATCH: | ||
657 | value = READ_BREADCRUMB(dev_priv); | ||
658 | break; | ||
657 | default: | 659 | default: |
658 | DRM_ERROR("Unkown parameter %d\n", param.param); | 660 | DRM_ERROR("Unkown parameter %d\n", param.param); |
659 | return DRM_ERR(EINVAL); | 661 | return DRM_ERR(EINVAL); |
@@ -699,7 +701,19 @@ static int i915_setparam(DRM_IOCTL_ARGS) | |||
699 | return 0; | 701 | return 0; |
700 | } | 702 | } |
701 | 703 | ||
702 | void i915_driver_pretakedown(drm_device_t * dev) | 704 | int i915_driver_load(drm_device_t *dev, unsigned long flags) |
705 | { | ||
706 | /* i915 has 4 more counters */ | ||
707 | dev->counters += 4; | ||
708 | dev->types[6] = _DRM_STAT_IRQ; | ||
709 | dev->types[7] = _DRM_STAT_PRIMARY; | ||
710 | dev->types[8] = _DRM_STAT_SECONDARY; | ||
711 | dev->types[9] = _DRM_STAT_DMA; | ||
712 | |||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | void i915_driver_lastclose(drm_device_t * dev) | ||
703 | { | 717 | { |
704 | if (dev->dev_private) { | 718 | if (dev->dev_private) { |
705 | drm_i915_private_t *dev_priv = dev->dev_private; | 719 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -708,7 +722,7 @@ void i915_driver_pretakedown(drm_device_t * dev) | |||
708 | i915_dma_cleanup(dev); | 722 | i915_dma_cleanup(dev); |
709 | } | 723 | } |
710 | 724 | ||
711 | void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp) | 725 | void i915_driver_preclose(drm_device_t * dev, DRMFILE filp) |
712 | { | 726 | { |
713 | if (dev->dev_private) { | 727 | if (dev->dev_private) { |
714 | drm_i915_private_t *dev_priv = dev->dev_private; | 728 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -717,18 +731,18 @@ void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp) | |||
717 | } | 731 | } |
718 | 732 | ||
719 | drm_ioctl_desc_t i915_ioctls[] = { | 733 | drm_ioctl_desc_t i915_ioctls[] = { |
720 | [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, 1, 1}, | 734 | [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
721 | [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, 1, 0}, | 735 | [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH}, |
722 | [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, 1, 0}, | 736 | [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, DRM_AUTH}, |
723 | [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, 1, 0}, | 737 | [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, DRM_AUTH}, |
724 | [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, 1, 0}, | 738 | [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, DRM_AUTH}, |
725 | [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, 1, 0}, | 739 | [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, DRM_AUTH}, |
726 | [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, 1, 0}, | 740 | [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, DRM_AUTH}, |
727 | [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, 1, 1}, | 741 | [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
728 | [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, 1, 0}, | 742 | [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH}, |
729 | [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, 1, 0}, | 743 | [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH}, |
730 | [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, 1, 1}, | 744 | [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
731 | [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, 1, 0} | 745 | [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH} |
732 | }; | 746 | }; |
733 | 747 | ||
734 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); | 748 | int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); |
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h index 23e027d29080..77412ddac007 100644 --- a/drivers/char/drm/i915_drm.h +++ b/drivers/char/drm/i915_drm.h | |||
@@ -1,5 +1,4 @@ | |||
1 | /************************************************************************** | 1 | /* |
2 | * | ||
3 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | 2 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. |
4 | * All Rights Reserved. | 3 | * All Rights Reserved. |
5 | * | 4 | * |
@@ -23,7 +22,7 @@ | |||
23 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | 22 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
24 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 23 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
25 | * | 24 | * |
26 | **************************************************************************/ | 25 | */ |
27 | 26 | ||
28 | #ifndef _I915_DRM_H_ | 27 | #ifndef _I915_DRM_H_ |
29 | #define _I915_DRM_H_ | 28 | #define _I915_DRM_H_ |
@@ -152,6 +151,7 @@ typedef struct drm_i915_irq_wait { | |||
152 | */ | 151 | */ |
153 | #define I915_PARAM_IRQ_ACTIVE 1 | 152 | #define I915_PARAM_IRQ_ACTIVE 1 |
154 | #define I915_PARAM_ALLOW_BATCHBUFFER 2 | 153 | #define I915_PARAM_ALLOW_BATCHBUFFER 2 |
154 | #define I915_PARAM_LAST_DISPATCH 3 | ||
155 | 155 | ||
156 | typedef struct drm_i915_getparam { | 156 | typedef struct drm_i915_getparam { |
157 | int param; | 157 | int param; |
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c index 0508240f4e3b..8e2e6095c4b3 100644 --- a/drivers/char/drm/i915_drv.c +++ b/drivers/char/drm/i915_drv.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*- | 1 | /* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*- |
2 | */ | 2 | */ |
3 | /************************************************************************** | 3 | /* |
4 | * | 4 | * |
5 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | 5 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. |
6 | * All Rights Reserved. | 6 | * All Rights Reserved. |
@@ -25,7 +25,7 @@ | |||
25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
27 | * | 27 | * |
28 | **************************************************************************/ | 28 | */ |
29 | 29 | ||
30 | #include "drmP.h" | 30 | #include "drmP.h" |
31 | #include "drm.h" | 31 | #include "drm.h" |
@@ -34,48 +34,22 @@ | |||
34 | 34 | ||
35 | #include "drm_pciids.h" | 35 | #include "drm_pciids.h" |
36 | 36 | ||
37 | static int postinit(struct drm_device *dev, unsigned long flags) | ||
38 | { | ||
39 | dev->counters += 4; | ||
40 | dev->types[6] = _DRM_STAT_IRQ; | ||
41 | dev->types[7] = _DRM_STAT_PRIMARY; | ||
42 | dev->types[8] = _DRM_STAT_SECONDARY; | ||
43 | dev->types[9] = _DRM_STAT_DMA; | ||
44 | |||
45 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n", | ||
46 | DRIVER_NAME, | ||
47 | DRIVER_MAJOR, | ||
48 | DRIVER_MINOR, | ||
49 | DRIVER_PATCHLEVEL, | ||
50 | DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev) | ||
51 | ); | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int version(drm_version_t * version) | ||
56 | { | ||
57 | int len; | ||
58 | |||
59 | version->version_major = DRIVER_MAJOR; | ||
60 | version->version_minor = DRIVER_MINOR; | ||
61 | version->version_patchlevel = DRIVER_PATCHLEVEL; | ||
62 | DRM_COPY(version->name, DRIVER_NAME); | ||
63 | DRM_COPY(version->date, DRIVER_DATE); | ||
64 | DRM_COPY(version->desc, DRIVER_DESC); | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | static struct pci_device_id pciidlist[] = { | 37 | static struct pci_device_id pciidlist[] = { |
69 | i915_PCI_IDS | 38 | i915_PCI_IDS |
70 | }; | 39 | }; |
71 | 40 | ||
72 | static struct drm_driver driver = { | 41 | static struct drm_driver driver = { |
42 | /* don't use mtrr's here, the Xserver or user space app should | ||
43 | * deal with them for intel hardware. | ||
44 | */ | ||
73 | .driver_features = | 45 | .driver_features = |
74 | DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | | 46 | DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/ |
75 | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, | 47 | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, |
76 | .pretakedown = i915_driver_pretakedown, | 48 | .load = i915_driver_load, |
77 | .prerelease = i915_driver_prerelease, | 49 | .lastclose = i915_driver_lastclose, |
50 | .preclose = i915_driver_preclose, | ||
78 | .device_is_agp = i915_driver_device_is_agp, | 51 | .device_is_agp = i915_driver_device_is_agp, |
52 | .vblank_wait = i915_driver_vblank_wait, | ||
79 | .irq_preinstall = i915_driver_irq_preinstall, | 53 | .irq_preinstall = i915_driver_irq_preinstall, |
80 | .irq_postinstall = i915_driver_irq_postinstall, | 54 | .irq_postinstall = i915_driver_irq_postinstall, |
81 | .irq_uninstall = i915_driver_irq_uninstall, | 55 | .irq_uninstall = i915_driver_irq_uninstall, |
@@ -83,8 +57,6 @@ static struct drm_driver driver = { | |||
83 | .reclaim_buffers = drm_core_reclaim_buffers, | 57 | .reclaim_buffers = drm_core_reclaim_buffers, |
84 | .get_map_ofs = drm_core_get_map_ofs, | 58 | .get_map_ofs = drm_core_get_map_ofs, |
85 | .get_reg_ofs = drm_core_get_reg_ofs, | 59 | .get_reg_ofs = drm_core_get_reg_ofs, |
86 | .postinit = postinit, | ||
87 | .version = version, | ||
88 | .ioctls = i915_ioctls, | 60 | .ioctls = i915_ioctls, |
89 | .fops = { | 61 | .fops = { |
90 | .owner = THIS_MODULE, | 62 | .owner = THIS_MODULE, |
@@ -97,11 +69,19 @@ static struct drm_driver driver = { | |||
97 | #ifdef CONFIG_COMPAT | 69 | #ifdef CONFIG_COMPAT |
98 | .compat_ioctl = i915_compat_ioctl, | 70 | .compat_ioctl = i915_compat_ioctl, |
99 | #endif | 71 | #endif |
100 | }, | 72 | }, |
73 | |||
101 | .pci_driver = { | 74 | .pci_driver = { |
102 | .name = DRIVER_NAME, | 75 | .name = DRIVER_NAME, |
103 | .id_table = pciidlist, | 76 | .id_table = pciidlist, |
104 | } | 77 | }, |
78 | |||
79 | .name = DRIVER_NAME, | ||
80 | .desc = DRIVER_DESC, | ||
81 | .date = DRIVER_DATE, | ||
82 | .major = DRIVER_MAJOR, | ||
83 | .minor = DRIVER_MINOR, | ||
84 | .patchlevel = DRIVER_PATCHLEVEL, | ||
105 | }; | 85 | }; |
106 | 86 | ||
107 | static int __init i915_init(void) | 87 | static int __init i915_init(void) |
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 17e457c73dc7..c6c71b45f101 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* i915_drv.h -- Private header for the I915 driver -*- linux-c -*- | 1 | /* i915_drv.h -- Private header for the I915 driver -*- linux-c -*- |
2 | */ | 2 | */ |
3 | /************************************************************************** | 3 | /* |
4 | * | 4 | * |
5 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | 5 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. |
6 | * All Rights Reserved. | 6 | * All Rights Reserved. |
@@ -25,7 +25,7 @@ | |||
25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | 25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
27 | * | 27 | * |
28 | **************************************************************************/ | 28 | */ |
29 | 29 | ||
30 | #ifndef _I915_DRV_H_ | 30 | #ifndef _I915_DRV_H_ |
31 | #define _I915_DRV_H_ | 31 | #define _I915_DRV_H_ |
@@ -37,21 +37,18 @@ | |||
37 | 37 | ||
38 | #define DRIVER_NAME "i915" | 38 | #define DRIVER_NAME "i915" |
39 | #define DRIVER_DESC "Intel Graphics" | 39 | #define DRIVER_DESC "Intel Graphics" |
40 | #define DRIVER_DATE "20040405" | 40 | #define DRIVER_DATE "20051209" |
41 | 41 | ||
42 | /* Interface history: | 42 | /* Interface history: |
43 | * | 43 | * |
44 | * 1.1: Original. | 44 | * 1.1: Original. |
45 | * 1.2: Add Power Management | ||
46 | * 1.3: Add vblank support | ||
45 | */ | 47 | */ |
46 | #define DRIVER_MAJOR 1 | 48 | #define DRIVER_MAJOR 1 |
47 | #define DRIVER_MINOR 1 | 49 | #define DRIVER_MINOR 3 |
48 | #define DRIVER_PATCHLEVEL 0 | 50 | #define DRIVER_PATCHLEVEL 0 |
49 | 51 | ||
50 | /* We use our own dma mechanisms, not the drm template code. However, | ||
51 | * the shared IRQ code is useful to us: | ||
52 | */ | ||
53 | #define __HAVE_PM 1 | ||
54 | |||
55 | typedef struct _drm_i915_ring_buffer { | 52 | typedef struct _drm_i915_ring_buffer { |
56 | int tail_mask; | 53 | int tail_mask; |
57 | unsigned long Start; | 54 | unsigned long Start; |
@@ -97,6 +94,7 @@ typedef struct drm_i915_private { | |||
97 | int tex_lru_log_granularity; | 94 | int tex_lru_log_granularity; |
98 | int allow_batchbuffer; | 95 | int allow_batchbuffer; |
99 | struct mem_block *agp_heap; | 96 | struct mem_block *agp_heap; |
97 | unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; | ||
100 | } drm_i915_private_t; | 98 | } drm_i915_private_t; |
101 | 99 | ||
102 | extern drm_ioctl_desc_t i915_ioctls[]; | 100 | extern drm_ioctl_desc_t i915_ioctls[]; |
@@ -104,14 +102,18 @@ extern int i915_max_ioctl; | |||
104 | 102 | ||
105 | /* i915_dma.c */ | 103 | /* i915_dma.c */ |
106 | extern void i915_kernel_lost_context(drm_device_t * dev); | 104 | extern void i915_kernel_lost_context(drm_device_t * dev); |
107 | extern void i915_driver_pretakedown(drm_device_t * dev); | 105 | extern int i915_driver_load(struct drm_device *, unsigned long flags); |
108 | extern void i915_driver_prerelease(drm_device_t * dev, DRMFILE filp); | 106 | extern void i915_driver_lastclose(drm_device_t * dev); |
107 | extern void i915_driver_preclose(drm_device_t * dev, DRMFILE filp); | ||
109 | extern int i915_driver_device_is_agp(drm_device_t * dev); | 108 | extern int i915_driver_device_is_agp(drm_device_t * dev); |
109 | extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, | ||
110 | unsigned long arg); | ||
110 | 111 | ||
111 | /* i915_irq.c */ | 112 | /* i915_irq.c */ |
112 | extern int i915_irq_emit(DRM_IOCTL_ARGS); | 113 | extern int i915_irq_emit(DRM_IOCTL_ARGS); |
113 | extern int i915_irq_wait(DRM_IOCTL_ARGS); | 114 | extern int i915_irq_wait(DRM_IOCTL_ARGS); |
114 | 115 | ||
116 | extern int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence); | ||
115 | extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); | 117 | extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); |
116 | extern void i915_driver_irq_preinstall(drm_device_t * dev); | 118 | extern void i915_driver_irq_preinstall(drm_device_t * dev); |
117 | extern void i915_driver_irq_postinstall(drm_device_t * dev); | 119 | extern void i915_driver_irq_postinstall(drm_device_t * dev); |
@@ -125,13 +127,10 @@ extern void i915_mem_takedown(struct mem_block **heap); | |||
125 | extern void i915_mem_release(drm_device_t * dev, | 127 | extern void i915_mem_release(drm_device_t * dev, |
126 | DRMFILE filp, struct mem_block *heap); | 128 | DRMFILE filp, struct mem_block *heap); |
127 | 129 | ||
128 | extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, | 130 | #define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg)) |
129 | unsigned long arg); | 131 | #define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val)) |
130 | 132 | #define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, (reg)) | |
131 | #define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, reg) | 133 | #define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, (reg), (val)) |
132 | #define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val) | ||
133 | #define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg) | ||
134 | #define I915_WRITE16(reg,val) DRM_WRITE16(dev_priv->mmio_map, reg, val) | ||
135 | 134 | ||
136 | #define I915_VERBOSE 0 | 135 | #define I915_VERBOSE 0 |
137 | 136 | ||
@@ -195,6 +194,13 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); | |||
195 | #define PPCR 0x61204 | 194 | #define PPCR 0x61204 |
196 | #define PPCR_ON (1<<0) | 195 | #define PPCR_ON (1<<0) |
197 | 196 | ||
197 | #define DVOB 0x61140 | ||
198 | #define DVOB_ON (1<<31) | ||
199 | #define DVOC 0x61160 | ||
200 | #define DVOC_ON (1<<31) | ||
201 | #define LVDS 0x61180 | ||
202 | #define LVDS_ON (1<<31) | ||
203 | |||
198 | #define ADPA 0x61100 | 204 | #define ADPA 0x61100 |
199 | #define ADPA_DPMS_MASK (~(3<<10)) | 205 | #define ADPA_DPMS_MASK (~(3<<10)) |
200 | #define ADPA_DPMS_ON (0<<10) | 206 | #define ADPA_DPMS_ON (0<<10) |
@@ -258,4 +264,6 @@ extern int i915_wait_ring(drm_device_t * dev, int n, const char *caller); | |||
258 | 264 | ||
259 | #define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) | 265 | #define CMD_OP_DESTBUFFER_INFO ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1) |
260 | 266 | ||
267 | #define READ_BREADCRUMB(dev_priv) (((u32 *)(dev_priv->hw_status_page))[5]) | ||
268 | |||
261 | #endif | 269 | #endif |
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index 4fa448ee846b..a1381c61aa63 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c | |||
@@ -1,7 +1,6 @@ | |||
1 | /* i915_dma.c -- DMA support for the I915 -*- linux-c -*- | 1 | /* i915_irq.c -- IRQ support for the I915 -*- linux-c -*- |
2 | */ | 2 | */ |
3 | /************************************************************************** | 3 | /* |
4 | * | ||
5 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | 4 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. |
6 | * All Rights Reserved. | 5 | * All Rights Reserved. |
7 | * | 6 | * |
@@ -25,16 +24,18 @@ | |||
25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | 24 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 25 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
27 | * | 26 | * |
28 | **************************************************************************/ | 27 | */ |
29 | 28 | ||
30 | #include "drmP.h" | 29 | #include "drmP.h" |
31 | #include "drm.h" | 30 | #include "drm.h" |
32 | #include "i915_drm.h" | 31 | #include "i915_drm.h" |
33 | #include "i915_drv.h" | 32 | #include "i915_drv.h" |
34 | 33 | ||
35 | #define USER_INT_FLAG 0x2 | 34 | #define USER_INT_FLAG (1<<1) |
35 | #define VSYNC_PIPEB_FLAG (1<<5) | ||
36 | #define VSYNC_PIPEA_FLAG (1<<7) | ||
37 | |||
36 | #define MAX_NOPID ((u32)~0) | 38 | #define MAX_NOPID ((u32)~0) |
37 | #define READ_BREADCRUMB(dev_priv) (((u32*)(dev_priv->hw_status_page))[5]) | ||
38 | 39 | ||
39 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | 40 | irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) |
40 | { | 41 | { |
@@ -43,7 +44,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
43 | u16 temp; | 44 | u16 temp; |
44 | 45 | ||
45 | temp = I915_READ16(I915REG_INT_IDENTITY_R); | 46 | temp = I915_READ16(I915REG_INT_IDENTITY_R); |
46 | temp &= USER_INT_FLAG; | 47 | temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG); |
47 | 48 | ||
48 | DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); | 49 | DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp); |
49 | 50 | ||
@@ -51,7 +52,15 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
51 | return IRQ_NONE; | 52 | return IRQ_NONE; |
52 | 53 | ||
53 | I915_WRITE16(I915REG_INT_IDENTITY_R, temp); | 54 | I915_WRITE16(I915REG_INT_IDENTITY_R, temp); |
54 | DRM_WAKEUP(&dev_priv->irq_queue); | 55 | |
56 | if (temp & USER_INT_FLAG) | ||
57 | DRM_WAKEUP(&dev_priv->irq_queue); | ||
58 | |||
59 | if (temp & VSYNC_PIPEA_FLAG) { | ||
60 | atomic_inc(&dev->vbl_received); | ||
61 | DRM_WAKEUP(&dev->vbl_queue); | ||
62 | drm_vbl_send_signals(dev); | ||
63 | } | ||
55 | 64 | ||
56 | return IRQ_HANDLED; | 65 | return IRQ_HANDLED; |
57 | } | 66 | } |
@@ -102,6 +111,27 @@ static int i915_wait_irq(drm_device_t * dev, int irq_nr) | |||
102 | return ret; | 111 | return ret; |
103 | } | 112 | } |
104 | 113 | ||
114 | int i915_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence) | ||
115 | { | ||
116 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
117 | unsigned int cur_vblank; | ||
118 | int ret = 0; | ||
119 | |||
120 | if (!dev_priv) { | ||
121 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
122 | return DRM_ERR(EINVAL); | ||
123 | } | ||
124 | |||
125 | DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, | ||
126 | (((cur_vblank = atomic_read(&dev->vbl_received)) | ||
127 | - *sequence) <= (1<<23))); | ||
128 | |||
129 | *sequence = cur_vblank; | ||
130 | |||
131 | return ret; | ||
132 | } | ||
133 | |||
134 | |||
105 | /* Needs the lock as it touches the ring. | 135 | /* Needs the lock as it touches the ring. |
106 | */ | 136 | */ |
107 | int i915_irq_emit(DRM_IOCTL_ARGS) | 137 | int i915_irq_emit(DRM_IOCTL_ARGS) |
@@ -165,7 +195,7 @@ void i915_driver_irq_postinstall(drm_device_t * dev) | |||
165 | { | 195 | { |
166 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 196 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
167 | 197 | ||
168 | I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG); | 198 | I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | VSYNC_PIPEA_FLAG); |
169 | DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); | 199 | DRM_INIT_WAITQUEUE(&dev_priv->irq_queue); |
170 | } | 200 | } |
171 | 201 | ||
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c index 13176d136a99..ba87ff17ff64 100644 --- a/drivers/char/drm/i915_mem.c +++ b/drivers/char/drm/i915_mem.c | |||
@@ -1,7 +1,6 @@ | |||
1 | /* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*- | 1 | /* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*- |
2 | */ | 2 | */ |
3 | /************************************************************************** | 3 | /* |
4 | * | ||
5 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. | 4 | * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. |
6 | * All Rights Reserved. | 5 | * All Rights Reserved. |
7 | * | 6 | * |
@@ -25,7 +24,7 @@ | |||
25 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | 24 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
26 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 25 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
27 | * | 26 | * |
28 | **************************************************************************/ | 27 | */ |
29 | 28 | ||
30 | #include "drmP.h" | 29 | #include "drmP.h" |
31 | #include "drm.h" | 30 | #include "drm.h" |
diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c index 70dc7f64b7b9..c2a4bac14521 100644 --- a/drivers/char/drm/mga_dma.c +++ b/drivers/char/drm/mga_dma.c | |||
@@ -44,7 +44,9 @@ | |||
44 | #define MGA_DEFAULT_USEC_TIMEOUT 10000 | 44 | #define MGA_DEFAULT_USEC_TIMEOUT 10000 |
45 | #define MGA_FREELIST_DEBUG 0 | 45 | #define MGA_FREELIST_DEBUG 0 |
46 | 46 | ||
47 | static int mga_do_cleanup_dma(drm_device_t * dev); | 47 | #define MINIMAL_CLEANUP 0 |
48 | #define FULL_CLEANUP 1 | ||
49 | static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup); | ||
48 | 50 | ||
49 | /* ================================================================ | 51 | /* ================================================================ |
50 | * Engine control | 52 | * Engine control |
@@ -391,7 +393,7 @@ int mga_freelist_put(drm_device_t * dev, drm_buf_t * buf) | |||
391 | * DMA initialization, cleanup | 393 | * DMA initialization, cleanup |
392 | */ | 394 | */ |
393 | 395 | ||
394 | int mga_driver_preinit(drm_device_t * dev, unsigned long flags) | 396 | int mga_driver_load(drm_device_t * dev, unsigned long flags) |
395 | { | 397 | { |
396 | drm_mga_private_t *dev_priv; | 398 | drm_mga_private_t *dev_priv; |
397 | 399 | ||
@@ -405,6 +407,14 @@ int mga_driver_preinit(drm_device_t * dev, unsigned long flags) | |||
405 | dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; | 407 | dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; |
406 | dev_priv->chipset = flags; | 408 | dev_priv->chipset = flags; |
407 | 409 | ||
410 | dev_priv->mmio_base = drm_get_resource_start(dev, 1); | ||
411 | dev_priv->mmio_size = drm_get_resource_len(dev, 1); | ||
412 | |||
413 | dev->counters += 3; | ||
414 | dev->types[6] = _DRM_STAT_IRQ; | ||
415 | dev->types[7] = _DRM_STAT_PRIMARY; | ||
416 | dev->types[8] = _DRM_STAT_SECONDARY; | ||
417 | |||
408 | return 0; | 418 | return 0; |
409 | } | 419 | } |
410 | 420 | ||
@@ -438,17 +448,19 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev, | |||
438 | drm_buf_desc_t req; | 448 | drm_buf_desc_t req; |
439 | drm_agp_mode_t mode; | 449 | drm_agp_mode_t mode; |
440 | drm_agp_info_t info; | 450 | drm_agp_info_t info; |
451 | drm_agp_buffer_t agp_req; | ||
452 | drm_agp_binding_t bind_req; | ||
441 | 453 | ||
442 | /* Acquire AGP. */ | 454 | /* Acquire AGP. */ |
443 | err = drm_agp_acquire(dev); | 455 | err = drm_agp_acquire(dev); |
444 | if (err) { | 456 | if (err) { |
445 | DRM_ERROR("Unable to acquire AGP\n"); | 457 | DRM_ERROR("Unable to acquire AGP: %d\n", err); |
446 | return err; | 458 | return err; |
447 | } | 459 | } |
448 | 460 | ||
449 | err = drm_agp_info(dev, &info); | 461 | err = drm_agp_info(dev, &info); |
450 | if (err) { | 462 | if (err) { |
451 | DRM_ERROR("Unable to get AGP info\n"); | 463 | DRM_ERROR("Unable to get AGP info: %d\n", err); |
452 | return err; | 464 | return err; |
453 | } | 465 | } |
454 | 466 | ||
@@ -472,18 +484,24 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev, | |||
472 | } | 484 | } |
473 | 485 | ||
474 | /* Allocate and bind AGP memory. */ | 486 | /* Allocate and bind AGP memory. */ |
475 | dev_priv->agp_pages = agp_size / PAGE_SIZE; | 487 | agp_req.size = agp_size; |
476 | dev_priv->agp_mem = drm_alloc_agp(dev, dev_priv->agp_pages, 0); | 488 | agp_req.type = 0; |
477 | if (dev_priv->agp_mem == NULL) { | 489 | err = drm_agp_alloc(dev, &agp_req); |
478 | dev_priv->agp_pages = 0; | 490 | if (err) { |
491 | dev_priv->agp_size = 0; | ||
479 | DRM_ERROR("Unable to allocate %uMB AGP memory\n", | 492 | DRM_ERROR("Unable to allocate %uMB AGP memory\n", |
480 | dma_bs->agp_size); | 493 | dma_bs->agp_size); |
481 | return DRM_ERR(ENOMEM); | 494 | return err; |
482 | } | 495 | } |
496 | |||
497 | dev_priv->agp_size = agp_size; | ||
498 | dev_priv->agp_handle = agp_req.handle; | ||
483 | 499 | ||
484 | err = drm_bind_agp(dev_priv->agp_mem, 0); | 500 | bind_req.handle = agp_req.handle; |
501 | bind_req.offset = 0; | ||
502 | err = drm_agp_bind(dev, &bind_req); | ||
485 | if (err) { | 503 | if (err) { |
486 | DRM_ERROR("Unable to bind AGP memory\n"); | 504 | DRM_ERROR("Unable to bind AGP memory: %d\n", err); |
487 | return err; | 505 | return err; |
488 | } | 506 | } |
489 | 507 | ||
@@ -497,7 +515,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev, | |||
497 | err = drm_addmap(dev, offset, warp_size, | 515 | err = drm_addmap(dev, offset, warp_size, |
498 | _DRM_AGP, _DRM_READ_ONLY, &dev_priv->warp); | 516 | _DRM_AGP, _DRM_READ_ONLY, &dev_priv->warp); |
499 | if (err) { | 517 | if (err) { |
500 | DRM_ERROR("Unable to map WARP microcode\n"); | 518 | DRM_ERROR("Unable to map WARP microcode: %d\n", err); |
501 | return err; | 519 | return err; |
502 | } | 520 | } |
503 | 521 | ||
@@ -505,7 +523,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev, | |||
505 | err = drm_addmap(dev, offset, dma_bs->primary_size, | 523 | err = drm_addmap(dev, offset, dma_bs->primary_size, |
506 | _DRM_AGP, _DRM_READ_ONLY, &dev_priv->primary); | 524 | _DRM_AGP, _DRM_READ_ONLY, &dev_priv->primary); |
507 | if (err) { | 525 | if (err) { |
508 | DRM_ERROR("Unable to map primary DMA region\n"); | 526 | DRM_ERROR("Unable to map primary DMA region: %d\n", err); |
509 | return err; | 527 | return err; |
510 | } | 528 | } |
511 | 529 | ||
@@ -513,7 +531,7 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev, | |||
513 | err = drm_addmap(dev, offset, secondary_size, | 531 | err = drm_addmap(dev, offset, secondary_size, |
514 | _DRM_AGP, 0, &dev->agp_buffer_map); | 532 | _DRM_AGP, 0, &dev->agp_buffer_map); |
515 | if (err) { | 533 | if (err) { |
516 | DRM_ERROR("Unable to map secondary DMA region\n"); | 534 | DRM_ERROR("Unable to map secondary DMA region: %d\n", err); |
517 | return err; | 535 | return err; |
518 | } | 536 | } |
519 | 537 | ||
@@ -525,15 +543,29 @@ static int mga_do_agp_dma_bootstrap(drm_device_t * dev, | |||
525 | 543 | ||
526 | err = drm_addbufs_agp(dev, &req); | 544 | err = drm_addbufs_agp(dev, &req); |
527 | if (err) { | 545 | if (err) { |
528 | DRM_ERROR("Unable to add secondary DMA buffers\n"); | 546 | DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err); |
529 | return err; | 547 | return err; |
530 | } | 548 | } |
531 | 549 | ||
550 | { | ||
551 | drm_map_list_t *_entry; | ||
552 | unsigned long agp_token = 0; | ||
553 | |||
554 | list_for_each_entry(_entry, &dev->maplist->head, head) { | ||
555 | if (_entry->map == dev->agp_buffer_map) | ||
556 | agp_token = _entry->user_token; | ||
557 | } | ||
558 | if (!agp_token) | ||
559 | return -EFAULT; | ||
560 | |||
561 | dev->agp_buffer_token = agp_token; | ||
562 | } | ||
563 | |||
532 | offset += secondary_size; | 564 | offset += secondary_size; |
533 | err = drm_addmap(dev, offset, agp_size - offset, | 565 | err = drm_addmap(dev, offset, agp_size - offset, |
534 | _DRM_AGP, 0, &dev_priv->agp_textures); | 566 | _DRM_AGP, 0, &dev_priv->agp_textures); |
535 | if (err) { | 567 | if (err) { |
536 | DRM_ERROR("Unable to map AGP texture region\n"); | 568 | DRM_ERROR("Unable to map AGP texture region %d\n", err); |
537 | return err; | 569 | return err; |
538 | } | 570 | } |
539 | 571 | ||
@@ -603,7 +635,8 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev, | |||
603 | err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT, | 635 | err = drm_addmap(dev, 0, warp_size, _DRM_CONSISTENT, |
604 | _DRM_READ_ONLY, &dev_priv->warp); | 636 | _DRM_READ_ONLY, &dev_priv->warp); |
605 | if (err != 0) { | 637 | if (err != 0) { |
606 | DRM_ERROR("Unable to create mapping for WARP microcode\n"); | 638 | DRM_ERROR("Unable to create mapping for WARP microcode: %d\n", |
639 | err); | ||
607 | return err; | 640 | return err; |
608 | } | 641 | } |
609 | 642 | ||
@@ -622,7 +655,7 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev, | |||
622 | } | 655 | } |
623 | 656 | ||
624 | if (err != 0) { | 657 | if (err != 0) { |
625 | DRM_ERROR("Unable to allocate primary DMA region\n"); | 658 | DRM_ERROR("Unable to allocate primary DMA region: %d\n", err); |
626 | return DRM_ERR(ENOMEM); | 659 | return DRM_ERR(ENOMEM); |
627 | } | 660 | } |
628 | 661 | ||
@@ -646,7 +679,7 @@ static int mga_do_pci_dma_bootstrap(drm_device_t * dev, | |||
646 | } | 679 | } |
647 | 680 | ||
648 | if (bin_count == 0) { | 681 | if (bin_count == 0) { |
649 | DRM_ERROR("Unable to add secondary DMA buffers\n"); | 682 | DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err); |
650 | return err; | 683 | return err; |
651 | } | 684 | } |
652 | 685 | ||
@@ -682,7 +715,7 @@ static int mga_do_dma_bootstrap(drm_device_t * dev, | |||
682 | err = drm_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size, | 715 | err = drm_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size, |
683 | _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio); | 716 | _DRM_REGISTERS, _DRM_READ_ONLY, &dev_priv->mmio); |
684 | if (err) { | 717 | if (err) { |
685 | DRM_ERROR("Unable to map MMIO region\n"); | 718 | DRM_ERROR("Unable to map MMIO region: %d\n", err); |
686 | return err; | 719 | return err; |
687 | } | 720 | } |
688 | 721 | ||
@@ -690,7 +723,7 @@ static int mga_do_dma_bootstrap(drm_device_t * dev, | |||
690 | _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL, | 723 | _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL, |
691 | &dev_priv->status); | 724 | &dev_priv->status); |
692 | if (err) { | 725 | if (err) { |
693 | DRM_ERROR("Unable to map status region\n"); | 726 | DRM_ERROR("Unable to map status region: %d\n", err); |
694 | return err; | 727 | return err; |
695 | } | 728 | } |
696 | 729 | ||
@@ -708,7 +741,7 @@ static int mga_do_dma_bootstrap(drm_device_t * dev, | |||
708 | */ | 741 | */ |
709 | 742 | ||
710 | if (err) { | 743 | if (err) { |
711 | mga_do_cleanup_dma(dev); | 744 | mga_do_cleanup_dma(dev, MINIMAL_CLEANUP); |
712 | } | 745 | } |
713 | 746 | ||
714 | /* Not only do we want to try and initialized PCI cards for PCI DMA, | 747 | /* Not only do we want to try and initialized PCI cards for PCI DMA, |
@@ -731,35 +764,32 @@ int mga_dma_bootstrap(DRM_IOCTL_ARGS) | |||
731 | DRM_DEVICE; | 764 | DRM_DEVICE; |
732 | drm_mga_dma_bootstrap_t bootstrap; | 765 | drm_mga_dma_bootstrap_t bootstrap; |
733 | int err; | 766 | int err; |
767 | static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 }; | ||
768 | const drm_mga_private_t *const dev_priv = | ||
769 | (drm_mga_private_t *) dev->dev_private; | ||
734 | 770 | ||
735 | DRM_COPY_FROM_USER_IOCTL(bootstrap, | 771 | DRM_COPY_FROM_USER_IOCTL(bootstrap, |
736 | (drm_mga_dma_bootstrap_t __user *) data, | 772 | (drm_mga_dma_bootstrap_t __user *) data, |
737 | sizeof(bootstrap)); | 773 | sizeof(bootstrap)); |
738 | 774 | ||
739 | err = mga_do_dma_bootstrap(dev, &bootstrap); | 775 | err = mga_do_dma_bootstrap(dev, &bootstrap); |
740 | if (!err) { | 776 | if (err) { |
741 | static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 }; | 777 | mga_do_cleanup_dma(dev, FULL_CLEANUP); |
742 | const drm_mga_private_t *const dev_priv = | 778 | return err; |
743 | (drm_mga_private_t *) dev->dev_private; | 779 | } |
744 | |||
745 | if (dev_priv->agp_textures != NULL) { | ||
746 | bootstrap.texture_handle = | ||
747 | dev_priv->agp_textures->offset; | ||
748 | bootstrap.texture_size = dev_priv->agp_textures->size; | ||
749 | } else { | ||
750 | bootstrap.texture_handle = 0; | ||
751 | bootstrap.texture_size = 0; | ||
752 | } | ||
753 | 780 | ||
754 | bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07]; | 781 | if (dev_priv->agp_textures != NULL) { |
755 | if (DRM_COPY_TO_USER((void __user *)data, &bootstrap, | 782 | bootstrap.texture_handle = dev_priv->agp_textures->offset; |
756 | sizeof(bootstrap))) { | 783 | bootstrap.texture_size = dev_priv->agp_textures->size; |
757 | err = DRM_ERR(EFAULT); | ||
758 | } | ||
759 | } else { | 784 | } else { |
760 | mga_do_cleanup_dma(dev); | 785 | bootstrap.texture_handle = 0; |
786 | bootstrap.texture_size = 0; | ||
761 | } | 787 | } |
762 | 788 | ||
789 | bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07]; | ||
790 | DRM_COPY_TO_USER_IOCTL((drm_mga_dma_bootstrap_t __user *)data, | ||
791 | bootstrap, sizeof(bootstrap)); | ||
792 | |||
763 | return err; | 793 | return err; |
764 | } | 794 | } |
765 | 795 | ||
@@ -853,13 +883,13 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init) | |||
853 | 883 | ||
854 | ret = mga_warp_install_microcode(dev_priv); | 884 | ret = mga_warp_install_microcode(dev_priv); |
855 | if (ret < 0) { | 885 | if (ret < 0) { |
856 | DRM_ERROR("failed to install WARP ucode!\n"); | 886 | DRM_ERROR("failed to install WARP ucode!: %d\n", ret); |
857 | return ret; | 887 | return ret; |
858 | } | 888 | } |
859 | 889 | ||
860 | ret = mga_warp_init(dev_priv); | 890 | ret = mga_warp_init(dev_priv); |
861 | if (ret < 0) { | 891 | if (ret < 0) { |
862 | DRM_ERROR("failed to init WARP engine!\n"); | 892 | DRM_ERROR("failed to init WARP engine!: %d\n", ret); |
863 | return ret; | 893 | return ret; |
864 | } | 894 | } |
865 | 895 | ||
@@ -904,7 +934,7 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init) | |||
904 | return 0; | 934 | return 0; |
905 | } | 935 | } |
906 | 936 | ||
907 | static int mga_do_cleanup_dma(drm_device_t * dev) | 937 | static int mga_do_cleanup_dma(drm_device_t *dev, int full_cleanup) |
908 | { | 938 | { |
909 | int err = 0; | 939 | int err = 0; |
910 | DRM_DEBUG("\n"); | 940 | DRM_DEBUG("\n"); |
@@ -932,31 +962,39 @@ static int mga_do_cleanup_dma(drm_device_t * dev) | |||
932 | 962 | ||
933 | if (dev_priv->used_new_dma_init) { | 963 | if (dev_priv->used_new_dma_init) { |
934 | #if __OS_HAS_AGP | 964 | #if __OS_HAS_AGP |
935 | if (dev_priv->agp_mem != NULL) { | 965 | if (dev_priv->agp_handle != 0) { |
936 | dev_priv->agp_textures = NULL; | 966 | drm_agp_binding_t unbind_req; |
937 | drm_unbind_agp(dev_priv->agp_mem); | 967 | drm_agp_buffer_t free_req; |
968 | |||
969 | unbind_req.handle = dev_priv->agp_handle; | ||
970 | drm_agp_unbind(dev, &unbind_req); | ||
938 | 971 | ||
939 | drm_free_agp(dev_priv->agp_mem, | 972 | free_req.handle = dev_priv->agp_handle; |
940 | dev_priv->agp_pages); | 973 | drm_agp_free(dev, &free_req); |
941 | dev_priv->agp_pages = 0; | 974 | |
942 | dev_priv->agp_mem = NULL; | 975 | dev_priv->agp_textures = NULL; |
976 | dev_priv->agp_size = 0; | ||
977 | dev_priv->agp_handle = 0; | ||
943 | } | 978 | } |
944 | 979 | ||
945 | if ((dev->agp != NULL) && dev->agp->acquired) { | 980 | if ((dev->agp != NULL) && dev->agp->acquired) { |
946 | err = drm_agp_release(dev); | 981 | err = drm_agp_release(dev); |
947 | } | 982 | } |
948 | #endif | 983 | #endif |
949 | dev_priv->used_new_dma_init = 0; | ||
950 | } | 984 | } |
951 | 985 | ||
952 | dev_priv->warp = NULL; | 986 | dev_priv->warp = NULL; |
953 | dev_priv->primary = NULL; | 987 | dev_priv->primary = NULL; |
954 | dev_priv->mmio = NULL; | ||
955 | dev_priv->status = NULL; | ||
956 | dev_priv->sarea = NULL; | 988 | dev_priv->sarea = NULL; |
957 | dev_priv->sarea_priv = NULL; | 989 | dev_priv->sarea_priv = NULL; |
958 | dev->agp_buffer_map = NULL; | 990 | dev->agp_buffer_map = NULL; |
959 | 991 | ||
992 | if (full_cleanup) { | ||
993 | dev_priv->mmio = NULL; | ||
994 | dev_priv->status = NULL; | ||
995 | dev_priv->used_new_dma_init = 0; | ||
996 | } | ||
997 | |||
960 | memset(&dev_priv->prim, 0, sizeof(dev_priv->prim)); | 998 | memset(&dev_priv->prim, 0, sizeof(dev_priv->prim)); |
961 | dev_priv->warp_pipe = 0; | 999 | dev_priv->warp_pipe = 0; |
962 | memset(dev_priv->warp_pipe_phys, 0, | 1000 | memset(dev_priv->warp_pipe_phys, 0, |
@@ -967,7 +1005,7 @@ static int mga_do_cleanup_dma(drm_device_t * dev) | |||
967 | } | 1005 | } |
968 | } | 1006 | } |
969 | 1007 | ||
970 | return err; | 1008 | return 0; |
971 | } | 1009 | } |
972 | 1010 | ||
973 | int mga_dma_init(DRM_IOCTL_ARGS) | 1011 | int mga_dma_init(DRM_IOCTL_ARGS) |
@@ -985,11 +1023,11 @@ int mga_dma_init(DRM_IOCTL_ARGS) | |||
985 | case MGA_INIT_DMA: | 1023 | case MGA_INIT_DMA: |
986 | err = mga_do_init_dma(dev, &init); | 1024 | err = mga_do_init_dma(dev, &init); |
987 | if (err) { | 1025 | if (err) { |
988 | (void)mga_do_cleanup_dma(dev); | 1026 | (void)mga_do_cleanup_dma(dev, FULL_CLEANUP); |
989 | } | 1027 | } |
990 | return err; | 1028 | return err; |
991 | case MGA_CLEANUP_DMA: | 1029 | case MGA_CLEANUP_DMA: |
992 | return mga_do_cleanup_dma(dev); | 1030 | return mga_do_cleanup_dma(dev, FULL_CLEANUP); |
993 | } | 1031 | } |
994 | 1032 | ||
995 | return DRM_ERR(EINVAL); | 1033 | return DRM_ERR(EINVAL); |
@@ -1118,7 +1156,7 @@ int mga_dma_buffers(DRM_IOCTL_ARGS) | |||
1118 | /** | 1156 | /** |
1119 | * Called just before the module is unloaded. | 1157 | * Called just before the module is unloaded. |
1120 | */ | 1158 | */ |
1121 | int mga_driver_postcleanup(drm_device_t * dev) | 1159 | int mga_driver_unload(drm_device_t * dev) |
1122 | { | 1160 | { |
1123 | drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER); | 1161 | drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER); |
1124 | dev->dev_private = NULL; | 1162 | dev->dev_private = NULL; |
@@ -1129,9 +1167,9 @@ int mga_driver_postcleanup(drm_device_t * dev) | |||
1129 | /** | 1167 | /** |
1130 | * Called when the last opener of the device is closed. | 1168 | * Called when the last opener of the device is closed. |
1131 | */ | 1169 | */ |
1132 | void mga_driver_pretakedown(drm_device_t * dev) | 1170 | void mga_driver_lastclose(drm_device_t * dev) |
1133 | { | 1171 | { |
1134 | mga_do_cleanup_dma(dev); | 1172 | mga_do_cleanup_dma(dev, FULL_CLEANUP); |
1135 | } | 1173 | } |
1136 | 1174 | ||
1137 | int mga_driver_dma_quiescent(drm_device_t * dev) | 1175 | int mga_driver_dma_quiescent(drm_device_t * dev) |
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c index 1713451a5cc6..9f7ed0e0351b 100644 --- a/drivers/char/drm/mga_drv.c +++ b/drivers/char/drm/mga_drv.c | |||
@@ -38,41 +38,6 @@ | |||
38 | #include "drm_pciids.h" | 38 | #include "drm_pciids.h" |
39 | 39 | ||
40 | static int mga_driver_device_is_agp(drm_device_t * dev); | 40 | static int mga_driver_device_is_agp(drm_device_t * dev); |
41 | static int postinit(struct drm_device *dev, unsigned long flags) | ||
42 | { | ||
43 | drm_mga_private_t *const dev_priv = | ||
44 | (drm_mga_private_t *) dev->dev_private; | ||
45 | |||
46 | dev_priv->mmio_base = pci_resource_start(dev->pdev, 1); | ||
47 | dev_priv->mmio_size = pci_resource_len(dev->pdev, 1); | ||
48 | |||
49 | dev->counters += 3; | ||
50 | dev->types[6] = _DRM_STAT_IRQ; | ||
51 | dev->types[7] = _DRM_STAT_PRIMARY; | ||
52 | dev->types[8] = _DRM_STAT_SECONDARY; | ||
53 | |||
54 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n", | ||
55 | DRIVER_NAME, | ||
56 | DRIVER_MAJOR, | ||
57 | DRIVER_MINOR, | ||
58 | DRIVER_PATCHLEVEL, | ||
59 | DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev) | ||
60 | ); | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static int version(drm_version_t * version) | ||
65 | { | ||
66 | int len; | ||
67 | |||
68 | version->version_major = DRIVER_MAJOR; | ||
69 | version->version_minor = DRIVER_MINOR; | ||
70 | version->version_patchlevel = DRIVER_PATCHLEVEL; | ||
71 | DRM_COPY(version->name, DRIVER_NAME); | ||
72 | DRM_COPY(version->date, DRIVER_DATE); | ||
73 | DRM_COPY(version->desc, DRIVER_DESC); | ||
74 | return 0; | ||
75 | } | ||
76 | 41 | ||
77 | static struct pci_device_id pciidlist[] = { | 42 | static struct pci_device_id pciidlist[] = { |
78 | mga_PCI_IDS | 43 | mga_PCI_IDS |
@@ -80,12 +45,12 @@ static struct pci_device_id pciidlist[] = { | |||
80 | 45 | ||
81 | static struct drm_driver driver = { | 46 | static struct drm_driver driver = { |
82 | .driver_features = | 47 | .driver_features = |
83 | DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | | 48 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | |
84 | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | | 49 | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | |
85 | DRIVER_IRQ_VBL, | 50 | DRIVER_IRQ_VBL, |
86 | .preinit = mga_driver_preinit, | 51 | .load = mga_driver_load, |
87 | .postcleanup = mga_driver_postcleanup, | 52 | .unload = mga_driver_unload, |
88 | .pretakedown = mga_driver_pretakedown, | 53 | .lastclose = mga_driver_lastclose, |
89 | .dma_quiescent = mga_driver_dma_quiescent, | 54 | .dma_quiescent = mga_driver_dma_quiescent, |
90 | .device_is_agp = mga_driver_device_is_agp, | 55 | .device_is_agp = mga_driver_device_is_agp, |
91 | .vblank_wait = mga_driver_vblank_wait, | 56 | .vblank_wait = mga_driver_vblank_wait, |
@@ -96,8 +61,6 @@ static struct drm_driver driver = { | |||
96 | .reclaim_buffers = drm_core_reclaim_buffers, | 61 | .reclaim_buffers = drm_core_reclaim_buffers, |
97 | .get_map_ofs = drm_core_get_map_ofs, | 62 | .get_map_ofs = drm_core_get_map_ofs, |
98 | .get_reg_ofs = drm_core_get_reg_ofs, | 63 | .get_reg_ofs = drm_core_get_reg_ofs, |
99 | .postinit = postinit, | ||
100 | .version = version, | ||
101 | .ioctls = mga_ioctls, | 64 | .ioctls = mga_ioctls, |
102 | .dma_ioctl = mga_dma_buffers, | 65 | .dma_ioctl = mga_dma_buffers, |
103 | .fops = { | 66 | .fops = { |
@@ -113,9 +76,16 @@ static struct drm_driver driver = { | |||
113 | #endif | 76 | #endif |
114 | }, | 77 | }, |
115 | .pci_driver = { | 78 | .pci_driver = { |
116 | .name = DRIVER_NAME, | 79 | .name = DRIVER_NAME, |
117 | .id_table = pciidlist, | 80 | .id_table = pciidlist, |
118 | } | 81 | }, |
82 | |||
83 | .name = DRIVER_NAME, | ||
84 | .desc = DRIVER_DESC, | ||
85 | .date = DRIVER_DATE, | ||
86 | .major = DRIVER_MAJOR, | ||
87 | .minor = DRIVER_MINOR, | ||
88 | .patchlevel = DRIVER_PATCHLEVEL, | ||
119 | }; | 89 | }; |
120 | 90 | ||
121 | static int __init mga_init(void) | 91 | static int __init mga_init(void) |
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h index 461728e6a58a..6b0c53193506 100644 --- a/drivers/char/drm/mga_drv.h +++ b/drivers/char/drm/mga_drv.h | |||
@@ -38,11 +38,11 @@ | |||
38 | 38 | ||
39 | #define DRIVER_NAME "mga" | 39 | #define DRIVER_NAME "mga" |
40 | #define DRIVER_DESC "Matrox G200/G400" | 40 | #define DRIVER_DESC "Matrox G200/G400" |
41 | #define DRIVER_DATE "20050607" | 41 | #define DRIVER_DATE "20051102" |
42 | 42 | ||
43 | #define DRIVER_MAJOR 3 | 43 | #define DRIVER_MAJOR 3 |
44 | #define DRIVER_MINOR 2 | 44 | #define DRIVER_MINOR 2 |
45 | #define DRIVER_PATCHLEVEL 0 | 45 | #define DRIVER_PATCHLEVEL 1 |
46 | 46 | ||
47 | typedef struct drm_mga_primary_buffer { | 47 | typedef struct drm_mga_primary_buffer { |
48 | u8 *start; | 48 | u8 *start; |
@@ -144,22 +144,22 @@ typedef struct drm_mga_private { | |||
144 | drm_local_map_t *primary; | 144 | drm_local_map_t *primary; |
145 | drm_local_map_t *agp_textures; | 145 | drm_local_map_t *agp_textures; |
146 | 146 | ||
147 | DRM_AGP_MEM *agp_mem; | 147 | unsigned long agp_handle; |
148 | unsigned int agp_pages; | 148 | unsigned int agp_size; |
149 | } drm_mga_private_t; | 149 | } drm_mga_private_t; |
150 | 150 | ||
151 | extern drm_ioctl_desc_t mga_ioctls[]; | 151 | extern drm_ioctl_desc_t mga_ioctls[]; |
152 | extern int mga_max_ioctl; | 152 | extern int mga_max_ioctl; |
153 | 153 | ||
154 | /* mga_dma.c */ | 154 | /* mga_dma.c */ |
155 | extern int mga_driver_preinit(drm_device_t * dev, unsigned long flags); | ||
156 | extern int mga_dma_bootstrap(DRM_IOCTL_ARGS); | 155 | extern int mga_dma_bootstrap(DRM_IOCTL_ARGS); |
157 | extern int mga_dma_init(DRM_IOCTL_ARGS); | 156 | extern int mga_dma_init(DRM_IOCTL_ARGS); |
158 | extern int mga_dma_flush(DRM_IOCTL_ARGS); | 157 | extern int mga_dma_flush(DRM_IOCTL_ARGS); |
159 | extern int mga_dma_reset(DRM_IOCTL_ARGS); | 158 | extern int mga_dma_reset(DRM_IOCTL_ARGS); |
160 | extern int mga_dma_buffers(DRM_IOCTL_ARGS); | 159 | extern int mga_dma_buffers(DRM_IOCTL_ARGS); |
161 | extern int mga_driver_postcleanup(drm_device_t * dev); | 160 | extern int mga_driver_load(drm_device_t *dev, unsigned long flags); |
162 | extern void mga_driver_pretakedown(drm_device_t * dev); | 161 | extern int mga_driver_unload(drm_device_t * dev); |
162 | extern void mga_driver_lastclose(drm_device_t * dev); | ||
163 | extern int mga_driver_dma_quiescent(drm_device_t * dev); | 163 | extern int mga_driver_dma_quiescent(drm_device_t * dev); |
164 | 164 | ||
165 | extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv); | 165 | extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv); |
diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c index 47f54b5ae956..2837e669183a 100644 --- a/drivers/char/drm/mga_state.c +++ b/drivers/char/drm/mga_state.c | |||
@@ -1127,19 +1127,19 @@ static int mga_wait_fence(DRM_IOCTL_ARGS) | |||
1127 | } | 1127 | } |
1128 | 1128 | ||
1129 | drm_ioctl_desc_t mga_ioctls[] = { | 1129 | drm_ioctl_desc_t mga_ioctls[] = { |
1130 | [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, 1, 1}, | 1130 | [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
1131 | [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, 1, 0}, | 1131 | [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, DRM_AUTH}, |
1132 | [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, 1, 0}, | 1132 | [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, DRM_AUTH}, |
1133 | [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, 1, 0}, | 1133 | [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, DRM_AUTH}, |
1134 | [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, 1, 0}, | 1134 | [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, DRM_AUTH}, |
1135 | [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, 1, 0}, | 1135 | [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, DRM_AUTH}, |
1136 | [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, 1, 0}, | 1136 | [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, DRM_AUTH}, |
1137 | [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, 1, 0}, | 1137 | [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, DRM_AUTH}, |
1138 | [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, 1, 0}, | 1138 | [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, DRM_AUTH}, |
1139 | [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, 1, 0}, | 1139 | [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, DRM_AUTH}, |
1140 | [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, 1, 0}, | 1140 | [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, DRM_AUTH}, |
1141 | [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, 1, 0}, | 1141 | [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, DRM_AUTH}, |
1142 | [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, 1, 1}, | 1142 | [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
1143 | }; | 1143 | }; |
1144 | 1144 | ||
1145 | int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); | 1145 | int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); |
diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c index 7452753d4d01..db5a60450e68 100644 --- a/drivers/char/drm/r128_cce.c +++ b/drivers/char/drm/r128_cce.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*- | 1 | /* r128_cce.c -- ATI Rage 128 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 | /* | ||
4 | * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. | 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. |
@@ -559,7 +560,8 @@ static int r128_do_init_cce(drm_device_t * dev, drm_r128_init_t * init) | |||
559 | if (dev_priv->is_pci) { | 560 | if (dev_priv->is_pci) { |
560 | #endif | 561 | #endif |
561 | dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; | 562 | dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; |
562 | dev_priv->gart_info.addr = dev_priv->gart_info.bus_addr = 0; | 563 | dev_priv->gart_info.addr = NULL; |
564 | dev_priv->gart_info.bus_addr = 0; | ||
563 | dev_priv->gart_info.is_pcie = 0; | 565 | dev_priv->gart_info.is_pcie = 0; |
564 | if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { | 566 | if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { |
565 | DRM_ERROR("failed to init PCI GART!\n"); | 567 | DRM_ERROR("failed to init PCI GART!\n"); |
@@ -601,15 +603,16 @@ int r128_do_cleanup_cce(drm_device_t * dev) | |||
601 | drm_core_ioremapfree(dev_priv->cce_ring, dev); | 603 | drm_core_ioremapfree(dev_priv->cce_ring, dev); |
602 | if (dev_priv->ring_rptr != NULL) | 604 | if (dev_priv->ring_rptr != NULL) |
603 | drm_core_ioremapfree(dev_priv->ring_rptr, dev); | 605 | drm_core_ioremapfree(dev_priv->ring_rptr, dev); |
604 | if (dev->agp_buffer_map != NULL) | 606 | if (dev->agp_buffer_map != NULL) { |
605 | drm_core_ioremapfree(dev->agp_buffer_map, dev); | 607 | drm_core_ioremapfree(dev->agp_buffer_map, dev); |
608 | dev->agp_buffer_map = NULL; | ||
609 | } | ||
606 | } else | 610 | } else |
607 | #endif | 611 | #endif |
608 | { | 612 | { |
609 | if (dev_priv->gart_info.bus_addr) | 613 | if (dev_priv->gart_info.bus_addr) |
610 | if (!drm_ati_pcigart_cleanup(dev, | 614 | if (!drm_ati_pcigart_cleanup(dev, |
611 | &dev_priv-> | 615 | &dev_priv->gart_info)) |
612 | gart_info)) | ||
613 | DRM_ERROR | 616 | DRM_ERROR |
614 | ("failed to cleanup PCI GART!\n"); | 617 | ("failed to cleanup PCI GART!\n"); |
615 | } | 618 | } |
diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h index 5ddc03202411..5d835b006f55 100644 --- a/drivers/char/drm/r128_drm.h +++ b/drivers/char/drm/r128_drm.h | |||
@@ -1,7 +1,7 @@ | |||
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 | /* Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. |
5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | 5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c index 1661e7351402..e20450ae220e 100644 --- a/drivers/char/drm/r128_drv.c +++ b/drivers/char/drm/r128_drv.c | |||
@@ -37,31 +37,6 @@ | |||
37 | 37 | ||
38 | #include "drm_pciids.h" | 38 | #include "drm_pciids.h" |
39 | 39 | ||
40 | static int postinit(struct drm_device *dev, unsigned long flags) | ||
41 | { | ||
42 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n", | ||
43 | DRIVER_NAME, | ||
44 | DRIVER_MAJOR, | ||
45 | DRIVER_MINOR, | ||
46 | DRIVER_PATCHLEVEL, | ||
47 | DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev) | ||
48 | ); | ||
49 | return 0; | ||
50 | } | ||
51 | |||
52 | static int version(drm_version_t * version) | ||
53 | { | ||
54 | int len; | ||
55 | |||
56 | version->version_major = DRIVER_MAJOR; | ||
57 | version->version_minor = DRIVER_MINOR; | ||
58 | version->version_patchlevel = DRIVER_PATCHLEVEL; | ||
59 | DRM_COPY(version->name, DRIVER_NAME); | ||
60 | DRM_COPY(version->date, DRIVER_DATE); | ||
61 | DRM_COPY(version->desc, DRIVER_DESC); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static struct pci_device_id pciidlist[] = { | 40 | static struct pci_device_id pciidlist[] = { |
66 | r128_PCI_IDS | 41 | r128_PCI_IDS |
67 | }; | 42 | }; |
@@ -72,8 +47,8 @@ static struct drm_driver driver = { | |||
72 | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | | 47 | DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | |
73 | DRIVER_IRQ_VBL, | 48 | DRIVER_IRQ_VBL, |
74 | .dev_priv_size = sizeof(drm_r128_buf_priv_t), | 49 | .dev_priv_size = sizeof(drm_r128_buf_priv_t), |
75 | .prerelease = r128_driver_prerelease, | 50 | .preclose = r128_driver_preclose, |
76 | .pretakedown = r128_driver_pretakedown, | 51 | .lastclose = r128_driver_lastclose, |
77 | .vblank_wait = r128_driver_vblank_wait, | 52 | .vblank_wait = r128_driver_vblank_wait, |
78 | .irq_preinstall = r128_driver_irq_preinstall, | 53 | .irq_preinstall = r128_driver_irq_preinstall, |
79 | .irq_postinstall = r128_driver_irq_postinstall, | 54 | .irq_postinstall = r128_driver_irq_postinstall, |
@@ -82,8 +57,6 @@ static struct drm_driver driver = { | |||
82 | .reclaim_buffers = drm_core_reclaim_buffers, | 57 | .reclaim_buffers = drm_core_reclaim_buffers, |
83 | .get_map_ofs = drm_core_get_map_ofs, | 58 | .get_map_ofs = drm_core_get_map_ofs, |
84 | .get_reg_ofs = drm_core_get_reg_ofs, | 59 | .get_reg_ofs = drm_core_get_reg_ofs, |
85 | .postinit = postinit, | ||
86 | .version = version, | ||
87 | .ioctls = r128_ioctls, | 60 | .ioctls = r128_ioctls, |
88 | .dma_ioctl = r128_cce_buffers, | 61 | .dma_ioctl = r128_cce_buffers, |
89 | .fops = { | 62 | .fops = { |
@@ -97,12 +70,19 @@ static struct drm_driver driver = { | |||
97 | #ifdef CONFIG_COMPAT | 70 | #ifdef CONFIG_COMPAT |
98 | .compat_ioctl = r128_compat_ioctl, | 71 | .compat_ioctl = r128_compat_ioctl, |
99 | #endif | 72 | #endif |
100 | } | 73 | }, |
101 | , | 74 | |
102 | .pci_driver = { | 75 | .pci_driver = { |
103 | .name = DRIVER_NAME, | 76 | .name = DRIVER_NAME, |
104 | .id_table = pciidlist, | 77 | .id_table = pciidlist, |
105 | } | 78 | }, |
79 | |||
80 | .name = DRIVER_NAME, | ||
81 | .desc = DRIVER_DESC, | ||
82 | .date = DRIVER_DATE, | ||
83 | .major = DRIVER_MAJOR, | ||
84 | .minor = DRIVER_MINOR, | ||
85 | .patchlevel = DRIVER_PATCHLEVEL, | ||
106 | }; | 86 | }; |
107 | 87 | ||
108 | static int __init r128_init(void) | 88 | static int __init r128_init(void) |
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h index 5c79e40eb88f..94abffb2cca5 100644 --- a/drivers/char/drm/r128_drv.h +++ b/drivers/char/drm/r128_drv.h | |||
@@ -1,7 +1,7 @@ | |||
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 | /* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. |
5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | 5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
@@ -154,8 +154,8 @@ extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS); | |||
154 | extern void r128_driver_irq_preinstall(drm_device_t * dev); | 154 | extern void r128_driver_irq_preinstall(drm_device_t * dev); |
155 | extern void r128_driver_irq_postinstall(drm_device_t * dev); | 155 | extern void r128_driver_irq_postinstall(drm_device_t * dev); |
156 | extern void r128_driver_irq_uninstall(drm_device_t * dev); | 156 | extern void r128_driver_irq_uninstall(drm_device_t * dev); |
157 | extern void r128_driver_pretakedown(drm_device_t * dev); | 157 | extern void r128_driver_lastclose(drm_device_t * dev); |
158 | extern void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp); | 158 | extern void r128_driver_preclose(drm_device_t * dev, DRMFILE filp); |
159 | 159 | ||
160 | extern long r128_compat_ioctl(struct file *filp, unsigned int cmd, | 160 | extern long r128_compat_ioctl(struct file *filp, unsigned int cmd, |
161 | unsigned long arg); | 161 | unsigned long arg); |
diff --git a/drivers/char/drm/r128_irq.c b/drivers/char/drm/r128_irq.c index 27eb0e31bd3b..87f8ca2b0685 100644 --- a/drivers/char/drm/r128_irq.c +++ b/drivers/char/drm/r128_irq.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- | 1 | /* r128_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/r128_state.c b/drivers/char/drm/r128_state.c index 14479cc08a57..caeecc2c36da 100644 --- a/drivers/char/drm/r128_state.c +++ b/drivers/char/drm/r128_state.c | |||
@@ -1,7 +1,7 @@ | |||
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 | /* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
5 | * All Rights Reserved. | 5 | * All Rights Reserved. |
6 | * | 6 | * |
7 | * Permission is hereby granted, free of charge, to any person obtaining a | 7 | * Permission is hereby granted, free of charge, to any person obtaining a |
@@ -1674,7 +1674,7 @@ static int r128_getparam(DRM_IOCTL_ARGS) | |||
1674 | return 0; | 1674 | return 0; |
1675 | } | 1675 | } |
1676 | 1676 | ||
1677 | void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp) | 1677 | void r128_driver_preclose(drm_device_t * dev, DRMFILE filp) |
1678 | { | 1678 | { |
1679 | if (dev->dev_private) { | 1679 | if (dev->dev_private) { |
1680 | drm_r128_private_t *dev_priv = dev->dev_private; | 1680 | drm_r128_private_t *dev_priv = dev->dev_private; |
@@ -1684,29 +1684,29 @@ void r128_driver_prerelease(drm_device_t * dev, DRMFILE filp) | |||
1684 | } | 1684 | } |
1685 | } | 1685 | } |
1686 | 1686 | ||
1687 | void r128_driver_pretakedown(drm_device_t * dev) | 1687 | void r128_driver_lastclose(drm_device_t * dev) |
1688 | { | 1688 | { |
1689 | r128_do_cleanup_cce(dev); | 1689 | r128_do_cleanup_cce(dev); |
1690 | } | 1690 | } |
1691 | 1691 | ||
1692 | drm_ioctl_desc_t r128_ioctls[] = { | 1692 | drm_ioctl_desc_t r128_ioctls[] = { |
1693 | [DRM_IOCTL_NR(DRM_R128_INIT)] = {r128_cce_init, 1, 1}, | 1693 | [DRM_IOCTL_NR(DRM_R128_INIT)] = {r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
1694 | [DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, 1, 1}, | 1694 | [DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
1695 | [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, 1, 1}, | 1695 | [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
1696 | [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, 1, 1}, | 1696 | [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
1697 | [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, 1, 0}, | 1697 | [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, DRM_AUTH}, |
1698 | [DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, 1, 0}, | 1698 | [DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, DRM_AUTH}, |
1699 | [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, 1, 0}, | 1699 | [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, DRM_AUTH}, |
1700 | [DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, 1, 0}, | 1700 | [DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, DRM_AUTH}, |
1701 | [DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, 1, 0}, | 1701 | [DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, DRM_AUTH}, |
1702 | [DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, 1, 0}, | 1702 | [DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, DRM_AUTH}, |
1703 | [DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, 1, 0}, | 1703 | [DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, DRM_AUTH}, |
1704 | [DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, 1, 0}, | 1704 | [DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, DRM_AUTH}, |
1705 | [DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, 1, 0}, | 1705 | [DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, DRM_AUTH}, |
1706 | [DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, 1, 0}, | 1706 | [DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, DRM_AUTH}, |
1707 | [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, 1, 0}, | 1707 | [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, DRM_AUTH}, |
1708 | [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, 1, 1}, | 1708 | [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
1709 | [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, 1, 0}, | 1709 | [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, DRM_AUTH}, |
1710 | }; | 1710 | }; |
1711 | 1711 | ||
1712 | int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls); | 1712 | int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls); |
diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 3a1ac5f78b43..291dbf4c8186 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c | |||
@@ -52,8 +52,8 @@ static const int r300_cliprect_cntl[4] = { | |||
52 | * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command | 52 | * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command |
53 | * buffer, starting with index n. | 53 | * buffer, starting with index n. |
54 | */ | 54 | */ |
55 | static int r300_emit_cliprects(drm_radeon_private_t * dev_priv, | 55 | static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, |
56 | drm_radeon_kcmd_buffer_t * cmdbuf, int n) | 56 | drm_radeon_kcmd_buffer_t *cmdbuf, int n) |
57 | { | 57 | { |
58 | drm_clip_rect_t box; | 58 | drm_clip_rect_t box; |
59 | int nr; | 59 | int nr; |
@@ -216,6 +216,7 @@ void r300_init_reg_flags(void) | |||
216 | ADD_RANGE(R300_TX_UNK1_0, 16); | 216 | ADD_RANGE(R300_TX_UNK1_0, 16); |
217 | ADD_RANGE(R300_TX_SIZE_0, 16); | 217 | ADD_RANGE(R300_TX_SIZE_0, 16); |
218 | ADD_RANGE(R300_TX_FORMAT_0, 16); | 218 | ADD_RANGE(R300_TX_FORMAT_0, 16); |
219 | ADD_RANGE(R300_TX_PITCH_0, 16); | ||
219 | /* Texture offset is dangerous and needs more checking */ | 220 | /* Texture offset is dangerous and needs more checking */ |
220 | ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); | 221 | ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); |
221 | ADD_RANGE(R300_TX_UNK4_0, 16); | 222 | ADD_RANGE(R300_TX_UNK4_0, 16); |
@@ -242,7 +243,7 @@ static __inline__ int r300_check_range(unsigned reg, int count) | |||
242 | 243 | ||
243 | /* we expect offsets passed to the framebuffer to be either within video memory or | 244 | /* we expect offsets passed to the framebuffer to be either within video memory or |
244 | within AGP space */ | 245 | within AGP space */ |
245 | static __inline__ int r300_check_offset(drm_radeon_private_t * dev_priv, | 246 | static __inline__ int r300_check_offset(drm_radeon_private_t *dev_priv, |
246 | u32 offset) | 247 | u32 offset) |
247 | { | 248 | { |
248 | /* we realy want to check against end of video aperture | 249 | /* we realy want to check against end of video aperture |
@@ -317,8 +318,8 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * | |||
317 | * | 318 | * |
318 | * Note that checks are performed on contents and addresses of the registers | 319 | * Note that checks are performed on contents and addresses of the registers |
319 | */ | 320 | */ |
320 | static __inline__ int r300_emit_packet0(drm_radeon_private_t * dev_priv, | 321 | static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv, |
321 | drm_radeon_kcmd_buffer_t * cmdbuf, | 322 | drm_radeon_kcmd_buffer_t *cmdbuf, |
322 | drm_r300_cmd_header_t header) | 323 | drm_r300_cmd_header_t header) |
323 | { | 324 | { |
324 | int reg; | 325 | int reg; |
@@ -363,8 +364,8 @@ static __inline__ int r300_emit_packet0(drm_radeon_private_t * dev_priv, | |||
363 | * the graphics card. | 364 | * the graphics card. |
364 | * Called by r300_do_cp_cmdbuf. | 365 | * Called by r300_do_cp_cmdbuf. |
365 | */ | 366 | */ |
366 | static __inline__ int r300_emit_vpu(drm_radeon_private_t * dev_priv, | 367 | static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv, |
367 | drm_radeon_kcmd_buffer_t * cmdbuf, | 368 | drm_radeon_kcmd_buffer_t *cmdbuf, |
368 | drm_r300_cmd_header_t header) | 369 | drm_r300_cmd_header_t header) |
369 | { | 370 | { |
370 | int sz; | 371 | int sz; |
@@ -400,8 +401,8 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t * dev_priv, | |||
400 | * Emit a clear packet from userspace. | 401 | * Emit a clear packet from userspace. |
401 | * Called by r300_emit_packet3. | 402 | * Called by r300_emit_packet3. |
402 | */ | 403 | */ |
403 | static __inline__ int r300_emit_clear(drm_radeon_private_t * dev_priv, | 404 | static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv, |
404 | drm_radeon_kcmd_buffer_t * cmdbuf) | 405 | drm_radeon_kcmd_buffer_t *cmdbuf) |
405 | { | 406 | { |
406 | RING_LOCALS; | 407 | RING_LOCALS; |
407 | 408 | ||
@@ -421,8 +422,8 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t * dev_priv, | |||
421 | return 0; | 422 | return 0; |
422 | } | 423 | } |
423 | 424 | ||
424 | static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv, | 425 | static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, |
425 | drm_radeon_kcmd_buffer_t * cmdbuf, | 426 | drm_radeon_kcmd_buffer_t *cmdbuf, |
426 | u32 header) | 427 | u32 header) |
427 | { | 428 | { |
428 | int count, i, k; | 429 | int count, i, k; |
@@ -489,8 +490,8 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t * dev_priv, | |||
489 | return 0; | 490 | return 0; |
490 | } | 491 | } |
491 | 492 | ||
492 | static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv, | 493 | static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, |
493 | drm_radeon_kcmd_buffer_t * cmdbuf) | 494 | drm_radeon_kcmd_buffer_t *cmdbuf) |
494 | { | 495 | { |
495 | u32 header; | 496 | u32 header; |
496 | int count; | 497 | int count; |
@@ -554,8 +555,8 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t * dev_priv, | |||
554 | * Emit a rendering packet3 from userspace. | 555 | * Emit a rendering packet3 from userspace. |
555 | * Called by r300_do_cp_cmdbuf. | 556 | * Called by r300_do_cp_cmdbuf. |
556 | */ | 557 | */ |
557 | static __inline__ int r300_emit_packet3(drm_radeon_private_t * dev_priv, | 558 | static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv, |
558 | drm_radeon_kcmd_buffer_t * cmdbuf, | 559 | drm_radeon_kcmd_buffer_t *cmdbuf, |
559 | drm_r300_cmd_header_t header) | 560 | drm_r300_cmd_header_t header) |
560 | { | 561 | { |
561 | int n; | 562 | int n; |
@@ -623,7 +624,7 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t * dev_priv, | |||
623 | /** | 624 | /** |
624 | * Emit the sequence to pacify R300. | 625 | * Emit the sequence to pacify R300. |
625 | */ | 626 | */ |
626 | static __inline__ void r300_pacify(drm_radeon_private_t * dev_priv) | 627 | static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv) |
627 | { | 628 | { |
628 | RING_LOCALS; | 629 | RING_LOCALS; |
629 | 630 | ||
@@ -657,9 +658,10 @@ static void r300_discard_buffer(drm_device_t * dev, drm_buf_t * buf) | |||
657 | * commands on the DMA ring buffer. | 658 | * commands on the DMA ring buffer. |
658 | * Called by the ioctl handler function radeon_cp_cmdbuf. | 659 | * Called by the ioctl handler function radeon_cp_cmdbuf. |
659 | */ | 660 | */ |
660 | int r300_do_cp_cmdbuf(drm_device_t * dev, | 661 | int r300_do_cp_cmdbuf(drm_device_t *dev, |
661 | DRMFILE filp, | 662 | DRMFILE filp, |
662 | drm_file_t * filp_priv, drm_radeon_kcmd_buffer_t * cmdbuf) | 663 | drm_file_t *filp_priv, |
664 | drm_radeon_kcmd_buffer_t *cmdbuf) | ||
663 | { | 665 | { |
664 | drm_radeon_private_t *dev_priv = dev->dev_private; | 666 | drm_radeon_private_t *dev_priv = dev->dev_private; |
665 | drm_device_dma_t *dma = dev->dma; | 667 | drm_device_dma_t *dma = dev->dma; |
diff --git a/drivers/char/drm/r300_reg.h b/drivers/char/drm/r300_reg.h index e5b73c002394..a0ed20e25221 100644 --- a/drivers/char/drm/r300_reg.h +++ b/drivers/char/drm/r300_reg.h | |||
@@ -797,6 +797,7 @@ I am fairly certain that they are correct unless stated otherwise in comments. | |||
797 | 797 | ||
798 | # define R300_TX_FORMAT_YUV_MODE 0x00800000 | 798 | # define R300_TX_FORMAT_YUV_MODE 0x00800000 |
799 | 799 | ||
800 | #define R300_TX_PITCH_0 0x4500 | ||
800 | #define R300_TX_OFFSET_0 0x4540 | 801 | #define R300_TX_OFFSET_0 0x4540 |
801 | /* BEGIN: Guess from R200 */ | 802 | /* BEGIN: Guess from R200 */ |
802 | # define R300_TXO_ENDIAN_NO_SWAP (0 << 0) | 803 | # define R300_TXO_ENDIAN_NO_SWAP (0 << 0) |
diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index 342302d46743..915665c7fe7c 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* radeon_cp.c -- CP support for Radeon -*- linux-c -*- | 1 | /* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */ |
2 | * | 2 | /* |
3 | * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. | 3 | * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. |
4 | * Copyright 2000 VA Linux Systems, Inc., Fremont, California. | 4 | * Copyright 2000 VA Linux Systems, Inc., Fremont, California. |
5 | * All Rights Reserved. | 5 | * All Rights Reserved. |
@@ -824,7 +824,7 @@ static int RADEON_READ_PLL(drm_device_t * dev, int addr) | |||
824 | return RADEON_READ(RADEON_CLOCK_CNTL_DATA); | 824 | return RADEON_READ(RADEON_CLOCK_CNTL_DATA); |
825 | } | 825 | } |
826 | 826 | ||
827 | static int RADEON_READ_PCIE(drm_radeon_private_t * dev_priv, int addr) | 827 | static int RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr) |
828 | { | 828 | { |
829 | RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff); | 829 | RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff); |
830 | return RADEON_READ(RADEON_PCIE_DATA); | 830 | return RADEON_READ(RADEON_PCIE_DATA); |
@@ -1125,7 +1125,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, | |||
1125 | | (dev_priv->fb_location >> 16)); | 1125 | | (dev_priv->fb_location >> 16)); |
1126 | 1126 | ||
1127 | #if __OS_HAS_AGP | 1127 | #if __OS_HAS_AGP |
1128 | if (!dev_priv->is_pci) { | 1128 | if (dev_priv->flags & CHIP_IS_AGP) { |
1129 | RADEON_WRITE(RADEON_MC_AGP_LOCATION, | 1129 | RADEON_WRITE(RADEON_MC_AGP_LOCATION, |
1130 | (((dev_priv->gart_vm_start - 1 + | 1130 | (((dev_priv->gart_vm_start - 1 + |
1131 | dev_priv->gart_size) & 0xffff0000) | | 1131 | dev_priv->gart_size) & 0xffff0000) | |
@@ -1152,7 +1152,7 @@ static void radeon_cp_init_ring_buffer(drm_device_t * dev, | |||
1152 | dev_priv->ring.tail = cur_read_ptr; | 1152 | dev_priv->ring.tail = cur_read_ptr; |
1153 | 1153 | ||
1154 | #if __OS_HAS_AGP | 1154 | #if __OS_HAS_AGP |
1155 | if (!dev_priv->is_pci) { | 1155 | if (dev_priv->flags & CHIP_IS_AGP) { |
1156 | /* set RADEON_AGP_BASE here instead of relying on X from user space */ | 1156 | /* set RADEON_AGP_BASE here instead of relying on X from user space */ |
1157 | RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); | 1157 | RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base); |
1158 | RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, | 1158 | RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, |
@@ -1278,13 +1278,15 @@ static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) | |||
1278 | /* Enable or disable PCI GART on the chip */ | 1278 | /* Enable or disable PCI GART on the chip */ |
1279 | static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) | 1279 | static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) |
1280 | { | 1280 | { |
1281 | u32 tmp = RADEON_READ(RADEON_AIC_CNTL); | 1281 | u32 tmp; |
1282 | 1282 | ||
1283 | if (dev_priv->flags & CHIP_IS_PCIE) { | 1283 | if (dev_priv->flags & CHIP_IS_PCIE) { |
1284 | radeon_set_pciegart(dev_priv, on); | 1284 | radeon_set_pciegart(dev_priv, on); |
1285 | return; | 1285 | return; |
1286 | } | 1286 | } |
1287 | 1287 | ||
1288 | tmp = RADEON_READ(RADEON_AIC_CNTL); | ||
1289 | |||
1288 | if (on) { | 1290 | if (on) { |
1289 | RADEON_WRITE(RADEON_AIC_CNTL, | 1291 | RADEON_WRITE(RADEON_AIC_CNTL, |
1290 | tmp | RADEON_PCIGART_TRANSLATE_EN); | 1292 | tmp | RADEON_PCIGART_TRANSLATE_EN); |
@@ -1312,13 +1314,17 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) | |||
1312 | static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | 1314 | static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) |
1313 | { | 1315 | { |
1314 | drm_radeon_private_t *dev_priv = dev->dev_private; | 1316 | drm_radeon_private_t *dev_priv = dev->dev_private; |
1317 | |||
1315 | DRM_DEBUG("\n"); | 1318 | DRM_DEBUG("\n"); |
1316 | 1319 | ||
1317 | dev_priv->is_pci = init->is_pci; | 1320 | if (init->is_pci && (dev_priv->flags & CHIP_IS_AGP)) |
1321 | { | ||
1322 | DRM_DEBUG("Forcing AGP card to PCI mode\n"); | ||
1323 | dev_priv->flags &= ~CHIP_IS_AGP; | ||
1324 | } | ||
1318 | 1325 | ||
1319 | if (dev_priv->is_pci && !dev->sg) { | 1326 | if ((!(dev_priv->flags & CHIP_IS_AGP)) && !dev->sg) { |
1320 | DRM_ERROR("PCI GART memory not allocated!\n"); | 1327 | DRM_ERROR("PCI GART memory not allocated!\n"); |
1321 | dev->dev_private = (void *)dev_priv; | ||
1322 | radeon_do_cleanup_cp(dev); | 1328 | radeon_do_cleanup_cp(dev); |
1323 | return DRM_ERR(EINVAL); | 1329 | return DRM_ERR(EINVAL); |
1324 | } | 1330 | } |
@@ -1327,12 +1333,11 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1327 | if (dev_priv->usec_timeout < 1 || | 1333 | if (dev_priv->usec_timeout < 1 || |
1328 | dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) { | 1334 | dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) { |
1329 | DRM_DEBUG("TIMEOUT problem!\n"); | 1335 | DRM_DEBUG("TIMEOUT problem!\n"); |
1330 | dev->dev_private = (void *)dev_priv; | ||
1331 | radeon_do_cleanup_cp(dev); | 1336 | radeon_do_cleanup_cp(dev); |
1332 | return DRM_ERR(EINVAL); | 1337 | return DRM_ERR(EINVAL); |
1333 | } | 1338 | } |
1334 | 1339 | ||
1335 | switch (init->func) { | 1340 | switch(init->func) { |
1336 | case RADEON_INIT_R200_CP: | 1341 | case RADEON_INIT_R200_CP: |
1337 | dev_priv->microcode_version = UCODE_R200; | 1342 | dev_priv->microcode_version = UCODE_R200; |
1338 | break; | 1343 | break; |
@@ -1353,7 +1358,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1353 | if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) && | 1358 | if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) && |
1354 | (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) { | 1359 | (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) { |
1355 | DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode); | 1360 | DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode); |
1356 | dev->dev_private = (void *)dev_priv; | ||
1357 | radeon_do_cleanup_cp(dev); | 1361 | radeon_do_cleanup_cp(dev); |
1358 | return DRM_ERR(EINVAL); | 1362 | return DRM_ERR(EINVAL); |
1359 | } | 1363 | } |
@@ -1416,8 +1420,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1416 | 1420 | ||
1417 | DRM_GETSAREA(); | 1421 | DRM_GETSAREA(); |
1418 | 1422 | ||
1419 | dev_priv->fb_offset = init->fb_offset; | ||
1420 | dev_priv->mmio_offset = init->mmio_offset; | ||
1421 | dev_priv->ring_offset = init->ring_offset; | 1423 | dev_priv->ring_offset = init->ring_offset; |
1422 | dev_priv->ring_rptr_offset = init->ring_rptr_offset; | 1424 | dev_priv->ring_rptr_offset = init->ring_rptr_offset; |
1423 | dev_priv->buffers_offset = init->buffers_offset; | 1425 | dev_priv->buffers_offset = init->buffers_offset; |
@@ -1425,29 +1427,19 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1425 | 1427 | ||
1426 | if (!dev_priv->sarea) { | 1428 | if (!dev_priv->sarea) { |
1427 | DRM_ERROR("could not find sarea!\n"); | 1429 | DRM_ERROR("could not find sarea!\n"); |
1428 | dev->dev_private = (void *)dev_priv; | ||
1429 | radeon_do_cleanup_cp(dev); | 1430 | radeon_do_cleanup_cp(dev); |
1430 | return DRM_ERR(EINVAL); | 1431 | return DRM_ERR(EINVAL); |
1431 | } | 1432 | } |
1432 | 1433 | ||
1433 | dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); | ||
1434 | if (!dev_priv->mmio) { | ||
1435 | DRM_ERROR("could not find mmio region!\n"); | ||
1436 | dev->dev_private = (void *)dev_priv; | ||
1437 | radeon_do_cleanup_cp(dev); | ||
1438 | return DRM_ERR(EINVAL); | ||
1439 | } | ||
1440 | dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset); | 1434 | dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset); |
1441 | if (!dev_priv->cp_ring) { | 1435 | if (!dev_priv->cp_ring) { |
1442 | DRM_ERROR("could not find cp ring region!\n"); | 1436 | DRM_ERROR("could not find cp ring region!\n"); |
1443 | dev->dev_private = (void *)dev_priv; | ||
1444 | radeon_do_cleanup_cp(dev); | 1437 | radeon_do_cleanup_cp(dev); |
1445 | return DRM_ERR(EINVAL); | 1438 | return DRM_ERR(EINVAL); |
1446 | } | 1439 | } |
1447 | dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); | 1440 | dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); |
1448 | if (!dev_priv->ring_rptr) { | 1441 | if (!dev_priv->ring_rptr) { |
1449 | DRM_ERROR("could not find ring read pointer!\n"); | 1442 | DRM_ERROR("could not find ring read pointer!\n"); |
1450 | dev->dev_private = (void *)dev_priv; | ||
1451 | radeon_do_cleanup_cp(dev); | 1443 | radeon_do_cleanup_cp(dev); |
1452 | return DRM_ERR(EINVAL); | 1444 | return DRM_ERR(EINVAL); |
1453 | } | 1445 | } |
@@ -1455,7 +1447,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1455 | dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); | 1447 | dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); |
1456 | if (!dev->agp_buffer_map) { | 1448 | if (!dev->agp_buffer_map) { |
1457 | DRM_ERROR("could not find dma buffer region!\n"); | 1449 | DRM_ERROR("could not find dma buffer region!\n"); |
1458 | dev->dev_private = (void *)dev_priv; | ||
1459 | radeon_do_cleanup_cp(dev); | 1450 | radeon_do_cleanup_cp(dev); |
1460 | return DRM_ERR(EINVAL); | 1451 | return DRM_ERR(EINVAL); |
1461 | } | 1452 | } |
@@ -1465,7 +1456,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1465 | drm_core_findmap(dev, init->gart_textures_offset); | 1456 | drm_core_findmap(dev, init->gart_textures_offset); |
1466 | if (!dev_priv->gart_textures) { | 1457 | if (!dev_priv->gart_textures) { |
1467 | DRM_ERROR("could not find GART texture region!\n"); | 1458 | DRM_ERROR("could not find GART texture region!\n"); |
1468 | dev->dev_private = (void *)dev_priv; | ||
1469 | radeon_do_cleanup_cp(dev); | 1459 | radeon_do_cleanup_cp(dev); |
1470 | return DRM_ERR(EINVAL); | 1460 | return DRM_ERR(EINVAL); |
1471 | } | 1461 | } |
@@ -1476,7 +1466,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1476 | init->sarea_priv_offset); | 1466 | init->sarea_priv_offset); |
1477 | 1467 | ||
1478 | #if __OS_HAS_AGP | 1468 | #if __OS_HAS_AGP |
1479 | if (!dev_priv->is_pci) { | 1469 | if (dev_priv->flags & CHIP_IS_AGP) { |
1480 | drm_core_ioremap(dev_priv->cp_ring, dev); | 1470 | drm_core_ioremap(dev_priv->cp_ring, dev); |
1481 | drm_core_ioremap(dev_priv->ring_rptr, dev); | 1471 | drm_core_ioremap(dev_priv->ring_rptr, dev); |
1482 | drm_core_ioremap(dev->agp_buffer_map, dev); | 1472 | drm_core_ioremap(dev->agp_buffer_map, dev); |
@@ -1484,7 +1474,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1484 | !dev_priv->ring_rptr->handle || | 1474 | !dev_priv->ring_rptr->handle || |
1485 | !dev->agp_buffer_map->handle) { | 1475 | !dev->agp_buffer_map->handle) { |
1486 | DRM_ERROR("could not find ioremap agp regions!\n"); | 1476 | DRM_ERROR("could not find ioremap agp regions!\n"); |
1487 | dev->dev_private = (void *)dev_priv; | ||
1488 | radeon_do_cleanup_cp(dev); | 1477 | radeon_do_cleanup_cp(dev); |
1489 | return DRM_ERR(EINVAL); | 1478 | return DRM_ERR(EINVAL); |
1490 | } | 1479 | } |
@@ -1525,7 +1514,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1525 | + RADEON_READ(RADEON_CONFIG_APER_SIZE); | 1514 | + RADEON_READ(RADEON_CONFIG_APER_SIZE); |
1526 | 1515 | ||
1527 | #if __OS_HAS_AGP | 1516 | #if __OS_HAS_AGP |
1528 | if (!dev_priv->is_pci) | 1517 | if (dev_priv->flags & CHIP_IS_AGP) |
1529 | dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset | 1518 | dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset |
1530 | - dev->agp->base | 1519 | - dev->agp->base |
1531 | + dev_priv->gart_vm_start); | 1520 | + dev_priv->gart_vm_start); |
@@ -1551,7 +1540,7 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1551 | dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; | 1540 | dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; |
1552 | 1541 | ||
1553 | #if __OS_HAS_AGP | 1542 | #if __OS_HAS_AGP |
1554 | if (!dev_priv->is_pci) { | 1543 | if (dev_priv->flags & CHIP_IS_AGP) { |
1555 | /* Turn off PCI GART */ | 1544 | /* Turn off PCI GART */ |
1556 | radeon_set_pcigart(dev_priv, 0); | 1545 | radeon_set_pcigart(dev_priv, 0); |
1557 | } else | 1546 | } else |
@@ -1561,25 +1550,28 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1561 | if (dev_priv->pcigart_offset) { | 1550 | if (dev_priv->pcigart_offset) { |
1562 | dev_priv->gart_info.bus_addr = | 1551 | dev_priv->gart_info.bus_addr = |
1563 | dev_priv->pcigart_offset + dev_priv->fb_location; | 1552 | dev_priv->pcigart_offset + dev_priv->fb_location; |
1553 | dev_priv->gart_info.mapping.offset = | ||
1554 | dev_priv->gart_info.bus_addr; | ||
1555 | dev_priv->gart_info.mapping.size = | ||
1556 | RADEON_PCIGART_TABLE_SIZE; | ||
1557 | |||
1558 | drm_core_ioremap(&dev_priv->gart_info.mapping, dev); | ||
1564 | dev_priv->gart_info.addr = | 1559 | dev_priv->gart_info.addr = |
1565 | (unsigned long)drm_ioremap(dev_priv->gart_info. | 1560 | dev_priv->gart_info.mapping.handle; |
1566 | bus_addr, | ||
1567 | RADEON_PCIGART_TABLE_SIZE, | ||
1568 | dev); | ||
1569 | 1561 | ||
1570 | dev_priv->gart_info.is_pcie = | 1562 | dev_priv->gart_info.is_pcie = |
1571 | !!(dev_priv->flags & CHIP_IS_PCIE); | 1563 | !!(dev_priv->flags & CHIP_IS_PCIE); |
1572 | dev_priv->gart_info.gart_table_location = | 1564 | dev_priv->gart_info.gart_table_location = |
1573 | DRM_ATI_GART_FB; | 1565 | DRM_ATI_GART_FB; |
1574 | 1566 | ||
1575 | DRM_DEBUG("Setting phys_pci_gart to %08lX %08lX\n", | 1567 | DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n", |
1576 | dev_priv->gart_info.addr, | 1568 | dev_priv->gart_info.addr, |
1577 | dev_priv->pcigart_offset); | 1569 | dev_priv->pcigart_offset); |
1578 | } else { | 1570 | } else { |
1579 | dev_priv->gart_info.gart_table_location = | 1571 | dev_priv->gart_info.gart_table_location = |
1580 | DRM_ATI_GART_MAIN; | 1572 | DRM_ATI_GART_MAIN; |
1581 | dev_priv->gart_info.addr = | 1573 | dev_priv->gart_info.addr = NULL; |
1582 | dev_priv->gart_info.bus_addr = 0; | 1574 | dev_priv->gart_info.bus_addr = 0; |
1583 | if (dev_priv->flags & CHIP_IS_PCIE) { | 1575 | if (dev_priv->flags & CHIP_IS_PCIE) { |
1584 | DRM_ERROR | 1576 | DRM_ERROR |
1585 | ("Cannot use PCI Express without GART in FB memory\n"); | 1577 | ("Cannot use PCI Express without GART in FB memory\n"); |
@@ -1590,7 +1582,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1590 | 1582 | ||
1591 | if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { | 1583 | if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { |
1592 | DRM_ERROR("failed to init PCI GART!\n"); | 1584 | DRM_ERROR("failed to init PCI GART!\n"); |
1593 | dev->dev_private = (void *)dev_priv; | ||
1594 | radeon_do_cleanup_cp(dev); | 1585 | radeon_do_cleanup_cp(dev); |
1595 | return DRM_ERR(ENOMEM); | 1586 | return DRM_ERR(ENOMEM); |
1596 | } | 1587 | } |
@@ -1604,8 +1595,6 @@ static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init) | |||
1604 | 1595 | ||
1605 | dev_priv->last_buf = 0; | 1596 | dev_priv->last_buf = 0; |
1606 | 1597 | ||
1607 | dev->dev_private = (void *)dev_priv; | ||
1608 | |||
1609 | radeon_do_engine_reset(dev); | 1598 | radeon_do_engine_reset(dev); |
1610 | 1599 | ||
1611 | return 0; | 1600 | return 0; |
@@ -1624,11 +1613,15 @@ static int radeon_do_cleanup_cp(drm_device_t * dev) | |||
1624 | drm_irq_uninstall(dev); | 1613 | drm_irq_uninstall(dev); |
1625 | 1614 | ||
1626 | #if __OS_HAS_AGP | 1615 | #if __OS_HAS_AGP |
1627 | if (!dev_priv->is_pci) { | 1616 | if (dev_priv->flags & CHIP_IS_AGP) { |
1628 | if (dev_priv->cp_ring != NULL) | 1617 | if (dev_priv->cp_ring != NULL) { |
1629 | drm_core_ioremapfree(dev_priv->cp_ring, dev); | 1618 | drm_core_ioremapfree(dev_priv->cp_ring, dev); |
1630 | if (dev_priv->ring_rptr != NULL) | 1619 | dev_priv->cp_ring = NULL; |
1620 | } | ||
1621 | if (dev_priv->ring_rptr != NULL) { | ||
1631 | drm_core_ioremapfree(dev_priv->ring_rptr, dev); | 1622 | drm_core_ioremapfree(dev_priv->ring_rptr, dev); |
1623 | dev_priv->ring_rptr = NULL; | ||
1624 | } | ||
1632 | if (dev->agp_buffer_map != NULL) { | 1625 | if (dev->agp_buffer_map != NULL) { |
1633 | drm_core_ioremapfree(dev->agp_buffer_map, dev); | 1626 | drm_core_ioremapfree(dev->agp_buffer_map, dev); |
1634 | dev->agp_buffer_map = NULL; | 1627 | dev->agp_buffer_map = NULL; |
@@ -1636,17 +1629,20 @@ static int radeon_do_cleanup_cp(drm_device_t * dev) | |||
1636 | } else | 1629 | } else |
1637 | #endif | 1630 | #endif |
1638 | { | 1631 | { |
1639 | if (dev_priv->gart_info.bus_addr) | 1632 | |
1633 | if (dev_priv->gart_info.bus_addr) { | ||
1634 | /* Turn off PCI GART */ | ||
1635 | radeon_set_pcigart(dev_priv, 0); | ||
1640 | if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) | 1636 | if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) |
1641 | DRM_ERROR("failed to cleanup PCI GART!\n"); | 1637 | DRM_ERROR("failed to cleanup PCI GART!\n"); |
1638 | } | ||
1642 | 1639 | ||
1643 | if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) { | 1640 | if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) |
1644 | drm_ioremapfree((void *)dev_priv->gart_info.addr, | 1641 | { |
1645 | RADEON_PCIGART_TABLE_SIZE, dev); | 1642 | drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev); |
1646 | dev_priv->gart_info.addr = 0; | 1643 | dev_priv->gart_info.addr = 0; |
1647 | } | 1644 | } |
1648 | } | 1645 | } |
1649 | |||
1650 | /* only clear to the start of flags */ | 1646 | /* only clear to the start of flags */ |
1651 | memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags)); | 1647 | memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags)); |
1652 | 1648 | ||
@@ -1672,7 +1668,7 @@ static int radeon_do_resume_cp(drm_device_t * dev) | |||
1672 | DRM_DEBUG("Starting radeon_do_resume_cp()\n"); | 1668 | DRM_DEBUG("Starting radeon_do_resume_cp()\n"); |
1673 | 1669 | ||
1674 | #if __OS_HAS_AGP | 1670 | #if __OS_HAS_AGP |
1675 | if (!dev_priv->is_pci) { | 1671 | if (dev_priv->flags & CHIP_IS_AGP) { |
1676 | /* Turn off PCI GART */ | 1672 | /* Turn off PCI GART */ |
1677 | radeon_set_pcigart(dev_priv, 0); | 1673 | radeon_set_pcigart(dev_priv, 0); |
1678 | } else | 1674 | } else |
@@ -2103,7 +2099,7 @@ int radeon_cp_buffers(DRM_IOCTL_ARGS) | |||
2103 | return ret; | 2099 | return ret; |
2104 | } | 2100 | } |
2105 | 2101 | ||
2106 | int radeon_driver_preinit(struct drm_device *dev, unsigned long flags) | 2102 | int radeon_driver_load(struct drm_device *dev, unsigned long flags) |
2107 | { | 2103 | { |
2108 | drm_radeon_private_t *dev_priv; | 2104 | drm_radeon_private_t *dev_priv; |
2109 | int ret = 0; | 2105 | int ret = 0; |
@@ -2136,11 +2132,14 @@ int radeon_driver_preinit(struct drm_device *dev, unsigned long flags) | |||
2136 | dev_priv->flags |= CHIP_IS_PCIE; | 2132 | dev_priv->flags |= CHIP_IS_PCIE; |
2137 | 2133 | ||
2138 | DRM_DEBUG("%s card detected\n", | 2134 | DRM_DEBUG("%s card detected\n", |
2139 | ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : "PCI")); | 2135 | ((dev_priv->flags & CHIP_IS_AGP) ? "AGP" : (((dev_priv->flags & CHIP_IS_PCIE) ? "PCIE" : "PCI")))); |
2140 | return ret; | 2136 | return ret; |
2141 | } | 2137 | } |
2142 | 2138 | ||
2143 | int radeon_presetup(struct drm_device *dev) | 2139 | /* Create mappings for registers and framebuffer so userland doesn't necessarily |
2140 | * have to find them. | ||
2141 | */ | ||
2142 | int radeon_driver_firstopen(struct drm_device *dev) | ||
2144 | { | 2143 | { |
2145 | int ret; | 2144 | int ret; |
2146 | drm_local_map_t *map; | 2145 | drm_local_map_t *map; |
@@ -2161,12 +2160,11 @@ int radeon_presetup(struct drm_device *dev) | |||
2161 | return 0; | 2160 | return 0; |
2162 | } | 2161 | } |
2163 | 2162 | ||
2164 | int radeon_driver_postcleanup(struct drm_device *dev) | 2163 | int radeon_driver_unload(struct drm_device *dev) |
2165 | { | 2164 | { |
2166 | drm_radeon_private_t *dev_priv = dev->dev_private; | 2165 | drm_radeon_private_t *dev_priv = dev->dev_private; |
2167 | 2166 | ||
2168 | DRM_DEBUG("\n"); | 2167 | DRM_DEBUG("\n"); |
2169 | |||
2170 | drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); | 2168 | drm_free(dev_priv, sizeof(*dev_priv), DRM_MEM_DRIVER); |
2171 | 2169 | ||
2172 | dev->dev_private = NULL; | 2170 | dev->dev_private = NULL; |
diff --git a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h index 1cd81a671a36..9c177a6b2a4c 100644 --- a/drivers/char/drm/radeon_drm.h +++ b/drivers/char/drm/radeon_drm.h | |||
@@ -624,6 +624,11 @@ typedef struct drm_radeon_indirect { | |||
624 | int discard; | 624 | int discard; |
625 | } drm_radeon_indirect_t; | 625 | } drm_radeon_indirect_t; |
626 | 626 | ||
627 | /* enum for card type parameters */ | ||
628 | #define RADEON_CARD_PCI 0 | ||
629 | #define RADEON_CARD_AGP 1 | ||
630 | #define RADEON_CARD_PCIE 2 | ||
631 | |||
627 | /* 1.3: An ioctl to get parameters that aren't available to the 3d | 632 | /* 1.3: An ioctl to get parameters that aren't available to the 3d |
628 | * client any other way. | 633 | * client any other way. |
629 | */ | 634 | */ |
@@ -640,6 +645,7 @@ typedef struct drm_radeon_indirect { | |||
640 | #define RADEON_PARAM_SAREA_HANDLE 9 | 645 | #define RADEON_PARAM_SAREA_HANDLE 9 |
641 | #define RADEON_PARAM_GART_TEX_HANDLE 10 | 646 | #define RADEON_PARAM_GART_TEX_HANDLE 10 |
642 | #define RADEON_PARAM_SCRATCH_OFFSET 11 | 647 | #define RADEON_PARAM_SCRATCH_OFFSET 11 |
648 | #define RADEON_PARAM_CARD_TYPE 12 | ||
643 | 649 | ||
644 | typedef struct drm_radeon_getparam { | 650 | typedef struct drm_radeon_getparam { |
645 | int param; | 651 | int param; |
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c index ee49670d8162..b04ed1b562b9 100644 --- a/drivers/char/drm/radeon_drv.c +++ b/drivers/char/drm/radeon_drv.c | |||
@@ -42,29 +42,15 @@ int radeon_no_wb; | |||
42 | MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers\n"); | 42 | MODULE_PARM_DESC(no_wb, "Disable AGP writeback for scratch registers\n"); |
43 | module_param_named(no_wb, radeon_no_wb, int, 0444); | 43 | module_param_named(no_wb, radeon_no_wb, int, 0444); |
44 | 44 | ||
45 | static int postinit(struct drm_device *dev, unsigned long flags) | 45 | static int dri_library_name(struct drm_device *dev, char *buf) |
46 | { | 46 | { |
47 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n", | 47 | drm_radeon_private_t *dev_priv = dev->dev_private; |
48 | DRIVER_NAME, | 48 | int family = dev_priv->flags & CHIP_FAMILY_MASK; |
49 | DRIVER_MAJOR, | ||
50 | DRIVER_MINOR, | ||
51 | DRIVER_PATCHLEVEL, | ||
52 | DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev) | ||
53 | ); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int version(drm_version_t * version) | ||
58 | { | ||
59 | int len; | ||
60 | 49 | ||
61 | version->version_major = DRIVER_MAJOR; | 50 | return snprintf(buf, PAGE_SIZE, "%s\n", |
62 | version->version_minor = DRIVER_MINOR; | 51 | (family < CHIP_R200) ? "radeon" : |
63 | version->version_patchlevel = DRIVER_PATCHLEVEL; | 52 | ((family < CHIP_R300) ? "r200" : |
64 | DRM_COPY(version->name, DRIVER_NAME); | 53 | "r300")); |
65 | DRM_COPY(version->date, DRIVER_DATE); | ||
66 | DRM_COPY(version->desc, DRIVER_DESC); | ||
67 | return 0; | ||
68 | } | 54 | } |
69 | 55 | ||
70 | static struct pci_device_id pciidlist[] = { | 56 | static struct pci_device_id pciidlist[] = { |
@@ -77,23 +63,22 @@ static struct drm_driver driver = { | |||
77 | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | | 63 | DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED | |
78 | DRIVER_IRQ_VBL, | 64 | DRIVER_IRQ_VBL, |
79 | .dev_priv_size = sizeof(drm_radeon_buf_priv_t), | 65 | .dev_priv_size = sizeof(drm_radeon_buf_priv_t), |
80 | .preinit = radeon_driver_preinit, | 66 | .load = radeon_driver_load, |
81 | .presetup = radeon_presetup, | 67 | .firstopen = radeon_driver_firstopen, |
82 | .postcleanup = radeon_driver_postcleanup, | 68 | .open = radeon_driver_open, |
83 | .prerelease = radeon_driver_prerelease, | 69 | .preclose = radeon_driver_preclose, |
84 | .pretakedown = radeon_driver_pretakedown, | 70 | .postclose = radeon_driver_postclose, |
85 | .open_helper = radeon_driver_open_helper, | 71 | .lastclose = radeon_driver_lastclose, |
72 | .unload = radeon_driver_unload, | ||
86 | .vblank_wait = radeon_driver_vblank_wait, | 73 | .vblank_wait = radeon_driver_vblank_wait, |
74 | .dri_library_name = dri_library_name, | ||
87 | .irq_preinstall = radeon_driver_irq_preinstall, | 75 | .irq_preinstall = radeon_driver_irq_preinstall, |
88 | .irq_postinstall = radeon_driver_irq_postinstall, | 76 | .irq_postinstall = radeon_driver_irq_postinstall, |
89 | .irq_uninstall = radeon_driver_irq_uninstall, | 77 | .irq_uninstall = radeon_driver_irq_uninstall, |
90 | .irq_handler = radeon_driver_irq_handler, | 78 | .irq_handler = radeon_driver_irq_handler, |
91 | .free_filp_priv = radeon_driver_free_filp_priv, | ||
92 | .reclaim_buffers = drm_core_reclaim_buffers, | 79 | .reclaim_buffers = drm_core_reclaim_buffers, |
93 | .get_map_ofs = drm_core_get_map_ofs, | 80 | .get_map_ofs = drm_core_get_map_ofs, |
94 | .get_reg_ofs = drm_core_get_reg_ofs, | 81 | .get_reg_ofs = drm_core_get_reg_ofs, |
95 | .postinit = postinit, | ||
96 | .version = version, | ||
97 | .ioctls = radeon_ioctls, | 82 | .ioctls = radeon_ioctls, |
98 | .dma_ioctl = radeon_cp_buffers, | 83 | .dma_ioctl = radeon_cp_buffers, |
99 | .fops = { | 84 | .fops = { |
@@ -107,12 +92,19 @@ static struct drm_driver driver = { | |||
107 | #ifdef CONFIG_COMPAT | 92 | #ifdef CONFIG_COMPAT |
108 | .compat_ioctl = radeon_compat_ioctl, | 93 | .compat_ioctl = radeon_compat_ioctl, |
109 | #endif | 94 | #endif |
110 | } | 95 | }, |
111 | , | 96 | |
112 | .pci_driver = { | 97 | .pci_driver = { |
113 | .name = DRIVER_NAME, | 98 | .name = DRIVER_NAME, |
114 | .id_table = pciidlist, | 99 | .id_table = pciidlist, |
115 | } | 100 | }, |
101 | |||
102 | .name = DRIVER_NAME, | ||
103 | .desc = DRIVER_DESC, | ||
104 | .date = DRIVER_DATE, | ||
105 | .major = DRIVER_MAJOR, | ||
106 | .minor = DRIVER_MINOR, | ||
107 | .patchlevel = DRIVER_PATCHLEVEL, | ||
116 | }; | 108 | }; |
117 | 109 | ||
118 | static int __init radeon_init(void) | 110 | static int __init radeon_init(void) |
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index d92ccee3e54c..498b19b1d641 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h | |||
@@ -38,7 +38,7 @@ | |||
38 | 38 | ||
39 | #define DRIVER_NAME "radeon" | 39 | #define DRIVER_NAME "radeon" |
40 | #define DRIVER_DESC "ATI Radeon" | 40 | #define DRIVER_DESC "ATI Radeon" |
41 | #define DRIVER_DATE "20050911" | 41 | #define DRIVER_DATE "20051229" |
42 | 42 | ||
43 | /* Interface history: | 43 | /* Interface history: |
44 | * | 44 | * |
@@ -73,7 +73,7 @@ | |||
73 | * 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color | 73 | * 1.11- Add packet R200_EMIT_RB3D_BLENDCOLOR to support GL_EXT_blend_color |
74 | * and GL_EXT_blend_[func|equation]_separate on r200 | 74 | * and GL_EXT_blend_[func|equation]_separate on r200 |
75 | * 1.12- Add R300 CP microcode support - this just loads the CP on r300 | 75 | * 1.12- Add R300 CP microcode support - this just loads the CP on r300 |
76 | * (No 3D support yet - just microcode loading) | 76 | * (No 3D support yet - just microcode loading). |
77 | * 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters | 77 | * 1.13- Add packet R200_EMIT_TCL_POINT_SPRITE_CNTL for ARB_point_parameters |
78 | * - Add hyperz support, add hyperz flags to clear ioctl. | 78 | * - Add hyperz support, add hyperz flags to clear ioctl. |
79 | * 1.14- Add support for color tiling | 79 | * 1.14- Add support for color tiling |
@@ -88,14 +88,13 @@ | |||
88 | * R200_EMIT_PP_TXFILTER_0-5, 2 more regs) and R200_EMIT_ATF_TFACTOR | 88 | * R200_EMIT_PP_TXFILTER_0-5, 2 more regs) and R200_EMIT_ATF_TFACTOR |
89 | * (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6) | 89 | * (replaces R200_EMIT_TFACTOR_0 (8 consts instead of 6) |
90 | * 1.19- Add support for gart table in FB memory and PCIE r300 | 90 | * 1.19- Add support for gart table in FB memory and PCIE r300 |
91 | * 1.20- Add support for r300 texrect | ||
92 | * 1.21- Add support for card type getparam | ||
91 | */ | 93 | */ |
92 | #define DRIVER_MAJOR 1 | 94 | #define DRIVER_MAJOR 1 |
93 | #define DRIVER_MINOR 19 | 95 | #define DRIVER_MINOR 21 |
94 | #define DRIVER_PATCHLEVEL 0 | 96 | #define DRIVER_PATCHLEVEL 0 |
95 | 97 | ||
96 | #define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 ) | ||
97 | #define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) ) | ||
98 | |||
99 | /* | 98 | /* |
100 | * Radeon chip families | 99 | * Radeon chip families |
101 | */ | 100 | */ |
@@ -103,8 +102,8 @@ enum radeon_family { | |||
103 | CHIP_R100, | 102 | CHIP_R100, |
104 | CHIP_RS100, | 103 | CHIP_RS100, |
105 | CHIP_RV100, | 104 | CHIP_RV100, |
106 | CHIP_R200, | ||
107 | CHIP_RV200, | 105 | CHIP_RV200, |
106 | CHIP_R200, | ||
108 | CHIP_RS200, | 107 | CHIP_RS200, |
109 | CHIP_R250, | 108 | CHIP_R250, |
110 | CHIP_RS250, | 109 | CHIP_RS250, |
@@ -138,6 +137,9 @@ enum radeon_chip_flags { | |||
138 | CHIP_IS_PCIE = 0x00200000UL, | 137 | CHIP_IS_PCIE = 0x00200000UL, |
139 | }; | 138 | }; |
140 | 139 | ||
140 | #define GET_RING_HEAD(dev_priv) DRM_READ32( (dev_priv)->ring_rptr, 0 ) | ||
141 | #define SET_RING_HEAD(dev_priv,val) DRM_WRITE32( (dev_priv)->ring_rptr, 0, (val) ) | ||
142 | |||
141 | typedef struct drm_radeon_freelist { | 143 | typedef struct drm_radeon_freelist { |
142 | unsigned int age; | 144 | unsigned int age; |
143 | drm_buf_t *buf; | 145 | drm_buf_t *buf; |
@@ -245,8 +247,6 @@ typedef struct drm_radeon_private { | |||
245 | 247 | ||
246 | drm_radeon_depth_clear_t depth_clear; | 248 | drm_radeon_depth_clear_t depth_clear; |
247 | 249 | ||
248 | unsigned long fb_offset; | ||
249 | unsigned long mmio_offset; | ||
250 | unsigned long ring_offset; | 250 | unsigned long ring_offset; |
251 | unsigned long ring_rptr_offset; | 251 | unsigned long ring_rptr_offset; |
252 | unsigned long buffers_offset; | 252 | unsigned long buffers_offset; |
@@ -273,7 +273,6 @@ typedef struct drm_radeon_private { | |||
273 | 273 | ||
274 | /* starting from here on, data is preserved accross an open */ | 274 | /* starting from here on, data is preserved accross an open */ |
275 | uint32_t flags; /* see radeon_chip_flags */ | 275 | uint32_t flags; /* see radeon_chip_flags */ |
276 | int is_pci; | ||
277 | } drm_radeon_private_t; | 276 | } drm_radeon_private_t; |
278 | 277 | ||
279 | typedef struct drm_radeon_buf_priv { | 278 | typedef struct drm_radeon_buf_priv { |
@@ -330,17 +329,14 @@ extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS); | |||
330 | extern void radeon_driver_irq_preinstall(drm_device_t * dev); | 329 | extern void radeon_driver_irq_preinstall(drm_device_t * dev); |
331 | extern void radeon_driver_irq_postinstall(drm_device_t * dev); | 330 | extern void radeon_driver_irq_postinstall(drm_device_t * dev); |
332 | extern void radeon_driver_irq_uninstall(drm_device_t * dev); | 331 | extern void radeon_driver_irq_uninstall(drm_device_t * dev); |
333 | extern void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp); | ||
334 | extern void radeon_driver_pretakedown(drm_device_t * dev); | ||
335 | extern int radeon_driver_open_helper(drm_device_t * dev, | ||
336 | drm_file_t * filp_priv); | ||
337 | extern void radeon_driver_free_filp_priv(drm_device_t * dev, | ||
338 | drm_file_t * filp_priv); | ||
339 | |||
340 | extern int radeon_preinit(struct drm_device *dev, unsigned long flags); | ||
341 | extern int radeon_postinit(struct drm_device *dev, unsigned long flags); | ||
342 | extern int radeon_postcleanup(struct drm_device *dev); | ||
343 | 332 | ||
333 | extern int radeon_driver_load(struct drm_device *dev, unsigned long flags); | ||
334 | extern int radeon_driver_unload(struct drm_device *dev); | ||
335 | extern int radeon_driver_firstopen(struct drm_device *dev); | ||
336 | extern void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp); | ||
337 | extern void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp); | ||
338 | extern void radeon_driver_lastclose(drm_device_t * dev); | ||
339 | extern int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv); | ||
344 | extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd, | 340 | extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd, |
345 | unsigned long arg); | 341 | unsigned long arg); |
346 | 342 | ||
@@ -364,6 +360,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, | |||
364 | */ | 360 | */ |
365 | 361 | ||
366 | #define RADEON_AGP_COMMAND 0x0f60 | 362 | #define RADEON_AGP_COMMAND 0x0f60 |
363 | #define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config */ | ||
364 | # define RADEON_AGP_ENABLE (1<<8) | ||
367 | #define RADEON_AUX_SCISSOR_CNTL 0x26f0 | 365 | #define RADEON_AUX_SCISSOR_CNTL 0x26f0 |
368 | # define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24) | 366 | # define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24) |
369 | # define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25) | 367 | # define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25) |
@@ -651,6 +649,8 @@ extern int r300_do_cp_cmdbuf(drm_device_t * dev, DRMFILE filp, | |||
651 | 649 | ||
652 | #define RADEON_WAIT_UNTIL 0x1720 | 650 | #define RADEON_WAIT_UNTIL 0x1720 |
653 | # define RADEON_WAIT_CRTC_PFLIP (1 << 0) | 651 | # define RADEON_WAIT_CRTC_PFLIP (1 << 0) |
652 | # define RADEON_WAIT_2D_IDLE (1 << 14) | ||
653 | # define RADEON_WAIT_3D_IDLE (1 << 15) | ||
654 | # define RADEON_WAIT_2D_IDLECLEAN (1 << 16) | 654 | # define RADEON_WAIT_2D_IDLECLEAN (1 << 16) |
655 | # define RADEON_WAIT_3D_IDLECLEAN (1 << 17) | 655 | # define RADEON_WAIT_3D_IDLECLEAN (1 << 17) |
656 | # define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) | 656 | # define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) |
@@ -1105,7 +1105,6 @@ do { \ | |||
1105 | write = 0; \ | 1105 | write = 0; \ |
1106 | _tab += _i; \ | 1106 | _tab += _i; \ |
1107 | } \ | 1107 | } \ |
1108 | \ | ||
1109 | while (_size > 0) { \ | 1108 | while (_size > 0) { \ |
1110 | *(ring + write) = *_tab++; \ | 1109 | *(ring + write) = *_tab++; \ |
1111 | write++; \ | 1110 | write++; \ |
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 231ac1438c69..7bc27516d425 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* radeon_state.c -- State support for Radeon -*- linux-c -*- | 1 | /* radeon_state.c -- State support for Radeon -*- linux-c -*- */ |
2 | * | 2 | /* |
3 | * Copyright 2000 VA Linux Systems, Inc., Fremont, California. | 3 | * Copyright 2000 VA Linux Systems, Inc., Fremont, California. |
4 | * All Rights Reserved. | 4 | * All Rights Reserved. |
5 | * | 5 | * |
@@ -72,10 +72,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * | |||
72 | 72 | ||
73 | case RADEON_EMIT_PP_MISC: | 73 | case RADEON_EMIT_PP_MISC: |
74 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, | 74 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, |
75 | &data[(RADEON_RB3D_DEPTHOFFSET | 75 | &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) { |
76 | - | ||
77 | RADEON_PP_MISC) / | ||
78 | 4])) { | ||
79 | DRM_ERROR("Invalid depth buffer offset\n"); | 76 | DRM_ERROR("Invalid depth buffer offset\n"); |
80 | return DRM_ERR(EINVAL); | 77 | return DRM_ERR(EINVAL); |
81 | } | 78 | } |
@@ -83,10 +80,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * | |||
83 | 80 | ||
84 | case RADEON_EMIT_PP_CNTL: | 81 | case RADEON_EMIT_PP_CNTL: |
85 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, | 82 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, |
86 | &data[(RADEON_RB3D_COLOROFFSET | 83 | &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) { |
87 | - | ||
88 | RADEON_PP_CNTL) / | ||
89 | 4])) { | ||
90 | DRM_ERROR("Invalid colour buffer offset\n"); | 84 | DRM_ERROR("Invalid colour buffer offset\n"); |
91 | return DRM_ERR(EINVAL); | 85 | return DRM_ERR(EINVAL); |
92 | } | 86 | } |
@@ -109,10 +103,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * | |||
109 | case RADEON_EMIT_PP_TXFILTER_1: | 103 | case RADEON_EMIT_PP_TXFILTER_1: |
110 | case RADEON_EMIT_PP_TXFILTER_2: | 104 | case RADEON_EMIT_PP_TXFILTER_2: |
111 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, | 105 | if (radeon_check_and_fixup_offset(dev_priv, filp_priv, |
112 | &data[(RADEON_PP_TXOFFSET_0 | 106 | &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) { |
113 | - | ||
114 | RADEON_PP_TXFILTER_0) / | ||
115 | 4])) { | ||
116 | DRM_ERROR("Invalid R100 texture offset\n"); | 107 | DRM_ERROR("Invalid R100 texture offset\n"); |
117 | return DRM_ERR(EINVAL); | 108 | return DRM_ERR(EINVAL); |
118 | } | 109 | } |
@@ -126,8 +117,9 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * | |||
126 | case R200_EMIT_PP_CUBIC_OFFSETS_5:{ | 117 | case R200_EMIT_PP_CUBIC_OFFSETS_5:{ |
127 | int i; | 118 | int i; |
128 | for (i = 0; i < 5; i++) { | 119 | for (i = 0; i < 5; i++) { |
129 | if (radeon_check_and_fixup_offset | 120 | if (radeon_check_and_fixup_offset(dev_priv, |
130 | (dev_priv, filp_priv, &data[i])) { | 121 | filp_priv, |
122 | &data[i])) { | ||
131 | DRM_ERROR | 123 | DRM_ERROR |
132 | ("Invalid R200 cubic texture offset\n"); | 124 | ("Invalid R200 cubic texture offset\n"); |
133 | return DRM_ERR(EINVAL); | 125 | return DRM_ERR(EINVAL); |
@@ -239,8 +231,9 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * | |||
239 | 231 | ||
240 | static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | 232 | static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * |
241 | dev_priv, | 233 | dev_priv, |
242 | drm_file_t * filp_priv, | 234 | drm_file_t *filp_priv, |
243 | drm_radeon_kcmd_buffer_t *cmdbuf, | 235 | drm_radeon_kcmd_buffer_t * |
236 | cmdbuf, | ||
244 | unsigned int *cmdsz) | 237 | unsigned int *cmdsz) |
245 | { | 238 | { |
246 | u32 *cmd = (u32 *) cmdbuf->buf; | 239 | u32 *cmd = (u32 *) cmdbuf->buf; |
@@ -555,7 +548,8 @@ static struct { | |||
555 | {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"}, | 548 | {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"}, |
556 | {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"}, | 549 | {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"}, |
557 | {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"}, | 550 | {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"}, |
558 | {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"}, | 551 | {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, |
552 | "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"}, | ||
559 | {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"}, | 553 | {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"}, |
560 | {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"}, | 554 | {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"}, |
561 | {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"}, | 555 | {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"}, |
@@ -569,7 +563,7 @@ static struct { | |||
569 | {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, | 563 | {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, |
570 | "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"}, | 564 | "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"}, |
571 | {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */ | 565 | {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */ |
572 | {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */ | 566 | {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */ |
573 | {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"}, | 567 | {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"}, |
574 | {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"}, | 568 | {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"}, |
575 | {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"}, | 569 | {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"}, |
@@ -592,7 +586,7 @@ static struct { | |||
592 | {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"}, | 586 | {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"}, |
593 | {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"}, | 587 | {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"}, |
594 | {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"}, | 588 | {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"}, |
595 | {R200_PP_AFS_0, 32, "R200_PP_AFS_0"}, /* 85 */ | 589 | {R200_PP_AFS_0, 32, "R200_PP_AFS_0"}, /* 85 */ |
596 | {R200_PP_AFS_1, 32, "R200_PP_AFS_1"}, | 590 | {R200_PP_AFS_1, 32, "R200_PP_AFS_1"}, |
597 | {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"}, | 591 | {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"}, |
598 | {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"}, | 592 | {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"}, |
@@ -985,8 +979,8 @@ static void radeon_cp_dispatch_clear(drm_device_t * dev, | |||
985 | * rendering a quad into just those buffers. Thus, we have to | 979 | * rendering a quad into just those buffers. Thus, we have to |
986 | * make sure the 3D engine is configured correctly. | 980 | * make sure the 3D engine is configured correctly. |
987 | */ | 981 | */ |
988 | if ((dev_priv->microcode_version == UCODE_R200) && | 982 | else if ((dev_priv->microcode_version == UCODE_R200) && |
989 | (flags & (RADEON_DEPTH | RADEON_STENCIL))) { | 983 | (flags & (RADEON_DEPTH | RADEON_STENCIL))) { |
990 | 984 | ||
991 | int tempPP_CNTL; | 985 | int tempPP_CNTL; |
992 | int tempRE_CNTL; | 986 | int tempRE_CNTL; |
@@ -1637,6 +1631,14 @@ static int radeon_cp_dispatch_texture(DRMFILE filp, | |||
1637 | (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); | 1631 | (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); |
1638 | dwords = size / 4; | 1632 | dwords = size / 4; |
1639 | 1633 | ||
1634 | #define RADEON_COPY_MT(_buf, _data, _width) \ | ||
1635 | do { \ | ||
1636 | if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\ | ||
1637 | DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \ | ||
1638 | return DRM_ERR(EFAULT); \ | ||
1639 | } \ | ||
1640 | } while(0) | ||
1641 | |||
1640 | if (microtile) { | 1642 | if (microtile) { |
1641 | /* texture micro tiling in use, minimum texture width is thus 16 bytes. | 1643 | /* texture micro tiling in use, minimum texture width is thus 16 bytes. |
1642 | however, we cannot use blitter directly for texture width < 64 bytes, | 1644 | however, we cannot use blitter directly for texture width < 64 bytes, |
@@ -1648,46 +1650,19 @@ static int radeon_cp_dispatch_texture(DRMFILE filp, | |||
1648 | from user space. */ | 1650 | from user space. */ |
1649 | if (tex->height == 1) { | 1651 | if (tex->height == 1) { |
1650 | if (tex_width >= 64 || tex_width <= 16) { | 1652 | if (tex_width >= 64 || tex_width <= 16) { |
1651 | if (DRM_COPY_FROM_USER(buffer, data, | 1653 | RADEON_COPY_MT(buffer, data, |
1652 | tex_width * | 1654 | (int)(tex_width * sizeof(u32))); |
1653 | sizeof(u32))) { | ||
1654 | DRM_ERROR | ||
1655 | ("EFAULT on pad, %d bytes\n", | ||
1656 | tex_width); | ||
1657 | return DRM_ERR(EFAULT); | ||
1658 | } | ||
1659 | } else if (tex_width == 32) { | 1655 | } else if (tex_width == 32) { |
1660 | if (DRM_COPY_FROM_USER | 1656 | RADEON_COPY_MT(buffer, data, 16); |
1661 | (buffer, data, 16)) { | 1657 | RADEON_COPY_MT(buffer + 8, |
1662 | DRM_ERROR | 1658 | data + 16, 16); |
1663 | ("EFAULT on pad, %d bytes\n", | ||
1664 | tex_width); | ||
1665 | return DRM_ERR(EFAULT); | ||
1666 | } | ||
1667 | if (DRM_COPY_FROM_USER | ||
1668 | (buffer + 8, data + 16, 16)) { | ||
1669 | DRM_ERROR | ||
1670 | ("EFAULT on pad, %d bytes\n", | ||
1671 | tex_width); | ||
1672 | return DRM_ERR(EFAULT); | ||
1673 | } | ||
1674 | } | 1659 | } |
1675 | } else if (tex_width >= 64 || tex_width == 16) { | 1660 | } else if (tex_width >= 64 || tex_width == 16) { |
1676 | if (DRM_COPY_FROM_USER(buffer, data, | 1661 | RADEON_COPY_MT(buffer, data, |
1677 | dwords * sizeof(u32))) { | 1662 | (int)(dwords * sizeof(u32))); |
1678 | DRM_ERROR("EFAULT on data, %d dwords\n", | ||
1679 | dwords); | ||
1680 | return DRM_ERR(EFAULT); | ||
1681 | } | ||
1682 | } else if (tex_width < 16) { | 1663 | } else if (tex_width < 16) { |
1683 | for (i = 0; i < tex->height; i++) { | 1664 | for (i = 0; i < tex->height; i++) { |
1684 | if (DRM_COPY_FROM_USER | 1665 | RADEON_COPY_MT(buffer, data, tex_width); |
1685 | (buffer, data, tex_width)) { | ||
1686 | DRM_ERROR | ||
1687 | ("EFAULT on pad, %d bytes\n", | ||
1688 | tex_width); | ||
1689 | return DRM_ERR(EFAULT); | ||
1690 | } | ||
1691 | buffer += 4; | 1666 | buffer += 4; |
1692 | data += tex_width; | 1667 | data += tex_width; |
1693 | } | 1668 | } |
@@ -1695,37 +1670,13 @@ static int radeon_cp_dispatch_texture(DRMFILE filp, | |||
1695 | /* TODO: make sure this works when not fitting in one buffer | 1670 | /* TODO: make sure this works when not fitting in one buffer |
1696 | (i.e. 32bytes x 2048...) */ | 1671 | (i.e. 32bytes x 2048...) */ |
1697 | for (i = 0; i < tex->height; i += 2) { | 1672 | for (i = 0; i < tex->height; i += 2) { |
1698 | if (DRM_COPY_FROM_USER | 1673 | RADEON_COPY_MT(buffer, data, 16); |
1699 | (buffer, data, 16)) { | ||
1700 | DRM_ERROR | ||
1701 | ("EFAULT on pad, %d bytes\n", | ||
1702 | tex_width); | ||
1703 | return DRM_ERR(EFAULT); | ||
1704 | } | ||
1705 | data += 16; | 1674 | data += 16; |
1706 | if (DRM_COPY_FROM_USER | 1675 | RADEON_COPY_MT(buffer + 8, data, 16); |
1707 | (buffer + 8, data, 16)) { | ||
1708 | DRM_ERROR | ||
1709 | ("EFAULT on pad, %d bytes\n", | ||
1710 | tex_width); | ||
1711 | return DRM_ERR(EFAULT); | ||
1712 | } | ||
1713 | data += 16; | 1676 | data += 16; |
1714 | if (DRM_COPY_FROM_USER | 1677 | RADEON_COPY_MT(buffer + 4, data, 16); |
1715 | (buffer + 4, data, 16)) { | ||
1716 | DRM_ERROR | ||
1717 | ("EFAULT on pad, %d bytes\n", | ||
1718 | tex_width); | ||
1719 | return DRM_ERR(EFAULT); | ||
1720 | } | ||
1721 | data += 16; | 1678 | data += 16; |
1722 | if (DRM_COPY_FROM_USER | 1679 | RADEON_COPY_MT(buffer + 12, data, 16); |
1723 | (buffer + 12, data, 16)) { | ||
1724 | DRM_ERROR | ||
1725 | ("EFAULT on pad, %d bytes\n", | ||
1726 | tex_width); | ||
1727 | return DRM_ERR(EFAULT); | ||
1728 | } | ||
1729 | data += 16; | 1680 | data += 16; |
1730 | buffer += 16; | 1681 | buffer += 16; |
1731 | } | 1682 | } |
@@ -1735,31 +1686,22 @@ static int radeon_cp_dispatch_texture(DRMFILE filp, | |||
1735 | /* Texture image width is larger than the minimum, so we | 1686 | /* Texture image width is larger than the minimum, so we |
1736 | * can upload it directly. | 1687 | * can upload it directly. |
1737 | */ | 1688 | */ |
1738 | if (DRM_COPY_FROM_USER(buffer, data, | 1689 | RADEON_COPY_MT(buffer, data, |
1739 | dwords * sizeof(u32))) { | 1690 | (int)(dwords * sizeof(u32))); |
1740 | DRM_ERROR("EFAULT on data, %d dwords\n", | ||
1741 | dwords); | ||
1742 | return DRM_ERR(EFAULT); | ||
1743 | } | ||
1744 | } else { | 1691 | } else { |
1745 | /* Texture image width is less than the minimum, so we | 1692 | /* Texture image width is less than the minimum, so we |
1746 | * need to pad out each image scanline to the minimum | 1693 | * need to pad out each image scanline to the minimum |
1747 | * width. | 1694 | * width. |
1748 | */ | 1695 | */ |
1749 | for (i = 0; i < tex->height; i++) { | 1696 | for (i = 0; i < tex->height; i++) { |
1750 | if (DRM_COPY_FROM_USER | 1697 | RADEON_COPY_MT(buffer, data, tex_width); |
1751 | (buffer, data, tex_width)) { | ||
1752 | DRM_ERROR | ||
1753 | ("EFAULT on pad, %d bytes\n", | ||
1754 | tex_width); | ||
1755 | return DRM_ERR(EFAULT); | ||
1756 | } | ||
1757 | buffer += 8; | 1698 | buffer += 8; |
1758 | data += tex_width; | 1699 | data += tex_width; |
1759 | } | 1700 | } |
1760 | } | 1701 | } |
1761 | } | 1702 | } |
1762 | 1703 | ||
1704 | #undef RADEON_COPY_MT | ||
1763 | buf->filp = filp; | 1705 | buf->filp = filp; |
1764 | buf->used = size; | 1706 | buf->used = size; |
1765 | offset = dev_priv->gart_buffers_offset + buf->offset; | 1707 | offset = dev_priv->gart_buffers_offset + buf->offset; |
@@ -1821,7 +1763,7 @@ static void radeon_cp_dispatch_stipple(drm_device_t * dev, u32 * stipple) | |||
1821 | } | 1763 | } |
1822 | 1764 | ||
1823 | static void radeon_apply_surface_regs(int surf_index, | 1765 | static void radeon_apply_surface_regs(int surf_index, |
1824 | drm_radeon_private_t * dev_priv) | 1766 | drm_radeon_private_t *dev_priv) |
1825 | { | 1767 | { |
1826 | if (!dev_priv->mmio) | 1768 | if (!dev_priv->mmio) |
1827 | return; | 1769 | return; |
@@ -1847,8 +1789,8 @@ static void radeon_apply_surface_regs(int surf_index, | |||
1847 | * freed, we suddenly need two surfaces to store A and C, which might | 1789 | * freed, we suddenly need two surfaces to store A and C, which might |
1848 | * not always be available. | 1790 | * not always be available. |
1849 | */ | 1791 | */ |
1850 | static int alloc_surface(drm_radeon_surface_alloc_t * new, | 1792 | static int alloc_surface(drm_radeon_surface_alloc_t *new, |
1851 | drm_radeon_private_t * dev_priv, DRMFILE filp) | 1793 | drm_radeon_private_t *dev_priv, DRMFILE filp) |
1852 | { | 1794 | { |
1853 | struct radeon_virt_surface *s; | 1795 | struct radeon_virt_surface *s; |
1854 | int i; | 1796 | int i; |
@@ -2158,6 +2100,11 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS) | |||
2158 | 2100 | ||
2159 | LOCK_TEST_WITH_RETURN(dev, filp); | 2101 | LOCK_TEST_WITH_RETURN(dev, filp); |
2160 | 2102 | ||
2103 | if (!dev_priv) { | ||
2104 | DRM_ERROR("%s called with no initialization\n", __FUNCTION__); | ||
2105 | return DRM_ERR(EINVAL); | ||
2106 | } | ||
2107 | |||
2161 | DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); | 2108 | DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); |
2162 | 2109 | ||
2163 | DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data, | 2110 | DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data, |
@@ -2596,9 +2543,9 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv, | |||
2596 | return 0; | 2543 | return 0; |
2597 | } | 2544 | } |
2598 | 2545 | ||
2599 | static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv, | 2546 | static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv, |
2600 | drm_radeon_cmd_header_t header, | 2547 | drm_radeon_cmd_header_t header, |
2601 | drm_radeon_kcmd_buffer_t * cmdbuf) | 2548 | drm_radeon_kcmd_buffer_t *cmdbuf) |
2602 | { | 2549 | { |
2603 | int sz = header.scalars.count; | 2550 | int sz = header.scalars.count; |
2604 | int start = header.scalars.offset; | 2551 | int start = header.scalars.offset; |
@@ -2618,9 +2565,9 @@ static __inline__ int radeon_emit_scalars(drm_radeon_private_t * dev_priv, | |||
2618 | 2565 | ||
2619 | /* God this is ugly | 2566 | /* God this is ugly |
2620 | */ | 2567 | */ |
2621 | static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv, | 2568 | static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv, |
2622 | drm_radeon_cmd_header_t header, | 2569 | drm_radeon_cmd_header_t header, |
2623 | drm_radeon_kcmd_buffer_t * cmdbuf) | 2570 | drm_radeon_kcmd_buffer_t *cmdbuf) |
2624 | { | 2571 | { |
2625 | int sz = header.scalars.count; | 2572 | int sz = header.scalars.count; |
2626 | int start = ((unsigned int)header.scalars.offset) + 0x100; | 2573 | int start = ((unsigned int)header.scalars.offset) + 0x100; |
@@ -2638,9 +2585,9 @@ static __inline__ int radeon_emit_scalars2(drm_radeon_private_t * dev_priv, | |||
2638 | return 0; | 2585 | return 0; |
2639 | } | 2586 | } |
2640 | 2587 | ||
2641 | static __inline__ int radeon_emit_vectors(drm_radeon_private_t * dev_priv, | 2588 | static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv, |
2642 | drm_radeon_cmd_header_t header, | 2589 | drm_radeon_cmd_header_t header, |
2643 | drm_radeon_kcmd_buffer_t * cmdbuf) | 2590 | drm_radeon_kcmd_buffer_t *cmdbuf) |
2644 | { | 2591 | { |
2645 | int sz = header.vectors.count; | 2592 | int sz = header.vectors.count; |
2646 | int start = header.vectors.offset; | 2593 | int start = header.vectors.offset; |
@@ -2685,8 +2632,8 @@ static int radeon_emit_packet3(drm_device_t * dev, | |||
2685 | return 0; | 2632 | return 0; |
2686 | } | 2633 | } |
2687 | 2634 | ||
2688 | static int radeon_emit_packet3_cliprect(drm_device_t * dev, | 2635 | static int radeon_emit_packet3_cliprect(drm_device_t *dev, |
2689 | drm_file_t * filp_priv, | 2636 | drm_file_t *filp_priv, |
2690 | drm_radeon_kcmd_buffer_t *cmdbuf, | 2637 | drm_radeon_kcmd_buffer_t *cmdbuf, |
2691 | int orig_nbox) | 2638 | int orig_nbox) |
2692 | { | 2639 | { |
@@ -2818,7 +2765,8 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) | |||
2818 | kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER); | 2765 | kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER); |
2819 | if (kbuf == NULL) | 2766 | if (kbuf == NULL) |
2820 | return DRM_ERR(ENOMEM); | 2767 | return DRM_ERR(ENOMEM); |
2821 | if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf, cmdbuf.bufsz)) { | 2768 | if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf, |
2769 | cmdbuf.bufsz)) { | ||
2822 | drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); | 2770 | drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); |
2823 | return DRM_ERR(EFAULT); | 2771 | return DRM_ERR(EFAULT); |
2824 | } | 2772 | } |
@@ -2981,7 +2929,7 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS) | |||
2981 | value = dev_priv->gart_vm_start; | 2929 | value = dev_priv->gart_vm_start; |
2982 | break; | 2930 | break; |
2983 | case RADEON_PARAM_REGISTER_HANDLE: | 2931 | case RADEON_PARAM_REGISTER_HANDLE: |
2984 | value = dev_priv->mmio_offset; | 2932 | value = dev_priv->mmio->offset; |
2985 | break; | 2933 | break; |
2986 | case RADEON_PARAM_STATUS_HANDLE: | 2934 | case RADEON_PARAM_STATUS_HANDLE: |
2987 | value = dev_priv->ring_rptr_offset; | 2935 | value = dev_priv->ring_rptr_offset; |
@@ -3004,6 +2952,15 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS) | |||
3004 | case RADEON_PARAM_GART_TEX_HANDLE: | 2952 | case RADEON_PARAM_GART_TEX_HANDLE: |
3005 | value = dev_priv->gart_textures_offset; | 2953 | value = dev_priv->gart_textures_offset; |
3006 | break; | 2954 | break; |
2955 | |||
2956 | case RADEON_PARAM_CARD_TYPE: | ||
2957 | if (dev_priv->flags & CHIP_IS_PCIE) | ||
2958 | value = RADEON_CARD_PCIE; | ||
2959 | else if (dev_priv->flags & CHIP_IS_AGP) | ||
2960 | value = RADEON_CARD_AGP; | ||
2961 | else | ||
2962 | value = RADEON_CARD_PCI; | ||
2963 | break; | ||
3007 | default: | 2964 | default: |
3008 | return DRM_ERR(EINVAL); | 2965 | return DRM_ERR(EINVAL); |
3009 | } | 2966 | } |
@@ -3066,10 +3023,11 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) | |||
3066 | /* When a client dies: | 3023 | /* When a client dies: |
3067 | * - Check for and clean up flipped page state | 3024 | * - Check for and clean up flipped page state |
3068 | * - Free any alloced GART memory. | 3025 | * - Free any alloced GART memory. |
3026 | * - Free any alloced radeon surfaces. | ||
3069 | * | 3027 | * |
3070 | * DRM infrastructure takes care of reclaiming dma buffers. | 3028 | * DRM infrastructure takes care of reclaiming dma buffers. |
3071 | */ | 3029 | */ |
3072 | void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp) | 3030 | void radeon_driver_preclose(drm_device_t * dev, DRMFILE filp) |
3073 | { | 3031 | { |
3074 | if (dev->dev_private) { | 3032 | if (dev->dev_private) { |
3075 | drm_radeon_private_t *dev_priv = dev->dev_private; | 3033 | drm_radeon_private_t *dev_priv = dev->dev_private; |
@@ -3082,16 +3040,17 @@ void radeon_driver_prerelease(drm_device_t * dev, DRMFILE filp) | |||
3082 | } | 3040 | } |
3083 | } | 3041 | } |
3084 | 3042 | ||
3085 | void radeon_driver_pretakedown(drm_device_t * dev) | 3043 | void radeon_driver_lastclose(drm_device_t * dev) |
3086 | { | 3044 | { |
3087 | radeon_do_release(dev); | 3045 | radeon_do_release(dev); |
3088 | } | 3046 | } |
3089 | 3047 | ||
3090 | int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv) | 3048 | int radeon_driver_open(drm_device_t * dev, drm_file_t * filp_priv) |
3091 | { | 3049 | { |
3092 | drm_radeon_private_t *dev_priv = dev->dev_private; | 3050 | drm_radeon_private_t *dev_priv = dev->dev_private; |
3093 | struct drm_radeon_driver_file_fields *radeon_priv; | 3051 | struct drm_radeon_driver_file_fields *radeon_priv; |
3094 | 3052 | ||
3053 | DRM_DEBUG("\n"); | ||
3095 | radeon_priv = | 3054 | radeon_priv = |
3096 | (struct drm_radeon_driver_file_fields *) | 3055 | (struct drm_radeon_driver_file_fields *) |
3097 | drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES); | 3056 | drm_alloc(sizeof(*radeon_priv), DRM_MEM_FILES); |
@@ -3100,6 +3059,7 @@ int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv) | |||
3100 | return -ENOMEM; | 3059 | return -ENOMEM; |
3101 | 3060 | ||
3102 | filp_priv->driver_priv = radeon_priv; | 3061 | filp_priv->driver_priv = radeon_priv; |
3062 | |||
3103 | if (dev_priv) | 3063 | if (dev_priv) |
3104 | radeon_priv->radeon_fb_delta = dev_priv->fb_location; | 3064 | radeon_priv->radeon_fb_delta = dev_priv->fb_location; |
3105 | else | 3065 | else |
@@ -3107,7 +3067,7 @@ int radeon_driver_open_helper(drm_device_t * dev, drm_file_t * filp_priv) | |||
3107 | return 0; | 3067 | return 0; |
3108 | } | 3068 | } |
3109 | 3069 | ||
3110 | void radeon_driver_free_filp_priv(drm_device_t * dev, drm_file_t * filp_priv) | 3070 | void radeon_driver_postclose(drm_device_t * dev, drm_file_t * filp_priv) |
3111 | { | 3071 | { |
3112 | struct drm_radeon_driver_file_fields *radeon_priv = | 3072 | struct drm_radeon_driver_file_fields *radeon_priv = |
3113 | filp_priv->driver_priv; | 3073 | filp_priv->driver_priv; |
@@ -3116,33 +3076,33 @@ void radeon_driver_free_filp_priv(drm_device_t * dev, drm_file_t * filp_priv) | |||
3116 | } | 3076 | } |
3117 | 3077 | ||
3118 | drm_ioctl_desc_t radeon_ioctls[] = { | 3078 | drm_ioctl_desc_t radeon_ioctls[] = { |
3119 | [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, 1, 1}, | 3079 | [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
3120 | [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, 1, 1}, | 3080 | [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
3121 | [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, 1, 1}, | 3081 | [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
3122 | [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, 1, 1}, | 3082 | [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
3123 | [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, 1, 0}, | 3083 | [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, DRM_AUTH}, |
3124 | [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, 1, 0}, | 3084 | [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, DRM_AUTH}, |
3125 | [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, 1, 0}, | 3085 | [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, DRM_AUTH}, |
3126 | [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, 1, 0}, | 3086 | [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, DRM_AUTH}, |
3127 | [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, 1, 0}, | 3087 | [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, DRM_AUTH}, |
3128 | [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, 1, 0}, | 3088 | [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, DRM_AUTH}, |
3129 | [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, 1, 0}, | 3089 | [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, DRM_AUTH}, |
3130 | [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, 1, 0}, | 3090 | [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, DRM_AUTH}, |
3131 | [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, 1, 0}, | 3091 | [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, DRM_AUTH}, |
3132 | [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, 1, 0}, | 3092 | [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, DRM_AUTH}, |
3133 | [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, 1, 1}, | 3093 | [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
3134 | [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, 1, 0}, | 3094 | [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, DRM_AUTH}, |
3135 | [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, 1, 0}, | 3095 | [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, DRM_AUTH}, |
3136 | [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, 1, 0}, | 3096 | [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, DRM_AUTH}, |
3137 | [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, 1, 0}, | 3097 | [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, DRM_AUTH}, |
3138 | [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, 1, 0}, | 3098 | [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, DRM_AUTH}, |
3139 | [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, 1, 0}, | 3099 | [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, DRM_AUTH}, |
3140 | [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, 1, 1}, | 3100 | [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
3141 | [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, 1, 0}, | 3101 | [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, DRM_AUTH}, |
3142 | [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, 1, 0}, | 3102 | [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, DRM_AUTH}, |
3143 | [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, 1, 0}, | 3103 | [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, DRM_AUTH}, |
3144 | [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, 1, 0}, | 3104 | [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, DRM_AUTH}, |
3145 | [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, 1, 0} | 3105 | [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, DRM_AUTH} |
3146 | }; | 3106 | }; |
3147 | 3107 | ||
3148 | int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls); | 3108 | int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls); |
diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c index 6d10515795cc..0d426deeefec 100644 --- a/drivers/char/drm/savage_bci.c +++ b/drivers/char/drm/savage_bci.c | |||
@@ -533,16 +533,32 @@ static void savage_fake_dma_flush(drm_savage_private_t * dev_priv) | |||
533 | dev_priv->first_dma_page = dev_priv->current_dma_page = 0; | 533 | dev_priv->first_dma_page = dev_priv->current_dma_page = 0; |
534 | } | 534 | } |
535 | 535 | ||
536 | int savage_driver_load(drm_device_t *dev, unsigned long chipset) | ||
537 | { | ||
538 | drm_savage_private_t *dev_priv; | ||
539 | |||
540 | dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER); | ||
541 | if (dev_priv == NULL) | ||
542 | return DRM_ERR(ENOMEM); | ||
543 | |||
544 | memset(dev_priv, 0, sizeof(drm_savage_private_t)); | ||
545 | dev->dev_private = (void *)dev_priv; | ||
546 | |||
547 | dev_priv->chipset = (enum savage_family)chipset; | ||
548 | |||
549 | return 0; | ||
550 | } | ||
551 | |||
552 | |||
536 | /* | 553 | /* |
537 | * Initalize mappings. On Savage4 and SavageIX the alignment | 554 | * Initalize mappings. On Savage4 and SavageIX the alignment |
538 | * and size of the aperture is not suitable for automatic MTRR setup | 555 | * and size of the aperture is not suitable for automatic MTRR setup |
539 | * in drm_addmap. Therefore we do it manually before the maps are | 556 | * in drm_addmap. Therefore we add them manually before the maps are |
540 | * initialized. We also need to take care of deleting the MTRRs in | 557 | * initialized, and tear them down on last close. |
541 | * postcleanup. | ||
542 | */ | 558 | */ |
543 | int savage_preinit(drm_device_t * dev, unsigned long chipset) | 559 | int savage_driver_firstopen(drm_device_t *dev) |
544 | { | 560 | { |
545 | drm_savage_private_t *dev_priv; | 561 | drm_savage_private_t *dev_priv = dev->dev_private; |
546 | unsigned long mmio_base, fb_base, fb_size, aperture_base; | 562 | unsigned long mmio_base, fb_base, fb_size, aperture_base; |
547 | /* fb_rsrc and aper_rsrc aren't really used currently, but still exist | 563 | /* fb_rsrc and aper_rsrc aren't really used currently, but still exist |
548 | * in case we decide we need information on the BAR for BSD in the | 564 | * in case we decide we need information on the BAR for BSD in the |
@@ -551,14 +567,6 @@ int savage_preinit(drm_device_t * dev, unsigned long chipset) | |||
551 | unsigned int fb_rsrc, aper_rsrc; | 567 | unsigned int fb_rsrc, aper_rsrc; |
552 | int ret = 0; | 568 | int ret = 0; |
553 | 569 | ||
554 | dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER); | ||
555 | if (dev_priv == NULL) | ||
556 | return DRM_ERR(ENOMEM); | ||
557 | |||
558 | memset(dev_priv, 0, sizeof(drm_savage_private_t)); | ||
559 | dev->dev_private = (void *)dev_priv; | ||
560 | dev_priv->chipset = (enum savage_family)chipset; | ||
561 | |||
562 | dev_priv->mtrr[0].handle = -1; | 570 | dev_priv->mtrr[0].handle = -1; |
563 | dev_priv->mtrr[1].handle = -1; | 571 | dev_priv->mtrr[1].handle = -1; |
564 | dev_priv->mtrr[2].handle = -1; | 572 | dev_priv->mtrr[2].handle = -1; |
@@ -576,26 +584,24 @@ int savage_preinit(drm_device_t * dev, unsigned long chipset) | |||
576 | dev_priv->mtrr[0].base = fb_base; | 584 | dev_priv->mtrr[0].base = fb_base; |
577 | dev_priv->mtrr[0].size = 0x01000000; | 585 | dev_priv->mtrr[0].size = 0x01000000; |
578 | dev_priv->mtrr[0].handle = | 586 | dev_priv->mtrr[0].handle = |
579 | mtrr_add(dev_priv->mtrr[0].base, | 587 | drm_mtrr_add(dev_priv->mtrr[0].base, |
580 | dev_priv->mtrr[0].size, MTRR_TYPE_WRCOMB, | 588 | dev_priv->mtrr[0].size, DRM_MTRR_WC); |
581 | 1); | ||
582 | dev_priv->mtrr[1].base = fb_base + 0x02000000; | 589 | dev_priv->mtrr[1].base = fb_base + 0x02000000; |
583 | dev_priv->mtrr[1].size = 0x02000000; | 590 | dev_priv->mtrr[1].size = 0x02000000; |
584 | dev_priv->mtrr[1].handle = | 591 | dev_priv->mtrr[1].handle = |
585 | mtrr_add(dev_priv->mtrr[1].base, | 592 | drm_mtrr_add(dev_priv->mtrr[1].base, |
586 | dev_priv->mtrr[1].size, MTRR_TYPE_WRCOMB, | 593 | dev_priv->mtrr[1].size, DRM_MTRR_WC); |
587 | 1); | ||
588 | dev_priv->mtrr[2].base = fb_base + 0x04000000; | 594 | dev_priv->mtrr[2].base = fb_base + 0x04000000; |
589 | dev_priv->mtrr[2].size = 0x04000000; | 595 | dev_priv->mtrr[2].size = 0x04000000; |
590 | dev_priv->mtrr[2].handle = | 596 | dev_priv->mtrr[2].handle = |
591 | mtrr_add(dev_priv->mtrr[2].base, | 597 | drm_mtrr_add(dev_priv->mtrr[2].base, |
592 | dev_priv->mtrr[2].size, MTRR_TYPE_WRCOMB, | 598 | dev_priv->mtrr[2].size, DRM_MTRR_WC); |
593 | 1); | ||
594 | } else { | 599 | } else { |
595 | DRM_ERROR("strange pci_resource_len %08lx\n", | 600 | DRM_ERROR("strange pci_resource_len %08lx\n", |
596 | drm_get_resource_len(dev, 0)); | 601 | drm_get_resource_len(dev, 0)); |
597 | } | 602 | } |
598 | } else if (chipset != S3_SUPERSAVAGE && chipset != S3_SAVAGE2000) { | 603 | } else if (dev_priv->chipset != S3_SUPERSAVAGE && |
604 | dev_priv->chipset != S3_SAVAGE2000) { | ||
599 | mmio_base = drm_get_resource_start(dev, 0); | 605 | mmio_base = drm_get_resource_start(dev, 0); |
600 | fb_rsrc = 1; | 606 | fb_rsrc = 1; |
601 | fb_base = drm_get_resource_start(dev, 1); | 607 | fb_base = drm_get_resource_start(dev, 1); |
@@ -609,9 +615,8 @@ int savage_preinit(drm_device_t * dev, unsigned long chipset) | |||
609 | dev_priv->mtrr[0].base = fb_base; | 615 | dev_priv->mtrr[0].base = fb_base; |
610 | dev_priv->mtrr[0].size = 0x08000000; | 616 | dev_priv->mtrr[0].size = 0x08000000; |
611 | dev_priv->mtrr[0].handle = | 617 | dev_priv->mtrr[0].handle = |
612 | mtrr_add(dev_priv->mtrr[0].base, | 618 | drm_mtrr_add(dev_priv->mtrr[0].base, |
613 | dev_priv->mtrr[0].size, MTRR_TYPE_WRCOMB, | 619 | dev_priv->mtrr[0].size, DRM_MTRR_WC); |
614 | 1); | ||
615 | } else { | 620 | } else { |
616 | DRM_ERROR("strange pci_resource_len %08lx\n", | 621 | DRM_ERROR("strange pci_resource_len %08lx\n", |
617 | drm_get_resource_len(dev, 1)); | 622 | drm_get_resource_len(dev, 1)); |
@@ -648,16 +653,21 @@ int savage_preinit(drm_device_t * dev, unsigned long chipset) | |||
648 | /* | 653 | /* |
649 | * Delete MTRRs and free device-private data. | 654 | * Delete MTRRs and free device-private data. |
650 | */ | 655 | */ |
651 | int savage_postcleanup(drm_device_t * dev) | 656 | void savage_driver_lastclose(drm_device_t *dev) |
652 | { | 657 | { |
653 | drm_savage_private_t *dev_priv = dev->dev_private; | 658 | drm_savage_private_t *dev_priv = dev->dev_private; |
654 | int i; | 659 | int i; |
655 | 660 | ||
656 | for (i = 0; i < 3; ++i) | 661 | for (i = 0; i < 3; ++i) |
657 | if (dev_priv->mtrr[i].handle >= 0) | 662 | if (dev_priv->mtrr[i].handle >= 0) |
658 | mtrr_del(dev_priv->mtrr[i].handle, | 663 | drm_mtrr_del(dev_priv->mtrr[i].handle, |
659 | dev_priv->mtrr[i].base, | 664 | dev_priv->mtrr[i].base, |
660 | dev_priv->mtrr[i].size); | 665 | dev_priv->mtrr[i].size, DRM_MTRR_WC); |
666 | } | ||
667 | |||
668 | int savage_driver_unload(drm_device_t *dev) | ||
669 | { | ||
670 | drm_savage_private_t *dev_priv = dev->dev_private; | ||
661 | 671 | ||
662 | drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER); | 672 | drm_free(dev_priv, sizeof(drm_savage_private_t), DRM_MEM_DRIVER); |
663 | 673 | ||
@@ -994,8 +1004,7 @@ static int savage_bci_event_wait(DRM_IOCTL_ARGS) | |||
994 | * DMA buffer management | 1004 | * DMA buffer management |
995 | */ | 1005 | */ |
996 | 1006 | ||
997 | static int savage_bci_get_buffers(DRMFILE filp, drm_device_t * dev, | 1007 | static int savage_bci_get_buffers(DRMFILE filp, drm_device_t *dev, drm_dma_t *d) |
998 | drm_dma_t * d) | ||
999 | { | 1008 | { |
1000 | drm_buf_t *buf; | 1009 | drm_buf_t *buf; |
1001 | int i; | 1010 | int i; |
@@ -1057,7 +1066,7 @@ int savage_bci_buffers(DRM_IOCTL_ARGS) | |||
1057 | return ret; | 1066 | return ret; |
1058 | } | 1067 | } |
1059 | 1068 | ||
1060 | void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp) | 1069 | void savage_reclaim_buffers(drm_device_t *dev, DRMFILE filp) |
1061 | { | 1070 | { |
1062 | drm_device_dma_t *dma = dev->dma; | 1071 | drm_device_dma_t *dma = dev->dma; |
1063 | drm_savage_private_t *dev_priv = dev->dev_private; | 1072 | drm_savage_private_t *dev_priv = dev->dev_private; |
@@ -1090,10 +1099,10 @@ void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp) | |||
1090 | } | 1099 | } |
1091 | 1100 | ||
1092 | drm_ioctl_desc_t savage_ioctls[] = { | 1101 | drm_ioctl_desc_t savage_ioctls[] = { |
1093 | [DRM_IOCTL_NR(DRM_SAVAGE_BCI_INIT)] = {savage_bci_init, 1, 1}, | 1102 | [DRM_IOCTL_NR(DRM_SAVAGE_BCI_INIT)] = {savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
1094 | [DRM_IOCTL_NR(DRM_SAVAGE_BCI_CMDBUF)] = {savage_bci_cmdbuf, 1, 0}, | 1103 | [DRM_IOCTL_NR(DRM_SAVAGE_BCI_CMDBUF)] = {savage_bci_cmdbuf, DRM_AUTH}, |
1095 | [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_EMIT)] = {savage_bci_event_emit, 1, 0}, | 1104 | [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_EMIT)] = {savage_bci_event_emit, DRM_AUTH}, |
1096 | [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_WAIT)] = {savage_bci_event_wait, 1, 0}, | 1105 | [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_WAIT)] = {savage_bci_event_wait, DRM_AUTH}, |
1097 | }; | 1106 | }; |
1098 | 1107 | ||
1099 | int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls); | 1108 | int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls); |
diff --git a/drivers/char/drm/savage_drv.c b/drivers/char/drm/savage_drv.c index 22d799cde41c..aa6c0d1a82f8 100644 --- a/drivers/char/drm/savage_drv.c +++ b/drivers/char/drm/savage_drv.c | |||
@@ -30,31 +30,6 @@ | |||
30 | 30 | ||
31 | #include "drm_pciids.h" | 31 | #include "drm_pciids.h" |
32 | 32 | ||
33 | static int postinit(struct drm_device *dev, unsigned long flags) | ||
34 | { | ||
35 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n", | ||
36 | DRIVER_NAME, | ||
37 | DRIVER_MAJOR, | ||
38 | DRIVER_MINOR, | ||
39 | DRIVER_PATCHLEVEL, | ||
40 | DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev) | ||
41 | ); | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int version(drm_version_t * version) | ||
46 | { | ||
47 | int len; | ||
48 | |||
49 | version->version_major = DRIVER_MAJOR; | ||
50 | version->version_minor = DRIVER_MINOR; | ||
51 | version->version_patchlevel = DRIVER_PATCHLEVEL; | ||
52 | DRM_COPY(version->name, DRIVER_NAME); | ||
53 | DRM_COPY(version->date, DRIVER_DATE); | ||
54 | DRM_COPY(version->desc, DRIVER_DESC); | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static struct pci_device_id pciidlist[] = { | 33 | static struct pci_device_id pciidlist[] = { |
59 | savage_PCI_IDS | 34 | savage_PCI_IDS |
60 | }; | 35 | }; |
@@ -63,13 +38,13 @@ static struct drm_driver driver = { | |||
63 | .driver_features = | 38 | .driver_features = |
64 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_PCI_DMA, | 39 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_PCI_DMA, |
65 | .dev_priv_size = sizeof(drm_savage_buf_priv_t), | 40 | .dev_priv_size = sizeof(drm_savage_buf_priv_t), |
66 | .preinit = savage_preinit, | 41 | .load = savage_driver_load, |
67 | .postinit = postinit, | 42 | .firstopen = savage_driver_firstopen, |
68 | .postcleanup = savage_postcleanup, | 43 | .lastclose = savage_driver_lastclose, |
44 | .unload = savage_driver_unload, | ||
69 | .reclaim_buffers = savage_reclaim_buffers, | 45 | .reclaim_buffers = savage_reclaim_buffers, |
70 | .get_map_ofs = drm_core_get_map_ofs, | 46 | .get_map_ofs = drm_core_get_map_ofs, |
71 | .get_reg_ofs = drm_core_get_reg_ofs, | 47 | .get_reg_ofs = drm_core_get_reg_ofs, |
72 | .version = version, | ||
73 | .ioctls = savage_ioctls, | 48 | .ioctls = savage_ioctls, |
74 | .dma_ioctl = savage_bci_buffers, | 49 | .dma_ioctl = savage_bci_buffers, |
75 | .fops = { | 50 | .fops = { |
@@ -80,12 +55,19 @@ static struct drm_driver driver = { | |||
80 | .mmap = drm_mmap, | 55 | .mmap = drm_mmap, |
81 | .poll = drm_poll, | 56 | .poll = drm_poll, |
82 | .fasync = drm_fasync, | 57 | .fasync = drm_fasync, |
83 | } | 58 | }, |
84 | , | 59 | |
85 | .pci_driver = { | 60 | .pci_driver = { |
86 | .name = DRIVER_NAME, | 61 | .name = DRIVER_NAME, |
87 | .id_table = pciidlist, | 62 | .id_table = pciidlist, |
88 | } | 63 | }, |
64 | |||
65 | .name = DRIVER_NAME, | ||
66 | .desc = DRIVER_DESC, | ||
67 | .date = DRIVER_DATE, | ||
68 | .major = DRIVER_MAJOR, | ||
69 | .minor = DRIVER_MINOR, | ||
70 | .patchlevel = DRIVER_PATCHLEVEL, | ||
89 | }; | 71 | }; |
90 | 72 | ||
91 | static int __init savage_init(void) | 73 | static int __init savage_init(void) |
diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h index a4b0fa998a95..dd46cb85439c 100644 --- a/drivers/char/drm/savage_drv.h +++ b/drivers/char/drm/savage_drv.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* savage_drv.h -- Private header for the savage driver | 1 | /* savage_drv.h -- Private header for the savage driver */ |
2 | * | 2 | /* |
3 | * Copyright 2004 Felix Kuehling | 3 | * Copyright 2004 Felix Kuehling |
4 | * All Rights Reserved. | 4 | * All Rights Reserved. |
5 | * | 5 | * |
@@ -192,7 +192,7 @@ typedef struct drm_savage_private { | |||
192 | /* Err, there is a macro wait_event in include/linux/wait.h. | 192 | /* Err, there is a macro wait_event in include/linux/wait.h. |
193 | * Avoid unwanted macro expansion. */ | 193 | * Avoid unwanted macro expansion. */ |
194 | void (*emit_clip_rect) (struct drm_savage_private * dev_priv, | 194 | void (*emit_clip_rect) (struct drm_savage_private * dev_priv, |
195 | drm_clip_rect_t * pbox); | 195 | const drm_clip_rect_t * pbox); |
196 | void (*dma_flush) (struct drm_savage_private * dev_priv); | 196 | void (*dma_flush) (struct drm_savage_private * dev_priv); |
197 | } drm_savage_private_t; | 197 | } drm_savage_private_t; |
198 | 198 | ||
@@ -208,16 +208,18 @@ extern void savage_dma_reset(drm_savage_private_t * dev_priv); | |||
208 | extern void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page); | 208 | extern void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page); |
209 | extern uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv, | 209 | extern uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv, |
210 | unsigned int n); | 210 | unsigned int n); |
211 | extern int savage_preinit(drm_device_t * dev, unsigned long chipset); | 211 | extern int savage_driver_load(drm_device_t *dev, unsigned long chipset); |
212 | extern int savage_postcleanup(drm_device_t * dev); | 212 | extern int savage_driver_firstopen(drm_device_t *dev); |
213 | extern void savage_driver_lastclose(drm_device_t *dev); | ||
214 | extern int savage_driver_unload(drm_device_t *dev); | ||
213 | extern int savage_do_cleanup_bci(drm_device_t * dev); | 215 | extern int savage_do_cleanup_bci(drm_device_t * dev); |
214 | extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp); | 216 | extern void savage_reclaim_buffers(drm_device_t * dev, DRMFILE filp); |
215 | 217 | ||
216 | /* state functions */ | 218 | /* state functions */ |
217 | extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv, | 219 | extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv, |
218 | drm_clip_rect_t * pbox); | 220 | const drm_clip_rect_t * pbox); |
219 | extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv, | 221 | extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv, |
220 | drm_clip_rect_t * pbox); | 222 | const drm_clip_rect_t * pbox); |
221 | 223 | ||
222 | #define SAVAGE_FB_SIZE_S3 0x01000000 /* 16MB */ | 224 | #define SAVAGE_FB_SIZE_S3 0x01000000 /* 16MB */ |
223 | #define SAVAGE_FB_SIZE_S4 0x02000000 /* 32MB */ | 225 | #define SAVAGE_FB_SIZE_S4 0x02000000 /* 32MB */ |
@@ -500,15 +502,6 @@ extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv, | |||
500 | 502 | ||
501 | #define BCI_WRITE( val ) *bci_ptr++ = (uint32_t)(val) | 503 | #define BCI_WRITE( val ) *bci_ptr++ = (uint32_t)(val) |
502 | 504 | ||
503 | #define BCI_COPY_FROM_USER(src,n) do { \ | ||
504 | unsigned int i; \ | ||
505 | for (i = 0; i < n; ++i) { \ | ||
506 | uint32_t val; \ | ||
507 | DRM_GET_USER_UNCHECKED(val, &((uint32_t*)(src))[i]); \ | ||
508 | BCI_WRITE(val); \ | ||
509 | } \ | ||
510 | } while(0) | ||
511 | |||
512 | /* | 505 | /* |
513 | * command DMA support | 506 | * command DMA support |
514 | */ | 507 | */ |
@@ -534,8 +527,8 @@ extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv, | |||
534 | 527 | ||
535 | #define DMA_WRITE( val ) *dma_ptr++ = (uint32_t)(val) | 528 | #define DMA_WRITE( val ) *dma_ptr++ = (uint32_t)(val) |
536 | 529 | ||
537 | #define DMA_COPY_FROM_USER(src,n) do { \ | 530 | #define DMA_COPY(src, n) do { \ |
538 | DRM_COPY_FROM_USER_UNCHECKED(dma_ptr, (src), (n)*4); \ | 531 | memcpy(dma_ptr, (src), (n)*4); \ |
539 | dma_ptr += n; \ | 532 | dma_ptr += n; \ |
540 | } while(0) | 533 | } while(0) |
541 | 534 | ||
diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c index e87a5d59b99c..ef2581d16146 100644 --- a/drivers/char/drm/savage_state.c +++ b/drivers/char/drm/savage_state.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include "savage_drv.h" | 27 | #include "savage_drv.h" |
28 | 28 | ||
29 | void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv, | 29 | void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv, |
30 | drm_clip_rect_t * pbox) | 30 | const drm_clip_rect_t * pbox) |
31 | { | 31 | { |
32 | uint32_t scstart = dev_priv->state.s3d.new_scstart; | 32 | uint32_t scstart = dev_priv->state.s3d.new_scstart; |
33 | uint32_t scend = dev_priv->state.s3d.new_scend; | 33 | uint32_t scend = dev_priv->state.s3d.new_scend; |
@@ -53,7 +53,7 @@ void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv, | |||
53 | } | 53 | } |
54 | 54 | ||
55 | void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv, | 55 | void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv, |
56 | drm_clip_rect_t * pbox) | 56 | const drm_clip_rect_t * pbox) |
57 | { | 57 | { |
58 | uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0; | 58 | uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0; |
59 | uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1; | 59 | uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1; |
@@ -115,18 +115,19 @@ static int savage_verify_texaddr(drm_savage_private_t * dev_priv, int unit, | |||
115 | 115 | ||
116 | #define SAVE_STATE(reg,where) \ | 116 | #define SAVE_STATE(reg,where) \ |
117 | if(start <= reg && start+count > reg) \ | 117 | if(start <= reg && start+count > reg) \ |
118 | DRM_GET_USER_UNCHECKED(dev_priv->state.where, ®s[reg-start]) | 118 | dev_priv->state.where = regs[reg - start] |
119 | #define SAVE_STATE_MASK(reg,where,mask) do { \ | 119 | #define SAVE_STATE_MASK(reg,where,mask) do { \ |
120 | if(start <= reg && start+count > reg) { \ | 120 | if(start <= reg && start+count > reg) { \ |
121 | uint32_t tmp; \ | 121 | uint32_t tmp; \ |
122 | DRM_GET_USER_UNCHECKED(tmp, ®s[reg-start]); \ | 122 | tmp = regs[reg - start]; \ |
123 | dev_priv->state.where = (tmp & (mask)) | \ | 123 | dev_priv->state.where = (tmp & (mask)) | \ |
124 | (dev_priv->state.where & ~(mask)); \ | 124 | (dev_priv->state.where & ~(mask)); \ |
125 | } \ | 125 | } \ |
126 | } while (0) | 126 | } while (0) |
127 | |||
127 | static int savage_verify_state_s3d(drm_savage_private_t * dev_priv, | 128 | static int savage_verify_state_s3d(drm_savage_private_t * dev_priv, |
128 | unsigned int start, unsigned int count, | 129 | unsigned int start, unsigned int count, |
129 | const uint32_t __user * regs) | 130 | const uint32_t *regs) |
130 | { | 131 | { |
131 | if (start < SAVAGE_TEXPALADDR_S3D || | 132 | if (start < SAVAGE_TEXPALADDR_S3D || |
132 | start + count - 1 > SAVAGE_DESTTEXRWWATERMARK_S3D) { | 133 | start + count - 1 > SAVAGE_DESTTEXRWWATERMARK_S3D) { |
@@ -148,8 +149,7 @@ static int savage_verify_state_s3d(drm_savage_private_t * dev_priv, | |||
148 | SAVE_STATE(SAVAGE_TEXADDR_S3D, s3d.texaddr); | 149 | SAVE_STATE(SAVAGE_TEXADDR_S3D, s3d.texaddr); |
149 | if (dev_priv->state.s3d.texctrl & SAVAGE_TEXCTRL_TEXEN_MASK) | 150 | if (dev_priv->state.s3d.texctrl & SAVAGE_TEXCTRL_TEXEN_MASK) |
150 | return savage_verify_texaddr(dev_priv, 0, | 151 | return savage_verify_texaddr(dev_priv, 0, |
151 | dev_priv->state.s3d. | 152 | dev_priv->state.s3d.texaddr); |
152 | texaddr); | ||
153 | } | 153 | } |
154 | 154 | ||
155 | return 0; | 155 | return 0; |
@@ -157,7 +157,7 @@ static int savage_verify_state_s3d(drm_savage_private_t * dev_priv, | |||
157 | 157 | ||
158 | static int savage_verify_state_s4(drm_savage_private_t * dev_priv, | 158 | static int savage_verify_state_s4(drm_savage_private_t * dev_priv, |
159 | unsigned int start, unsigned int count, | 159 | unsigned int start, unsigned int count, |
160 | const uint32_t __user * regs) | 160 | const uint32_t *regs) |
161 | { | 161 | { |
162 | int ret = 0; | 162 | int ret = 0; |
163 | 163 | ||
@@ -174,19 +174,18 @@ static int savage_verify_state_s4(drm_savage_private_t * dev_priv, | |||
174 | ~SAVAGE_SCISSOR_MASK_S4); | 174 | ~SAVAGE_SCISSOR_MASK_S4); |
175 | 175 | ||
176 | /* if any texture regs were changed ... */ | 176 | /* if any texture regs were changed ... */ |
177 | if (start <= SAVAGE_TEXDESCR_S4 && start + count > SAVAGE_TEXPALADDR_S4) { | 177 | if (start <= SAVAGE_TEXDESCR_S4 && |
178 | start + count > SAVAGE_TEXPALADDR_S4) { | ||
178 | /* ... check texture state */ | 179 | /* ... check texture state */ |
179 | SAVE_STATE(SAVAGE_TEXDESCR_S4, s4.texdescr); | 180 | SAVE_STATE(SAVAGE_TEXDESCR_S4, s4.texdescr); |
180 | SAVE_STATE(SAVAGE_TEXADDR0_S4, s4.texaddr0); | 181 | SAVE_STATE(SAVAGE_TEXADDR0_S4, s4.texaddr0); |
181 | SAVE_STATE(SAVAGE_TEXADDR1_S4, s4.texaddr1); | 182 | SAVE_STATE(SAVAGE_TEXADDR1_S4, s4.texaddr1); |
182 | if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX0EN_MASK) | 183 | if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX0EN_MASK) |
183 | ret |= | 184 | ret |= savage_verify_texaddr(dev_priv, 0, |
184 | savage_verify_texaddr(dev_priv, 0, | 185 | dev_priv->state.s4.texaddr0); |
185 | dev_priv->state.s4.texaddr0); | ||
186 | if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX1EN_MASK) | 186 | if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX1EN_MASK) |
187 | ret |= | 187 | ret |= savage_verify_texaddr(dev_priv, 1, |
188 | savage_verify_texaddr(dev_priv, 1, | 188 | dev_priv->state.s4.texaddr1); |
189 | dev_priv->state.s4.texaddr1); | ||
190 | } | 189 | } |
191 | 190 | ||
192 | return ret; | 191 | return ret; |
@@ -197,7 +196,7 @@ static int savage_verify_state_s4(drm_savage_private_t * dev_priv, | |||
197 | 196 | ||
198 | static int savage_dispatch_state(drm_savage_private_t * dev_priv, | 197 | static int savage_dispatch_state(drm_savage_private_t * dev_priv, |
199 | const drm_savage_cmd_header_t * cmd_header, | 198 | const drm_savage_cmd_header_t * cmd_header, |
200 | const uint32_t __user * regs) | 199 | const uint32_t *regs) |
201 | { | 200 | { |
202 | unsigned int count = cmd_header->state.count; | 201 | unsigned int count = cmd_header->state.count; |
203 | unsigned int start = cmd_header->state.start; | 202 | unsigned int start = cmd_header->state.start; |
@@ -209,9 +208,6 @@ static int savage_dispatch_state(drm_savage_private_t * dev_priv, | |||
209 | if (!count) | 208 | if (!count) |
210 | return 0; | 209 | return 0; |
211 | 210 | ||
212 | if (DRM_VERIFYAREA_READ(regs, count * 4)) | ||
213 | return DRM_ERR(EFAULT); | ||
214 | |||
215 | if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { | 211 | if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { |
216 | ret = savage_verify_state_s3d(dev_priv, start, count, regs); | 212 | ret = savage_verify_state_s3d(dev_priv, start, count, regs); |
217 | if (ret != 0) | 213 | if (ret != 0) |
@@ -236,8 +232,8 @@ static int savage_dispatch_state(drm_savage_private_t * dev_priv, | |||
236 | /* scissor regs are emitted in savage_dispatch_draw */ | 232 | /* scissor regs are emitted in savage_dispatch_draw */ |
237 | if (start < SAVAGE_DRAWCTRL0_S4) { | 233 | if (start < SAVAGE_DRAWCTRL0_S4) { |
238 | if (start + count > SAVAGE_DRAWCTRL1_S4 + 1) | 234 | if (start + count > SAVAGE_DRAWCTRL1_S4 + 1) |
239 | count2 = | 235 | count2 = count - |
240 | count - (SAVAGE_DRAWCTRL1_S4 + 1 - start); | 236 | (SAVAGE_DRAWCTRL1_S4 + 1 - start); |
241 | if (start + count > SAVAGE_DRAWCTRL0_S4) | 237 | if (start + count > SAVAGE_DRAWCTRL0_S4) |
242 | count = SAVAGE_DRAWCTRL0_S4 - start; | 238 | count = SAVAGE_DRAWCTRL0_S4 - start; |
243 | } else if (start <= SAVAGE_DRAWCTRL1_S4) { | 239 | } else if (start <= SAVAGE_DRAWCTRL1_S4) { |
@@ -263,7 +259,7 @@ static int savage_dispatch_state(drm_savage_private_t * dev_priv, | |||
263 | while (count > 0) { | 259 | while (count > 0) { |
264 | unsigned int n = count < 255 ? count : 255; | 260 | unsigned int n = count < 255 ? count : 255; |
265 | DMA_SET_REGISTERS(start, n); | 261 | DMA_SET_REGISTERS(start, n); |
266 | DMA_COPY_FROM_USER(regs, n); | 262 | DMA_COPY(regs, n); |
267 | count -= n; | 263 | count -= n; |
268 | start += n; | 264 | start += n; |
269 | regs += n; | 265 | regs += n; |
@@ -421,8 +417,8 @@ static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv, | |||
421 | 417 | ||
422 | static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv, | 418 | static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv, |
423 | const drm_savage_cmd_header_t * cmd_header, | 419 | const drm_savage_cmd_header_t * cmd_header, |
424 | const uint32_t __user * vtxbuf, | 420 | const uint32_t *vtxbuf, unsigned int vb_size, |
425 | unsigned int vb_size, unsigned int vb_stride) | 421 | unsigned int vb_stride) |
426 | { | 422 | { |
427 | unsigned char reorder = 0; | 423 | unsigned char reorder = 0; |
428 | unsigned int prim = cmd_header->prim.prim; | 424 | unsigned int prim = cmd_header->prim.prim; |
@@ -507,8 +503,7 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv, | |||
507 | 503 | ||
508 | for (i = start; i < start + count; ++i) { | 504 | for (i = start; i < start + count; ++i) { |
509 | unsigned int j = i + reorder[i % 3]; | 505 | unsigned int j = i + reorder[i % 3]; |
510 | DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j], | 506 | DMA_COPY(&vtxbuf[vb_stride * j], vtx_size); |
511 | vtx_size); | ||
512 | } | 507 | } |
513 | 508 | ||
514 | DMA_COMMIT(); | 509 | DMA_COMMIT(); |
@@ -517,13 +512,12 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv, | |||
517 | DMA_DRAW_PRIMITIVE(count, prim, skip); | 512 | DMA_DRAW_PRIMITIVE(count, prim, skip); |
518 | 513 | ||
519 | if (vb_stride == vtx_size) { | 514 | if (vb_stride == vtx_size) { |
520 | DMA_COPY_FROM_USER(&vtxbuf[vb_stride * start], | 515 | DMA_COPY(&vtxbuf[vb_stride * start], |
521 | vtx_size * count); | 516 | vtx_size * count); |
522 | } else { | 517 | } else { |
523 | for (i = start; i < start + count; ++i) { | 518 | for (i = start; i < start + count; ++i) { |
524 | DMA_COPY_FROM_USER(&vtxbuf | 519 | DMA_COPY(&vtxbuf [vb_stride * i], |
525 | [vb_stride * i], | 520 | vtx_size); |
526 | vtx_size); | ||
527 | } | 521 | } |
528 | } | 522 | } |
529 | 523 | ||
@@ -541,7 +535,7 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv, | |||
541 | 535 | ||
542 | static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, | 536 | static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, |
543 | const drm_savage_cmd_header_t * cmd_header, | 537 | const drm_savage_cmd_header_t * cmd_header, |
544 | const uint16_t __user * usr_idx, | 538 | const uint16_t *idx, |
545 | const drm_buf_t * dmabuf) | 539 | const drm_buf_t * dmabuf) |
546 | { | 540 | { |
547 | unsigned char reorder = 0; | 541 | unsigned char reorder = 0; |
@@ -628,11 +622,8 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, | |||
628 | while (n != 0) { | 622 | while (n != 0) { |
629 | /* Can emit up to 255 indices (85 triangles) at once. */ | 623 | /* Can emit up to 255 indices (85 triangles) at once. */ |
630 | unsigned int count = n > 255 ? 255 : n; | 624 | unsigned int count = n > 255 ? 255 : n; |
631 | /* Is it ok to allocate 510 bytes on the stack in an ioctl? */ | ||
632 | uint16_t idx[255]; | ||
633 | 625 | ||
634 | /* Copy and check indices */ | 626 | /* check indices */ |
635 | DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count * 2); | ||
636 | for (i = 0; i < count; ++i) { | 627 | for (i = 0; i < count; ++i) { |
637 | if (idx[i] > dmabuf->total / 32) { | 628 | if (idx[i] > dmabuf->total / 32) { |
638 | DRM_ERROR("idx[%u]=%u out of range (0-%u)\n", | 629 | DRM_ERROR("idx[%u]=%u out of range (0-%u)\n", |
@@ -652,8 +643,8 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, | |||
652 | 643 | ||
653 | for (i = 1; i + 1 < count; i += 2) | 644 | for (i = 1; i + 1 < count; i += 2) |
654 | BCI_WRITE(idx[i + reorder[i % 3]] | | 645 | BCI_WRITE(idx[i + reorder[i % 3]] | |
655 | (idx[i + 1 + reorder[(i + 1) % 3]] << | 646 | (idx[i + 1 + |
656 | 16)); | 647 | reorder[(i + 1) % 3]] << 16)); |
657 | if (i < count) | 648 | if (i < count) |
658 | BCI_WRITE(idx[i + reorder[i % 3]]); | 649 | BCI_WRITE(idx[i + reorder[i % 3]]); |
659 | } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { | 650 | } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { |
@@ -674,7 +665,7 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, | |||
674 | BCI_WRITE(idx[i]); | 665 | BCI_WRITE(idx[i]); |
675 | } | 666 | } |
676 | 667 | ||
677 | usr_idx += count; | 668 | idx += count; |
678 | n -= count; | 669 | n -= count; |
679 | 670 | ||
680 | prim |= BCI_CMD_DRAW_CONT; | 671 | prim |= BCI_CMD_DRAW_CONT; |
@@ -685,8 +676,8 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, | |||
685 | 676 | ||
686 | static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, | 677 | static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, |
687 | const drm_savage_cmd_header_t * cmd_header, | 678 | const drm_savage_cmd_header_t * cmd_header, |
688 | const uint16_t __user * usr_idx, | 679 | const uint16_t *idx, |
689 | const uint32_t __user * vtxbuf, | 680 | const uint32_t *vtxbuf, |
690 | unsigned int vb_size, unsigned int vb_stride) | 681 | unsigned int vb_size, unsigned int vb_stride) |
691 | { | 682 | { |
692 | unsigned char reorder = 0; | 683 | unsigned char reorder = 0; |
@@ -751,11 +742,8 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, | |||
751 | while (n != 0) { | 742 | while (n != 0) { |
752 | /* Can emit up to 255 vertices (85 triangles) at once. */ | 743 | /* Can emit up to 255 vertices (85 triangles) at once. */ |
753 | unsigned int count = n > 255 ? 255 : n; | 744 | unsigned int count = n > 255 ? 255 : n; |
754 | /* Is it ok to allocate 510 bytes on the stack in an ioctl? */ | 745 | |
755 | uint16_t idx[255]; | 746 | /* Check indices */ |
756 | |||
757 | /* Copy and check indices */ | ||
758 | DRM_COPY_FROM_USER_UNCHECKED(idx, usr_idx, count * 2); | ||
759 | for (i = 0; i < count; ++i) { | 747 | for (i = 0; i < count; ++i) { |
760 | if (idx[i] > vb_size / (vb_stride * 4)) { | 748 | if (idx[i] > vb_size / (vb_stride * 4)) { |
761 | DRM_ERROR("idx[%u]=%u out of range (0-%u)\n", | 749 | DRM_ERROR("idx[%u]=%u out of range (0-%u)\n", |
@@ -775,8 +763,7 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, | |||
775 | 763 | ||
776 | for (i = 0; i < count; ++i) { | 764 | for (i = 0; i < count; ++i) { |
777 | unsigned int j = idx[i + reorder[i % 3]]; | 765 | unsigned int j = idx[i + reorder[i % 3]]; |
778 | DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j], | 766 | DMA_COPY(&vtxbuf[vb_stride * j], vtx_size); |
779 | vtx_size); | ||
780 | } | 767 | } |
781 | 768 | ||
782 | DMA_COMMIT(); | 769 | DMA_COMMIT(); |
@@ -786,14 +773,13 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, | |||
786 | 773 | ||
787 | for (i = 0; i < count; ++i) { | 774 | for (i = 0; i < count; ++i) { |
788 | unsigned int j = idx[i]; | 775 | unsigned int j = idx[i]; |
789 | DMA_COPY_FROM_USER(&vtxbuf[vb_stride * j], | 776 | DMA_COPY(&vtxbuf[vb_stride * j], vtx_size); |
790 | vtx_size); | ||
791 | } | 777 | } |
792 | 778 | ||
793 | DMA_COMMIT(); | 779 | DMA_COMMIT(); |
794 | } | 780 | } |
795 | 781 | ||
796 | usr_idx += count; | 782 | idx += count; |
797 | n -= count; | 783 | n -= count; |
798 | 784 | ||
799 | prim |= BCI_CMD_DRAW_CONT; | 785 | prim |= BCI_CMD_DRAW_CONT; |
@@ -804,11 +790,11 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, | |||
804 | 790 | ||
805 | static int savage_dispatch_clear(drm_savage_private_t * dev_priv, | 791 | static int savage_dispatch_clear(drm_savage_private_t * dev_priv, |
806 | const drm_savage_cmd_header_t * cmd_header, | 792 | const drm_savage_cmd_header_t * cmd_header, |
807 | const drm_savage_cmd_header_t __user * data, | 793 | const drm_savage_cmd_header_t *data, |
808 | unsigned int nbox, | 794 | unsigned int nbox, |
809 | const drm_clip_rect_t __user * usr_boxes) | 795 | const drm_clip_rect_t *boxes) |
810 | { | 796 | { |
811 | unsigned int flags = cmd_header->clear0.flags, mask, value; | 797 | unsigned int flags = cmd_header->clear0.flags; |
812 | unsigned int clear_cmd; | 798 | unsigned int clear_cmd; |
813 | unsigned int i, nbufs; | 799 | unsigned int i, nbufs; |
814 | DMA_LOCALS; | 800 | DMA_LOCALS; |
@@ -816,9 +802,6 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv, | |||
816 | if (nbox == 0) | 802 | if (nbox == 0) |
817 | return 0; | 803 | return 0; |
818 | 804 | ||
819 | DRM_GET_USER_UNCHECKED(mask, &data->clear1.mask); | ||
820 | DRM_GET_USER_UNCHECKED(value, &data->clear1.value); | ||
821 | |||
822 | clear_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP | | 805 | clear_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP | |
823 | BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW; | 806 | BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW; |
824 | BCI_CMD_SET_ROP(clear_cmd, 0xCC); | 807 | BCI_CMD_SET_ROP(clear_cmd, 0xCC); |
@@ -828,21 +811,19 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv, | |||
828 | if (nbufs == 0) | 811 | if (nbufs == 0) |
829 | return 0; | 812 | return 0; |
830 | 813 | ||
831 | if (mask != 0xffffffff) { | 814 | if (data->clear1.mask != 0xffffffff) { |
832 | /* set mask */ | 815 | /* set mask */ |
833 | BEGIN_DMA(2); | 816 | BEGIN_DMA(2); |
834 | DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1); | 817 | DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1); |
835 | DMA_WRITE(mask); | 818 | DMA_WRITE(data->clear1.mask); |
836 | DMA_COMMIT(); | 819 | DMA_COMMIT(); |
837 | } | 820 | } |
838 | for (i = 0; i < nbox; ++i) { | 821 | for (i = 0; i < nbox; ++i) { |
839 | drm_clip_rect_t box; | ||
840 | unsigned int x, y, w, h; | 822 | unsigned int x, y, w, h; |
841 | unsigned int buf; | 823 | unsigned int buf; |
842 | DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box)); | 824 | x = boxes[i].x1, y = boxes[i].y1; |
843 | x = box.x1, y = box.y1; | 825 | w = boxes[i].x2 - boxes[i].x1; |
844 | w = box.x2 - box.x1; | 826 | h = boxes[i].y2 - boxes[i].y1; |
845 | h = box.y2 - box.y1; | ||
846 | BEGIN_DMA(nbufs * 6); | 827 | BEGIN_DMA(nbufs * 6); |
847 | for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) { | 828 | for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) { |
848 | if (!(flags & buf)) | 829 | if (!(flags & buf)) |
@@ -862,13 +843,13 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv, | |||
862 | DMA_WRITE(dev_priv->depth_bd); | 843 | DMA_WRITE(dev_priv->depth_bd); |
863 | break; | 844 | break; |
864 | } | 845 | } |
865 | DMA_WRITE(value); | 846 | DMA_WRITE(data->clear1.value); |
866 | DMA_WRITE(BCI_X_Y(x, y)); | 847 | DMA_WRITE(BCI_X_Y(x, y)); |
867 | DMA_WRITE(BCI_W_H(w, h)); | 848 | DMA_WRITE(BCI_W_H(w, h)); |
868 | } | 849 | } |
869 | DMA_COMMIT(); | 850 | DMA_COMMIT(); |
870 | } | 851 | } |
871 | if (mask != 0xffffffff) { | 852 | if (data->clear1.mask != 0xffffffff) { |
872 | /* reset mask */ | 853 | /* reset mask */ |
873 | BEGIN_DMA(2); | 854 | BEGIN_DMA(2); |
874 | DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1); | 855 | DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1); |
@@ -880,8 +861,7 @@ static int savage_dispatch_clear(drm_savage_private_t * dev_priv, | |||
880 | } | 861 | } |
881 | 862 | ||
882 | static int savage_dispatch_swap(drm_savage_private_t * dev_priv, | 863 | static int savage_dispatch_swap(drm_savage_private_t * dev_priv, |
883 | unsigned int nbox, | 864 | unsigned int nbox, const drm_clip_rect_t *boxes) |
884 | const drm_clip_rect_t __user * usr_boxes) | ||
885 | { | 865 | { |
886 | unsigned int swap_cmd; | 866 | unsigned int swap_cmd; |
887 | unsigned int i; | 867 | unsigned int i; |
@@ -895,16 +875,14 @@ static int savage_dispatch_swap(drm_savage_private_t * dev_priv, | |||
895 | BCI_CMD_SET_ROP(swap_cmd, 0xCC); | 875 | BCI_CMD_SET_ROP(swap_cmd, 0xCC); |
896 | 876 | ||
897 | for (i = 0; i < nbox; ++i) { | 877 | for (i = 0; i < nbox; ++i) { |
898 | drm_clip_rect_t box; | ||
899 | DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box)); | ||
900 | |||
901 | BEGIN_DMA(6); | 878 | BEGIN_DMA(6); |
902 | DMA_WRITE(swap_cmd); | 879 | DMA_WRITE(swap_cmd); |
903 | DMA_WRITE(dev_priv->back_offset); | 880 | DMA_WRITE(dev_priv->back_offset); |
904 | DMA_WRITE(dev_priv->back_bd); | 881 | DMA_WRITE(dev_priv->back_bd); |
905 | DMA_WRITE(BCI_X_Y(box.x1, box.y1)); | 882 | DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1)); |
906 | DMA_WRITE(BCI_X_Y(box.x1, box.y1)); | 883 | DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1)); |
907 | DMA_WRITE(BCI_W_H(box.x2 - box.x1, box.y2 - box.y1)); | 884 | DMA_WRITE(BCI_W_H(boxes[i].x2 - boxes[i].x1, |
885 | boxes[i].y2 - boxes[i].y1)); | ||
908 | DMA_COMMIT(); | 886 | DMA_COMMIT(); |
909 | } | 887 | } |
910 | 888 | ||
@@ -912,68 +890,52 @@ static int savage_dispatch_swap(drm_savage_private_t * dev_priv, | |||
912 | } | 890 | } |
913 | 891 | ||
914 | static int savage_dispatch_draw(drm_savage_private_t * dev_priv, | 892 | static int savage_dispatch_draw(drm_savage_private_t * dev_priv, |
915 | const drm_savage_cmd_header_t __user * start, | 893 | const drm_savage_cmd_header_t *start, |
916 | const drm_savage_cmd_header_t __user * end, | 894 | const drm_savage_cmd_header_t *end, |
917 | const drm_buf_t * dmabuf, | 895 | const drm_buf_t * dmabuf, |
918 | const unsigned int __user * usr_vtxbuf, | 896 | const unsigned int *vtxbuf, |
919 | unsigned int vb_size, unsigned int vb_stride, | 897 | unsigned int vb_size, unsigned int vb_stride, |
920 | unsigned int nbox, | 898 | unsigned int nbox, |
921 | const drm_clip_rect_t __user * usr_boxes) | 899 | const drm_clip_rect_t *boxes) |
922 | { | 900 | { |
923 | unsigned int i, j; | 901 | unsigned int i, j; |
924 | int ret; | 902 | int ret; |
925 | 903 | ||
926 | for (i = 0; i < nbox; ++i) { | 904 | for (i = 0; i < nbox; ++i) { |
927 | drm_clip_rect_t box; | 905 | const drm_savage_cmd_header_t *cmdbuf; |
928 | const drm_savage_cmd_header_t __user *usr_cmdbuf; | 906 | dev_priv->emit_clip_rect(dev_priv, &boxes[i]); |
929 | DRM_COPY_FROM_USER_UNCHECKED(&box, &usr_boxes[i], sizeof(box)); | ||
930 | dev_priv->emit_clip_rect(dev_priv, &box); | ||
931 | 907 | ||
932 | usr_cmdbuf = start; | 908 | cmdbuf = start; |
933 | while (usr_cmdbuf < end) { | 909 | while (cmdbuf < end) { |
934 | drm_savage_cmd_header_t cmd_header; | 910 | drm_savage_cmd_header_t cmd_header; |
935 | DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf, | 911 | cmd_header = *cmdbuf; |
936 | sizeof(cmd_header)); | 912 | cmdbuf++; |
937 | usr_cmdbuf++; | ||
938 | switch (cmd_header.cmd.cmd) { | 913 | switch (cmd_header.cmd.cmd) { |
939 | case SAVAGE_CMD_DMA_PRIM: | 914 | case SAVAGE_CMD_DMA_PRIM: |
940 | ret = | 915 | ret = savage_dispatch_dma_prim( |
941 | savage_dispatch_dma_prim(dev_priv, | 916 | dev_priv, &cmd_header, dmabuf); |
942 | &cmd_header, | ||
943 | dmabuf); | ||
944 | break; | 917 | break; |
945 | case SAVAGE_CMD_VB_PRIM: | 918 | case SAVAGE_CMD_VB_PRIM: |
946 | ret = | 919 | ret = savage_dispatch_vb_prim( |
947 | savage_dispatch_vb_prim(dev_priv, | 920 | dev_priv, &cmd_header, |
948 | &cmd_header, | 921 | vtxbuf, vb_size, vb_stride); |
949 | (const uint32_t | ||
950 | __user *) | ||
951 | usr_vtxbuf, vb_size, | ||
952 | vb_stride); | ||
953 | break; | 922 | break; |
954 | case SAVAGE_CMD_DMA_IDX: | 923 | case SAVAGE_CMD_DMA_IDX: |
955 | j = (cmd_header.idx.count + 3) / 4; | 924 | j = (cmd_header.idx.count + 3) / 4; |
956 | /* j was check in savage_bci_cmdbuf */ | 925 | /* j was check in savage_bci_cmdbuf */ |
957 | ret = | 926 | ret = savage_dispatch_dma_idx(dev_priv, |
958 | savage_dispatch_dma_idx(dev_priv, | 927 | &cmd_header, (const uint16_t *)cmdbuf, |
959 | &cmd_header, | 928 | dmabuf); |
960 | (const uint16_t | 929 | cmdbuf += j; |
961 | __user *) | ||
962 | usr_cmdbuf, dmabuf); | ||
963 | usr_cmdbuf += j; | ||
964 | break; | 930 | break; |
965 | case SAVAGE_CMD_VB_IDX: | 931 | case SAVAGE_CMD_VB_IDX: |
966 | j = (cmd_header.idx.count + 3) / 4; | 932 | j = (cmd_header.idx.count + 3) / 4; |
967 | /* j was check in savage_bci_cmdbuf */ | 933 | /* j was check in savage_bci_cmdbuf */ |
968 | ret = | 934 | ret = savage_dispatch_vb_idx(dev_priv, |
969 | savage_dispatch_vb_idx(dev_priv, | 935 | &cmd_header, (const uint16_t *)cmdbuf, |
970 | &cmd_header, | 936 | (const uint32_t *)vtxbuf, vb_size, |
971 | (const uint16_t | 937 | vb_stride); |
972 | __user *)usr_cmdbuf, | 938 | cmdbuf += j; |
973 | (const uint32_t | ||
974 | __user *)usr_vtxbuf, | ||
975 | vb_size, vb_stride); | ||
976 | usr_cmdbuf += j; | ||
977 | break; | 939 | break; |
978 | default: | 940 | default: |
979 | /* What's the best return code? EFAULT? */ | 941 | /* What's the best return code? EFAULT? */ |
@@ -998,10 +960,10 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) | |||
998 | drm_device_dma_t *dma = dev->dma; | 960 | drm_device_dma_t *dma = dev->dma; |
999 | drm_buf_t *dmabuf; | 961 | drm_buf_t *dmabuf; |
1000 | drm_savage_cmdbuf_t cmdbuf; | 962 | drm_savage_cmdbuf_t cmdbuf; |
1001 | drm_savage_cmd_header_t __user *usr_cmdbuf; | 963 | drm_savage_cmd_header_t *kcmd_addr = NULL; |
1002 | drm_savage_cmd_header_t __user *first_draw_cmd; | 964 | drm_savage_cmd_header_t *first_draw_cmd; |
1003 | unsigned int __user *usr_vtxbuf; | 965 | unsigned int *kvb_addr = NULL; |
1004 | drm_clip_rect_t __user *usr_boxes; | 966 | drm_clip_rect_t *kbox_addr = NULL; |
1005 | unsigned int i, j; | 967 | unsigned int i, j; |
1006 | int ret = 0; | 968 | int ret = 0; |
1007 | 969 | ||
@@ -1024,15 +986,53 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) | |||
1024 | dmabuf = NULL; | 986 | dmabuf = NULL; |
1025 | } | 987 | } |
1026 | 988 | ||
1027 | usr_cmdbuf = (drm_savage_cmd_header_t __user *) cmdbuf.cmd_addr; | 989 | /* Copy the user buffers into kernel temporary areas. This hasn't been |
1028 | usr_vtxbuf = (unsigned int __user *)cmdbuf.vb_addr; | 990 | * a performance loss compared to VERIFYAREA_READ/ |
1029 | usr_boxes = (drm_clip_rect_t __user *) cmdbuf.box_addr; | 991 | * COPY_FROM_USER_UNCHECKED when done in other drivers, and is correct |
1030 | if ((cmdbuf.size && DRM_VERIFYAREA_READ(usr_cmdbuf, cmdbuf.size * 8)) || | 992 | * for locking on FreeBSD. |
1031 | (cmdbuf.vb_size && DRM_VERIFYAREA_READ(usr_vtxbuf, cmdbuf.vb_size)) | 993 | */ |
1032 | || (cmdbuf.nbox | 994 | if (cmdbuf.size) { |
1033 | && DRM_VERIFYAREA_READ(usr_boxes, | 995 | kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER); |
1034 | cmdbuf.nbox * sizeof(drm_clip_rect_t)))) | 996 | if (kcmd_addr == NULL) |
1035 | return DRM_ERR(EFAULT); | 997 | return ENOMEM; |
998 | |||
999 | if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr, | ||
1000 | cmdbuf.size * 8)) | ||
1001 | { | ||
1002 | drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER); | ||
1003 | return DRM_ERR(EFAULT); | ||
1004 | } | ||
1005 | cmdbuf.cmd_addr = kcmd_addr; | ||
1006 | } | ||
1007 | if (cmdbuf.vb_size) { | ||
1008 | kvb_addr = drm_alloc(cmdbuf.vb_size, DRM_MEM_DRIVER); | ||
1009 | if (kvb_addr == NULL) { | ||
1010 | ret = DRM_ERR(ENOMEM); | ||
1011 | goto done; | ||
1012 | } | ||
1013 | |||
1014 | if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf.vb_addr, | ||
1015 | cmdbuf.vb_size)) { | ||
1016 | ret = DRM_ERR(EFAULT); | ||
1017 | goto done; | ||
1018 | } | ||
1019 | cmdbuf.vb_addr = kvb_addr; | ||
1020 | } | ||
1021 | if (cmdbuf.nbox) { | ||
1022 | kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(drm_clip_rect_t), | ||
1023 | DRM_MEM_DRIVER); | ||
1024 | if (kbox_addr == NULL) { | ||
1025 | ret = DRM_ERR(ENOMEM); | ||
1026 | goto done; | ||
1027 | } | ||
1028 | |||
1029 | if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf.box_addr, | ||
1030 | cmdbuf.nbox * sizeof(drm_clip_rect_t))) { | ||
1031 | ret = DRM_ERR(EFAULT); | ||
1032 | goto done; | ||
1033 | } | ||
1034 | cmdbuf.box_addr = kbox_addr; | ||
1035 | } | ||
1036 | 1036 | ||
1037 | /* Make sure writes to DMA buffers are finished before sending | 1037 | /* Make sure writes to DMA buffers are finished before sending |
1038 | * DMA commands to the graphics hardware. */ | 1038 | * DMA commands to the graphics hardware. */ |
@@ -1046,9 +1046,8 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) | |||
1046 | first_draw_cmd = NULL; | 1046 | first_draw_cmd = NULL; |
1047 | while (i < cmdbuf.size) { | 1047 | while (i < cmdbuf.size) { |
1048 | drm_savage_cmd_header_t cmd_header; | 1048 | drm_savage_cmd_header_t cmd_header; |
1049 | DRM_COPY_FROM_USER_UNCHECKED(&cmd_header, usr_cmdbuf, | 1049 | cmd_header = *(drm_savage_cmd_header_t *)cmdbuf.cmd_addr; |
1050 | sizeof(cmd_header)); | 1050 | cmdbuf.cmd_addr++; |
1051 | usr_cmdbuf++; | ||
1052 | i++; | 1051 | i++; |
1053 | 1052 | ||
1054 | /* Group drawing commands with same state to minimize | 1053 | /* Group drawing commands with same state to minimize |
@@ -1068,21 +1067,18 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) | |||
1068 | case SAVAGE_CMD_DMA_PRIM: | 1067 | case SAVAGE_CMD_DMA_PRIM: |
1069 | case SAVAGE_CMD_VB_PRIM: | 1068 | case SAVAGE_CMD_VB_PRIM: |
1070 | if (!first_draw_cmd) | 1069 | if (!first_draw_cmd) |
1071 | first_draw_cmd = usr_cmdbuf - 1; | 1070 | first_draw_cmd = cmdbuf.cmd_addr - 1; |
1072 | usr_cmdbuf += j; | 1071 | cmdbuf.cmd_addr += j; |
1073 | i += j; | 1072 | i += j; |
1074 | break; | 1073 | break; |
1075 | default: | 1074 | default: |
1076 | if (first_draw_cmd) { | 1075 | if (first_draw_cmd) { |
1077 | ret = | 1076 | ret = savage_dispatch_draw( |
1078 | savage_dispatch_draw(dev_priv, | 1077 | dev_priv, first_draw_cmd, |
1079 | first_draw_cmd, | 1078 | cmdbuf.cmd_addr - 1, |
1080 | usr_cmdbuf - 1, dmabuf, | 1079 | dmabuf, cmdbuf.vb_addr, cmdbuf.vb_size, |
1081 | usr_vtxbuf, | 1080 | cmdbuf.vb_stride, |
1082 | cmdbuf.vb_size, | 1081 | cmdbuf.nbox, cmdbuf.box_addr); |
1083 | cmdbuf.vb_stride, | ||
1084 | cmdbuf.nbox, | ||
1085 | usr_boxes); | ||
1086 | if (ret != 0) | 1082 | if (ret != 0) |
1087 | return ret; | 1083 | return ret; |
1088 | first_draw_cmd = NULL; | 1084 | first_draw_cmd = NULL; |
@@ -1098,12 +1094,12 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) | |||
1098 | DRM_ERROR("command SAVAGE_CMD_STATE extends " | 1094 | DRM_ERROR("command SAVAGE_CMD_STATE extends " |
1099 | "beyond end of command buffer\n"); | 1095 | "beyond end of command buffer\n"); |
1100 | DMA_FLUSH(); | 1096 | DMA_FLUSH(); |
1101 | return DRM_ERR(EINVAL); | 1097 | ret = DRM_ERR(EINVAL); |
1098 | goto done; | ||
1102 | } | 1099 | } |
1103 | ret = savage_dispatch_state(dev_priv, &cmd_header, | 1100 | ret = savage_dispatch_state(dev_priv, &cmd_header, |
1104 | (uint32_t __user *) | 1101 | (const uint32_t *)cmdbuf.cmd_addr); |
1105 | usr_cmdbuf); | 1102 | cmdbuf.cmd_addr += j; |
1106 | usr_cmdbuf += j; | ||
1107 | i += j; | 1103 | i += j; |
1108 | break; | 1104 | break; |
1109 | case SAVAGE_CMD_CLEAR: | 1105 | case SAVAGE_CMD_CLEAR: |
@@ -1111,39 +1107,40 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) | |||
1111 | DRM_ERROR("command SAVAGE_CMD_CLEAR extends " | 1107 | DRM_ERROR("command SAVAGE_CMD_CLEAR extends " |
1112 | "beyond end of command buffer\n"); | 1108 | "beyond end of command buffer\n"); |
1113 | DMA_FLUSH(); | 1109 | DMA_FLUSH(); |
1114 | return DRM_ERR(EINVAL); | 1110 | ret = DRM_ERR(EINVAL); |
1111 | goto done; | ||
1115 | } | 1112 | } |
1116 | ret = savage_dispatch_clear(dev_priv, &cmd_header, | 1113 | ret = savage_dispatch_clear(dev_priv, &cmd_header, |
1117 | usr_cmdbuf, | 1114 | cmdbuf.cmd_addr, |
1118 | cmdbuf.nbox, usr_boxes); | 1115 | cmdbuf.nbox, cmdbuf.box_addr); |
1119 | usr_cmdbuf++; | 1116 | cmdbuf.cmd_addr++; |
1120 | i++; | 1117 | i++; |
1121 | break; | 1118 | break; |
1122 | case SAVAGE_CMD_SWAP: | 1119 | case SAVAGE_CMD_SWAP: |
1123 | ret = savage_dispatch_swap(dev_priv, | 1120 | ret = savage_dispatch_swap(dev_priv, cmdbuf.nbox, |
1124 | cmdbuf.nbox, usr_boxes); | 1121 | cmdbuf.box_addr); |
1125 | break; | 1122 | break; |
1126 | default: | 1123 | default: |
1127 | DRM_ERROR("invalid command 0x%x\n", cmd_header.cmd.cmd); | 1124 | DRM_ERROR("invalid command 0x%x\n", cmd_header.cmd.cmd); |
1128 | DMA_FLUSH(); | 1125 | DMA_FLUSH(); |
1129 | return DRM_ERR(EINVAL); | 1126 | ret = DRM_ERR(EINVAL); |
1127 | goto done; | ||
1130 | } | 1128 | } |
1131 | 1129 | ||
1132 | if (ret != 0) { | 1130 | if (ret != 0) { |
1133 | DMA_FLUSH(); | 1131 | DMA_FLUSH(); |
1134 | return ret; | 1132 | goto done; |
1135 | } | 1133 | } |
1136 | } | 1134 | } |
1137 | 1135 | ||
1138 | if (first_draw_cmd) { | 1136 | if (first_draw_cmd) { |
1139 | ret = | 1137 | ret = savage_dispatch_draw ( |
1140 | savage_dispatch_draw(dev_priv, first_draw_cmd, usr_cmdbuf, | 1138 | dev_priv, first_draw_cmd, cmdbuf.cmd_addr, dmabuf, |
1141 | dmabuf, usr_vtxbuf, cmdbuf.vb_size, | 1139 | cmdbuf.vb_addr, cmdbuf.vb_size, cmdbuf.vb_stride, |
1142 | cmdbuf.vb_stride, cmdbuf.nbox, | 1140 | cmdbuf.nbox, cmdbuf.box_addr); |
1143 | usr_boxes); | ||
1144 | if (ret != 0) { | 1141 | if (ret != 0) { |
1145 | DMA_FLUSH(); | 1142 | DMA_FLUSH(); |
1146 | return ret; | 1143 | goto done; |
1147 | } | 1144 | } |
1148 | } | 1145 | } |
1149 | 1146 | ||
@@ -1157,5 +1154,12 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) | |||
1157 | savage_freelist_put(dev, dmabuf); | 1154 | savage_freelist_put(dev, dmabuf); |
1158 | } | 1155 | } |
1159 | 1156 | ||
1160 | return 0; | 1157 | done: |
1158 | /* If we didn't need to allocate them, these'll be NULL */ | ||
1159 | drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER); | ||
1160 | drm_free(kvb_addr, cmdbuf.vb_size, DRM_MEM_DRIVER); | ||
1161 | drm_free(kbox_addr, cmdbuf.nbox * sizeof(drm_clip_rect_t), | ||
1162 | DRM_MEM_DRIVER); | ||
1163 | |||
1164 | return ret; | ||
1161 | } | 1165 | } |
diff --git a/drivers/char/drm/sis_drm.h b/drivers/char/drm/sis_drm.h index 8f273da76ddb..30f7b3827466 100644 --- a/drivers/char/drm/sis_drm.h +++ b/drivers/char/drm/sis_drm.h | |||
@@ -1,3 +1,28 @@ | |||
1 | /* sis_drv.h -- Private header for sis driver -*- linux-c -*- */ | ||
2 | /* | ||
3 | * Copyright 2005 Eric Anholt | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
7 | * copy of this software and associated documentation files (the "Software"), | ||
8 | * to deal in the Software without restriction, including without limitation | ||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
11 | * Software is furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice (including the next | ||
14 | * paragraph) shall be included in all copies or substantial portions of the | ||
15 | * Software. | ||
16 | * | ||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
23 | * SOFTWARE. | ||
24 | * | ||
25 | */ | ||
1 | 26 | ||
2 | #ifndef __SIS_DRM_H__ | 27 | #ifndef __SIS_DRM_H__ |
3 | #define __SIS_DRM_H__ | 28 | #define __SIS_DRM_H__ |
diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c index 3cef10643a8f..6f6d7d613ede 100644 --- a/drivers/char/drm/sis_drv.c +++ b/drivers/char/drm/sis_drv.c | |||
@@ -32,31 +32,6 @@ | |||
32 | 32 | ||
33 | #include "drm_pciids.h" | 33 | #include "drm_pciids.h" |
34 | 34 | ||
35 | static int postinit(struct drm_device *dev, unsigned long flags) | ||
36 | { | ||
37 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n", | ||
38 | DRIVER_NAME, | ||
39 | DRIVER_MAJOR, | ||
40 | DRIVER_MINOR, | ||
41 | DRIVER_PATCHLEVEL, | ||
42 | DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev) | ||
43 | ); | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static int version(drm_version_t * version) | ||
48 | { | ||
49 | int len; | ||
50 | |||
51 | version->version_major = DRIVER_MAJOR; | ||
52 | version->version_minor = DRIVER_MINOR; | ||
53 | version->version_patchlevel = DRIVER_PATCHLEVEL; | ||
54 | DRM_COPY(version->name, DRIVER_NAME); | ||
55 | DRM_COPY(version->date, DRIVER_DATE); | ||
56 | DRM_COPY(version->desc, DRIVER_DESC); | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static struct pci_device_id pciidlist[] = { | 35 | static struct pci_device_id pciidlist[] = { |
61 | sisdrv_PCI_IDS | 36 | sisdrv_PCI_IDS |
62 | }; | 37 | }; |
@@ -68,8 +43,6 @@ static struct drm_driver driver = { | |||
68 | .reclaim_buffers = drm_core_reclaim_buffers, | 43 | .reclaim_buffers = drm_core_reclaim_buffers, |
69 | .get_map_ofs = drm_core_get_map_ofs, | 44 | .get_map_ofs = drm_core_get_map_ofs, |
70 | .get_reg_ofs = drm_core_get_reg_ofs, | 45 | .get_reg_ofs = drm_core_get_reg_ofs, |
71 | .postinit = postinit, | ||
72 | .version = version, | ||
73 | .ioctls = sis_ioctls, | 46 | .ioctls = sis_ioctls, |
74 | .fops = { | 47 | .fops = { |
75 | .owner = THIS_MODULE, | 48 | .owner = THIS_MODULE, |
@@ -79,11 +52,18 @@ static struct drm_driver driver = { | |||
79 | .mmap = drm_mmap, | 52 | .mmap = drm_mmap, |
80 | .poll = drm_poll, | 53 | .poll = drm_poll, |
81 | .fasync = drm_fasync, | 54 | .fasync = drm_fasync, |
82 | }, | 55 | }, |
83 | .pci_driver = { | 56 | .pci_driver = { |
84 | .name = DRIVER_NAME, | 57 | .name = DRIVER_NAME, |
85 | .id_table = pciidlist, | 58 | .id_table = pciidlist, |
86 | } | 59 | }, |
60 | |||
61 | .name = DRIVER_NAME, | ||
62 | .desc = DRIVER_DESC, | ||
63 | .date = DRIVER_DATE, | ||
64 | .major = DRIVER_MAJOR, | ||
65 | .minor = DRIVER_MINOR, | ||
66 | .patchlevel = DRIVER_PATCHLEVEL, | ||
87 | }; | 67 | }; |
88 | 68 | ||
89 | static int __init sis_init(void) | 69 | static int __init sis_init(void) |
diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h index b1fddad83a93..e218e5269503 100644 --- a/drivers/char/drm/sis_drv.h +++ b/drivers/char/drm/sis_drv.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* sis_drv.h -- Private header for sis driver -*- linux-c -*- | 1 | /* sis_drv.h -- Private header for sis driver -*- linux-c -*- */ |
2 | * | 2 | /* |
3 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. | 3 | * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. |
4 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | 4 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
5 | * All rights reserved. | 5 | * All rights reserved. |
diff --git a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h index da850b4f5440..94f2b4728b63 100644 --- a/drivers/char/drm/sis_ds.h +++ b/drivers/char/drm/sis_ds.h | |||
@@ -1,6 +1,7 @@ | |||
1 | /* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*- | 1 | /* sis_ds.h -- Private header for Direct Rendering Manager -*- linux-c -*- |
2 | * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw | 2 | * Created: Mon Jan 4 10:05:05 1999 by sclin@sis.com.tw |
3 | * | 3 | */ |
4 | /* | ||
4 | * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. | 5 | * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan. |
5 | * All rights reserved. | 6 | * All rights reserved. |
6 | * | 7 | * |
@@ -35,7 +36,7 @@ | |||
35 | 36 | ||
36 | #define SET_SIZE 5000 | 37 | #define SET_SIZE 5000 |
37 | 38 | ||
38 | typedef unsigned int ITEM_TYPE; | 39 | typedef unsigned long ITEM_TYPE; |
39 | 40 | ||
40 | typedef struct { | 41 | typedef struct { |
41 | ITEM_TYPE val; | 42 | ITEM_TYPE val; |
diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c index a8529728fa63..6774d2fe3452 100644 --- a/drivers/char/drm/sis_mm.c +++ b/drivers/char/drm/sis_mm.c | |||
@@ -86,7 +86,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS) | |||
86 | { | 86 | { |
87 | drm_sis_mem_t fb; | 87 | drm_sis_mem_t fb; |
88 | struct sis_memreq req; | 88 | struct sis_memreq req; |
89 | drm_sis_mem_t __user *argp = (void __user *)data; | 89 | drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data; |
90 | int retval = 0; | 90 | int retval = 0; |
91 | 91 | ||
92 | DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb)); | 92 | DRM_COPY_FROM_USER_IOCTL(fb, argp, sizeof(fb)); |
@@ -110,7 +110,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS) | |||
110 | 110 | ||
111 | DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); | 111 | DRM_COPY_TO_USER_IOCTL(argp, fb, sizeof(fb)); |
112 | 112 | ||
113 | DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size, req.offset); | 113 | DRM_DEBUG("alloc fb, size = %d, offset = %ld\n", fb.size, req.offset); |
114 | 114 | ||
115 | return retval; | 115 | return retval; |
116 | } | 116 | } |
@@ -127,9 +127,9 @@ static int sis_fb_free(DRM_IOCTL_ARGS) | |||
127 | 127 | ||
128 | if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) | 128 | if (!del_alloc_set(fb.context, VIDEO_TYPE, fb.free)) |
129 | retval = DRM_ERR(EINVAL); | 129 | retval = DRM_ERR(EINVAL); |
130 | sis_free((u32) fb.free); | 130 | sis_free(fb.free); |
131 | 131 | ||
132 | DRM_DEBUG("free fb, offset = %lu\n", fb.free); | 132 | DRM_DEBUG("free fb, offset = 0x%lx\n", fb.free); |
133 | 133 | ||
134 | return retval; | 134 | return retval; |
135 | } | 135 | } |
@@ -176,7 +176,7 @@ static int sis_fb_alloc(DRM_IOCTL_ARGS) | |||
176 | { | 176 | { |
177 | DRM_DEVICE; | 177 | DRM_DEVICE; |
178 | drm_sis_private_t *dev_priv = dev->dev_private; | 178 | drm_sis_private_t *dev_priv = dev->dev_private; |
179 | drm_sis_mem_t __user *argp = (void __user *)data; | 179 | drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data; |
180 | drm_sis_mem_t fb; | 180 | drm_sis_mem_t fb; |
181 | PMemBlock block; | 181 | PMemBlock block; |
182 | int retval = 0; | 182 | int retval = 0; |
@@ -267,7 +267,7 @@ static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS) | |||
267 | { | 267 | { |
268 | DRM_DEVICE; | 268 | DRM_DEVICE; |
269 | drm_sis_private_t *dev_priv = dev->dev_private; | 269 | drm_sis_private_t *dev_priv = dev->dev_private; |
270 | drm_sis_mem_t __user *argp = (void __user *)data; | 270 | drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *)data; |
271 | drm_sis_mem_t agp; | 271 | drm_sis_mem_t agp; |
272 | PMemBlock block; | 272 | PMemBlock block; |
273 | int retval = 0; | 273 | int retval = 0; |
@@ -367,7 +367,7 @@ int sis_final_context(struct drm_device *dev, int context) | |||
367 | 367 | ||
368 | if (i < MAX_CONTEXT) { | 368 | if (i < MAX_CONTEXT) { |
369 | set_t *set; | 369 | set_t *set; |
370 | unsigned int item; | 370 | ITEM_TYPE item; |
371 | int retval; | 371 | int retval; |
372 | 372 | ||
373 | DRM_DEBUG("find socket %d, context = %d\n", i, context); | 373 | DRM_DEBUG("find socket %d, context = %d\n", i, context); |
@@ -376,7 +376,7 @@ int sis_final_context(struct drm_device *dev, int context) | |||
376 | set = global_ppriv[i].sets[0]; | 376 | set = global_ppriv[i].sets[0]; |
377 | retval = setFirst(set, &item); | 377 | retval = setFirst(set, &item); |
378 | while (retval) { | 378 | while (retval) { |
379 | DRM_DEBUG("free video memory 0x%x\n", item); | 379 | DRM_DEBUG("free video memory 0x%lx\n", item); |
380 | #if defined(__linux__) && defined(CONFIG_FB_SIS) | 380 | #if defined(__linux__) && defined(CONFIG_FB_SIS) |
381 | sis_free(item); | 381 | sis_free(item); |
382 | #else | 382 | #else |
@@ -390,7 +390,7 @@ int sis_final_context(struct drm_device *dev, int context) | |||
390 | set = global_ppriv[i].sets[1]; | 390 | set = global_ppriv[i].sets[1]; |
391 | retval = setFirst(set, &item); | 391 | retval = setFirst(set, &item); |
392 | while (retval) { | 392 | while (retval) { |
393 | DRM_DEBUG("free agp memory 0x%x\n", item); | 393 | DRM_DEBUG("free agp memory 0x%lx\n", item); |
394 | mmFreeMem((PMemBlock) item); | 394 | mmFreeMem((PMemBlock) item); |
395 | retval = setNext(set, &item); | 395 | retval = setNext(set, &item); |
396 | } | 396 | } |
@@ -403,12 +403,12 @@ int sis_final_context(struct drm_device *dev, int context) | |||
403 | } | 403 | } |
404 | 404 | ||
405 | drm_ioctl_desc_t sis_ioctls[] = { | 405 | drm_ioctl_desc_t sis_ioctls[] = { |
406 | [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, 1, 0}, | 406 | [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH}, |
407 | [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, 1, 0}, | 407 | [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_fb_free, DRM_AUTH}, |
408 | [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, 1, 1}, | 408 | [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = {sis_ioctl_agp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, |
409 | [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, 1, 0}, | 409 | [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH}, |
410 | [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, 1, 0}, | 410 | [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_ioctl_agp_free, DRM_AUTH}, |
411 | [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, 1, 1} | 411 | [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = {sis_fb_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY} |
412 | }; | 412 | }; |
413 | 413 | ||
414 | int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls); | 414 | int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls); |
diff --git a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c index c275cbb6e9ce..baa4416032a8 100644 --- a/drivers/char/drm/tdfx_drv.c +++ b/drivers/char/drm/tdfx_drv.c | |||
@@ -36,31 +36,6 @@ | |||
36 | 36 | ||
37 | #include "drm_pciids.h" | 37 | #include "drm_pciids.h" |
38 | 38 | ||
39 | static int postinit(struct drm_device *dev, unsigned long flags) | ||
40 | { | ||
41 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n", | ||
42 | DRIVER_NAME, | ||
43 | DRIVER_MAJOR, | ||
44 | DRIVER_MINOR, | ||
45 | DRIVER_PATCHLEVEL, | ||
46 | DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev) | ||
47 | ); | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | static int version(drm_version_t * version) | ||
52 | { | ||
53 | int len; | ||
54 | |||
55 | version->version_major = DRIVER_MAJOR; | ||
56 | version->version_minor = DRIVER_MINOR; | ||
57 | version->version_patchlevel = DRIVER_PATCHLEVEL; | ||
58 | DRM_COPY(version->name, DRIVER_NAME); | ||
59 | DRM_COPY(version->date, DRIVER_DATE); | ||
60 | DRM_COPY(version->desc, DRIVER_DESC); | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static struct pci_device_id pciidlist[] = { | 39 | static struct pci_device_id pciidlist[] = { |
65 | tdfx_PCI_IDS | 40 | tdfx_PCI_IDS |
66 | }; | 41 | }; |
@@ -70,8 +45,6 @@ static struct drm_driver driver = { | |||
70 | .reclaim_buffers = drm_core_reclaim_buffers, | 45 | .reclaim_buffers = drm_core_reclaim_buffers, |
71 | .get_map_ofs = drm_core_get_map_ofs, | 46 | .get_map_ofs = drm_core_get_map_ofs, |
72 | .get_reg_ofs = drm_core_get_reg_ofs, | 47 | .get_reg_ofs = drm_core_get_reg_ofs, |
73 | .postinit = postinit, | ||
74 | .version = version, | ||
75 | .fops = { | 48 | .fops = { |
76 | .owner = THIS_MODULE, | 49 | .owner = THIS_MODULE, |
77 | .open = drm_open, | 50 | .open = drm_open, |
@@ -80,11 +53,18 @@ static struct drm_driver driver = { | |||
80 | .mmap = drm_mmap, | 53 | .mmap = drm_mmap, |
81 | .poll = drm_poll, | 54 | .poll = drm_poll, |
82 | .fasync = drm_fasync, | 55 | .fasync = drm_fasync, |
83 | }, | 56 | }, |
84 | .pci_driver = { | 57 | .pci_driver = { |
85 | .name = DRIVER_NAME, | 58 | .name = DRIVER_NAME, |
86 | .id_table = pciidlist, | 59 | .id_table = pciidlist, |
87 | } | 60 | }, |
61 | |||
62 | .name = DRIVER_NAME, | ||
63 | .desc = DRIVER_DESC, | ||
64 | .date = DRIVER_DATE, | ||
65 | .major = DRIVER_MAJOR, | ||
66 | .minor = DRIVER_MINOR, | ||
67 | .patchlevel = DRIVER_PATCHLEVEL, | ||
88 | }; | 68 | }; |
89 | 69 | ||
90 | static int __init tdfx_init(void) | 70 | static int __init tdfx_init(void) |
diff --git a/drivers/char/drm/tdfx_drv.h b/drivers/char/drm/tdfx_drv.h index a582a3db4c75..84204ec1b046 100644 --- a/drivers/char/drm/tdfx_drv.h +++ b/drivers/char/drm/tdfx_drv.h | |||
@@ -1,6 +1,7 @@ | |||
1 | /* tdfx.h -- 3dfx DRM template customization -*- linux-c -*- | 1 | /* tdfx.h -- 3dfx DRM template customization -*- linux-c -*- |
2 | * Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com | 2 | * Created: Wed Feb 14 12:32:32 2001 by gareth@valinux.com |
3 | * | 3 | */ |
4 | /* | ||
4 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. | 5 | * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. |
5 | * All Rights Reserved. | 6 | * All Rights Reserved. |
6 | * | 7 | * |
@@ -30,10 +31,6 @@ | |||
30 | #ifndef __TDFX_H__ | 31 | #ifndef __TDFX_H__ |
31 | #define __TDFX_H__ | 32 | #define __TDFX_H__ |
32 | 33 | ||
33 | /* This remains constant for all DRM template files. | ||
34 | */ | ||
35 | #define DRM(x) tdfx_##x | ||
36 | |||
37 | /* General customization: | 34 | /* General customization: |
38 | */ | 35 | */ |
39 | 36 | ||
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c index d4b1766608b0..593c0b8f650a 100644 --- a/drivers/char/drm/via_dma.c +++ b/drivers/char/drm/via_dma.c | |||
@@ -213,7 +213,9 @@ static int via_initialize(drm_device_t * dev, | |||
213 | dev_priv->dma_wrap = init->size; | 213 | dev_priv->dma_wrap = init->size; |
214 | dev_priv->dma_offset = init->offset; | 214 | dev_priv->dma_offset = init->offset; |
215 | dev_priv->last_pause_ptr = NULL; | 215 | dev_priv->last_pause_ptr = NULL; |
216 | dev_priv->hw_addr_ptr = dev_priv->mmio->handle + init->reg_pause_addr; | 216 | dev_priv->hw_addr_ptr = |
217 | (volatile uint32_t *)((char *)dev_priv->mmio->handle + | ||
218 | init->reg_pause_addr); | ||
217 | 219 | ||
218 | via_cmdbuf_start(dev_priv); | 220 | via_cmdbuf_start(dev_priv); |
219 | 221 | ||
@@ -232,13 +234,13 @@ int via_dma_init(DRM_IOCTL_ARGS) | |||
232 | 234 | ||
233 | switch (init.func) { | 235 | switch (init.func) { |
234 | case VIA_INIT_DMA: | 236 | case VIA_INIT_DMA: |
235 | if (!capable(CAP_SYS_ADMIN)) | 237 | if (!DRM_SUSER(DRM_CURPROC)) |
236 | retcode = DRM_ERR(EPERM); | 238 | retcode = DRM_ERR(EPERM); |
237 | else | 239 | else |
238 | retcode = via_initialize(dev, dev_priv, &init); | 240 | retcode = via_initialize(dev, dev_priv, &init); |
239 | break; | 241 | break; |
240 | case VIA_CLEANUP_DMA: | 242 | case VIA_CLEANUP_DMA: |
241 | if (!capable(CAP_SYS_ADMIN)) | 243 | if (!DRM_SUSER(DRM_CURPROC)) |
242 | retcode = DRM_ERR(EPERM); | 244 | retcode = DRM_ERR(EPERM); |
243 | else | 245 | else |
244 | retcode = via_dma_cleanup(dev); | 246 | retcode = via_dma_cleanup(dev); |
@@ -349,9 +351,6 @@ int via_cmdbuffer(DRM_IOCTL_ARGS) | |||
349 | return 0; | 351 | return 0; |
350 | } | 352 | } |
351 | 353 | ||
352 | extern int | ||
353 | via_parse_command_stream(drm_device_t * dev, const uint32_t * buf, | ||
354 | unsigned int size); | ||
355 | static int via_dispatch_pci_cmdbuffer(drm_device_t * dev, | 354 | static int via_dispatch_pci_cmdbuffer(drm_device_t * dev, |
356 | drm_via_cmdbuffer_t * cmd) | 355 | drm_via_cmdbuffer_t * cmd) |
357 | { | 356 | { |
@@ -450,9 +449,9 @@ static int via_hook_segment(drm_via_private_t * dev_priv, | |||
450 | if ((count <= 8) && (count >= 0)) { | 449 | if ((count <= 8) && (count >= 0)) { |
451 | uint32_t rgtr, ptr; | 450 | uint32_t rgtr, ptr; |
452 | rgtr = *(dev_priv->hw_addr_ptr); | 451 | rgtr = *(dev_priv->hw_addr_ptr); |
453 | ptr = ((char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) + | 452 | ptr = ((volatile char *)dev_priv->last_pause_ptr - |
454 | dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4 - | 453 | dev_priv->dma_ptr) + dev_priv->dma_offset + |
455 | CMDBUF_ALIGNMENT_SIZE; | 454 | (uint32_t) dev_priv->agpAddr + 4 - CMDBUF_ALIGNMENT_SIZE; |
456 | if (rgtr <= ptr) { | 455 | if (rgtr <= ptr) { |
457 | DRM_ERROR | 456 | DRM_ERROR |
458 | ("Command regulator\npaused at count %d, address %x, " | 457 | ("Command regulator\npaused at count %d, address %x, " |
@@ -472,7 +471,7 @@ static int via_hook_segment(drm_via_private_t * dev_priv, | |||
472 | && count--) ; | 471 | && count--) ; |
473 | 472 | ||
474 | rgtr = *(dev_priv->hw_addr_ptr); | 473 | rgtr = *(dev_priv->hw_addr_ptr); |
475 | ptr = ((char *)paused_at - dev_priv->dma_ptr) + | 474 | ptr = ((volatile char *)paused_at - dev_priv->dma_ptr) + |
476 | dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; | 475 | dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4; |
477 | 476 | ||
478 | ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ? | 477 | ptr_low = (ptr > 3 * CMDBUF_ALIGNMENT_SIZE) ? |
@@ -724,3 +723,22 @@ int via_cmdbuf_size(DRM_IOCTL_ARGS) | |||
724 | sizeof(d_siz)); | 723 | sizeof(d_siz)); |
725 | return ret; | 724 | return ret; |
726 | } | 725 | } |
726 | |||
727 | drm_ioctl_desc_t via_ioctls[] = { | ||
728 | [DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, DRM_AUTH}, | ||
729 | [DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, DRM_AUTH}, | ||
730 | [DRM_IOCTL_NR(DRM_VIA_AGP_INIT)] = {via_agp_init, DRM_AUTH|DRM_MASTER}, | ||
731 | [DRM_IOCTL_NR(DRM_VIA_FB_INIT)] = {via_fb_init, DRM_AUTH|DRM_MASTER}, | ||
732 | [DRM_IOCTL_NR(DRM_VIA_MAP_INIT)] = {via_map_init, DRM_AUTH|DRM_MASTER}, | ||
733 | [DRM_IOCTL_NR(DRM_VIA_DEC_FUTEX)] = {via_decoder_futex, DRM_AUTH}, | ||
734 | [DRM_IOCTL_NR(DRM_VIA_DMA_INIT)] = {via_dma_init, DRM_AUTH}, | ||
735 | [DRM_IOCTL_NR(DRM_VIA_CMDBUFFER)] = {via_cmdbuffer, DRM_AUTH}, | ||
736 | [DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, DRM_AUTH}, | ||
737 | [DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, DRM_AUTH}, | ||
738 | [DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, DRM_AUTH}, | ||
739 | [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, DRM_AUTH}, | ||
740 | [DRM_IOCTL_NR(DRM_VIA_DMA_BLIT)] = {via_dma_blit, DRM_AUTH}, | ||
741 | [DRM_IOCTL_NR(DRM_VIA_BLIT_SYNC)] = {via_dma_blit_sync, DRM_AUTH} | ||
742 | }; | ||
743 | |||
744 | int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls); | ||
diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c new file mode 100644 index 000000000000..9d5e027dae0e --- /dev/null +++ b/drivers/char/drm/via_dmablit.c | |||
@@ -0,0 +1,805 @@ | |||
1 | /* via_dmablit.c -- PCI DMA BitBlt support for the VIA Unichrome/Pro | ||
2 | * | ||
3 | * Copyright (C) 2005 Thomas Hellstrom, All Rights Reserved. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sub license, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice (including the | ||
13 | * next paragraph) shall be included in all copies or substantial portions | ||
14 | * of the Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
19 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
20 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
21 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
22 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
23 | * | ||
24 | * Authors: | ||
25 | * Thomas Hellstrom. | ||
26 | * Partially based on code obtained from Digeo Inc. | ||
27 | */ | ||
28 | |||
29 | |||
30 | /* | ||
31 | * Unmaps the DMA mappings. | ||
32 | * FIXME: Is this a NoOp on x86? Also | ||
33 | * FIXME: What happens if this one is called and a pending blit has previously done | ||
34 | * the same DMA mappings? | ||
35 | */ | ||
36 | |||
37 | #include "drmP.h" | ||
38 | #include "via_drm.h" | ||
39 | #include "via_drv.h" | ||
40 | #include "via_dmablit.h" | ||
41 | |||
42 | #include <linux/pagemap.h> | ||
43 | |||
44 | #define VIA_PGDN(x) (((unsigned long)(x)) & PAGE_MASK) | ||
45 | #define VIA_PGOFF(x) (((unsigned long)(x)) & ~PAGE_MASK) | ||
46 | #define VIA_PFN(x) ((unsigned long)(x) >> PAGE_SHIFT) | ||
47 | |||
48 | typedef struct _drm_via_descriptor { | ||
49 | uint32_t mem_addr; | ||
50 | uint32_t dev_addr; | ||
51 | uint32_t size; | ||
52 | uint32_t next; | ||
53 | } drm_via_descriptor_t; | ||
54 | |||
55 | |||
56 | /* | ||
57 | * Unmap a DMA mapping. | ||
58 | */ | ||
59 | |||
60 | |||
61 | |||
62 | static void | ||
63 | via_unmap_blit_from_device(struct pci_dev *pdev, drm_via_sg_info_t *vsg) | ||
64 | { | ||
65 | int num_desc = vsg->num_desc; | ||
66 | unsigned cur_descriptor_page = num_desc / vsg->descriptors_per_page; | ||
67 | unsigned descriptor_this_page = num_desc % vsg->descriptors_per_page; | ||
68 | drm_via_descriptor_t *desc_ptr = vsg->desc_pages[cur_descriptor_page] + | ||
69 | descriptor_this_page; | ||
70 | dma_addr_t next = vsg->chain_start; | ||
71 | |||
72 | while(num_desc--) { | ||
73 | if (descriptor_this_page-- == 0) { | ||
74 | cur_descriptor_page--; | ||
75 | descriptor_this_page = vsg->descriptors_per_page - 1; | ||
76 | desc_ptr = vsg->desc_pages[cur_descriptor_page] + | ||
77 | descriptor_this_page; | ||
78 | } | ||
79 | dma_unmap_single(&pdev->dev, next, sizeof(*desc_ptr), DMA_TO_DEVICE); | ||
80 | dma_unmap_page(&pdev->dev, desc_ptr->mem_addr, desc_ptr->size, vsg->direction); | ||
81 | next = (dma_addr_t) desc_ptr->next; | ||
82 | desc_ptr--; | ||
83 | } | ||
84 | } | ||
85 | |||
86 | /* | ||
87 | * If mode = 0, count how many descriptors are needed. | ||
88 | * If mode = 1, Map the DMA pages for the device, put together and map also the descriptors. | ||
89 | * Descriptors are run in reverse order by the hardware because we are not allowed to update the | ||
90 | * 'next' field without syncing calls when the descriptor is already mapped. | ||
91 | */ | ||
92 | |||
93 | static void | ||
94 | via_map_blit_for_device(struct pci_dev *pdev, | ||
95 | const drm_via_dmablit_t *xfer, | ||
96 | drm_via_sg_info_t *vsg, | ||
97 | int mode) | ||
98 | { | ||
99 | unsigned cur_descriptor_page = 0; | ||
100 | unsigned num_descriptors_this_page = 0; | ||
101 | unsigned char *mem_addr = xfer->mem_addr; | ||
102 | unsigned char *cur_mem; | ||
103 | unsigned char *first_addr = (unsigned char *)VIA_PGDN(mem_addr); | ||
104 | uint32_t fb_addr = xfer->fb_addr; | ||
105 | uint32_t cur_fb; | ||
106 | unsigned long line_len; | ||
107 | unsigned remaining_len; | ||
108 | int num_desc = 0; | ||
109 | int cur_line; | ||
110 | dma_addr_t next = 0 | VIA_DMA_DPR_EC; | ||
111 | drm_via_descriptor_t *desc_ptr = 0; | ||
112 | |||
113 | if (mode == 1) | ||
114 | desc_ptr = vsg->desc_pages[cur_descriptor_page]; | ||
115 | |||
116 | for (cur_line = 0; cur_line < xfer->num_lines; ++cur_line) { | ||
117 | |||
118 | line_len = xfer->line_length; | ||
119 | cur_fb = fb_addr; | ||
120 | cur_mem = mem_addr; | ||
121 | |||
122 | while (line_len > 0) { | ||
123 | |||
124 | remaining_len = min(PAGE_SIZE-VIA_PGOFF(cur_mem), line_len); | ||
125 | line_len -= remaining_len; | ||
126 | |||
127 | if (mode == 1) { | ||
128 | desc_ptr->mem_addr = | ||
129 | dma_map_page(&pdev->dev, | ||
130 | vsg->pages[VIA_PFN(cur_mem) - | ||
131 | VIA_PFN(first_addr)], | ||
132 | VIA_PGOFF(cur_mem), remaining_len, | ||
133 | vsg->direction); | ||
134 | desc_ptr->dev_addr = cur_fb; | ||
135 | |||
136 | desc_ptr->size = remaining_len; | ||
137 | desc_ptr->next = (uint32_t) next; | ||
138 | next = dma_map_single(&pdev->dev, desc_ptr, sizeof(*desc_ptr), | ||
139 | DMA_TO_DEVICE); | ||
140 | desc_ptr++; | ||
141 | if (++num_descriptors_this_page >= vsg->descriptors_per_page) { | ||
142 | num_descriptors_this_page = 0; | ||
143 | desc_ptr = vsg->desc_pages[++cur_descriptor_page]; | ||
144 | } | ||
145 | } | ||
146 | |||
147 | num_desc++; | ||
148 | cur_mem += remaining_len; | ||
149 | cur_fb += remaining_len; | ||
150 | } | ||
151 | |||
152 | mem_addr += xfer->mem_stride; | ||
153 | fb_addr += xfer->fb_stride; | ||
154 | } | ||
155 | |||
156 | if (mode == 1) { | ||
157 | vsg->chain_start = next; | ||
158 | vsg->state = dr_via_device_mapped; | ||
159 | } | ||
160 | vsg->num_desc = num_desc; | ||
161 | } | ||
162 | |||
163 | /* | ||
164 | * Function that frees up all resources for a blit. It is usable even if the | ||
165 | * blit info has only be partially built as long as the status enum is consistent | ||
166 | * with the actual status of the used resources. | ||
167 | */ | ||
168 | |||
169 | |||
170 | void | ||
171 | via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg) | ||
172 | { | ||
173 | struct page *page; | ||
174 | int i; | ||
175 | |||
176 | switch(vsg->state) { | ||
177 | case dr_via_device_mapped: | ||
178 | via_unmap_blit_from_device(pdev, vsg); | ||
179 | case dr_via_desc_pages_alloc: | ||
180 | for (i=0; i<vsg->num_desc_pages; ++i) { | ||
181 | if (vsg->desc_pages[i] != NULL) | ||
182 | free_page((unsigned long)vsg->desc_pages[i]); | ||
183 | } | ||
184 | kfree(vsg->desc_pages); | ||
185 | case dr_via_pages_locked: | ||
186 | for (i=0; i<vsg->num_pages; ++i) { | ||
187 | if ( NULL != (page = vsg->pages[i])) { | ||
188 | if (! PageReserved(page) && (DMA_FROM_DEVICE == vsg->direction)) | ||
189 | SetPageDirty(page); | ||
190 | page_cache_release(page); | ||
191 | } | ||
192 | } | ||
193 | case dr_via_pages_alloc: | ||
194 | vfree(vsg->pages); | ||
195 | default: | ||
196 | vsg->state = dr_via_sg_init; | ||
197 | } | ||
198 | if (vsg->bounce_buffer) { | ||
199 | vfree(vsg->bounce_buffer); | ||
200 | vsg->bounce_buffer = NULL; | ||
201 | } | ||
202 | vsg->free_on_sequence = 0; | ||
203 | } | ||
204 | |||
205 | /* | ||
206 | * Fire a blit engine. | ||
207 | */ | ||
208 | |||
209 | static void | ||
210 | via_fire_dmablit(drm_device_t *dev, drm_via_sg_info_t *vsg, int engine) | ||
211 | { | ||
212 | drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; | ||
213 | |||
214 | VIA_WRITE(VIA_PCI_DMA_MAR0 + engine*0x10, 0); | ||
215 | VIA_WRITE(VIA_PCI_DMA_DAR0 + engine*0x10, 0); | ||
216 | VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD | | ||
217 | VIA_DMA_CSR_DE); | ||
218 | VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); | ||
219 | VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0); | ||
220 | VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); | ||
221 | VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * Obtain a page pointer array and lock all pages into system memory. A segmentation violation will | ||
226 | * occur here if the calling user does not have access to the submitted address. | ||
227 | */ | ||
228 | |||
229 | static int | ||
230 | via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) | ||
231 | { | ||
232 | int ret; | ||
233 | unsigned long first_pfn = VIA_PFN(xfer->mem_addr); | ||
234 | vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride -1)) - | ||
235 | first_pfn + 1; | ||
236 | |||
237 | if (NULL == (vsg->pages = vmalloc(sizeof(struct page *) * vsg->num_pages))) | ||
238 | return DRM_ERR(ENOMEM); | ||
239 | memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages); | ||
240 | down_read(¤t->mm->mmap_sem); | ||
241 | ret = get_user_pages(current, current->mm, (unsigned long) xfer->mem_addr, | ||
242 | vsg->num_pages, vsg->direction, 0, vsg->pages, NULL); | ||
243 | |||
244 | up_read(¤t->mm->mmap_sem); | ||
245 | if (ret != vsg->num_pages) { | ||
246 | if (ret < 0) | ||
247 | return ret; | ||
248 | vsg->state = dr_via_pages_locked; | ||
249 | return DRM_ERR(EINVAL); | ||
250 | } | ||
251 | vsg->state = dr_via_pages_locked; | ||
252 | DRM_DEBUG("DMA pages locked\n"); | ||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | /* | ||
257 | * Allocate DMA capable memory for the blit descriptor chain, and an array that keeps track of the | ||
258 | * pages we allocate. We don't want to use kmalloc for the descriptor chain because it may be | ||
259 | * quite large for some blits, and pages don't need to be contingous. | ||
260 | */ | ||
261 | |||
262 | static int | ||
263 | via_alloc_desc_pages(drm_via_sg_info_t *vsg) | ||
264 | { | ||
265 | int i; | ||
266 | |||
267 | vsg->descriptors_per_page = PAGE_SIZE / sizeof( drm_via_descriptor_t); | ||
268 | vsg->num_desc_pages = (vsg->num_desc + vsg->descriptors_per_page - 1) / | ||
269 | vsg->descriptors_per_page; | ||
270 | |||
271 | if (NULL == (vsg->desc_pages = kmalloc(sizeof(void *) * vsg->num_desc_pages, GFP_KERNEL))) | ||
272 | return DRM_ERR(ENOMEM); | ||
273 | |||
274 | memset(vsg->desc_pages, 0, sizeof(void *) * vsg->num_desc_pages); | ||
275 | vsg->state = dr_via_desc_pages_alloc; | ||
276 | for (i=0; i<vsg->num_desc_pages; ++i) { | ||
277 | if (NULL == (vsg->desc_pages[i] = | ||
278 | (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL))) | ||
279 | return DRM_ERR(ENOMEM); | ||
280 | } | ||
281 | DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages, | ||
282 | vsg->num_desc); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static void | ||
287 | via_abort_dmablit(drm_device_t *dev, int engine) | ||
288 | { | ||
289 | drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; | ||
290 | |||
291 | VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA); | ||
292 | } | ||
293 | |||
294 | static void | ||
295 | via_dmablit_engine_off(drm_device_t *dev, int engine) | ||
296 | { | ||
297 | drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; | ||
298 | |||
299 | VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD); | ||
300 | } | ||
301 | |||
302 | |||
303 | |||
304 | /* | ||
305 | * The dmablit part of the IRQ handler. Trying to do only reasonably fast things here. | ||
306 | * The rest, like unmapping and freeing memory for done blits is done in a separate workqueue | ||
307 | * task. Basically the task of the interrupt handler is to submit a new blit to the engine, while | ||
308 | * the workqueue task takes care of processing associated with the old blit. | ||
309 | */ | ||
310 | |||
311 | void | ||
312 | via_dmablit_handler(drm_device_t *dev, int engine, int from_irq) | ||
313 | { | ||
314 | drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; | ||
315 | drm_via_blitq_t *blitq = dev_priv->blit_queues + engine; | ||
316 | int cur; | ||
317 | int done_transfer; | ||
318 | unsigned long irqsave=0; | ||
319 | uint32_t status = 0; | ||
320 | |||
321 | DRM_DEBUG("DMA blit handler called. engine = %d, from_irq = %d, blitq = 0x%lx\n", | ||
322 | engine, from_irq, (unsigned long) blitq); | ||
323 | |||
324 | if (from_irq) { | ||
325 | spin_lock(&blitq->blit_lock); | ||
326 | } else { | ||
327 | spin_lock_irqsave(&blitq->blit_lock, irqsave); | ||
328 | } | ||
329 | |||
330 | done_transfer = blitq->is_active && | ||
331 | (( status = VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD); | ||
332 | done_transfer = done_transfer || ( blitq->aborting && !(status & VIA_DMA_CSR_DE)); | ||
333 | |||
334 | cur = blitq->cur; | ||
335 | if (done_transfer) { | ||
336 | |||
337 | blitq->blits[cur]->aborted = blitq->aborting; | ||
338 | blitq->done_blit_handle++; | ||
339 | DRM_WAKEUP(blitq->blit_queue + cur); | ||
340 | |||
341 | cur++; | ||
342 | if (cur >= VIA_NUM_BLIT_SLOTS) | ||
343 | cur = 0; | ||
344 | blitq->cur = cur; | ||
345 | |||
346 | /* | ||
347 | * Clear transfer done flag. | ||
348 | */ | ||
349 | |||
350 | VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD); | ||
351 | |||
352 | blitq->is_active = 0; | ||
353 | blitq->aborting = 0; | ||
354 | schedule_work(&blitq->wq); | ||
355 | |||
356 | } else if (blitq->is_active && time_after_eq(jiffies, blitq->end)) { | ||
357 | |||
358 | /* | ||
359 | * Abort transfer after one second. | ||
360 | */ | ||
361 | |||
362 | via_abort_dmablit(dev, engine); | ||
363 | blitq->aborting = 1; | ||
364 | blitq->end = jiffies + DRM_HZ; | ||
365 | } | ||
366 | |||
367 | if (!blitq->is_active) { | ||
368 | if (blitq->num_outstanding) { | ||
369 | via_fire_dmablit(dev, blitq->blits[cur], engine); | ||
370 | blitq->is_active = 1; | ||
371 | blitq->cur = cur; | ||
372 | blitq->num_outstanding--; | ||
373 | blitq->end = jiffies + DRM_HZ; | ||
374 | if (!timer_pending(&blitq->poll_timer)) { | ||
375 | blitq->poll_timer.expires = jiffies+1; | ||
376 | add_timer(&blitq->poll_timer); | ||
377 | } | ||
378 | } else { | ||
379 | if (timer_pending(&blitq->poll_timer)) { | ||
380 | del_timer(&blitq->poll_timer); | ||
381 | } | ||
382 | via_dmablit_engine_off(dev, engine); | ||
383 | } | ||
384 | } | ||
385 | |||
386 | if (from_irq) { | ||
387 | spin_unlock(&blitq->blit_lock); | ||
388 | } else { | ||
389 | spin_unlock_irqrestore(&blitq->blit_lock, irqsave); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | |||
394 | |||
395 | /* | ||
396 | * Check whether this blit is still active, performing necessary locking. | ||
397 | */ | ||
398 | |||
399 | static int | ||
400 | via_dmablit_active(drm_via_blitq_t *blitq, int engine, uint32_t handle, wait_queue_head_t **queue) | ||
401 | { | ||
402 | unsigned long irqsave; | ||
403 | uint32_t slot; | ||
404 | int active; | ||
405 | |||
406 | spin_lock_irqsave(&blitq->blit_lock, irqsave); | ||
407 | |||
408 | /* | ||
409 | * Allow for handle wraparounds. | ||
410 | */ | ||
411 | |||
412 | active = ((blitq->done_blit_handle - handle) > (1 << 23)) && | ||
413 | ((blitq->cur_blit_handle - handle) <= (1 << 23)); | ||
414 | |||
415 | if (queue && active) { | ||
416 | slot = handle - blitq->done_blit_handle + blitq->cur -1; | ||
417 | if (slot >= VIA_NUM_BLIT_SLOTS) { | ||
418 | slot -= VIA_NUM_BLIT_SLOTS; | ||
419 | } | ||
420 | *queue = blitq->blit_queue + slot; | ||
421 | } | ||
422 | |||
423 | spin_unlock_irqrestore(&blitq->blit_lock, irqsave); | ||
424 | |||
425 | return active; | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | * Sync. Wait for at least three seconds for the blit to be performed. | ||
430 | */ | ||
431 | |||
432 | static int | ||
433 | via_dmablit_sync(drm_device_t *dev, uint32_t handle, int engine) | ||
434 | { | ||
435 | |||
436 | drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; | ||
437 | drm_via_blitq_t *blitq = dev_priv->blit_queues + engine; | ||
438 | wait_queue_head_t *queue; | ||
439 | int ret = 0; | ||
440 | |||
441 | if (via_dmablit_active(blitq, engine, handle, &queue)) { | ||
442 | DRM_WAIT_ON(ret, *queue, 3 * DRM_HZ, | ||
443 | !via_dmablit_active(blitq, engine, handle, NULL)); | ||
444 | } | ||
445 | DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n", | ||
446 | handle, engine, ret); | ||
447 | |||
448 | return ret; | ||
449 | } | ||
450 | |||
451 | |||
452 | /* | ||
453 | * A timer that regularly polls the blit engine in cases where we don't have interrupts: | ||
454 | * a) Broken hardware (typically those that don't have any video capture facility). | ||
455 | * b) Blit abort. The hardware doesn't send an interrupt when a blit is aborted. | ||
456 | * The timer and hardware IRQ's can and do work in parallel. If the hardware has | ||
457 | * irqs, it will shorten the latency somewhat. | ||
458 | */ | ||
459 | |||
460 | |||
461 | |||
462 | static void | ||
463 | via_dmablit_timer(unsigned long data) | ||
464 | { | ||
465 | drm_via_blitq_t *blitq = (drm_via_blitq_t *) data; | ||
466 | drm_device_t *dev = blitq->dev; | ||
467 | int engine = (int) | ||
468 | (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues); | ||
469 | |||
470 | DRM_DEBUG("Polling timer called for engine %d, jiffies %lu\n", engine, | ||
471 | (unsigned long) jiffies); | ||
472 | |||
473 | via_dmablit_handler(dev, engine, 0); | ||
474 | |||
475 | if (!timer_pending(&blitq->poll_timer)) { | ||
476 | blitq->poll_timer.expires = jiffies+1; | ||
477 | add_timer(&blitq->poll_timer); | ||
478 | } | ||
479 | via_dmablit_handler(dev, engine, 0); | ||
480 | |||
481 | } | ||
482 | |||
483 | |||
484 | |||
485 | |||
486 | /* | ||
487 | * Workqueue task that frees data and mappings associated with a blit. | ||
488 | * Also wakes up waiting processes. Each of these tasks handles one | ||
489 | * blit engine only and may not be called on each interrupt. | ||
490 | */ | ||
491 | |||
492 | |||
493 | static void | ||
494 | via_dmablit_workqueue(void *data) | ||
495 | { | ||
496 | drm_via_blitq_t *blitq = (drm_via_blitq_t *) data; | ||
497 | drm_device_t *dev = blitq->dev; | ||
498 | unsigned long irqsave; | ||
499 | drm_via_sg_info_t *cur_sg; | ||
500 | int cur_released; | ||
501 | |||
502 | |||
503 | DRM_DEBUG("Workqueue task called for blit engine %ld\n",(unsigned long) | ||
504 | (blitq - ((drm_via_private_t *)dev->dev_private)->blit_queues)); | ||
505 | |||
506 | spin_lock_irqsave(&blitq->blit_lock, irqsave); | ||
507 | |||
508 | while(blitq->serviced != blitq->cur) { | ||
509 | |||
510 | cur_released = blitq->serviced++; | ||
511 | |||
512 | DRM_DEBUG("Releasing blit slot %d\n", cur_released); | ||
513 | |||
514 | if (blitq->serviced >= VIA_NUM_BLIT_SLOTS) | ||
515 | blitq->serviced = 0; | ||
516 | |||
517 | cur_sg = blitq->blits[cur_released]; | ||
518 | blitq->num_free++; | ||
519 | |||
520 | spin_unlock_irqrestore(&blitq->blit_lock, irqsave); | ||
521 | |||
522 | DRM_WAKEUP(&blitq->busy_queue); | ||
523 | |||
524 | via_free_sg_info(dev->pdev, cur_sg); | ||
525 | kfree(cur_sg); | ||
526 | |||
527 | spin_lock_irqsave(&blitq->blit_lock, irqsave); | ||
528 | } | ||
529 | |||
530 | spin_unlock_irqrestore(&blitq->blit_lock, irqsave); | ||
531 | } | ||
532 | |||
533 | |||
534 | /* | ||
535 | * Init all blit engines. Currently we use two, but some hardware have 4. | ||
536 | */ | ||
537 | |||
538 | |||
539 | void | ||
540 | via_init_dmablit(drm_device_t *dev) | ||
541 | { | ||
542 | int i,j; | ||
543 | drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; | ||
544 | drm_via_blitq_t *blitq; | ||
545 | |||
546 | pci_set_master(dev->pdev); | ||
547 | |||
548 | for (i=0; i< VIA_NUM_BLIT_ENGINES; ++i) { | ||
549 | blitq = dev_priv->blit_queues + i; | ||
550 | blitq->dev = dev; | ||
551 | blitq->cur_blit_handle = 0; | ||
552 | blitq->done_blit_handle = 0; | ||
553 | blitq->head = 0; | ||
554 | blitq->cur = 0; | ||
555 | blitq->serviced = 0; | ||
556 | blitq->num_free = VIA_NUM_BLIT_SLOTS; | ||
557 | blitq->num_outstanding = 0; | ||
558 | blitq->is_active = 0; | ||
559 | blitq->aborting = 0; | ||
560 | blitq->blit_lock = SPIN_LOCK_UNLOCKED; | ||
561 | for (j=0; j<VIA_NUM_BLIT_SLOTS; ++j) { | ||
562 | DRM_INIT_WAITQUEUE(blitq->blit_queue + j); | ||
563 | } | ||
564 | DRM_INIT_WAITQUEUE(&blitq->busy_queue); | ||
565 | INIT_WORK(&blitq->wq, via_dmablit_workqueue, blitq); | ||
566 | init_timer(&blitq->poll_timer); | ||
567 | blitq->poll_timer.function = &via_dmablit_timer; | ||
568 | blitq->poll_timer.data = (unsigned long) blitq; | ||
569 | } | ||
570 | } | ||
571 | |||
572 | /* | ||
573 | * Build all info and do all mappings required for a blit. | ||
574 | */ | ||
575 | |||
576 | |||
577 | static int | ||
578 | via_build_sg_info(drm_device_t *dev, drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) | ||
579 | { | ||
580 | int draw = xfer->to_fb; | ||
581 | int ret = 0; | ||
582 | |||
583 | vsg->direction = (draw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE; | ||
584 | vsg->bounce_buffer = 0; | ||
585 | |||
586 | vsg->state = dr_via_sg_init; | ||
587 | |||
588 | if (xfer->num_lines <= 0 || xfer->line_length <= 0) { | ||
589 | DRM_ERROR("Zero size bitblt.\n"); | ||
590 | return DRM_ERR(EINVAL); | ||
591 | } | ||
592 | |||
593 | /* | ||
594 | * Below check is a driver limitation, not a hardware one. We | ||
595 | * don't want to lock unused pages, and don't want to incoporate the | ||
596 | * extra logic of avoiding them. Make sure there are no. | ||
597 | * (Not a big limitation anyway.) | ||
598 | */ | ||
599 | |||
600 | if (((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) || | ||
601 | (xfer->mem_stride > 2048*4)) { | ||
602 | DRM_ERROR("Too large system memory stride. Stride: %d, " | ||
603 | "Length: %d\n", xfer->mem_stride, xfer->line_length); | ||
604 | return DRM_ERR(EINVAL); | ||
605 | } | ||
606 | |||
607 | if (xfer->num_lines > 2048) { | ||
608 | DRM_ERROR("Too many PCI DMA bitblt lines.\n"); | ||
609 | return DRM_ERR(EINVAL); | ||
610 | } | ||
611 | |||
612 | /* | ||
613 | * we allow a negative fb stride to allow flipping of images in | ||
614 | * transfer. | ||
615 | */ | ||
616 | |||
617 | if (xfer->mem_stride < xfer->line_length || | ||
618 | abs(xfer->fb_stride) < xfer->line_length) { | ||
619 | DRM_ERROR("Invalid frame-buffer / memory stride.\n"); | ||
620 | return DRM_ERR(EINVAL); | ||
621 | } | ||
622 | |||
623 | /* | ||
624 | * A hardware bug seems to be worked around if system memory addresses start on | ||
625 | * 16 byte boundaries. This seems a bit restrictive however. VIA is contacted | ||
626 | * about this. Meanwhile, impose the following restrictions: | ||
627 | */ | ||
628 | |||
629 | #ifdef VIA_BUGFREE | ||
630 | if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) || | ||
631 | ((xfer->mem_stride & 3) != (xfer->fb_stride & 3))) { | ||
632 | DRM_ERROR("Invalid DRM bitblt alignment.\n"); | ||
633 | return DRM_ERR(EINVAL); | ||
634 | } | ||
635 | #else | ||
636 | if ((((unsigned long)xfer->mem_addr & 15) || | ||
637 | ((unsigned long)xfer->fb_addr & 3)) || (xfer->mem_stride & 15) || | ||
638 | (xfer->fb_stride & 3)) { | ||
639 | DRM_ERROR("Invalid DRM bitblt alignment.\n"); | ||
640 | return DRM_ERR(EINVAL); | ||
641 | } | ||
642 | #endif | ||
643 | |||
644 | if (0 != (ret = via_lock_all_dma_pages(vsg, xfer))) { | ||
645 | DRM_ERROR("Could not lock DMA pages.\n"); | ||
646 | via_free_sg_info(dev->pdev, vsg); | ||
647 | return ret; | ||
648 | } | ||
649 | |||
650 | via_map_blit_for_device(dev->pdev, xfer, vsg, 0); | ||
651 | if (0 != (ret = via_alloc_desc_pages(vsg))) { | ||
652 | DRM_ERROR("Could not allocate DMA descriptor pages.\n"); | ||
653 | via_free_sg_info(dev->pdev, vsg); | ||
654 | return ret; | ||
655 | } | ||
656 | via_map_blit_for_device(dev->pdev, xfer, vsg, 1); | ||
657 | |||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | |||
662 | /* | ||
663 | * Reserve one free slot in the blit queue. Will wait for one second for one | ||
664 | * to become available. Otherwise -EBUSY is returned. | ||
665 | */ | ||
666 | |||
667 | static int | ||
668 | via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine) | ||
669 | { | ||
670 | int ret=0; | ||
671 | unsigned long irqsave; | ||
672 | |||
673 | DRM_DEBUG("Num free is %d\n", blitq->num_free); | ||
674 | spin_lock_irqsave(&blitq->blit_lock, irqsave); | ||
675 | while(blitq->num_free == 0) { | ||
676 | spin_unlock_irqrestore(&blitq->blit_lock, irqsave); | ||
677 | |||
678 | DRM_WAIT_ON(ret, blitq->busy_queue, DRM_HZ, blitq->num_free > 0); | ||
679 | if (ret) { | ||
680 | return (DRM_ERR(EINTR) == ret) ? DRM_ERR(EAGAIN) : ret; | ||
681 | } | ||
682 | |||
683 | spin_lock_irqsave(&blitq->blit_lock, irqsave); | ||
684 | } | ||
685 | |||
686 | blitq->num_free--; | ||
687 | spin_unlock_irqrestore(&blitq->blit_lock, irqsave); | ||
688 | |||
689 | return 0; | ||
690 | } | ||
691 | |||
692 | /* | ||
693 | * Hand back a free slot if we changed our mind. | ||
694 | */ | ||
695 | |||
696 | static void | ||
697 | via_dmablit_release_slot(drm_via_blitq_t *blitq) | ||
698 | { | ||
699 | unsigned long irqsave; | ||
700 | |||
701 | spin_lock_irqsave(&blitq->blit_lock, irqsave); | ||
702 | blitq->num_free++; | ||
703 | spin_unlock_irqrestore(&blitq->blit_lock, irqsave); | ||
704 | DRM_WAKEUP( &blitq->busy_queue ); | ||
705 | } | ||
706 | |||
707 | /* | ||
708 | * Grab a free slot. Build blit info and queue a blit. | ||
709 | */ | ||
710 | |||
711 | |||
712 | static int | ||
713 | via_dmablit(drm_device_t *dev, drm_via_dmablit_t *xfer) | ||
714 | { | ||
715 | drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; | ||
716 | drm_via_sg_info_t *vsg; | ||
717 | drm_via_blitq_t *blitq; | ||
718 | int ret; | ||
719 | int engine; | ||
720 | unsigned long irqsave; | ||
721 | |||
722 | if (dev_priv == NULL) { | ||
723 | DRM_ERROR("Called without initialization.\n"); | ||
724 | return DRM_ERR(EINVAL); | ||
725 | } | ||
726 | |||
727 | engine = (xfer->to_fb) ? 0 : 1; | ||
728 | blitq = dev_priv->blit_queues + engine; | ||
729 | if (0 != (ret = via_dmablit_grab_slot(blitq, engine))) { | ||
730 | return ret; | ||
731 | } | ||
732 | if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) { | ||
733 | via_dmablit_release_slot(blitq); | ||
734 | return DRM_ERR(ENOMEM); | ||
735 | } | ||
736 | if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) { | ||
737 | via_dmablit_release_slot(blitq); | ||
738 | kfree(vsg); | ||
739 | return ret; | ||
740 | } | ||
741 | spin_lock_irqsave(&blitq->blit_lock, irqsave); | ||
742 | |||
743 | blitq->blits[blitq->head++] = vsg; | ||
744 | if (blitq->head >= VIA_NUM_BLIT_SLOTS) | ||
745 | blitq->head = 0; | ||
746 | blitq->num_outstanding++; | ||
747 | xfer->sync.sync_handle = ++blitq->cur_blit_handle; | ||
748 | |||
749 | spin_unlock_irqrestore(&blitq->blit_lock, irqsave); | ||
750 | xfer->sync.engine = engine; | ||
751 | |||
752 | via_dmablit_handler(dev, engine, 0); | ||
753 | |||
754 | return 0; | ||
755 | } | ||
756 | |||
757 | /* | ||
758 | * Sync on a previously submitted blit. Note that the X server use signals extensively, and | ||
759 | * that there is a very big proability that this IOCTL will be interrupted by a signal. In that | ||
760 | * case it returns with -EAGAIN for the signal to be delivered. | ||
761 | * The caller should then reissue the IOCTL. This is similar to what is being done for drmGetLock(). | ||
762 | */ | ||
763 | |||
764 | int | ||
765 | via_dma_blit_sync( DRM_IOCTL_ARGS ) | ||
766 | { | ||
767 | drm_via_blitsync_t sync; | ||
768 | int err; | ||
769 | DRM_DEVICE; | ||
770 | |||
771 | DRM_COPY_FROM_USER_IOCTL(sync, (drm_via_blitsync_t *)data, sizeof(sync)); | ||
772 | |||
773 | if (sync.engine >= VIA_NUM_BLIT_ENGINES) | ||
774 | return DRM_ERR(EINVAL); | ||
775 | |||
776 | err = via_dmablit_sync(dev, sync.sync_handle, sync.engine); | ||
777 | |||
778 | if (DRM_ERR(EINTR) == err) | ||
779 | err = DRM_ERR(EAGAIN); | ||
780 | |||
781 | return err; | ||
782 | } | ||
783 | |||
784 | |||
785 | /* | ||
786 | * Queue a blit and hand back a handle to be used for sync. This IOCTL may be interrupted by a signal | ||
787 | * while waiting for a free slot in the blit queue. In that case it returns with -EAGAIN and should | ||
788 | * be reissued. See the above IOCTL code. | ||
789 | */ | ||
790 | |||
791 | int | ||
792 | via_dma_blit( DRM_IOCTL_ARGS ) | ||
793 | { | ||
794 | drm_via_dmablit_t xfer; | ||
795 | int err; | ||
796 | DRM_DEVICE; | ||
797 | |||
798 | DRM_COPY_FROM_USER_IOCTL(xfer, (drm_via_dmablit_t __user *)data, sizeof(xfer)); | ||
799 | |||
800 | err = via_dmablit(dev, &xfer); | ||
801 | |||
802 | DRM_COPY_TO_USER_IOCTL((void __user *)data, xfer, sizeof(xfer)); | ||
803 | |||
804 | return err; | ||
805 | } | ||
diff --git a/drivers/char/drm/via_dmablit.h b/drivers/char/drm/via_dmablit.h new file mode 100644 index 000000000000..f4036cd5d0e0 --- /dev/null +++ b/drivers/char/drm/via_dmablit.h | |||
@@ -0,0 +1,140 @@ | |||
1 | /* via_dmablit.h -- PCI DMA BitBlt support for the VIA Unichrome/Pro | ||
2 | * | ||
3 | * Copyright 2005 Thomas Hellstrom. | ||
4 | * All Rights Reserved. | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
7 | * copy of this software and associated documentation files (the "Software"), | ||
8 | * to deal in the Software without restriction, including without limitation | ||
9 | * the rights to use, copy, modify, merge, publish, distribute, sub license, | ||
10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
11 | * Software is furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice (including the | ||
14 | * next paragraph) shall be included in all copies or substantial portions | ||
15 | * of the Software. | ||
16 | * | ||
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
20 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, | ||
21 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
22 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
23 | * USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
24 | * | ||
25 | * Authors: | ||
26 | * Thomas Hellstrom. | ||
27 | * Register info from Digeo Inc. | ||
28 | */ | ||
29 | |||
30 | #ifndef _VIA_DMABLIT_H | ||
31 | #define _VIA_DMABLIT_H | ||
32 | |||
33 | #include <linux/dma-mapping.h> | ||
34 | |||
35 | #define VIA_NUM_BLIT_ENGINES 2 | ||
36 | #define VIA_NUM_BLIT_SLOTS 8 | ||
37 | |||
38 | struct _drm_via_descriptor; | ||
39 | |||
40 | typedef struct _drm_via_sg_info { | ||
41 | struct page **pages; | ||
42 | unsigned long num_pages; | ||
43 | struct _drm_via_descriptor **desc_pages; | ||
44 | int num_desc_pages; | ||
45 | int num_desc; | ||
46 | enum dma_data_direction direction; | ||
47 | unsigned char *bounce_buffer; | ||
48 | dma_addr_t chain_start; | ||
49 | uint32_t free_on_sequence; | ||
50 | unsigned int descriptors_per_page; | ||
51 | int aborted; | ||
52 | enum { | ||
53 | dr_via_device_mapped, | ||
54 | dr_via_desc_pages_alloc, | ||
55 | dr_via_pages_locked, | ||
56 | dr_via_pages_alloc, | ||
57 | dr_via_sg_init | ||
58 | } state; | ||
59 | } drm_via_sg_info_t; | ||
60 | |||
61 | typedef struct _drm_via_blitq { | ||
62 | drm_device_t *dev; | ||
63 | uint32_t cur_blit_handle; | ||
64 | uint32_t done_blit_handle; | ||
65 | unsigned serviced; | ||
66 | unsigned head; | ||
67 | unsigned cur; | ||
68 | unsigned num_free; | ||
69 | unsigned num_outstanding; | ||
70 | unsigned long end; | ||
71 | int aborting; | ||
72 | int is_active; | ||
73 | drm_via_sg_info_t *blits[VIA_NUM_BLIT_SLOTS]; | ||
74 | spinlock_t blit_lock; | ||
75 | wait_queue_head_t blit_queue[VIA_NUM_BLIT_SLOTS]; | ||
76 | wait_queue_head_t busy_queue; | ||
77 | struct work_struct wq; | ||
78 | struct timer_list poll_timer; | ||
79 | } drm_via_blitq_t; | ||
80 | |||
81 | |||
82 | /* | ||
83 | * PCI DMA Registers | ||
84 | * Channels 2 & 3 don't seem to be implemented in hardware. | ||
85 | */ | ||
86 | |||
87 | #define VIA_PCI_DMA_MAR0 0xE40 /* Memory Address Register of Channel 0 */ | ||
88 | #define VIA_PCI_DMA_DAR0 0xE44 /* Device Address Register of Channel 0 */ | ||
89 | #define VIA_PCI_DMA_BCR0 0xE48 /* Byte Count Register of Channel 0 */ | ||
90 | #define VIA_PCI_DMA_DPR0 0xE4C /* Descriptor Pointer Register of Channel 0 */ | ||
91 | |||
92 | #define VIA_PCI_DMA_MAR1 0xE50 /* Memory Address Register of Channel 1 */ | ||
93 | #define VIA_PCI_DMA_DAR1 0xE54 /* Device Address Register of Channel 1 */ | ||
94 | #define VIA_PCI_DMA_BCR1 0xE58 /* Byte Count Register of Channel 1 */ | ||
95 | #define VIA_PCI_DMA_DPR1 0xE5C /* Descriptor Pointer Register of Channel 1 */ | ||
96 | |||
97 | #define VIA_PCI_DMA_MAR2 0xE60 /* Memory Address Register of Channel 2 */ | ||
98 | #define VIA_PCI_DMA_DAR2 0xE64 /* Device Address Register of Channel 2 */ | ||
99 | #define VIA_PCI_DMA_BCR2 0xE68 /* Byte Count Register of Channel 2 */ | ||
100 | #define VIA_PCI_DMA_DPR2 0xE6C /* Descriptor Pointer Register of Channel 2 */ | ||
101 | |||
102 | #define VIA_PCI_DMA_MAR3 0xE70 /* Memory Address Register of Channel 3 */ | ||
103 | #define VIA_PCI_DMA_DAR3 0xE74 /* Device Address Register of Channel 3 */ | ||
104 | #define VIA_PCI_DMA_BCR3 0xE78 /* Byte Count Register of Channel 3 */ | ||
105 | #define VIA_PCI_DMA_DPR3 0xE7C /* Descriptor Pointer Register of Channel 3 */ | ||
106 | |||
107 | #define VIA_PCI_DMA_MR0 0xE80 /* Mode Register of Channel 0 */ | ||
108 | #define VIA_PCI_DMA_MR1 0xE84 /* Mode Register of Channel 1 */ | ||
109 | #define VIA_PCI_DMA_MR2 0xE88 /* Mode Register of Channel 2 */ | ||
110 | #define VIA_PCI_DMA_MR3 0xE8C /* Mode Register of Channel 3 */ | ||
111 | |||
112 | #define VIA_PCI_DMA_CSR0 0xE90 /* Command/Status Register of Channel 0 */ | ||
113 | #define VIA_PCI_DMA_CSR1 0xE94 /* Command/Status Register of Channel 1 */ | ||
114 | #define VIA_PCI_DMA_CSR2 0xE98 /* Command/Status Register of Channel 2 */ | ||
115 | #define VIA_PCI_DMA_CSR3 0xE9C /* Command/Status Register of Channel 3 */ | ||
116 | |||
117 | #define VIA_PCI_DMA_PTR 0xEA0 /* Priority Type Register */ | ||
118 | |||
119 | /* Define for DMA engine */ | ||
120 | /* DPR */ | ||
121 | #define VIA_DMA_DPR_EC (1<<1) /* end of chain */ | ||
122 | #define VIA_DMA_DPR_DDIE (1<<2) /* descriptor done interrupt enable */ | ||
123 | #define VIA_DMA_DPR_DT (1<<3) /* direction of transfer (RO) */ | ||
124 | |||
125 | /* MR */ | ||
126 | #define VIA_DMA_MR_CM (1<<0) /* chaining mode */ | ||
127 | #define VIA_DMA_MR_TDIE (1<<1) /* transfer done interrupt enable */ | ||
128 | #define VIA_DMA_MR_HENDMACMD (1<<7) /* ? */ | ||
129 | |||
130 | /* CSR */ | ||
131 | #define VIA_DMA_CSR_DE (1<<0) /* DMA enable */ | ||
132 | #define VIA_DMA_CSR_TS (1<<1) /* transfer start */ | ||
133 | #define VIA_DMA_CSR_TA (1<<2) /* transfer abort */ | ||
134 | #define VIA_DMA_CSR_TD (1<<3) /* transfer done */ | ||
135 | #define VIA_DMA_CSR_DD (1<<4) /* descriptor done */ | ||
136 | #define VIA_DMA_DPR_EC (1<<1) /* end of chain */ | ||
137 | |||
138 | |||
139 | |||
140 | #endif | ||
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h index ebde9206115e..47f0b5b26379 100644 --- a/drivers/char/drm/via_drm.h +++ b/drivers/char/drm/via_drm.h | |||
@@ -75,6 +75,8 @@ | |||
75 | #define DRM_VIA_CMDBUF_SIZE 0x0b | 75 | #define DRM_VIA_CMDBUF_SIZE 0x0b |
76 | #define NOT_USED | 76 | #define NOT_USED |
77 | #define DRM_VIA_WAIT_IRQ 0x0d | 77 | #define DRM_VIA_WAIT_IRQ 0x0d |
78 | #define DRM_VIA_DMA_BLIT 0x0e | ||
79 | #define DRM_VIA_BLIT_SYNC 0x0f | ||
78 | 80 | ||
79 | #define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t) | 81 | #define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t) |
80 | #define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t) | 82 | #define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t) |
@@ -89,6 +91,8 @@ | |||
89 | #define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \ | 91 | #define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \ |
90 | drm_via_cmdbuf_size_t) | 92 | drm_via_cmdbuf_size_t) |
91 | #define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t) | 93 | #define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t) |
94 | #define DRM_IOCTL_VIA_DMA_BLIT DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_DMA_BLIT, drm_via_dmablit_t) | ||
95 | #define DRM_IOCTL_VIA_BLIT_SYNC DRM_IOW(DRM_COMMAND_BASE + DRM_VIA_BLIT_SYNC, drm_via_blitsync_t) | ||
92 | 96 | ||
93 | /* Indices into buf.Setup where various bits of state are mirrored per | 97 | /* Indices into buf.Setup where various bits of state are mirrored per |
94 | * context and per buffer. These can be fired at the card as a unit, | 98 | * context and per buffer. These can be fired at the card as a unit, |
@@ -103,8 +107,12 @@ | |||
103 | #define VIA_BACK 0x2 | 107 | #define VIA_BACK 0x2 |
104 | #define VIA_DEPTH 0x4 | 108 | #define VIA_DEPTH 0x4 |
105 | #define VIA_STENCIL 0x8 | 109 | #define VIA_STENCIL 0x8 |
106 | #define VIDEO 0 | 110 | #define VIA_MEM_VIDEO 0 /* matches drm constant */ |
107 | #define AGP 1 | 111 | #define VIA_MEM_AGP 1 /* matches drm constant */ |
112 | #define VIA_MEM_SYSTEM 2 | ||
113 | #define VIA_MEM_MIXED 3 | ||
114 | #define VIA_MEM_UNKNOWN 4 | ||
115 | |||
108 | typedef struct { | 116 | typedef struct { |
109 | uint32_t offset; | 117 | uint32_t offset; |
110 | uint32_t size; | 118 | uint32_t size; |
@@ -192,6 +200,9 @@ typedef struct _drm_via_sarea { | |||
192 | unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS]; | 200 | unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS]; |
193 | unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */ | 201 | unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */ |
194 | 202 | ||
203 | /* Used by the 3d driver only at this point, for pageflipping: | ||
204 | */ | ||
205 | unsigned int pfCurrentOffset; | ||
195 | } drm_via_sarea_t; | 206 | } drm_via_sarea_t; |
196 | 207 | ||
197 | typedef struct _drm_via_cmdbuf_size { | 208 | typedef struct _drm_via_cmdbuf_size { |
@@ -212,6 +223,16 @@ typedef enum { | |||
212 | 223 | ||
213 | #define VIA_IRQ_FLAGS_MASK 0xF0000000 | 224 | #define VIA_IRQ_FLAGS_MASK 0xF0000000 |
214 | 225 | ||
226 | enum drm_via_irqs { | ||
227 | drm_via_irq_hqv0 = 0, | ||
228 | drm_via_irq_hqv1, | ||
229 | drm_via_irq_dma0_dd, | ||
230 | drm_via_irq_dma0_td, | ||
231 | drm_via_irq_dma1_dd, | ||
232 | drm_via_irq_dma1_td, | ||
233 | drm_via_irq_num | ||
234 | }; | ||
235 | |||
215 | struct drm_via_wait_irq_request { | 236 | struct drm_via_wait_irq_request { |
216 | unsigned irq; | 237 | unsigned irq; |
217 | via_irq_seq_type_t type; | 238 | via_irq_seq_type_t type; |
@@ -224,20 +245,25 @@ typedef union drm_via_irqwait { | |||
224 | struct drm_wait_vblank_reply reply; | 245 | struct drm_wait_vblank_reply reply; |
225 | } drm_via_irqwait_t; | 246 | } drm_via_irqwait_t; |
226 | 247 | ||
227 | #ifdef __KERNEL__ | 248 | typedef struct drm_via_blitsync { |
228 | 249 | uint32_t sync_handle; | |
229 | int via_fb_init(DRM_IOCTL_ARGS); | 250 | unsigned engine; |
230 | int via_mem_alloc(DRM_IOCTL_ARGS); | 251 | } drm_via_blitsync_t; |
231 | int via_mem_free(DRM_IOCTL_ARGS); | 252 | |
232 | int via_agp_init(DRM_IOCTL_ARGS); | 253 | typedef struct drm_via_dmablit { |
233 | int via_map_init(DRM_IOCTL_ARGS); | 254 | uint32_t num_lines; |
234 | int via_decoder_futex(DRM_IOCTL_ARGS); | 255 | uint32_t line_length; |
235 | int via_dma_init(DRM_IOCTL_ARGS); | 256 | |
236 | int via_cmdbuffer(DRM_IOCTL_ARGS); | 257 | uint32_t fb_addr; |
237 | int via_flush_ioctl(DRM_IOCTL_ARGS); | 258 | uint32_t fb_stride; |
238 | int via_pci_cmdbuffer(DRM_IOCTL_ARGS); | 259 | |
239 | int via_cmdbuf_size(DRM_IOCTL_ARGS); | 260 | unsigned char *mem_addr; |
240 | int via_wait_irq(DRM_IOCTL_ARGS); | 261 | uint32_t mem_stride; |
262 | |||
263 | int bounce_buffer; | ||
264 | int to_fb; | ||
265 | |||
266 | drm_via_blitsync_t sync; | ||
267 | } drm_via_dmablit_t; | ||
241 | 268 | ||
242 | #endif | ||
243 | #endif /* _VIA_DRM_H_ */ | 269 | #endif /* _VIA_DRM_H_ */ |
diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c index 016665e0c69f..3f012255d315 100644 --- a/drivers/char/drm/via_drv.c +++ b/drivers/char/drm/via_drv.c | |||
@@ -29,54 +29,21 @@ | |||
29 | 29 | ||
30 | #include "drm_pciids.h" | 30 | #include "drm_pciids.h" |
31 | 31 | ||
32 | static int postinit(struct drm_device *dev, unsigned long flags) | 32 | static int dri_library_name(struct drm_device *dev, char *buf) |
33 | { | 33 | { |
34 | DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n", | 34 | return snprintf(buf, PAGE_SIZE, "unichrome"); |
35 | DRIVER_NAME, | ||
36 | DRIVER_MAJOR, | ||
37 | DRIVER_MINOR, | ||
38 | DRIVER_PATCHLEVEL, | ||
39 | DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev) | ||
40 | ); | ||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | static int version(drm_version_t * version) | ||
45 | { | ||
46 | int len; | ||
47 | |||
48 | version->version_major = DRIVER_MAJOR; | ||
49 | version->version_minor = DRIVER_MINOR; | ||
50 | version->version_patchlevel = DRIVER_PATCHLEVEL; | ||
51 | DRM_COPY(version->name, DRIVER_NAME); | ||
52 | DRM_COPY(version->date, DRIVER_DATE); | ||
53 | DRM_COPY(version->desc, DRIVER_DESC); | ||
54 | return 0; | ||
55 | } | 35 | } |
56 | 36 | ||
57 | static struct pci_device_id pciidlist[] = { | 37 | static struct pci_device_id pciidlist[] = { |
58 | viadrv_PCI_IDS | 38 | viadrv_PCI_IDS |
59 | }; | 39 | }; |
60 | 40 | ||
61 | static drm_ioctl_desc_t ioctls[] = { | ||
62 | [DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, 1, 0}, | ||
63 | [DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, 1, 0}, | ||
64 | [DRM_IOCTL_NR(DRM_VIA_AGP_INIT)] = {via_agp_init, 1, 0}, | ||
65 | [DRM_IOCTL_NR(DRM_VIA_FB_INIT)] = {via_fb_init, 1, 0}, | ||
66 | [DRM_IOCTL_NR(DRM_VIA_MAP_INIT)] = {via_map_init, 1, 0}, | ||
67 | [DRM_IOCTL_NR(DRM_VIA_DEC_FUTEX)] = {via_decoder_futex, 1, 0}, | ||
68 | [DRM_IOCTL_NR(DRM_VIA_DMA_INIT)] = {via_dma_init, 1, 0}, | ||
69 | [DRM_IOCTL_NR(DRM_VIA_CMDBUFFER)] = {via_cmdbuffer, 1, 0}, | ||
70 | [DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, 1, 0}, | ||
71 | [DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, 1, 0}, | ||
72 | [DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, 1, 0}, | ||
73 | [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, 1, 0} | ||
74 | }; | ||
75 | |||
76 | static struct drm_driver driver = { | 41 | static struct drm_driver driver = { |
77 | .driver_features = | 42 | .driver_features = |
78 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | | 43 | DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ | |
79 | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, | 44 | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL, |
45 | .load = via_driver_load, | ||
46 | .unload = via_driver_unload, | ||
80 | .context_ctor = via_init_context, | 47 | .context_ctor = via_init_context, |
81 | .context_dtor = via_final_context, | 48 | .context_dtor = via_final_context, |
82 | .vblank_wait = via_driver_vblank_wait, | 49 | .vblank_wait = via_driver_vblank_wait, |
@@ -85,13 +52,11 @@ static struct drm_driver driver = { | |||
85 | .irq_uninstall = via_driver_irq_uninstall, | 52 | .irq_uninstall = via_driver_irq_uninstall, |
86 | .irq_handler = via_driver_irq_handler, | 53 | .irq_handler = via_driver_irq_handler, |
87 | .dma_quiescent = via_driver_dma_quiescent, | 54 | .dma_quiescent = via_driver_dma_quiescent, |
55 | .dri_library_name = dri_library_name, | ||
88 | .reclaim_buffers = drm_core_reclaim_buffers, | 56 | .reclaim_buffers = drm_core_reclaim_buffers, |
89 | .get_map_ofs = drm_core_get_map_ofs, | 57 | .get_map_ofs = drm_core_get_map_ofs, |
90 | .get_reg_ofs = drm_core_get_reg_ofs, | 58 | .get_reg_ofs = drm_core_get_reg_ofs, |
91 | .postinit = postinit, | 59 | .ioctls = via_ioctls, |
92 | .version = version, | ||
93 | .ioctls = ioctls, | ||
94 | .num_ioctls = DRM_ARRAY_SIZE(ioctls), | ||
95 | .fops = { | 60 | .fops = { |
96 | .owner = THIS_MODULE, | 61 | .owner = THIS_MODULE, |
97 | .open = drm_open, | 62 | .open = drm_open, |
@@ -100,15 +65,23 @@ static struct drm_driver driver = { | |||
100 | .mmap = drm_mmap, | 65 | .mmap = drm_mmap, |
101 | .poll = drm_poll, | 66 | .poll = drm_poll, |
102 | .fasync = drm_fasync, | 67 | .fasync = drm_fasync, |
103 | }, | 68 | }, |
104 | .pci_driver = { | 69 | .pci_driver = { |
105 | .name = DRIVER_NAME, | 70 | .name = DRIVER_NAME, |
106 | .id_table = pciidlist, | 71 | .id_table = pciidlist, |
107 | } | 72 | }, |
73 | |||
74 | .name = DRIVER_NAME, | ||
75 | .desc = DRIVER_DESC, | ||
76 | .date = DRIVER_DATE, | ||
77 | .major = DRIVER_MAJOR, | ||
78 | .minor = DRIVER_MINOR, | ||
79 | .patchlevel = DRIVER_PATCHLEVEL, | ||
108 | }; | 80 | }; |
109 | 81 | ||
110 | static int __init via_init(void) | 82 | static int __init via_init(void) |
111 | { | 83 | { |
84 | driver.num_ioctls = via_max_ioctl; | ||
112 | via_init_command_verifier(); | 85 | via_init_command_verifier(); |
113 | return drm_init(&driver); | 86 | return drm_init(&driver); |
114 | } | 87 | } |
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h index 7d5daf43797e..aad4f99f5405 100644 --- a/drivers/char/drm/via_drv.h +++ b/drivers/char/drm/via_drv.h | |||
@@ -24,24 +24,26 @@ | |||
24 | #ifndef _VIA_DRV_H_ | 24 | #ifndef _VIA_DRV_H_ |
25 | #define _VIA_DRV_H_ | 25 | #define _VIA_DRV_H_ |
26 | 26 | ||
27 | #define DRIVER_AUTHOR "VIA" | 27 | #define DRIVER_AUTHOR "Various" |
28 | 28 | ||
29 | #define DRIVER_NAME "via" | 29 | #define DRIVER_NAME "via" |
30 | #define DRIVER_DESC "VIA Unichrome / Pro" | 30 | #define DRIVER_DESC "VIA Unichrome / Pro" |
31 | #define DRIVER_DATE "20050523" | 31 | #define DRIVER_DATE "20051116" |
32 | 32 | ||
33 | #define DRIVER_MAJOR 2 | 33 | #define DRIVER_MAJOR 2 |
34 | #define DRIVER_MINOR 6 | 34 | #define DRIVER_MINOR 7 |
35 | #define DRIVER_PATCHLEVEL 3 | 35 | #define DRIVER_PATCHLEVEL 4 |
36 | 36 | ||
37 | #include "via_verifier.h" | 37 | #include "via_verifier.h" |
38 | 38 | ||
39 | #include "via_dmablit.h" | ||
40 | |||
39 | #define VIA_PCI_BUF_SIZE 60000 | 41 | #define VIA_PCI_BUF_SIZE 60000 |
40 | #define VIA_FIRE_BUF_SIZE 1024 | 42 | #define VIA_FIRE_BUF_SIZE 1024 |
41 | #define VIA_NUM_IRQS 2 | 43 | #define VIA_NUM_IRQS 4 |
42 | 44 | ||
43 | typedef struct drm_via_ring_buffer { | 45 | typedef struct drm_via_ring_buffer { |
44 | drm_map_t map; | 46 | drm_local_map_t map; |
45 | char *virtual_start; | 47 | char *virtual_start; |
46 | } drm_via_ring_buffer_t; | 48 | } drm_via_ring_buffer_t; |
47 | 49 | ||
@@ -56,9 +58,9 @@ typedef struct drm_via_irq { | |||
56 | 58 | ||
57 | typedef struct drm_via_private { | 59 | typedef struct drm_via_private { |
58 | drm_via_sarea_t *sarea_priv; | 60 | drm_via_sarea_t *sarea_priv; |
59 | drm_map_t *sarea; | 61 | drm_local_map_t *sarea; |
60 | drm_map_t *fb; | 62 | drm_local_map_t *fb; |
61 | drm_map_t *mmio; | 63 | drm_local_map_t *mmio; |
62 | unsigned long agpAddr; | 64 | unsigned long agpAddr; |
63 | wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS]; | 65 | wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS]; |
64 | char *dma_ptr; | 66 | char *dma_ptr; |
@@ -82,8 +84,15 @@ typedef struct drm_via_private { | |||
82 | maskarray_t *irq_masks; | 84 | maskarray_t *irq_masks; |
83 | uint32_t irq_enable_mask; | 85 | uint32_t irq_enable_mask; |
84 | uint32_t irq_pending_mask; | 86 | uint32_t irq_pending_mask; |
87 | int *irq_map; | ||
88 | drm_via_blitq_t blit_queues[VIA_NUM_BLIT_ENGINES]; | ||
85 | } drm_via_private_t; | 89 | } drm_via_private_t; |
86 | 90 | ||
91 | enum via_family { | ||
92 | VIA_OTHER = 0, | ||
93 | VIA_PRO_GROUP_A, | ||
94 | }; | ||
95 | |||
87 | /* VIA MMIO register access */ | 96 | /* VIA MMIO register access */ |
88 | #define VIA_BASE ((dev_priv->mmio)) | 97 | #define VIA_BASE ((dev_priv->mmio)) |
89 | 98 | ||
@@ -92,12 +101,31 @@ typedef struct drm_via_private { | |||
92 | #define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg) | 101 | #define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg) |
93 | #define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val) | 102 | #define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val) |
94 | 103 | ||
104 | extern drm_ioctl_desc_t via_ioctls[]; | ||
105 | extern int via_max_ioctl; | ||
106 | |||
107 | extern int via_fb_init(DRM_IOCTL_ARGS); | ||
108 | extern int via_mem_alloc(DRM_IOCTL_ARGS); | ||
109 | extern int via_mem_free(DRM_IOCTL_ARGS); | ||
110 | extern int via_agp_init(DRM_IOCTL_ARGS); | ||
111 | extern int via_map_init(DRM_IOCTL_ARGS); | ||
112 | extern int via_decoder_futex(DRM_IOCTL_ARGS); | ||
113 | extern int via_dma_init(DRM_IOCTL_ARGS); | ||
114 | extern int via_cmdbuffer(DRM_IOCTL_ARGS); | ||
115 | extern int via_flush_ioctl(DRM_IOCTL_ARGS); | ||
116 | extern int via_pci_cmdbuffer(DRM_IOCTL_ARGS); | ||
117 | extern int via_cmdbuf_size(DRM_IOCTL_ARGS); | ||
118 | extern int via_wait_irq(DRM_IOCTL_ARGS); | ||
119 | extern int via_dma_blit_sync( DRM_IOCTL_ARGS ); | ||
120 | extern int via_dma_blit( DRM_IOCTL_ARGS ); | ||
121 | |||
122 | extern int via_driver_load(drm_device_t *dev, unsigned long chipset); | ||
123 | extern int via_driver_unload(drm_device_t *dev); | ||
124 | |||
95 | extern int via_init_context(drm_device_t * dev, int context); | 125 | extern int via_init_context(drm_device_t * dev, int context); |
96 | extern int via_final_context(drm_device_t * dev, int context); | 126 | extern int via_final_context(drm_device_t * dev, int context); |
97 | 127 | ||
98 | extern int via_do_cleanup_map(drm_device_t * dev); | 128 | extern int via_do_cleanup_map(drm_device_t * dev); |
99 | extern int via_map_init(struct inode *inode, struct file *filp, | ||
100 | unsigned int cmd, unsigned long arg); | ||
101 | extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence); | 129 | extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence); |
102 | 130 | ||
103 | extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS); | 131 | extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS); |
@@ -111,8 +139,10 @@ extern int via_driver_dma_quiescent(drm_device_t * dev); | |||
111 | extern void via_init_futex(drm_via_private_t * dev_priv); | 139 | extern void via_init_futex(drm_via_private_t * dev_priv); |
112 | extern void via_cleanup_futex(drm_via_private_t * dev_priv); | 140 | extern void via_cleanup_futex(drm_via_private_t * dev_priv); |
113 | extern void via_release_futex(drm_via_private_t * dev_priv, int context); | 141 | extern void via_release_futex(drm_via_private_t * dev_priv, int context); |
142 | extern int via_driver_irq_wait(drm_device_t * dev, unsigned int irq, | ||
143 | int force_sequence, unsigned int *sequence); | ||
114 | 144 | ||
115 | extern int via_parse_command_stream(drm_device_t * dev, const uint32_t * buf, | 145 | extern void via_dmablit_handler(drm_device_t *dev, int engine, int from_irq); |
116 | unsigned int size); | 146 | extern void via_init_dmablit(drm_device_t *dev); |
117 | 147 | ||
118 | #endif | 148 | #endif |
diff --git a/drivers/char/drm/via_ds.c b/drivers/char/drm/via_ds.c index 5c71e089246c..9429736b3b96 100644 --- a/drivers/char/drm/via_ds.c +++ b/drivers/char/drm/via_ds.c | |||
@@ -22,14 +22,7 @@ | |||
22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | 22 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
23 | * DEALINGS IN THE SOFTWARE. | 23 | * DEALINGS IN THE SOFTWARE. |
24 | */ | 24 | */ |
25 | #include <linux/module.h> | 25 | #include "drmP.h" |
26 | #include <linux/delay.h> | ||
27 | #include <linux/errno.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/poll.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <asm/io.h> | ||
33 | 26 | ||
34 | #include "via_ds.h" | 27 | #include "via_ds.h" |
35 | extern unsigned int VIA_DEBUG; | 28 | extern unsigned int VIA_DEBUG; |
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c index d023add1929b..56d7e3daea12 100644 --- a/drivers/char/drm/via_irq.c +++ b/drivers/char/drm/via_irq.c | |||
@@ -50,6 +50,15 @@ | |||
50 | #define VIA_IRQ_HQV1_ENABLE (1 << 25) | 50 | #define VIA_IRQ_HQV1_ENABLE (1 << 25) |
51 | #define VIA_IRQ_HQV0_PENDING (1 << 9) | 51 | #define VIA_IRQ_HQV0_PENDING (1 << 9) |
52 | #define VIA_IRQ_HQV1_PENDING (1 << 10) | 52 | #define VIA_IRQ_HQV1_PENDING (1 << 10) |
53 | #define VIA_IRQ_DMA0_DD_ENABLE (1 << 20) | ||
54 | #define VIA_IRQ_DMA0_TD_ENABLE (1 << 21) | ||
55 | #define VIA_IRQ_DMA1_DD_ENABLE (1 << 22) | ||
56 | #define VIA_IRQ_DMA1_TD_ENABLE (1 << 23) | ||
57 | #define VIA_IRQ_DMA0_DD_PENDING (1 << 4) | ||
58 | #define VIA_IRQ_DMA0_TD_PENDING (1 << 5) | ||
59 | #define VIA_IRQ_DMA1_DD_PENDING (1 << 6) | ||
60 | #define VIA_IRQ_DMA1_TD_PENDING (1 << 7) | ||
61 | |||
53 | 62 | ||
54 | /* | 63 | /* |
55 | * Device-specific IRQs go here. This type might need to be extended with | 64 | * Device-specific IRQs go here. This type might need to be extended with |
@@ -61,13 +70,24 @@ static maskarray_t via_pro_group_a_irqs[] = { | |||
61 | {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, | 70 | {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, |
62 | 0x00000000}, | 71 | 0x00000000}, |
63 | {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, | 72 | {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, |
64 | 0x00000000} | 73 | 0x00000000}, |
74 | {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, | ||
75 | VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, | ||
76 | {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1, | ||
77 | VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, | ||
65 | }; | 78 | }; |
66 | static int via_num_pro_group_a = | 79 | static int via_num_pro_group_a = |
67 | sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t); | 80 | sizeof(via_pro_group_a_irqs) / sizeof(maskarray_t); |
81 | static int via_irqmap_pro_group_a[] = {0, 1, -1, 2, -1, 3}; | ||
68 | 82 | ||
69 | static maskarray_t via_unichrome_irqs[] = { }; | 83 | static maskarray_t via_unichrome_irqs[] = { |
84 | {VIA_IRQ_DMA0_TD_ENABLE, VIA_IRQ_DMA0_TD_PENDING, VIA_PCI_DMA_CSR0, | ||
85 | VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008}, | ||
86 | {VIA_IRQ_DMA1_TD_ENABLE, VIA_IRQ_DMA1_TD_PENDING, VIA_PCI_DMA_CSR1, | ||
87 | VIA_DMA_CSR_TA | VIA_DMA_CSR_TD, 0x00000008} | ||
88 | }; | ||
70 | static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t); | 89 | static int via_num_unichrome = sizeof(via_unichrome_irqs) / sizeof(maskarray_t); |
90 | static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1}; | ||
71 | 91 | ||
72 | static unsigned time_diff(struct timeval *now, struct timeval *then) | 92 | static unsigned time_diff(struct timeval *now, struct timeval *then) |
73 | { | 93 | { |
@@ -113,6 +133,11 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS) | |||
113 | atomic_inc(&cur_irq->irq_received); | 133 | atomic_inc(&cur_irq->irq_received); |
114 | DRM_WAKEUP(&cur_irq->irq_queue); | 134 | DRM_WAKEUP(&cur_irq->irq_queue); |
115 | handled = 1; | 135 | handled = 1; |
136 | if (dev_priv->irq_map[drm_via_irq_dma0_td] == i) { | ||
137 | via_dmablit_handler(dev, 0, 1); | ||
138 | } else if (dev_priv->irq_map[drm_via_irq_dma1_td] == i) { | ||
139 | via_dmablit_handler(dev, 1, 1); | ||
140 | } | ||
116 | } | 141 | } |
117 | cur_irq++; | 142 | cur_irq++; |
118 | } | 143 | } |
@@ -165,7 +190,7 @@ int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence) | |||
165 | return ret; | 190 | return ret; |
166 | } | 191 | } |
167 | 192 | ||
168 | static int | 193 | int |
169 | via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence, | 194 | via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence, |
170 | unsigned int *sequence) | 195 | unsigned int *sequence) |
171 | { | 196 | { |
@@ -174,6 +199,7 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence, | |||
174 | drm_via_irq_t *cur_irq = dev_priv->via_irqs; | 199 | drm_via_irq_t *cur_irq = dev_priv->via_irqs; |
175 | int ret = 0; | 200 | int ret = 0; |
176 | maskarray_t *masks = dev_priv->irq_masks; | 201 | maskarray_t *masks = dev_priv->irq_masks; |
202 | int real_irq; | ||
177 | 203 | ||
178 | DRM_DEBUG("%s\n", __FUNCTION__); | 204 | DRM_DEBUG("%s\n", __FUNCTION__); |
179 | 205 | ||
@@ -182,15 +208,23 @@ via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence, | |||
182 | return DRM_ERR(EINVAL); | 208 | return DRM_ERR(EINVAL); |
183 | } | 209 | } |
184 | 210 | ||
185 | if (irq >= dev_priv->num_irqs) { | 211 | if (irq >= drm_via_irq_num) { |
186 | DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, | 212 | DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, |
187 | irq); | 213 | irq); |
188 | return DRM_ERR(EINVAL); | 214 | return DRM_ERR(EINVAL); |
189 | } | 215 | } |
190 | 216 | ||
191 | cur_irq += irq; | 217 | real_irq = dev_priv->irq_map[irq]; |
218 | |||
219 | if (real_irq < 0) { | ||
220 | DRM_ERROR("%s Video IRQ %d not available on this hardware.\n", | ||
221 | __FUNCTION__, irq); | ||
222 | return DRM_ERR(EINVAL); | ||
223 | } | ||
224 | |||
225 | cur_irq += real_irq; | ||
192 | 226 | ||
193 | if (masks[irq][2] && !force_sequence) { | 227 | if (masks[real_irq][2] && !force_sequence) { |
194 | DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ, | 228 | DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ, |
195 | ((VIA_READ(masks[irq][2]) & masks[irq][3]) == | 229 | ((VIA_READ(masks[irq][2]) & masks[irq][3]) == |
196 | masks[irq][4])); | 230 | masks[irq][4])); |
@@ -226,6 +260,8 @@ void via_driver_irq_preinstall(drm_device_t * dev) | |||
226 | via_pro_group_a_irqs : via_unichrome_irqs; | 260 | via_pro_group_a_irqs : via_unichrome_irqs; |
227 | dev_priv->num_irqs = (dev_priv->pro_group_a) ? | 261 | dev_priv->num_irqs = (dev_priv->pro_group_a) ? |
228 | via_num_pro_group_a : via_num_unichrome; | 262 | via_num_pro_group_a : via_num_unichrome; |
263 | dev_priv->irq_map = (dev_priv->pro_group_a) ? | ||
264 | via_irqmap_pro_group_a : via_irqmap_unichrome; | ||
229 | 265 | ||
230 | for (i = 0; i < dev_priv->num_irqs; ++i) { | 266 | for (i = 0; i < dev_priv->num_irqs; ++i) { |
231 | atomic_set(&cur_irq->irq_received, 0); | 267 | atomic_set(&cur_irq->irq_received, 0); |
@@ -241,7 +277,7 @@ void via_driver_irq_preinstall(drm_device_t * dev) | |||
241 | 277 | ||
242 | dev_priv->last_vblank_valid = 0; | 278 | dev_priv->last_vblank_valid = 0; |
243 | 279 | ||
244 | // Clear VSync interrupt regs | 280 | /* Clear VSync interrupt regs */ |
245 | status = VIA_READ(VIA_REG_INTERRUPT); | 281 | status = VIA_READ(VIA_REG_INTERRUPT); |
246 | VIA_WRITE(VIA_REG_INTERRUPT, status & | 282 | VIA_WRITE(VIA_REG_INTERRUPT, status & |
247 | ~(dev_priv->irq_enable_mask)); | 283 | ~(dev_priv->irq_enable_mask)); |
@@ -291,8 +327,7 @@ void via_driver_irq_uninstall(drm_device_t * dev) | |||
291 | 327 | ||
292 | int via_wait_irq(DRM_IOCTL_ARGS) | 328 | int via_wait_irq(DRM_IOCTL_ARGS) |
293 | { | 329 | { |
294 | drm_file_t *priv = filp->private_data; | 330 | DRM_DEVICE; |
295 | drm_device_t *dev = priv->head->dev; | ||
296 | drm_via_irqwait_t __user *argp = (void __user *)data; | 331 | drm_via_irqwait_t __user *argp = (void __user *)data; |
297 | drm_via_irqwait_t irqwait; | 332 | drm_via_irqwait_t irqwait; |
298 | struct timeval now; | 333 | struct timeval now; |
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c index 6bd6ac52ad1b..c6a08e96285b 100644 --- a/drivers/char/drm/via_map.c +++ b/drivers/char/drm/via_map.c | |||
@@ -27,16 +27,10 @@ | |||
27 | 27 | ||
28 | static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init) | 28 | static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init) |
29 | { | 29 | { |
30 | drm_via_private_t *dev_priv; | 30 | drm_via_private_t *dev_priv = dev->dev_private; |
31 | 31 | ||
32 | DRM_DEBUG("%s\n", __FUNCTION__); | 32 | DRM_DEBUG("%s\n", __FUNCTION__); |
33 | 33 | ||
34 | dev_priv = drm_alloc(sizeof(drm_via_private_t), DRM_MEM_DRIVER); | ||
35 | if (dev_priv == NULL) | ||
36 | return -ENOMEM; | ||
37 | |||
38 | memset(dev_priv, 0, sizeof(drm_via_private_t)); | ||
39 | |||
40 | DRM_GETSAREA(); | 34 | DRM_GETSAREA(); |
41 | if (!dev_priv->sarea) { | 35 | if (!dev_priv->sarea) { |
42 | DRM_ERROR("could not find sarea!\n"); | 36 | DRM_ERROR("could not find sarea!\n"); |
@@ -67,7 +61,8 @@ static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init) | |||
67 | dev_priv->agpAddr = init->agpAddr; | 61 | dev_priv->agpAddr = init->agpAddr; |
68 | 62 | ||
69 | via_init_futex(dev_priv); | 63 | via_init_futex(dev_priv); |
70 | dev_priv->pro_group_a = (dev->pdev->device == 0x3118); | 64 | |
65 | via_init_dmablit(dev); | ||
71 | 66 | ||
72 | dev->dev_private = (void *)dev_priv; | 67 | dev->dev_private = (void *)dev_priv; |
73 | return 0; | 68 | return 0; |
@@ -75,15 +70,7 @@ static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init) | |||
75 | 70 | ||
76 | int via_do_cleanup_map(drm_device_t * dev) | 71 | int via_do_cleanup_map(drm_device_t * dev) |
77 | { | 72 | { |
78 | if (dev->dev_private) { | 73 | via_dma_cleanup(dev); |
79 | |||
80 | drm_via_private_t *dev_priv = dev->dev_private; | ||
81 | |||
82 | via_dma_cleanup(dev); | ||
83 | |||
84 | drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER); | ||
85 | dev->dev_private = NULL; | ||
86 | } | ||
87 | 74 | ||
88 | return 0; | 75 | return 0; |
89 | } | 76 | } |
@@ -107,3 +94,29 @@ int via_map_init(DRM_IOCTL_ARGS) | |||
107 | 94 | ||
108 | return -EINVAL; | 95 | return -EINVAL; |
109 | } | 96 | } |
97 | |||
98 | int via_driver_load(drm_device_t *dev, unsigned long chipset) | ||
99 | { | ||
100 | drm_via_private_t *dev_priv; | ||
101 | |||
102 | dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER); | ||
103 | if (dev_priv == NULL) | ||
104 | return DRM_ERR(ENOMEM); | ||
105 | |||
106 | dev->dev_private = (void *)dev_priv; | ||
107 | |||
108 | if (chipset == VIA_PRO_GROUP_A) | ||
109 | dev_priv->pro_group_a = 1; | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | int via_driver_unload(drm_device_t *dev) | ||
115 | { | ||
116 | drm_via_private_t *dev_priv = dev->dev_private; | ||
117 | |||
118 | drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER); | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c index 3baddacdff26..33e0cb12e4c3 100644 --- a/drivers/char/drm/via_mm.c +++ b/drivers/char/drm/via_mm.c | |||
@@ -42,7 +42,7 @@ static int via_agp_free(drm_via_mem_t * mem); | |||
42 | static int via_fb_alloc(drm_via_mem_t * mem); | 42 | static int via_fb_alloc(drm_via_mem_t * mem); |
43 | static int via_fb_free(drm_via_mem_t * mem); | 43 | static int via_fb_free(drm_via_mem_t * mem); |
44 | 44 | ||
45 | static int add_alloc_set(int context, int type, unsigned int val) | 45 | static int add_alloc_set(int context, int type, unsigned long val) |
46 | { | 46 | { |
47 | int i, retval = 0; | 47 | int i, retval = 0; |
48 | 48 | ||
@@ -56,7 +56,7 @@ static int add_alloc_set(int context, int type, unsigned int val) | |||
56 | return retval; | 56 | return retval; |
57 | } | 57 | } |
58 | 58 | ||
59 | static int del_alloc_set(int context, int type, unsigned int val) | 59 | static int del_alloc_set(int context, int type, unsigned long val) |
60 | { | 60 | { |
61 | int i, retval = 0; | 61 | int i, retval = 0; |
62 | 62 | ||
@@ -199,13 +199,13 @@ int via_mem_alloc(DRM_IOCTL_ARGS) | |||
199 | sizeof(mem)); | 199 | sizeof(mem)); |
200 | 200 | ||
201 | switch (mem.type) { | 201 | switch (mem.type) { |
202 | case VIDEO: | 202 | case VIA_MEM_VIDEO: |
203 | if (via_fb_alloc(&mem) < 0) | 203 | if (via_fb_alloc(&mem) < 0) |
204 | return -EFAULT; | 204 | return -EFAULT; |
205 | DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, | 205 | DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, |
206 | sizeof(mem)); | 206 | sizeof(mem)); |
207 | return 0; | 207 | return 0; |
208 | case AGP: | 208 | case VIA_MEM_AGP: |
209 | if (via_agp_alloc(&mem) < 0) | 209 | if (via_agp_alloc(&mem) < 0) |
210 | return -EFAULT; | 210 | return -EFAULT; |
211 | DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, | 211 | DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, |
@@ -232,7 +232,7 @@ static int via_fb_alloc(drm_via_mem_t * mem) | |||
232 | if (block) { | 232 | if (block) { |
233 | fb.offset = block->ofs; | 233 | fb.offset = block->ofs; |
234 | fb.free = (unsigned long)block; | 234 | fb.free = (unsigned long)block; |
235 | if (!add_alloc_set(fb.context, VIDEO, fb.free)) { | 235 | if (!add_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) { |
236 | DRM_DEBUG("adding to allocation set fails\n"); | 236 | DRM_DEBUG("adding to allocation set fails\n"); |
237 | via_mmFreeMem((PMemBlock) fb.free); | 237 | via_mmFreeMem((PMemBlock) fb.free); |
238 | retval = -1; | 238 | retval = -1; |
@@ -269,7 +269,7 @@ static int via_agp_alloc(drm_via_mem_t * mem) | |||
269 | if (block) { | 269 | if (block) { |
270 | agp.offset = block->ofs; | 270 | agp.offset = block->ofs; |
271 | agp.free = (unsigned long)block; | 271 | agp.free = (unsigned long)block; |
272 | if (!add_alloc_set(agp.context, AGP, agp.free)) { | 272 | if (!add_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) { |
273 | DRM_DEBUG("adding to allocation set fails\n"); | 273 | DRM_DEBUG("adding to allocation set fails\n"); |
274 | via_mmFreeMem((PMemBlock) agp.free); | 274 | via_mmFreeMem((PMemBlock) agp.free); |
275 | retval = -1; | 275 | retval = -1; |
@@ -297,11 +297,11 @@ int via_mem_free(DRM_IOCTL_ARGS) | |||
297 | 297 | ||
298 | switch (mem.type) { | 298 | switch (mem.type) { |
299 | 299 | ||
300 | case VIDEO: | 300 | case VIA_MEM_VIDEO: |
301 | if (via_fb_free(&mem) == 0) | 301 | if (via_fb_free(&mem) == 0) |
302 | return 0; | 302 | return 0; |
303 | break; | 303 | break; |
304 | case AGP: | 304 | case VIA_MEM_AGP: |
305 | if (via_agp_free(&mem) == 0) | 305 | if (via_agp_free(&mem) == 0) |
306 | return 0; | 306 | return 0; |
307 | break; | 307 | break; |
@@ -329,7 +329,7 @@ static int via_fb_free(drm_via_mem_t * mem) | |||
329 | 329 | ||
330 | via_mmFreeMem((PMemBlock) fb.free); | 330 | via_mmFreeMem((PMemBlock) fb.free); |
331 | 331 | ||
332 | if (!del_alloc_set(fb.context, VIDEO, fb.free)) { | 332 | if (!del_alloc_set(fb.context, VIA_MEM_VIDEO, fb.free)) { |
333 | retval = -1; | 333 | retval = -1; |
334 | } | 334 | } |
335 | 335 | ||
@@ -352,7 +352,7 @@ static int via_agp_free(drm_via_mem_t * mem) | |||
352 | 352 | ||
353 | via_mmFreeMem((PMemBlock) agp.free); | 353 | via_mmFreeMem((PMemBlock) agp.free); |
354 | 354 | ||
355 | if (!del_alloc_set(agp.context, AGP, agp.free)) { | 355 | if (!del_alloc_set(agp.context, VIA_MEM_AGP, agp.free)) { |
356 | retval = -1; | 356 | retval = -1; |
357 | } | 357 | } |
358 | 358 | ||
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c index 4ac495f297f7..70c897c88766 100644 --- a/drivers/char/drm/via_verifier.c +++ b/drivers/char/drm/via_verifier.c | |||
@@ -237,7 +237,7 @@ static hazard_t table3[256]; | |||
237 | static __inline__ int | 237 | static __inline__ int |
238 | eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words) | 238 | eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words) |
239 | { | 239 | { |
240 | if ((*buf - buf_end) >= num_words) { | 240 | if ((buf_end - *buf) >= num_words) { |
241 | *buf += num_words; | 241 | *buf += num_words; |
242 | return 0; | 242 | return 0; |
243 | } | 243 | } |
@@ -249,14 +249,14 @@ eat_words(const uint32_t ** buf, const uint32_t * buf_end, unsigned num_words) | |||
249 | * Partially stolen from drm_memory.h | 249 | * Partially stolen from drm_memory.h |
250 | */ | 250 | */ |
251 | 251 | ||
252 | static __inline__ drm_map_t *via_drm_lookup_agp_map(drm_via_state_t * seq, | 252 | static __inline__ drm_local_map_t *via_drm_lookup_agp_map(drm_via_state_t *seq, |
253 | unsigned long offset, | 253 | unsigned long offset, |
254 | unsigned long size, | 254 | unsigned long size, |
255 | drm_device_t * dev) | 255 | drm_device_t * dev) |
256 | { | 256 | { |
257 | struct list_head *list; | 257 | struct list_head *list; |
258 | drm_map_list_t *r_list; | 258 | drm_map_list_t *r_list; |
259 | drm_map_t *map = seq->map_cache; | 259 | drm_local_map_t *map = seq->map_cache; |
260 | 260 | ||
261 | if (map && map->offset <= offset | 261 | if (map && map->offset <= offset |
262 | && (offset + size) <= (map->offset + map->size)) { | 262 | && (offset + size) <= (map->offset + map->size)) { |
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h index eb4eda344345..256590fcc22a 100644 --- a/drivers/char/drm/via_verifier.h +++ b/drivers/char/drm/via_verifier.h | |||
@@ -47,7 +47,7 @@ typedef struct { | |||
47 | int agp_texture; | 47 | int agp_texture; |
48 | int multitex; | 48 | int multitex; |
49 | drm_device_t *dev; | 49 | drm_device_t *dev; |
50 | drm_map_t *map_cache; | 50 | drm_local_map_t *map_cache; |
51 | uint32_t vertex_count; | 51 | uint32_t vertex_count; |
52 | int agp; | 52 | int agp; |
53 | const uint32_t *buf_start; | 53 | const uint32_t *buf_start; |
@@ -55,5 +55,7 @@ typedef struct { | |||
55 | 55 | ||
56 | extern int via_verify_command_stream(const uint32_t * buf, unsigned int size, | 56 | extern int via_verify_command_stream(const uint32_t * buf, unsigned int size, |
57 | drm_device_t * dev, int agp); | 57 | drm_device_t * dev, int agp); |
58 | extern int via_parse_command_stream(drm_device_t *dev, const uint32_t *buf, | ||
59 | unsigned int size); | ||
58 | 60 | ||
59 | #endif | 61 | #endif |
diff --git a/drivers/char/drm/via_video.c b/drivers/char/drm/via_video.c index 7fab9fbdf424..300ac61b09ed 100644 --- a/drivers/char/drm/via_video.c +++ b/drivers/char/drm/via_video.c | |||
@@ -50,8 +50,11 @@ void via_release_futex(drm_via_private_t * dev_priv, int context) | |||
50 | unsigned int i; | 50 | unsigned int i; |
51 | volatile int *lock; | 51 | volatile int *lock; |
52 | 52 | ||
53 | if (!dev_priv->sarea_priv) | ||
54 | return; | ||
55 | |||
53 | for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) { | 56 | for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) { |
54 | lock = (int *)XVMCLOCKPTR(dev_priv->sarea_priv, i); | 57 | lock = (volatile int *)XVMCLOCKPTR(dev_priv->sarea_priv, i); |
55 | if ((_DRM_LOCKING_CONTEXT(*lock) == context)) { | 58 | if ((_DRM_LOCKING_CONTEXT(*lock) == context)) { |
56 | if (_DRM_LOCK_IS_HELD(*lock) | 59 | if (_DRM_LOCK_IS_HELD(*lock) |
57 | && (*lock & _DRM_LOCK_CONT)) { | 60 | && (*lock & _DRM_LOCK_CONT)) { |
@@ -79,7 +82,7 @@ int via_decoder_futex(DRM_IOCTL_ARGS) | |||
79 | if (fx.lock > VIA_NR_XVMC_LOCKS) | 82 | if (fx.lock > VIA_NR_XVMC_LOCKS) |
80 | return -EFAULT; | 83 | return -EFAULT; |
81 | 84 | ||
82 | lock = (int *)XVMCLOCKPTR(sAPriv, fx.lock); | 85 | lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx.lock); |
83 | 86 | ||
84 | switch (fx.func) { | 87 | switch (fx.func) { |
85 | case VIA_FUTEX_WAIT: | 88 | case VIA_FUTEX_WAIT: |
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index 8693835cb2d5..e233cf280bc0 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c | |||
@@ -165,7 +165,7 @@ static int dsp56k_reset(void) | |||
165 | return 0; | 165 | return 0; |
166 | } | 166 | } |
167 | 167 | ||
168 | static int dsp56k_upload(u_char *bin, int len) | 168 | static int dsp56k_upload(u_char __user *bin, int len) |
169 | { | 169 | { |
170 | int i; | 170 | int i; |
171 | u_char *p; | 171 | u_char *p; |
@@ -199,7 +199,7 @@ static int dsp56k_upload(u_char *bin, int len) | |||
199 | return 0; | 199 | return 0; |
200 | } | 200 | } |
201 | 201 | ||
202 | static ssize_t dsp56k_read(struct file *file, char *buf, size_t count, | 202 | static ssize_t dsp56k_read(struct file *file, char __user *buf, size_t count, |
203 | loff_t *ppos) | 203 | loff_t *ppos) |
204 | { | 204 | { |
205 | struct inode *inode = file->f_dentry->d_inode; | 205 | struct inode *inode = file->f_dentry->d_inode; |
@@ -225,10 +225,10 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count, | |||
225 | } | 225 | } |
226 | case 2: /* 16 bit */ | 226 | case 2: /* 16 bit */ |
227 | { | 227 | { |
228 | short *data; | 228 | short __user *data; |
229 | 229 | ||
230 | count /= 2; | 230 | count /= 2; |
231 | data = (short*) buf; | 231 | data = (short __user *) buf; |
232 | handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE, | 232 | handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE, |
233 | put_user(dsp56k_host_interface.data.w[1], data+n++)); | 233 | put_user(dsp56k_host_interface.data.w[1], data+n++)); |
234 | return 2*n; | 234 | return 2*n; |
@@ -244,10 +244,10 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count, | |||
244 | } | 244 | } |
245 | case 4: /* 32 bit */ | 245 | case 4: /* 32 bit */ |
246 | { | 246 | { |
247 | long *data; | 247 | long __user *data; |
248 | 248 | ||
249 | count /= 4; | 249 | count /= 4; |
250 | data = (long*) buf; | 250 | data = (long __user *) buf; |
251 | handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE, | 251 | handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_RECEIVE, |
252 | put_user(dsp56k_host_interface.data.l, data+n++)); | 252 | put_user(dsp56k_host_interface.data.l, data+n++)); |
253 | return 4*n; | 253 | return 4*n; |
@@ -262,7 +262,7 @@ static ssize_t dsp56k_read(struct file *file, char *buf, size_t count, | |||
262 | } | 262 | } |
263 | } | 263 | } |
264 | 264 | ||
265 | static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count, | 265 | static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t count, |
266 | loff_t *ppos) | 266 | loff_t *ppos) |
267 | { | 267 | { |
268 | struct inode *inode = file->f_dentry->d_inode; | 268 | struct inode *inode = file->f_dentry->d_inode; |
@@ -287,10 +287,10 @@ static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count, | |||
287 | } | 287 | } |
288 | case 2: /* 16 bit */ | 288 | case 2: /* 16 bit */ |
289 | { | 289 | { |
290 | const short *data; | 290 | const short __user *data; |
291 | 291 | ||
292 | count /= 2; | 292 | count /= 2; |
293 | data = (const short *)buf; | 293 | data = (const short __user *)buf; |
294 | handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, | 294 | handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, |
295 | get_user(dsp56k_host_interface.data.w[1], data+n++)); | 295 | get_user(dsp56k_host_interface.data.w[1], data+n++)); |
296 | return 2*n; | 296 | return 2*n; |
@@ -306,10 +306,10 @@ static ssize_t dsp56k_write(struct file *file, const char *buf, size_t count, | |||
306 | } | 306 | } |
307 | case 4: /* 32 bit */ | 307 | case 4: /* 32 bit */ |
308 | { | 308 | { |
309 | const long *data; | 309 | const long __user *data; |
310 | 310 | ||
311 | count /= 4; | 311 | count /= 4; |
312 | data = (const long *)buf; | 312 | data = (const long __user *)buf; |
313 | handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, | 313 | handshake(count, dsp56k.maxio, dsp56k.timeout, DSP56K_TRANSMIT, |
314 | get_user(dsp56k_host_interface.data.l, data+n++)); | 314 | get_user(dsp56k_host_interface.data.l, data+n++)); |
315 | return 4*n; | 315 | return 4*n; |
@@ -328,6 +328,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, | |||
328 | unsigned int cmd, unsigned long arg) | 328 | unsigned int cmd, unsigned long arg) |
329 | { | 329 | { |
330 | int dev = iminor(inode) & 0x0f; | 330 | int dev = iminor(inode) & 0x0f; |
331 | void __user *argp = (void __user *)arg; | ||
331 | 332 | ||
332 | switch(dev) | 333 | switch(dev) |
333 | { | 334 | { |
@@ -336,9 +337,9 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, | |||
336 | switch(cmd) { | 337 | switch(cmd) { |
337 | case DSP56K_UPLOAD: | 338 | case DSP56K_UPLOAD: |
338 | { | 339 | { |
339 | char *bin; | 340 | char __user *bin; |
340 | int r, len; | 341 | int r, len; |
341 | struct dsp56k_upload *binary = (struct dsp56k_upload *) arg; | 342 | struct dsp56k_upload __user *binary = argp; |
342 | 343 | ||
343 | if(get_user(len, &binary->len) < 0) | 344 | if(get_user(len, &binary->len) < 0) |
344 | return -EFAULT; | 345 | return -EFAULT; |
@@ -372,7 +373,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, | |||
372 | case DSP56K_HOST_FLAGS: | 373 | case DSP56K_HOST_FLAGS: |
373 | { | 374 | { |
374 | int dir, out, status; | 375 | int dir, out, status; |
375 | struct dsp56k_host_flags *hf = (struct dsp56k_host_flags*) arg; | 376 | struct dsp56k_host_flags __user *hf = argp; |
376 | 377 | ||
377 | if(get_user(dir, &hf->dir) < 0) | 378 | if(get_user(dir, &hf->dir) < 0) |
378 | return -EFAULT; | 379 | return -EFAULT; |
diff --git a/drivers/char/esp.c b/drivers/char/esp.c index e469f641c728..dd5dc8fa490d 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c | |||
@@ -160,7 +160,6 @@ static void rs_wait_until_sent(struct tty_struct *, int); | |||
160 | * memory if large numbers of serial ports are open. | 160 | * memory if large numbers of serial ports are open. |
161 | */ | 161 | */ |
162 | static unsigned char *tmp_buf; | 162 | static unsigned char *tmp_buf; |
163 | static DECLARE_MUTEX(tmp_buf_sem); | ||
164 | 163 | ||
165 | static inline int serial_paranoia_check(struct esp_struct *info, | 164 | static inline int serial_paranoia_check(struct esp_struct *info, |
166 | char *name, const char *routine) | 165 | char *name, const char *routine) |
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c index 204a7302a4a9..e38a5f0e07bb 100644 --- a/drivers/char/generic_serial.c +++ b/drivers/char/generic_serial.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #define DEBUG | 34 | #define DEBUG |
35 | 35 | ||
36 | static char * tmp_buf; | 36 | static char * tmp_buf; |
37 | static DECLARE_MUTEX(tmp_buf_sem); | ||
38 | 37 | ||
39 | static int gs_debug; | 38 | static int gs_debug; |
40 | 39 | ||
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 704c3c07f0ab..29c41f4418c0 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -534,7 +534,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, | |||
534 | return virtr + wrote; | 534 | return virtr + wrote; |
535 | } | 535 | } |
536 | 536 | ||
537 | #if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) | 537 | #if defined(CONFIG_ISA) || !defined(__mc68000__) |
538 | static ssize_t read_port(struct file * file, char __user * buf, | 538 | static ssize_t read_port(struct file * file, char __user * buf, |
539 | size_t count, loff_t *ppos) | 539 | size_t count, loff_t *ppos) |
540 | { | 540 | { |
@@ -795,7 +795,7 @@ static struct file_operations null_fops = { | |||
795 | .write = write_null, | 795 | .write = write_null, |
796 | }; | 796 | }; |
797 | 797 | ||
798 | #if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) | 798 | #if defined(CONFIG_ISA) || !defined(__mc68000__) |
799 | static struct file_operations port_fops = { | 799 | static struct file_operations port_fops = { |
800 | .llseek = memory_lseek, | 800 | .llseek = memory_lseek, |
801 | .read = read_port, | 801 | .read = read_port, |
@@ -865,7 +865,7 @@ static int memory_open(struct inode * inode, struct file * filp) | |||
865 | case 3: | 865 | case 3: |
866 | filp->f_op = &null_fops; | 866 | filp->f_op = &null_fops; |
867 | break; | 867 | break; |
868 | #if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) | 868 | #if defined(CONFIG_ISA) || !defined(__mc68000__) |
869 | case 4: | 869 | case 4: |
870 | filp->f_op = &port_fops; | 870 | filp->f_op = &port_fops; |
871 | break; | 871 | break; |
@@ -912,7 +912,7 @@ static const struct { | |||
912 | {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, | 912 | {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, |
913 | {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, | 913 | {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, |
914 | {3, "null", S_IRUGO | S_IWUGO, &null_fops}, | 914 | {3, "null", S_IRUGO | S_IWUGO, &null_fops}, |
915 | #if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) | 915 | #if defined(CONFIG_ISA) || !defined(__mc68000__) |
916 | {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, | 916 | {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, |
917 | #endif | 917 | #endif |
918 | {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, | 918 | {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, |
diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 050e70ee5920..119e629656b7 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c | |||
@@ -82,7 +82,6 @@ | |||
82 | static struct riscom_board * IRQ_to_board[16]; | 82 | static struct riscom_board * IRQ_to_board[16]; |
83 | static struct tty_driver *riscom_driver; | 83 | static struct tty_driver *riscom_driver; |
84 | static unsigned char * tmp_buf; | 84 | static unsigned char * tmp_buf; |
85 | static DECLARE_MUTEX(tmp_buf_sem); | ||
86 | 85 | ||
87 | static unsigned long baud_table[] = { | 86 | static unsigned long baud_table[] = { |
88 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | 87 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, |
diff --git a/drivers/char/scc.h b/drivers/char/scc.h index 51810f72f1a9..93998f5baff5 100644 --- a/drivers/char/scc.h +++ b/drivers/char/scc.h | |||
@@ -399,7 +399,7 @@ struct scc_port { | |||
399 | __asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\ | 399 | __asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\ |
400 | } while (0) | 400 | } while (0) |
401 | 401 | ||
402 | extern unsigned char scc_shadow[2][16]; | 402 | static unsigned char scc_shadow[2][16]; |
403 | 403 | ||
404 | /* The following functions should relax the somehow complicated | 404 | /* The following functions should relax the somehow complicated |
405 | * register access of the SCC. _SCCwrite() stores all written values | 405 | * register access of the SCC. _SCCwrite() stores all written values |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index f36342ae8e7e..037c940ac71b 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
@@ -129,7 +129,6 @@ struct cyclades_port cy_port[] = { | |||
129 | * memory if large numbers of serial ports are open. | 129 | * memory if large numbers of serial ports are open. |
130 | */ | 130 | */ |
131 | static unsigned char *tmp_buf = 0; | 131 | static unsigned char *tmp_buf = 0; |
132 | DECLARE_MUTEX(tmp_buf_sem); | ||
133 | 132 | ||
134 | /* | 133 | /* |
135 | * This is used to look up the divisor speeds and the timeouts | 134 | * This is used to look up the divisor speeds and the timeouts |
diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 0a574bdbce36..5343e9fc6ab7 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c | |||
@@ -184,7 +184,6 @@ static int sx_poll = HZ; | |||
184 | 184 | ||
185 | static struct tty_driver *specialix_driver; | 185 | static struct tty_driver *specialix_driver; |
186 | static unsigned char * tmp_buf; | 186 | static unsigned char * tmp_buf; |
187 | static DECLARE_MUTEX(tmp_buf_sem); | ||
188 | 187 | ||
189 | static unsigned long baud_table[] = { | 188 | static unsigned long baud_table[] = { |
190 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, | 189 | 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, |
@@ -2556,8 +2555,6 @@ static int __init specialix_init_module(void) | |||
2556 | 2555 | ||
2557 | func_enter(); | 2556 | func_enter(); |
2558 | 2557 | ||
2559 | init_MUTEX(&tmp_buf_sem); /* Init de the semaphore - pvdl */ | ||
2560 | |||
2561 | if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { | 2558 | if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { |
2562 | for(i = 0; i < SX_NBOARD; i++) { | 2559 | for(i = 0; i < SX_NBOARD; i++) { |
2563 | sx_board[i].base = iobase[i]; | 2560 | sx_board[i].base = iobase[i]; |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 9f1b466c4f84..ede688a4e141 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -951,7 +951,6 @@ static void* mgsl_get_text_ptr(void) | |||
951 | * memory if large numbers of serial ports are open. | 951 | * memory if large numbers of serial ports are open. |
952 | */ | 952 | */ |
953 | static unsigned char *tmp_buf; | 953 | static unsigned char *tmp_buf; |
954 | static DECLARE_MUTEX(tmp_buf_sem); | ||
955 | 954 | ||
956 | static inline int mgsl_paranoia_check(struct mgsl_struct *info, | 955 | static inline int mgsl_paranoia_check(struct mgsl_struct *info, |
957 | char *name, const char *routine) | 956 | char *name, const char *routine) |
diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index faee5e7acaf7..4e5360388748 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c | |||
@@ -476,19 +476,19 @@ static struct port_info *get_port_data(struct tty_struct *tty) | |||
476 | */ | 476 | */ |
477 | static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp) | 477 | static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp) |
478 | { | 478 | { |
479 | struct HvLpEvent *hev = &viochar->event; | ||
480 | |||
479 | memset(viochar, 0, sizeof(struct viocharlpevent)); | 481 | memset(viochar, 0, sizeof(struct viocharlpevent)); |
480 | 482 | ||
481 | viochar->event.xFlags.xValid = 1; | 483 | hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK | |
482 | viochar->event.xFlags.xFunction = HvLpEvent_Function_Int; | 484 | HV_LP_EVENT_INT; |
483 | viochar->event.xFlags.xAckInd = HvLpEvent_AckInd_NoAck; | 485 | hev->xType = HvLpEvent_Type_VirtualIo; |
484 | viochar->event.xFlags.xAckType = HvLpEvent_AckType_DeferredAck; | 486 | hev->xSubtype = viomajorsubtype_chario | viochardata; |
485 | viochar->event.xType = HvLpEvent_Type_VirtualIo; | 487 | hev->xSourceLp = HvLpConfig_getLpIndex(); |
486 | viochar->event.xSubtype = viomajorsubtype_chario | viochardata; | 488 | hev->xTargetLp = lp; |
487 | viochar->event.xSourceLp = HvLpConfig_getLpIndex(); | 489 | hev->xSizeMinus1 = sizeof(struct viocharlpevent); |
488 | viochar->event.xTargetLp = lp; | 490 | hev->xSourceInstanceId = viopath_sourceinst(lp); |
489 | viochar->event.xSizeMinus1 = sizeof(struct viocharlpevent); | 491 | hev->xTargetInstanceId = viopath_targetinst(lp); |
490 | viochar->event.xSourceInstanceId = viopath_sourceinst(lp); | ||
491 | viochar->event.xTargetInstanceId = viopath_targetinst(lp); | ||
492 | } | 492 | } |
493 | 493 | ||
494 | /* | 494 | /* |
@@ -752,7 +752,7 @@ static void vioHandleOpenEvent(struct HvLpEvent *event) | |||
752 | struct port_info *pi; | 752 | struct port_info *pi; |
753 | int reject = 0; | 753 | int reject = 0; |
754 | 754 | ||
755 | if (event->xFlags.xFunction == HvLpEvent_Function_Ack) { | 755 | if (hvlpevent_is_ack(event)) { |
756 | if (port >= VTTY_PORTS) | 756 | if (port >= VTTY_PORTS) |
757 | return; | 757 | return; |
758 | 758 | ||
@@ -788,7 +788,7 @@ static void vioHandleOpenEvent(struct HvLpEvent *event) | |||
788 | } | 788 | } |
789 | 789 | ||
790 | /* This had better require an ack, otherwise complain */ | 790 | /* This had better require an ack, otherwise complain */ |
791 | if (event->xFlags.xAckInd != HvLpEvent_AckInd_DoAck) { | 791 | if (!hvlpevent_need_ack(event)) { |
792 | printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n"); | 792 | printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n"); |
793 | return; | 793 | return; |
794 | } | 794 | } |
@@ -856,7 +856,7 @@ static void vioHandleCloseEvent(struct HvLpEvent *event) | |||
856 | struct viocharlpevent *cevent = (struct viocharlpevent *)event; | 856 | struct viocharlpevent *cevent = (struct viocharlpevent *)event; |
857 | u8 port = cevent->virtual_device; | 857 | u8 port = cevent->virtual_device; |
858 | 858 | ||
859 | if (event->xFlags.xFunction == HvLpEvent_Function_Int) { | 859 | if (hvlpevent_is_int(event)) { |
860 | if (port >= VTTY_PORTS) { | 860 | if (port >= VTTY_PORTS) { |
861 | printk(VIOCONS_KERN_WARN | 861 | printk(VIOCONS_KERN_WARN |
862 | "close message from invalid virtual device.\n"); | 862 | "close message from invalid virtual device.\n"); |
@@ -1056,8 +1056,7 @@ static void vioHandleCharEvent(struct HvLpEvent *event) | |||
1056 | vioHandleConfig(event); | 1056 | vioHandleConfig(event); |
1057 | break; | 1057 | break; |
1058 | default: | 1058 | default: |
1059 | if ((event->xFlags.xFunction == HvLpEvent_Function_Int) && | 1059 | if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) { |
1060 | (event->xFlags.xAckInd == HvLpEvent_AckInd_DoAck)) { | ||
1061 | event->xRc = HvLpEvent_Rc_InvalidSubtype; | 1060 | event->xRc = HvLpEvent_Rc_InvalidSubtype; |
1062 | HvCallEvent_ackLpEvent(event); | 1061 | HvCallEvent_ackLpEvent(event); |
1063 | } | 1062 | } |
diff --git a/drivers/dio/dio-driver.c b/drivers/dio/dio-driver.c index ffe6f44ac76f..ca8e69d2f64d 100644 --- a/drivers/dio/dio-driver.c +++ b/drivers/dio/dio-driver.c | |||
@@ -83,7 +83,6 @@ int dio_register_driver(struct dio_driver *drv) | |||
83 | /* initialize common driver fields */ | 83 | /* initialize common driver fields */ |
84 | drv->driver.name = drv->name; | 84 | drv->driver.name = drv->name; |
85 | drv->driver.bus = &dio_bus_type; | 85 | drv->driver.bus = &dio_bus_type; |
86 | drv->driver.probe = dio_device_probe; | ||
87 | 86 | ||
88 | /* register with core */ | 87 | /* register with core */ |
89 | count = driver_register(&drv->driver); | 88 | count = driver_register(&drv->driver); |
@@ -145,7 +144,8 @@ static int dio_bus_match(struct device *dev, struct device_driver *drv) | |||
145 | 144 | ||
146 | struct bus_type dio_bus_type = { | 145 | struct bus_type dio_bus_type = { |
147 | .name = "dio", | 146 | .name = "dio", |
148 | .match = dio_bus_match | 147 | .match = dio_bus_match, |
148 | .probe = dio_device_probe, | ||
149 | }; | 149 | }; |
150 | 150 | ||
151 | 151 | ||
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 70f7ab829d36..86e2234faf80 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -899,6 +899,12 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num | |||
899 | struct pxa_i2c *i2c = adap->algo_data; | 899 | struct pxa_i2c *i2c = adap->algo_data; |
900 | int ret, i; | 900 | int ret, i; |
901 | 901 | ||
902 | /* If the I2C controller is disabled we need to reset it (probably due | ||
903 | to a suspend/resume destroying state). We do this here as we can then | ||
904 | avoid worrying about resuming the controller before its users. */ | ||
905 | if (!(ICR & ICR_IUE)) | ||
906 | i2c_pxa_reset(i2c); | ||
907 | |||
902 | for (i = adap->retries; i >= 0; i--) { | 908 | for (i = adap->retries; i >= 0; i--) { |
903 | ret = i2c_pxa_do_xfer(i2c, msgs, num); | 909 | ret = i2c_pxa_do_xfer(i2c, msgs, num); |
904 | if (ret != I2C_RETRY) | 910 | if (ret != I2C_RETRY) |
@@ -939,7 +945,9 @@ static struct pxa_i2c i2c_pxa = { | |||
939 | static int i2c_pxa_probe(struct platform_device *dev) | 945 | static int i2c_pxa_probe(struct platform_device *dev) |
940 | { | 946 | { |
941 | struct pxa_i2c *i2c = &i2c_pxa; | 947 | struct pxa_i2c *i2c = &i2c_pxa; |
948 | #ifdef CONFIG_I2C_PXA_SLAVE | ||
942 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; | 949 | struct i2c_pxa_platform_data *plat = dev->dev.platform_data; |
950 | #endif | ||
943 | int ret; | 951 | int ret; |
944 | 952 | ||
945 | #ifdef CONFIG_PXA27x | 953 | #ifdef CONFIG_PXA27x |
@@ -1024,5 +1032,7 @@ static void i2c_adap_pxa_exit(void) | |||
1024 | return platform_driver_unregister(&i2c_pxa_driver); | 1032 | return platform_driver_unregister(&i2c_pxa_driver); |
1025 | } | 1033 | } |
1026 | 1034 | ||
1035 | MODULE_LICENSE("GPL"); | ||
1036 | |||
1027 | module_init(i2c_adap_pxa_init); | 1037 | module_init(i2c_adap_pxa_init); |
1028 | module_exit(i2c_adap_pxa_exit); | 1038 | module_exit(i2c_adap_pxa_exit); |
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 52b77477df57..0ce58b506046 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c | |||
@@ -63,13 +63,6 @@ static int i2c_bus_resume(struct device * dev) | |||
63 | return rc; | 63 | return rc; |
64 | } | 64 | } |
65 | 65 | ||
66 | struct bus_type i2c_bus_type = { | ||
67 | .name = "i2c", | ||
68 | .match = i2c_device_match, | ||
69 | .suspend = i2c_bus_suspend, | ||
70 | .resume = i2c_bus_resume, | ||
71 | }; | ||
72 | |||
73 | static int i2c_device_probe(struct device *dev) | 66 | static int i2c_device_probe(struct device *dev) |
74 | { | 67 | { |
75 | return -ENODEV; | 68 | return -ENODEV; |
@@ -80,6 +73,15 @@ static int i2c_device_remove(struct device *dev) | |||
80 | return 0; | 73 | return 0; |
81 | } | 74 | } |
82 | 75 | ||
76 | struct bus_type i2c_bus_type = { | ||
77 | .name = "i2c", | ||
78 | .match = i2c_device_match, | ||
79 | .probe = i2c_device_probe, | ||
80 | .remove = i2c_device_remove, | ||
81 | .suspend = i2c_bus_suspend, | ||
82 | .resume = i2c_bus_resume, | ||
83 | }; | ||
84 | |||
83 | void i2c_adapter_dev_release(struct device *dev) | 85 | void i2c_adapter_dev_release(struct device *dev) |
84 | { | 86 | { |
85 | struct i2c_adapter *adap = dev_to_i2c_adapter(dev); | 87 | struct i2c_adapter *adap = dev_to_i2c_adapter(dev); |
@@ -90,8 +92,6 @@ struct device_driver i2c_adapter_driver = { | |||
90 | .owner = THIS_MODULE, | 92 | .owner = THIS_MODULE, |
91 | .name = "i2c_adapter", | 93 | .name = "i2c_adapter", |
92 | .bus = &i2c_bus_type, | 94 | .bus = &i2c_bus_type, |
93 | .probe = i2c_device_probe, | ||
94 | .remove = i2c_device_remove, | ||
95 | }; | 95 | }; |
96 | 96 | ||
97 | static void i2c_adapter_class_dev_release(struct class_device *dev) | 97 | static void i2c_adapter_class_dev_release(struct class_device *dev) |
@@ -294,8 +294,6 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) | |||
294 | /* add the driver to the list of i2c drivers in the driver core */ | 294 | /* add the driver to the list of i2c drivers in the driver core */ |
295 | driver->driver.owner = owner; | 295 | driver->driver.owner = owner; |
296 | driver->driver.bus = &i2c_bus_type; | 296 | driver->driver.bus = &i2c_bus_type; |
297 | driver->driver.probe = i2c_device_probe; | ||
298 | driver->driver.remove = i2c_device_remove; | ||
299 | 297 | ||
300 | res = driver_register(&driver->driver); | 298 | res = driver_register(&driver->driver); |
301 | if (res) | 299 | if (res) |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 9b2ebd219ad0..ef09a7ef2396 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
@@ -3256,9 +3256,8 @@ sector_t ide_cdrom_capacity (ide_drive_t *drive) | |||
3256 | } | 3256 | } |
3257 | #endif | 3257 | #endif |
3258 | 3258 | ||
3259 | static int ide_cd_remove(struct device *dev) | 3259 | static void ide_cd_remove(ide_drive_t *drive) |
3260 | { | 3260 | { |
3261 | ide_drive_t *drive = to_ide_device(dev); | ||
3262 | struct cdrom_info *info = drive->driver_data; | 3261 | struct cdrom_info *info = drive->driver_data; |
3263 | 3262 | ||
3264 | ide_unregister_subdriver(drive, info->driver); | 3263 | ide_unregister_subdriver(drive, info->driver); |
@@ -3266,8 +3265,6 @@ static int ide_cd_remove(struct device *dev) | |||
3266 | del_gendisk(info->disk); | 3265 | del_gendisk(info->disk); |
3267 | 3266 | ||
3268 | ide_cd_put(info); | 3267 | ide_cd_put(info); |
3269 | |||
3270 | return 0; | ||
3271 | } | 3268 | } |
3272 | 3269 | ||
3273 | static void ide_cd_release(struct kref *kref) | 3270 | static void ide_cd_release(struct kref *kref) |
@@ -3291,7 +3288,7 @@ static void ide_cd_release(struct kref *kref) | |||
3291 | kfree(info); | 3288 | kfree(info); |
3292 | } | 3289 | } |
3293 | 3290 | ||
3294 | static int ide_cd_probe(struct device *); | 3291 | static int ide_cd_probe(ide_drive_t *); |
3295 | 3292 | ||
3296 | #ifdef CONFIG_PROC_FS | 3293 | #ifdef CONFIG_PROC_FS |
3297 | static int proc_idecd_read_capacity | 3294 | static int proc_idecd_read_capacity |
@@ -3317,9 +3314,9 @@ static ide_driver_t ide_cdrom_driver = { | |||
3317 | .owner = THIS_MODULE, | 3314 | .owner = THIS_MODULE, |
3318 | .name = "ide-cdrom", | 3315 | .name = "ide-cdrom", |
3319 | .bus = &ide_bus_type, | 3316 | .bus = &ide_bus_type, |
3320 | .probe = ide_cd_probe, | ||
3321 | .remove = ide_cd_remove, | ||
3322 | }, | 3317 | }, |
3318 | .probe = ide_cd_probe, | ||
3319 | .remove = ide_cd_remove, | ||
3323 | .version = IDECD_VERSION, | 3320 | .version = IDECD_VERSION, |
3324 | .media = ide_cdrom, | 3321 | .media = ide_cdrom, |
3325 | .supports_dsc_overlap = 1, | 3322 | .supports_dsc_overlap = 1, |
@@ -3413,9 +3410,8 @@ static char *ignore = NULL; | |||
3413 | module_param(ignore, charp, 0400); | 3410 | module_param(ignore, charp, 0400); |
3414 | MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); | 3411 | MODULE_DESCRIPTION("ATAPI CD-ROM Driver"); |
3415 | 3412 | ||
3416 | static int ide_cd_probe(struct device *dev) | 3413 | static int ide_cd_probe(ide_drive_t *drive) |
3417 | { | 3414 | { |
3418 | ide_drive_t *drive = to_ide_device(dev); | ||
3419 | struct cdrom_info *info; | 3415 | struct cdrom_info *info; |
3420 | struct gendisk *g; | 3416 | struct gendisk *g; |
3421 | struct request_sense sense; | 3417 | struct request_sense sense; |
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index cab362ea0336..245b508208df 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
@@ -997,9 +997,8 @@ static void ide_cacheflush_p(ide_drive_t *drive) | |||
997 | printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); | 997 | printk(KERN_INFO "%s: wcache flush failed!\n", drive->name); |
998 | } | 998 | } |
999 | 999 | ||
1000 | static int ide_disk_remove(struct device *dev) | 1000 | static void ide_disk_remove(ide_drive_t *drive) |
1001 | { | 1001 | { |
1002 | ide_drive_t *drive = to_ide_device(dev); | ||
1003 | struct ide_disk_obj *idkp = drive->driver_data; | 1002 | struct ide_disk_obj *idkp = drive->driver_data; |
1004 | struct gendisk *g = idkp->disk; | 1003 | struct gendisk *g = idkp->disk; |
1005 | 1004 | ||
@@ -1010,8 +1009,6 @@ static int ide_disk_remove(struct device *dev) | |||
1010 | ide_cacheflush_p(drive); | 1009 | ide_cacheflush_p(drive); |
1011 | 1010 | ||
1012 | ide_disk_put(idkp); | 1011 | ide_disk_put(idkp); |
1013 | |||
1014 | return 0; | ||
1015 | } | 1012 | } |
1016 | 1013 | ||
1017 | static void ide_disk_release(struct kref *kref) | 1014 | static void ide_disk_release(struct kref *kref) |
@@ -1027,12 +1024,10 @@ static void ide_disk_release(struct kref *kref) | |||
1027 | kfree(idkp); | 1024 | kfree(idkp); |
1028 | } | 1025 | } |
1029 | 1026 | ||
1030 | static int ide_disk_probe(struct device *dev); | 1027 | static int ide_disk_probe(ide_drive_t *drive); |
1031 | 1028 | ||
1032 | static void ide_device_shutdown(struct device *dev) | 1029 | static void ide_device_shutdown(ide_drive_t *drive) |
1033 | { | 1030 | { |
1034 | ide_drive_t *drive = container_of(dev, ide_drive_t, gendev); | ||
1035 | |||
1036 | #ifdef CONFIG_ALPHA | 1031 | #ifdef CONFIG_ALPHA |
1037 | /* On Alpha, halt(8) doesn't actually turn the machine off, | 1032 | /* On Alpha, halt(8) doesn't actually turn the machine off, |
1038 | it puts you into the sort of firmware monitor. Typically, | 1033 | it puts you into the sort of firmware monitor. Typically, |
@@ -1054,7 +1049,7 @@ static void ide_device_shutdown(struct device *dev) | |||
1054 | } | 1049 | } |
1055 | 1050 | ||
1056 | printk("Shutdown: %s\n", drive->name); | 1051 | printk("Shutdown: %s\n", drive->name); |
1057 | dev->bus->suspend(dev, PMSG_SUSPEND); | 1052 | drive->gendev.bus->suspend(&drive->gendev, PMSG_SUSPEND); |
1058 | } | 1053 | } |
1059 | 1054 | ||
1060 | static ide_driver_t idedisk_driver = { | 1055 | static ide_driver_t idedisk_driver = { |
@@ -1062,10 +1057,10 @@ static ide_driver_t idedisk_driver = { | |||
1062 | .owner = THIS_MODULE, | 1057 | .owner = THIS_MODULE, |
1063 | .name = "ide-disk", | 1058 | .name = "ide-disk", |
1064 | .bus = &ide_bus_type, | 1059 | .bus = &ide_bus_type, |
1065 | .probe = ide_disk_probe, | ||
1066 | .remove = ide_disk_remove, | ||
1067 | .shutdown = ide_device_shutdown, | ||
1068 | }, | 1060 | }, |
1061 | .probe = ide_disk_probe, | ||
1062 | .remove = ide_disk_remove, | ||
1063 | .shutdown = ide_device_shutdown, | ||
1069 | .version = IDEDISK_VERSION, | 1064 | .version = IDEDISK_VERSION, |
1070 | .media = ide_disk, | 1065 | .media = ide_disk, |
1071 | .supports_dsc_overlap = 0, | 1066 | .supports_dsc_overlap = 0, |
@@ -1182,9 +1177,8 @@ static struct block_device_operations idedisk_ops = { | |||
1182 | 1177 | ||
1183 | MODULE_DESCRIPTION("ATA DISK Driver"); | 1178 | MODULE_DESCRIPTION("ATA DISK Driver"); |
1184 | 1179 | ||
1185 | static int ide_disk_probe(struct device *dev) | 1180 | static int ide_disk_probe(ide_drive_t *drive) |
1186 | { | 1181 | { |
1187 | ide_drive_t *drive = to_ide_device(dev); | ||
1188 | struct ide_disk_obj *idkp; | 1182 | struct ide_disk_obj *idkp; |
1189 | struct gendisk *g; | 1183 | struct gendisk *g; |
1190 | 1184 | ||
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 5945f551aaaa..1f8db9ac05d1 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
@@ -1871,9 +1871,8 @@ static void idefloppy_setup (ide_drive_t *drive, idefloppy_floppy_t *floppy) | |||
1871 | idefloppy_add_settings(drive); | 1871 | idefloppy_add_settings(drive); |
1872 | } | 1872 | } |
1873 | 1873 | ||
1874 | static int ide_floppy_remove(struct device *dev) | 1874 | static void ide_floppy_remove(ide_drive_t *drive) |
1875 | { | 1875 | { |
1876 | ide_drive_t *drive = to_ide_device(dev); | ||
1877 | idefloppy_floppy_t *floppy = drive->driver_data; | 1876 | idefloppy_floppy_t *floppy = drive->driver_data; |
1878 | struct gendisk *g = floppy->disk; | 1877 | struct gendisk *g = floppy->disk; |
1879 | 1878 | ||
@@ -1882,8 +1881,6 @@ static int ide_floppy_remove(struct device *dev) | |||
1882 | del_gendisk(g); | 1881 | del_gendisk(g); |
1883 | 1882 | ||
1884 | ide_floppy_put(floppy); | 1883 | ide_floppy_put(floppy); |
1885 | |||
1886 | return 0; | ||
1887 | } | 1884 | } |
1888 | 1885 | ||
1889 | static void ide_floppy_release(struct kref *kref) | 1886 | static void ide_floppy_release(struct kref *kref) |
@@ -1922,16 +1919,16 @@ static ide_proc_entry_t idefloppy_proc[] = { | |||
1922 | 1919 | ||
1923 | #endif /* CONFIG_PROC_FS */ | 1920 | #endif /* CONFIG_PROC_FS */ |
1924 | 1921 | ||
1925 | static int ide_floppy_probe(struct device *); | 1922 | static int ide_floppy_probe(ide_drive_t *); |
1926 | 1923 | ||
1927 | static ide_driver_t idefloppy_driver = { | 1924 | static ide_driver_t idefloppy_driver = { |
1928 | .gen_driver = { | 1925 | .gen_driver = { |
1929 | .owner = THIS_MODULE, | 1926 | .owner = THIS_MODULE, |
1930 | .name = "ide-floppy", | 1927 | .name = "ide-floppy", |
1931 | .bus = &ide_bus_type, | 1928 | .bus = &ide_bus_type, |
1932 | .probe = ide_floppy_probe, | ||
1933 | .remove = ide_floppy_remove, | ||
1934 | }, | 1929 | }, |
1930 | .probe = ide_floppy_probe, | ||
1931 | .remove = ide_floppy_remove, | ||
1935 | .version = IDEFLOPPY_VERSION, | 1932 | .version = IDEFLOPPY_VERSION, |
1936 | .media = ide_floppy, | 1933 | .media = ide_floppy, |
1937 | .supports_dsc_overlap = 0, | 1934 | .supports_dsc_overlap = 0, |
@@ -2136,9 +2133,8 @@ static struct block_device_operations idefloppy_ops = { | |||
2136 | .revalidate_disk= idefloppy_revalidate_disk | 2133 | .revalidate_disk= idefloppy_revalidate_disk |
2137 | }; | 2134 | }; |
2138 | 2135 | ||
2139 | static int ide_floppy_probe(struct device *dev) | 2136 | static int ide_floppy_probe(ide_drive_t *drive) |
2140 | { | 2137 | { |
2141 | ide_drive_t *drive = to_ide_device(dev); | ||
2142 | idefloppy_floppy_t *floppy; | 2138 | idefloppy_floppy_t *floppy; |
2143 | struct gendisk *g; | 2139 | struct gendisk *g; |
2144 | 2140 | ||
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index bcbaeb50bb93..8d50df4526a4 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -55,22 +55,9 @@ | |||
55 | #include <asm/io.h> | 55 | #include <asm/io.h> |
56 | #include <asm/bitops.h> | 56 | #include <asm/bitops.h> |
57 | 57 | ||
58 | void ide_softirq_done(struct request *rq) | ||
59 | { | ||
60 | request_queue_t *q = rq->q; | ||
61 | |||
62 | add_disk_randomness(rq->rq_disk); | ||
63 | end_that_request_chunk(rq, 1, rq->data_len); | ||
64 | |||
65 | spin_lock_irq(q->queue_lock); | ||
66 | end_that_request_last(rq, 1); | ||
67 | spin_unlock_irq(q->queue_lock); | ||
68 | } | ||
69 | |||
70 | int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, | 58 | int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, |
71 | int nr_sectors) | 59 | int nr_sectors) |
72 | { | 60 | { |
73 | unsigned int nbytes; | ||
74 | int ret = 1; | 61 | int ret = 1; |
75 | 62 | ||
76 | BUG_ON(!(rq->flags & REQ_STARTED)); | 63 | BUG_ON(!(rq->flags & REQ_STARTED)); |
@@ -94,27 +81,12 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, | |||
94 | HWGROUP(drive)->hwif->ide_dma_on(drive); | 81 | HWGROUP(drive)->hwif->ide_dma_on(drive); |
95 | } | 82 | } |
96 | 83 | ||
97 | /* | 84 | if (!end_that_request_first(rq, uptodate, nr_sectors)) { |
98 | * For partial completions (or non fs/pc requests), use the regular | 85 | add_disk_randomness(rq->rq_disk); |
99 | * direct completion path. Same thing for requests that failed, to | ||
100 | * preserve the ->errors value we use the normal completion path | ||
101 | * for those | ||
102 | */ | ||
103 | nbytes = nr_sectors << 9; | ||
104 | if (!rq->errors && rq_all_done(rq, nbytes)) { | ||
105 | rq->data_len = nbytes; | ||
106 | blkdev_dequeue_request(rq); | 86 | blkdev_dequeue_request(rq); |
107 | HWGROUP(drive)->rq = NULL; | 87 | HWGROUP(drive)->rq = NULL; |
108 | blk_complete_request(rq); | 88 | end_that_request_last(rq, uptodate); |
109 | ret = 0; | 89 | ret = 0; |
110 | } else { | ||
111 | if (!end_that_request_first(rq, uptodate, nr_sectors)) { | ||
112 | add_disk_randomness(rq->rq_disk); | ||
113 | blkdev_dequeue_request(rq); | ||
114 | HWGROUP(drive)->rq = NULL; | ||
115 | end_that_request_last(rq, uptodate); | ||
116 | ret = 0; | ||
117 | } | ||
118 | } | 90 | } |
119 | 91 | ||
120 | return ret; | 92 | return ret; |
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 7cb2d86601db..e7425546b4b1 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
@@ -1011,8 +1011,6 @@ static int ide_init_queue(ide_drive_t *drive) | |||
1011 | blk_queue_max_hw_segments(q, max_sg_entries); | 1011 | blk_queue_max_hw_segments(q, max_sg_entries); |
1012 | blk_queue_max_phys_segments(q, max_sg_entries); | 1012 | blk_queue_max_phys_segments(q, max_sg_entries); |
1013 | 1013 | ||
1014 | blk_queue_softirq_done(q, ide_softirq_done); | ||
1015 | |||
1016 | /* assign drive queue */ | 1014 | /* assign drive queue */ |
1017 | drive->queue = q; | 1015 | drive->queue = q; |
1018 | 1016 | ||
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index fab9b2b02504..0101d0def7c5 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
@@ -4682,9 +4682,8 @@ static void idetape_setup (ide_drive_t *drive, idetape_tape_t *tape, int minor) | |||
4682 | idetape_add_settings(drive); | 4682 | idetape_add_settings(drive); |
4683 | } | 4683 | } |
4684 | 4684 | ||
4685 | static int ide_tape_remove(struct device *dev) | 4685 | static void ide_tape_remove(ide_drive_t *drive) |
4686 | { | 4686 | { |
4687 | ide_drive_t *drive = to_ide_device(dev); | ||
4688 | idetape_tape_t *tape = drive->driver_data; | 4687 | idetape_tape_t *tape = drive->driver_data; |
4689 | 4688 | ||
4690 | ide_unregister_subdriver(drive, tape->driver); | 4689 | ide_unregister_subdriver(drive, tape->driver); |
@@ -4692,8 +4691,6 @@ static int ide_tape_remove(struct device *dev) | |||
4692 | ide_unregister_region(tape->disk); | 4691 | ide_unregister_region(tape->disk); |
4693 | 4692 | ||
4694 | ide_tape_put(tape); | 4693 | ide_tape_put(tape); |
4695 | |||
4696 | return 0; | ||
4697 | } | 4694 | } |
4698 | 4695 | ||
4699 | static void ide_tape_release(struct kref *kref) | 4696 | static void ide_tape_release(struct kref *kref) |
@@ -4745,16 +4742,16 @@ static ide_proc_entry_t idetape_proc[] = { | |||
4745 | 4742 | ||
4746 | #endif | 4743 | #endif |
4747 | 4744 | ||
4748 | static int ide_tape_probe(struct device *); | 4745 | static int ide_tape_probe(ide_drive_t *); |
4749 | 4746 | ||
4750 | static ide_driver_t idetape_driver = { | 4747 | static ide_driver_t idetape_driver = { |
4751 | .gen_driver = { | 4748 | .gen_driver = { |
4752 | .owner = THIS_MODULE, | 4749 | .owner = THIS_MODULE, |
4753 | .name = "ide-tape", | 4750 | .name = "ide-tape", |
4754 | .bus = &ide_bus_type, | 4751 | .bus = &ide_bus_type, |
4755 | .probe = ide_tape_probe, | ||
4756 | .remove = ide_tape_remove, | ||
4757 | }, | 4752 | }, |
4753 | .probe = ide_tape_probe, | ||
4754 | .remove = ide_tape_remove, | ||
4758 | .version = IDETAPE_VERSION, | 4755 | .version = IDETAPE_VERSION, |
4759 | .media = ide_tape, | 4756 | .media = ide_tape, |
4760 | .supports_dsc_overlap = 1, | 4757 | .supports_dsc_overlap = 1, |
@@ -4825,9 +4822,8 @@ static struct block_device_operations idetape_block_ops = { | |||
4825 | .ioctl = idetape_ioctl, | 4822 | .ioctl = idetape_ioctl, |
4826 | }; | 4823 | }; |
4827 | 4824 | ||
4828 | static int ide_tape_probe(struct device *dev) | 4825 | static int ide_tape_probe(ide_drive_t *drive) |
4829 | { | 4826 | { |
4830 | ide_drive_t *drive = to_ide_device(dev); | ||
4831 | idetape_tape_t *tape; | 4827 | idetape_tape_t *tape; |
4832 | struct gendisk *g; | 4828 | struct gendisk *g; |
4833 | int minor; | 4829 | int minor; |
@@ -4883,9 +4879,9 @@ static int ide_tape_probe(struct device *dev) | |||
4883 | idetape_setup(drive, tape, minor); | 4879 | idetape_setup(drive, tape, minor); |
4884 | 4880 | ||
4885 | class_device_create(idetape_sysfs_class, NULL, | 4881 | class_device_create(idetape_sysfs_class, NULL, |
4886 | MKDEV(IDETAPE_MAJOR, minor), dev, "%s", tape->name); | 4882 | MKDEV(IDETAPE_MAJOR, minor), &drive->gendev, "%s", tape->name); |
4887 | class_device_create(idetape_sysfs_class, NULL, | 4883 | class_device_create(idetape_sysfs_class, NULL, |
4888 | MKDEV(IDETAPE_MAJOR, minor + 128), dev, "n%s", tape->name); | 4884 | MKDEV(IDETAPE_MAJOR, minor + 128), &drive->gendev, "n%s", tape->name); |
4889 | 4885 | ||
4890 | devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor), | 4886 | devfs_mk_cdev(MKDEV(HWIF(drive)->major, minor), |
4891 | S_IFCHR | S_IRUGO | S_IWUGO, | 4887 | S_IFCHR | S_IRUGO | S_IWUGO, |
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index ec5a4cb173b0..afeb02bbb722 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c | |||
@@ -1949,10 +1949,41 @@ static int ide_uevent(struct device *dev, char **envp, int num_envp, | |||
1949 | return 0; | 1949 | return 0; |
1950 | } | 1950 | } |
1951 | 1951 | ||
1952 | static int generic_ide_probe(struct device *dev) | ||
1953 | { | ||
1954 | ide_drive_t *drive = to_ide_device(dev); | ||
1955 | ide_driver_t *drv = to_ide_driver(dev->driver); | ||
1956 | |||
1957 | return drv->probe ? drv->probe(drive) : -ENODEV; | ||
1958 | } | ||
1959 | |||
1960 | static int generic_ide_remove(struct device *dev) | ||
1961 | { | ||
1962 | ide_drive_t *drive = to_ide_device(dev); | ||
1963 | ide_driver_t *drv = to_ide_driver(dev->driver); | ||
1964 | |||
1965 | if (drv->remove) | ||
1966 | drv->remove(drive); | ||
1967 | |||
1968 | return 0; | ||
1969 | } | ||
1970 | |||
1971 | static void generic_ide_shutdown(struct device *dev) | ||
1972 | { | ||
1973 | ide_drive_t *drive = to_ide_device(dev); | ||
1974 | ide_driver_t *drv = to_ide_driver(dev->driver); | ||
1975 | |||
1976 | if (dev->driver && drv->shutdown) | ||
1977 | drv->shutdown(drive); | ||
1978 | } | ||
1979 | |||
1952 | struct bus_type ide_bus_type = { | 1980 | struct bus_type ide_bus_type = { |
1953 | .name = "ide", | 1981 | .name = "ide", |
1954 | .match = ide_bus_match, | 1982 | .match = ide_bus_match, |
1955 | .uevent = ide_uevent, | 1983 | .uevent = ide_uevent, |
1984 | .probe = generic_ide_probe, | ||
1985 | .remove = generic_ide_remove, | ||
1986 | .shutdown = generic_ide_shutdown, | ||
1956 | .dev_attrs = ide_dev_attrs, | 1987 | .dev_attrs = ide_dev_attrs, |
1957 | .suspend = generic_ide_suspend, | 1988 | .suspend = generic_ide_suspend, |
1958 | .resume = generic_ide_resume, | 1989 | .resume = generic_ide_resume, |
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 3a611fe5497e..c06b18102b6a 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -3163,22 +3163,6 @@ int ib_cm_init_qp_attr(struct ib_cm_id *cm_id, | |||
3163 | } | 3163 | } |
3164 | EXPORT_SYMBOL(ib_cm_init_qp_attr); | 3164 | EXPORT_SYMBOL(ib_cm_init_qp_attr); |
3165 | 3165 | ||
3166 | static __be64 cm_get_ca_guid(struct ib_device *device) | ||
3167 | { | ||
3168 | struct ib_device_attr *device_attr; | ||
3169 | __be64 guid; | ||
3170 | int ret; | ||
3171 | |||
3172 | device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL); | ||
3173 | if (!device_attr) | ||
3174 | return 0; | ||
3175 | |||
3176 | ret = ib_query_device(device, device_attr); | ||
3177 | guid = ret ? 0 : device_attr->node_guid; | ||
3178 | kfree(device_attr); | ||
3179 | return guid; | ||
3180 | } | ||
3181 | |||
3182 | static void cm_add_one(struct ib_device *device) | 3166 | static void cm_add_one(struct ib_device *device) |
3183 | { | 3167 | { |
3184 | struct cm_device *cm_dev; | 3168 | struct cm_device *cm_dev; |
@@ -3200,9 +3184,7 @@ static void cm_add_one(struct ib_device *device) | |||
3200 | return; | 3184 | return; |
3201 | 3185 | ||
3202 | cm_dev->device = device; | 3186 | cm_dev->device = device; |
3203 | cm_dev->ca_guid = cm_get_ca_guid(device); | 3187 | cm_dev->ca_guid = device->node_guid; |
3204 | if (!cm_dev->ca_guid) | ||
3205 | goto error1; | ||
3206 | 3188 | ||
3207 | set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); | 3189 | set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask); |
3208 | for (i = 1; i <= device->phys_port_cnt; i++) { | 3190 | for (i = 1; i <= device->phys_port_cnt; i++) { |
@@ -3217,11 +3199,11 @@ static void cm_add_one(struct ib_device *device) | |||
3217 | cm_recv_handler, | 3199 | cm_recv_handler, |
3218 | port); | 3200 | port); |
3219 | if (IS_ERR(port->mad_agent)) | 3201 | if (IS_ERR(port->mad_agent)) |
3220 | goto error2; | 3202 | goto error1; |
3221 | 3203 | ||
3222 | ret = ib_modify_port(device, i, 0, &port_modify); | 3204 | ret = ib_modify_port(device, i, 0, &port_modify); |
3223 | if (ret) | 3205 | if (ret) |
3224 | goto error3; | 3206 | goto error2; |
3225 | } | 3207 | } |
3226 | ib_set_client_data(device, &cm_client, cm_dev); | 3208 | ib_set_client_data(device, &cm_client, cm_dev); |
3227 | 3209 | ||
@@ -3230,9 +3212,9 @@ static void cm_add_one(struct ib_device *device) | |||
3230 | write_unlock_irqrestore(&cm.device_lock, flags); | 3212 | write_unlock_irqrestore(&cm.device_lock, flags); |
3231 | return; | 3213 | return; |
3232 | 3214 | ||
3233 | error3: | ||
3234 | ib_unregister_mad_agent(port->mad_agent); | ||
3235 | error2: | 3215 | error2: |
3216 | ib_unregister_mad_agent(port->mad_agent); | ||
3217 | error1: | ||
3236 | port_modify.set_port_cap_mask = 0; | 3218 | port_modify.set_port_cap_mask = 0; |
3237 | port_modify.clr_port_cap_mask = IB_PORT_CM_SUP; | 3219 | port_modify.clr_port_cap_mask = IB_PORT_CM_SUP; |
3238 | while (--i) { | 3220 | while (--i) { |
@@ -3240,7 +3222,6 @@ error2: | |||
3240 | ib_modify_port(device, port->port_num, 0, &port_modify); | 3222 | ib_modify_port(device, port->port_num, 0, &port_modify); |
3241 | ib_unregister_mad_agent(port->mad_agent); | 3223 | ib_unregister_mad_agent(port->mad_agent); |
3242 | } | 3224 | } |
3243 | error1: | ||
3244 | kfree(cm_dev); | 3225 | kfree(cm_dev); |
3245 | } | 3226 | } |
3246 | 3227 | ||
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index e169e798354b..b2f3cb91d9bc 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c | |||
@@ -38,8 +38,7 @@ | |||
38 | #include <linux/errno.h> | 38 | #include <linux/errno.h> |
39 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | 41 | #include <linux/mutex.h> | |
42 | #include <asm/semaphore.h> | ||
43 | 42 | ||
44 | #include "core_priv.h" | 43 | #include "core_priv.h" |
45 | 44 | ||
@@ -57,13 +56,13 @@ static LIST_HEAD(device_list); | |||
57 | static LIST_HEAD(client_list); | 56 | static LIST_HEAD(client_list); |
58 | 57 | ||
59 | /* | 58 | /* |
60 | * device_sem protects access to both device_list and client_list. | 59 | * device_mutex protects access to both device_list and client_list. |
61 | * There's no real point to using multiple locks or something fancier | 60 | * There's no real point to using multiple locks or something fancier |
62 | * like an rwsem: we always access both lists, and we're always | 61 | * like an rwsem: we always access both lists, and we're always |
63 | * modifying one list or the other list. In any case this is not a | 62 | * modifying one list or the other list. In any case this is not a |
64 | * hot path so there's no point in trying to optimize. | 63 | * hot path so there's no point in trying to optimize. |
65 | */ | 64 | */ |
66 | static DECLARE_MUTEX(device_sem); | 65 | static DEFINE_MUTEX(device_mutex); |
67 | 66 | ||
68 | static int ib_device_check_mandatory(struct ib_device *device) | 67 | static int ib_device_check_mandatory(struct ib_device *device) |
69 | { | 68 | { |
@@ -221,7 +220,7 @@ int ib_register_device(struct ib_device *device) | |||
221 | { | 220 | { |
222 | int ret; | 221 | int ret; |
223 | 222 | ||
224 | down(&device_sem); | 223 | mutex_lock(&device_mutex); |
225 | 224 | ||
226 | if (strchr(device->name, '%')) { | 225 | if (strchr(device->name, '%')) { |
227 | ret = alloc_name(device->name); | 226 | ret = alloc_name(device->name); |
@@ -259,7 +258,7 @@ int ib_register_device(struct ib_device *device) | |||
259 | } | 258 | } |
260 | 259 | ||
261 | out: | 260 | out: |
262 | up(&device_sem); | 261 | mutex_unlock(&device_mutex); |
263 | return ret; | 262 | return ret; |
264 | } | 263 | } |
265 | EXPORT_SYMBOL(ib_register_device); | 264 | EXPORT_SYMBOL(ib_register_device); |
@@ -276,7 +275,7 @@ void ib_unregister_device(struct ib_device *device) | |||
276 | struct ib_client_data *context, *tmp; | 275 | struct ib_client_data *context, *tmp; |
277 | unsigned long flags; | 276 | unsigned long flags; |
278 | 277 | ||
279 | down(&device_sem); | 278 | mutex_lock(&device_mutex); |
280 | 279 | ||
281 | list_for_each_entry_reverse(client, &client_list, list) | 280 | list_for_each_entry_reverse(client, &client_list, list) |
282 | if (client->remove) | 281 | if (client->remove) |
@@ -284,7 +283,7 @@ void ib_unregister_device(struct ib_device *device) | |||
284 | 283 | ||
285 | list_del(&device->core_list); | 284 | list_del(&device->core_list); |
286 | 285 | ||
287 | up(&device_sem); | 286 | mutex_unlock(&device_mutex); |
288 | 287 | ||
289 | spin_lock_irqsave(&device->client_data_lock, flags); | 288 | spin_lock_irqsave(&device->client_data_lock, flags); |
290 | list_for_each_entry_safe(context, tmp, &device->client_data_list, list) | 289 | list_for_each_entry_safe(context, tmp, &device->client_data_list, list) |
@@ -312,14 +311,14 @@ int ib_register_client(struct ib_client *client) | |||
312 | { | 311 | { |
313 | struct ib_device *device; | 312 | struct ib_device *device; |
314 | 313 | ||
315 | down(&device_sem); | 314 | mutex_lock(&device_mutex); |
316 | 315 | ||
317 | list_add_tail(&client->list, &client_list); | 316 | list_add_tail(&client->list, &client_list); |
318 | list_for_each_entry(device, &device_list, core_list) | 317 | list_for_each_entry(device, &device_list, core_list) |
319 | if (client->add && !add_client_context(device, client)) | 318 | if (client->add && !add_client_context(device, client)) |
320 | client->add(device); | 319 | client->add(device); |
321 | 320 | ||
322 | up(&device_sem); | 321 | mutex_unlock(&device_mutex); |
323 | 322 | ||
324 | return 0; | 323 | return 0; |
325 | } | 324 | } |
@@ -339,7 +338,7 @@ void ib_unregister_client(struct ib_client *client) | |||
339 | struct ib_device *device; | 338 | struct ib_device *device; |
340 | unsigned long flags; | 339 | unsigned long flags; |
341 | 340 | ||
342 | down(&device_sem); | 341 | mutex_lock(&device_mutex); |
343 | 342 | ||
344 | list_for_each_entry(device, &device_list, core_list) { | 343 | list_for_each_entry(device, &device_list, core_list) { |
345 | if (client->remove) | 344 | if (client->remove) |
@@ -355,7 +354,7 @@ void ib_unregister_client(struct ib_client *client) | |||
355 | } | 354 | } |
356 | list_del(&client->list); | 355 | list_del(&client->list); |
357 | 356 | ||
358 | up(&device_sem); | 357 | mutex_unlock(&device_mutex); |
359 | } | 358 | } |
360 | EXPORT_SYMBOL(ib_unregister_client); | 359 | EXPORT_SYMBOL(ib_unregister_client); |
361 | 360 | ||
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 1f1743c5c9a3..5982d687a000 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c | |||
@@ -445,13 +445,7 @@ static int ib_device_uevent(struct class_device *cdev, char **envp, | |||
445 | return -ENOMEM; | 445 | return -ENOMEM; |
446 | 446 | ||
447 | /* | 447 | /* |
448 | * It might be nice to pass the node GUID with the event, but | 448 | * It would be nice to pass the node GUID with the event... |
449 | * right now the only way to get it is to query the device | ||
450 | * provider, and this can crash during device removal because | ||
451 | * we are will be running after driver removal has started. | ||
452 | * We could add a node_guid field to struct ib_device, or we | ||
453 | * could just let userspace read the node GUID from sysfs when | ||
454 | * devices are added. | ||
455 | */ | 449 | */ |
456 | 450 | ||
457 | envp[i] = NULL; | 451 | envp[i] = NULL; |
@@ -623,21 +617,15 @@ static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf) | |||
623 | static ssize_t show_node_guid(struct class_device *cdev, char *buf) | 617 | static ssize_t show_node_guid(struct class_device *cdev, char *buf) |
624 | { | 618 | { |
625 | struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); | 619 | struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); |
626 | struct ib_device_attr attr; | ||
627 | ssize_t ret; | ||
628 | 620 | ||
629 | if (!ibdev_is_alive(dev)) | 621 | if (!ibdev_is_alive(dev)) |
630 | return -ENODEV; | 622 | return -ENODEV; |
631 | 623 | ||
632 | ret = ib_query_device(dev, &attr); | ||
633 | if (ret) | ||
634 | return ret; | ||
635 | |||
636 | return sprintf(buf, "%04x:%04x:%04x:%04x\n", | 624 | return sprintf(buf, "%04x:%04x:%04x:%04x\n", |
637 | be16_to_cpu(((__be16 *) &attr.node_guid)[0]), | 625 | be16_to_cpu(((__be16 *) &dev->node_guid)[0]), |
638 | be16_to_cpu(((__be16 *) &attr.node_guid)[1]), | 626 | be16_to_cpu(((__be16 *) &dev->node_guid)[1]), |
639 | be16_to_cpu(((__be16 *) &attr.node_guid)[2]), | 627 | be16_to_cpu(((__be16 *) &dev->node_guid)[2]), |
640 | be16_to_cpu(((__be16 *) &attr.node_guid)[3])); | 628 | be16_to_cpu(((__be16 *) &dev->node_guid)[3])); |
641 | } | 629 | } |
642 | 630 | ||
643 | static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL); | 631 | static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL); |
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c index 6e15787d1de1..e95c4293a496 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/mount.h> | 42 | #include <linux/mount.h> |
43 | #include <linux/cdev.h> | 43 | #include <linux/cdev.h> |
44 | #include <linux/idr.h> | 44 | #include <linux/idr.h> |
45 | #include <linux/mutex.h> | ||
45 | 46 | ||
46 | #include <asm/uaccess.h> | 47 | #include <asm/uaccess.h> |
47 | 48 | ||
@@ -113,7 +114,7 @@ static struct ib_client ucm_client = { | |||
113 | .remove = ib_ucm_remove_one | 114 | .remove = ib_ucm_remove_one |
114 | }; | 115 | }; |
115 | 116 | ||
116 | static DECLARE_MUTEX(ctx_id_mutex); | 117 | static DEFINE_MUTEX(ctx_id_mutex); |
117 | static DEFINE_IDR(ctx_id_table); | 118 | static DEFINE_IDR(ctx_id_table); |
118 | static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES); | 119 | static DECLARE_BITMAP(dev_map, IB_UCM_MAX_DEVICES); |
119 | 120 | ||
@@ -121,7 +122,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) | |||
121 | { | 122 | { |
122 | struct ib_ucm_context *ctx; | 123 | struct ib_ucm_context *ctx; |
123 | 124 | ||
124 | down(&ctx_id_mutex); | 125 | mutex_lock(&ctx_id_mutex); |
125 | ctx = idr_find(&ctx_id_table, id); | 126 | ctx = idr_find(&ctx_id_table, id); |
126 | if (!ctx) | 127 | if (!ctx) |
127 | ctx = ERR_PTR(-ENOENT); | 128 | ctx = ERR_PTR(-ENOENT); |
@@ -129,7 +130,7 @@ static struct ib_ucm_context *ib_ucm_ctx_get(struct ib_ucm_file *file, int id) | |||
129 | ctx = ERR_PTR(-EINVAL); | 130 | ctx = ERR_PTR(-EINVAL); |
130 | else | 131 | else |
131 | atomic_inc(&ctx->ref); | 132 | atomic_inc(&ctx->ref); |
132 | up(&ctx_id_mutex); | 133 | mutex_unlock(&ctx_id_mutex); |
133 | 134 | ||
134 | return ctx; | 135 | return ctx; |
135 | } | 136 | } |
@@ -186,9 +187,9 @@ static struct ib_ucm_context *ib_ucm_ctx_alloc(struct ib_ucm_file *file) | |||
186 | if (!result) | 187 | if (!result) |
187 | goto error; | 188 | goto error; |
188 | 189 | ||
189 | down(&ctx_id_mutex); | 190 | mutex_lock(&ctx_id_mutex); |
190 | result = idr_get_new(&ctx_id_table, ctx, &ctx->id); | 191 | result = idr_get_new(&ctx_id_table, ctx, &ctx->id); |
191 | up(&ctx_id_mutex); | 192 | mutex_unlock(&ctx_id_mutex); |
192 | } while (result == -EAGAIN); | 193 | } while (result == -EAGAIN); |
193 | 194 | ||
194 | if (result) | 195 | if (result) |
@@ -550,9 +551,9 @@ static ssize_t ib_ucm_create_id(struct ib_ucm_file *file, | |||
550 | err2: | 551 | err2: |
551 | ib_destroy_cm_id(ctx->cm_id); | 552 | ib_destroy_cm_id(ctx->cm_id); |
552 | err1: | 553 | err1: |
553 | down(&ctx_id_mutex); | 554 | mutex_lock(&ctx_id_mutex); |
554 | idr_remove(&ctx_id_table, ctx->id); | 555 | idr_remove(&ctx_id_table, ctx->id); |
555 | up(&ctx_id_mutex); | 556 | mutex_unlock(&ctx_id_mutex); |
556 | kfree(ctx); | 557 | kfree(ctx); |
557 | return result; | 558 | return result; |
558 | } | 559 | } |
@@ -572,7 +573,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file, | |||
572 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) | 573 | if (copy_from_user(&cmd, inbuf, sizeof(cmd))) |
573 | return -EFAULT; | 574 | return -EFAULT; |
574 | 575 | ||
575 | down(&ctx_id_mutex); | 576 | mutex_lock(&ctx_id_mutex); |
576 | ctx = idr_find(&ctx_id_table, cmd.id); | 577 | ctx = idr_find(&ctx_id_table, cmd.id); |
577 | if (!ctx) | 578 | if (!ctx) |
578 | ctx = ERR_PTR(-ENOENT); | 579 | ctx = ERR_PTR(-ENOENT); |
@@ -580,7 +581,7 @@ static ssize_t ib_ucm_destroy_id(struct ib_ucm_file *file, | |||
580 | ctx = ERR_PTR(-EINVAL); | 581 | ctx = ERR_PTR(-EINVAL); |
581 | else | 582 | else |
582 | idr_remove(&ctx_id_table, ctx->id); | 583 | idr_remove(&ctx_id_table, ctx->id); |
583 | up(&ctx_id_mutex); | 584 | mutex_unlock(&ctx_id_mutex); |
584 | 585 | ||
585 | if (IS_ERR(ctx)) | 586 | if (IS_ERR(ctx)) |
586 | return PTR_ERR(ctx); | 587 | return PTR_ERR(ctx); |
@@ -1280,9 +1281,9 @@ static int ib_ucm_close(struct inode *inode, struct file *filp) | |||
1280 | struct ib_ucm_context, file_list); | 1281 | struct ib_ucm_context, file_list); |
1281 | up(&file->mutex); | 1282 | up(&file->mutex); |
1282 | 1283 | ||
1283 | down(&ctx_id_mutex); | 1284 | mutex_lock(&ctx_id_mutex); |
1284 | idr_remove(&ctx_id_table, ctx->id); | 1285 | idr_remove(&ctx_id_table, ctx->id); |
1285 | up(&ctx_id_mutex); | 1286 | mutex_unlock(&ctx_id_mutex); |
1286 | 1287 | ||
1287 | ib_destroy_cm_id(ctx->cm_id); | 1288 | ib_destroy_cm_id(ctx->cm_id); |
1288 | ib_ucm_cleanup_events(ctx); | 1289 | ib_ucm_cleanup_events(ctx); |
diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index 7114e3fbab00..f7eecbc6af6c 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h | |||
@@ -41,6 +41,7 @@ | |||
41 | 41 | ||
42 | #include <linux/kref.h> | 42 | #include <linux/kref.h> |
43 | #include <linux/idr.h> | 43 | #include <linux/idr.h> |
44 | #include <linux/mutex.h> | ||
44 | 45 | ||
45 | #include <rdma/ib_verbs.h> | 46 | #include <rdma/ib_verbs.h> |
46 | #include <rdma/ib_user_verbs.h> | 47 | #include <rdma/ib_user_verbs.h> |
@@ -88,7 +89,7 @@ struct ib_uverbs_event_file { | |||
88 | 89 | ||
89 | struct ib_uverbs_file { | 90 | struct ib_uverbs_file { |
90 | struct kref ref; | 91 | struct kref ref; |
91 | struct semaphore mutex; | 92 | struct mutex mutex; |
92 | struct ib_uverbs_device *device; | 93 | struct ib_uverbs_device *device; |
93 | struct ib_ucontext *ucontext; | 94 | struct ib_ucontext *ucontext; |
94 | struct ib_event_handler event_handler; | 95 | struct ib_event_handler event_handler; |
@@ -131,7 +132,7 @@ struct ib_ucq_object { | |||
131 | u32 async_events_reported; | 132 | u32 async_events_reported; |
132 | }; | 133 | }; |
133 | 134 | ||
134 | extern struct semaphore ib_uverbs_idr_mutex; | 135 | extern struct mutex ib_uverbs_idr_mutex; |
135 | extern struct idr ib_uverbs_pd_idr; | 136 | extern struct idr ib_uverbs_pd_idr; |
136 | extern struct idr ib_uverbs_mr_idr; | 137 | extern struct idr ib_uverbs_mr_idr; |
137 | extern struct idr ib_uverbs_mw_idr; | 138 | extern struct idr ib_uverbs_mw_idr; |
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index a02c5a05c984..407b6284d7d5 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c | |||
@@ -67,7 +67,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, | |||
67 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 67 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
68 | return -EFAULT; | 68 | return -EFAULT; |
69 | 69 | ||
70 | down(&file->mutex); | 70 | mutex_lock(&file->mutex); |
71 | 71 | ||
72 | if (file->ucontext) { | 72 | if (file->ucontext) { |
73 | ret = -EINVAL; | 73 | ret = -EINVAL; |
@@ -119,7 +119,7 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, | |||
119 | 119 | ||
120 | fd_install(resp.async_fd, filp); | 120 | fd_install(resp.async_fd, filp); |
121 | 121 | ||
122 | up(&file->mutex); | 122 | mutex_unlock(&file->mutex); |
123 | 123 | ||
124 | return in_len; | 124 | return in_len; |
125 | 125 | ||
@@ -131,7 +131,7 @@ err_free: | |||
131 | ibdev->dealloc_ucontext(ucontext); | 131 | ibdev->dealloc_ucontext(ucontext); |
132 | 132 | ||
133 | err: | 133 | err: |
134 | up(&file->mutex); | 134 | mutex_unlock(&file->mutex); |
135 | return ret; | 135 | return ret; |
136 | } | 136 | } |
137 | 137 | ||
@@ -157,7 +157,7 @@ ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, | |||
157 | memset(&resp, 0, sizeof resp); | 157 | memset(&resp, 0, sizeof resp); |
158 | 158 | ||
159 | resp.fw_ver = attr.fw_ver; | 159 | resp.fw_ver = attr.fw_ver; |
160 | resp.node_guid = attr.node_guid; | 160 | resp.node_guid = file->device->ib_dev->node_guid; |
161 | resp.sys_image_guid = attr.sys_image_guid; | 161 | resp.sys_image_guid = attr.sys_image_guid; |
162 | resp.max_mr_size = attr.max_mr_size; | 162 | resp.max_mr_size = attr.max_mr_size; |
163 | resp.page_size_cap = attr.page_size_cap; | 163 | resp.page_size_cap = attr.page_size_cap; |
@@ -290,7 +290,7 @@ ssize_t ib_uverbs_alloc_pd(struct ib_uverbs_file *file, | |||
290 | pd->uobject = uobj; | 290 | pd->uobject = uobj; |
291 | atomic_set(&pd->usecnt, 0); | 291 | atomic_set(&pd->usecnt, 0); |
292 | 292 | ||
293 | down(&ib_uverbs_idr_mutex); | 293 | mutex_lock(&ib_uverbs_idr_mutex); |
294 | 294 | ||
295 | retry: | 295 | retry: |
296 | if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { | 296 | if (!idr_pre_get(&ib_uverbs_pd_idr, GFP_KERNEL)) { |
@@ -314,11 +314,11 @@ retry: | |||
314 | goto err_idr; | 314 | goto err_idr; |
315 | } | 315 | } |
316 | 316 | ||
317 | down(&file->mutex); | 317 | mutex_lock(&file->mutex); |
318 | list_add_tail(&uobj->list, &file->ucontext->pd_list); | 318 | list_add_tail(&uobj->list, &file->ucontext->pd_list); |
319 | up(&file->mutex); | 319 | mutex_unlock(&file->mutex); |
320 | 320 | ||
321 | up(&ib_uverbs_idr_mutex); | 321 | mutex_unlock(&ib_uverbs_idr_mutex); |
322 | 322 | ||
323 | return in_len; | 323 | return in_len; |
324 | 324 | ||
@@ -326,7 +326,7 @@ err_idr: | |||
326 | idr_remove(&ib_uverbs_pd_idr, uobj->id); | 326 | idr_remove(&ib_uverbs_pd_idr, uobj->id); |
327 | 327 | ||
328 | err_up: | 328 | err_up: |
329 | up(&ib_uverbs_idr_mutex); | 329 | mutex_unlock(&ib_uverbs_idr_mutex); |
330 | ib_dealloc_pd(pd); | 330 | ib_dealloc_pd(pd); |
331 | 331 | ||
332 | err: | 332 | err: |
@@ -346,7 +346,7 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, | |||
346 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 346 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
347 | return -EFAULT; | 347 | return -EFAULT; |
348 | 348 | ||
349 | down(&ib_uverbs_idr_mutex); | 349 | mutex_lock(&ib_uverbs_idr_mutex); |
350 | 350 | ||
351 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 351 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
352 | if (!pd || pd->uobject->context != file->ucontext) | 352 | if (!pd || pd->uobject->context != file->ucontext) |
@@ -360,14 +360,14 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, | |||
360 | 360 | ||
361 | idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); | 361 | idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); |
362 | 362 | ||
363 | down(&file->mutex); | 363 | mutex_lock(&file->mutex); |
364 | list_del(&uobj->list); | 364 | list_del(&uobj->list); |
365 | up(&file->mutex); | 365 | mutex_unlock(&file->mutex); |
366 | 366 | ||
367 | kfree(uobj); | 367 | kfree(uobj); |
368 | 368 | ||
369 | out: | 369 | out: |
370 | up(&ib_uverbs_idr_mutex); | 370 | mutex_unlock(&ib_uverbs_idr_mutex); |
371 | 371 | ||
372 | return ret ? ret : in_len; | 372 | return ret ? ret : in_len; |
373 | } | 373 | } |
@@ -426,7 +426,7 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file, | |||
426 | 426 | ||
427 | obj->umem.virt_base = cmd.hca_va; | 427 | obj->umem.virt_base = cmd.hca_va; |
428 | 428 | ||
429 | down(&ib_uverbs_idr_mutex); | 429 | mutex_lock(&ib_uverbs_idr_mutex); |
430 | 430 | ||
431 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 431 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
432 | if (!pd || pd->uobject->context != file->ucontext) { | 432 | if (!pd || pd->uobject->context != file->ucontext) { |
@@ -476,11 +476,11 @@ retry: | |||
476 | goto err_idr; | 476 | goto err_idr; |
477 | } | 477 | } |
478 | 478 | ||
479 | down(&file->mutex); | 479 | mutex_lock(&file->mutex); |
480 | list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); | 480 | list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); |
481 | up(&file->mutex); | 481 | mutex_unlock(&file->mutex); |
482 | 482 | ||
483 | up(&ib_uverbs_idr_mutex); | 483 | mutex_unlock(&ib_uverbs_idr_mutex); |
484 | 484 | ||
485 | return in_len; | 485 | return in_len; |
486 | 486 | ||
@@ -492,7 +492,7 @@ err_unreg: | |||
492 | atomic_dec(&pd->usecnt); | 492 | atomic_dec(&pd->usecnt); |
493 | 493 | ||
494 | err_up: | 494 | err_up: |
495 | up(&ib_uverbs_idr_mutex); | 495 | mutex_unlock(&ib_uverbs_idr_mutex); |
496 | 496 | ||
497 | ib_umem_release(file->device->ib_dev, &obj->umem); | 497 | ib_umem_release(file->device->ib_dev, &obj->umem); |
498 | 498 | ||
@@ -513,7 +513,7 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, | |||
513 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 513 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
514 | return -EFAULT; | 514 | return -EFAULT; |
515 | 515 | ||
516 | down(&ib_uverbs_idr_mutex); | 516 | mutex_lock(&ib_uverbs_idr_mutex); |
517 | 517 | ||
518 | mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); | 518 | mr = idr_find(&ib_uverbs_mr_idr, cmd.mr_handle); |
519 | if (!mr || mr->uobject->context != file->ucontext) | 519 | if (!mr || mr->uobject->context != file->ucontext) |
@@ -527,15 +527,15 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, | |||
527 | 527 | ||
528 | idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); | 528 | idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); |
529 | 529 | ||
530 | down(&file->mutex); | 530 | mutex_lock(&file->mutex); |
531 | list_del(&memobj->uobject.list); | 531 | list_del(&memobj->uobject.list); |
532 | up(&file->mutex); | 532 | mutex_unlock(&file->mutex); |
533 | 533 | ||
534 | ib_umem_release(file->device->ib_dev, &memobj->umem); | 534 | ib_umem_release(file->device->ib_dev, &memobj->umem); |
535 | kfree(memobj); | 535 | kfree(memobj); |
536 | 536 | ||
537 | out: | 537 | out: |
538 | up(&ib_uverbs_idr_mutex); | 538 | mutex_unlock(&ib_uverbs_idr_mutex); |
539 | 539 | ||
540 | return ret ? ret : in_len; | 540 | return ret ? ret : in_len; |
541 | } | 541 | } |
@@ -628,7 +628,7 @@ ssize_t ib_uverbs_create_cq(struct ib_uverbs_file *file, | |||
628 | cq->cq_context = ev_file; | 628 | cq->cq_context = ev_file; |
629 | atomic_set(&cq->usecnt, 0); | 629 | atomic_set(&cq->usecnt, 0); |
630 | 630 | ||
631 | down(&ib_uverbs_idr_mutex); | 631 | mutex_lock(&ib_uverbs_idr_mutex); |
632 | 632 | ||
633 | retry: | 633 | retry: |
634 | if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { | 634 | if (!idr_pre_get(&ib_uverbs_cq_idr, GFP_KERNEL)) { |
@@ -653,11 +653,11 @@ retry: | |||
653 | goto err_idr; | 653 | goto err_idr; |
654 | } | 654 | } |
655 | 655 | ||
656 | down(&file->mutex); | 656 | mutex_lock(&file->mutex); |
657 | list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); | 657 | list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); |
658 | up(&file->mutex); | 658 | mutex_unlock(&file->mutex); |
659 | 659 | ||
660 | up(&ib_uverbs_idr_mutex); | 660 | mutex_unlock(&ib_uverbs_idr_mutex); |
661 | 661 | ||
662 | return in_len; | 662 | return in_len; |
663 | 663 | ||
@@ -665,7 +665,7 @@ err_idr: | |||
665 | idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); | 665 | idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); |
666 | 666 | ||
667 | err_up: | 667 | err_up: |
668 | up(&ib_uverbs_idr_mutex); | 668 | mutex_unlock(&ib_uverbs_idr_mutex); |
669 | ib_destroy_cq(cq); | 669 | ib_destroy_cq(cq); |
670 | 670 | ||
671 | err: | 671 | err: |
@@ -701,7 +701,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, | |||
701 | goto out_wc; | 701 | goto out_wc; |
702 | } | 702 | } |
703 | 703 | ||
704 | down(&ib_uverbs_idr_mutex); | 704 | mutex_lock(&ib_uverbs_idr_mutex); |
705 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); | 705 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); |
706 | if (!cq || cq->uobject->context != file->ucontext) { | 706 | if (!cq || cq->uobject->context != file->ucontext) { |
707 | ret = -EINVAL; | 707 | ret = -EINVAL; |
@@ -731,7 +731,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file, | |||
731 | ret = -EFAULT; | 731 | ret = -EFAULT; |
732 | 732 | ||
733 | out: | 733 | out: |
734 | up(&ib_uverbs_idr_mutex); | 734 | mutex_unlock(&ib_uverbs_idr_mutex); |
735 | kfree(resp); | 735 | kfree(resp); |
736 | 736 | ||
737 | out_wc: | 737 | out_wc: |
@@ -750,14 +750,14 @@ ssize_t ib_uverbs_req_notify_cq(struct ib_uverbs_file *file, | |||
750 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 750 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
751 | return -EFAULT; | 751 | return -EFAULT; |
752 | 752 | ||
753 | down(&ib_uverbs_idr_mutex); | 753 | mutex_lock(&ib_uverbs_idr_mutex); |
754 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); | 754 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); |
755 | if (cq && cq->uobject->context == file->ucontext) { | 755 | if (cq && cq->uobject->context == file->ucontext) { |
756 | ib_req_notify_cq(cq, cmd.solicited_only ? | 756 | ib_req_notify_cq(cq, cmd.solicited_only ? |
757 | IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); | 757 | IB_CQ_SOLICITED : IB_CQ_NEXT_COMP); |
758 | ret = in_len; | 758 | ret = in_len; |
759 | } | 759 | } |
760 | up(&ib_uverbs_idr_mutex); | 760 | mutex_unlock(&ib_uverbs_idr_mutex); |
761 | 761 | ||
762 | return ret; | 762 | return ret; |
763 | } | 763 | } |
@@ -779,7 +779,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, | |||
779 | 779 | ||
780 | memset(&resp, 0, sizeof resp); | 780 | memset(&resp, 0, sizeof resp); |
781 | 781 | ||
782 | down(&ib_uverbs_idr_mutex); | 782 | mutex_lock(&ib_uverbs_idr_mutex); |
783 | 783 | ||
784 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); | 784 | cq = idr_find(&ib_uverbs_cq_idr, cmd.cq_handle); |
785 | if (!cq || cq->uobject->context != file->ucontext) | 785 | if (!cq || cq->uobject->context != file->ucontext) |
@@ -795,9 +795,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, | |||
795 | 795 | ||
796 | idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); | 796 | idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); |
797 | 797 | ||
798 | down(&file->mutex); | 798 | mutex_lock(&file->mutex); |
799 | list_del(&uobj->uobject.list); | 799 | list_del(&uobj->uobject.list); |
800 | up(&file->mutex); | 800 | mutex_unlock(&file->mutex); |
801 | 801 | ||
802 | ib_uverbs_release_ucq(file, ev_file, uobj); | 802 | ib_uverbs_release_ucq(file, ev_file, uobj); |
803 | 803 | ||
@@ -811,7 +811,7 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, | |||
811 | ret = -EFAULT; | 811 | ret = -EFAULT; |
812 | 812 | ||
813 | out: | 813 | out: |
814 | up(&ib_uverbs_idr_mutex); | 814 | mutex_unlock(&ib_uverbs_idr_mutex); |
815 | 815 | ||
816 | return ret ? ret : in_len; | 816 | return ret ? ret : in_len; |
817 | } | 817 | } |
@@ -845,7 +845,7 @@ ssize_t ib_uverbs_create_qp(struct ib_uverbs_file *file, | |||
845 | if (!uobj) | 845 | if (!uobj) |
846 | return -ENOMEM; | 846 | return -ENOMEM; |
847 | 847 | ||
848 | down(&ib_uverbs_idr_mutex); | 848 | mutex_lock(&ib_uverbs_idr_mutex); |
849 | 849 | ||
850 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 850 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
851 | scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); | 851 | scq = idr_find(&ib_uverbs_cq_idr, cmd.send_cq_handle); |
@@ -930,11 +930,11 @@ retry: | |||
930 | goto err_idr; | 930 | goto err_idr; |
931 | } | 931 | } |
932 | 932 | ||
933 | down(&file->mutex); | 933 | mutex_lock(&file->mutex); |
934 | list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list); | 934 | list_add_tail(&uobj->uevent.uobject.list, &file->ucontext->qp_list); |
935 | up(&file->mutex); | 935 | mutex_unlock(&file->mutex); |
936 | 936 | ||
937 | up(&ib_uverbs_idr_mutex); | 937 | mutex_unlock(&ib_uverbs_idr_mutex); |
938 | 938 | ||
939 | return in_len; | 939 | return in_len; |
940 | 940 | ||
@@ -950,7 +950,7 @@ err_destroy: | |||
950 | atomic_dec(&attr.srq->usecnt); | 950 | atomic_dec(&attr.srq->usecnt); |
951 | 951 | ||
952 | err_up: | 952 | err_up: |
953 | up(&ib_uverbs_idr_mutex); | 953 | mutex_unlock(&ib_uverbs_idr_mutex); |
954 | 954 | ||
955 | kfree(uobj); | 955 | kfree(uobj); |
956 | return ret; | 956 | return ret; |
@@ -972,7 +972,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, | |||
972 | if (!attr) | 972 | if (!attr) |
973 | return -ENOMEM; | 973 | return -ENOMEM; |
974 | 974 | ||
975 | down(&ib_uverbs_idr_mutex); | 975 | mutex_lock(&ib_uverbs_idr_mutex); |
976 | 976 | ||
977 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 977 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
978 | if (!qp || qp->uobject->context != file->ucontext) { | 978 | if (!qp || qp->uobject->context != file->ucontext) { |
@@ -1033,7 +1033,7 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file, | |||
1033 | ret = in_len; | 1033 | ret = in_len; |
1034 | 1034 | ||
1035 | out: | 1035 | out: |
1036 | up(&ib_uverbs_idr_mutex); | 1036 | mutex_unlock(&ib_uverbs_idr_mutex); |
1037 | kfree(attr); | 1037 | kfree(attr); |
1038 | 1038 | ||
1039 | return ret; | 1039 | return ret; |
@@ -1054,7 +1054,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, | |||
1054 | 1054 | ||
1055 | memset(&resp, 0, sizeof resp); | 1055 | memset(&resp, 0, sizeof resp); |
1056 | 1056 | ||
1057 | down(&ib_uverbs_idr_mutex); | 1057 | mutex_lock(&ib_uverbs_idr_mutex); |
1058 | 1058 | ||
1059 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1059 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
1060 | if (!qp || qp->uobject->context != file->ucontext) | 1060 | if (!qp || qp->uobject->context != file->ucontext) |
@@ -1073,9 +1073,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, | |||
1073 | 1073 | ||
1074 | idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); | 1074 | idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); |
1075 | 1075 | ||
1076 | down(&file->mutex); | 1076 | mutex_lock(&file->mutex); |
1077 | list_del(&uobj->uevent.uobject.list); | 1077 | list_del(&uobj->uevent.uobject.list); |
1078 | up(&file->mutex); | 1078 | mutex_unlock(&file->mutex); |
1079 | 1079 | ||
1080 | ib_uverbs_release_uevent(file, &uobj->uevent); | 1080 | ib_uverbs_release_uevent(file, &uobj->uevent); |
1081 | 1081 | ||
@@ -1088,7 +1088,7 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, | |||
1088 | ret = -EFAULT; | 1088 | ret = -EFAULT; |
1089 | 1089 | ||
1090 | out: | 1090 | out: |
1091 | up(&ib_uverbs_idr_mutex); | 1091 | mutex_unlock(&ib_uverbs_idr_mutex); |
1092 | 1092 | ||
1093 | return ret ? ret : in_len; | 1093 | return ret ? ret : in_len; |
1094 | } | 1094 | } |
@@ -1119,7 +1119,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, | |||
1119 | if (!user_wr) | 1119 | if (!user_wr) |
1120 | return -ENOMEM; | 1120 | return -ENOMEM; |
1121 | 1121 | ||
1122 | down(&ib_uverbs_idr_mutex); | 1122 | mutex_lock(&ib_uverbs_idr_mutex); |
1123 | 1123 | ||
1124 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1124 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
1125 | if (!qp || qp->uobject->context != file->ucontext) | 1125 | if (!qp || qp->uobject->context != file->ucontext) |
@@ -1224,7 +1224,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file, | |||
1224 | ret = -EFAULT; | 1224 | ret = -EFAULT; |
1225 | 1225 | ||
1226 | out: | 1226 | out: |
1227 | up(&ib_uverbs_idr_mutex); | 1227 | mutex_unlock(&ib_uverbs_idr_mutex); |
1228 | 1228 | ||
1229 | while (wr) { | 1229 | while (wr) { |
1230 | next = wr->next; | 1230 | next = wr->next; |
@@ -1341,7 +1341,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, | |||
1341 | if (IS_ERR(wr)) | 1341 | if (IS_ERR(wr)) |
1342 | return PTR_ERR(wr); | 1342 | return PTR_ERR(wr); |
1343 | 1343 | ||
1344 | down(&ib_uverbs_idr_mutex); | 1344 | mutex_lock(&ib_uverbs_idr_mutex); |
1345 | 1345 | ||
1346 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1346 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
1347 | if (!qp || qp->uobject->context != file->ucontext) | 1347 | if (!qp || qp->uobject->context != file->ucontext) |
@@ -1362,7 +1362,7 @@ ssize_t ib_uverbs_post_recv(struct ib_uverbs_file *file, | |||
1362 | ret = -EFAULT; | 1362 | ret = -EFAULT; |
1363 | 1363 | ||
1364 | out: | 1364 | out: |
1365 | up(&ib_uverbs_idr_mutex); | 1365 | mutex_unlock(&ib_uverbs_idr_mutex); |
1366 | 1366 | ||
1367 | while (wr) { | 1367 | while (wr) { |
1368 | next = wr->next; | 1368 | next = wr->next; |
@@ -1392,7 +1392,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, | |||
1392 | if (IS_ERR(wr)) | 1392 | if (IS_ERR(wr)) |
1393 | return PTR_ERR(wr); | 1393 | return PTR_ERR(wr); |
1394 | 1394 | ||
1395 | down(&ib_uverbs_idr_mutex); | 1395 | mutex_lock(&ib_uverbs_idr_mutex); |
1396 | 1396 | ||
1397 | srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); | 1397 | srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); |
1398 | if (!srq || srq->uobject->context != file->ucontext) | 1398 | if (!srq || srq->uobject->context != file->ucontext) |
@@ -1413,7 +1413,7 @@ ssize_t ib_uverbs_post_srq_recv(struct ib_uverbs_file *file, | |||
1413 | ret = -EFAULT; | 1413 | ret = -EFAULT; |
1414 | 1414 | ||
1415 | out: | 1415 | out: |
1416 | up(&ib_uverbs_idr_mutex); | 1416 | mutex_unlock(&ib_uverbs_idr_mutex); |
1417 | 1417 | ||
1418 | while (wr) { | 1418 | while (wr) { |
1419 | next = wr->next; | 1419 | next = wr->next; |
@@ -1446,7 +1446,7 @@ ssize_t ib_uverbs_create_ah(struct ib_uverbs_file *file, | |||
1446 | if (!uobj) | 1446 | if (!uobj) |
1447 | return -ENOMEM; | 1447 | return -ENOMEM; |
1448 | 1448 | ||
1449 | down(&ib_uverbs_idr_mutex); | 1449 | mutex_lock(&ib_uverbs_idr_mutex); |
1450 | 1450 | ||
1451 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 1451 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
1452 | if (!pd || pd->uobject->context != file->ucontext) { | 1452 | if (!pd || pd->uobject->context != file->ucontext) { |
@@ -1498,11 +1498,11 @@ retry: | |||
1498 | goto err_idr; | 1498 | goto err_idr; |
1499 | } | 1499 | } |
1500 | 1500 | ||
1501 | down(&file->mutex); | 1501 | mutex_lock(&file->mutex); |
1502 | list_add_tail(&uobj->list, &file->ucontext->ah_list); | 1502 | list_add_tail(&uobj->list, &file->ucontext->ah_list); |
1503 | up(&file->mutex); | 1503 | mutex_unlock(&file->mutex); |
1504 | 1504 | ||
1505 | up(&ib_uverbs_idr_mutex); | 1505 | mutex_unlock(&ib_uverbs_idr_mutex); |
1506 | 1506 | ||
1507 | return in_len; | 1507 | return in_len; |
1508 | 1508 | ||
@@ -1513,7 +1513,7 @@ err_destroy: | |||
1513 | ib_destroy_ah(ah); | 1513 | ib_destroy_ah(ah); |
1514 | 1514 | ||
1515 | err_up: | 1515 | err_up: |
1516 | up(&ib_uverbs_idr_mutex); | 1516 | mutex_unlock(&ib_uverbs_idr_mutex); |
1517 | 1517 | ||
1518 | kfree(uobj); | 1518 | kfree(uobj); |
1519 | return ret; | 1519 | return ret; |
@@ -1530,7 +1530,7 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file, | |||
1530 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1530 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
1531 | return -EFAULT; | 1531 | return -EFAULT; |
1532 | 1532 | ||
1533 | down(&ib_uverbs_idr_mutex); | 1533 | mutex_lock(&ib_uverbs_idr_mutex); |
1534 | 1534 | ||
1535 | ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle); | 1535 | ah = idr_find(&ib_uverbs_ah_idr, cmd.ah_handle); |
1536 | if (!ah || ah->uobject->context != file->ucontext) | 1536 | if (!ah || ah->uobject->context != file->ucontext) |
@@ -1544,14 +1544,14 @@ ssize_t ib_uverbs_destroy_ah(struct ib_uverbs_file *file, | |||
1544 | 1544 | ||
1545 | idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle); | 1545 | idr_remove(&ib_uverbs_ah_idr, cmd.ah_handle); |
1546 | 1546 | ||
1547 | down(&file->mutex); | 1547 | mutex_lock(&file->mutex); |
1548 | list_del(&uobj->list); | 1548 | list_del(&uobj->list); |
1549 | up(&file->mutex); | 1549 | mutex_unlock(&file->mutex); |
1550 | 1550 | ||
1551 | kfree(uobj); | 1551 | kfree(uobj); |
1552 | 1552 | ||
1553 | out: | 1553 | out: |
1554 | up(&ib_uverbs_idr_mutex); | 1554 | mutex_unlock(&ib_uverbs_idr_mutex); |
1555 | 1555 | ||
1556 | return ret ? ret : in_len; | 1556 | return ret ? ret : in_len; |
1557 | } | 1557 | } |
@@ -1569,7 +1569,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, | |||
1569 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1569 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
1570 | return -EFAULT; | 1570 | return -EFAULT; |
1571 | 1571 | ||
1572 | down(&ib_uverbs_idr_mutex); | 1572 | mutex_lock(&ib_uverbs_idr_mutex); |
1573 | 1573 | ||
1574 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1574 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
1575 | if (!qp || qp->uobject->context != file->ucontext) | 1575 | if (!qp || qp->uobject->context != file->ucontext) |
@@ -1602,7 +1602,7 @@ ssize_t ib_uverbs_attach_mcast(struct ib_uverbs_file *file, | |||
1602 | kfree(mcast); | 1602 | kfree(mcast); |
1603 | 1603 | ||
1604 | out: | 1604 | out: |
1605 | up(&ib_uverbs_idr_mutex); | 1605 | mutex_unlock(&ib_uverbs_idr_mutex); |
1606 | 1606 | ||
1607 | return ret ? ret : in_len; | 1607 | return ret ? ret : in_len; |
1608 | } | 1608 | } |
@@ -1620,7 +1620,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, | |||
1620 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1620 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
1621 | return -EFAULT; | 1621 | return -EFAULT; |
1622 | 1622 | ||
1623 | down(&ib_uverbs_idr_mutex); | 1623 | mutex_lock(&ib_uverbs_idr_mutex); |
1624 | 1624 | ||
1625 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); | 1625 | qp = idr_find(&ib_uverbs_qp_idr, cmd.qp_handle); |
1626 | if (!qp || qp->uobject->context != file->ucontext) | 1626 | if (!qp || qp->uobject->context != file->ucontext) |
@@ -1641,7 +1641,7 @@ ssize_t ib_uverbs_detach_mcast(struct ib_uverbs_file *file, | |||
1641 | } | 1641 | } |
1642 | 1642 | ||
1643 | out: | 1643 | out: |
1644 | up(&ib_uverbs_idr_mutex); | 1644 | mutex_unlock(&ib_uverbs_idr_mutex); |
1645 | 1645 | ||
1646 | return ret ? ret : in_len; | 1646 | return ret ? ret : in_len; |
1647 | } | 1647 | } |
@@ -1673,7 +1673,7 @@ ssize_t ib_uverbs_create_srq(struct ib_uverbs_file *file, | |||
1673 | if (!uobj) | 1673 | if (!uobj) |
1674 | return -ENOMEM; | 1674 | return -ENOMEM; |
1675 | 1675 | ||
1676 | down(&ib_uverbs_idr_mutex); | 1676 | mutex_lock(&ib_uverbs_idr_mutex); |
1677 | 1677 | ||
1678 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); | 1678 | pd = idr_find(&ib_uverbs_pd_idr, cmd.pd_handle); |
1679 | 1679 | ||
@@ -1730,11 +1730,11 @@ retry: | |||
1730 | goto err_idr; | 1730 | goto err_idr; |
1731 | } | 1731 | } |
1732 | 1732 | ||
1733 | down(&file->mutex); | 1733 | mutex_lock(&file->mutex); |
1734 | list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); | 1734 | list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); |
1735 | up(&file->mutex); | 1735 | mutex_unlock(&file->mutex); |
1736 | 1736 | ||
1737 | up(&ib_uverbs_idr_mutex); | 1737 | mutex_unlock(&ib_uverbs_idr_mutex); |
1738 | 1738 | ||
1739 | return in_len; | 1739 | return in_len; |
1740 | 1740 | ||
@@ -1746,7 +1746,7 @@ err_destroy: | |||
1746 | atomic_dec(&pd->usecnt); | 1746 | atomic_dec(&pd->usecnt); |
1747 | 1747 | ||
1748 | err_up: | 1748 | err_up: |
1749 | up(&ib_uverbs_idr_mutex); | 1749 | mutex_unlock(&ib_uverbs_idr_mutex); |
1750 | 1750 | ||
1751 | kfree(uobj); | 1751 | kfree(uobj); |
1752 | return ret; | 1752 | return ret; |
@@ -1764,7 +1764,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, | |||
1764 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1764 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
1765 | return -EFAULT; | 1765 | return -EFAULT; |
1766 | 1766 | ||
1767 | down(&ib_uverbs_idr_mutex); | 1767 | mutex_lock(&ib_uverbs_idr_mutex); |
1768 | 1768 | ||
1769 | srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); | 1769 | srq = idr_find(&ib_uverbs_srq_idr, cmd.srq_handle); |
1770 | if (!srq || srq->uobject->context != file->ucontext) { | 1770 | if (!srq || srq->uobject->context != file->ucontext) { |
@@ -1778,7 +1778,7 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file, | |||
1778 | ret = ib_modify_srq(srq, &attr, cmd.attr_mask); | 1778 | ret = ib_modify_srq(srq, &attr, cmd.attr_mask); |
1779 | 1779 | ||
1780 | out: | 1780 | out: |
1781 | up(&ib_uverbs_idr_mutex); | 1781 | mutex_unlock(&ib_uverbs_idr_mutex); |
1782 | 1782 | ||
1783 | return ret ? ret : in_len; | 1783 | return ret ? ret : in_len; |
1784 | } | 1784 | } |
@@ -1796,7 +1796,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, | |||
1796 | if (copy_from_user(&cmd, buf, sizeof cmd)) | 1796 | if (copy_from_user(&cmd, buf, sizeof cmd)) |
1797 | return -EFAULT; | 1797 | return -EFAULT; |
1798 | 1798 | ||
1799 | down(&ib_uverbs_idr_mutex); | 1799 | mutex_lock(&ib_uverbs_idr_mutex); |
1800 | 1800 | ||
1801 | memset(&resp, 0, sizeof resp); | 1801 | memset(&resp, 0, sizeof resp); |
1802 | 1802 | ||
@@ -1812,9 +1812,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, | |||
1812 | 1812 | ||
1813 | idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); | 1813 | idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); |
1814 | 1814 | ||
1815 | down(&file->mutex); | 1815 | mutex_lock(&file->mutex); |
1816 | list_del(&uobj->uobject.list); | 1816 | list_del(&uobj->uobject.list); |
1817 | up(&file->mutex); | 1817 | mutex_unlock(&file->mutex); |
1818 | 1818 | ||
1819 | ib_uverbs_release_uevent(file, uobj); | 1819 | ib_uverbs_release_uevent(file, uobj); |
1820 | 1820 | ||
@@ -1827,7 +1827,7 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, | |||
1827 | ret = -EFAULT; | 1827 | ret = -EFAULT; |
1828 | 1828 | ||
1829 | out: | 1829 | out: |
1830 | up(&ib_uverbs_idr_mutex); | 1830 | mutex_unlock(&ib_uverbs_idr_mutex); |
1831 | 1831 | ||
1832 | return ret ? ret : in_len; | 1832 | return ret ? ret : in_len; |
1833 | } | 1833 | } |
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index 81737bd6faea..96ea79b63df7 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c | |||
@@ -66,7 +66,7 @@ enum { | |||
66 | 66 | ||
67 | static struct class *uverbs_class; | 67 | static struct class *uverbs_class; |
68 | 68 | ||
69 | DECLARE_MUTEX(ib_uverbs_idr_mutex); | 69 | DEFINE_MUTEX(ib_uverbs_idr_mutex); |
70 | DEFINE_IDR(ib_uverbs_pd_idr); | 70 | DEFINE_IDR(ib_uverbs_pd_idr); |
71 | DEFINE_IDR(ib_uverbs_mr_idr); | 71 | DEFINE_IDR(ib_uverbs_mr_idr); |
72 | DEFINE_IDR(ib_uverbs_mw_idr); | 72 | DEFINE_IDR(ib_uverbs_mw_idr); |
@@ -180,7 +180,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, | |||
180 | if (!context) | 180 | if (!context) |
181 | return 0; | 181 | return 0; |
182 | 182 | ||
183 | down(&ib_uverbs_idr_mutex); | 183 | mutex_lock(&ib_uverbs_idr_mutex); |
184 | 184 | ||
185 | list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { | 185 | list_for_each_entry_safe(uobj, tmp, &context->ah_list, list) { |
186 | struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id); | 186 | struct ib_ah *ah = idr_find(&ib_uverbs_ah_idr, uobj->id); |
@@ -250,7 +250,7 @@ static int ib_uverbs_cleanup_ucontext(struct ib_uverbs_file *file, | |||
250 | kfree(uobj); | 250 | kfree(uobj); |
251 | } | 251 | } |
252 | 252 | ||
253 | up(&ib_uverbs_idr_mutex); | 253 | mutex_unlock(&ib_uverbs_idr_mutex); |
254 | 254 | ||
255 | return context->device->dealloc_ucontext(context); | 255 | return context->device->dealloc_ucontext(context); |
256 | } | 256 | } |
@@ -653,7 +653,7 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) | |||
653 | file->ucontext = NULL; | 653 | file->ucontext = NULL; |
654 | file->async_file = NULL; | 654 | file->async_file = NULL; |
655 | kref_init(&file->ref); | 655 | kref_init(&file->ref); |
656 | init_MUTEX(&file->mutex); | 656 | mutex_init(&file->mutex); |
657 | 657 | ||
658 | filp->private_data = file; | 658 | filp->private_data = file; |
659 | 659 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index 22fdc446f25c..a14eed08a0fc 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c | |||
@@ -163,6 +163,11 @@ int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah) | |||
163 | return 0; | 163 | return 0; |
164 | } | 164 | } |
165 | 165 | ||
166 | int mthca_ah_grh_present(struct mthca_ah *ah) | ||
167 | { | ||
168 | return !!(ah->av->g_slid & 0x80); | ||
169 | } | ||
170 | |||
166 | int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, | 171 | int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, |
167 | struct ib_ud_header *header) | 172 | struct ib_ud_header *header) |
168 | { | 173 | { |
@@ -172,8 +177,7 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, | |||
172 | header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; | 177 | header->lrh.service_level = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28; |
173 | header->lrh.destination_lid = ah->av->dlid; | 178 | header->lrh.destination_lid = ah->av->dlid; |
174 | header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f); | 179 | header->lrh.source_lid = cpu_to_be16(ah->av->g_slid & 0x7f); |
175 | if (ah->av->g_slid & 0x80) { | 180 | if (mthca_ah_grh_present(ah)) { |
176 | header->grh_present = 1; | ||
177 | header->grh.traffic_class = | 181 | header->grh.traffic_class = |
178 | (be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff; | 182 | (be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 20) & 0xff; |
179 | header->grh.flow_label = | 183 | header->grh.flow_label = |
@@ -184,8 +188,6 @@ int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, | |||
184 | &header->grh.source_gid); | 188 | &header->grh.source_gid); |
185 | memcpy(header->grh.destination_gid.raw, | 189 | memcpy(header->grh.destination_gid.raw, |
186 | ah->av->dgid, 16); | 190 | ah->av->dgid, 16); |
187 | } else { | ||
188 | header->grh_present = 0; | ||
189 | } | 191 | } |
190 | 192 | ||
191 | return 0; | 193 | return 0; |
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index 22ac72bc20c3..be1791be627b 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c | |||
@@ -606,7 +606,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, | |||
606 | err = -EINVAL; | 606 | err = -EINVAL; |
607 | goto out; | 607 | goto out; |
608 | } | 608 | } |
609 | for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i) { | 609 | for (i = 0; i < mthca_icm_size(&iter) >> lg; ++i) { |
610 | if (virt != -1) { | 610 | if (virt != -1) { |
611 | pages[nent * 2] = cpu_to_be64(virt); | 611 | pages[nent * 2] = cpu_to_be64(virt); |
612 | virt += 1 << lg; | 612 | virt += 1 << lg; |
@@ -727,8 +727,8 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) | |||
727 | * system pages needed. | 727 | * system pages needed. |
728 | */ | 728 | */ |
729 | dev->fw.arbel.fw_pages = | 729 | dev->fw.arbel.fw_pages = |
730 | (dev->fw.arbel.fw_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> | 730 | ALIGN(dev->fw.arbel.fw_pages, PAGE_SIZE >> 12) >> |
731 | (PAGE_SHIFT - 12); | 731 | (PAGE_SHIFT - 12); |
732 | 732 | ||
733 | mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n", | 733 | mthca_dbg(dev, "Clear int @ %llx, EQ arm @ %llx, EQ set CI @ %llx\n", |
734 | (unsigned long long) dev->fw.arbel.clr_int_base, | 734 | (unsigned long long) dev->fw.arbel.clr_int_base, |
@@ -1445,6 +1445,7 @@ int mthca_SET_ICM_SIZE(struct mthca_dev *dev, u64 icm_size, u64 *aux_pages, | |||
1445 | * pages needed. | 1445 | * pages needed. |
1446 | */ | 1446 | */ |
1447 | *aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12); | 1447 | *aux_pages = (*aux_pages + (1 << (PAGE_SHIFT - 12)) - 1) >> (PAGE_SHIFT - 12); |
1448 | *aux_pages = ALIGN(*aux_pages, PAGE_SIZE >> 12) >> (PAGE_SHIFT - 12); | ||
1448 | 1449 | ||
1449 | return 0; | 1450 | return 0; |
1450 | } | 1451 | } |
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 795b379260bf..a104ab041ea3 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h | |||
@@ -520,6 +520,7 @@ int mthca_create_ah(struct mthca_dev *dev, | |||
520 | int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah); | 520 | int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah); |
521 | int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, | 521 | int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah, |
522 | struct ib_ud_header *header); | 522 | struct ib_ud_header *header); |
523 | int mthca_ah_grh_present(struct mthca_ah *ah); | ||
523 | 524 | ||
524 | int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); | 525 | int mthca_multicast_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); |
525 | int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); | 526 | int mthca_multicast_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid); |
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index e8a948f087c0..2eabb27804cd 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c | |||
@@ -45,6 +45,7 @@ | |||
45 | enum { | 45 | enum { |
46 | MTHCA_NUM_ASYNC_EQE = 0x80, | 46 | MTHCA_NUM_ASYNC_EQE = 0x80, |
47 | MTHCA_NUM_CMD_EQE = 0x80, | 47 | MTHCA_NUM_CMD_EQE = 0x80, |
48 | MTHCA_NUM_SPARE_EQE = 0x80, | ||
48 | MTHCA_EQ_ENTRY_SIZE = 0x20 | 49 | MTHCA_EQ_ENTRY_SIZE = 0x20 |
49 | }; | 50 | }; |
50 | 51 | ||
@@ -277,11 +278,10 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq) | |||
277 | { | 278 | { |
278 | struct mthca_eqe *eqe; | 279 | struct mthca_eqe *eqe; |
279 | int disarm_cqn; | 280 | int disarm_cqn; |
280 | int eqes_found = 0; | 281 | int eqes_found = 0; |
282 | int set_ci = 0; | ||
281 | 283 | ||
282 | while ((eqe = next_eqe_sw(eq))) { | 284 | while ((eqe = next_eqe_sw(eq))) { |
283 | int set_ci = 0; | ||
284 | |||
285 | /* | 285 | /* |
286 | * Make sure we read EQ entry contents after we've | 286 | * Make sure we read EQ entry contents after we've |
287 | * checked the ownership bit. | 287 | * checked the ownership bit. |
@@ -345,12 +345,6 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq) | |||
345 | be16_to_cpu(eqe->event.cmd.token), | 345 | be16_to_cpu(eqe->event.cmd.token), |
346 | eqe->event.cmd.status, | 346 | eqe->event.cmd.status, |
347 | be64_to_cpu(eqe->event.cmd.out_param)); | 347 | be64_to_cpu(eqe->event.cmd.out_param)); |
348 | /* | ||
349 | * cmd_event() may add more commands. | ||
350 | * The card will think the queue has overflowed if | ||
351 | * we don't tell it we've been processing events. | ||
352 | */ | ||
353 | set_ci = 1; | ||
354 | break; | 348 | break; |
355 | 349 | ||
356 | case MTHCA_EVENT_TYPE_PORT_CHANGE: | 350 | case MTHCA_EVENT_TYPE_PORT_CHANGE: |
@@ -385,8 +379,16 @@ static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq) | |||
385 | set_eqe_hw(eqe); | 379 | set_eqe_hw(eqe); |
386 | ++eq->cons_index; | 380 | ++eq->cons_index; |
387 | eqes_found = 1; | 381 | eqes_found = 1; |
382 | ++set_ci; | ||
388 | 383 | ||
389 | if (unlikely(set_ci)) { | 384 | /* |
385 | * The HCA will think the queue has overflowed if we | ||
386 | * don't tell it we've been processing events. We | ||
387 | * create our EQs with MTHCA_NUM_SPARE_EQE extra | ||
388 | * entries, so we must update our consumer index at | ||
389 | * least that often. | ||
390 | */ | ||
391 | if (unlikely(set_ci >= MTHCA_NUM_SPARE_EQE)) { | ||
390 | /* | 392 | /* |
391 | * Conditional on hca_type is OK here because | 393 | * Conditional on hca_type is OK here because |
392 | * this is a rare case, not the fast path. | 394 | * this is a rare case, not the fast path. |
@@ -862,19 +864,19 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev) | |||
862 | intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ? | 864 | intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ? |
863 | 128 : dev->eq_table.inta_pin; | 865 | 128 : dev->eq_table.inta_pin; |
864 | 866 | ||
865 | err = mthca_create_eq(dev, dev->limits.num_cqs, | 867 | err = mthca_create_eq(dev, dev->limits.num_cqs + MTHCA_NUM_SPARE_EQE, |
866 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr, | 868 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr, |
867 | &dev->eq_table.eq[MTHCA_EQ_COMP]); | 869 | &dev->eq_table.eq[MTHCA_EQ_COMP]); |
868 | if (err) | 870 | if (err) |
869 | goto err_out_unmap; | 871 | goto err_out_unmap; |
870 | 872 | ||
871 | err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE, | 873 | err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE + MTHCA_NUM_SPARE_EQE, |
872 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr, | 874 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr, |
873 | &dev->eq_table.eq[MTHCA_EQ_ASYNC]); | 875 | &dev->eq_table.eq[MTHCA_EQ_ASYNC]); |
874 | if (err) | 876 | if (err) |
875 | goto err_out_comp; | 877 | goto err_out_comp; |
876 | 878 | ||
877 | err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE, | 879 | err = mthca_create_eq(dev, MTHCA_NUM_CMD_EQE + MTHCA_NUM_SPARE_EQE, |
878 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr, | 880 | (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 130 : intr, |
879 | &dev->eq_table.eq[MTHCA_EQ_CMD]); | 881 | &dev->eq_table.eq[MTHCA_EQ_CMD]); |
880 | if (err) | 882 | if (err) |
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 4cc7e2846df1..484a7e6b7f8c 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c | |||
@@ -33,7 +33,7 @@ | |||
33 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 33 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
34 | * SOFTWARE. | 34 | * SOFTWARE. |
35 | * | 35 | * |
36 | * $Id: mthca_provider.c 1397 2004-12-28 05:09:00Z roland $ | 36 | * $Id: mthca_provider.c 4859 2006-01-09 21:55:10Z roland $ |
37 | */ | 37 | */ |
38 | 38 | ||
39 | #include <rdma/ib_smi.h> | 39 | #include <rdma/ib_smi.h> |
@@ -45,6 +45,14 @@ | |||
45 | #include "mthca_user.h" | 45 | #include "mthca_user.h" |
46 | #include "mthca_memfree.h" | 46 | #include "mthca_memfree.h" |
47 | 47 | ||
48 | static void init_query_mad(struct ib_smp *mad) | ||
49 | { | ||
50 | mad->base_version = 1; | ||
51 | mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | ||
52 | mad->class_version = 1; | ||
53 | mad->method = IB_MGMT_METHOD_GET; | ||
54 | } | ||
55 | |||
48 | static int mthca_query_device(struct ib_device *ibdev, | 56 | static int mthca_query_device(struct ib_device *ibdev, |
49 | struct ib_device_attr *props) | 57 | struct ib_device_attr *props) |
50 | { | 58 | { |
@@ -55,7 +63,7 @@ static int mthca_query_device(struct ib_device *ibdev, | |||
55 | 63 | ||
56 | u8 status; | 64 | u8 status; |
57 | 65 | ||
58 | in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); | 66 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
59 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 67 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
60 | if (!in_mad || !out_mad) | 68 | if (!in_mad || !out_mad) |
61 | goto out; | 69 | goto out; |
@@ -64,12 +72,8 @@ static int mthca_query_device(struct ib_device *ibdev, | |||
64 | 72 | ||
65 | props->fw_ver = mdev->fw_ver; | 73 | props->fw_ver = mdev->fw_ver; |
66 | 74 | ||
67 | memset(in_mad, 0, sizeof *in_mad); | 75 | init_query_mad(in_mad); |
68 | in_mad->base_version = 1; | 76 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; |
69 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | ||
70 | in_mad->class_version = 1; | ||
71 | in_mad->method = IB_MGMT_METHOD_GET; | ||
72 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | ||
73 | 77 | ||
74 | err = mthca_MAD_IFC(mdev, 1, 1, | 78 | err = mthca_MAD_IFC(mdev, 1, 1, |
75 | 1, NULL, NULL, in_mad, out_mad, | 79 | 1, NULL, NULL, in_mad, out_mad, |
@@ -87,7 +91,6 @@ static int mthca_query_device(struct ib_device *ibdev, | |||
87 | props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); | 91 | props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); |
88 | props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); | 92 | props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); |
89 | memcpy(&props->sys_image_guid, out_mad->data + 4, 8); | 93 | memcpy(&props->sys_image_guid, out_mad->data + 4, 8); |
90 | memcpy(&props->node_guid, out_mad->data + 12, 8); | ||
91 | 94 | ||
92 | props->max_mr_size = ~0ull; | 95 | props->max_mr_size = ~0ull; |
93 | props->page_size_cap = mdev->limits.page_size_cap; | 96 | props->page_size_cap = mdev->limits.page_size_cap; |
@@ -128,20 +131,16 @@ static int mthca_query_port(struct ib_device *ibdev, | |||
128 | int err = -ENOMEM; | 131 | int err = -ENOMEM; |
129 | u8 status; | 132 | u8 status; |
130 | 133 | ||
131 | in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); | 134 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
132 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 135 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
133 | if (!in_mad || !out_mad) | 136 | if (!in_mad || !out_mad) |
134 | goto out; | 137 | goto out; |
135 | 138 | ||
136 | memset(props, 0, sizeof *props); | 139 | memset(props, 0, sizeof *props); |
137 | 140 | ||
138 | memset(in_mad, 0, sizeof *in_mad); | 141 | init_query_mad(in_mad); |
139 | in_mad->base_version = 1; | 142 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; |
140 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | 143 | in_mad->attr_mod = cpu_to_be32(port); |
141 | in_mad->class_version = 1; | ||
142 | in_mad->method = IB_MGMT_METHOD_GET; | ||
143 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | ||
144 | in_mad->attr_mod = cpu_to_be32(port); | ||
145 | 144 | ||
146 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, | 145 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, |
147 | port, NULL, NULL, in_mad, out_mad, | 146 | port, NULL, NULL, in_mad, out_mad, |
@@ -220,18 +219,14 @@ static int mthca_query_pkey(struct ib_device *ibdev, | |||
220 | int err = -ENOMEM; | 219 | int err = -ENOMEM; |
221 | u8 status; | 220 | u8 status; |
222 | 221 | ||
223 | in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); | 222 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
224 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 223 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
225 | if (!in_mad || !out_mad) | 224 | if (!in_mad || !out_mad) |
226 | goto out; | 225 | goto out; |
227 | 226 | ||
228 | memset(in_mad, 0, sizeof *in_mad); | 227 | init_query_mad(in_mad); |
229 | in_mad->base_version = 1; | 228 | in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; |
230 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | 229 | in_mad->attr_mod = cpu_to_be32(index / 32); |
231 | in_mad->class_version = 1; | ||
232 | in_mad->method = IB_MGMT_METHOD_GET; | ||
233 | in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; | ||
234 | in_mad->attr_mod = cpu_to_be32(index / 32); | ||
235 | 230 | ||
236 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, | 231 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, |
237 | port, NULL, NULL, in_mad, out_mad, | 232 | port, NULL, NULL, in_mad, out_mad, |
@@ -259,18 +254,14 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port, | |||
259 | int err = -ENOMEM; | 254 | int err = -ENOMEM; |
260 | u8 status; | 255 | u8 status; |
261 | 256 | ||
262 | in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); | 257 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); |
263 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | 258 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); |
264 | if (!in_mad || !out_mad) | 259 | if (!in_mad || !out_mad) |
265 | goto out; | 260 | goto out; |
266 | 261 | ||
267 | memset(in_mad, 0, sizeof *in_mad); | 262 | init_query_mad(in_mad); |
268 | in_mad->base_version = 1; | 263 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; |
269 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | 264 | in_mad->attr_mod = cpu_to_be32(port); |
270 | in_mad->class_version = 1; | ||
271 | in_mad->method = IB_MGMT_METHOD_GET; | ||
272 | in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; | ||
273 | in_mad->attr_mod = cpu_to_be32(port); | ||
274 | 265 | ||
275 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, | 266 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, |
276 | port, NULL, NULL, in_mad, out_mad, | 267 | port, NULL, NULL, in_mad, out_mad, |
@@ -284,13 +275,9 @@ static int mthca_query_gid(struct ib_device *ibdev, u8 port, | |||
284 | 275 | ||
285 | memcpy(gid->raw, out_mad->data + 8, 8); | 276 | memcpy(gid->raw, out_mad->data + 8, 8); |
286 | 277 | ||
287 | memset(in_mad, 0, sizeof *in_mad); | 278 | init_query_mad(in_mad); |
288 | in_mad->base_version = 1; | 279 | in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; |
289 | in_mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; | 280 | in_mad->attr_mod = cpu_to_be32(index / 8); |
290 | in_mad->class_version = 1; | ||
291 | in_mad->method = IB_MGMT_METHOD_GET; | ||
292 | in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; | ||
293 | in_mad->attr_mod = cpu_to_be32(index / 8); | ||
294 | 281 | ||
295 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, | 282 | err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1, |
296 | port, NULL, NULL, in_mad, out_mad, | 283 | port, NULL, NULL, in_mad, out_mad, |
@@ -458,8 +445,10 @@ static struct ib_srq *mthca_create_srq(struct ib_pd *pd, | |||
458 | if (pd->uobject) { | 445 | if (pd->uobject) { |
459 | context = to_mucontext(pd->uobject->context); | 446 | context = to_mucontext(pd->uobject->context); |
460 | 447 | ||
461 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) | 448 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { |
462 | return ERR_PTR(-EFAULT); | 449 | err = -EFAULT; |
450 | goto err_free; | ||
451 | } | ||
463 | 452 | ||
464 | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, | 453 | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, |
465 | context->db_tab, ucmd.db_index, | 454 | context->db_tab, ucmd.db_index, |
@@ -535,8 +524,10 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd, | |||
535 | if (pd->uobject) { | 524 | if (pd->uobject) { |
536 | context = to_mucontext(pd->uobject->context); | 525 | context = to_mucontext(pd->uobject->context); |
537 | 526 | ||
538 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) | 527 | if (ib_copy_from_udata(&ucmd, udata, sizeof ucmd)) { |
528 | kfree(qp); | ||
539 | return ERR_PTR(-EFAULT); | 529 | return ERR_PTR(-EFAULT); |
530 | } | ||
540 | 531 | ||
541 | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, | 532 | err = mthca_map_user_db(to_mdev(pd->device), &context->uar, |
542 | context->db_tab, | 533 | context->db_tab, |
@@ -783,24 +774,20 @@ static struct ib_mr *mthca_reg_phys_mr(struct ib_pd *pd, | |||
783 | if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK)) | 774 | if ((*iova_start & ~PAGE_MASK) != (buffer_list[0].addr & ~PAGE_MASK)) |
784 | return ERR_PTR(-EINVAL); | 775 | return ERR_PTR(-EINVAL); |
785 | 776 | ||
786 | if (num_phys_buf > 1 && | ||
787 | ((buffer_list[0].addr + buffer_list[0].size) & ~PAGE_MASK)) | ||
788 | return ERR_PTR(-EINVAL); | ||
789 | |||
790 | mask = 0; | 777 | mask = 0; |
791 | total_size = 0; | 778 | total_size = 0; |
792 | for (i = 0; i < num_phys_buf; ++i) { | 779 | for (i = 0; i < num_phys_buf; ++i) { |
793 | if (i != 0 && buffer_list[i].addr & ~PAGE_MASK) | 780 | if (i != 0) |
794 | return ERR_PTR(-EINVAL); | 781 | mask |= buffer_list[i].addr; |
795 | if (i != 0 && i != num_phys_buf - 1 && | 782 | if (i != num_phys_buf - 1) |
796 | (buffer_list[i].size & ~PAGE_MASK)) | 783 | mask |= buffer_list[i].addr + buffer_list[i].size; |
797 | return ERR_PTR(-EINVAL); | ||
798 | 784 | ||
799 | total_size += buffer_list[i].size; | 785 | total_size += buffer_list[i].size; |
800 | if (i > 0) | ||
801 | mask |= buffer_list[i].addr; | ||
802 | } | 786 | } |
803 | 787 | ||
788 | if (mask & ~PAGE_MASK) | ||
789 | return ERR_PTR(-EINVAL); | ||
790 | |||
804 | /* Find largest page shift we can use to cover buffers */ | 791 | /* Find largest page shift we can use to cover buffers */ |
805 | for (shift = PAGE_SHIFT; shift < 31; ++shift) | 792 | for (shift = PAGE_SHIFT; shift < 31; ++shift) |
806 | if (num_phys_buf > 1) { | 793 | if (num_phys_buf > 1) { |
@@ -1070,11 +1057,48 @@ static struct class_device_attribute *mthca_class_attributes[] = { | |||
1070 | &class_device_attr_board_id | 1057 | &class_device_attr_board_id |
1071 | }; | 1058 | }; |
1072 | 1059 | ||
1060 | static int mthca_init_node_data(struct mthca_dev *dev) | ||
1061 | { | ||
1062 | struct ib_smp *in_mad = NULL; | ||
1063 | struct ib_smp *out_mad = NULL; | ||
1064 | int err = -ENOMEM; | ||
1065 | u8 status; | ||
1066 | |||
1067 | in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); | ||
1068 | out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); | ||
1069 | if (!in_mad || !out_mad) | ||
1070 | goto out; | ||
1071 | |||
1072 | init_query_mad(in_mad); | ||
1073 | in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; | ||
1074 | |||
1075 | err = mthca_MAD_IFC(dev, 1, 1, | ||
1076 | 1, NULL, NULL, in_mad, out_mad, | ||
1077 | &status); | ||
1078 | if (err) | ||
1079 | goto out; | ||
1080 | if (status) { | ||
1081 | err = -EINVAL; | ||
1082 | goto out; | ||
1083 | } | ||
1084 | |||
1085 | memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8); | ||
1086 | |||
1087 | out: | ||
1088 | kfree(in_mad); | ||
1089 | kfree(out_mad); | ||
1090 | return err; | ||
1091 | } | ||
1092 | |||
1073 | int mthca_register_device(struct mthca_dev *dev) | 1093 | int mthca_register_device(struct mthca_dev *dev) |
1074 | { | 1094 | { |
1075 | int ret; | 1095 | int ret; |
1076 | int i; | 1096 | int i; |
1077 | 1097 | ||
1098 | ret = mthca_init_node_data(dev); | ||
1099 | if (ret) | ||
1100 | return ret; | ||
1101 | |||
1078 | strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX); | 1102 | strlcpy(dev->ib_dev.name, "mthca%d", IB_DEVICE_NAME_MAX); |
1079 | dev->ib_dev.owner = THIS_MODULE; | 1103 | dev->ib_dev.owner = THIS_MODULE; |
1080 | 1104 | ||
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c index 564b6d51c394..fba608ed7df2 100644 --- a/drivers/infiniband/hw/mthca/mthca_qp.c +++ b/drivers/infiniband/hw/mthca/mthca_qp.c | |||
@@ -1434,7 +1434,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp, | |||
1434 | u16 pkey; | 1434 | u16 pkey; |
1435 | 1435 | ||
1436 | ib_ud_header_init(256, /* assume a MAD */ | 1436 | ib_ud_header_init(256, /* assume a MAD */ |
1437 | sqp->ud_header.grh_present, | 1437 | mthca_ah_grh_present(to_mah(wr->wr.ud.ah)), |
1438 | &sqp->ud_header); | 1438 | &sqp->ud_header); |
1439 | 1439 | ||
1440 | err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header); | 1440 | err = mthca_read_ah(dev, to_mah(wr->wr.ud.ah), &sqp->ud_header); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 9923a15a9996..e0a5412b7e68 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h | |||
@@ -45,11 +45,11 @@ | |||
45 | #include <linux/config.h> | 45 | #include <linux/config.h> |
46 | #include <linux/kref.h> | 46 | #include <linux/kref.h> |
47 | #include <linux/if_infiniband.h> | 47 | #include <linux/if_infiniband.h> |
48 | #include <linux/mutex.h> | ||
48 | 49 | ||
49 | #include <net/neighbour.h> | 50 | #include <net/neighbour.h> |
50 | 51 | ||
51 | #include <asm/atomic.h> | 52 | #include <asm/atomic.h> |
52 | #include <asm/semaphore.h> | ||
53 | 53 | ||
54 | #include <rdma/ib_verbs.h> | 54 | #include <rdma/ib_verbs.h> |
55 | #include <rdma/ib_pack.h> | 55 | #include <rdma/ib_pack.h> |
@@ -123,8 +123,8 @@ struct ipoib_dev_priv { | |||
123 | 123 | ||
124 | unsigned long flags; | 124 | unsigned long flags; |
125 | 125 | ||
126 | struct semaphore mcast_mutex; | 126 | struct mutex mcast_mutex; |
127 | struct semaphore vlan_mutex; | 127 | struct mutex vlan_mutex; |
128 | 128 | ||
129 | struct rb_root path_tree; | 129 | struct rb_root path_tree; |
130 | struct list_head path_list; | 130 | struct list_head path_list; |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 23885801b6d2..86bcdd72a107 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
@@ -52,7 +52,7 @@ MODULE_PARM_DESC(data_debug_level, | |||
52 | 52 | ||
53 | #define IPOIB_OP_RECV (1ul << 31) | 53 | #define IPOIB_OP_RECV (1ul << 31) |
54 | 54 | ||
55 | static DECLARE_MUTEX(pkey_sem); | 55 | static DEFINE_MUTEX(pkey_mutex); |
56 | 56 | ||
57 | struct ipoib_ah *ipoib_create_ah(struct net_device *dev, | 57 | struct ipoib_ah *ipoib_create_ah(struct net_device *dev, |
58 | struct ib_pd *pd, struct ib_ah_attr *attr) | 58 | struct ib_pd *pd, struct ib_ah_attr *attr) |
@@ -445,25 +445,16 @@ int ipoib_ib_dev_down(struct net_device *dev) | |||
445 | 445 | ||
446 | /* Shutdown the P_Key thread if still active */ | 446 | /* Shutdown the P_Key thread if still active */ |
447 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { | 447 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { |
448 | down(&pkey_sem); | 448 | mutex_lock(&pkey_mutex); |
449 | set_bit(IPOIB_PKEY_STOP, &priv->flags); | 449 | set_bit(IPOIB_PKEY_STOP, &priv->flags); |
450 | cancel_delayed_work(&priv->pkey_task); | 450 | cancel_delayed_work(&priv->pkey_task); |
451 | up(&pkey_sem); | 451 | mutex_unlock(&pkey_mutex); |
452 | flush_workqueue(ipoib_workqueue); | 452 | flush_workqueue(ipoib_workqueue); |
453 | } | 453 | } |
454 | 454 | ||
455 | ipoib_mcast_stop_thread(dev, 1); | 455 | ipoib_mcast_stop_thread(dev, 1); |
456 | |||
457 | /* | ||
458 | * Flush the multicast groups first so we stop any multicast joins. The | ||
459 | * completion thread may have already died and we may deadlock waiting | ||
460 | * for the completion thread to finish some multicast joins. | ||
461 | */ | ||
462 | ipoib_mcast_dev_flush(dev); | 456 | ipoib_mcast_dev_flush(dev); |
463 | 457 | ||
464 | /* Delete broadcast and local addresses since they will be recreated */ | ||
465 | ipoib_mcast_dev_down(dev); | ||
466 | |||
467 | ipoib_flush_paths(dev); | 458 | ipoib_flush_paths(dev); |
468 | 459 | ||
469 | return 0; | 460 | return 0; |
@@ -608,13 +599,13 @@ void ipoib_ib_dev_flush(void *_dev) | |||
608 | if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) | 599 | if (test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)) |
609 | ipoib_ib_dev_up(dev); | 600 | ipoib_ib_dev_up(dev); |
610 | 601 | ||
611 | down(&priv->vlan_mutex); | 602 | mutex_lock(&priv->vlan_mutex); |
612 | 603 | ||
613 | /* Flush any child interfaces too */ | 604 | /* Flush any child interfaces too */ |
614 | list_for_each_entry(cpriv, &priv->child_intfs, list) | 605 | list_for_each_entry(cpriv, &priv->child_intfs, list) |
615 | ipoib_ib_dev_flush(&cpriv->dev); | 606 | ipoib_ib_dev_flush(&cpriv->dev); |
616 | 607 | ||
617 | up(&priv->vlan_mutex); | 608 | mutex_unlock(&priv->vlan_mutex); |
618 | } | 609 | } |
619 | 610 | ||
620 | void ipoib_ib_dev_cleanup(struct net_device *dev) | 611 | void ipoib_ib_dev_cleanup(struct net_device *dev) |
@@ -624,9 +615,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev) | |||
624 | ipoib_dbg(priv, "cleaning up ib_dev\n"); | 615 | ipoib_dbg(priv, "cleaning up ib_dev\n"); |
625 | 616 | ||
626 | ipoib_mcast_stop_thread(dev, 1); | 617 | ipoib_mcast_stop_thread(dev, 1); |
627 | 618 | ipoib_mcast_dev_flush(dev); | |
628 | /* Delete the broadcast address and the local address */ | ||
629 | ipoib_mcast_dev_down(dev); | ||
630 | 619 | ||
631 | ipoib_transport_dev_cleanup(dev); | 620 | ipoib_transport_dev_cleanup(dev); |
632 | } | 621 | } |
@@ -662,12 +651,12 @@ void ipoib_pkey_poll(void *dev_ptr) | |||
662 | if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) | 651 | if (test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) |
663 | ipoib_open(dev); | 652 | ipoib_open(dev); |
664 | else { | 653 | else { |
665 | down(&pkey_sem); | 654 | mutex_lock(&pkey_mutex); |
666 | if (!test_bit(IPOIB_PKEY_STOP, &priv->flags)) | 655 | if (!test_bit(IPOIB_PKEY_STOP, &priv->flags)) |
667 | queue_delayed_work(ipoib_workqueue, | 656 | queue_delayed_work(ipoib_workqueue, |
668 | &priv->pkey_task, | 657 | &priv->pkey_task, |
669 | HZ); | 658 | HZ); |
670 | up(&pkey_sem); | 659 | mutex_unlock(&pkey_mutex); |
671 | } | 660 | } |
672 | } | 661 | } |
673 | 662 | ||
@@ -681,12 +670,12 @@ int ipoib_pkey_dev_delay_open(struct net_device *dev) | |||
681 | 670 | ||
682 | /* P_Key value not assigned yet - start polling */ | 671 | /* P_Key value not assigned yet - start polling */ |
683 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { | 672 | if (!test_bit(IPOIB_PKEY_ASSIGNED, &priv->flags)) { |
684 | down(&pkey_sem); | 673 | mutex_lock(&pkey_mutex); |
685 | clear_bit(IPOIB_PKEY_STOP, &priv->flags); | 674 | clear_bit(IPOIB_PKEY_STOP, &priv->flags); |
686 | queue_delayed_work(ipoib_workqueue, | 675 | queue_delayed_work(ipoib_workqueue, |
687 | &priv->pkey_task, | 676 | &priv->pkey_task, |
688 | HZ); | 677 | HZ); |
689 | up(&pkey_sem); | 678 | mutex_unlock(&pkey_mutex); |
690 | return 1; | 679 | return 1; |
691 | } | 680 | } |
692 | 681 | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 780009c7eaa6..fd3f5c862a5d 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c | |||
@@ -105,7 +105,7 @@ int ipoib_open(struct net_device *dev) | |||
105 | struct ipoib_dev_priv *cpriv; | 105 | struct ipoib_dev_priv *cpriv; |
106 | 106 | ||
107 | /* Bring up any child interfaces too */ | 107 | /* Bring up any child interfaces too */ |
108 | down(&priv->vlan_mutex); | 108 | mutex_lock(&priv->vlan_mutex); |
109 | list_for_each_entry(cpriv, &priv->child_intfs, list) { | 109 | list_for_each_entry(cpriv, &priv->child_intfs, list) { |
110 | int flags; | 110 | int flags; |
111 | 111 | ||
@@ -115,7 +115,7 @@ int ipoib_open(struct net_device *dev) | |||
115 | 115 | ||
116 | dev_change_flags(cpriv->dev, flags | IFF_UP); | 116 | dev_change_flags(cpriv->dev, flags | IFF_UP); |
117 | } | 117 | } |
118 | up(&priv->vlan_mutex); | 118 | mutex_unlock(&priv->vlan_mutex); |
119 | } | 119 | } |
120 | 120 | ||
121 | netif_start_queue(dev); | 121 | netif_start_queue(dev); |
@@ -140,7 +140,7 @@ static int ipoib_stop(struct net_device *dev) | |||
140 | struct ipoib_dev_priv *cpriv; | 140 | struct ipoib_dev_priv *cpriv; |
141 | 141 | ||
142 | /* Bring down any child interfaces too */ | 142 | /* Bring down any child interfaces too */ |
143 | down(&priv->vlan_mutex); | 143 | mutex_lock(&priv->vlan_mutex); |
144 | list_for_each_entry(cpriv, &priv->child_intfs, list) { | 144 | list_for_each_entry(cpriv, &priv->child_intfs, list) { |
145 | int flags; | 145 | int flags; |
146 | 146 | ||
@@ -150,7 +150,7 @@ static int ipoib_stop(struct net_device *dev) | |||
150 | 150 | ||
151 | dev_change_flags(cpriv->dev, flags & ~IFF_UP); | 151 | dev_change_flags(cpriv->dev, flags & ~IFF_UP); |
152 | } | 152 | } |
153 | up(&priv->vlan_mutex); | 153 | mutex_unlock(&priv->vlan_mutex); |
154 | } | 154 | } |
155 | 155 | ||
156 | return 0; | 156 | return 0; |
@@ -892,8 +892,8 @@ static void ipoib_setup(struct net_device *dev) | |||
892 | spin_lock_init(&priv->lock); | 892 | spin_lock_init(&priv->lock); |
893 | spin_lock_init(&priv->tx_lock); | 893 | spin_lock_init(&priv->tx_lock); |
894 | 894 | ||
895 | init_MUTEX(&priv->mcast_mutex); | 895 | mutex_init(&priv->mcast_mutex); |
896 | init_MUTEX(&priv->vlan_mutex); | 896 | mutex_init(&priv->vlan_mutex); |
897 | 897 | ||
898 | INIT_LIST_HEAD(&priv->path_list); | 898 | INIT_LIST_HEAD(&priv->path_list); |
899 | INIT_LIST_HEAD(&priv->child_intfs); | 899 | INIT_LIST_HEAD(&priv->child_intfs); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index ed0c2ead8bc1..98039da0caf0 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c | |||
@@ -55,7 +55,7 @@ MODULE_PARM_DESC(mcast_debug_level, | |||
55 | "Enable multicast debug tracing if > 0"); | 55 | "Enable multicast debug tracing if > 0"); |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | static DECLARE_MUTEX(mcast_mutex); | 58 | static DEFINE_MUTEX(mcast_mutex); |
59 | 59 | ||
60 | /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ | 60 | /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ |
61 | struct ipoib_mcast { | 61 | struct ipoib_mcast { |
@@ -97,8 +97,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) | |||
97 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 97 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
98 | struct ipoib_neigh *neigh, *tmp; | 98 | struct ipoib_neigh *neigh, *tmp; |
99 | unsigned long flags; | 99 | unsigned long flags; |
100 | LIST_HEAD(ah_list); | ||
101 | struct ipoib_ah *ah, *tah; | ||
102 | 100 | ||
103 | ipoib_dbg_mcast(netdev_priv(dev), | 101 | ipoib_dbg_mcast(netdev_priv(dev), |
104 | "deleting multicast group " IPOIB_GID_FMT "\n", | 102 | "deleting multicast group " IPOIB_GID_FMT "\n", |
@@ -107,8 +105,14 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) | |||
107 | spin_lock_irqsave(&priv->lock, flags); | 105 | spin_lock_irqsave(&priv->lock, flags); |
108 | 106 | ||
109 | list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) { | 107 | list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) { |
108 | /* | ||
109 | * It's safe to call ipoib_put_ah() inside priv->lock | ||
110 | * here, because we know that mcast->ah will always | ||
111 | * hold one more reference, so ipoib_put_ah() will | ||
112 | * never do more than decrement the ref count. | ||
113 | */ | ||
110 | if (neigh->ah) | 114 | if (neigh->ah) |
111 | list_add_tail(&neigh->ah->list, &ah_list); | 115 | ipoib_put_ah(neigh->ah); |
112 | *to_ipoib_neigh(neigh->neighbour) = NULL; | 116 | *to_ipoib_neigh(neigh->neighbour) = NULL; |
113 | neigh->neighbour->ops->destructor = NULL; | 117 | neigh->neighbour->ops->destructor = NULL; |
114 | kfree(neigh); | 118 | kfree(neigh); |
@@ -116,9 +120,6 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast) | |||
116 | 120 | ||
117 | spin_unlock_irqrestore(&priv->lock, flags); | 121 | spin_unlock_irqrestore(&priv->lock, flags); |
118 | 122 | ||
119 | list_for_each_entry_safe(ah, tah, &ah_list, list) | ||
120 | ipoib_put_ah(ah); | ||
121 | |||
122 | if (mcast->ah) | 123 | if (mcast->ah) |
123 | ipoib_put_ah(mcast->ah); | 124 | ipoib_put_ah(mcast->ah); |
124 | 125 | ||
@@ -384,10 +385,10 @@ static void ipoib_mcast_join_complete(int status, | |||
384 | 385 | ||
385 | if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) { | 386 | if (!status && !ipoib_mcast_join_finish(mcast, mcmember)) { |
386 | mcast->backoff = 1; | 387 | mcast->backoff = 1; |
387 | down(&mcast_mutex); | 388 | mutex_lock(&mcast_mutex); |
388 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | 389 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) |
389 | queue_work(ipoib_workqueue, &priv->mcast_task); | 390 | queue_work(ipoib_workqueue, &priv->mcast_task); |
390 | up(&mcast_mutex); | 391 | mutex_unlock(&mcast_mutex); |
391 | complete(&mcast->done); | 392 | complete(&mcast->done); |
392 | return; | 393 | return; |
393 | } | 394 | } |
@@ -417,7 +418,7 @@ static void ipoib_mcast_join_complete(int status, | |||
417 | 418 | ||
418 | mcast->query = NULL; | 419 | mcast->query = NULL; |
419 | 420 | ||
420 | down(&mcast_mutex); | 421 | mutex_lock(&mcast_mutex); |
421 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) { | 422 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) { |
422 | if (status == -ETIMEDOUT) | 423 | if (status == -ETIMEDOUT) |
423 | queue_work(ipoib_workqueue, &priv->mcast_task); | 424 | queue_work(ipoib_workqueue, &priv->mcast_task); |
@@ -426,7 +427,7 @@ static void ipoib_mcast_join_complete(int status, | |||
426 | mcast->backoff * HZ); | 427 | mcast->backoff * HZ); |
427 | } else | 428 | } else |
428 | complete(&mcast->done); | 429 | complete(&mcast->done); |
429 | up(&mcast_mutex); | 430 | mutex_unlock(&mcast_mutex); |
430 | 431 | ||
431 | return; | 432 | return; |
432 | } | 433 | } |
@@ -481,12 +482,12 @@ static void ipoib_mcast_join(struct net_device *dev, struct ipoib_mcast *mcast, | |||
481 | if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) | 482 | if (mcast->backoff > IPOIB_MAX_BACKOFF_SECONDS) |
482 | mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; | 483 | mcast->backoff = IPOIB_MAX_BACKOFF_SECONDS; |
483 | 484 | ||
484 | down(&mcast_mutex); | 485 | mutex_lock(&mcast_mutex); |
485 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | 486 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) |
486 | queue_delayed_work(ipoib_workqueue, | 487 | queue_delayed_work(ipoib_workqueue, |
487 | &priv->mcast_task, | 488 | &priv->mcast_task, |
488 | mcast->backoff * HZ); | 489 | mcast->backoff * HZ); |
489 | up(&mcast_mutex); | 490 | mutex_unlock(&mcast_mutex); |
490 | } else | 491 | } else |
491 | mcast->query_id = ret; | 492 | mcast->query_id = ret; |
492 | } | 493 | } |
@@ -519,11 +520,11 @@ void ipoib_mcast_join_task(void *dev_ptr) | |||
519 | priv->broadcast = ipoib_mcast_alloc(dev, 1); | 520 | priv->broadcast = ipoib_mcast_alloc(dev, 1); |
520 | if (!priv->broadcast) { | 521 | if (!priv->broadcast) { |
521 | ipoib_warn(priv, "failed to allocate broadcast group\n"); | 522 | ipoib_warn(priv, "failed to allocate broadcast group\n"); |
522 | down(&mcast_mutex); | 523 | mutex_lock(&mcast_mutex); |
523 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) | 524 | if (test_bit(IPOIB_MCAST_RUN, &priv->flags)) |
524 | queue_delayed_work(ipoib_workqueue, | 525 | queue_delayed_work(ipoib_workqueue, |
525 | &priv->mcast_task, HZ); | 526 | &priv->mcast_task, HZ); |
526 | up(&mcast_mutex); | 527 | mutex_unlock(&mcast_mutex); |
527 | return; | 528 | return; |
528 | } | 529 | } |
529 | 530 | ||
@@ -579,10 +580,10 @@ int ipoib_mcast_start_thread(struct net_device *dev) | |||
579 | 580 | ||
580 | ipoib_dbg_mcast(priv, "starting multicast thread\n"); | 581 | ipoib_dbg_mcast(priv, "starting multicast thread\n"); |
581 | 582 | ||
582 | down(&mcast_mutex); | 583 | mutex_lock(&mcast_mutex); |
583 | if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags)) | 584 | if (!test_and_set_bit(IPOIB_MCAST_RUN, &priv->flags)) |
584 | queue_work(ipoib_workqueue, &priv->mcast_task); | 585 | queue_work(ipoib_workqueue, &priv->mcast_task); |
585 | up(&mcast_mutex); | 586 | mutex_unlock(&mcast_mutex); |
586 | 587 | ||
587 | return 0; | 588 | return 0; |
588 | } | 589 | } |
@@ -594,10 +595,10 @@ int ipoib_mcast_stop_thread(struct net_device *dev, int flush) | |||
594 | 595 | ||
595 | ipoib_dbg_mcast(priv, "stopping multicast thread\n"); | 596 | ipoib_dbg_mcast(priv, "stopping multicast thread\n"); |
596 | 597 | ||
597 | down(&mcast_mutex); | 598 | mutex_lock(&mcast_mutex); |
598 | clear_bit(IPOIB_MCAST_RUN, &priv->flags); | 599 | clear_bit(IPOIB_MCAST_RUN, &priv->flags); |
599 | cancel_delayed_work(&priv->mcast_task); | 600 | cancel_delayed_work(&priv->mcast_task); |
600 | up(&mcast_mutex); | 601 | mutex_unlock(&mcast_mutex); |
601 | 602 | ||
602 | if (flush) | 603 | if (flush) |
603 | flush_workqueue(ipoib_workqueue); | 604 | flush_workqueue(ipoib_workqueue); |
@@ -741,48 +742,23 @@ void ipoib_mcast_dev_flush(struct net_device *dev) | |||
741 | { | 742 | { |
742 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 743 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
743 | LIST_HEAD(remove_list); | 744 | LIST_HEAD(remove_list); |
744 | struct ipoib_mcast *mcast, *tmcast, *nmcast; | 745 | struct ipoib_mcast *mcast, *tmcast; |
745 | unsigned long flags; | 746 | unsigned long flags; |
746 | 747 | ||
747 | ipoib_dbg_mcast(priv, "flushing multicast list\n"); | 748 | ipoib_dbg_mcast(priv, "flushing multicast list\n"); |
748 | 749 | ||
749 | spin_lock_irqsave(&priv->lock, flags); | 750 | spin_lock_irqsave(&priv->lock, flags); |
750 | list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) { | ||
751 | nmcast = ipoib_mcast_alloc(dev, 0); | ||
752 | if (nmcast) { | ||
753 | nmcast->flags = | ||
754 | mcast->flags & (1 << IPOIB_MCAST_FLAG_SENDONLY); | ||
755 | 751 | ||
756 | nmcast->mcmember.mgid = mcast->mcmember.mgid; | 752 | list_for_each_entry_safe(mcast, tmcast, &priv->multicast_list, list) { |
757 | 753 | list_del(&mcast->list); | |
758 | /* Add the new group in before the to-be-destroyed group */ | 754 | rb_erase(&mcast->rb_node, &priv->multicast_tree); |
759 | list_add_tail(&nmcast->list, &mcast->list); | 755 | list_add_tail(&mcast->list, &remove_list); |
760 | list_del_init(&mcast->list); | ||
761 | |||
762 | rb_replace_node(&mcast->rb_node, &nmcast->rb_node, | ||
763 | &priv->multicast_tree); | ||
764 | |||
765 | list_add_tail(&mcast->list, &remove_list); | ||
766 | } else { | ||
767 | ipoib_warn(priv, "could not reallocate multicast group " | ||
768 | IPOIB_GID_FMT "\n", | ||
769 | IPOIB_GID_ARG(mcast->mcmember.mgid)); | ||
770 | } | ||
771 | } | 756 | } |
772 | 757 | ||
773 | if (priv->broadcast) { | 758 | if (priv->broadcast) { |
774 | nmcast = ipoib_mcast_alloc(dev, 0); | 759 | rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree); |
775 | if (nmcast) { | 760 | list_add_tail(&priv->broadcast->list, &remove_list); |
776 | nmcast->mcmember.mgid = priv->broadcast->mcmember.mgid; | 761 | priv->broadcast = NULL; |
777 | |||
778 | rb_replace_node(&priv->broadcast->rb_node, | ||
779 | &nmcast->rb_node, | ||
780 | &priv->multicast_tree); | ||
781 | |||
782 | list_add_tail(&priv->broadcast->list, &remove_list); | ||
783 | } | ||
784 | |||
785 | priv->broadcast = nmcast; | ||
786 | } | 762 | } |
787 | 763 | ||
788 | spin_unlock_irqrestore(&priv->lock, flags); | 764 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -793,24 +769,6 @@ void ipoib_mcast_dev_flush(struct net_device *dev) | |||
793 | } | 769 | } |
794 | } | 770 | } |
795 | 771 | ||
796 | void ipoib_mcast_dev_down(struct net_device *dev) | ||
797 | { | ||
798 | struct ipoib_dev_priv *priv = netdev_priv(dev); | ||
799 | unsigned long flags; | ||
800 | |||
801 | /* Delete broadcast since it will be recreated */ | ||
802 | if (priv->broadcast) { | ||
803 | ipoib_dbg_mcast(priv, "deleting broadcast group\n"); | ||
804 | |||
805 | spin_lock_irqsave(&priv->lock, flags); | ||
806 | rb_erase(&priv->broadcast->rb_node, &priv->multicast_tree); | ||
807 | spin_unlock_irqrestore(&priv->lock, flags); | ||
808 | ipoib_mcast_leave(dev, priv->broadcast); | ||
809 | ipoib_mcast_free(priv->broadcast); | ||
810 | priv->broadcast = NULL; | ||
811 | } | ||
812 | } | ||
813 | |||
814 | void ipoib_mcast_restart_task(void *dev_ptr) | 772 | void ipoib_mcast_restart_task(void *dev_ptr) |
815 | { | 773 | { |
816 | struct net_device *dev = dev_ptr; | 774 | struct net_device *dev = dev_ptr; |
@@ -824,7 +782,8 @@ void ipoib_mcast_restart_task(void *dev_ptr) | |||
824 | 782 | ||
825 | ipoib_mcast_stop_thread(dev, 0); | 783 | ipoib_mcast_stop_thread(dev, 0); |
826 | 784 | ||
827 | spin_lock_irqsave(&priv->lock, flags); | 785 | spin_lock_irqsave(&dev->xmit_lock, flags); |
786 | spin_lock(&priv->lock); | ||
828 | 787 | ||
829 | /* | 788 | /* |
830 | * Unfortunately, the networking core only gives us a list of all of | 789 | * Unfortunately, the networking core only gives us a list of all of |
@@ -896,7 +855,9 @@ void ipoib_mcast_restart_task(void *dev_ptr) | |||
896 | list_add_tail(&mcast->list, &remove_list); | 855 | list_add_tail(&mcast->list, &remove_list); |
897 | } | 856 | } |
898 | } | 857 | } |
899 | spin_unlock_irqrestore(&priv->lock, flags); | 858 | |
859 | spin_unlock(&priv->lock); | ||
860 | spin_unlock_irqrestore(&dev->xmit_lock, flags); | ||
900 | 861 | ||
901 | /* We have to cancel outside of the spinlock */ | 862 | /* We have to cancel outside of the spinlock */ |
902 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { | 863 | list_for_each_entry_safe(mcast, tmcast, &remove_list, list) { |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c index e829e10400e3..faaf10e5fc7b 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c | |||
@@ -65,9 +65,9 @@ int ipoib_mcast_attach(struct net_device *dev, u16 mlid, union ib_gid *mgid) | |||
65 | } | 65 | } |
66 | 66 | ||
67 | /* attach QP to multicast group */ | 67 | /* attach QP to multicast group */ |
68 | down(&priv->mcast_mutex); | 68 | mutex_lock(&priv->mcast_mutex); |
69 | ret = ib_attach_mcast(priv->qp, mgid, mlid); | 69 | ret = ib_attach_mcast(priv->qp, mgid, mlid); |
70 | up(&priv->mcast_mutex); | 70 | mutex_unlock(&priv->mcast_mutex); |
71 | if (ret) | 71 | if (ret) |
72 | ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret); | 72 | ipoib_warn(priv, "failed to attach to multicast group, ret = %d\n", ret); |
73 | 73 | ||
@@ -81,9 +81,9 @@ int ipoib_mcast_detach(struct net_device *dev, u16 mlid, union ib_gid *mgid) | |||
81 | struct ipoib_dev_priv *priv = netdev_priv(dev); | 81 | struct ipoib_dev_priv *priv = netdev_priv(dev); |
82 | int ret; | 82 | int ret; |
83 | 83 | ||
84 | down(&priv->mcast_mutex); | 84 | mutex_lock(&priv->mcast_mutex); |
85 | ret = ib_detach_mcast(priv->qp, mgid, mlid); | 85 | ret = ib_detach_mcast(priv->qp, mgid, mlid); |
86 | up(&priv->mcast_mutex); | 86 | mutex_unlock(&priv->mcast_mutex); |
87 | if (ret) | 87 | if (ret) |
88 | ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret); | 88 | ipoib_warn(priv, "ib_detach_mcast failed (result = %d)\n", ret); |
89 | 89 | ||
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c index d280b341a37f..4ca175553f9f 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c | |||
@@ -63,7 +63,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | |||
63 | 63 | ||
64 | ppriv = netdev_priv(pdev); | 64 | ppriv = netdev_priv(pdev); |
65 | 65 | ||
66 | down(&ppriv->vlan_mutex); | 66 | mutex_lock(&ppriv->vlan_mutex); |
67 | 67 | ||
68 | /* | 68 | /* |
69 | * First ensure this isn't a duplicate. We check the parent device and | 69 | * First ensure this isn't a duplicate. We check the parent device and |
@@ -124,7 +124,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey) | |||
124 | 124 | ||
125 | list_add_tail(&priv->list, &ppriv->child_intfs); | 125 | list_add_tail(&priv->list, &ppriv->child_intfs); |
126 | 126 | ||
127 | up(&ppriv->vlan_mutex); | 127 | mutex_unlock(&ppriv->vlan_mutex); |
128 | 128 | ||
129 | return 0; | 129 | return 0; |
130 | 130 | ||
@@ -139,7 +139,7 @@ device_init_failed: | |||
139 | free_netdev(priv->dev); | 139 | free_netdev(priv->dev); |
140 | 140 | ||
141 | err: | 141 | err: |
142 | up(&ppriv->vlan_mutex); | 142 | mutex_unlock(&ppriv->vlan_mutex); |
143 | return result; | 143 | return result; |
144 | } | 144 | } |
145 | 145 | ||
@@ -153,7 +153,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) | |||
153 | 153 | ||
154 | ppriv = netdev_priv(pdev); | 154 | ppriv = netdev_priv(pdev); |
155 | 155 | ||
156 | down(&ppriv->vlan_mutex); | 156 | mutex_lock(&ppriv->vlan_mutex); |
157 | list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { | 157 | list_for_each_entry_safe(priv, tpriv, &ppriv->child_intfs, list) { |
158 | if (priv->pkey == pkey) { | 158 | if (priv->pkey == pkey) { |
159 | unregister_netdev(priv->dev); | 159 | unregister_netdev(priv->dev); |
@@ -167,7 +167,7 @@ int ipoib_vlan_delete(struct net_device *pdev, unsigned short pkey) | |||
167 | break; | 167 | break; |
168 | } | 168 | } |
169 | } | 169 | } |
170 | up(&ppriv->vlan_mutex); | 170 | mutex_unlock(&ppriv->vlan_mutex); |
171 | 171 | ||
172 | return ret; | 172 | return ret; |
173 | } | 173 | } |
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index dd488d3cffa9..31207e664148 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c | |||
@@ -1516,8 +1516,7 @@ static ssize_t show_port(struct class_device *class_dev, char *buf) | |||
1516 | 1516 | ||
1517 | static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); | 1517 | static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL); |
1518 | 1518 | ||
1519 | static struct srp_host *srp_add_port(struct ib_device *device, | 1519 | static struct srp_host *srp_add_port(struct ib_device *device, u8 port) |
1520 | __be64 node_guid, u8 port) | ||
1521 | { | 1520 | { |
1522 | struct srp_host *host; | 1521 | struct srp_host *host; |
1523 | 1522 | ||
@@ -1532,7 +1531,7 @@ static struct srp_host *srp_add_port(struct ib_device *device, | |||
1532 | host->port = port; | 1531 | host->port = port; |
1533 | 1532 | ||
1534 | host->initiator_port_id[7] = port; | 1533 | host->initiator_port_id[7] = port; |
1535 | memcpy(host->initiator_port_id + 8, &node_guid, 8); | 1534 | memcpy(host->initiator_port_id + 8, &device->node_guid, 8); |
1536 | 1535 | ||
1537 | host->pd = ib_alloc_pd(device); | 1536 | host->pd = ib_alloc_pd(device); |
1538 | if (IS_ERR(host->pd)) | 1537 | if (IS_ERR(host->pd)) |
@@ -1580,22 +1579,11 @@ static void srp_add_one(struct ib_device *device) | |||
1580 | { | 1579 | { |
1581 | struct list_head *dev_list; | 1580 | struct list_head *dev_list; |
1582 | struct srp_host *host; | 1581 | struct srp_host *host; |
1583 | struct ib_device_attr *dev_attr; | ||
1584 | int s, e, p; | 1582 | int s, e, p; |
1585 | 1583 | ||
1586 | dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL); | ||
1587 | if (!dev_attr) | ||
1588 | return; | ||
1589 | |||
1590 | if (ib_query_device(device, dev_attr)) { | ||
1591 | printk(KERN_WARNING PFX "Couldn't query node GUID for %s.\n", | ||
1592 | device->name); | ||
1593 | goto out; | ||
1594 | } | ||
1595 | |||
1596 | dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); | 1584 | dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL); |
1597 | if (!dev_list) | 1585 | if (!dev_list) |
1598 | goto out; | 1586 | return; |
1599 | 1587 | ||
1600 | INIT_LIST_HEAD(dev_list); | 1588 | INIT_LIST_HEAD(dev_list); |
1601 | 1589 | ||
@@ -1608,15 +1596,12 @@ static void srp_add_one(struct ib_device *device) | |||
1608 | } | 1596 | } |
1609 | 1597 | ||
1610 | for (p = s; p <= e; ++p) { | 1598 | for (p = s; p <= e; ++p) { |
1611 | host = srp_add_port(device, dev_attr->node_guid, p); | 1599 | host = srp_add_port(device, p); |
1612 | if (host) | 1600 | if (host) |
1613 | list_add_tail(&host->list, dev_list); | 1601 | list_add_tail(&host->list, dev_list); |
1614 | } | 1602 | } |
1615 | 1603 | ||
1616 | ib_set_client_data(device, &srp_client, dev_list); | 1604 | ib_set_client_data(device, &srp_client, dev_list); |
1617 | |||
1618 | out: | ||
1619 | kfree(dev_attr); | ||
1620 | } | 1605 | } |
1621 | 1606 | ||
1622 | static void srp_remove_one(struct ib_device *device) | 1607 | static void srp_remove_one(struct ib_device *device) |
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 362b33556b1a..745979f33dc2 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
@@ -159,7 +159,7 @@ struct input_event_compat { | |||
159 | #ifdef CONFIG_X86_64 | 159 | #ifdef CONFIG_X86_64 |
160 | # define COMPAT_TEST is_compat_task() | 160 | # define COMPAT_TEST is_compat_task() |
161 | #elif defined(CONFIG_IA64) | 161 | #elif defined(CONFIG_IA64) |
162 | # define COMPAT_TEST IS_IA32_PROCESS(ia64_task_regs(current)) | 162 | # define COMPAT_TEST IS_IA32_PROCESS(task_pt_regs(current)) |
163 | #elif defined(CONFIG_S390) | 163 | #elif defined(CONFIG_S390) |
164 | # define COMPAT_TEST test_thread_flag(TIF_31BIT) | 164 | # define COMPAT_TEST test_thread_flag(TIF_31BIT) |
165 | #elif defined(CONFIG_MIPS) | 165 | #elif defined(CONFIG_MIPS) |
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index caac6d63d46f..b765a155c008 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
@@ -50,9 +50,7 @@ static DECLARE_MUTEX(gameport_sem); | |||
50 | 50 | ||
51 | static LIST_HEAD(gameport_list); | 51 | static LIST_HEAD(gameport_list); |
52 | 52 | ||
53 | static struct bus_type gameport_bus = { | 53 | static struct bus_type gameport_bus; |
54 | .name = "gameport", | ||
55 | }; | ||
56 | 54 | ||
57 | static void gameport_add_port(struct gameport *gameport); | 55 | static void gameport_add_port(struct gameport *gameport); |
58 | static void gameport_destroy_port(struct gameport *gameport); | 56 | static void gameport_destroy_port(struct gameport *gameport); |
@@ -703,11 +701,15 @@ static int gameport_driver_remove(struct device *dev) | |||
703 | return 0; | 701 | return 0; |
704 | } | 702 | } |
705 | 703 | ||
704 | static struct bus_type gameport_bus = { | ||
705 | .name = "gameport", | ||
706 | .probe = gameport_driver_probe, | ||
707 | .remove = gameport_driver_remove, | ||
708 | }; | ||
709 | |||
706 | void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) | 710 | void __gameport_register_driver(struct gameport_driver *drv, struct module *owner) |
707 | { | 711 | { |
708 | drv->driver.bus = &gameport_bus; | 712 | drv->driver.bus = &gameport_bus; |
709 | drv->driver.probe = gameport_driver_probe; | ||
710 | drv->driver.remove = gameport_driver_remove; | ||
711 | gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER); | 713 | gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER); |
712 | } | 714 | } |
713 | 715 | ||
diff --git a/drivers/input/input.c b/drivers/input/input.c index fe33ff334e27..4fe3da3c667a 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -528,40 +528,56 @@ INPUT_DEV_STRING_ATTR_SHOW(name); | |||
528 | INPUT_DEV_STRING_ATTR_SHOW(phys); | 528 | INPUT_DEV_STRING_ATTR_SHOW(phys); |
529 | INPUT_DEV_STRING_ATTR_SHOW(uniq); | 529 | INPUT_DEV_STRING_ATTR_SHOW(uniq); |
530 | 530 | ||
531 | static int print_modalias_bits(char *buf, char prefix, unsigned long *arr, | 531 | static int print_modalias_bits(char *buf, int size, char prefix, unsigned long *arr, |
532 | unsigned int min, unsigned int max) | 532 | unsigned int min, unsigned int max) |
533 | { | 533 | { |
534 | int len, i; | 534 | int len, i; |
535 | 535 | ||
536 | len = sprintf(buf, "%c", prefix); | 536 | len = snprintf(buf, size, "%c", prefix); |
537 | for (i = min; i < max; i++) | 537 | for (i = min; i < max; i++) |
538 | if (arr[LONG(i)] & BIT(i)) | 538 | if (arr[LONG(i)] & BIT(i)) |
539 | len += sprintf(buf+len, "%X,", i); | 539 | len += snprintf(buf + len, size - len, "%X,", i); |
540 | return len; | 540 | return len; |
541 | } | 541 | } |
542 | 542 | ||
543 | static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) | 543 | static int print_modalias(char *buf, int size, struct input_dev *id) |
544 | { | 544 | { |
545 | struct input_dev *id = to_input_dev(dev); | 545 | int len; |
546 | ssize_t len = 0; | ||
547 | 546 | ||
548 | len += sprintf(buf+len, "input:b%04Xv%04Xp%04Xe%04X-", | 547 | len = snprintf(buf, size, "input:b%04Xv%04Xp%04Xe%04X-", |
549 | id->id.bustype, | 548 | id->id.bustype, |
550 | id->id.vendor, | 549 | id->id.vendor, |
551 | id->id.product, | 550 | id->id.product, |
552 | id->id.version); | 551 | id->id.version); |
553 | 552 | ||
554 | len += print_modalias_bits(buf+len, 'e', id->evbit, 0, EV_MAX); | 553 | len += print_modalias_bits(buf + len, size - len, 'e', id->evbit, |
555 | len += print_modalias_bits(buf+len, 'k', id->keybit, | 554 | 0, EV_MAX); |
555 | len += print_modalias_bits(buf + len, size - len, 'k', id->keybit, | ||
556 | KEY_MIN_INTERESTING, KEY_MAX); | 556 | KEY_MIN_INTERESTING, KEY_MAX); |
557 | len += print_modalias_bits(buf+len, 'r', id->relbit, 0, REL_MAX); | 557 | len += print_modalias_bits(buf + len, size - len, 'r', id->relbit, |
558 | len += print_modalias_bits(buf+len, 'a', id->absbit, 0, ABS_MAX); | 558 | 0, REL_MAX); |
559 | len += print_modalias_bits(buf+len, 'm', id->mscbit, 0, MSC_MAX); | 559 | len += print_modalias_bits(buf + len, size - len, 'a', id->absbit, |
560 | len += print_modalias_bits(buf+len, 'l', id->ledbit, 0, LED_MAX); | 560 | 0, ABS_MAX); |
561 | len += print_modalias_bits(buf+len, 's', id->sndbit, 0, SND_MAX); | 561 | len += print_modalias_bits(buf + len, size - len, 'm', id->mscbit, |
562 | len += print_modalias_bits(buf+len, 'f', id->ffbit, 0, FF_MAX); | 562 | 0, MSC_MAX); |
563 | len += print_modalias_bits(buf+len, 'w', id->swbit, 0, SW_MAX); | 563 | len += print_modalias_bits(buf + len, size - len, 'l', id->ledbit, |
564 | len += sprintf(buf+len, "\n"); | 564 | 0, LED_MAX); |
565 | len += print_modalias_bits(buf + len, size - len, 's', id->sndbit, | ||
566 | 0, SND_MAX); | ||
567 | len += print_modalias_bits(buf + len, size - len, 'f', id->ffbit, | ||
568 | 0, FF_MAX); | ||
569 | len += print_modalias_bits(buf + len, size - len, 'w', id->swbit, | ||
570 | 0, SW_MAX); | ||
571 | return len; | ||
572 | } | ||
573 | |||
574 | static ssize_t input_dev_show_modalias(struct class_device *dev, char *buf) | ||
575 | { | ||
576 | struct input_dev *id = to_input_dev(dev); | ||
577 | ssize_t len; | ||
578 | |||
579 | len = print_modalias(buf, PAGE_SIZE, id); | ||
580 | len += snprintf(buf + len, PAGE_SIZE-len, "\n"); | ||
565 | return len; | 581 | return len; |
566 | } | 582 | } |
567 | static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); | 583 | static CLASS_DEVICE_ATTR(modalias, S_IRUGO, input_dev_show_modalias, NULL); |
@@ -728,8 +744,11 @@ static int input_dev_uevent(struct class_device *cdev, char **envp, | |||
728 | if (test_bit(EV_SW, dev->evbit)) | 744 | if (test_bit(EV_SW, dev->evbit)) |
729 | INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX); | 745 | INPUT_ADD_HOTPLUG_BM_VAR("SW=", dev->swbit, SW_MAX); |
730 | 746 | ||
731 | envp[i] = NULL; | 747 | envp[i++] = buffer + len; |
748 | len += snprintf(buffer + len, buffer_size - len, "MODALIAS="); | ||
749 | len += print_modalias(buffer + len, buffer_size - len, dev) + 1; | ||
732 | 750 | ||
751 | envp[i] = NULL; | ||
733 | return 0; | 752 | return 0; |
734 | } | 753 | } |
735 | 754 | ||
diff --git a/drivers/input/joystick/amijoy.c b/drivers/input/joystick/amijoy.c index 8558a99f6635..ec55a29fc861 100644 --- a/drivers/input/joystick/amijoy.c +++ b/drivers/input/joystick/amijoy.c | |||
@@ -64,8 +64,8 @@ static irqreturn_t amijoy_interrupt(int irq, void *dummy, struct pt_regs *fp) | |||
64 | if (amijoy[i]) { | 64 | if (amijoy[i]) { |
65 | 65 | ||
66 | switch (i) { | 66 | switch (i) { |
67 | case 0: data = ~custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break; | 67 | case 0: data = ~amiga_custom.joy0dat; button = (~ciaa.pra >> 6) & 1; break; |
68 | case 1: data = ~custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break; | 68 | case 1: data = ~amiga_custom.joy1dat; button = (~ciaa.pra >> 7) & 1; break; |
69 | } | 69 | } |
70 | 70 | ||
71 | input_regs(amijoy_dev[i], fp); | 71 | input_regs(amijoy_dev[i], fp); |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 24474335dfd1..2141501e9f2e 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -348,6 +348,40 @@ static int alps_tap_mode(struct psmouse *psmouse, int enable) | |||
348 | return 0; | 348 | return 0; |
349 | } | 349 | } |
350 | 350 | ||
351 | /* | ||
352 | * alps_poll() - poll the touchpad for current motion packet. | ||
353 | * Used in resync. | ||
354 | */ | ||
355 | static int alps_poll(struct psmouse *psmouse) | ||
356 | { | ||
357 | struct alps_data *priv = psmouse->private; | ||
358 | unsigned char buf[6]; | ||
359 | int poll_failed; | ||
360 | |||
361 | if (priv->i->flags & ALPS_PASS) | ||
362 | alps_passthrough_mode(psmouse, 1); | ||
363 | |||
364 | poll_failed = ps2_command(&psmouse->ps2dev, buf, | ||
365 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)) < 0; | ||
366 | |||
367 | if (priv->i->flags & ALPS_PASS) | ||
368 | alps_passthrough_mode(psmouse, 0); | ||
369 | |||
370 | if (poll_failed || (buf[0] & priv->i->mask0) != priv->i->byte0) | ||
371 | return -1; | ||
372 | |||
373 | if ((psmouse->badbyte & 0xc8) == 0x08) { | ||
374 | /* | ||
375 | * Poll the track stick ... | ||
376 | */ | ||
377 | if (ps2_command(&psmouse->ps2dev, buf, PSMOUSE_CMD_POLL | (3 << 8))) | ||
378 | return -1; | ||
379 | } | ||
380 | |||
381 | memcpy(psmouse->packet, buf, sizeof(buf)); | ||
382 | return 0; | ||
383 | } | ||
384 | |||
351 | static int alps_reconnect(struct psmouse *psmouse) | 385 | static int alps_reconnect(struct psmouse *psmouse) |
352 | { | 386 | { |
353 | struct alps_data *priv = psmouse->private; | 387 | struct alps_data *priv = psmouse->private; |
@@ -451,10 +485,14 @@ int alps_init(struct psmouse *psmouse) | |||
451 | input_register_device(priv->dev2); | 485 | input_register_device(priv->dev2); |
452 | 486 | ||
453 | psmouse->protocol_handler = alps_process_byte; | 487 | psmouse->protocol_handler = alps_process_byte; |
488 | psmouse->poll = alps_poll; | ||
454 | psmouse->disconnect = alps_disconnect; | 489 | psmouse->disconnect = alps_disconnect; |
455 | psmouse->reconnect = alps_reconnect; | 490 | psmouse->reconnect = alps_reconnect; |
456 | psmouse->pktsize = 6; | 491 | psmouse->pktsize = 6; |
457 | 492 | ||
493 | /* We are having trouble resyncing ALPS touchpads so disable it for now */ | ||
494 | psmouse->resync_time = 0; | ||
495 | |||
458 | return 0; | 496 | return 0; |
459 | 497 | ||
460 | init_fail: | 498 | init_fail: |
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c index d13d4c8fe3c5..c8b2cc9f184c 100644 --- a/drivers/input/mouse/amimouse.c +++ b/drivers/input/mouse/amimouse.c | |||
@@ -41,7 +41,7 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp) | |||
41 | unsigned short joy0dat, potgor; | 41 | unsigned short joy0dat, potgor; |
42 | int nx, ny, dx, dy; | 42 | int nx, ny, dx, dy; |
43 | 43 | ||
44 | joy0dat = custom.joy0dat; | 44 | joy0dat = amiga_custom.joy0dat; |
45 | 45 | ||
46 | nx = joy0dat & 0xff; | 46 | nx = joy0dat & 0xff; |
47 | ny = joy0dat >> 8; | 47 | ny = joy0dat >> 8; |
@@ -57,7 +57,7 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp) | |||
57 | amimouse_lastx = nx; | 57 | amimouse_lastx = nx; |
58 | amimouse_lasty = ny; | 58 | amimouse_lasty = ny; |
59 | 59 | ||
60 | potgor = custom.potgor; | 60 | potgor = amiga_custom.potgor; |
61 | 61 | ||
62 | input_regs(amimouse_dev, fp); | 62 | input_regs(amimouse_dev, fp); |
63 | 63 | ||
@@ -77,7 +77,7 @@ static int amimouse_open(struct input_dev *dev) | |||
77 | { | 77 | { |
78 | unsigned short joy0dat; | 78 | unsigned short joy0dat; |
79 | 79 | ||
80 | joy0dat = custom.joy0dat; | 80 | joy0dat = amiga_custom.joy0dat; |
81 | 81 | ||
82 | amimouse_lastx = joy0dat & 0xff; | 82 | amimouse_lastx = joy0dat & 0xff; |
83 | amimouse_lasty = joy0dat >> 8; | 83 | amimouse_lasty = joy0dat >> 8; |
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c index 025a71de5404..c88520d3d13c 100644 --- a/drivers/input/mouse/logips2pp.c +++ b/drivers/input/mouse/logips2pp.c | |||
@@ -117,7 +117,7 @@ static int ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned cha | |||
117 | if (psmouse_sliced_command(psmouse, command)) | 117 | if (psmouse_sliced_command(psmouse, command)) |
118 | return -1; | 118 | return -1; |
119 | 119 | ||
120 | if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL)) | 120 | if (ps2_command(&psmouse->ps2dev, param, PSMOUSE_CMD_POLL | 0x0300)) |
121 | return -1; | 121 | return -1; |
122 | 122 | ||
123 | return 0; | 123 | return 0; |
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index 4d5ecc04c5b6..7665fd9ce559 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
@@ -54,10 +54,14 @@ static unsigned int psmouse_smartscroll = 1; | |||
54 | module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); | 54 | module_param_named(smartscroll, psmouse_smartscroll, bool, 0644); |
55 | MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); | 55 | MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled."); |
56 | 56 | ||
57 | static unsigned int psmouse_resetafter; | 57 | static unsigned int psmouse_resetafter = 5; |
58 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); | 58 | module_param_named(resetafter, psmouse_resetafter, uint, 0644); |
59 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); | 59 | MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never)."); |
60 | 60 | ||
61 | static unsigned int psmouse_resync_time = 5; | ||
62 | module_param_named(resync_time, psmouse_resync_time, uint, 0644); | ||
63 | MODULE_PARM_DESC(resync_time, "How long can mouse stay idle before forcing resync (in seconds, 0 = never)."); | ||
64 | |||
61 | PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, | 65 | PSMOUSE_DEFINE_ATTR(protocol, S_IWUSR | S_IRUGO, |
62 | NULL, | 66 | NULL, |
63 | psmouse_attr_show_protocol, psmouse_attr_set_protocol); | 67 | psmouse_attr_show_protocol, psmouse_attr_set_protocol); |
@@ -70,12 +74,16 @@ PSMOUSE_DEFINE_ATTR(resolution, S_IWUSR | S_IRUGO, | |||
70 | PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, | 74 | PSMOUSE_DEFINE_ATTR(resetafter, S_IWUSR | S_IRUGO, |
71 | (void *) offsetof(struct psmouse, resetafter), | 75 | (void *) offsetof(struct psmouse, resetafter), |
72 | psmouse_show_int_attr, psmouse_set_int_attr); | 76 | psmouse_show_int_attr, psmouse_set_int_attr); |
77 | PSMOUSE_DEFINE_ATTR(resync_time, S_IWUSR | S_IRUGO, | ||
78 | (void *) offsetof(struct psmouse, resync_time), | ||
79 | psmouse_show_int_attr, psmouse_set_int_attr); | ||
73 | 80 | ||
74 | static struct attribute *psmouse_attributes[] = { | 81 | static struct attribute *psmouse_attributes[] = { |
75 | &psmouse_attr_protocol.dattr.attr, | 82 | &psmouse_attr_protocol.dattr.attr, |
76 | &psmouse_attr_rate.dattr.attr, | 83 | &psmouse_attr_rate.dattr.attr, |
77 | &psmouse_attr_resolution.dattr.attr, | 84 | &psmouse_attr_resolution.dattr.attr, |
78 | &psmouse_attr_resetafter.dattr.attr, | 85 | &psmouse_attr_resetafter.dattr.attr, |
86 | &psmouse_attr_resync_time.dattr.attr, | ||
79 | NULL | 87 | NULL |
80 | }; | 88 | }; |
81 | 89 | ||
@@ -98,6 +106,8 @@ __obsolete_setup("psmouse_rate="); | |||
98 | */ | 106 | */ |
99 | static DECLARE_MUTEX(psmouse_sem); | 107 | static DECLARE_MUTEX(psmouse_sem); |
100 | 108 | ||
109 | static struct workqueue_struct *kpsmoused_wq; | ||
110 | |||
101 | struct psmouse_protocol { | 111 | struct psmouse_protocol { |
102 | enum psmouse_type type; | 112 | enum psmouse_type type; |
103 | char *name; | 113 | char *name; |
@@ -178,15 +188,79 @@ static psmouse_ret_t psmouse_process_byte(struct psmouse *psmouse, struct pt_reg | |||
178 | } | 188 | } |
179 | 189 | ||
180 | /* | 190 | /* |
181 | * psmouse_interrupt() handles incoming characters, either gathering them into | 191 | * __psmouse_set_state() sets new psmouse state and resets all flags. |
182 | * packets or passing them to the command routine as command output. | 192 | */ |
193 | |||
194 | static inline void __psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | ||
195 | { | ||
196 | psmouse->state = new_state; | ||
197 | psmouse->pktcnt = psmouse->out_of_sync = 0; | ||
198 | psmouse->ps2dev.flags = 0; | ||
199 | psmouse->last = jiffies; | ||
200 | } | ||
201 | |||
202 | |||
203 | /* | ||
204 | * psmouse_set_state() sets new psmouse state and resets all flags and | ||
205 | * counters while holding serio lock so fighting with interrupt handler | ||
206 | * is not a concern. | ||
207 | */ | ||
208 | |||
209 | static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | ||
210 | { | ||
211 | serio_pause_rx(psmouse->ps2dev.serio); | ||
212 | __psmouse_set_state(psmouse, new_state); | ||
213 | serio_continue_rx(psmouse->ps2dev.serio); | ||
214 | } | ||
215 | |||
216 | /* | ||
217 | * psmouse_handle_byte() processes one byte of the input data stream | ||
218 | * by calling corresponding protocol handler. | ||
219 | */ | ||
220 | |||
221 | static int psmouse_handle_byte(struct psmouse *psmouse, struct pt_regs *regs) | ||
222 | { | ||
223 | psmouse_ret_t rc = psmouse->protocol_handler(psmouse, regs); | ||
224 | |||
225 | switch (rc) { | ||
226 | case PSMOUSE_BAD_DATA: | ||
227 | if (psmouse->state == PSMOUSE_ACTIVATED) { | ||
228 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | ||
229 | psmouse->name, psmouse->phys, psmouse->pktcnt); | ||
230 | if (++psmouse->out_of_sync == psmouse->resetafter) { | ||
231 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
232 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | ||
233 | serio_reconnect(psmouse->ps2dev.serio); | ||
234 | return -1; | ||
235 | } | ||
236 | } | ||
237 | psmouse->pktcnt = 0; | ||
238 | break; | ||
239 | |||
240 | case PSMOUSE_FULL_PACKET: | ||
241 | psmouse->pktcnt = 0; | ||
242 | if (psmouse->out_of_sync) { | ||
243 | psmouse->out_of_sync = 0; | ||
244 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | ||
245 | psmouse->name, psmouse->phys); | ||
246 | } | ||
247 | break; | ||
248 | |||
249 | case PSMOUSE_GOOD_DATA: | ||
250 | break; | ||
251 | } | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * psmouse_interrupt() handles incoming characters, either passing them | ||
257 | * for normal processing or gathering them as command response. | ||
183 | */ | 258 | */ |
184 | 259 | ||
185 | static irqreturn_t psmouse_interrupt(struct serio *serio, | 260 | static irqreturn_t psmouse_interrupt(struct serio *serio, |
186 | unsigned char data, unsigned int flags, struct pt_regs *regs) | 261 | unsigned char data, unsigned int flags, struct pt_regs *regs) |
187 | { | 262 | { |
188 | struct psmouse *psmouse = serio_get_drvdata(serio); | 263 | struct psmouse *psmouse = serio_get_drvdata(serio); |
189 | psmouse_ret_t rc; | ||
190 | 264 | ||
191 | if (psmouse->state == PSMOUSE_IGNORE) | 265 | if (psmouse->state == PSMOUSE_IGNORE) |
192 | goto out; | 266 | goto out; |
@@ -208,67 +282,58 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
208 | if (ps2_handle_response(&psmouse->ps2dev, data)) | 282 | if (ps2_handle_response(&psmouse->ps2dev, data)) |
209 | goto out; | 283 | goto out; |
210 | 284 | ||
211 | if (psmouse->state == PSMOUSE_INITIALIZING) | 285 | if (psmouse->state <= PSMOUSE_RESYNCING) |
212 | goto out; | 286 | goto out; |
213 | 287 | ||
214 | if (psmouse->state == PSMOUSE_ACTIVATED && | 288 | if (psmouse->state == PSMOUSE_ACTIVATED && |
215 | psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { | 289 | psmouse->pktcnt && time_after(jiffies, psmouse->last + HZ/2)) { |
216 | printk(KERN_WARNING "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", | 290 | printk(KERN_INFO "psmouse.c: %s at %s lost synchronization, throwing %d bytes away.\n", |
217 | psmouse->name, psmouse->phys, psmouse->pktcnt); | 291 | psmouse->name, psmouse->phys, psmouse->pktcnt); |
218 | psmouse->pktcnt = 0; | 292 | psmouse->badbyte = psmouse->packet[0]; |
293 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | ||
294 | queue_work(kpsmoused_wq, &psmouse->resync_work); | ||
295 | goto out; | ||
219 | } | 296 | } |
220 | 297 | ||
221 | psmouse->last = jiffies; | ||
222 | psmouse->packet[psmouse->pktcnt++] = data; | 298 | psmouse->packet[psmouse->pktcnt++] = data; |
223 | 299 | /* | |
224 | if (psmouse->packet[0] == PSMOUSE_RET_BAT) { | 300 | * Check if this is a new device announcement (0xAA 0x00) |
301 | */ | ||
302 | if (unlikely(psmouse->packet[0] == PSMOUSE_RET_BAT && psmouse->pktcnt <= 2)) { | ||
225 | if (psmouse->pktcnt == 1) | 303 | if (psmouse->pktcnt == 1) |
226 | goto out; | 304 | goto out; |
227 | 305 | ||
228 | if (psmouse->pktcnt == 2) { | 306 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { |
229 | if (psmouse->packet[1] == PSMOUSE_RET_ID) { | 307 | __psmouse_set_state(psmouse, PSMOUSE_IGNORE); |
230 | psmouse->state = PSMOUSE_IGNORE; | 308 | serio_reconnect(serio); |
231 | serio_reconnect(serio); | 309 | goto out; |
232 | goto out; | ||
233 | } | ||
234 | if (psmouse->type == PSMOUSE_SYNAPTICS) { | ||
235 | /* neither 0xAA nor 0x00 are valid first bytes | ||
236 | * for a packet in absolute mode | ||
237 | */ | ||
238 | psmouse->pktcnt = 0; | ||
239 | goto out; | ||
240 | } | ||
241 | } | 310 | } |
242 | } | 311 | /* |
243 | 312 | * Not a new device, try processing first byte normally | |
244 | rc = psmouse->protocol_handler(psmouse, regs); | 313 | */ |
314 | psmouse->pktcnt = 1; | ||
315 | if (psmouse_handle_byte(psmouse, regs)) | ||
316 | goto out; | ||
245 | 317 | ||
246 | switch (rc) { | 318 | psmouse->packet[psmouse->pktcnt++] = data; |
247 | case PSMOUSE_BAD_DATA: | 319 | } |
248 | printk(KERN_WARNING "psmouse.c: %s at %s lost sync at byte %d\n", | ||
249 | psmouse->name, psmouse->phys, psmouse->pktcnt); | ||
250 | psmouse->pktcnt = 0; | ||
251 | 320 | ||
252 | if (++psmouse->out_of_sync == psmouse->resetafter) { | 321 | /* |
253 | psmouse->state = PSMOUSE_IGNORE; | 322 | * See if we need to force resync because mouse was idle for too long |
254 | printk(KERN_NOTICE "psmouse.c: issuing reconnect request\n"); | 323 | */ |
255 | serio_reconnect(psmouse->ps2dev.serio); | 324 | if (psmouse->state == PSMOUSE_ACTIVATED && |
256 | } | 325 | psmouse->pktcnt == 1 && psmouse->resync_time && |
257 | break; | 326 | time_after(jiffies, psmouse->last + psmouse->resync_time * HZ)) { |
327 | psmouse->badbyte = psmouse->packet[0]; | ||
328 | __psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | ||
329 | queue_work(kpsmoused_wq, &psmouse->resync_work); | ||
330 | goto out; | ||
331 | } | ||
258 | 332 | ||
259 | case PSMOUSE_FULL_PACKET: | 333 | psmouse->last = jiffies; |
260 | psmouse->pktcnt = 0; | 334 | psmouse_handle_byte(psmouse, regs); |
261 | if (psmouse->out_of_sync) { | ||
262 | psmouse->out_of_sync = 0; | ||
263 | printk(KERN_NOTICE "psmouse.c: %s at %s - driver resynched.\n", | ||
264 | psmouse->name, psmouse->phys); | ||
265 | } | ||
266 | break; | ||
267 | 335 | ||
268 | case PSMOUSE_GOOD_DATA: | 336 | out: |
269 | break; | ||
270 | } | ||
271 | out: | ||
272 | return IRQ_HANDLED; | 337 | return IRQ_HANDLED; |
273 | } | 338 | } |
274 | 339 | ||
@@ -752,21 +817,6 @@ static void psmouse_initialize(struct psmouse *psmouse) | |||
752 | } | 817 | } |
753 | 818 | ||
754 | /* | 819 | /* |
755 | * psmouse_set_state() sets new psmouse state and resets all flags and | ||
756 | * counters while holding serio lock so fighting with interrupt handler | ||
757 | * is not a concern. | ||
758 | */ | ||
759 | |||
760 | static void psmouse_set_state(struct psmouse *psmouse, enum psmouse_state new_state) | ||
761 | { | ||
762 | serio_pause_rx(psmouse->ps2dev.serio); | ||
763 | psmouse->state = new_state; | ||
764 | psmouse->pktcnt = psmouse->out_of_sync = 0; | ||
765 | psmouse->ps2dev.flags = 0; | ||
766 | serio_continue_rx(psmouse->ps2dev.serio); | ||
767 | } | ||
768 | |||
769 | /* | ||
770 | * psmouse_activate() enables the mouse so that we get motion reports from it. | 820 | * psmouse_activate() enables the mouse so that we get motion reports from it. |
771 | */ | 821 | */ |
772 | 822 | ||
@@ -794,6 +844,111 @@ static void psmouse_deactivate(struct psmouse *psmouse) | |||
794 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 844 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
795 | } | 845 | } |
796 | 846 | ||
847 | /* | ||
848 | * psmouse_poll() - default poll hanlder. Everyone except for ALPS uses it. | ||
849 | */ | ||
850 | |||
851 | static int psmouse_poll(struct psmouse *psmouse) | ||
852 | { | ||
853 | return ps2_command(&psmouse->ps2dev, psmouse->packet, | ||
854 | PSMOUSE_CMD_POLL | (psmouse->pktsize << 8)); | ||
855 | } | ||
856 | |||
857 | |||
858 | /* | ||
859 | * psmouse_resync() attempts to re-validate current protocol. | ||
860 | */ | ||
861 | |||
862 | static void psmouse_resync(void *p) | ||
863 | { | ||
864 | struct psmouse *psmouse = p, *parent = NULL; | ||
865 | struct serio *serio = psmouse->ps2dev.serio; | ||
866 | psmouse_ret_t rc = PSMOUSE_GOOD_DATA; | ||
867 | int failed = 0, enabled = 0; | ||
868 | int i; | ||
869 | |||
870 | down(&psmouse_sem); | ||
871 | |||
872 | if (psmouse->state != PSMOUSE_RESYNCING) | ||
873 | goto out; | ||
874 | |||
875 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | ||
876 | parent = serio_get_drvdata(serio->parent); | ||
877 | psmouse_deactivate(parent); | ||
878 | } | ||
879 | |||
880 | /* | ||
881 | * Some mice don't ACK commands sent while they are in the middle of | ||
882 | * transmitting motion packet. To avoid delay we use ps2_sendbyte() | ||
883 | * instead of ps2_command() which would wait for 200ms for an ACK | ||
884 | * that may never come. | ||
885 | * As an additional quirk ALPS touchpads may not only forget to ACK | ||
886 | * disable command but will stop reporting taps, so if we see that | ||
887 | * mouse at least once ACKs disable we will do full reconnect if ACK | ||
888 | * is missing. | ||
889 | */ | ||
890 | psmouse->num_resyncs++; | ||
891 | |||
892 | if (ps2_sendbyte(&psmouse->ps2dev, PSMOUSE_CMD_DISABLE, 20)) { | ||
893 | if (psmouse->num_resyncs < 3 || psmouse->acks_disable_command) | ||
894 | failed = 1; | ||
895 | } else | ||
896 | psmouse->acks_disable_command = 1; | ||
897 | |||
898 | /* | ||
899 | * Poll the mouse. If it was reset the packet will be shorter than | ||
900 | * psmouse->pktsize and ps2_command will fail. We do not expect and | ||
901 | * do not handle scenario when mouse "upgrades" its protocol while | ||
902 | * disconnected since it would require additional delay. If we ever | ||
903 | * see a mouse that does it we'll adjust the code. | ||
904 | */ | ||
905 | if (!failed) { | ||
906 | if (psmouse->poll(psmouse)) | ||
907 | failed = 1; | ||
908 | else { | ||
909 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | ||
910 | for (i = 0; i < psmouse->pktsize; i++) { | ||
911 | psmouse->pktcnt++; | ||
912 | rc = psmouse->protocol_handler(psmouse, NULL); | ||
913 | if (rc != PSMOUSE_GOOD_DATA) | ||
914 | break; | ||
915 | } | ||
916 | if (rc != PSMOUSE_FULL_PACKET) | ||
917 | failed = 1; | ||
918 | psmouse_set_state(psmouse, PSMOUSE_RESYNCING); | ||
919 | } | ||
920 | } | ||
921 | /* | ||
922 | * Now try to enable mouse. We try to do that even if poll failed and also | ||
923 | * repeat our attempts 5 times, otherwise we may be left out with disabled | ||
924 | * mouse. | ||
925 | */ | ||
926 | for (i = 0; i < 5; i++) { | ||
927 | if (!ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE)) { | ||
928 | enabled = 1; | ||
929 | break; | ||
930 | } | ||
931 | msleep(200); | ||
932 | } | ||
933 | |||
934 | if (!enabled) { | ||
935 | printk(KERN_WARNING "psmouse.c: failed to re-enable mouse on %s\n", | ||
936 | psmouse->ps2dev.serio->phys); | ||
937 | failed = 1; | ||
938 | } | ||
939 | |||
940 | if (failed) { | ||
941 | psmouse_set_state(psmouse, PSMOUSE_IGNORE); | ||
942 | printk(KERN_INFO "psmouse.c: resync failed, issuing reconnect request\n"); | ||
943 | serio_reconnect(serio); | ||
944 | } else | ||
945 | psmouse_set_state(psmouse, PSMOUSE_ACTIVATED); | ||
946 | |||
947 | if (parent) | ||
948 | psmouse_activate(parent); | ||
949 | out: | ||
950 | up(&psmouse_sem); | ||
951 | } | ||
797 | 952 | ||
798 | /* | 953 | /* |
799 | * psmouse_cleanup() resets the mouse into power-on state. | 954 | * psmouse_cleanup() resets the mouse into power-on state. |
@@ -822,6 +977,11 @@ static void psmouse_disconnect(struct serio *serio) | |||
822 | 977 | ||
823 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); | 978 | psmouse_set_state(psmouse, PSMOUSE_CMD_MODE); |
824 | 979 | ||
980 | /* make sure we don't have a resync in progress */ | ||
981 | up(&psmouse_sem); | ||
982 | flush_workqueue(kpsmoused_wq); | ||
983 | down(&psmouse_sem); | ||
984 | |||
825 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { | 985 | if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) { |
826 | parent = serio_get_drvdata(serio->parent); | 986 | parent = serio_get_drvdata(serio->parent); |
827 | psmouse_deactivate(parent); | 987 | psmouse_deactivate(parent); |
@@ -859,6 +1019,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto | |||
859 | 1019 | ||
860 | psmouse->set_rate = psmouse_set_rate; | 1020 | psmouse->set_rate = psmouse_set_rate; |
861 | psmouse->set_resolution = psmouse_set_resolution; | 1021 | psmouse->set_resolution = psmouse_set_resolution; |
1022 | psmouse->poll = psmouse_poll; | ||
862 | psmouse->protocol_handler = psmouse_process_byte; | 1023 | psmouse->protocol_handler = psmouse_process_byte; |
863 | psmouse->pktsize = 3; | 1024 | psmouse->pktsize = 3; |
864 | 1025 | ||
@@ -874,6 +1035,23 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, struct psmouse_proto | |||
874 | else | 1035 | else |
875 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); | 1036 | psmouse->type = psmouse_extensions(psmouse, psmouse_max_proto, 1); |
876 | 1037 | ||
1038 | /* | ||
1039 | * If mouse's packet size is 3 there is no point in polling the | ||
1040 | * device in hopes to detect protocol reset - we won't get less | ||
1041 | * than 3 bytes response anyhow. | ||
1042 | */ | ||
1043 | if (psmouse->pktsize == 3) | ||
1044 | psmouse->resync_time = 0; | ||
1045 | |||
1046 | /* | ||
1047 | * Some smart KVMs fake response to POLL command returning just | ||
1048 | * 3 bytes and messing up our resync logic, so if initial poll | ||
1049 | * fails we won't try polling the device anymore. Hopefully | ||
1050 | * such KVM will maintain initially selected protocol. | ||
1051 | */ | ||
1052 | if (psmouse->resync_time && psmouse->poll(psmouse)) | ||
1053 | psmouse->resync_time = 0; | ||
1054 | |||
877 | sprintf(psmouse->devname, "%s %s %s", | 1055 | sprintf(psmouse->devname, "%s %s %s", |
878 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); | 1056 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); |
879 | 1057 | ||
@@ -914,6 +1092,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
914 | goto out; | 1092 | goto out; |
915 | 1093 | ||
916 | ps2_init(&psmouse->ps2dev, serio); | 1094 | ps2_init(&psmouse->ps2dev, serio); |
1095 | INIT_WORK(&psmouse->resync_work, psmouse_resync, psmouse); | ||
917 | psmouse->dev = input_dev; | 1096 | psmouse->dev = input_dev; |
918 | sprintf(psmouse->phys, "%s/input0", serio->phys); | 1097 | sprintf(psmouse->phys, "%s/input0", serio->phys); |
919 | 1098 | ||
@@ -934,6 +1113,7 @@ static int psmouse_connect(struct serio *serio, struct serio_driver *drv) | |||
934 | psmouse->rate = psmouse_rate; | 1113 | psmouse->rate = psmouse_rate; |
935 | psmouse->resolution = psmouse_resolution; | 1114 | psmouse->resolution = psmouse_resolution; |
936 | psmouse->resetafter = psmouse_resetafter; | 1115 | psmouse->resetafter = psmouse_resetafter; |
1116 | psmouse->resync_time = parent ? 0 : psmouse_resync_time; | ||
937 | psmouse->smartscroll = psmouse_smartscroll; | 1117 | psmouse->smartscroll = psmouse_smartscroll; |
938 | 1118 | ||
939 | psmouse_switch_protocol(psmouse, NULL); | 1119 | psmouse_switch_protocol(psmouse, NULL); |
@@ -1278,13 +1458,21 @@ static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp) | |||
1278 | 1458 | ||
1279 | static int __init psmouse_init(void) | 1459 | static int __init psmouse_init(void) |
1280 | { | 1460 | { |
1461 | kpsmoused_wq = create_singlethread_workqueue("kpsmoused"); | ||
1462 | if (!kpsmoused_wq) { | ||
1463 | printk(KERN_ERR "psmouse: failed to create kpsmoused workqueue\n"); | ||
1464 | return -ENOMEM; | ||
1465 | } | ||
1466 | |||
1281 | serio_register_driver(&psmouse_drv); | 1467 | serio_register_driver(&psmouse_drv); |
1468 | |||
1282 | return 0; | 1469 | return 0; |
1283 | } | 1470 | } |
1284 | 1471 | ||
1285 | static void __exit psmouse_exit(void) | 1472 | static void __exit psmouse_exit(void) |
1286 | { | 1473 | { |
1287 | serio_unregister_driver(&psmouse_drv); | 1474 | serio_unregister_driver(&psmouse_drv); |
1475 | destroy_workqueue(kpsmoused_wq); | ||
1288 | } | 1476 | } |
1289 | 1477 | ||
1290 | module_init(psmouse_init); | 1478 | module_init(psmouse_init); |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index 7c4192bd1279..4d9107fba6a1 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
@@ -7,7 +7,7 @@ | |||
7 | #define PSMOUSE_CMD_GETINFO 0x03e9 | 7 | #define PSMOUSE_CMD_GETINFO 0x03e9 |
8 | #define PSMOUSE_CMD_SETSTREAM 0x00ea | 8 | #define PSMOUSE_CMD_SETSTREAM 0x00ea |
9 | #define PSMOUSE_CMD_SETPOLL 0x00f0 | 9 | #define PSMOUSE_CMD_SETPOLL 0x00f0 |
10 | #define PSMOUSE_CMD_POLL 0x03eb | 10 | #define PSMOUSE_CMD_POLL 0x00eb /* caller sets number of bytes to receive */ |
11 | #define PSMOUSE_CMD_GETID 0x02f2 | 11 | #define PSMOUSE_CMD_GETID 0x02f2 |
12 | #define PSMOUSE_CMD_SETRATE 0x10f3 | 12 | #define PSMOUSE_CMD_SETRATE 0x10f3 |
13 | #define PSMOUSE_CMD_ENABLE 0x00f4 | 13 | #define PSMOUSE_CMD_ENABLE 0x00f4 |
@@ -23,6 +23,7 @@ | |||
23 | enum psmouse_state { | 23 | enum psmouse_state { |
24 | PSMOUSE_IGNORE, | 24 | PSMOUSE_IGNORE, |
25 | PSMOUSE_INITIALIZING, | 25 | PSMOUSE_INITIALIZING, |
26 | PSMOUSE_RESYNCING, | ||
26 | PSMOUSE_CMD_MODE, | 27 | PSMOUSE_CMD_MODE, |
27 | PSMOUSE_ACTIVATED, | 28 | PSMOUSE_ACTIVATED, |
28 | }; | 29 | }; |
@@ -38,15 +39,19 @@ struct psmouse { | |||
38 | void *private; | 39 | void *private; |
39 | struct input_dev *dev; | 40 | struct input_dev *dev; |
40 | struct ps2dev ps2dev; | 41 | struct ps2dev ps2dev; |
42 | struct work_struct resync_work; | ||
41 | char *vendor; | 43 | char *vendor; |
42 | char *name; | 44 | char *name; |
43 | unsigned char packet[8]; | 45 | unsigned char packet[8]; |
46 | unsigned char badbyte; | ||
44 | unsigned char pktcnt; | 47 | unsigned char pktcnt; |
45 | unsigned char pktsize; | 48 | unsigned char pktsize; |
46 | unsigned char type; | 49 | unsigned char type; |
50 | unsigned char acks_disable_command; | ||
47 | unsigned int model; | 51 | unsigned int model; |
48 | unsigned long last; | 52 | unsigned long last; |
49 | unsigned long out_of_sync; | 53 | unsigned long out_of_sync; |
54 | unsigned long num_resyncs; | ||
50 | enum psmouse_state state; | 55 | enum psmouse_state state; |
51 | char devname[64]; | 56 | char devname[64]; |
52 | char phys[32]; | 57 | char phys[32]; |
@@ -54,6 +59,7 @@ struct psmouse { | |||
54 | unsigned int rate; | 59 | unsigned int rate; |
55 | unsigned int resolution; | 60 | unsigned int resolution; |
56 | unsigned int resetafter; | 61 | unsigned int resetafter; |
62 | unsigned int resync_time; | ||
57 | unsigned int smartscroll; /* Logitech only */ | 63 | unsigned int smartscroll; /* Logitech only */ |
58 | 64 | ||
59 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); | 65 | psmouse_ret_t (*protocol_handler)(struct psmouse *psmouse, struct pt_regs *regs); |
@@ -62,6 +68,7 @@ struct psmouse { | |||
62 | 68 | ||
63 | int (*reconnect)(struct psmouse *psmouse); | 69 | int (*reconnect)(struct psmouse *psmouse); |
64 | void (*disconnect)(struct psmouse *psmouse); | 70 | void (*disconnect)(struct psmouse *psmouse); |
71 | int (*poll)(struct psmouse *psmouse); | ||
65 | 72 | ||
66 | void (*pt_activate)(struct psmouse *psmouse); | 73 | void (*pt_activate)(struct psmouse *psmouse); |
67 | void (*pt_deactivate)(struct psmouse *psmouse); | 74 | void (*pt_deactivate)(struct psmouse *psmouse); |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 97cdfd6acaca..2051bec2c394 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
@@ -652,6 +652,8 @@ int synaptics_init(struct psmouse *psmouse) | |||
652 | psmouse->disconnect = synaptics_disconnect; | 652 | psmouse->disconnect = synaptics_disconnect; |
653 | psmouse->reconnect = synaptics_reconnect; | 653 | psmouse->reconnect = synaptics_reconnect; |
654 | psmouse->pktsize = 6; | 654 | psmouse->pktsize = 6; |
655 | /* Synaptics can usually stay in sync without extra help */ | ||
656 | psmouse->resync_time = 0; | ||
655 | 657 | ||
656 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) | 658 | if (SYN_CAP_PASS_THROUGH(priv->capabilities)) |
657 | synaptics_pt_create(psmouse); | 659 | synaptics_pt_create(psmouse); |
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 2d2f9fb3aded..a4c6f3522723 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h | |||
@@ -173,6 +173,13 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = { | |||
173 | DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), | 173 | DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), |
174 | }, | 174 | }, |
175 | }, | 175 | }, |
176 | { | ||
177 | .ident = "Sony Vaio FS-115b", | ||
178 | .matches = { | ||
179 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
180 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"), | ||
181 | }, | ||
182 | }, | ||
176 | { } | 183 | { } |
177 | }; | 184 | }; |
178 | 185 | ||
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c index 8e530cc970e1..2f76813c3a64 100644 --- a/drivers/input/serio/serio.c +++ b/drivers/input/serio/serio.c | |||
@@ -59,9 +59,7 @@ static DECLARE_MUTEX(serio_sem); | |||
59 | 59 | ||
60 | static LIST_HEAD(serio_list); | 60 | static LIST_HEAD(serio_list); |
61 | 61 | ||
62 | static struct bus_type serio_bus = { | 62 | static struct bus_type serio_bus; |
63 | .name = "serio", | ||
64 | }; | ||
65 | 63 | ||
66 | static void serio_add_port(struct serio *serio); | 64 | static void serio_add_port(struct serio *serio); |
67 | static void serio_destroy_port(struct serio *serio); | 65 | static void serio_destroy_port(struct serio *serio); |
@@ -750,11 +748,15 @@ static int serio_driver_remove(struct device *dev) | |||
750 | return 0; | 748 | return 0; |
751 | } | 749 | } |
752 | 750 | ||
751 | static struct bus_type serio_bus = { | ||
752 | .name = "serio", | ||
753 | .probe = serio_driver_probe, | ||
754 | .remove = serio_driver_remove, | ||
755 | }; | ||
756 | |||
753 | void __serio_register_driver(struct serio_driver *drv, struct module *owner) | 757 | void __serio_register_driver(struct serio_driver *drv, struct module *owner) |
754 | { | 758 | { |
755 | drv->driver.bus = &serio_bus; | 759 | drv->driver.bus = &serio_bus; |
756 | drv->driver.probe = serio_driver_probe; | ||
757 | drv->driver.remove = serio_driver_remove; | ||
758 | 760 | ||
759 | serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER); | 761 | serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER); |
760 | } | 762 | } |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 21d55ed4b88a..2c674023a6ac 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -11,6 +11,19 @@ menuconfig INPUT_TOUCHSCREEN | |||
11 | 11 | ||
12 | if INPUT_TOUCHSCREEN | 12 | if INPUT_TOUCHSCREEN |
13 | 13 | ||
14 | config TOUCHSCREEN_ADS7846 | ||
15 | tristate "ADS 7846 based touchscreens" | ||
16 | depends on SPI_MASTER | ||
17 | help | ||
18 | Say Y here if you have a touchscreen interface using the | ||
19 | ADS7846 controller, and your board-specific initialization | ||
20 | code includes that in its table of SPI devices. | ||
21 | |||
22 | If unsure, say N (but it's safe to say "Y"). | ||
23 | |||
24 | To compile this driver as a module, choose M here: the | ||
25 | module will be called ads7846. | ||
26 | |||
14 | config TOUCHSCREEN_BITSY | 27 | config TOUCHSCREEN_BITSY |
15 | tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" | 28 | tristate "Compaq iPAQ H3600 (Bitsy) touchscreen" |
16 | depends on SA1100_BITSY | 29 | depends on SA1100_BITSY |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 6842869c9a26..5e5557c43121 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | # Each configuration option enables a list of files. | 5 | # Each configuration option enables a list of files. |
6 | 6 | ||
7 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o | ||
7 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 8 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
8 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o | 9 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o |
9 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 10 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c new file mode 100644 index 000000000000..dd8c6a9ffc76 --- /dev/null +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -0,0 +1,625 @@ | |||
1 | /* | ||
2 | * ADS7846 based touchscreen and sensor driver | ||
3 | * | ||
4 | * Copyright (c) 2005 David Brownell | ||
5 | * | ||
6 | * Using code from: | ||
7 | * - corgi_ts.c | ||
8 | * Copyright (C) 2004-2005 Richard Purdie | ||
9 | * - omap_ts.[hc], ads7846.h, ts_osk.c | ||
10 | * Copyright (C) 2002 MontaVista Software | ||
11 | * Copyright (C) 2004 Texas Instruments | ||
12 | * Copyright (C) 2005 Dirk Behme | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/spi/spi.h> | ||
25 | #include <linux/spi/ads7846.h> | ||
26 | |||
27 | #ifdef CONFIG_ARM | ||
28 | #include <asm/mach-types.h> | ||
29 | #ifdef CONFIG_ARCH_OMAP | ||
30 | #include <asm/arch/gpio.h> | ||
31 | #endif | ||
32 | |||
33 | #else | ||
34 | #define set_irq_type(irq,type) do{}while(0) | ||
35 | #endif | ||
36 | |||
37 | |||
38 | /* | ||
39 | * This code has been lightly tested on an ads7846. | ||
40 | * Support for ads7843 and ads7845 has only been stubbed in. | ||
41 | * | ||
42 | * Not yet done: investigate the values reported. Are x/y/pressure | ||
43 | * event values sane enough for X11? How accurate are the temperature | ||
44 | * and voltage readings? (System-specific calibration should support | ||
45 | * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) | ||
46 | * | ||
47 | * app note sbaa036 talks in more detail about accurate sampling... | ||
48 | * that ought to help in situations like LCDs inducing noise (which | ||
49 | * can also be helped by using synch signals) and more generally. | ||
50 | */ | ||
51 | |||
52 | #define TS_POLL_PERIOD msecs_to_jiffies(10) | ||
53 | |||
54 | struct ts_event { | ||
55 | /* For portability, we can't read 12 bit values using SPI (which | ||
56 | * would make the controller deliver them as native byteorder u16 | ||
57 | * with msbs zeroed). Instead, we read them as two 8-byte values, | ||
58 | * which need byteswapping then range adjustment. | ||
59 | */ | ||
60 | __be16 x; | ||
61 | __be16 y; | ||
62 | __be16 z1, z2; | ||
63 | }; | ||
64 | |||
65 | struct ads7846 { | ||
66 | struct input_dev input; | ||
67 | char phys[32]; | ||
68 | |||
69 | struct spi_device *spi; | ||
70 | u16 model; | ||
71 | u16 vref_delay_usecs; | ||
72 | u16 x_plate_ohms; | ||
73 | |||
74 | struct ts_event tc; | ||
75 | |||
76 | struct spi_transfer xfer[8]; | ||
77 | struct spi_message msg; | ||
78 | |||
79 | spinlock_t lock; | ||
80 | struct timer_list timer; /* P: lock */ | ||
81 | unsigned pendown:1; /* P: lock */ | ||
82 | unsigned pending:1; /* P: lock */ | ||
83 | // FIXME remove "irq_disabled" | ||
84 | unsigned irq_disabled:1; /* P: lock */ | ||
85 | }; | ||
86 | |||
87 | /* leave chip selected when we're done, for quicker re-select? */ | ||
88 | #if 0 | ||
89 | #define CS_CHANGE(xfer) ((xfer).cs_change = 1) | ||
90 | #else | ||
91 | #define CS_CHANGE(xfer) ((xfer).cs_change = 0) | ||
92 | #endif | ||
93 | |||
94 | /*--------------------------------------------------------------------------*/ | ||
95 | |||
96 | /* The ADS7846 has touchscreen and other sensors. | ||
97 | * Earlier ads784x chips are somewhat compatible. | ||
98 | */ | ||
99 | #define ADS_START (1 << 7) | ||
100 | #define ADS_A2A1A0_d_y (1 << 4) /* differential */ | ||
101 | #define ADS_A2A1A0_d_z1 (3 << 4) /* differential */ | ||
102 | #define ADS_A2A1A0_d_z2 (4 << 4) /* differential */ | ||
103 | #define ADS_A2A1A0_d_x (5 << 4) /* differential */ | ||
104 | #define ADS_A2A1A0_temp0 (0 << 4) /* non-differential */ | ||
105 | #define ADS_A2A1A0_vbatt (2 << 4) /* non-differential */ | ||
106 | #define ADS_A2A1A0_vaux (6 << 4) /* non-differential */ | ||
107 | #define ADS_A2A1A0_temp1 (7 << 4) /* non-differential */ | ||
108 | #define ADS_8_BIT (1 << 3) | ||
109 | #define ADS_12_BIT (0 << 3) | ||
110 | #define ADS_SER (1 << 2) /* non-differential */ | ||
111 | #define ADS_DFR (0 << 2) /* differential */ | ||
112 | #define ADS_PD10_PDOWN (0 << 0) /* lowpower mode + penirq */ | ||
113 | #define ADS_PD10_ADC_ON (1 << 0) /* ADC on */ | ||
114 | #define ADS_PD10_REF_ON (2 << 0) /* vREF on + penirq */ | ||
115 | #define ADS_PD10_ALL_ON (3 << 0) /* ADC + vREF on */ | ||
116 | |||
117 | #define MAX_12BIT ((1<<12)-1) | ||
118 | |||
119 | /* leave ADC powered up (disables penirq) between differential samples */ | ||
120 | #define READ_12BIT_DFR(x) (ADS_START | ADS_A2A1A0_d_ ## x \ | ||
121 | | ADS_12_BIT | ADS_DFR) | ||
122 | |||
123 | static const u8 read_y = READ_12BIT_DFR(y) | ADS_PD10_ADC_ON; | ||
124 | static const u8 read_z1 = READ_12BIT_DFR(z1) | ADS_PD10_ADC_ON; | ||
125 | static const u8 read_z2 = READ_12BIT_DFR(z2) | ADS_PD10_ADC_ON; | ||
126 | static const u8 read_x = READ_12BIT_DFR(x) | ADS_PD10_PDOWN; /* LAST */ | ||
127 | |||
128 | /* single-ended samples need to first power up reference voltage; | ||
129 | * we leave both ADC and VREF powered | ||
130 | */ | ||
131 | #define READ_12BIT_SER(x) (ADS_START | ADS_A2A1A0_ ## x \ | ||
132 | | ADS_12_BIT | ADS_SER) | ||
133 | |||
134 | static const u8 ref_on = READ_12BIT_DFR(x) | ADS_PD10_ALL_ON; | ||
135 | static const u8 ref_off = READ_12BIT_DFR(y) | ADS_PD10_PDOWN; | ||
136 | |||
137 | /*--------------------------------------------------------------------------*/ | ||
138 | |||
139 | /* | ||
140 | * Non-touchscreen sensors only use single-ended conversions. | ||
141 | */ | ||
142 | |||
143 | struct ser_req { | ||
144 | u8 command; | ||
145 | u16 scratch; | ||
146 | __be16 sample; | ||
147 | struct spi_message msg; | ||
148 | struct spi_transfer xfer[6]; | ||
149 | }; | ||
150 | |||
151 | static int ads7846_read12_ser(struct device *dev, unsigned command) | ||
152 | { | ||
153 | struct spi_device *spi = to_spi_device(dev); | ||
154 | struct ads7846 *ts = dev_get_drvdata(dev); | ||
155 | struct ser_req *req = kzalloc(sizeof *req, SLAB_KERNEL); | ||
156 | int status; | ||
157 | int sample; | ||
158 | int i; | ||
159 | |||
160 | if (!req) | ||
161 | return -ENOMEM; | ||
162 | |||
163 | INIT_LIST_HEAD(&req->msg.transfers); | ||
164 | |||
165 | /* activate reference, so it has time to settle; */ | ||
166 | req->xfer[0].tx_buf = &ref_on; | ||
167 | req->xfer[0].len = 1; | ||
168 | req->xfer[1].rx_buf = &req->scratch; | ||
169 | req->xfer[1].len = 2; | ||
170 | |||
171 | /* | ||
172 | * for external VREF, 0 usec (and assume it's always on); | ||
173 | * for 1uF, use 800 usec; | ||
174 | * no cap, 100 usec. | ||
175 | */ | ||
176 | req->xfer[1].delay_usecs = ts->vref_delay_usecs; | ||
177 | |||
178 | /* take sample */ | ||
179 | req->command = (u8) command; | ||
180 | req->xfer[2].tx_buf = &req->command; | ||
181 | req->xfer[2].len = 1; | ||
182 | req->xfer[3].rx_buf = &req->sample; | ||
183 | req->xfer[3].len = 2; | ||
184 | |||
185 | /* REVISIT: take a few more samples, and compare ... */ | ||
186 | |||
187 | /* turn off reference */ | ||
188 | req->xfer[4].tx_buf = &ref_off; | ||
189 | req->xfer[4].len = 1; | ||
190 | req->xfer[5].rx_buf = &req->scratch; | ||
191 | req->xfer[5].len = 2; | ||
192 | |||
193 | CS_CHANGE(req->xfer[5]); | ||
194 | |||
195 | /* group all the transfers together, so we can't interfere with | ||
196 | * reading touchscreen state; disable penirq while sampling | ||
197 | */ | ||
198 | for (i = 0; i < 6; i++) | ||
199 | spi_message_add_tail(&req->xfer[i], &req->msg); | ||
200 | |||
201 | disable_irq(spi->irq); | ||
202 | status = spi_sync(spi, &req->msg); | ||
203 | enable_irq(spi->irq); | ||
204 | |||
205 | if (req->msg.status) | ||
206 | status = req->msg.status; | ||
207 | sample = be16_to_cpu(req->sample); | ||
208 | sample = sample >> 4; | ||
209 | kfree(req); | ||
210 | |||
211 | return status ? status : sample; | ||
212 | } | ||
213 | |||
214 | #define SHOW(name) static ssize_t \ | ||
215 | name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \ | ||
216 | { \ | ||
217 | ssize_t v = ads7846_read12_ser(dev, \ | ||
218 | READ_12BIT_SER(name) | ADS_PD10_ALL_ON); \ | ||
219 | if (v < 0) \ | ||
220 | return v; \ | ||
221 | return sprintf(buf, "%u\n", (unsigned) v); \ | ||
222 | } \ | ||
223 | static DEVICE_ATTR(name, S_IRUGO, name ## _show, NULL); | ||
224 | |||
225 | SHOW(temp0) | ||
226 | SHOW(temp1) | ||
227 | SHOW(vaux) | ||
228 | SHOW(vbatt) | ||
229 | |||
230 | /*--------------------------------------------------------------------------*/ | ||
231 | |||
232 | /* | ||
233 | * PENIRQ only kicks the timer. The timer only reissues the SPI transfer, | ||
234 | * to retrieve touchscreen status. | ||
235 | * | ||
236 | * The SPI transfer completion callback does the real work. It reports | ||
237 | * touchscreen events and reactivates the timer (or IRQ) as appropriate. | ||
238 | */ | ||
239 | |||
240 | static void ads7846_rx(void *ads) | ||
241 | { | ||
242 | struct ads7846 *ts = ads; | ||
243 | unsigned Rt; | ||
244 | unsigned sync = 0; | ||
245 | u16 x, y, z1, z2; | ||
246 | unsigned long flags; | ||
247 | |||
248 | /* adjust: 12 bit samples (left aligned), built from | ||
249 | * two 8 bit values writen msb-first. | ||
250 | */ | ||
251 | x = be16_to_cpu(ts->tc.x) >> 4; | ||
252 | y = be16_to_cpu(ts->tc.y) >> 4; | ||
253 | z1 = be16_to_cpu(ts->tc.z1) >> 4; | ||
254 | z2 = be16_to_cpu(ts->tc.z2) >> 4; | ||
255 | |||
256 | /* range filtering */ | ||
257 | if (x == MAX_12BIT) | ||
258 | x = 0; | ||
259 | |||
260 | if (x && z1 && ts->spi->dev.power.power_state.event == PM_EVENT_ON) { | ||
261 | /* compute touch pressure resistance using equation #2 */ | ||
262 | Rt = z2; | ||
263 | Rt -= z1; | ||
264 | Rt *= x; | ||
265 | Rt *= ts->x_plate_ohms; | ||
266 | Rt /= z1; | ||
267 | Rt = (Rt + 2047) >> 12; | ||
268 | } else | ||
269 | Rt = 0; | ||
270 | |||
271 | /* NOTE: "pendown" is inferred from pressure; we don't rely on | ||
272 | * being able to check nPENIRQ status, or "friendly" trigger modes | ||
273 | * (both-edges is much better than just-falling or low-level). | ||
274 | * | ||
275 | * REVISIT: some boards may require reading nPENIRQ; it's | ||
276 | * needed on 7843. and 7845 reads pressure differently... | ||
277 | * | ||
278 | * REVISIT: the touchscreen might not be connected; this code | ||
279 | * won't notice that, even if nPENIRQ never fires ... | ||
280 | */ | ||
281 | if (!ts->pendown && Rt != 0) { | ||
282 | input_report_key(&ts->input, BTN_TOUCH, 1); | ||
283 | sync = 1; | ||
284 | } else if (ts->pendown && Rt == 0) { | ||
285 | input_report_key(&ts->input, BTN_TOUCH, 0); | ||
286 | sync = 1; | ||
287 | } | ||
288 | |||
289 | if (Rt) { | ||
290 | input_report_abs(&ts->input, ABS_X, x); | ||
291 | input_report_abs(&ts->input, ABS_Y, y); | ||
292 | input_report_abs(&ts->input, ABS_PRESSURE, Rt); | ||
293 | sync = 1; | ||
294 | } | ||
295 | if (sync) | ||
296 | input_sync(&ts->input); | ||
297 | |||
298 | #ifdef VERBOSE | ||
299 | if (Rt || ts->pendown) | ||
300 | pr_debug("%s: %d/%d/%d%s\n", ts->spi->dev.bus_id, | ||
301 | x, y, Rt, Rt ? "" : " UP"); | ||
302 | #endif | ||
303 | |||
304 | /* don't retrigger while we're suspended */ | ||
305 | spin_lock_irqsave(&ts->lock, flags); | ||
306 | |||
307 | ts->pendown = (Rt != 0); | ||
308 | ts->pending = 0; | ||
309 | |||
310 | if (ts->spi->dev.power.power_state.event == PM_EVENT_ON) { | ||
311 | if (ts->pendown) | ||
312 | mod_timer(&ts->timer, jiffies + TS_POLL_PERIOD); | ||
313 | else if (ts->irq_disabled) { | ||
314 | ts->irq_disabled = 0; | ||
315 | enable_irq(ts->spi->irq); | ||
316 | } | ||
317 | } | ||
318 | |||
319 | spin_unlock_irqrestore(&ts->lock, flags); | ||
320 | } | ||
321 | |||
322 | static void ads7846_timer(unsigned long handle) | ||
323 | { | ||
324 | struct ads7846 *ts = (void *)handle; | ||
325 | int status = 0; | ||
326 | unsigned long flags; | ||
327 | |||
328 | spin_lock_irqsave(&ts->lock, flags); | ||
329 | if (!ts->pending) { | ||
330 | ts->pending = 1; | ||
331 | if (!ts->irq_disabled) { | ||
332 | ts->irq_disabled = 1; | ||
333 | disable_irq(ts->spi->irq); | ||
334 | } | ||
335 | status = spi_async(ts->spi, &ts->msg); | ||
336 | if (status) | ||
337 | dev_err(&ts->spi->dev, "spi_async --> %d\n", | ||
338 | status); | ||
339 | } | ||
340 | spin_unlock_irqrestore(&ts->lock, flags); | ||
341 | } | ||
342 | |||
343 | static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) | ||
344 | { | ||
345 | ads7846_timer((unsigned long) handle); | ||
346 | return IRQ_HANDLED; | ||
347 | } | ||
348 | |||
349 | /*--------------------------------------------------------------------------*/ | ||
350 | |||
351 | static int | ||
352 | ads7846_suspend(struct spi_device *spi, pm_message_t message) | ||
353 | { | ||
354 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | ||
355 | unsigned long flags; | ||
356 | |||
357 | spin_lock_irqsave(&ts->lock, flags); | ||
358 | |||
359 | spi->dev.power.power_state = message; | ||
360 | |||
361 | /* are we waiting for IRQ, or polling? */ | ||
362 | if (!ts->pendown) { | ||
363 | if (!ts->irq_disabled) { | ||
364 | ts->irq_disabled = 1; | ||
365 | disable_irq(ts->spi->irq); | ||
366 | } | ||
367 | } else { | ||
368 | /* polling; force a final SPI completion; | ||
369 | * that will clean things up neatly | ||
370 | */ | ||
371 | if (!ts->pending) | ||
372 | mod_timer(&ts->timer, jiffies); | ||
373 | |||
374 | while (ts->pendown || ts->pending) { | ||
375 | spin_unlock_irqrestore(&ts->lock, flags); | ||
376 | udelay(10); | ||
377 | spin_lock_irqsave(&ts->lock, flags); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | /* we know the chip's in lowpower mode since we always | ||
382 | * leave it that way after every request | ||
383 | */ | ||
384 | |||
385 | spin_unlock_irqrestore(&ts->lock, flags); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | static int ads7846_resume(struct spi_device *spi) | ||
390 | { | ||
391 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | ||
392 | |||
393 | ts->irq_disabled = 0; | ||
394 | enable_irq(ts->spi->irq); | ||
395 | spi->dev.power.power_state = PMSG_ON; | ||
396 | return 0; | ||
397 | } | ||
398 | |||
399 | static int __devinit ads7846_probe(struct spi_device *spi) | ||
400 | { | ||
401 | struct ads7846 *ts; | ||
402 | struct ads7846_platform_data *pdata = spi->dev.platform_data; | ||
403 | struct spi_transfer *x; | ||
404 | int i; | ||
405 | |||
406 | if (!spi->irq) { | ||
407 | dev_dbg(&spi->dev, "no IRQ?\n"); | ||
408 | return -ENODEV; | ||
409 | } | ||
410 | |||
411 | if (!pdata) { | ||
412 | dev_dbg(&spi->dev, "no platform data?\n"); | ||
413 | return -ENODEV; | ||
414 | } | ||
415 | |||
416 | /* don't exceed max specified sample rate */ | ||
417 | if (spi->max_speed_hz > (125000 * 16)) { | ||
418 | dev_dbg(&spi->dev, "f(sample) %d KHz?\n", | ||
419 | (spi->max_speed_hz/16)/1000); | ||
420 | return -EINVAL; | ||
421 | } | ||
422 | |||
423 | /* We'd set the wordsize to 12 bits ... except that some controllers | ||
424 | * will then treat the 8 bit command words as 12 bits (and drop the | ||
425 | * four MSBs of the 12 bit result). Result: inputs must be shifted | ||
426 | * to discard the four garbage LSBs. | ||
427 | */ | ||
428 | |||
429 | if (!(ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL))) | ||
430 | return -ENOMEM; | ||
431 | |||
432 | dev_set_drvdata(&spi->dev, ts); | ||
433 | |||
434 | ts->spi = spi; | ||
435 | spi->dev.power.power_state = PMSG_ON; | ||
436 | |||
437 | init_timer(&ts->timer); | ||
438 | ts->timer.data = (unsigned long) ts; | ||
439 | ts->timer.function = ads7846_timer; | ||
440 | |||
441 | ts->model = pdata->model ? : 7846; | ||
442 | ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100; | ||
443 | ts->x_plate_ohms = pdata->x_plate_ohms ? : 400; | ||
444 | |||
445 | init_input_dev(&ts->input); | ||
446 | |||
447 | ts->input.dev = &spi->dev; | ||
448 | ts->input.name = "ADS784x Touchscreen"; | ||
449 | snprintf(ts->phys, sizeof ts->phys, "%s/input0", spi->dev.bus_id); | ||
450 | ts->input.phys = ts->phys; | ||
451 | |||
452 | ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); | ||
453 | ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); | ||
454 | input_set_abs_params(&ts->input, ABS_X, | ||
455 | pdata->x_min ? : 0, | ||
456 | pdata->x_max ? : MAX_12BIT, | ||
457 | 0, 0); | ||
458 | input_set_abs_params(&ts->input, ABS_Y, | ||
459 | pdata->y_min ? : 0, | ||
460 | pdata->y_max ? : MAX_12BIT, | ||
461 | 0, 0); | ||
462 | input_set_abs_params(&ts->input, ABS_PRESSURE, | ||
463 | pdata->pressure_min, pdata->pressure_max, 0, 0); | ||
464 | |||
465 | input_register_device(&ts->input); | ||
466 | |||
467 | /* set up the transfers to read touchscreen state; this assumes we | ||
468 | * use formula #2 for pressure, not #3. | ||
469 | */ | ||
470 | x = ts->xfer; | ||
471 | |||
472 | /* y- still on; turn on only y+ (and ADC) */ | ||
473 | x->tx_buf = &read_y; | ||
474 | x->len = 1; | ||
475 | x++; | ||
476 | x->rx_buf = &ts->tc.y; | ||
477 | x->len = 2; | ||
478 | x++; | ||
479 | |||
480 | /* turn y+ off, x- on; we'll use formula #2 */ | ||
481 | if (ts->model == 7846) { | ||
482 | x->tx_buf = &read_z1; | ||
483 | x->len = 1; | ||
484 | x++; | ||
485 | x->rx_buf = &ts->tc.z1; | ||
486 | x->len = 2; | ||
487 | x++; | ||
488 | |||
489 | x->tx_buf = &read_z2; | ||
490 | x->len = 1; | ||
491 | x++; | ||
492 | x->rx_buf = &ts->tc.z2; | ||
493 | x->len = 2; | ||
494 | x++; | ||
495 | } | ||
496 | |||
497 | /* turn y- off, x+ on, then leave in lowpower */ | ||
498 | x->tx_buf = &read_x; | ||
499 | x->len = 1; | ||
500 | x++; | ||
501 | x->rx_buf = &ts->tc.x; | ||
502 | x->len = 2; | ||
503 | x++; | ||
504 | |||
505 | CS_CHANGE(x[-1]); | ||
506 | |||
507 | for (i = 0; i < x - ts->xfer; i++) | ||
508 | spi_message_add_tail(&ts->xfer[i], &ts->msg); | ||
509 | ts->msg.complete = ads7846_rx; | ||
510 | ts->msg.context = ts; | ||
511 | |||
512 | if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM, | ||
513 | spi->dev.bus_id, ts)) { | ||
514 | dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); | ||
515 | input_unregister_device(&ts->input); | ||
516 | kfree(ts); | ||
517 | return -EBUSY; | ||
518 | } | ||
519 | set_irq_type(spi->irq, IRQT_FALLING); | ||
520 | |||
521 | dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq); | ||
522 | |||
523 | /* take a first sample, leaving nPENIRQ active; avoid | ||
524 | * the touchscreen, in case it's not connected. | ||
525 | */ | ||
526 | (void) ads7846_read12_ser(&spi->dev, | ||
527 | READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON); | ||
528 | |||
529 | /* ads7843/7845 don't have temperature sensors, and | ||
530 | * use the other sensors a bit differently too | ||
531 | */ | ||
532 | if (ts->model == 7846) { | ||
533 | device_create_file(&spi->dev, &dev_attr_temp0); | ||
534 | device_create_file(&spi->dev, &dev_attr_temp1); | ||
535 | } | ||
536 | if (ts->model != 7845) | ||
537 | device_create_file(&spi->dev, &dev_attr_vbatt); | ||
538 | device_create_file(&spi->dev, &dev_attr_vaux); | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | static int __devexit ads7846_remove(struct spi_device *spi) | ||
544 | { | ||
545 | struct ads7846 *ts = dev_get_drvdata(&spi->dev); | ||
546 | |||
547 | ads7846_suspend(spi, PMSG_SUSPEND); | ||
548 | free_irq(ts->spi->irq, ts); | ||
549 | if (ts->irq_disabled) | ||
550 | enable_irq(ts->spi->irq); | ||
551 | |||
552 | if (ts->model == 7846) { | ||
553 | device_remove_file(&spi->dev, &dev_attr_temp0); | ||
554 | device_remove_file(&spi->dev, &dev_attr_temp1); | ||
555 | } | ||
556 | if (ts->model != 7845) | ||
557 | device_remove_file(&spi->dev, &dev_attr_vbatt); | ||
558 | device_remove_file(&spi->dev, &dev_attr_vaux); | ||
559 | |||
560 | input_unregister_device(&ts->input); | ||
561 | kfree(ts); | ||
562 | |||
563 | dev_dbg(&spi->dev, "unregistered touchscreen\n"); | ||
564 | return 0; | ||
565 | } | ||
566 | |||
567 | static struct spi_driver ads7846_driver = { | ||
568 | .driver = { | ||
569 | .name = "ads7846", | ||
570 | .bus = &spi_bus_type, | ||
571 | .owner = THIS_MODULE, | ||
572 | }, | ||
573 | .probe = ads7846_probe, | ||
574 | .remove = __devexit_p(ads7846_remove), | ||
575 | .suspend = ads7846_suspend, | ||
576 | .resume = ads7846_resume, | ||
577 | }; | ||
578 | |||
579 | static int __init ads7846_init(void) | ||
580 | { | ||
581 | /* grr, board-specific init should stay out of drivers!! */ | ||
582 | |||
583 | #ifdef CONFIG_ARCH_OMAP | ||
584 | if (machine_is_omap_osk()) { | ||
585 | /* GPIO4 = PENIRQ; GPIO6 = BUSY */ | ||
586 | omap_request_gpio(4); | ||
587 | omap_set_gpio_direction(4, 1); | ||
588 | omap_request_gpio(6); | ||
589 | omap_set_gpio_direction(6, 1); | ||
590 | } | ||
591 | // also TI 1510 Innovator, bitbanging through FPGA | ||
592 | // also Nokia 770 | ||
593 | // also Palm Tungsten T2 | ||
594 | #endif | ||
595 | |||
596 | // PXA: | ||
597 | // also Dell Axim X50 | ||
598 | // also HP iPaq H191x/H192x/H415x/H435x | ||
599 | // also Intel Lubbock (additional to UCB1400; as temperature sensor) | ||
600 | // also Sharp Zaurus C7xx, C8xx (corgi/sheperd/husky) | ||
601 | |||
602 | // Atmel at91sam9261-EK uses ads7843 | ||
603 | |||
604 | // also various AMD Au1x00 devel boards | ||
605 | |||
606 | return spi_register_driver(&ads7846_driver); | ||
607 | } | ||
608 | module_init(ads7846_init); | ||
609 | |||
610 | static void __exit ads7846_exit(void) | ||
611 | { | ||
612 | spi_unregister_driver(&ads7846_driver); | ||
613 | |||
614 | #ifdef CONFIG_ARCH_OMAP | ||
615 | if (machine_is_omap_osk()) { | ||
616 | omap_free_gpio(4); | ||
617 | omap_free_gpio(6); | ||
618 | } | ||
619 | #endif | ||
620 | |||
621 | } | ||
622 | module_exit(ads7846_exit); | ||
623 | |||
624 | MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); | ||
625 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/macintosh/adb-iop.c b/drivers/macintosh/adb-iop.c index 71aeb912ec61..d56d400b6aaa 100644 --- a/drivers/macintosh/adb-iop.c +++ b/drivers/macintosh/adb-iop.c | |||
@@ -239,7 +239,7 @@ static int adb_iop_write(struct adb_request *req) | |||
239 | 239 | ||
240 | local_irq_save(flags); | 240 | local_irq_save(flags); |
241 | 241 | ||
242 | req->next = 0; | 242 | req->next = NULL; |
243 | req->sent = 0; | 243 | req->sent = 0; |
244 | req->complete = 0; | 244 | req->complete = 0; |
245 | req->reply_len = 0; | 245 | req->reply_len = 0; |
diff --git a/drivers/macintosh/macio-adb.c b/drivers/macintosh/macio-adb.c index cf6a6f2248ac..314fc0830d90 100644 --- a/drivers/macintosh/macio-adb.c +++ b/drivers/macintosh/macio-adb.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/irq.h> | 17 | #include <asm/irq.h> |
18 | #include <asm/system.h> | 18 | #include <asm/system.h> |
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/ioport.h> | ||
20 | 21 | ||
21 | struct preg { | 22 | struct preg { |
22 | unsigned char r; | 23 | unsigned char r; |
@@ -88,24 +89,26 @@ int macio_probe(void) | |||
88 | int macio_init(void) | 89 | int macio_init(void) |
89 | { | 90 | { |
90 | struct device_node *adbs; | 91 | struct device_node *adbs; |
92 | struct resource r; | ||
91 | 93 | ||
92 | adbs = find_compatible_devices("adb", "chrp,adb0"); | 94 | adbs = find_compatible_devices("adb", "chrp,adb0"); |
93 | if (adbs == 0) | 95 | if (adbs == 0) |
94 | return -ENXIO; | 96 | return -ENXIO; |
95 | 97 | ||
96 | #if 0 | 98 | #if 0 |
97 | { int i; | 99 | { int i = 0; |
98 | 100 | ||
99 | printk("macio_adb_init: node = %p, addrs =", adbs->node); | 101 | printk("macio_adb_init: node = %p, addrs =", adbs->node); |
100 | for (i = 0; i < adbs->n_addrs; ++i) | 102 | while(!of_address_to_resource(adbs, i, &r)) |
101 | printk(" %x(%x)", adbs->addrs[i].address, adbs->addrs[i].size); | 103 | printk(" %x(%x)", r.start, r.end - r.start); |
102 | printk(", intrs ="); | 104 | printk(", intrs ="); |
103 | for (i = 0; i < adbs->n_intrs; ++i) | 105 | for (i = 0; i < adbs->n_intrs; ++i) |
104 | printk(" %x", adbs->intrs[i].line); | 106 | printk(" %x", adbs->intrs[i].line); |
105 | printk("\n"); } | 107 | printk("\n"); } |
106 | #endif | 108 | #endif |
107 | 109 | if (of_address_to_resource(adbs, 0, &r)) | |
108 | adb = ioremap(adbs->addrs->address, sizeof(struct adb_regs)); | 110 | return -ENXIO; |
111 | adb = ioremap(r.start, sizeof(struct adb_regs)); | ||
109 | 112 | ||
110 | out_8(&adb->ctrl.r, 0); | 113 | out_8(&adb->ctrl.r, 0); |
111 | out_8(&adb->intr.r, 0); | 114 | out_8(&adb->intr.r, 0); |
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 2a545ceb523b..ed6d3174d660 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c | |||
@@ -211,6 +211,9 @@ struct bus_type macio_bus_type = { | |||
211 | .name = "macio", | 211 | .name = "macio", |
212 | .match = macio_bus_match, | 212 | .match = macio_bus_match, |
213 | .uevent = macio_uevent, | 213 | .uevent = macio_uevent, |
214 | .probe = macio_device_probe, | ||
215 | .remove = macio_device_remove, | ||
216 | .shutdown = macio_device_shutdown, | ||
214 | .suspend = macio_device_suspend, | 217 | .suspend = macio_device_suspend, |
215 | .resume = macio_device_resume, | 218 | .resume = macio_device_resume, |
216 | .dev_attrs = macio_dev_attrs, | 219 | .dev_attrs = macio_dev_attrs, |
@@ -528,9 +531,6 @@ int macio_register_driver(struct macio_driver *drv) | |||
528 | /* initialize common driver fields */ | 531 | /* initialize common driver fields */ |
529 | drv->driver.name = drv->name; | 532 | drv->driver.name = drv->name; |
530 | drv->driver.bus = &macio_bus_type; | 533 | drv->driver.bus = &macio_bus_type; |
531 | drv->driver.probe = macio_device_probe; | ||
532 | drv->driver.remove = macio_device_remove; | ||
533 | drv->driver.shutdown = macio_device_shutdown; | ||
534 | 534 | ||
535 | /* register with core */ | 535 | /* register with core */ |
536 | count = driver_register(&drv->driver); | 536 | count = driver_register(&drv->driver); |
diff --git a/drivers/macintosh/via-macii.c b/drivers/macintosh/via-macii.c index e9a159ad3022..2a2ffe060169 100644 --- a/drivers/macintosh/via-macii.c +++ b/drivers/macintosh/via-macii.c | |||
@@ -260,7 +260,7 @@ static int macii_write(struct adb_request *req) | |||
260 | return -EINVAL; | 260 | return -EINVAL; |
261 | } | 261 | } |
262 | 262 | ||
263 | req->next = 0; | 263 | req->next = NULL; |
264 | req->sent = 0; | 264 | req->sent = 0; |
265 | req->complete = 0; | 265 | req->complete = 0; |
266 | req->reply_len = 0; | 266 | req->reply_len = 0; |
@@ -295,7 +295,7 @@ static void macii_poll(void) | |||
295 | unsigned long flags; | 295 | unsigned long flags; |
296 | 296 | ||
297 | local_irq_save(flags); | 297 | local_irq_save(flags); |
298 | if (via[IFR] & SR_INT) macii_interrupt(0, 0, 0); | 298 | if (via[IFR] & SR_INT) macii_interrupt(0, NULL, NULL); |
299 | local_irq_restore(flags); | 299 | local_irq_restore(flags); |
300 | } | 300 | } |
301 | 301 | ||
diff --git a/drivers/macintosh/via-maciisi.c b/drivers/macintosh/via-maciisi.c index a1966975d58f..0129fcc3b183 100644 --- a/drivers/macintosh/via-maciisi.c +++ b/drivers/macintosh/via-maciisi.c | |||
@@ -294,6 +294,24 @@ static void maciisi_sync(struct adb_request *req) | |||
294 | printk(KERN_ERR "maciisi_send_request: poll timed out!\n"); | 294 | printk(KERN_ERR "maciisi_send_request: poll timed out!\n"); |
295 | } | 295 | } |
296 | 296 | ||
297 | int | ||
298 | maciisi_request(struct adb_request *req, void (*done)(struct adb_request *), | ||
299 | int nbytes, ...) | ||
300 | { | ||
301 | va_list list; | ||
302 | int i; | ||
303 | |||
304 | req->nbytes = nbytes; | ||
305 | req->done = done; | ||
306 | req->reply_expected = 0; | ||
307 | va_start(list, nbytes); | ||
308 | for (i = 0; i < nbytes; i++) | ||
309 | req->data[i++] = va_arg(list, int); | ||
310 | va_end(list); | ||
311 | |||
312 | return maciisi_send_request(req, 1); | ||
313 | } | ||
314 | |||
297 | /* Enqueue a request, and run the queue if possible */ | 315 | /* Enqueue a request, and run the queue if possible */ |
298 | static int | 316 | static int |
299 | maciisi_write(struct adb_request* req) | 317 | maciisi_write(struct adb_request* req) |
@@ -308,7 +326,7 @@ maciisi_write(struct adb_request* req) | |||
308 | req->complete = 1; | 326 | req->complete = 1; |
309 | return -EINVAL; | 327 | return -EINVAL; |
310 | } | 328 | } |
311 | req->next = 0; | 329 | req->next = NULL; |
312 | req->sent = 0; | 330 | req->sent = 0; |
313 | req->complete = 0; | 331 | req->complete = 0; |
314 | req->reply_len = 0; | 332 | req->reply_len = 0; |
@@ -403,7 +421,7 @@ maciisi_poll(void) | |||
403 | 421 | ||
404 | local_irq_save(flags); | 422 | local_irq_save(flags); |
405 | if (via[IFR] & SR_INT) { | 423 | if (via[IFR] & SR_INT) { |
406 | maciisi_interrupt(0, 0, 0); | 424 | maciisi_interrupt(0, NULL, NULL); |
407 | } | 425 | } |
408 | else /* avoid calling this function too quickly in a loop */ | 426 | else /* avoid calling this function too quickly in a loop */ |
409 | udelay(ADB_DELAY); | 427 | udelay(ADB_DELAY); |
diff --git a/drivers/macintosh/via-pmu68k.c b/drivers/macintosh/via-pmu68k.c index 6f80d76ac17c..f08e52f2107b 100644 --- a/drivers/macintosh/via-pmu68k.c +++ b/drivers/macintosh/via-pmu68k.c | |||
@@ -493,7 +493,7 @@ pmu_queue_request(struct adb_request *req) | |||
493 | return -EINVAL; | 493 | return -EINVAL; |
494 | } | 494 | } |
495 | 495 | ||
496 | req->next = 0; | 496 | req->next = NULL; |
497 | req->sent = 0; | 497 | req->sent = 0; |
498 | req->complete = 0; | 498 | req->complete = 0; |
499 | local_irq_save(flags); | 499 | local_irq_save(flags); |
@@ -717,7 +717,7 @@ pmu_handle_data(unsigned char *data, int len, struct pt_regs *regs) | |||
717 | printk(KERN_ERR "PMU: extra ADB reply\n"); | 717 | printk(KERN_ERR "PMU: extra ADB reply\n"); |
718 | return; | 718 | return; |
719 | } | 719 | } |
720 | req_awaiting_reply = 0; | 720 | req_awaiting_reply = NULL; |
721 | if (len <= 2) | 721 | if (len <= 2) |
722 | req->reply_len = 0; | 722 | req->reply_len = 0; |
723 | else { | 723 | else { |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 0302723fa21f..1778104e106c 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -1238,6 +1238,7 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
1238 | mdk_rdev_t *same_pdev; | 1238 | mdk_rdev_t *same_pdev; |
1239 | char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; | 1239 | char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE]; |
1240 | struct kobject *ko; | 1240 | struct kobject *ko; |
1241 | char *s; | ||
1241 | 1242 | ||
1242 | if (rdev->mddev) { | 1243 | if (rdev->mddev) { |
1243 | MD_BUG(); | 1244 | MD_BUG(); |
@@ -1277,6 +1278,8 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) | |||
1277 | bdevname(rdev->bdev,b); | 1278 | bdevname(rdev->bdev,b); |
1278 | if (kobject_set_name(&rdev->kobj, "dev-%s", b) < 0) | 1279 | if (kobject_set_name(&rdev->kobj, "dev-%s", b) < 0) |
1279 | return -ENOMEM; | 1280 | return -ENOMEM; |
1281 | while ( (s=strchr(rdev->kobj.k_name, '/')) != NULL) | ||
1282 | *s = '!'; | ||
1280 | 1283 | ||
1281 | list_add(&rdev->same_set, &mddev->disks); | 1284 | list_add(&rdev->same_set, &mddev->disks); |
1282 | rdev->mddev = mddev; | 1285 | rdev->mddev = mddev; |
diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index f65f64b00ff3..44fcbe77c8f9 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c | |||
@@ -779,9 +779,8 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) | |||
779 | return 0; | 779 | return 0; |
780 | } | 780 | } |
781 | 781 | ||
782 | static int dvb_bt8xx_probe(struct device *dev) | 782 | static int dvb_bt8xx_probe(struct bttv_sub_device *sub) |
783 | { | 783 | { |
784 | struct bttv_sub_device *sub = to_bttv_sub_dev(dev); | ||
785 | struct dvb_bt8xx_card *card; | 784 | struct dvb_bt8xx_card *card; |
786 | struct pci_dev* bttv_pci_dev; | 785 | struct pci_dev* bttv_pci_dev; |
787 | int ret; | 786 | int ret; |
@@ -890,13 +889,13 @@ static int dvb_bt8xx_probe(struct device *dev) | |||
890 | return ret; | 889 | return ret; |
891 | } | 890 | } |
892 | 891 | ||
893 | dev_set_drvdata(dev, card); | 892 | dev_set_drvdata(&sub->dev, card); |
894 | return 0; | 893 | return 0; |
895 | } | 894 | } |
896 | 895 | ||
897 | static int dvb_bt8xx_remove(struct device *dev) | 896 | static int dvb_bt8xx_remove(struct bttv_sub_device *sub) |
898 | { | 897 | { |
899 | struct dvb_bt8xx_card *card = dev_get_drvdata(dev); | 898 | struct dvb_bt8xx_card *card = dev_get_drvdata(&sub->dev); |
900 | 899 | ||
901 | dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr); | 900 | dprintk("dvb_bt8xx: unloading card%d\n", card->bttv_nr); |
902 | 901 | ||
@@ -919,14 +918,14 @@ static int dvb_bt8xx_remove(struct device *dev) | |||
919 | static struct bttv_sub_driver driver = { | 918 | static struct bttv_sub_driver driver = { |
920 | .drv = { | 919 | .drv = { |
921 | .name = "dvb-bt8xx", | 920 | .name = "dvb-bt8xx", |
922 | .probe = dvb_bt8xx_probe, | ||
923 | .remove = dvb_bt8xx_remove, | ||
924 | /* FIXME: | ||
925 | * .shutdown = dvb_bt8xx_shutdown, | ||
926 | * .suspend = dvb_bt8xx_suspend, | ||
927 | * .resume = dvb_bt8xx_resume, | ||
928 | */ | ||
929 | }, | 921 | }, |
922 | .probe = dvb_bt8xx_probe, | ||
923 | .remove = dvb_bt8xx_remove, | ||
924 | /* FIXME: | ||
925 | * .shutdown = dvb_bt8xx_shutdown, | ||
926 | * .suspend = dvb_bt8xx_suspend, | ||
927 | * .resume = dvb_bt8xx_resume, | ||
928 | */ | ||
930 | }; | 929 | }; |
931 | 930 | ||
932 | static int __init dvb_bt8xx_init(void) | 931 | static int __init dvb_bt8xx_init(void) |
diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c index d64accc17b0e..c4d5e2b70c28 100644 --- a/drivers/media/video/bttv-gpio.c +++ b/drivers/media/video/bttv-gpio.c | |||
@@ -47,9 +47,29 @@ static int bttv_sub_bus_match(struct device *dev, struct device_driver *drv) | |||
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
49 | 49 | ||
50 | static int bttv_sub_probe(struct device *dev) | ||
51 | { | ||
52 | struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); | ||
53 | struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); | ||
54 | |||
55 | return sub->probe ? sub->probe(sdev) : -ENODEV; | ||
56 | } | ||
57 | |||
58 | static int bttv_sub_remove(struct device *dev) | ||
59 | { | ||
60 | struct bttv_sub_device *sdev = to_bttv_sub_dev(dev); | ||
61 | struct bttv_sub_driver *sub = to_bttv_sub_drv(dev->driver); | ||
62 | |||
63 | if (sub->remove) | ||
64 | sub->remove(sdev); | ||
65 | return 0; | ||
66 | } | ||
67 | |||
50 | struct bus_type bttv_sub_bus_type = { | 68 | struct bus_type bttv_sub_bus_type = { |
51 | .name = "bttv-sub", | 69 | .name = "bttv-sub", |
52 | .match = &bttv_sub_bus_match, | 70 | .match = &bttv_sub_bus_match, |
71 | .probe = bttv_sub_probe, | ||
72 | .remove = bttv_sub_remove, | ||
53 | }; | 73 | }; |
54 | EXPORT_SYMBOL(bttv_sub_bus_type); | 74 | EXPORT_SYMBOL(bttv_sub_bus_type); |
55 | 75 | ||
diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index e370d74f2a1b..9908c8e0c951 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h | |||
@@ -365,6 +365,8 @@ struct bttv_sub_device { | |||
365 | struct bttv_sub_driver { | 365 | struct bttv_sub_driver { |
366 | struct device_driver drv; | 366 | struct device_driver drv; |
367 | char wanted[BUS_ID_SIZE]; | 367 | char wanted[BUS_ID_SIZE]; |
368 | int (*probe)(struct bttv_sub_device *sub); | ||
369 | void (*remove)(struct bttv_sub_device *sub); | ||
368 | void (*gpio_irq)(struct bttv_sub_device *sub); | 370 | void (*gpio_irq)(struct bttv_sub_device *sub); |
369 | }; | 371 | }; |
370 | #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) | 372 | #define to_bttv_sub_drv(x) container_of((x), struct bttv_sub_driver, drv) |
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index 55ba23075c90..75f401d52fda 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c | |||
@@ -77,6 +77,8 @@ static int mcp_bus_resume(struct device *dev) | |||
77 | static struct bus_type mcp_bus_type = { | 77 | static struct bus_type mcp_bus_type = { |
78 | .name = "mcp", | 78 | .name = "mcp", |
79 | .match = mcp_bus_match, | 79 | .match = mcp_bus_match, |
80 | .probe = mcp_bus_probe, | ||
81 | .remove = mcp_bus_remove, | ||
80 | .suspend = mcp_bus_suspend, | 82 | .suspend = mcp_bus_suspend, |
81 | .resume = mcp_bus_resume, | 83 | .resume = mcp_bus_resume, |
82 | }; | 84 | }; |
@@ -227,8 +229,6 @@ EXPORT_SYMBOL(mcp_host_unregister); | |||
227 | int mcp_driver_register(struct mcp_driver *mcpdrv) | 229 | int mcp_driver_register(struct mcp_driver *mcpdrv) |
228 | { | 230 | { |
229 | mcpdrv->drv.bus = &mcp_bus_type; | 231 | mcpdrv->drv.bus = &mcp_bus_type; |
230 | mcpdrv->drv.probe = mcp_bus_probe; | ||
231 | mcpdrv->drv.remove = mcp_bus_remove; | ||
232 | return driver_register(&mcpdrv->drv); | 232 | return driver_register(&mcpdrv->drv); |
233 | } | 233 | } |
234 | EXPORT_SYMBOL(mcp_driver_register); | 234 | EXPORT_SYMBOL(mcp_driver_register); |
diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index b42e0fbab59b..aff83f966803 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c | |||
@@ -24,13 +24,14 @@ | |||
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
27 | #include <linux/mutex.h> | ||
27 | 28 | ||
28 | #include <asm/dma.h> | 29 | #include <asm/dma.h> |
29 | #include <asm/hardware.h> | 30 | #include <asm/hardware.h> |
30 | 31 | ||
31 | #include "ucb1x00.h" | 32 | #include "ucb1x00.h" |
32 | 33 | ||
33 | static DECLARE_MUTEX(ucb1x00_sem); | 34 | static DEFINE_MUTEX(ucb1x00_mutex); |
34 | static LIST_HEAD(ucb1x00_drivers); | 35 | static LIST_HEAD(ucb1x00_drivers); |
35 | static LIST_HEAD(ucb1x00_devices); | 36 | static LIST_HEAD(ucb1x00_devices); |
36 | 37 | ||
@@ -521,12 +522,12 @@ static int ucb1x00_probe(struct mcp *mcp) | |||
521 | goto err_irq; | 522 | goto err_irq; |
522 | 523 | ||
523 | INIT_LIST_HEAD(&ucb->devs); | 524 | INIT_LIST_HEAD(&ucb->devs); |
524 | down(&ucb1x00_sem); | 525 | mutex_lock(&ucb1x00_mutex); |
525 | list_add(&ucb->node, &ucb1x00_devices); | 526 | list_add(&ucb->node, &ucb1x00_devices); |
526 | list_for_each_entry(drv, &ucb1x00_drivers, node) { | 527 | list_for_each_entry(drv, &ucb1x00_drivers, node) { |
527 | ucb1x00_add_dev(ucb, drv); | 528 | ucb1x00_add_dev(ucb, drv); |
528 | } | 529 | } |
529 | up(&ucb1x00_sem); | 530 | mutex_unlock(&ucb1x00_mutex); |
530 | goto out; | 531 | goto out; |
531 | 532 | ||
532 | err_irq: | 533 | err_irq: |
@@ -544,13 +545,13 @@ static void ucb1x00_remove(struct mcp *mcp) | |||
544 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); | 545 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); |
545 | struct list_head *l, *n; | 546 | struct list_head *l, *n; |
546 | 547 | ||
547 | down(&ucb1x00_sem); | 548 | mutex_lock(&ucb1x00_mutex); |
548 | list_del(&ucb->node); | 549 | list_del(&ucb->node); |
549 | list_for_each_safe(l, n, &ucb->devs) { | 550 | list_for_each_safe(l, n, &ucb->devs) { |
550 | struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, dev_node); | 551 | struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, dev_node); |
551 | ucb1x00_remove_dev(dev); | 552 | ucb1x00_remove_dev(dev); |
552 | } | 553 | } |
553 | up(&ucb1x00_sem); | 554 | mutex_unlock(&ucb1x00_mutex); |
554 | 555 | ||
555 | free_irq(ucb->irq, ucb); | 556 | free_irq(ucb->irq, ucb); |
556 | class_device_unregister(&ucb->cdev); | 557 | class_device_unregister(&ucb->cdev); |
@@ -561,12 +562,12 @@ int ucb1x00_register_driver(struct ucb1x00_driver *drv) | |||
561 | struct ucb1x00 *ucb; | 562 | struct ucb1x00 *ucb; |
562 | 563 | ||
563 | INIT_LIST_HEAD(&drv->devs); | 564 | INIT_LIST_HEAD(&drv->devs); |
564 | down(&ucb1x00_sem); | 565 | mutex_lock(&ucb1x00_mutex); |
565 | list_add(&drv->node, &ucb1x00_drivers); | 566 | list_add(&drv->node, &ucb1x00_drivers); |
566 | list_for_each_entry(ucb, &ucb1x00_devices, node) { | 567 | list_for_each_entry(ucb, &ucb1x00_devices, node) { |
567 | ucb1x00_add_dev(ucb, drv); | 568 | ucb1x00_add_dev(ucb, drv); |
568 | } | 569 | } |
569 | up(&ucb1x00_sem); | 570 | mutex_unlock(&ucb1x00_mutex); |
570 | return 0; | 571 | return 0; |
571 | } | 572 | } |
572 | 573 | ||
@@ -574,13 +575,13 @@ void ucb1x00_unregister_driver(struct ucb1x00_driver *drv) | |||
574 | { | 575 | { |
575 | struct list_head *n, *l; | 576 | struct list_head *n, *l; |
576 | 577 | ||
577 | down(&ucb1x00_sem); | 578 | mutex_lock(&ucb1x00_mutex); |
578 | list_del(&drv->node); | 579 | list_del(&drv->node); |
579 | list_for_each_safe(l, n, &drv->devs) { | 580 | list_for_each_safe(l, n, &drv->devs) { |
580 | struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, drv_node); | 581 | struct ucb1x00_dev *dev = list_entry(l, struct ucb1x00_dev, drv_node); |
581 | ucb1x00_remove_dev(dev); | 582 | ucb1x00_remove_dev(dev); |
582 | } | 583 | } |
583 | up(&ucb1x00_sem); | 584 | mutex_unlock(&ucb1x00_mutex); |
584 | } | 585 | } |
585 | 586 | ||
586 | static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state) | 587 | static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state) |
@@ -588,12 +589,12 @@ static int ucb1x00_suspend(struct mcp *mcp, pm_message_t state) | |||
588 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); | 589 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); |
589 | struct ucb1x00_dev *dev; | 590 | struct ucb1x00_dev *dev; |
590 | 591 | ||
591 | down(&ucb1x00_sem); | 592 | mutex_lock(&ucb1x00_mutex); |
592 | list_for_each_entry(dev, &ucb->devs, dev_node) { | 593 | list_for_each_entry(dev, &ucb->devs, dev_node) { |
593 | if (dev->drv->suspend) | 594 | if (dev->drv->suspend) |
594 | dev->drv->suspend(dev, state); | 595 | dev->drv->suspend(dev, state); |
595 | } | 596 | } |
596 | up(&ucb1x00_sem); | 597 | mutex_unlock(&ucb1x00_mutex); |
597 | return 0; | 598 | return 0; |
598 | } | 599 | } |
599 | 600 | ||
@@ -602,12 +603,12 @@ static int ucb1x00_resume(struct mcp *mcp) | |||
602 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); | 603 | struct ucb1x00 *ucb = mcp_get_drvdata(mcp); |
603 | struct ucb1x00_dev *dev; | 604 | struct ucb1x00_dev *dev; |
604 | 605 | ||
605 | down(&ucb1x00_sem); | 606 | mutex_lock(&ucb1x00_mutex); |
606 | list_for_each_entry(dev, &ucb->devs, dev_node) { | 607 | list_for_each_entry(dev, &ucb->devs, dev_node) { |
607 | if (dev->drv->resume) | 608 | if (dev->drv->resume) |
608 | dev->drv->resume(dev); | 609 | dev->drv->resume(dev); |
609 | } | 610 | } |
610 | up(&ucb1x00_sem); | 611 | mutex_unlock(&ucb1x00_mutex); |
611 | return 0; | 612 | return 0; |
612 | } | 613 | } |
613 | 614 | ||
diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index f2c42b13945d..9b7c37e0e574 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/kdev_t.h> | 28 | #include <linux/kdev_t.h> |
29 | #include <linux/blkdev.h> | 29 | #include <linux/blkdev.h> |
30 | #include <linux/devfs_fs_kernel.h> | 30 | #include <linux/devfs_fs_kernel.h> |
31 | #include <linux/mutex.h> | ||
31 | 32 | ||
32 | #include <linux/mmc/card.h> | 33 | #include <linux/mmc/card.h> |
33 | #include <linux/mmc/protocol.h> | 34 | #include <linux/mmc/protocol.h> |
@@ -57,33 +58,33 @@ struct mmc_blk_data { | |||
57 | unsigned int read_only; | 58 | unsigned int read_only; |
58 | }; | 59 | }; |
59 | 60 | ||
60 | static DECLARE_MUTEX(open_lock); | 61 | static DEFINE_MUTEX(open_lock); |
61 | 62 | ||
62 | static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) | 63 | static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) |
63 | { | 64 | { |
64 | struct mmc_blk_data *md; | 65 | struct mmc_blk_data *md; |
65 | 66 | ||
66 | down(&open_lock); | 67 | mutex_lock(&open_lock); |
67 | md = disk->private_data; | 68 | md = disk->private_data; |
68 | if (md && md->usage == 0) | 69 | if (md && md->usage == 0) |
69 | md = NULL; | 70 | md = NULL; |
70 | if (md) | 71 | if (md) |
71 | md->usage++; | 72 | md->usage++; |
72 | up(&open_lock); | 73 | mutex_unlock(&open_lock); |
73 | 74 | ||
74 | return md; | 75 | return md; |
75 | } | 76 | } |
76 | 77 | ||
77 | static void mmc_blk_put(struct mmc_blk_data *md) | 78 | static void mmc_blk_put(struct mmc_blk_data *md) |
78 | { | 79 | { |
79 | down(&open_lock); | 80 | mutex_lock(&open_lock); |
80 | md->usage--; | 81 | md->usage--; |
81 | if (md->usage == 0) { | 82 | if (md->usage == 0) { |
82 | put_disk(md->disk); | 83 | put_disk(md->disk); |
83 | mmc_cleanup_queue(&md->queue); | 84 | mmc_cleanup_queue(&md->queue); |
84 | kfree(md); | 85 | kfree(md); |
85 | } | 86 | } |
86 | up(&open_lock); | 87 | mutex_unlock(&open_lock); |
87 | } | 88 | } |
88 | 89 | ||
89 | static int mmc_blk_open(struct inode *inode, struct file *filp) | 90 | static int mmc_blk_open(struct inode *inode, struct file *filp) |
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c index ec701667abfc..a2a35fd946ee 100644 --- a/drivers/mmc/mmc_sysfs.c +++ b/drivers/mmc/mmc_sysfs.c | |||
@@ -136,17 +136,7 @@ static int mmc_bus_resume(struct device *dev) | |||
136 | return ret; | 136 | return ret; |
137 | } | 137 | } |
138 | 138 | ||
139 | static struct bus_type mmc_bus_type = { | 139 | static int mmc_bus_probe(struct device *dev) |
140 | .name = "mmc", | ||
141 | .dev_attrs = mmc_dev_attrs, | ||
142 | .match = mmc_bus_match, | ||
143 | .uevent = mmc_bus_uevent, | ||
144 | .suspend = mmc_bus_suspend, | ||
145 | .resume = mmc_bus_resume, | ||
146 | }; | ||
147 | |||
148 | |||
149 | static int mmc_drv_probe(struct device *dev) | ||
150 | { | 140 | { |
151 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 141 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
152 | struct mmc_card *card = dev_to_mmc_card(dev); | 142 | struct mmc_card *card = dev_to_mmc_card(dev); |
@@ -154,7 +144,7 @@ static int mmc_drv_probe(struct device *dev) | |||
154 | return drv->probe(card); | 144 | return drv->probe(card); |
155 | } | 145 | } |
156 | 146 | ||
157 | static int mmc_drv_remove(struct device *dev) | 147 | static int mmc_bus_remove(struct device *dev) |
158 | { | 148 | { |
159 | struct mmc_driver *drv = to_mmc_driver(dev->driver); | 149 | struct mmc_driver *drv = to_mmc_driver(dev->driver); |
160 | struct mmc_card *card = dev_to_mmc_card(dev); | 150 | struct mmc_card *card = dev_to_mmc_card(dev); |
@@ -164,6 +154,16 @@ static int mmc_drv_remove(struct device *dev) | |||
164 | return 0; | 154 | return 0; |
165 | } | 155 | } |
166 | 156 | ||
157 | static struct bus_type mmc_bus_type = { | ||
158 | .name = "mmc", | ||
159 | .dev_attrs = mmc_dev_attrs, | ||
160 | .match = mmc_bus_match, | ||
161 | .uevent = mmc_bus_uevent, | ||
162 | .probe = mmc_bus_probe, | ||
163 | .remove = mmc_bus_remove, | ||
164 | .suspend = mmc_bus_suspend, | ||
165 | .resume = mmc_bus_resume, | ||
166 | }; | ||
167 | 167 | ||
168 | /** | 168 | /** |
169 | * mmc_register_driver - register a media driver | 169 | * mmc_register_driver - register a media driver |
@@ -172,8 +172,6 @@ static int mmc_drv_remove(struct device *dev) | |||
172 | int mmc_register_driver(struct mmc_driver *drv) | 172 | int mmc_register_driver(struct mmc_driver *drv) |
173 | { | 173 | { |
174 | drv->drv.bus = &mmc_bus_type; | 174 | drv->drv.bus = &mmc_bus_type; |
175 | drv->drv.probe = mmc_drv_probe; | ||
176 | drv->drv.remove = mmc_drv_remove; | ||
177 | return driver_register(&drv->drv); | 175 | return driver_register(&drv->drv); |
178 | } | 176 | } |
179 | 177 | ||
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 9a2aa4033c6a..5038e90ceb12 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
@@ -47,6 +47,22 @@ config MTD_MS02NV | |||
47 | accelerator. Say Y here if you have a DECstation 5000/2x0 or a | 47 | accelerator. Say Y here if you have a DECstation 5000/2x0 or a |
48 | DECsystem 5900 equipped with such a module. | 48 | DECsystem 5900 equipped with such a module. |
49 | 49 | ||
50 | config MTD_DATAFLASH | ||
51 | tristate "Support for AT45xxx DataFlash" | ||
52 | depends on MTD && SPI_MASTER && EXPERIMENTAL | ||
53 | help | ||
54 | This enables access to AT45xxx DataFlash chips, using SPI. | ||
55 | Sometimes DataFlash chips are packaged inside MMC-format | ||
56 | cards; at this writing, the MMC stack won't handle those. | ||
57 | |||
58 | config MTD_M25P80 | ||
59 | tristate "Support for M25 SPI Flash" | ||
60 | depends on MTD && SPI_MASTER && EXPERIMENTAL | ||
61 | help | ||
62 | This enables access to ST M25P80 and similar SPI flash chips, | ||
63 | used for program and data storage. Set up your spi devices | ||
64 | with the right board-specific platform data. | ||
65 | |||
50 | config MTD_SLRAM | 66 | config MTD_SLRAM |
51 | tristate "Uncached system RAM" | 67 | tristate "Uncached system RAM" |
52 | depends on MTD | 68 | depends on MTD |
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index e38db348057d..7c5ed2178380 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile | |||
@@ -23,3 +23,5 @@ obj-$(CONFIG_MTD_MTDRAM) += mtdram.o | |||
23 | obj-$(CONFIG_MTD_LART) += lart.o | 23 | obj-$(CONFIG_MTD_LART) += lart.o |
24 | obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o | 24 | obj-$(CONFIG_MTD_BLKMTD) += blkmtd.o |
25 | obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o | 25 | obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o |
26 | obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o | ||
27 | obj-$(CONFIG_MTD_M25P80) += m25p80.o | ||
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c new file mode 100644 index 000000000000..d5f24089be71 --- /dev/null +++ b/drivers/mtd/devices/m25p80.c | |||
@@ -0,0 +1,582 @@ | |||
1 | /* | ||
2 | * MTD SPI driver for ST M25Pxx flash chips | ||
3 | * | ||
4 | * Author: Mike Lavender, mike@steroidmicros.com | ||
5 | * | ||
6 | * Copyright (c) 2005, Intec Automation Inc. | ||
7 | * | ||
8 | * Some parts are based on lart.c by Abraham Van Der Merwe | ||
9 | * | ||
10 | * Cleaned up and generalized based on mtd_dataflash.c | ||
11 | * | ||
12 | * This code is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License version 2 as | ||
14 | * published by the Free Software Foundation. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/mtd/mtd.h> | ||
24 | #include <linux/mtd/partitions.h> | ||
25 | #include <linux/spi/spi.h> | ||
26 | #include <linux/spi/flash.h> | ||
27 | |||
28 | #include <asm/semaphore.h> | ||
29 | |||
30 | |||
31 | /* NOTE: AT 25F and SST 25LF series are very similar, | ||
32 | * but commands for sector erase and chip id differ... | ||
33 | */ | ||
34 | |||
35 | #define FLASH_PAGESIZE 256 | ||
36 | |||
37 | /* Flash opcodes. */ | ||
38 | #define OPCODE_WREN 6 /* Write enable */ | ||
39 | #define OPCODE_RDSR 5 /* Read status register */ | ||
40 | #define OPCODE_READ 3 /* Read data bytes */ | ||
41 | #define OPCODE_PP 2 /* Page program */ | ||
42 | #define OPCODE_SE 0xd8 /* Sector erase */ | ||
43 | #define OPCODE_RES 0xab /* Read Electronic Signature */ | ||
44 | #define OPCODE_RDID 0x9f /* Read JEDEC ID */ | ||
45 | |||
46 | /* Status Register bits. */ | ||
47 | #define SR_WIP 1 /* Write in progress */ | ||
48 | #define SR_WEL 2 /* Write enable latch */ | ||
49 | #define SR_BP0 4 /* Block protect 0 */ | ||
50 | #define SR_BP1 8 /* Block protect 1 */ | ||
51 | #define SR_BP2 0x10 /* Block protect 2 */ | ||
52 | #define SR_SRWD 0x80 /* SR write protect */ | ||
53 | |||
54 | /* Define max times to check status register before we give up. */ | ||
55 | #define MAX_READY_WAIT_COUNT 100000 | ||
56 | |||
57 | |||
58 | #ifdef CONFIG_MTD_PARTITIONS | ||
59 | #define mtd_has_partitions() (1) | ||
60 | #else | ||
61 | #define mtd_has_partitions() (0) | ||
62 | #endif | ||
63 | |||
64 | /****************************************************************************/ | ||
65 | |||
66 | struct m25p { | ||
67 | struct spi_device *spi; | ||
68 | struct semaphore lock; | ||
69 | struct mtd_info mtd; | ||
70 | unsigned partitioned; | ||
71 | u8 command[4]; | ||
72 | }; | ||
73 | |||
74 | static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) | ||
75 | { | ||
76 | return container_of(mtd, struct m25p, mtd); | ||
77 | } | ||
78 | |||
79 | /****************************************************************************/ | ||
80 | |||
81 | /* | ||
82 | * Internal helper functions | ||
83 | */ | ||
84 | |||
85 | /* | ||
86 | * Read the status register, returning its value in the location | ||
87 | * Return the status register value. | ||
88 | * Returns negative if error occurred. | ||
89 | */ | ||
90 | static int read_sr(struct m25p *flash) | ||
91 | { | ||
92 | ssize_t retval; | ||
93 | u8 code = OPCODE_RDSR; | ||
94 | u8 val; | ||
95 | |||
96 | retval = spi_write_then_read(flash->spi, &code, 1, &val, 1); | ||
97 | |||
98 | if (retval < 0) { | ||
99 | dev_err(&flash->spi->dev, "error %d reading SR\n", | ||
100 | (int) retval); | ||
101 | return retval; | ||
102 | } | ||
103 | |||
104 | return val; | ||
105 | } | ||
106 | |||
107 | |||
108 | /* | ||
109 | * Set write enable latch with Write Enable command. | ||
110 | * Returns negative if error occurred. | ||
111 | */ | ||
112 | static inline int write_enable(struct m25p *flash) | ||
113 | { | ||
114 | u8 code = OPCODE_WREN; | ||
115 | |||
116 | return spi_write_then_read(flash->spi, &code, 1, NULL, 0); | ||
117 | } | ||
118 | |||
119 | |||
120 | /* | ||
121 | * Service routine to read status register until ready, or timeout occurs. | ||
122 | * Returns non-zero if error. | ||
123 | */ | ||
124 | static int wait_till_ready(struct m25p *flash) | ||
125 | { | ||
126 | int count; | ||
127 | int sr; | ||
128 | |||
129 | /* one chip guarantees max 5 msec wait here after page writes, | ||
130 | * but potentially three seconds (!) after page erase. | ||
131 | */ | ||
132 | for (count = 0; count < MAX_READY_WAIT_COUNT; count++) { | ||
133 | if ((sr = read_sr(flash)) < 0) | ||
134 | break; | ||
135 | else if (!(sr & SR_WIP)) | ||
136 | return 0; | ||
137 | |||
138 | /* REVISIT sometimes sleeping would be best */ | ||
139 | } | ||
140 | |||
141 | return 1; | ||
142 | } | ||
143 | |||
144 | |||
145 | /* | ||
146 | * Erase one sector of flash memory at offset ``offset'' which is any | ||
147 | * address within the sector which should be erased. | ||
148 | * | ||
149 | * Returns 0 if successful, non-zero otherwise. | ||
150 | */ | ||
151 | static int erase_sector(struct m25p *flash, u32 offset) | ||
152 | { | ||
153 | DEBUG(MTD_DEBUG_LEVEL3, "%s: %s at 0x%08x\n", flash->spi->dev.bus_id, | ||
154 | __FUNCTION__, offset); | ||
155 | |||
156 | /* Wait until finished previous write command. */ | ||
157 | if (wait_till_ready(flash)) | ||
158 | return 1; | ||
159 | |||
160 | /* Send write enable, then erase commands. */ | ||
161 | write_enable(flash); | ||
162 | |||
163 | /* Set up command buffer. */ | ||
164 | flash->command[0] = OPCODE_SE; | ||
165 | flash->command[1] = offset >> 16; | ||
166 | flash->command[2] = offset >> 8; | ||
167 | flash->command[3] = offset; | ||
168 | |||
169 | spi_write(flash->spi, flash->command, sizeof(flash->command)); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | /****************************************************************************/ | ||
175 | |||
176 | /* | ||
177 | * MTD implementation | ||
178 | */ | ||
179 | |||
180 | /* | ||
181 | * Erase an address range on the flash chip. The address range may extend | ||
182 | * one or more erase sectors. Return an error is there is a problem erasing. | ||
183 | */ | ||
184 | static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) | ||
185 | { | ||
186 | struct m25p *flash = mtd_to_m25p(mtd); | ||
187 | u32 addr,len; | ||
188 | |||
189 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | ||
190 | flash->spi->dev.bus_id, __FUNCTION__, "at", | ||
191 | (u32)instr->addr, instr->len); | ||
192 | |||
193 | /* sanity checks */ | ||
194 | if (instr->addr + instr->len > flash->mtd.size) | ||
195 | return -EINVAL; | ||
196 | if ((instr->addr % mtd->erasesize) != 0 | ||
197 | || (instr->len % mtd->erasesize) != 0) { | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | |||
201 | addr = instr->addr; | ||
202 | len = instr->len; | ||
203 | |||
204 | down(&flash->lock); | ||
205 | |||
206 | /* now erase those sectors */ | ||
207 | while (len) { | ||
208 | if (erase_sector(flash, addr)) { | ||
209 | instr->state = MTD_ERASE_FAILED; | ||
210 | up(&flash->lock); | ||
211 | return -EIO; | ||
212 | } | ||
213 | |||
214 | addr += mtd->erasesize; | ||
215 | len -= mtd->erasesize; | ||
216 | } | ||
217 | |||
218 | up(&flash->lock); | ||
219 | |||
220 | instr->state = MTD_ERASE_DONE; | ||
221 | mtd_erase_callback(instr); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * Read an address range from the flash chip. The address range | ||
228 | * may be any size provided it is within the physical boundaries. | ||
229 | */ | ||
230 | static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
231 | size_t *retlen, u_char *buf) | ||
232 | { | ||
233 | struct m25p *flash = mtd_to_m25p(mtd); | ||
234 | struct spi_transfer t[2]; | ||
235 | struct spi_message m; | ||
236 | |||
237 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | ||
238 | flash->spi->dev.bus_id, __FUNCTION__, "from", | ||
239 | (u32)from, len); | ||
240 | |||
241 | /* sanity checks */ | ||
242 | if (!len) | ||
243 | return 0; | ||
244 | |||
245 | if (from + len > flash->mtd.size) | ||
246 | return -EINVAL; | ||
247 | |||
248 | spi_message_init(&m); | ||
249 | memset(t, 0, (sizeof t)); | ||
250 | |||
251 | t[0].tx_buf = flash->command; | ||
252 | t[0].len = sizeof(flash->command); | ||
253 | spi_message_add_tail(&t[0], &m); | ||
254 | |||
255 | t[1].rx_buf = buf; | ||
256 | t[1].len = len; | ||
257 | spi_message_add_tail(&t[1], &m); | ||
258 | |||
259 | /* Byte count starts at zero. */ | ||
260 | if (retlen) | ||
261 | *retlen = 0; | ||
262 | |||
263 | down(&flash->lock); | ||
264 | |||
265 | /* Wait till previous write/erase is done. */ | ||
266 | if (wait_till_ready(flash)) { | ||
267 | /* REVISIT status return?? */ | ||
268 | up(&flash->lock); | ||
269 | return 1; | ||
270 | } | ||
271 | |||
272 | /* NOTE: OPCODE_FAST_READ (if available) is faster... */ | ||
273 | |||
274 | /* Set up the write data buffer. */ | ||
275 | flash->command[0] = OPCODE_READ; | ||
276 | flash->command[1] = from >> 16; | ||
277 | flash->command[2] = from >> 8; | ||
278 | flash->command[3] = from; | ||
279 | |||
280 | spi_sync(flash->spi, &m); | ||
281 | |||
282 | *retlen = m.actual_length - sizeof(flash->command); | ||
283 | |||
284 | up(&flash->lock); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * Write an address range to the flash chip. Data must be written in | ||
291 | * FLASH_PAGESIZE chunks. The address range may be any size provided | ||
292 | * it is within the physical boundaries. | ||
293 | */ | ||
294 | static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
295 | size_t *retlen, const u_char *buf) | ||
296 | { | ||
297 | struct m25p *flash = mtd_to_m25p(mtd); | ||
298 | u32 page_offset, page_size; | ||
299 | struct spi_transfer t[2]; | ||
300 | struct spi_message m; | ||
301 | |||
302 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | ||
303 | flash->spi->dev.bus_id, __FUNCTION__, "to", | ||
304 | (u32)to, len); | ||
305 | |||
306 | if (retlen) | ||
307 | *retlen = 0; | ||
308 | |||
309 | /* sanity checks */ | ||
310 | if (!len) | ||
311 | return(0); | ||
312 | |||
313 | if (to + len > flash->mtd.size) | ||
314 | return -EINVAL; | ||
315 | |||
316 | spi_message_init(&m); | ||
317 | memset(t, 0, (sizeof t)); | ||
318 | |||
319 | t[0].tx_buf = flash->command; | ||
320 | t[0].len = sizeof(flash->command); | ||
321 | spi_message_add_tail(&t[0], &m); | ||
322 | |||
323 | t[1].tx_buf = buf; | ||
324 | spi_message_add_tail(&t[1], &m); | ||
325 | |||
326 | down(&flash->lock); | ||
327 | |||
328 | /* Wait until finished previous write command. */ | ||
329 | if (wait_till_ready(flash)) | ||
330 | return 1; | ||
331 | |||
332 | write_enable(flash); | ||
333 | |||
334 | /* Set up the opcode in the write buffer. */ | ||
335 | flash->command[0] = OPCODE_PP; | ||
336 | flash->command[1] = to >> 16; | ||
337 | flash->command[2] = to >> 8; | ||
338 | flash->command[3] = to; | ||
339 | |||
340 | /* what page do we start with? */ | ||
341 | page_offset = to % FLASH_PAGESIZE; | ||
342 | |||
343 | /* do all the bytes fit onto one page? */ | ||
344 | if (page_offset + len <= FLASH_PAGESIZE) { | ||
345 | t[1].len = len; | ||
346 | |||
347 | spi_sync(flash->spi, &m); | ||
348 | |||
349 | *retlen = m.actual_length - sizeof(flash->command); | ||
350 | } else { | ||
351 | u32 i; | ||
352 | |||
353 | /* the size of data remaining on the first page */ | ||
354 | page_size = FLASH_PAGESIZE - page_offset; | ||
355 | |||
356 | t[1].len = page_size; | ||
357 | spi_sync(flash->spi, &m); | ||
358 | |||
359 | *retlen = m.actual_length - sizeof(flash->command); | ||
360 | |||
361 | /* write everything in PAGESIZE chunks */ | ||
362 | for (i = page_size; i < len; i += page_size) { | ||
363 | page_size = len - i; | ||
364 | if (page_size > FLASH_PAGESIZE) | ||
365 | page_size = FLASH_PAGESIZE; | ||
366 | |||
367 | /* write the next page to flash */ | ||
368 | flash->command[1] = (to + i) >> 16; | ||
369 | flash->command[2] = (to + i) >> 8; | ||
370 | flash->command[3] = (to + i); | ||
371 | |||
372 | t[1].tx_buf = buf + i; | ||
373 | t[1].len = page_size; | ||
374 | |||
375 | wait_till_ready(flash); | ||
376 | |||
377 | write_enable(flash); | ||
378 | |||
379 | spi_sync(flash->spi, &m); | ||
380 | |||
381 | if (retlen) | ||
382 | *retlen += m.actual_length | ||
383 | - sizeof(flash->command); | ||
384 | } | ||
385 | } | ||
386 | |||
387 | up(&flash->lock); | ||
388 | |||
389 | return 0; | ||
390 | } | ||
391 | |||
392 | |||
393 | /****************************************************************************/ | ||
394 | |||
395 | /* | ||
396 | * SPI device driver setup and teardown | ||
397 | */ | ||
398 | |||
399 | struct flash_info { | ||
400 | char *name; | ||
401 | u8 id; | ||
402 | u16 jedec_id; | ||
403 | unsigned sector_size; | ||
404 | unsigned n_sectors; | ||
405 | }; | ||
406 | |||
407 | static struct flash_info __devinitdata m25p_data [] = { | ||
408 | /* REVISIT: fill in JEDEC ids, for parts that have them */ | ||
409 | { "m25p05", 0x05, 0x0000, 32 * 1024, 2 }, | ||
410 | { "m25p10", 0x10, 0x0000, 32 * 1024, 4 }, | ||
411 | { "m25p20", 0x11, 0x0000, 64 * 1024, 4 }, | ||
412 | { "m25p40", 0x12, 0x0000, 64 * 1024, 8 }, | ||
413 | { "m25p80", 0x13, 0x0000, 64 * 1024, 16 }, | ||
414 | { "m25p16", 0x14, 0x0000, 64 * 1024, 32 }, | ||
415 | { "m25p32", 0x15, 0x0000, 64 * 1024, 64 }, | ||
416 | { "m25p64", 0x16, 0x2017, 64 * 1024, 128 }, | ||
417 | }; | ||
418 | |||
419 | /* | ||
420 | * board specific setup should have ensured the SPI clock used here | ||
421 | * matches what the READ command supports, at least until this driver | ||
422 | * understands FAST_READ (for clocks over 25 MHz). | ||
423 | */ | ||
424 | static int __devinit m25p_probe(struct spi_device *spi) | ||
425 | { | ||
426 | struct flash_platform_data *data; | ||
427 | struct m25p *flash; | ||
428 | struct flash_info *info; | ||
429 | unsigned i; | ||
430 | |||
431 | /* Platform data helps sort out which chip type we have, as | ||
432 | * well as how this board partitions it. | ||
433 | */ | ||
434 | data = spi->dev.platform_data; | ||
435 | if (!data || !data->type) { | ||
436 | /* FIXME some chips can identify themselves with RES | ||
437 | * or JEDEC get-id commands. Try them ... | ||
438 | */ | ||
439 | DEBUG(MTD_DEBUG_LEVEL1, "%s: no chip id\n", | ||
440 | flash->spi->dev.bus_id); | ||
441 | return -ENODEV; | ||
442 | } | ||
443 | |||
444 | for (i = 0, info = m25p_data; i < ARRAY_SIZE(m25p_data); i++, info++) { | ||
445 | if (strcmp(data->type, info->name) == 0) | ||
446 | break; | ||
447 | } | ||
448 | if (i == ARRAY_SIZE(m25p_data)) { | ||
449 | DEBUG(MTD_DEBUG_LEVEL1, "%s: unrecognized id %s\n", | ||
450 | flash->spi->dev.bus_id, data->type); | ||
451 | return -ENODEV; | ||
452 | } | ||
453 | |||
454 | flash = kzalloc(sizeof *flash, SLAB_KERNEL); | ||
455 | if (!flash) | ||
456 | return -ENOMEM; | ||
457 | |||
458 | flash->spi = spi; | ||
459 | init_MUTEX(&flash->lock); | ||
460 | dev_set_drvdata(&spi->dev, flash); | ||
461 | |||
462 | if (data->name) | ||
463 | flash->mtd.name = data->name; | ||
464 | else | ||
465 | flash->mtd.name = spi->dev.bus_id; | ||
466 | |||
467 | flash->mtd.type = MTD_NORFLASH; | ||
468 | flash->mtd.flags = MTD_CAP_NORFLASH; | ||
469 | flash->mtd.size = info->sector_size * info->n_sectors; | ||
470 | flash->mtd.erasesize = info->sector_size; | ||
471 | flash->mtd.erase = m25p80_erase; | ||
472 | flash->mtd.read = m25p80_read; | ||
473 | flash->mtd.write = m25p80_write; | ||
474 | |||
475 | dev_info(&spi->dev, "%s (%d Kbytes)\n", info->name, | ||
476 | flash->mtd.size / 1024); | ||
477 | |||
478 | DEBUG(MTD_DEBUG_LEVEL2, | ||
479 | "mtd .name = %s, .size = 0x%.8x (%uM) " | ||
480 | ".erasesize = 0x%.8x (%uK) .numeraseregions = %d\n", | ||
481 | flash->mtd.name, | ||
482 | flash->mtd.size, flash->mtd.size / (1024*1024), | ||
483 | flash->mtd.erasesize, flash->mtd.erasesize / 1024, | ||
484 | flash->mtd.numeraseregions); | ||
485 | |||
486 | if (flash->mtd.numeraseregions) | ||
487 | for (i = 0; i < flash->mtd.numeraseregions; i++) | ||
488 | DEBUG(MTD_DEBUG_LEVEL2, | ||
489 | "mtd.eraseregions[%d] = { .offset = 0x%.8x, " | ||
490 | ".erasesize = 0x%.8x (%uK), " | ||
491 | ".numblocks = %d }\n", | ||
492 | i, flash->mtd.eraseregions[i].offset, | ||
493 | flash->mtd.eraseregions[i].erasesize, | ||
494 | flash->mtd.eraseregions[i].erasesize / 1024, | ||
495 | flash->mtd.eraseregions[i].numblocks); | ||
496 | |||
497 | |||
498 | /* partitions should match sector boundaries; and it may be good to | ||
499 | * use readonly partitions for writeprotected sectors (BP2..BP0). | ||
500 | */ | ||
501 | if (mtd_has_partitions()) { | ||
502 | struct mtd_partition *parts = NULL; | ||
503 | int nr_parts = 0; | ||
504 | |||
505 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
506 | static const char *part_probes[] = { "cmdlinepart", NULL, }; | ||
507 | |||
508 | nr_parts = parse_mtd_partitions(&flash->mtd, | ||
509 | part_probes, &parts, 0); | ||
510 | #endif | ||
511 | |||
512 | if (nr_parts <= 0 && data && data->parts) { | ||
513 | parts = data->parts; | ||
514 | nr_parts = data->nr_parts; | ||
515 | } | ||
516 | |||
517 | if (nr_parts > 0) { | ||
518 | for (i = 0; i < data->nr_parts; i++) { | ||
519 | DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = " | ||
520 | "{.name = %s, .offset = 0x%.8x, " | ||
521 | ".size = 0x%.8x (%uK) }\n", | ||
522 | i, data->parts[i].name, | ||
523 | data->parts[i].offset, | ||
524 | data->parts[i].size, | ||
525 | data->parts[i].size / 1024); | ||
526 | } | ||
527 | flash->partitioned = 1; | ||
528 | return add_mtd_partitions(&flash->mtd, parts, nr_parts); | ||
529 | } | ||
530 | } else if (data->nr_parts) | ||
531 | dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", | ||
532 | data->nr_parts, data->name); | ||
533 | |||
534 | return add_mtd_device(&flash->mtd) == 1 ? -ENODEV : 0; | ||
535 | } | ||
536 | |||
537 | |||
538 | static int __devexit m25p_remove(struct spi_device *spi) | ||
539 | { | ||
540 | struct m25p *flash = dev_get_drvdata(&spi->dev); | ||
541 | int status; | ||
542 | |||
543 | /* Clean up MTD stuff. */ | ||
544 | if (mtd_has_partitions() && flash->partitioned) | ||
545 | status = del_mtd_partitions(&flash->mtd); | ||
546 | else | ||
547 | status = del_mtd_device(&flash->mtd); | ||
548 | if (status == 0) | ||
549 | kfree(flash); | ||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | |||
554 | static struct spi_driver m25p80_driver = { | ||
555 | .driver = { | ||
556 | .name = "m25p80", | ||
557 | .bus = &spi_bus_type, | ||
558 | .owner = THIS_MODULE, | ||
559 | }, | ||
560 | .probe = m25p_probe, | ||
561 | .remove = __devexit_p(m25p_remove), | ||
562 | }; | ||
563 | |||
564 | |||
565 | static int m25p80_init(void) | ||
566 | { | ||
567 | return spi_register_driver(&m25p80_driver); | ||
568 | } | ||
569 | |||
570 | |||
571 | static void m25p80_exit(void) | ||
572 | { | ||
573 | spi_unregister_driver(&m25p80_driver); | ||
574 | } | ||
575 | |||
576 | |||
577 | module_init(m25p80_init); | ||
578 | module_exit(m25p80_exit); | ||
579 | |||
580 | MODULE_LICENSE("GPL"); | ||
581 | MODULE_AUTHOR("Mike Lavender"); | ||
582 | MODULE_DESCRIPTION("MTD SPI driver for ST M25Pxx flash chips"); | ||
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c new file mode 100644 index 000000000000..155737e7483f --- /dev/null +++ b/drivers/mtd/devices/mtd_dataflash.c | |||
@@ -0,0 +1,629 @@ | |||
1 | /* | ||
2 | * Atmel AT45xxx DataFlash MTD driver for lightweight SPI framework | ||
3 | * | ||
4 | * Largely derived from at91_dataflash.c: | ||
5 | * Copyright (C) 2003-2005 SAN People (Pty) Ltd | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | #include <linux/config.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/spi/spi.h> | ||
19 | #include <linux/spi/flash.h> | ||
20 | |||
21 | #include <linux/mtd/mtd.h> | ||
22 | #include <linux/mtd/partitions.h> | ||
23 | |||
24 | |||
25 | /* | ||
26 | * DataFlash is a kind of SPI flash. Most AT45 chips have two buffers in | ||
27 | * each chip, which may be used for double buffered I/O; but this driver | ||
28 | * doesn't (yet) use these for any kind of i/o overlap or prefetching. | ||
29 | * | ||
30 | * Sometimes DataFlash is packaged in MMC-format cards, although the | ||
31 | * MMC stack can't use SPI (yet), or distinguish between MMC and DataFlash | ||
32 | * protocols during enumeration. | ||
33 | */ | ||
34 | |||
35 | #define CONFIG_DATAFLASH_WRITE_VERIFY | ||
36 | |||
37 | /* reads can bypass the buffers */ | ||
38 | #define OP_READ_CONTINUOUS 0xE8 | ||
39 | #define OP_READ_PAGE 0xD2 | ||
40 | |||
41 | /* group B requests can run even while status reports "busy" */ | ||
42 | #define OP_READ_STATUS 0xD7 /* group B */ | ||
43 | |||
44 | /* move data between host and buffer */ | ||
45 | #define OP_READ_BUFFER1 0xD4 /* group B */ | ||
46 | #define OP_READ_BUFFER2 0xD6 /* group B */ | ||
47 | #define OP_WRITE_BUFFER1 0x84 /* group B */ | ||
48 | #define OP_WRITE_BUFFER2 0x87 /* group B */ | ||
49 | |||
50 | /* erasing flash */ | ||
51 | #define OP_ERASE_PAGE 0x81 | ||
52 | #define OP_ERASE_BLOCK 0x50 | ||
53 | |||
54 | /* move data between buffer and flash */ | ||
55 | #define OP_TRANSFER_BUF1 0x53 | ||
56 | #define OP_TRANSFER_BUF2 0x55 | ||
57 | #define OP_MREAD_BUFFER1 0xD4 | ||
58 | #define OP_MREAD_BUFFER2 0xD6 | ||
59 | #define OP_MWERASE_BUFFER1 0x83 | ||
60 | #define OP_MWERASE_BUFFER2 0x86 | ||
61 | #define OP_MWRITE_BUFFER1 0x88 /* sector must be pre-erased */ | ||
62 | #define OP_MWRITE_BUFFER2 0x89 /* sector must be pre-erased */ | ||
63 | |||
64 | /* write to buffer, then write-erase to flash */ | ||
65 | #define OP_PROGRAM_VIA_BUF1 0x82 | ||
66 | #define OP_PROGRAM_VIA_BUF2 0x85 | ||
67 | |||
68 | /* compare buffer to flash */ | ||
69 | #define OP_COMPARE_BUF1 0x60 | ||
70 | #define OP_COMPARE_BUF2 0x61 | ||
71 | |||
72 | /* read flash to buffer, then write-erase to flash */ | ||
73 | #define OP_REWRITE_VIA_BUF1 0x58 | ||
74 | #define OP_REWRITE_VIA_BUF2 0x59 | ||
75 | |||
76 | /* newer chips report JEDEC manufacturer and device IDs; chip | ||
77 | * serial number and OTP bits; and per-sector writeprotect. | ||
78 | */ | ||
79 | #define OP_READ_ID 0x9F | ||
80 | #define OP_READ_SECURITY 0x77 | ||
81 | #define OP_WRITE_SECURITY 0x9A /* OTP bits */ | ||
82 | |||
83 | |||
84 | struct dataflash { | ||
85 | u8 command[4]; | ||
86 | char name[24]; | ||
87 | |||
88 | unsigned partitioned:1; | ||
89 | |||
90 | unsigned short page_offset; /* offset in flash address */ | ||
91 | unsigned int page_size; /* of bytes per page */ | ||
92 | |||
93 | struct semaphore lock; | ||
94 | struct spi_device *spi; | ||
95 | |||
96 | struct mtd_info mtd; | ||
97 | }; | ||
98 | |||
99 | #ifdef CONFIG_MTD_PARTITIONS | ||
100 | #define mtd_has_partitions() (1) | ||
101 | #else | ||
102 | #define mtd_has_partitions() (0) | ||
103 | #endif | ||
104 | |||
105 | /* ......................................................................... */ | ||
106 | |||
107 | /* | ||
108 | * Return the status of the DataFlash device. | ||
109 | */ | ||
110 | static inline int dataflash_status(struct spi_device *spi) | ||
111 | { | ||
112 | /* NOTE: at45db321c over 25 MHz wants to write | ||
113 | * a dummy byte after the opcode... | ||
114 | */ | ||
115 | return spi_w8r8(spi, OP_READ_STATUS); | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Poll the DataFlash device until it is READY. | ||
120 | * This usually takes 5-20 msec or so; more for sector erase. | ||
121 | */ | ||
122 | static int dataflash_waitready(struct spi_device *spi) | ||
123 | { | ||
124 | int status; | ||
125 | |||
126 | for (;;) { | ||
127 | status = dataflash_status(spi); | ||
128 | if (status < 0) { | ||
129 | DEBUG(MTD_DEBUG_LEVEL1, "%s: status %d?\n", | ||
130 | spi->dev.bus_id, status); | ||
131 | status = 0; | ||
132 | } | ||
133 | |||
134 | if (status & (1 << 7)) /* RDY/nBSY */ | ||
135 | return status; | ||
136 | |||
137 | msleep(3); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | /* ......................................................................... */ | ||
142 | |||
143 | /* | ||
144 | * Erase pages of flash. | ||
145 | */ | ||
146 | static int dataflash_erase(struct mtd_info *mtd, struct erase_info *instr) | ||
147 | { | ||
148 | struct dataflash *priv = (struct dataflash *)mtd->priv; | ||
149 | struct spi_device *spi = priv->spi; | ||
150 | struct spi_transfer x = { .tx_dma = 0, }; | ||
151 | struct spi_message msg; | ||
152 | unsigned blocksize = priv->page_size << 3; | ||
153 | u8 *command; | ||
154 | |||
155 | DEBUG(MTD_DEBUG_LEVEL2, "%s: erase addr=0x%x len 0x%x\n", | ||
156 | spi->dev.bus_id, | ||
157 | instr->addr, instr->len); | ||
158 | |||
159 | /* Sanity checks */ | ||
160 | if ((instr->addr + instr->len) > mtd->size | ||
161 | || (instr->len % priv->page_size) != 0 | ||
162 | || (instr->addr % priv->page_size) != 0) | ||
163 | return -EINVAL; | ||
164 | |||
165 | spi_message_init(&msg); | ||
166 | |||
167 | x.tx_buf = command = priv->command; | ||
168 | x.len = 4; | ||
169 | spi_message_add_tail(&x, &msg); | ||
170 | |||
171 | down(&priv->lock); | ||
172 | while (instr->len > 0) { | ||
173 | unsigned int pageaddr; | ||
174 | int status; | ||
175 | int do_block; | ||
176 | |||
177 | /* Calculate flash page address; use block erase (for speed) if | ||
178 | * we're at a block boundary and need to erase the whole block. | ||
179 | */ | ||
180 | pageaddr = instr->addr / priv->page_size; | ||
181 | do_block = (pageaddr & 0x7) == 0 && instr->len <= blocksize; | ||
182 | pageaddr = pageaddr << priv->page_offset; | ||
183 | |||
184 | command[0] = do_block ? OP_ERASE_BLOCK : OP_ERASE_PAGE; | ||
185 | command[1] = (u8)(pageaddr >> 16); | ||
186 | command[2] = (u8)(pageaddr >> 8); | ||
187 | command[3] = 0; | ||
188 | |||
189 | DEBUG(MTD_DEBUG_LEVEL3, "ERASE %s: (%x) %x %x %x [%i]\n", | ||
190 | do_block ? "block" : "page", | ||
191 | command[0], command[1], command[2], command[3], | ||
192 | pageaddr); | ||
193 | |||
194 | status = spi_sync(spi, &msg); | ||
195 | (void) dataflash_waitready(spi); | ||
196 | |||
197 | if (status < 0) { | ||
198 | printk(KERN_ERR "%s: erase %x, err %d\n", | ||
199 | spi->dev.bus_id, pageaddr, status); | ||
200 | /* REVISIT: can retry instr->retries times; or | ||
201 | * giveup and instr->fail_addr = instr->addr; | ||
202 | */ | ||
203 | continue; | ||
204 | } | ||
205 | |||
206 | if (do_block) { | ||
207 | instr->addr += blocksize; | ||
208 | instr->len -= blocksize; | ||
209 | } else { | ||
210 | instr->addr += priv->page_size; | ||
211 | instr->len -= priv->page_size; | ||
212 | } | ||
213 | } | ||
214 | up(&priv->lock); | ||
215 | |||
216 | /* Inform MTD subsystem that erase is complete */ | ||
217 | instr->state = MTD_ERASE_DONE; | ||
218 | mtd_erase_callback(instr); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * Read from the DataFlash device. | ||
225 | * from : Start offset in flash device | ||
226 | * len : Amount to read | ||
227 | * retlen : About of data actually read | ||
228 | * buf : Buffer containing the data | ||
229 | */ | ||
230 | static int dataflash_read(struct mtd_info *mtd, loff_t from, size_t len, | ||
231 | size_t *retlen, u_char *buf) | ||
232 | { | ||
233 | struct dataflash *priv = (struct dataflash *)mtd->priv; | ||
234 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; | ||
235 | struct spi_message msg; | ||
236 | unsigned int addr; | ||
237 | u8 *command; | ||
238 | int status; | ||
239 | |||
240 | DEBUG(MTD_DEBUG_LEVEL2, "%s: read 0x%x..0x%x\n", | ||
241 | priv->spi->dev.bus_id, (unsigned)from, (unsigned)(from + len)); | ||
242 | |||
243 | *retlen = 0; | ||
244 | |||
245 | /* Sanity checks */ | ||
246 | if (!len) | ||
247 | return 0; | ||
248 | if (from + len > mtd->size) | ||
249 | return -EINVAL; | ||
250 | |||
251 | /* Calculate flash page/byte address */ | ||
252 | addr = (((unsigned)from / priv->page_size) << priv->page_offset) | ||
253 | + ((unsigned)from % priv->page_size); | ||
254 | |||
255 | command = priv->command; | ||
256 | |||
257 | DEBUG(MTD_DEBUG_LEVEL3, "READ: (%x) %x %x %x\n", | ||
258 | command[0], command[1], command[2], command[3]); | ||
259 | |||
260 | spi_message_init(&msg); | ||
261 | |||
262 | x[0].tx_buf = command; | ||
263 | x[0].len = 8; | ||
264 | spi_message_add_tail(&x[0], &msg); | ||
265 | |||
266 | x[1].rx_buf = buf; | ||
267 | x[1].len = len; | ||
268 | spi_message_add_tail(&x[1], &msg); | ||
269 | |||
270 | down(&priv->lock); | ||
271 | |||
272 | /* Continuous read, max clock = f(car) which may be less than | ||
273 | * the peak rate available. Some chips support commands with | ||
274 | * fewer "don't care" bytes. Both buffers stay unchanged. | ||
275 | */ | ||
276 | command[0] = OP_READ_CONTINUOUS; | ||
277 | command[1] = (u8)(addr >> 16); | ||
278 | command[2] = (u8)(addr >> 8); | ||
279 | command[3] = (u8)(addr >> 0); | ||
280 | /* plus 4 "don't care" bytes */ | ||
281 | |||
282 | status = spi_sync(priv->spi, &msg); | ||
283 | up(&priv->lock); | ||
284 | |||
285 | if (status >= 0) { | ||
286 | *retlen = msg.actual_length - 8; | ||
287 | status = 0; | ||
288 | } else | ||
289 | DEBUG(MTD_DEBUG_LEVEL1, "%s: read %x..%x --> %d\n", | ||
290 | priv->spi->dev.bus_id, | ||
291 | (unsigned)from, (unsigned)(from + len), | ||
292 | status); | ||
293 | return status; | ||
294 | } | ||
295 | |||
296 | /* | ||
297 | * Write to the DataFlash device. | ||
298 | * to : Start offset in flash device | ||
299 | * len : Amount to write | ||
300 | * retlen : Amount of data actually written | ||
301 | * buf : Buffer containing the data | ||
302 | */ | ||
303 | static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len, | ||
304 | size_t * retlen, const u_char * buf) | ||
305 | { | ||
306 | struct dataflash *priv = (struct dataflash *)mtd->priv; | ||
307 | struct spi_device *spi = priv->spi; | ||
308 | struct spi_transfer x[2] = { { .tx_dma = 0, }, }; | ||
309 | struct spi_message msg; | ||
310 | unsigned int pageaddr, addr, offset, writelen; | ||
311 | size_t remaining = len; | ||
312 | u_char *writebuf = (u_char *) buf; | ||
313 | int status = -EINVAL; | ||
314 | u8 *command; | ||
315 | |||
316 | DEBUG(MTD_DEBUG_LEVEL2, "%s: write 0x%x..0x%x\n", | ||
317 | spi->dev.bus_id, (unsigned)to, (unsigned)(to + len)); | ||
318 | |||
319 | *retlen = 0; | ||
320 | |||
321 | /* Sanity checks */ | ||
322 | if (!len) | ||
323 | return 0; | ||
324 | if ((to + len) > mtd->size) | ||
325 | return -EINVAL; | ||
326 | |||
327 | spi_message_init(&msg); | ||
328 | |||
329 | x[0].tx_buf = command = priv->command; | ||
330 | x[0].len = 4; | ||
331 | spi_message_add_tail(&x[0], &msg); | ||
332 | |||
333 | pageaddr = ((unsigned)to / priv->page_size); | ||
334 | offset = ((unsigned)to % priv->page_size); | ||
335 | if (offset + len > priv->page_size) | ||
336 | writelen = priv->page_size - offset; | ||
337 | else | ||
338 | writelen = len; | ||
339 | |||
340 | down(&priv->lock); | ||
341 | while (remaining > 0) { | ||
342 | DEBUG(MTD_DEBUG_LEVEL3, "write @ %i:%i len=%i\n", | ||
343 | pageaddr, offset, writelen); | ||
344 | |||
345 | /* REVISIT: | ||
346 | * (a) each page in a sector must be rewritten at least | ||
347 | * once every 10K sibling erase/program operations. | ||
348 | * (b) for pages that are already erased, we could | ||
349 | * use WRITE+MWRITE not PROGRAM for ~30% speedup. | ||
350 | * (c) WRITE to buffer could be done while waiting for | ||
351 | * a previous MWRITE/MWERASE to complete ... | ||
352 | * (d) error handling here seems to be mostly missing. | ||
353 | * | ||
354 | * Two persistent bits per page, plus a per-sector counter, | ||
355 | * could support (a) and (b) ... we might consider using | ||
356 | * the second half of sector zero, which is just one block, | ||
357 | * to track that state. (On AT91, that sector should also | ||
358 | * support boot-from-DataFlash.) | ||
359 | */ | ||
360 | |||
361 | addr = pageaddr << priv->page_offset; | ||
362 | |||
363 | /* (1) Maybe transfer partial page to Buffer1 */ | ||
364 | if (writelen != priv->page_size) { | ||
365 | command[0] = OP_TRANSFER_BUF1; | ||
366 | command[1] = (addr & 0x00FF0000) >> 16; | ||
367 | command[2] = (addr & 0x0000FF00) >> 8; | ||
368 | command[3] = 0; | ||
369 | |||
370 | DEBUG(MTD_DEBUG_LEVEL3, "TRANSFER: (%x) %x %x %x\n", | ||
371 | command[0], command[1], command[2], command[3]); | ||
372 | |||
373 | status = spi_sync(spi, &msg); | ||
374 | if (status < 0) | ||
375 | DEBUG(MTD_DEBUG_LEVEL1, "%s: xfer %u -> %d \n", | ||
376 | spi->dev.bus_id, addr, status); | ||
377 | |||
378 | (void) dataflash_waitready(priv->spi); | ||
379 | } | ||
380 | |||
381 | /* (2) Program full page via Buffer1 */ | ||
382 | addr += offset; | ||
383 | command[0] = OP_PROGRAM_VIA_BUF1; | ||
384 | command[1] = (addr & 0x00FF0000) >> 16; | ||
385 | command[2] = (addr & 0x0000FF00) >> 8; | ||
386 | command[3] = (addr & 0x000000FF); | ||
387 | |||
388 | DEBUG(MTD_DEBUG_LEVEL3, "PROGRAM: (%x) %x %x %x\n", | ||
389 | command[0], command[1], command[2], command[3]); | ||
390 | |||
391 | x[1].tx_buf = writebuf; | ||
392 | x[1].len = writelen; | ||
393 | spi_message_add_tail(x + 1, &msg); | ||
394 | status = spi_sync(spi, &msg); | ||
395 | spi_transfer_del(x + 1); | ||
396 | if (status < 0) | ||
397 | DEBUG(MTD_DEBUG_LEVEL1, "%s: pgm %u/%u -> %d \n", | ||
398 | spi->dev.bus_id, addr, writelen, status); | ||
399 | |||
400 | (void) dataflash_waitready(priv->spi); | ||
401 | |||
402 | |||
403 | #ifdef CONFIG_DATAFLASH_WRITE_VERIFY | ||
404 | |||
405 | /* (3) Compare to Buffer1 */ | ||
406 | addr = pageaddr << priv->page_offset; | ||
407 | command[0] = OP_COMPARE_BUF1; | ||
408 | command[1] = (addr & 0x00FF0000) >> 16; | ||
409 | command[2] = (addr & 0x0000FF00) >> 8; | ||
410 | command[3] = 0; | ||
411 | |||
412 | DEBUG(MTD_DEBUG_LEVEL3, "COMPARE: (%x) %x %x %x\n", | ||
413 | command[0], command[1], command[2], command[3]); | ||
414 | |||
415 | status = spi_sync(spi, &msg); | ||
416 | if (status < 0) | ||
417 | DEBUG(MTD_DEBUG_LEVEL1, "%s: compare %u -> %d \n", | ||
418 | spi->dev.bus_id, addr, status); | ||
419 | |||
420 | status = dataflash_waitready(priv->spi); | ||
421 | |||
422 | /* Check result of the compare operation */ | ||
423 | if ((status & (1 << 6)) == 1) { | ||
424 | printk(KERN_ERR "%s: compare page %u, err %d\n", | ||
425 | spi->dev.bus_id, pageaddr, status); | ||
426 | remaining = 0; | ||
427 | status = -EIO; | ||
428 | break; | ||
429 | } else | ||
430 | status = 0; | ||
431 | |||
432 | #endif /* CONFIG_DATAFLASH_WRITE_VERIFY */ | ||
433 | |||
434 | remaining = remaining - writelen; | ||
435 | pageaddr++; | ||
436 | offset = 0; | ||
437 | writebuf += writelen; | ||
438 | *retlen += writelen; | ||
439 | |||
440 | if (remaining > priv->page_size) | ||
441 | writelen = priv->page_size; | ||
442 | else | ||
443 | writelen = remaining; | ||
444 | } | ||
445 | up(&priv->lock); | ||
446 | |||
447 | return status; | ||
448 | } | ||
449 | |||
450 | /* ......................................................................... */ | ||
451 | |||
452 | /* | ||
453 | * Register DataFlash device with MTD subsystem. | ||
454 | */ | ||
455 | static int __devinit | ||
456 | add_dataflash(struct spi_device *spi, char *name, | ||
457 | int nr_pages, int pagesize, int pageoffset) | ||
458 | { | ||
459 | struct dataflash *priv; | ||
460 | struct mtd_info *device; | ||
461 | struct flash_platform_data *pdata = spi->dev.platform_data; | ||
462 | |||
463 | priv = (struct dataflash *) kzalloc(sizeof *priv, GFP_KERNEL); | ||
464 | if (!priv) | ||
465 | return -ENOMEM; | ||
466 | |||
467 | init_MUTEX(&priv->lock); | ||
468 | priv->spi = spi; | ||
469 | priv->page_size = pagesize; | ||
470 | priv->page_offset = pageoffset; | ||
471 | |||
472 | /* name must be usable with cmdlinepart */ | ||
473 | sprintf(priv->name, "spi%d.%d-%s", | ||
474 | spi->master->bus_num, spi->chip_select, | ||
475 | name); | ||
476 | |||
477 | device = &priv->mtd; | ||
478 | device->name = (pdata && pdata->name) ? pdata->name : priv->name; | ||
479 | device->size = nr_pages * pagesize; | ||
480 | device->erasesize = pagesize; | ||
481 | device->owner = THIS_MODULE; | ||
482 | device->type = MTD_DATAFLASH; | ||
483 | device->flags = MTD_CAP_NORFLASH; | ||
484 | device->erase = dataflash_erase; | ||
485 | device->read = dataflash_read; | ||
486 | device->write = dataflash_write; | ||
487 | device->priv = priv; | ||
488 | |||
489 | dev_info(&spi->dev, "%s (%d KBytes)\n", name, device->size/1024); | ||
490 | dev_set_drvdata(&spi->dev, priv); | ||
491 | |||
492 | if (mtd_has_partitions()) { | ||
493 | struct mtd_partition *parts; | ||
494 | int nr_parts = 0; | ||
495 | |||
496 | #ifdef CONFIG_MTD_CMDLINE_PARTS | ||
497 | static const char *part_probes[] = { "cmdlinepart", NULL, }; | ||
498 | |||
499 | nr_parts = parse_mtd_partitions(device, part_probes, &parts, 0); | ||
500 | #endif | ||
501 | |||
502 | if (nr_parts <= 0 && pdata && pdata->parts) { | ||
503 | parts = pdata->parts; | ||
504 | nr_parts = pdata->nr_parts; | ||
505 | } | ||
506 | |||
507 | if (nr_parts > 0) { | ||
508 | priv->partitioned = 1; | ||
509 | return add_mtd_partitions(device, parts, nr_parts); | ||
510 | } | ||
511 | } else if (pdata && pdata->nr_parts) | ||
512 | dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", | ||
513 | pdata->nr_parts, device->name); | ||
514 | |||
515 | return add_mtd_device(device) == 1 ? -ENODEV : 0; | ||
516 | } | ||
517 | |||
518 | /* | ||
519 | * Detect and initialize DataFlash device: | ||
520 | * | ||
521 | * Device Density ID code #Pages PageSize Offset | ||
522 | * AT45DB011B 1Mbit (128K) xx0011xx (0x0c) 512 264 9 | ||
523 | * AT45DB021B 2Mbit (256K) xx0101xx (0x14) 1025 264 9 | ||
524 | * AT45DB041B 4Mbit (512K) xx0111xx (0x1c) 2048 264 9 | ||
525 | * AT45DB081B 8Mbit (1M) xx1001xx (0x24) 4096 264 9 | ||
526 | * AT45DB0161B 16Mbit (2M) xx1011xx (0x2c) 4096 528 10 | ||
527 | * AT45DB0321B 32Mbit (4M) xx1101xx (0x34) 8192 528 10 | ||
528 | * AT45DB0642 64Mbit (8M) xx111xxx (0x3c) 8192 1056 11 | ||
529 | * AT45DB1282 128Mbit (16M) xx0100xx (0x10) 16384 1056 11 | ||
530 | */ | ||
531 | static int __devinit dataflash_probe(struct spi_device *spi) | ||
532 | { | ||
533 | int status; | ||
534 | |||
535 | status = dataflash_status(spi); | ||
536 | if (status <= 0 || status == 0xff) { | ||
537 | DEBUG(MTD_DEBUG_LEVEL1, "%s: status error %d\n", | ||
538 | spi->dev.bus_id, status); | ||
539 | if (status == 0xff) | ||
540 | status = -ENODEV; | ||
541 | return status; | ||
542 | } | ||
543 | |||
544 | /* if there's a device there, assume it's dataflash. | ||
545 | * board setup should have set spi->max_speed_max to | ||
546 | * match f(car) for continuous reads, mode 0 or 3. | ||
547 | */ | ||
548 | switch (status & 0x3c) { | ||
549 | case 0x0c: /* 0 0 1 1 x x */ | ||
550 | status = add_dataflash(spi, "AT45DB011B", 512, 264, 9); | ||
551 | break; | ||
552 | case 0x14: /* 0 1 0 1 x x */ | ||
553 | status = add_dataflash(spi, "AT45DB021B", 1025, 264, 9); | ||
554 | break; | ||
555 | case 0x1c: /* 0 1 1 1 x x */ | ||
556 | status = add_dataflash(spi, "AT45DB041x", 2048, 264, 9); | ||
557 | break; | ||
558 | case 0x24: /* 1 0 0 1 x x */ | ||
559 | status = add_dataflash(spi, "AT45DB081B", 4096, 264, 9); | ||
560 | break; | ||
561 | case 0x2c: /* 1 0 1 1 x x */ | ||
562 | status = add_dataflash(spi, "AT45DB161x", 4096, 528, 10); | ||
563 | break; | ||
564 | case 0x34: /* 1 1 0 1 x x */ | ||
565 | status = add_dataflash(spi, "AT45DB321x", 8192, 528, 10); | ||
566 | break; | ||
567 | case 0x38: /* 1 1 1 x x x */ | ||
568 | case 0x3c: | ||
569 | status = add_dataflash(spi, "AT45DB642x", 8192, 1056, 11); | ||
570 | break; | ||
571 | /* obsolete AT45DB1282 not (yet?) supported */ | ||
572 | default: | ||
573 | DEBUG(MTD_DEBUG_LEVEL1, "%s: unsupported device (%x)\n", | ||
574 | spi->dev.bus_id, status & 0x3c); | ||
575 | status = -ENODEV; | ||
576 | } | ||
577 | |||
578 | if (status < 0) | ||
579 | DEBUG(MTD_DEBUG_LEVEL1, "%s: add_dataflash --> %d\n", | ||
580 | spi->dev.bus_id, status); | ||
581 | |||
582 | return status; | ||
583 | } | ||
584 | |||
585 | static int __devexit dataflash_remove(struct spi_device *spi) | ||
586 | { | ||
587 | struct dataflash *flash = dev_get_drvdata(&spi->dev); | ||
588 | int status; | ||
589 | |||
590 | DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", spi->dev.bus_id); | ||
591 | |||
592 | if (mtd_has_partitions() && flash->partitioned) | ||
593 | status = del_mtd_partitions(&flash->mtd); | ||
594 | else | ||
595 | status = del_mtd_device(&flash->mtd); | ||
596 | if (status == 0) | ||
597 | kfree(flash); | ||
598 | return status; | ||
599 | } | ||
600 | |||
601 | static struct spi_driver dataflash_driver = { | ||
602 | .driver = { | ||
603 | .name = "mtd_dataflash", | ||
604 | .bus = &spi_bus_type, | ||
605 | .owner = THIS_MODULE, | ||
606 | }, | ||
607 | |||
608 | .probe = dataflash_probe, | ||
609 | .remove = __devexit_p(dataflash_remove), | ||
610 | |||
611 | /* FIXME: investigate suspend and resume... */ | ||
612 | }; | ||
613 | |||
614 | static int __init dataflash_init(void) | ||
615 | { | ||
616 | return spi_register_driver(&dataflash_driver); | ||
617 | } | ||
618 | module_init(dataflash_init); | ||
619 | |||
620 | static void __exit dataflash_exit(void) | ||
621 | { | ||
622 | spi_unregister_driver(&dataflash_driver); | ||
623 | } | ||
624 | module_exit(dataflash_exit); | ||
625 | |||
626 | |||
627 | MODULE_LICENSE("GPL"); | ||
628 | MODULE_AUTHOR("Andrew Victor, David Brownell"); | ||
629 | MODULE_DESCRIPTION("MTD DataFlash driver"); | ||
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 854ddfb90da1..f2a63186ae05 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c | |||
@@ -169,9 +169,9 @@ static void tlb_clear_slave(struct bonding *bond, struct slave *slave, int save_ | |||
169 | index = next_index; | 169 | index = next_index; |
170 | } | 170 | } |
171 | 171 | ||
172 | _unlock_tx_hashtbl(bond); | ||
173 | |||
174 | tlb_init_slave(slave); | 172 | tlb_init_slave(slave); |
173 | |||
174 | _unlock_tx_hashtbl(bond); | ||
175 | } | 175 | } |
176 | 176 | ||
177 | /* Must be called before starting the monitor timer */ | 177 | /* Must be called before starting the monitor timer */ |
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index f20bb85c1ea5..3dd78d048c3e 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h | |||
@@ -22,8 +22,8 @@ | |||
22 | #include "bond_3ad.h" | 22 | #include "bond_3ad.h" |
23 | #include "bond_alb.h" | 23 | #include "bond_alb.h" |
24 | 24 | ||
25 | #define DRV_VERSION "3.0.0" | 25 | #define DRV_VERSION "3.0.1" |
26 | #define DRV_RELDATE "November 8, 2005" | 26 | #define DRV_RELDATE "January 9, 2006" |
27 | #define DRV_NAME "bonding" | 27 | #define DRV_NAME "bonding" |
28 | #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" | 28 | #define DRV_DESCRIPTION "Ethernet Channel Bonding Driver" |
29 | 29 | ||
diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 22cd04556707..23de22631c64 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c | |||
@@ -132,6 +132,10 @@ | |||
132 | * TODO: | 132 | * TODO: |
133 | * o several entry points race with dev->close | 133 | * o several entry points race with dev->close |
134 | * o check for tx-no-resources/stop Q races with tx clean/wake Q | 134 | * o check for tx-no-resources/stop Q races with tx clean/wake Q |
135 | * | ||
136 | * FIXES: | ||
137 | * 2005/12/02 - Michael O'Donnell <Michael.ODonnell at stratus dot com> | ||
138 | * - Stratus87247: protect MDI control register manipulations | ||
135 | */ | 139 | */ |
136 | 140 | ||
137 | #include <linux/config.h> | 141 | #include <linux/config.h> |
@@ -578,6 +582,7 @@ struct nic { | |||
578 | u16 leds; | 582 | u16 leds; |
579 | u16 eeprom_wc; | 583 | u16 eeprom_wc; |
580 | u16 eeprom[256]; | 584 | u16 eeprom[256]; |
585 | spinlock_t mdio_lock; | ||
581 | }; | 586 | }; |
582 | 587 | ||
583 | static inline void e100_write_flush(struct nic *nic) | 588 | static inline void e100_write_flush(struct nic *nic) |
@@ -876,15 +881,35 @@ static u16 mdio_ctrl(struct nic *nic, u32 addr, u32 dir, u32 reg, u16 data) | |||
876 | { | 881 | { |
877 | u32 data_out = 0; | 882 | u32 data_out = 0; |
878 | unsigned int i; | 883 | unsigned int i; |
884 | unsigned long flags; | ||
879 | 885 | ||
886 | |||
887 | /* | ||
888 | * Stratus87247: we shouldn't be writing the MDI control | ||
889 | * register until the Ready bit shows True. Also, since | ||
890 | * manipulation of the MDI control registers is a multi-step | ||
891 | * procedure it should be done under lock. | ||
892 | */ | ||
893 | spin_lock_irqsave(&nic->mdio_lock, flags); | ||
894 | for (i = 100; i; --i) { | ||
895 | if (readl(&nic->csr->mdi_ctrl) & mdi_ready) | ||
896 | break; | ||
897 | udelay(20); | ||
898 | } | ||
899 | if (unlikely(!i)) { | ||
900 | printk("e100.mdio_ctrl(%s) won't go Ready\n", | ||
901 | nic->netdev->name ); | ||
902 | spin_unlock_irqrestore(&nic->mdio_lock, flags); | ||
903 | return 0; /* No way to indicate timeout error */ | ||
904 | } | ||
880 | writel((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); | 905 | writel((reg << 16) | (addr << 21) | dir | data, &nic->csr->mdi_ctrl); |
881 | 906 | ||
882 | for(i = 0; i < 100; i++) { | 907 | for (i = 0; i < 100; i++) { |
883 | udelay(20); | 908 | udelay(20); |
884 | if((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready) | 909 | if ((data_out = readl(&nic->csr->mdi_ctrl)) & mdi_ready) |
885 | break; | 910 | break; |
886 | } | 911 | } |
887 | 912 | spin_unlock_irqrestore(&nic->mdio_lock, flags); | |
888 | DPRINTK(HW, DEBUG, | 913 | DPRINTK(HW, DEBUG, |
889 | "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", | 914 | "%s:addr=%d, reg=%d, data_in=0x%04X, data_out=0x%04X\n", |
890 | dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); | 915 | dir == mdi_read ? "READ" : "WRITE", addr, reg, data, data_out); |
@@ -2562,6 +2587,7 @@ static int __devinit e100_probe(struct pci_dev *pdev, | |||
2562 | /* locks must be initialized before calling hw_reset */ | 2587 | /* locks must be initialized before calling hw_reset */ |
2563 | spin_lock_init(&nic->cb_lock); | 2588 | spin_lock_init(&nic->cb_lock); |
2564 | spin_lock_init(&nic->cmd_lock); | 2589 | spin_lock_init(&nic->cmd_lock); |
2590 | spin_lock_init(&nic->mdio_lock); | ||
2565 | 2591 | ||
2566 | /* Reset the device before pci_set_master() in case device is in some | 2592 | /* Reset the device before pci_set_master() in case device is in some |
2567 | * funky state and has an interrupt pending - hint: we don't have the | 2593 | * funky state and has an interrupt pending - hint: we don't have the |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 146f9513aea5..0c18dbd67d3b 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -84,6 +84,7 @@ | |||
84 | #include <linux/ip.h> | 84 | #include <linux/ip.h> |
85 | #include <linux/tcp.h> | 85 | #include <linux/tcp.h> |
86 | #include <linux/udp.h> | 86 | #include <linux/udp.h> |
87 | #include <linux/in.h> | ||
87 | 88 | ||
88 | #include <asm/io.h> | 89 | #include <asm/io.h> |
89 | #include <asm/irq.h> | 90 | #include <asm/irq.h> |
@@ -398,12 +399,15 @@ static int init_phy(struct net_device *dev) | |||
398 | priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? | 399 | priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? |
399 | SUPPORTED_1000baseT_Full : 0; | 400 | SUPPORTED_1000baseT_Full : 0; |
400 | struct phy_device *phydev; | 401 | struct phy_device *phydev; |
402 | char phy_id[BUS_ID_SIZE]; | ||
401 | 403 | ||
402 | priv->oldlink = 0; | 404 | priv->oldlink = 0; |
403 | priv->oldspeed = 0; | 405 | priv->oldspeed = 0; |
404 | priv->oldduplex = -1; | 406 | priv->oldduplex = -1; |
405 | 407 | ||
406 | phydev = phy_connect(dev, priv->einfo->bus_id, &adjust_link, 0); | 408 | snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id); |
409 | |||
410 | phydev = phy_connect(dev, phy_id, &adjust_link, 0); | ||
407 | 411 | ||
408 | if (IS_ERR(phydev)) { | 412 | if (IS_ERR(phydev)) { |
409 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); | 413 | printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); |
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 04a462c2a5b7..74e52fcbf806 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c | |||
@@ -128,6 +128,7 @@ int gfar_mdio_probe(struct device *dev) | |||
128 | struct gianfar_mdio_data *pdata; | 128 | struct gianfar_mdio_data *pdata; |
129 | struct gfar_mii *regs; | 129 | struct gfar_mii *regs; |
130 | struct mii_bus *new_bus; | 130 | struct mii_bus *new_bus; |
131 | struct resource *r; | ||
131 | int err = 0; | 132 | int err = 0; |
132 | 133 | ||
133 | if (NULL == dev) | 134 | if (NULL == dev) |
@@ -151,8 +152,10 @@ int gfar_mdio_probe(struct device *dev) | |||
151 | return -ENODEV; | 152 | return -ENODEV; |
152 | } | 153 | } |
153 | 154 | ||
155 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
156 | |||
154 | /* Set the PHY base address */ | 157 | /* Set the PHY base address */ |
155 | regs = (struct gfar_mii *) ioremap(pdata->paddr, | 158 | regs = (struct gfar_mii *) ioremap(r->start, |
156 | sizeof (struct gfar_mii)); | 159 | sizeof (struct gfar_mii)); |
157 | 160 | ||
158 | if (NULL == regs) { | 161 | if (NULL == regs) { |
diff --git a/drivers/net/hplance.c b/drivers/net/hplance.c index 08703d6f934c..d8410634bcaf 100644 --- a/drivers/net/hplance.c +++ b/drivers/net/hplance.c | |||
@@ -150,7 +150,7 @@ static void __init hplance_init(struct net_device *dev, struct dio_dev *d) | |||
150 | lp->lance.name = (char*)d->name; /* discards const, shut up gcc */ | 150 | lp->lance.name = (char*)d->name; /* discards const, shut up gcc */ |
151 | lp->lance.base = va; | 151 | lp->lance.base = va; |
152 | lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */ | 152 | lp->lance.init_block = (struct lance_init_block *)(va + HPLANCE_MEMOFF); /* CPU addr */ |
153 | lp->lance.lance_init_block = 0; /* LANCE addr of same RAM */ | 153 | lp->lance.lance_init_block = NULL; /* LANCE addr of same RAM */ |
154 | lp->lance.busmaster_regval = LE_C3_BSWP; /* we're bigendian */ | 154 | lp->lance.busmaster_regval = LE_C3_BSWP; /* we're bigendian */ |
155 | lp->lance.irq = d->ipl; | 155 | lp->lance.irq = d->ipl; |
156 | lp->lance.writerap = hplance_writerap; | 156 | lp->lance.writerap = hplance_writerap; |
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index 77eadf84cb2c..f0f04be989d6 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c | |||
@@ -590,9 +590,9 @@ static void veth_handle_event(struct HvLpEvent *event, struct pt_regs *regs) | |||
590 | { | 590 | { |
591 | struct veth_lpevent *veth_event = (struct veth_lpevent *)event; | 591 | struct veth_lpevent *veth_event = (struct veth_lpevent *)event; |
592 | 592 | ||
593 | if (event->xFlags.xFunction == HvLpEvent_Function_Ack) | 593 | if (hvlpevent_is_ack(event)) |
594 | veth_handle_ack(veth_event); | 594 | veth_handle_ack(veth_event); |
595 | else if (event->xFlags.xFunction == HvLpEvent_Function_Int) | 595 | else |
596 | veth_handle_int(veth_event); | 596 | veth_handle_int(veth_event); |
597 | } | 597 | } |
598 | 598 | ||
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index d8c99f038fa0..06cb460361a8 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c | |||
@@ -559,55 +559,52 @@ static void mac8390_no_reset(struct net_device *dev) | |||
559 | /* directly from daynaport.c by Alan Cox */ | 559 | /* directly from daynaport.c by Alan Cox */ |
560 | static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count) | 560 | static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count) |
561 | { | 561 | { |
562 | volatile unsigned short *ptr; | 562 | volatile unsigned char *ptr; |
563 | unsigned short *target=to; | 563 | unsigned char *target=to; |
564 | from<<=1; /* word, skip overhead */ | 564 | from<<=1; /* word, skip overhead */ |
565 | ptr=(unsigned short *)(dev->mem_start+from); | 565 | ptr=(unsigned char *)(dev->mem_start+from); |
566 | /* Leading byte? */ | 566 | /* Leading byte? */ |
567 | if (from&2) { | 567 | if (from&2) { |
568 | *((char *)target)++ = *(((char *)ptr++)-1); | 568 | *target++ = ptr[-1]; |
569 | ptr += 2; | ||
569 | count--; | 570 | count--; |
570 | } | 571 | } |
571 | while(count>=2) | 572 | while(count>=2) |
572 | { | 573 | { |
573 | *target++=*ptr++; /* Copy and */ | 574 | *(unsigned short *)target = *(unsigned short volatile *)ptr; |
574 | ptr++; /* skip cruft */ | 575 | ptr += 4; /* skip cruft */ |
576 | target += 2; | ||
575 | count-=2; | 577 | count-=2; |
576 | } | 578 | } |
577 | /* Trailing byte? */ | 579 | /* Trailing byte? */ |
578 | if(count) | 580 | if(count) |
579 | { | 581 | *target = *ptr; |
580 | /* Big endian */ | ||
581 | unsigned short v=*ptr; | ||
582 | *((char *)target)=v>>8; | ||
583 | } | ||
584 | } | 582 | } |
585 | 583 | ||
586 | static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count) | 584 | static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count) |
587 | { | 585 | { |
588 | volatile unsigned short *ptr; | 586 | volatile unsigned short *ptr; |
589 | const unsigned short *src=from; | 587 | const unsigned char *src=from; |
590 | to<<=1; /* word, skip overhead */ | 588 | to<<=1; /* word, skip overhead */ |
591 | ptr=(unsigned short *)(dev->mem_start+to); | 589 | ptr=(unsigned short *)(dev->mem_start+to); |
592 | /* Leading byte? */ | 590 | /* Leading byte? */ |
593 | if (to&2) { /* avoid a byte write (stomps on other data) */ | 591 | if (to&2) { /* avoid a byte write (stomps on other data) */ |
594 | ptr[-1] = (ptr[-1]&0xFF00)|*((unsigned char *)src)++; | 592 | ptr[-1] = (ptr[-1]&0xFF00)|*src++; |
595 | ptr++; | 593 | ptr++; |
596 | count--; | 594 | count--; |
597 | } | 595 | } |
598 | while(count>=2) | 596 | while(count>=2) |
599 | { | 597 | { |
600 | *ptr++=*src++; /* Copy and */ | 598 | *ptr++=*(unsigned short *)src; /* Copy and */ |
601 | ptr++; /* skip cruft */ | 599 | ptr++; /* skip cruft */ |
600 | src += 2; | ||
602 | count-=2; | 601 | count-=2; |
603 | } | 602 | } |
604 | /* Trailing byte? */ | 603 | /* Trailing byte? */ |
605 | if(count) | 604 | if(count) |
606 | { | 605 | { |
607 | /* Big endian */ | ||
608 | unsigned short v=*src; | ||
609 | /* card doesn't like byte writes */ | 606 | /* card doesn't like byte writes */ |
610 | *ptr=(*ptr&0x00FF)|(v&0xFF00); | 607 | *ptr=(*ptr&0x00FF)|(*src << 8); |
611 | } | 608 | } |
612 | } | 609 | } |
613 | 610 | ||
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 02940c0fef68..459443b572ce 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
@@ -81,7 +81,7 @@ int mdiobus_register(struct mii_bus *bus) | |||
81 | 81 | ||
82 | phydev->dev.parent = bus->dev; | 82 | phydev->dev.parent = bus->dev; |
83 | phydev->dev.bus = &mdio_bus_type; | 83 | phydev->dev.bus = &mdio_bus_type; |
84 | sprintf(phydev->dev.bus_id, "phy%d:%d", bus->id, i); | 84 | snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, i); |
85 | 85 | ||
86 | phydev->bus = bus; | 86 | phydev->bus = bus; |
87 | 87 | ||
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index b8686e47f899..1474b7c5ac0b 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c | |||
@@ -42,7 +42,7 @@ | |||
42 | */ | 42 | */ |
43 | void phy_print_status(struct phy_device *phydev) | 43 | void phy_print_status(struct phy_device *phydev) |
44 | { | 44 | { |
45 | pr_info("%s: Link is %s", phydev->dev.bus_id, | 45 | pr_info("PHY: %s - Link is %s", phydev->dev.bus_id, |
46 | phydev->link ? "Up" : "Down"); | 46 | phydev->link ? "Up" : "Down"); |
47 | if (phydev->link) | 47 | if (phydev->link) |
48 | printk(" - %d/%s", phydev->speed, | 48 | printk(" - %d/%s", phydev->speed, |
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c index 5c8fcd40ef4d..01bdb2334058 100644 --- a/drivers/net/sun3lance.c +++ b/drivers/net/sun3lance.c | |||
@@ -389,7 +389,7 @@ static int __init lance_probe( struct net_device *dev) | |||
389 | dev->stop = &lance_close; | 389 | dev->stop = &lance_close; |
390 | dev->get_stats = &lance_get_stats; | 390 | dev->get_stats = &lance_get_stats; |
391 | dev->set_multicast_list = &set_multicast_list; | 391 | dev->set_multicast_list = &set_multicast_list; |
392 | dev->set_mac_address = 0; | 392 | dev->set_mac_address = NULL; |
393 | // KLUDGE -- REMOVE ME | 393 | // KLUDGE -- REMOVE ME |
394 | set_bit(__LINK_STATE_PRESENT, &dev->state); | 394 | set_bit(__LINK_STATE_PRESENT, &dev->state); |
395 | 395 | ||
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c index 1a4316336256..983981666800 100644 --- a/drivers/net/tulip/uli526x.c +++ b/drivers/net/tulip/uli526x.c | |||
@@ -1689,9 +1689,9 @@ MODULE_AUTHOR("Peer Chen, peer.chen@uli.com.tw"); | |||
1689 | MODULE_DESCRIPTION("ULi M5261/M5263 fast ethernet driver"); | 1689 | MODULE_DESCRIPTION("ULi M5261/M5263 fast ethernet driver"); |
1690 | MODULE_LICENSE("GPL"); | 1690 | MODULE_LICENSE("GPL"); |
1691 | 1691 | ||
1692 | MODULE_PARM(debug, "i"); | 1692 | module_param(debug, int, 0644); |
1693 | MODULE_PARM(mode, "i"); | 1693 | module_param(mode, int, 0); |
1694 | MODULE_PARM(cr6set, "i"); | 1694 | module_param(cr6set, int, 0); |
1695 | MODULE_PARM_DESC(debug, "ULi M5261/M5263 enable debugging (0-1)"); | 1695 | MODULE_PARM_DESC(debug, "ULi M5261/M5263 enable debugging (0-1)"); |
1696 | MODULE_PARM_DESC(mode, "ULi M5261/M5263: Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA"); | 1696 | MODULE_PARM_DESC(mode, "ULi M5261/M5263: Bit 0: 10/100Mbps, bit 2: duplex, bit 8: HomePNA"); |
1697 | 1697 | ||
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index 82c6b757d306..c2d5907dc8e0 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c | |||
@@ -791,7 +791,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi | |||
791 | #endif | 791 | #endif |
792 | 792 | ||
793 | if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) { | 793 | if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) { |
794 | dev->features |= NETIF_F_HW_CSUM; | 794 | dev->features |= NETIF_F_IP_CSUM; |
795 | } | 795 | } |
796 | 796 | ||
797 | ret = register_netdev(dev); | 797 | ret = register_netdev(dev); |
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 24f7967aab67..c1a6e69f7905 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
@@ -243,7 +243,7 @@ config IPW2200_DEBUG | |||
243 | 243 | ||
244 | config AIRO | 244 | config AIRO |
245 | tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards" | 245 | tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards" |
246 | depends on NET_RADIO && ISA_DMA_API && (PCI || BROKEN) | 246 | depends on NET_RADIO && ISA_DMA_API && CRYPTO && (PCI || BROKEN) |
247 | ---help--- | 247 | ---help--- |
248 | This is the standard Linux driver to support Cisco/Aironet ISA and | 248 | This is the standard Linux driver to support Cisco/Aironet ISA and |
249 | PCI 802.11 wireless cards. | 249 | PCI 802.11 wireless cards. |
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index e4729ddf29fd..f0ccfef66445 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c | |||
@@ -1407,6 +1407,17 @@ static int atmel_close(struct net_device *dev) | |||
1407 | { | 1407 | { |
1408 | struct atmel_private *priv = netdev_priv(dev); | 1408 | struct atmel_private *priv = netdev_priv(dev); |
1409 | 1409 | ||
1410 | /* Send event to userspace that we are disassociating */ | ||
1411 | if (priv->station_state == STATION_STATE_READY) { | ||
1412 | union iwreq_data wrqu; | ||
1413 | |||
1414 | wrqu.data.length = 0; | ||
1415 | wrqu.data.flags = 0; | ||
1416 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
1417 | memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); | ||
1418 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
1419 | } | ||
1420 | |||
1410 | atmel_enter_state(priv, STATION_STATE_DOWN); | 1421 | atmel_enter_state(priv, STATION_STATE_DOWN); |
1411 | 1422 | ||
1412 | if (priv->bus_type == BUS_TYPE_PCCARD) | 1423 | if (priv->bus_type == BUS_TYPE_PCCARD) |
@@ -1780,10 +1791,10 @@ static int atmel_set_encode(struct net_device *dev, | |||
1780 | priv->wep_is_on = 1; | 1791 | priv->wep_is_on = 1; |
1781 | priv->exclude_unencrypted = 1; | 1792 | priv->exclude_unencrypted = 1; |
1782 | if (priv->wep_key_len[index] > 5) { | 1793 | if (priv->wep_key_len[index] > 5) { |
1783 | priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; | 1794 | priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; |
1784 | priv->encryption_level = 2; | 1795 | priv->encryption_level = 2; |
1785 | } else { | 1796 | } else { |
1786 | priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; | 1797 | priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; |
1787 | priv->encryption_level = 1; | 1798 | priv->encryption_level = 1; |
1788 | } | 1799 | } |
1789 | } | 1800 | } |
@@ -1853,6 +1864,181 @@ static int atmel_get_encode(struct net_device *dev, | |||
1853 | return 0; | 1864 | return 0; |
1854 | } | 1865 | } |
1855 | 1866 | ||
1867 | static int atmel_set_encodeext(struct net_device *dev, | ||
1868 | struct iw_request_info *info, | ||
1869 | union iwreq_data *wrqu, | ||
1870 | char *extra) | ||
1871 | { | ||
1872 | struct atmel_private *priv = netdev_priv(dev); | ||
1873 | struct iw_point *encoding = &wrqu->encoding; | ||
1874 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | ||
1875 | int idx, key_len; | ||
1876 | |||
1877 | /* Determine and validate the key index */ | ||
1878 | idx = encoding->flags & IW_ENCODE_INDEX; | ||
1879 | if (idx) { | ||
1880 | if (idx < 1 || idx > WEP_KEYS) | ||
1881 | return -EINVAL; | ||
1882 | idx--; | ||
1883 | } else | ||
1884 | idx = priv->default_key; | ||
1885 | |||
1886 | if ((encoding->flags & IW_ENCODE_DISABLED) || | ||
1887 | ext->alg == IW_ENCODE_ALG_NONE) { | ||
1888 | priv->wep_is_on = 0; | ||
1889 | priv->encryption_level = 0; | ||
1890 | priv->pairwise_cipher_suite = CIPHER_SUITE_NONE; | ||
1891 | } | ||
1892 | |||
1893 | if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) | ||
1894 | priv->default_key = idx; | ||
1895 | |||
1896 | /* Set the requested key */ | ||
1897 | switch (ext->alg) { | ||
1898 | case IW_ENCODE_ALG_NONE: | ||
1899 | break; | ||
1900 | case IW_ENCODE_ALG_WEP: | ||
1901 | if (ext->key_len > 5) { | ||
1902 | priv->wep_key_len[idx] = 13; | ||
1903 | priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; | ||
1904 | priv->encryption_level = 2; | ||
1905 | } else if (ext->key_len > 0) { | ||
1906 | priv->wep_key_len[idx] = 5; | ||
1907 | priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; | ||
1908 | priv->encryption_level = 1; | ||
1909 | } else { | ||
1910 | return -EINVAL; | ||
1911 | } | ||
1912 | priv->wep_is_on = 1; | ||
1913 | memset(priv->wep_keys[idx], 0, 13); | ||
1914 | key_len = min ((int)ext->key_len, priv->wep_key_len[idx]); | ||
1915 | memcpy(priv->wep_keys[idx], ext->key, key_len); | ||
1916 | break; | ||
1917 | default: | ||
1918 | return -EINVAL; | ||
1919 | } | ||
1920 | |||
1921 | return -EINPROGRESS; | ||
1922 | } | ||
1923 | |||
1924 | static int atmel_get_encodeext(struct net_device *dev, | ||
1925 | struct iw_request_info *info, | ||
1926 | union iwreq_data *wrqu, | ||
1927 | char *extra) | ||
1928 | { | ||
1929 | struct atmel_private *priv = netdev_priv(dev); | ||
1930 | struct iw_point *encoding = &wrqu->encoding; | ||
1931 | struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; | ||
1932 | int idx, max_key_len; | ||
1933 | |||
1934 | max_key_len = encoding->length - sizeof(*ext); | ||
1935 | if (max_key_len < 0) | ||
1936 | return -EINVAL; | ||
1937 | |||
1938 | idx = encoding->flags & IW_ENCODE_INDEX; | ||
1939 | if (idx) { | ||
1940 | if (idx < 1 || idx > WEP_KEYS) | ||
1941 | return -EINVAL; | ||
1942 | idx--; | ||
1943 | } else | ||
1944 | idx = priv->default_key; | ||
1945 | |||
1946 | encoding->flags = idx + 1; | ||
1947 | memset(ext, 0, sizeof(*ext)); | ||
1948 | |||
1949 | if (!priv->wep_is_on) { | ||
1950 | ext->alg = IW_ENCODE_ALG_NONE; | ||
1951 | ext->key_len = 0; | ||
1952 | encoding->flags |= IW_ENCODE_DISABLED; | ||
1953 | } else { | ||
1954 | if (priv->encryption_level > 0) | ||
1955 | ext->alg = IW_ENCODE_ALG_WEP; | ||
1956 | else | ||
1957 | return -EINVAL; | ||
1958 | |||
1959 | ext->key_len = priv->wep_key_len[idx]; | ||
1960 | memcpy(ext->key, priv->wep_keys[idx], ext->key_len); | ||
1961 | encoding->flags |= IW_ENCODE_ENABLED; | ||
1962 | } | ||
1963 | |||
1964 | return 0; | ||
1965 | } | ||
1966 | |||
1967 | static int atmel_set_auth(struct net_device *dev, | ||
1968 | struct iw_request_info *info, | ||
1969 | union iwreq_data *wrqu, char *extra) | ||
1970 | { | ||
1971 | struct atmel_private *priv = netdev_priv(dev); | ||
1972 | struct iw_param *param = &wrqu->param; | ||
1973 | |||
1974 | switch (param->flags & IW_AUTH_INDEX) { | ||
1975 | case IW_AUTH_WPA_VERSION: | ||
1976 | case IW_AUTH_CIPHER_PAIRWISE: | ||
1977 | case IW_AUTH_CIPHER_GROUP: | ||
1978 | case IW_AUTH_KEY_MGMT: | ||
1979 | case IW_AUTH_RX_UNENCRYPTED_EAPOL: | ||
1980 | case IW_AUTH_PRIVACY_INVOKED: | ||
1981 | /* | ||
1982 | * atmel does not use these parameters | ||
1983 | */ | ||
1984 | break; | ||
1985 | |||
1986 | case IW_AUTH_DROP_UNENCRYPTED: | ||
1987 | priv->exclude_unencrypted = param->value ? 1 : 0; | ||
1988 | break; | ||
1989 | |||
1990 | case IW_AUTH_80211_AUTH_ALG: { | ||
1991 | if (param->value & IW_AUTH_ALG_SHARED_KEY) { | ||
1992 | priv->exclude_unencrypted = 1; | ||
1993 | } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { | ||
1994 | priv->exclude_unencrypted = 0; | ||
1995 | } else | ||
1996 | return -EINVAL; | ||
1997 | break; | ||
1998 | } | ||
1999 | |||
2000 | case IW_AUTH_WPA_ENABLED: | ||
2001 | /* Silently accept disable of WPA */ | ||
2002 | if (param->value > 0) | ||
2003 | return -EOPNOTSUPP; | ||
2004 | break; | ||
2005 | |||
2006 | default: | ||
2007 | return -EOPNOTSUPP; | ||
2008 | } | ||
2009 | return -EINPROGRESS; | ||
2010 | } | ||
2011 | |||
2012 | static int atmel_get_auth(struct net_device *dev, | ||
2013 | struct iw_request_info *info, | ||
2014 | union iwreq_data *wrqu, char *extra) | ||
2015 | { | ||
2016 | struct atmel_private *priv = netdev_priv(dev); | ||
2017 | struct iw_param *param = &wrqu->param; | ||
2018 | |||
2019 | switch (param->flags & IW_AUTH_INDEX) { | ||
2020 | case IW_AUTH_DROP_UNENCRYPTED: | ||
2021 | param->value = priv->exclude_unencrypted; | ||
2022 | break; | ||
2023 | |||
2024 | case IW_AUTH_80211_AUTH_ALG: | ||
2025 | if (priv->exclude_unencrypted == 1) | ||
2026 | param->value = IW_AUTH_ALG_SHARED_KEY; | ||
2027 | else | ||
2028 | param->value = IW_AUTH_ALG_OPEN_SYSTEM; | ||
2029 | break; | ||
2030 | |||
2031 | case IW_AUTH_WPA_ENABLED: | ||
2032 | param->value = 0; | ||
2033 | break; | ||
2034 | |||
2035 | default: | ||
2036 | return -EOPNOTSUPP; | ||
2037 | } | ||
2038 | return 0; | ||
2039 | } | ||
2040 | |||
2041 | |||
1856 | static int atmel_get_name(struct net_device *dev, | 2042 | static int atmel_get_name(struct net_device *dev, |
1857 | struct iw_request_info *info, | 2043 | struct iw_request_info *info, |
1858 | char *cwrq, | 2044 | char *cwrq, |
@@ -2289,13 +2475,15 @@ static int atmel_set_wap(struct net_device *dev, | |||
2289 | { | 2475 | { |
2290 | struct atmel_private *priv = netdev_priv(dev); | 2476 | struct atmel_private *priv = netdev_priv(dev); |
2291 | int i; | 2477 | int i; |
2292 | static const u8 bcast[] = { 255, 255, 255, 255, 255, 255 }; | 2478 | static const u8 any[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
2479 | static const u8 off[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; | ||
2293 | unsigned long flags; | 2480 | unsigned long flags; |
2294 | 2481 | ||
2295 | if (awrq->sa_family != ARPHRD_ETHER) | 2482 | if (awrq->sa_family != ARPHRD_ETHER) |
2296 | return -EINVAL; | 2483 | return -EINVAL; |
2297 | 2484 | ||
2298 | if (memcmp(bcast, awrq->sa_data, 6) == 0) { | 2485 | if (!memcmp(any, awrq->sa_data, 6) || |
2486 | !memcmp(off, awrq->sa_data, 6)) { | ||
2299 | del_timer_sync(&priv->management_timer); | 2487 | del_timer_sync(&priv->management_timer); |
2300 | spin_lock_irqsave(&priv->irqlock, flags); | 2488 | spin_lock_irqsave(&priv->irqlock, flags); |
2301 | atmel_scan(priv, 1); | 2489 | atmel_scan(priv, 1); |
@@ -2378,6 +2566,15 @@ static const iw_handler atmel_handler[] = | |||
2378 | (iw_handler) atmel_get_encode, /* SIOCGIWENCODE */ | 2566 | (iw_handler) atmel_get_encode, /* SIOCGIWENCODE */ |
2379 | (iw_handler) atmel_set_power, /* SIOCSIWPOWER */ | 2567 | (iw_handler) atmel_set_power, /* SIOCSIWPOWER */ |
2380 | (iw_handler) atmel_get_power, /* SIOCGIWPOWER */ | 2568 | (iw_handler) atmel_get_power, /* SIOCGIWPOWER */ |
2569 | (iw_handler) NULL, /* -- hole -- */ | ||
2570 | (iw_handler) NULL, /* -- hole -- */ | ||
2571 | (iw_handler) NULL, /* SIOCSIWGENIE */ | ||
2572 | (iw_handler) NULL, /* SIOCGIWGENIE */ | ||
2573 | (iw_handler) atmel_set_auth, /* SIOCSIWAUTH */ | ||
2574 | (iw_handler) atmel_get_auth, /* SIOCGIWAUTH */ | ||
2575 | (iw_handler) atmel_set_encodeext, /* SIOCSIWENCODEEXT */ | ||
2576 | (iw_handler) atmel_get_encodeext, /* SIOCGIWENCODEEXT */ | ||
2577 | (iw_handler) NULL, /* SIOCSIWPMKSA */ | ||
2381 | }; | 2578 | }; |
2382 | 2579 | ||
2383 | static const iw_handler atmel_private_handler[] = | 2580 | static const iw_handler atmel_private_handler[] = |
@@ -2924,6 +3121,8 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype) | |||
2924 | u16 ass_id = le16_to_cpu(ass_resp->ass_id); | 3121 | u16 ass_id = le16_to_cpu(ass_resp->ass_id); |
2925 | u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length; | 3122 | u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length; |
2926 | 3123 | ||
3124 | union iwreq_data wrqu; | ||
3125 | |||
2927 | if (frame_len < 8 + rates_len) | 3126 | if (frame_len < 8 + rates_len) |
2928 | return; | 3127 | return; |
2929 | 3128 | ||
@@ -2954,6 +3153,14 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype) | |||
2954 | priv->station_is_associated = 1; | 3153 | priv->station_is_associated = 1; |
2955 | priv->station_was_associated = 1; | 3154 | priv->station_was_associated = 1; |
2956 | atmel_enter_state(priv, STATION_STATE_READY); | 3155 | atmel_enter_state(priv, STATION_STATE_READY); |
3156 | |||
3157 | /* Send association event to userspace */ | ||
3158 | wrqu.data.length = 0; | ||
3159 | wrqu.data.flags = 0; | ||
3160 | memcpy(wrqu.ap_addr.sa_data, priv->CurrentBSSID, ETH_ALEN); | ||
3161 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
3162 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
3163 | |||
2957 | return; | 3164 | return; |
2958 | } | 3165 | } |
2959 | 3166 | ||
@@ -3632,6 +3839,7 @@ static int reset_atmel_card(struct net_device *dev) | |||
3632 | 3839 | ||
3633 | struct atmel_private *priv = netdev_priv(dev); | 3840 | struct atmel_private *priv = netdev_priv(dev); |
3634 | u8 configuration; | 3841 | u8 configuration; |
3842 | int old_state = priv->station_state; | ||
3635 | 3843 | ||
3636 | /* data to add to the firmware names, in priority order | 3844 | /* data to add to the firmware names, in priority order |
3637 | this implemenents firmware versioning */ | 3845 | this implemenents firmware versioning */ |
@@ -3792,6 +4000,17 @@ static int reset_atmel_card(struct net_device *dev) | |||
3792 | else | 4000 | else |
3793 | build_wep_mib(priv); | 4001 | build_wep_mib(priv); |
3794 | 4002 | ||
4003 | if (old_state == STATION_STATE_READY) | ||
4004 | { | ||
4005 | union iwreq_data wrqu; | ||
4006 | |||
4007 | wrqu.data.length = 0; | ||
4008 | wrqu.data.flags = 0; | ||
4009 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | ||
4010 | memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); | ||
4011 | wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); | ||
4012 | } | ||
4013 | |||
3795 | return 1; | 4014 | return 1; |
3796 | } | 4015 | } |
3797 | 4016 | ||
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 7146b69b812c..0aa14c92b570 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c | |||
@@ -380,8 +380,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner) | |||
380 | /* initialize common driver fields */ | 380 | /* initialize common driver fields */ |
381 | drv->driver.name = drv->name; | 381 | drv->driver.name = drv->name; |
382 | drv->driver.bus = &pci_bus_type; | 382 | drv->driver.bus = &pci_bus_type; |
383 | drv->driver.probe = pci_device_probe; | ||
384 | drv->driver.remove = pci_device_remove; | ||
385 | /* FIXME, once all of the existing PCI drivers have been fixed to set | 383 | /* FIXME, once all of the existing PCI drivers have been fixed to set |
386 | * the pci shutdown function, this test can go away. */ | 384 | * the pci shutdown function, this test can go away. */ |
387 | if (!drv->driver.shutdown) | 385 | if (!drv->driver.shutdown) |
@@ -513,6 +511,8 @@ struct bus_type pci_bus_type = { | |||
513 | .name = "pci", | 511 | .name = "pci", |
514 | .match = pci_bus_match, | 512 | .match = pci_bus_match, |
515 | .uevent = pci_uevent, | 513 | .uevent = pci_uevent, |
514 | .probe = pci_device_probe, | ||
515 | .remove = pci_device_remove, | ||
516 | .suspend = pci_device_suspend, | 516 | .suspend = pci_device_suspend, |
517 | .resume = pci_device_resume, | 517 | .resume = pci_device_resume, |
518 | .dev_attrs = pci_dev_attrs, | 518 | .dev_attrs = pci_dev_attrs, |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 0252582b91cd..0a424a4e8187 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
@@ -311,8 +311,6 @@ int pcmcia_register_driver(struct pcmcia_driver *driver) | |||
311 | /* initialize common fields */ | 311 | /* initialize common fields */ |
312 | driver->drv.bus = &pcmcia_bus_type; | 312 | driver->drv.bus = &pcmcia_bus_type; |
313 | driver->drv.owner = driver->owner; | 313 | driver->drv.owner = driver->owner; |
314 | driver->drv.probe = pcmcia_device_probe; | ||
315 | driver->drv.remove = pcmcia_device_remove; | ||
316 | 314 | ||
317 | return driver_register(&driver->drv); | 315 | return driver_register(&driver->drv); |
318 | } | 316 | } |
@@ -920,6 +918,37 @@ pcmcia_device_stringattr(prod_id2, prod_id[1]); | |||
920 | pcmcia_device_stringattr(prod_id3, prod_id[2]); | 918 | pcmcia_device_stringattr(prod_id3, prod_id[2]); |
921 | pcmcia_device_stringattr(prod_id4, prod_id[3]); | 919 | pcmcia_device_stringattr(prod_id4, prod_id[3]); |
922 | 920 | ||
921 | |||
922 | static ssize_t pcmcia_show_pm_state(struct device *dev, struct device_attribute *attr, char *buf) | ||
923 | { | ||
924 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | ||
925 | |||
926 | if (p_dev->dev.power.power_state.event != PM_EVENT_ON) | ||
927 | return sprintf(buf, "off\n"); | ||
928 | else | ||
929 | return sprintf(buf, "on\n"); | ||
930 | } | ||
931 | |||
932 | static ssize_t pcmcia_store_pm_state(struct device *dev, struct device_attribute *attr, | ||
933 | const char *buf, size_t count) | ||
934 | { | ||
935 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | ||
936 | int ret = 0; | ||
937 | |||
938 | if (!count) | ||
939 | return -EINVAL; | ||
940 | |||
941 | if ((p_dev->dev.power.power_state.event == PM_EVENT_ON) && | ||
942 | (!strncmp(buf, "off", 3))) | ||
943 | ret = dpm_runtime_suspend(dev, PMSG_SUSPEND); | ||
944 | else if ((p_dev->dev.power.power_state.event != PM_EVENT_ON) && | ||
945 | (!strncmp(buf, "on", 2))) | ||
946 | dpm_runtime_resume(dev); | ||
947 | |||
948 | return ret ? ret : count; | ||
949 | } | ||
950 | |||
951 | |||
923 | static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) | 952 | static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) |
924 | { | 953 | { |
925 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 954 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
@@ -945,8 +974,9 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, | |||
945 | struct device_attribute *attr, const char *buf, size_t count) | 974 | struct device_attribute *attr, const char *buf, size_t count) |
946 | { | 975 | { |
947 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); | 976 | struct pcmcia_device *p_dev = to_pcmcia_dev(dev); |
948 | if (!count) | 977 | |
949 | return -EINVAL; | 978 | if (!count) |
979 | return -EINVAL; | ||
950 | 980 | ||
951 | down(&p_dev->socket->skt_sem); | 981 | down(&p_dev->socket->skt_sem); |
952 | p_dev->allow_func_id_match = 1; | 982 | p_dev->allow_func_id_match = 1; |
@@ -959,6 +989,7 @@ static ssize_t pcmcia_store_allow_func_id_match(struct device *dev, | |||
959 | 989 | ||
960 | static struct device_attribute pcmcia_dev_attrs[] = { | 990 | static struct device_attribute pcmcia_dev_attrs[] = { |
961 | __ATTR(function, 0444, func_show, NULL), | 991 | __ATTR(function, 0444, func_show, NULL), |
992 | __ATTR(pm_state, 0644, pcmcia_show_pm_state, pcmcia_store_pm_state), | ||
962 | __ATTR_RO(func_id), | 993 | __ATTR_RO(func_id), |
963 | __ATTR_RO(manf_id), | 994 | __ATTR_RO(manf_id), |
964 | __ATTR_RO(card_id), | 995 | __ATTR_RO(card_id), |
@@ -1167,6 +1198,8 @@ struct bus_type pcmcia_bus_type = { | |||
1167 | .uevent = pcmcia_bus_uevent, | 1198 | .uevent = pcmcia_bus_uevent, |
1168 | .match = pcmcia_bus_match, | 1199 | .match = pcmcia_bus_match, |
1169 | .dev_attrs = pcmcia_dev_attrs, | 1200 | .dev_attrs = pcmcia_dev_attrs, |
1201 | .probe = pcmcia_device_probe, | ||
1202 | .remove = pcmcia_device_remove, | ||
1170 | .suspend = pcmcia_dev_suspend, | 1203 | .suspend = pcmcia_dev_suspend, |
1171 | .resume = pcmcia_dev_resume, | 1204 | .resume = pcmcia_dev_resume, |
1172 | }; | 1205 | }; |
diff --git a/drivers/pcmcia/pxa2xx_mainstone.c b/drivers/pcmcia/pxa2xx_mainstone.c index 5d957dfe23d9..fda06941e730 100644 --- a/drivers/pcmcia/pxa2xx_mainstone.c +++ b/drivers/pcmcia/pxa2xx_mainstone.c | |||
@@ -171,27 +171,22 @@ static int __init mst_pcmcia_init(void) | |||
171 | { | 171 | { |
172 | int ret; | 172 | int ret; |
173 | 173 | ||
174 | mst_pcmcia_device = kzalloc(sizeof(*mst_pcmcia_device), GFP_KERNEL); | 174 | mst_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); |
175 | if (!mst_pcmcia_device) | 175 | if (!mst_pcmcia_device) |
176 | return -ENOMEM; | 176 | return -ENOMEM; |
177 | mst_pcmcia_device->name = "pxa2xx-pcmcia"; | 177 | |
178 | mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops; | 178 | mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops; |
179 | 179 | ||
180 | ret = platform_device_register(mst_pcmcia_device); | 180 | ret = platform_device_add(mst_pcmcia_device); |
181 | |||
181 | if (ret) | 182 | if (ret) |
182 | kfree(mst_pcmcia_device); | 183 | platform_device_put(mst_pcmcia_device); |
183 | 184 | ||
184 | return ret; | 185 | return ret; |
185 | } | 186 | } |
186 | 187 | ||
187 | static void __exit mst_pcmcia_exit(void) | 188 | static void __exit mst_pcmcia_exit(void) |
188 | { | 189 | { |
189 | /* | ||
190 | * This call is supposed to free our mst_pcmcia_device. | ||
191 | * Unfortunately platform_device don't have a free method, and | ||
192 | * we can't assume it's free of any reference at this point so we | ||
193 | * can't free it either. | ||
194 | */ | ||
195 | platform_device_unregister(mst_pcmcia_device); | 190 | platform_device_unregister(mst_pcmcia_device); |
196 | } | 191 | } |
197 | 192 | ||
diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index 12a7244a5ec8..fd3647368955 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c | |||
@@ -263,30 +263,25 @@ static int __init sharpsl_pcmcia_init(void) | |||
263 | { | 263 | { |
264 | int ret; | 264 | int ret; |
265 | 265 | ||
266 | sharpsl_pcmcia_ops.nr=platform_scoop_config->num_devs; | 266 | sharpsl_pcmcia_ops.nr = platform_scoop_config->num_devs; |
267 | sharpsl_pcmcia_device = kzalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL); | 267 | sharpsl_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); |
268 | |||
268 | if (!sharpsl_pcmcia_device) | 269 | if (!sharpsl_pcmcia_device) |
269 | return -ENOMEM; | 270 | return -ENOMEM; |
270 | 271 | ||
271 | sharpsl_pcmcia_device->name = "pxa2xx-pcmcia"; | ||
272 | sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops; | 272 | sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops; |
273 | sharpsl_pcmcia_device->dev.parent=platform_scoop_config->devs[0].dev; | 273 | sharpsl_pcmcia_device->dev.parent = platform_scoop_config->devs[0].dev; |
274 | |||
275 | ret = platform_device_add(sharpsl_pcmcia_device); | ||
274 | 276 | ||
275 | ret = platform_device_register(sharpsl_pcmcia_device); | ||
276 | if (ret) | 277 | if (ret) |
277 | kfree(sharpsl_pcmcia_device); | 278 | platform_device_put(sharpsl_pcmcia_device); |
278 | 279 | ||
279 | return ret; | 280 | return ret; |
280 | } | 281 | } |
281 | 282 | ||
282 | static void __exit sharpsl_pcmcia_exit(void) | 283 | static void __exit sharpsl_pcmcia_exit(void) |
283 | { | 284 | { |
284 | /* | ||
285 | * This call is supposed to free our sharpsl_pcmcia_device. | ||
286 | * Unfortunately platform_device don't have a free method, and | ||
287 | * we can't assume it's free of any reference at this point so we | ||
288 | * can't free it either. | ||
289 | */ | ||
290 | platform_device_unregister(sharpsl_pcmcia_device); | 285 | platform_device_unregister(sharpsl_pcmcia_device); |
291 | } | 286 | } |
292 | 287 | ||
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c index 7a7744662d54..5ab1cdef7c48 100644 --- a/drivers/pcmcia/socket_sysfs.c +++ b/drivers/pcmcia/socket_sysfs.c | |||
@@ -98,6 +98,30 @@ static ssize_t pccard_store_insert(struct class_device *dev, const char *buf, si | |||
98 | } | 98 | } |
99 | static CLASS_DEVICE_ATTR(card_insert, 0200, NULL, pccard_store_insert); | 99 | static CLASS_DEVICE_ATTR(card_insert, 0200, NULL, pccard_store_insert); |
100 | 100 | ||
101 | |||
102 | static ssize_t pccard_show_card_pm_state(struct class_device *dev, char *buf) | ||
103 | { | ||
104 | struct pcmcia_socket *s = to_socket(dev); | ||
105 | return sprintf(buf, "%s\n", s->state & SOCKET_SUSPEND ? "off" : "on"); | ||
106 | } | ||
107 | |||
108 | static ssize_t pccard_store_card_pm_state(struct class_device *dev, const char *buf, size_t count) | ||
109 | { | ||
110 | ssize_t ret = -EINVAL; | ||
111 | struct pcmcia_socket *s = to_socket(dev); | ||
112 | |||
113 | if (!count) | ||
114 | return -EINVAL; | ||
115 | |||
116 | if (!(s->state & SOCKET_SUSPEND) && !strncmp(buf, "off", 3)) | ||
117 | ret = pcmcia_suspend_card(s); | ||
118 | else if ((s->state & SOCKET_SUSPEND) && !strncmp(buf, "on", 2)) | ||
119 | ret = pcmcia_resume_card(s); | ||
120 | |||
121 | return ret ? -ENODEV : count; | ||
122 | } | ||
123 | static CLASS_DEVICE_ATTR(card_pm_state, 0644, pccard_show_card_pm_state, pccard_store_card_pm_state); | ||
124 | |||
101 | static ssize_t pccard_store_eject(struct class_device *dev, const char *buf, size_t count) | 125 | static ssize_t pccard_store_eject(struct class_device *dev, const char *buf, size_t count) |
102 | { | 126 | { |
103 | ssize_t ret; | 127 | ssize_t ret; |
@@ -320,6 +344,7 @@ static struct class_device_attribute *pccard_socket_attributes[] = { | |||
320 | &class_device_attr_card_vpp, | 344 | &class_device_attr_card_vpp, |
321 | &class_device_attr_card_vcc, | 345 | &class_device_attr_card_vcc, |
322 | &class_device_attr_card_insert, | 346 | &class_device_attr_card_insert, |
347 | &class_device_attr_card_pm_state, | ||
323 | &class_device_attr_card_eject, | 348 | &class_device_attr_card_eject, |
324 | &class_device_attr_card_irq_mask, | 349 | &class_device_attr_card_irq_mask, |
325 | &class_device_attr_available_resources_setup_done, | 350 | &class_device_attr_available_resources_setup_done, |
diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 15fb758a9e52..7cafacdd12b0 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c | |||
@@ -195,6 +195,8 @@ static int pnp_bus_resume(struct device *dev) | |||
195 | struct bus_type pnp_bus_type = { | 195 | struct bus_type pnp_bus_type = { |
196 | .name = "pnp", | 196 | .name = "pnp", |
197 | .match = pnp_bus_match, | 197 | .match = pnp_bus_match, |
198 | .probe = pnp_device_probe, | ||
199 | .remove = pnp_device_remove, | ||
198 | .suspend = pnp_bus_suspend, | 200 | .suspend = pnp_bus_suspend, |
199 | .resume = pnp_bus_resume, | 201 | .resume = pnp_bus_resume, |
200 | }; | 202 | }; |
@@ -215,8 +217,6 @@ int pnp_register_driver(struct pnp_driver *drv) | |||
215 | 217 | ||
216 | drv->driver.name = drv->name; | 218 | drv->driver.name = drv->name; |
217 | drv->driver.bus = &pnp_bus_type; | 219 | drv->driver.bus = &pnp_bus_type; |
218 | drv->driver.probe = pnp_device_probe; | ||
219 | drv->driver.remove = pnp_device_remove; | ||
220 | 220 | ||
221 | count = driver_register(&drv->driver); | 221 | count = driver_register(&drv->driver); |
222 | 222 | ||
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index dc749609699a..5480119ff9d3 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c | |||
@@ -147,8 +147,6 @@ int rio_register_driver(struct rio_driver *rdrv) | |||
147 | /* initialize common driver fields */ | 147 | /* initialize common driver fields */ |
148 | rdrv->driver.name = rdrv->name; | 148 | rdrv->driver.name = rdrv->name; |
149 | rdrv->driver.bus = &rio_bus_type; | 149 | rdrv->driver.bus = &rio_bus_type; |
150 | rdrv->driver.probe = rio_device_probe; | ||
151 | rdrv->driver.remove = rio_device_remove; | ||
152 | 150 | ||
153 | /* register with core */ | 151 | /* register with core */ |
154 | return driver_register(&rdrv->driver); | 152 | return driver_register(&rdrv->driver); |
@@ -204,7 +202,9 @@ static struct device rio_bus = { | |||
204 | struct bus_type rio_bus_type = { | 202 | struct bus_type rio_bus_type = { |
205 | .name = "rapidio", | 203 | .name = "rapidio", |
206 | .match = rio_match_bus, | 204 | .match = rio_match_bus, |
207 | .dev_attrs = rio_dev_attrs | 205 | .dev_attrs = rio_dev_attrs, |
206 | .probe = rio_device_probe, | ||
207 | .remove = rio_device_remove, | ||
208 | }; | 208 | }; |
209 | 209 | ||
210 | /** | 210 | /** |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index e849289d4f3c..503a568e47c3 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -52,11 +52,7 @@ ccwgroup_uevent (struct device *dev, char **envp, int num_envp, char *buffer, | |||
52 | return 0; | 52 | return 0; |
53 | } | 53 | } |
54 | 54 | ||
55 | static struct bus_type ccwgroup_bus_type = { | 55 | static struct bus_type ccwgroup_bus_type; |
56 | .name = "ccwgroup", | ||
57 | .match = ccwgroup_bus_match, | ||
58 | .uevent = ccwgroup_uevent, | ||
59 | }; | ||
60 | 56 | ||
61 | static inline void | 57 | static inline void |
62 | __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) | 58 | __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev) |
@@ -389,6 +385,14 @@ ccwgroup_remove (struct device *dev) | |||
389 | return 0; | 385 | return 0; |
390 | } | 386 | } |
391 | 387 | ||
388 | static struct bus_type ccwgroup_bus_type = { | ||
389 | .name = "ccwgroup", | ||
390 | .match = ccwgroup_bus_match, | ||
391 | .uevent = ccwgroup_uevent, | ||
392 | .probe = ccwgroup_probe, | ||
393 | .remove = ccwgroup_remove, | ||
394 | }; | ||
395 | |||
392 | int | 396 | int |
393 | ccwgroup_driver_register (struct ccwgroup_driver *cdriver) | 397 | ccwgroup_driver_register (struct ccwgroup_driver *cdriver) |
394 | { | 398 | { |
@@ -396,8 +400,6 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver) | |||
396 | cdriver->driver = (struct device_driver) { | 400 | cdriver->driver = (struct device_driver) { |
397 | .bus = &ccwgroup_bus_type, | 401 | .bus = &ccwgroup_bus_type, |
398 | .name = cdriver->name, | 402 | .name = cdriver->name, |
399 | .probe = ccwgroup_probe, | ||
400 | .remove = ccwgroup_remove, | ||
401 | }; | 403 | }; |
402 | 404 | ||
403 | return driver_register(&cdriver->driver); | 405 | return driver_register(&cdriver->driver); |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index e565193650c7..2d319fb812ca 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -542,9 +542,41 @@ css_bus_match (struct device *dev, struct device_driver *drv) | |||
542 | return 0; | 542 | return 0; |
543 | } | 543 | } |
544 | 544 | ||
545 | static int | ||
546 | css_probe (struct device *dev) | ||
547 | { | ||
548 | struct subchannel *sch; | ||
549 | |||
550 | sch = to_subchannel(dev); | ||
551 | sch->driver = container_of (dev->driver, struct css_driver, drv); | ||
552 | return (sch->driver->probe ? sch->driver->probe(sch) : 0); | ||
553 | } | ||
554 | |||
555 | static int | ||
556 | css_remove (struct device *dev) | ||
557 | { | ||
558 | struct subchannel *sch; | ||
559 | |||
560 | sch = to_subchannel(dev); | ||
561 | return (sch->driver->remove ? sch->driver->remove(sch) : 0); | ||
562 | } | ||
563 | |||
564 | static void | ||
565 | css_shutdown (struct device *dev) | ||
566 | { | ||
567 | struct subchannel *sch; | ||
568 | |||
569 | sch = to_subchannel(dev); | ||
570 | if (sch->driver->shutdown) | ||
571 | sch->driver->shutdown(sch); | ||
572 | } | ||
573 | |||
545 | struct bus_type css_bus_type = { | 574 | struct bus_type css_bus_type = { |
546 | .name = "css", | 575 | .name = "css", |
547 | .match = &css_bus_match, | 576 | .match = css_bus_match, |
577 | .probe = css_probe, | ||
578 | .remove = css_remove, | ||
579 | .shutdown = css_shutdown, | ||
548 | }; | 580 | }; |
549 | 581 | ||
550 | subsys_initcall(init_channel_subsystem); | 582 | subsys_initcall(init_channel_subsystem); |
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 251ebd7a7d3a..aa5ab5d4547c 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -115,6 +115,7 @@ struct ccw_device_private { | |||
115 | * Currently, we only care about I/O subchannels (type 0), these | 115 | * Currently, we only care about I/O subchannels (type 0), these |
116 | * have a ccw_device connected to them. | 116 | * have a ccw_device connected to them. |
117 | */ | 117 | */ |
118 | struct subchannel; | ||
118 | struct css_driver { | 119 | struct css_driver { |
119 | unsigned int subchannel_type; | 120 | unsigned int subchannel_type; |
120 | struct device_driver drv; | 121 | struct device_driver drv; |
@@ -122,6 +123,9 @@ struct css_driver { | |||
122 | int (*notify)(struct device *, int); | 123 | int (*notify)(struct device *, int); |
123 | void (*verify)(struct device *); | 124 | void (*verify)(struct device *); |
124 | void (*termination)(struct device *); | 125 | void (*termination)(struct device *); |
126 | int (*probe)(struct subchannel *); | ||
127 | int (*remove)(struct subchannel *); | ||
128 | void (*shutdown)(struct subchannel *); | ||
125 | }; | 129 | }; |
126 | 130 | ||
127 | /* | 131 | /* |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index fa3e4c0a2536..eb73605a0527 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -107,33 +107,29 @@ ccw_uevent (struct device *dev, char **envp, int num_envp, | |||
107 | return 0; | 107 | return 0; |
108 | } | 108 | } |
109 | 109 | ||
110 | struct bus_type ccw_bus_type = { | 110 | struct bus_type ccw_bus_type; |
111 | .name = "ccw", | ||
112 | .match = &ccw_bus_match, | ||
113 | .uevent = &ccw_uevent, | ||
114 | }; | ||
115 | 111 | ||
116 | static int io_subchannel_probe (struct device *); | 112 | static int io_subchannel_probe (struct subchannel *); |
117 | static int io_subchannel_remove (struct device *); | 113 | static int io_subchannel_remove (struct subchannel *); |
118 | void io_subchannel_irq (struct device *); | 114 | void io_subchannel_irq (struct device *); |
119 | static int io_subchannel_notify(struct device *, int); | 115 | static int io_subchannel_notify(struct device *, int); |
120 | static void io_subchannel_verify(struct device *); | 116 | static void io_subchannel_verify(struct device *); |
121 | static void io_subchannel_ioterm(struct device *); | 117 | static void io_subchannel_ioterm(struct device *); |
122 | static void io_subchannel_shutdown(struct device *); | 118 | static void io_subchannel_shutdown(struct subchannel *); |
123 | 119 | ||
124 | struct css_driver io_subchannel_driver = { | 120 | struct css_driver io_subchannel_driver = { |
125 | .subchannel_type = SUBCHANNEL_TYPE_IO, | 121 | .subchannel_type = SUBCHANNEL_TYPE_IO, |
126 | .drv = { | 122 | .drv = { |
127 | .name = "io_subchannel", | 123 | .name = "io_subchannel", |
128 | .bus = &css_bus_type, | 124 | .bus = &css_bus_type, |
129 | .probe = &io_subchannel_probe, | ||
130 | .remove = &io_subchannel_remove, | ||
131 | .shutdown = &io_subchannel_shutdown, | ||
132 | }, | 125 | }, |
133 | .irq = io_subchannel_irq, | 126 | .irq = io_subchannel_irq, |
134 | .notify = io_subchannel_notify, | 127 | .notify = io_subchannel_notify, |
135 | .verify = io_subchannel_verify, | 128 | .verify = io_subchannel_verify, |
136 | .termination = io_subchannel_ioterm, | 129 | .termination = io_subchannel_ioterm, |
130 | .probe = io_subchannel_probe, | ||
131 | .remove = io_subchannel_remove, | ||
132 | .shutdown = io_subchannel_shutdown, | ||
137 | }; | 133 | }; |
138 | 134 | ||
139 | struct workqueue_struct *ccw_device_work; | 135 | struct workqueue_struct *ccw_device_work; |
@@ -803,14 +799,12 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) | |||
803 | } | 799 | } |
804 | 800 | ||
805 | static int | 801 | static int |
806 | io_subchannel_probe (struct device *pdev) | 802 | io_subchannel_probe (struct subchannel *sch) |
807 | { | 803 | { |
808 | struct subchannel *sch; | ||
809 | struct ccw_device *cdev; | 804 | struct ccw_device *cdev; |
810 | int rc; | 805 | int rc; |
811 | unsigned long flags; | 806 | unsigned long flags; |
812 | 807 | ||
813 | sch = to_subchannel(pdev); | ||
814 | if (sch->dev.driver_data) { | 808 | if (sch->dev.driver_data) { |
815 | /* | 809 | /* |
816 | * This subchannel already has an associated ccw_device. | 810 | * This subchannel already has an associated ccw_device. |
@@ -846,7 +840,7 @@ io_subchannel_probe (struct device *pdev) | |||
846 | memset(cdev->private, 0, sizeof(struct ccw_device_private)); | 840 | memset(cdev->private, 0, sizeof(struct ccw_device_private)); |
847 | atomic_set(&cdev->private->onoff, 0); | 841 | atomic_set(&cdev->private->onoff, 0); |
848 | cdev->dev = (struct device) { | 842 | cdev->dev = (struct device) { |
849 | .parent = pdev, | 843 | .parent = &sch->dev, |
850 | .release = ccw_device_release, | 844 | .release = ccw_device_release, |
851 | }; | 845 | }; |
852 | INIT_LIST_HEAD(&cdev->private->kick_work.entry); | 846 | INIT_LIST_HEAD(&cdev->private->kick_work.entry); |
@@ -859,7 +853,7 @@ io_subchannel_probe (struct device *pdev) | |||
859 | return -ENODEV; | 853 | return -ENODEV; |
860 | } | 854 | } |
861 | 855 | ||
862 | rc = io_subchannel_recog(cdev, to_subchannel(pdev)); | 856 | rc = io_subchannel_recog(cdev, sch); |
863 | if (rc) { | 857 | if (rc) { |
864 | spin_lock_irqsave(&sch->lock, flags); | 858 | spin_lock_irqsave(&sch->lock, flags); |
865 | sch->dev.driver_data = NULL; | 859 | sch->dev.driver_data = NULL; |
@@ -883,17 +877,17 @@ ccw_device_unregister(void *data) | |||
883 | } | 877 | } |
884 | 878 | ||
885 | static int | 879 | static int |
886 | io_subchannel_remove (struct device *dev) | 880 | io_subchannel_remove (struct subchannel *sch) |
887 | { | 881 | { |
888 | struct ccw_device *cdev; | 882 | struct ccw_device *cdev; |
889 | unsigned long flags; | 883 | unsigned long flags; |
890 | 884 | ||
891 | if (!dev->driver_data) | 885 | if (!sch->dev.driver_data) |
892 | return 0; | 886 | return 0; |
893 | cdev = dev->driver_data; | 887 | cdev = sch->dev.driver_data; |
894 | /* Set ccw device to not operational and drop reference. */ | 888 | /* Set ccw device to not operational and drop reference. */ |
895 | spin_lock_irqsave(cdev->ccwlock, flags); | 889 | spin_lock_irqsave(cdev->ccwlock, flags); |
896 | dev->driver_data = NULL; | 890 | sch->dev.driver_data = NULL; |
897 | cdev->private->state = DEV_STATE_NOT_OPER; | 891 | cdev->private->state = DEV_STATE_NOT_OPER; |
898 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 892 | spin_unlock_irqrestore(cdev->ccwlock, flags); |
899 | /* | 893 | /* |
@@ -948,14 +942,12 @@ io_subchannel_ioterm(struct device *dev) | |||
948 | } | 942 | } |
949 | 943 | ||
950 | static void | 944 | static void |
951 | io_subchannel_shutdown(struct device *dev) | 945 | io_subchannel_shutdown(struct subchannel *sch) |
952 | { | 946 | { |
953 | struct subchannel *sch; | ||
954 | struct ccw_device *cdev; | 947 | struct ccw_device *cdev; |
955 | int ret; | 948 | int ret; |
956 | 949 | ||
957 | sch = to_subchannel(dev); | 950 | cdev = sch->dev.driver_data; |
958 | cdev = dev->driver_data; | ||
959 | 951 | ||
960 | if (cio_is_console(sch->schid)) | 952 | if (cio_is_console(sch->schid)) |
961 | return; | 953 | return; |
@@ -1129,6 +1121,14 @@ ccw_device_remove (struct device *dev) | |||
1129 | return 0; | 1121 | return 0; |
1130 | } | 1122 | } |
1131 | 1123 | ||
1124 | struct bus_type ccw_bus_type = { | ||
1125 | .name = "ccw", | ||
1126 | .match = ccw_bus_match, | ||
1127 | .uevent = ccw_uevent, | ||
1128 | .probe = ccw_device_probe, | ||
1129 | .remove = ccw_device_remove, | ||
1130 | }; | ||
1131 | |||
1132 | int | 1132 | int |
1133 | ccw_driver_register (struct ccw_driver *cdriver) | 1133 | ccw_driver_register (struct ccw_driver *cdriver) |
1134 | { | 1134 | { |
@@ -1136,8 +1136,6 @@ ccw_driver_register (struct ccw_driver *cdriver) | |||
1136 | 1136 | ||
1137 | drv->bus = &ccw_bus_type; | 1137 | drv->bus = &ccw_bus_type; |
1138 | drv->name = cdriver->name; | 1138 | drv->name = cdriver->name; |
1139 | drv->probe = ccw_device_probe; | ||
1140 | drv->remove = ccw_device_remove; | ||
1141 | 1139 | ||
1142 | return driver_register(drv); | 1140 | return driver_register(drv); |
1143 | } | 1141 | } |
diff --git a/drivers/sbus/char/aurora.c b/drivers/sbus/char/aurora.c index 92e6c5639dd3..015db40ad8a4 100644 --- a/drivers/sbus/char/aurora.c +++ b/drivers/sbus/char/aurora.c | |||
@@ -92,7 +92,6 @@ static struct Aurora_port aurora_port[AURORA_TNPORTS] = { | |||
92 | 92 | ||
93 | /* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/ | 93 | /* no longer used. static struct Aurora_board * IRQ_to_board[16] = { NULL, } ;*/ |
94 | static unsigned char * tmp_buf = NULL; | 94 | static unsigned char * tmp_buf = NULL; |
95 | static DECLARE_MUTEX(tmp_buf_sem); | ||
96 | 95 | ||
97 | DECLARE_TASK_QUEUE(tq_aurora); | 96 | DECLARE_TASK_QUEUE(tq_aurora); |
98 | 97 | ||
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index b9d2bb88787a..320e765fa0cd 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
@@ -45,7 +45,7 @@ obj-$(CONFIG_CYBERSTORMII_SCSI) += NCR53C9x.o cyberstormII.o | |||
45 | obj-$(CONFIG_BLZ2060_SCSI) += NCR53C9x.o blz2060.o | 45 | obj-$(CONFIG_BLZ2060_SCSI) += NCR53C9x.o blz2060.o |
46 | obj-$(CONFIG_BLZ1230_SCSI) += NCR53C9x.o blz1230.o | 46 | obj-$(CONFIG_BLZ1230_SCSI) += NCR53C9x.o blz1230.o |
47 | obj-$(CONFIG_FASTLANE_SCSI) += NCR53C9x.o fastlane.o | 47 | obj-$(CONFIG_FASTLANE_SCSI) += NCR53C9x.o fastlane.o |
48 | obj-$(CONFIG_OKTAGON_SCSI) += NCR53C9x.o oktagon_esp.o oktagon_io.o | 48 | obj-$(CONFIG_OKTAGON_SCSI) += NCR53C9x.o oktagon_esp_mod.o |
49 | obj-$(CONFIG_ATARI_SCSI) += atari_scsi.o | 49 | obj-$(CONFIG_ATARI_SCSI) += atari_scsi.o |
50 | obj-$(CONFIG_MAC_SCSI) += mac_scsi.o | 50 | obj-$(CONFIG_MAC_SCSI) += mac_scsi.o |
51 | obj-$(CONFIG_SCSI_MAC_ESP) += mac_esp.o NCR53C9x.o | 51 | obj-$(CONFIG_SCSI_MAC_ESP) += mac_esp.o NCR53C9x.o |
@@ -164,6 +164,7 @@ CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m) | |||
164 | zalon7xx-objs := zalon.o ncr53c8xx.o | 164 | zalon7xx-objs := zalon.o ncr53c8xx.o |
165 | NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o | 165 | NCR_Q720_mod-objs := NCR_Q720.o ncr53c8xx.o |
166 | libata-objs := libata-core.o libata-scsi.o | 166 | libata-objs := libata-core.o libata-scsi.o |
167 | oktagon_esp_mod-objs := oktagon_esp.o oktagon_io.o | ||
167 | 168 | ||
168 | # Files generated that shall be removed upon make clean | 169 | # Files generated that shall be removed upon make clean |
169 | clean-files := 53c7xx_d.h 53c700_d.h \ | 170 | clean-files := 53c7xx_d.h 53c700_d.h \ |
diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c index 640590bd014a..c7dd0154d012 100644 --- a/drivers/scsi/NCR53C9x.c +++ b/drivers/scsi/NCR53C9x.c | |||
@@ -1799,6 +1799,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs) | |||
1799 | */ | 1799 | */ |
1800 | int oldphase, i = 0; /* or where we left off last time ?? esp->current_data ?? */ | 1800 | int oldphase, i = 0; /* or where we left off last time ?? esp->current_data ?? */ |
1801 | int fifocnt = 0; | 1801 | int fifocnt = 0; |
1802 | unsigned char *p = phys_to_virt((unsigned long)SCptr->SCp.ptr); | ||
1802 | 1803 | ||
1803 | oldphase = esp_read(eregs->esp_status) & ESP_STAT_PMASK; | 1804 | oldphase = esp_read(eregs->esp_status) & ESP_STAT_PMASK; |
1804 | 1805 | ||
@@ -1860,7 +1861,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs) | |||
1860 | 1861 | ||
1861 | /* read fifo */ | 1862 | /* read fifo */ |
1862 | for(j=0;j<fifocnt;j++) | 1863 | for(j=0;j<fifocnt;j++) |
1863 | SCptr->SCp.ptr[i++] = esp_read(eregs->esp_fdata); | 1864 | p[i++] = esp_read(eregs->esp_fdata); |
1864 | 1865 | ||
1865 | ESPDATA(("(%d) ", i)); | 1866 | ESPDATA(("(%d) ", i)); |
1866 | 1867 | ||
@@ -1882,7 +1883,7 @@ static int esp_do_data(struct NCR_ESP *esp, struct ESP_regs *eregs) | |||
1882 | 1883 | ||
1883 | /* fill fifo */ | 1884 | /* fill fifo */ |
1884 | for(j=0;j<this_count;j++) | 1885 | for(j=0;j<this_count;j++) |
1885 | esp_write(eregs->esp_fdata, SCptr->SCp.ptr[i++]); | 1886 | esp_write(eregs->esp_fdata, p[i++]); |
1886 | 1887 | ||
1887 | /* how many left if this goes out ?? */ | 1888 | /* how many left if this goes out ?? */ |
1888 | hmuch -= this_count; | 1889 | hmuch -= this_count; |
diff --git a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c index 763e409a1ff3..3867ac2de4c2 100644 --- a/drivers/scsi/blz1230.c +++ b/drivers/scsi/blz1230.c | |||
@@ -224,7 +224,7 @@ static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp) | |||
224 | static void dma_dump_state(struct NCR_ESP *esp) | 224 | static void dma_dump_state(struct NCR_ESP *esp) |
225 | { | 225 | { |
226 | ESPLOG(("intreq:<%04x>, intena:<%04x>\n", | 226 | ESPLOG(("intreq:<%04x>, intena:<%04x>\n", |
227 | custom.intreqr, custom.intenar)); | 227 | amiga_custom.intreqr, amiga_custom.intenar)); |
228 | } | 228 | } |
229 | 229 | ||
230 | void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) | 230 | void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) |
@@ -298,7 +298,7 @@ static int dma_irq_p(struct NCR_ESP *esp) | |||
298 | 298 | ||
299 | static int dma_ports_p(struct NCR_ESP *esp) | 299 | static int dma_ports_p(struct NCR_ESP *esp) |
300 | { | 300 | { |
301 | return ((custom.intenar) & IF_PORTS); | 301 | return ((amiga_custom.intenar) & IF_PORTS); |
302 | } | 302 | } |
303 | 303 | ||
304 | static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) | 304 | static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) |
diff --git a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c index d72d05fffdfa..4ebe69e32756 100644 --- a/drivers/scsi/blz2060.c +++ b/drivers/scsi/blz2060.c | |||
@@ -190,7 +190,7 @@ static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp) | |||
190 | static void dma_dump_state(struct NCR_ESP *esp) | 190 | static void dma_dump_state(struct NCR_ESP *esp) |
191 | { | 191 | { |
192 | ESPLOG(("intreq:<%04x>, intena:<%04x>\n", | 192 | ESPLOG(("intreq:<%04x>, intena:<%04x>\n", |
193 | custom.intreqr, custom.intenar)); | 193 | amiga_custom.intreqr, amiga_custom.intenar)); |
194 | } | 194 | } |
195 | 195 | ||
196 | static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) | 196 | static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) |
@@ -251,7 +251,7 @@ static void dma_led_on(struct NCR_ESP *esp) | |||
251 | 251 | ||
252 | static int dma_ports_p(struct NCR_ESP *esp) | 252 | static int dma_ports_p(struct NCR_ESP *esp) |
253 | { | 253 | { |
254 | return ((custom.intenar) & IF_PORTS); | 254 | return ((amiga_custom.intenar) & IF_PORTS); |
255 | } | 255 | } |
256 | 256 | ||
257 | static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) | 257 | static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) |
diff --git a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c index f9b940e56430..a4a4fac5c0a1 100644 --- a/drivers/scsi/cyberstorm.c +++ b/drivers/scsi/cyberstorm.c | |||
@@ -223,7 +223,7 @@ static void dma_dump_state(struct NCR_ESP *esp) | |||
223 | esp->esp_id, ((struct cyber_dma_registers *) | 223 | esp->esp_id, ((struct cyber_dma_registers *) |
224 | (esp->dregs))->cond_reg)); | 224 | (esp->dregs))->cond_reg)); |
225 | ESPLOG(("intreq:<%04x>, intena:<%04x>\n", | 225 | ESPLOG(("intreq:<%04x>, intena:<%04x>\n", |
226 | custom.intreqr, custom.intenar)); | 226 | amiga_custom.intreqr, amiga_custom.intenar)); |
227 | } | 227 | } |
228 | 228 | ||
229 | static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) | 229 | static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) |
@@ -322,7 +322,7 @@ static void dma_led_on(struct NCR_ESP *esp) | |||
322 | 322 | ||
323 | static int dma_ports_p(struct NCR_ESP *esp) | 323 | static int dma_ports_p(struct NCR_ESP *esp) |
324 | { | 324 | { |
325 | return ((custom.intenar) & IF_PORTS); | 325 | return ((amiga_custom.intenar) & IF_PORTS); |
326 | } | 326 | } |
327 | 327 | ||
328 | static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) | 328 | static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) |
diff --git a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c index a3caabfd7557..3a803d73bc5f 100644 --- a/drivers/scsi/cyberstormII.c +++ b/drivers/scsi/cyberstormII.c | |||
@@ -200,7 +200,7 @@ static void dma_dump_state(struct NCR_ESP *esp) | |||
200 | esp->esp_id, ((struct cyberII_dma_registers *) | 200 | esp->esp_id, ((struct cyberII_dma_registers *) |
201 | (esp->dregs))->cond_reg)); | 201 | (esp->dregs))->cond_reg)); |
202 | ESPLOG(("intreq:<%04x>, intena:<%04x>\n", | 202 | ESPLOG(("intreq:<%04x>, intena:<%04x>\n", |
203 | custom.intreqr, custom.intenar)); | 203 | amiga_custom.intreqr, amiga_custom.intenar)); |
204 | } | 204 | } |
205 | 205 | ||
206 | static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) | 206 | static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) |
@@ -259,7 +259,7 @@ static void dma_led_on(struct NCR_ESP *esp) | |||
259 | 259 | ||
260 | static int dma_ports_p(struct NCR_ESP *esp) | 260 | static int dma_ports_p(struct NCR_ESP *esp) |
261 | { | 261 | { |
262 | return ((custom.intenar) & IF_PORTS); | 262 | return ((amiga_custom.intenar) & IF_PORTS); |
263 | } | 263 | } |
264 | 264 | ||
265 | static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) | 265 | static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) |
diff --git a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c index ccee68b52f7e..8ae9c406a83b 100644 --- a/drivers/scsi/fastlane.c +++ b/drivers/scsi/fastlane.c | |||
@@ -268,7 +268,7 @@ static void dma_dump_state(struct NCR_ESP *esp) | |||
268 | esp->esp_id, ((struct fastlane_dma_registers *) | 268 | esp->esp_id, ((struct fastlane_dma_registers *) |
269 | (esp->dregs))->cond_reg)); | 269 | (esp->dregs))->cond_reg)); |
270 | ESPLOG(("intreq:<%04x>, intena:<%04x>\n", | 270 | ESPLOG(("intreq:<%04x>, intena:<%04x>\n", |
271 | custom.intreqr, custom.intenar)); | 271 | amiga_custom.intreqr, amiga_custom.intenar)); |
272 | } | 272 | } |
273 | 273 | ||
274 | static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) | 274 | static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length) |
@@ -368,7 +368,7 @@ static void dma_led_on(struct NCR_ESP *esp) | |||
368 | 368 | ||
369 | static int dma_ports_p(struct NCR_ESP *esp) | 369 | static int dma_ports_p(struct NCR_ESP *esp) |
370 | { | 370 | { |
371 | return ((custom.intenar) & IF_PORTS); | 371 | return ((amiga_custom.intenar) & IF_PORTS); |
372 | } | 372 | } |
373 | 373 | ||
374 | static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) | 374 | static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) |
diff --git a/drivers/scsi/oktagon_esp.c b/drivers/scsi/oktagon_esp.c index 5d9c9ada814f..dee426f8c07b 100644 --- a/drivers/scsi/oktagon_esp.c +++ b/drivers/scsi/oktagon_esp.c | |||
@@ -490,7 +490,7 @@ static void dma_led_on(struct NCR_ESP *esp) | |||
490 | 490 | ||
491 | static int dma_ports_p(struct NCR_ESP *esp) | 491 | static int dma_ports_p(struct NCR_ESP *esp) |
492 | { | 492 | { |
493 | return ((custom.intenar) & IF_PORTS); | 493 | return ((amiga_custom.intenar) & IF_PORTS); |
494 | } | 494 | } |
495 | 495 | ||
496 | static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) | 496 | static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write) |
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 3ded9daaf4a0..0e529f8171c4 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -221,8 +221,6 @@ static struct bus_type pseudo_lld_bus; | |||
221 | static struct device_driver sdebug_driverfs_driver = { | 221 | static struct device_driver sdebug_driverfs_driver = { |
222 | .name = sdebug_proc_name, | 222 | .name = sdebug_proc_name, |
223 | .bus = &pseudo_lld_bus, | 223 | .bus = &pseudo_lld_bus, |
224 | .probe = sdebug_driver_probe, | ||
225 | .remove = sdebug_driver_remove, | ||
226 | }; | 224 | }; |
227 | 225 | ||
228 | static const int check_condition_result = | 226 | static const int check_condition_result = |
@@ -1796,6 +1794,8 @@ static int pseudo_lld_bus_match(struct device *dev, | |||
1796 | static struct bus_type pseudo_lld_bus = { | 1794 | static struct bus_type pseudo_lld_bus = { |
1797 | .name = "pseudo", | 1795 | .name = "pseudo", |
1798 | .match = pseudo_lld_bus_match, | 1796 | .match = pseudo_lld_bus_match, |
1797 | .probe = sdebug_driver_probe, | ||
1798 | .remove = sdebug_driver_remove, | ||
1799 | }; | 1799 | }; |
1800 | 1800 | ||
1801 | static void sdebug_release_adapter(struct device * dev) | 1801 | static void sdebug_release_adapter(struct device * dev) |
diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index fd63add6a577..fb53eeaee617 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c | |||
@@ -465,7 +465,7 @@ wd33c93_execute(struct Scsi_Host *instance) | |||
465 | */ | 465 | */ |
466 | 466 | ||
467 | cmd = (struct scsi_cmnd *) hostdata->input_Q; | 467 | cmd = (struct scsi_cmnd *) hostdata->input_Q; |
468 | prev = 0; | 468 | prev = NULL; |
469 | while (cmd) { | 469 | while (cmd) { |
470 | if (!(hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))) | 470 | if (!(hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))) |
471 | break; | 471 | break; |
@@ -1569,7 +1569,7 @@ wd33c93_abort(struct scsi_cmnd * cmd) | |||
1569 | */ | 1569 | */ |
1570 | 1570 | ||
1571 | tmp = (struct scsi_cmnd *) hostdata->input_Q; | 1571 | tmp = (struct scsi_cmnd *) hostdata->input_Q; |
1572 | prev = 0; | 1572 | prev = NULL; |
1573 | while (tmp) { | 1573 | while (tmp) { |
1574 | if (tmp == cmd) { | 1574 | if (tmp == cmd) { |
1575 | if (prev) | 1575 | if (prev) |
diff --git a/drivers/serial/68328serial.c b/drivers/serial/68328serial.c index 4dd5c3f98167..8cbf0fc5a225 100644 --- a/drivers/serial/68328serial.c +++ b/drivers/serial/68328serial.c | |||
@@ -143,7 +143,6 @@ static int m68328_console_cbaud = DEFAULT_CBAUD; | |||
143 | * memory if large numbers of serial ports are open. | 143 | * memory if large numbers of serial ports are open. |
144 | */ | 144 | */ |
145 | static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */ | 145 | static unsigned char tmp_buf[SERIAL_XMIT_SIZE]; /* This is cheating */ |
146 | DECLARE_MUTEX(tmp_buf_sem); | ||
147 | 146 | ||
148 | static inline int serial_paranoia_check(struct m68k_serial *info, | 147 | static inline int serial_paranoia_check(struct m68k_serial *info, |
149 | char *name, const char *routine) | 148 | char *name, const char *routine) |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 54e5cc0dd5f8..fb610c3634a4 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/serial.h> | 41 | #include <linux/serial.h> |
42 | #include <linux/serial_8250.h> | 42 | #include <linux/serial_8250.h> |
43 | #include <linux/nmi.h> | 43 | #include <linux/nmi.h> |
44 | #include <linux/mutex.h> | ||
44 | 45 | ||
45 | #include <asm/io.h> | 46 | #include <asm/io.h> |
46 | #include <asm/irq.h> | 47 | #include <asm/irq.h> |
@@ -2467,7 +2468,7 @@ static struct platform_device *serial8250_isa_devs; | |||
2467 | * 16x50 serial ports to be configured at run-time, to support PCMCIA | 2468 | * 16x50 serial ports to be configured at run-time, to support PCMCIA |
2468 | * modems and PCI multiport cards. | 2469 | * modems and PCI multiport cards. |
2469 | */ | 2470 | */ |
2470 | static DECLARE_MUTEX(serial_sem); | 2471 | static DEFINE_MUTEX(serial_mutex); |
2471 | 2472 | ||
2472 | static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port) | 2473 | static struct uart_8250_port *serial8250_find_match_or_unused(struct uart_port *port) |
2473 | { | 2474 | { |
@@ -2522,7 +2523,7 @@ int serial8250_register_port(struct uart_port *port) | |||
2522 | if (port->uartclk == 0) | 2523 | if (port->uartclk == 0) |
2523 | return -EINVAL; | 2524 | return -EINVAL; |
2524 | 2525 | ||
2525 | down(&serial_sem); | 2526 | mutex_lock(&serial_mutex); |
2526 | 2527 | ||
2527 | uart = serial8250_find_match_or_unused(port); | 2528 | uart = serial8250_find_match_or_unused(port); |
2528 | if (uart) { | 2529 | if (uart) { |
@@ -2544,7 +2545,7 @@ int serial8250_register_port(struct uart_port *port) | |||
2544 | if (ret == 0) | 2545 | if (ret == 0) |
2545 | ret = uart->port.line; | 2546 | ret = uart->port.line; |
2546 | } | 2547 | } |
2547 | up(&serial_sem); | 2548 | mutex_unlock(&serial_mutex); |
2548 | 2549 | ||
2549 | return ret; | 2550 | return ret; |
2550 | } | 2551 | } |
@@ -2561,7 +2562,7 @@ void serial8250_unregister_port(int line) | |||
2561 | { | 2562 | { |
2562 | struct uart_8250_port *uart = &serial8250_ports[line]; | 2563 | struct uart_8250_port *uart = &serial8250_ports[line]; |
2563 | 2564 | ||
2564 | down(&serial_sem); | 2565 | mutex_lock(&serial_mutex); |
2565 | uart_remove_one_port(&serial8250_reg, &uart->port); | 2566 | uart_remove_one_port(&serial8250_reg, &uart->port); |
2566 | if (serial8250_isa_devs) { | 2567 | if (serial8250_isa_devs) { |
2567 | uart->port.flags &= ~UPF_BOOT_AUTOCONF; | 2568 | uart->port.flags &= ~UPF_BOOT_AUTOCONF; |
@@ -2571,7 +2572,7 @@ void serial8250_unregister_port(int line) | |||
2571 | } else { | 2572 | } else { |
2572 | uart->port.dev = NULL; | 2573 | uart->port.dev = NULL; |
2573 | } | 2574 | } |
2574 | up(&serial_sem); | 2575 | mutex_unlock(&serial_mutex); |
2575 | } | 2576 | } |
2576 | EXPORT_SYMBOL(serial8250_unregister_port); | 2577 | EXPORT_SYMBOL(serial8250_unregister_port); |
2577 | 2578 | ||
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 698cb76819d9..843717275d49 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
@@ -280,6 +280,40 @@ config SERIAL_AMBA_PL011_CONSOLE | |||
280 | your boot loader (lilo or loadlin) about how to pass options to the | 280 | your boot loader (lilo or loadlin) about how to pass options to the |
281 | kernel at boot time.) | 281 | kernel at boot time.) |
282 | 282 | ||
283 | config SERIAL_AT91 | ||
284 | bool "AT91RM9200 serial port support" | ||
285 | depends on ARM && ARCH_AT91RM9200 | ||
286 | select SERIAL_CORE | ||
287 | help | ||
288 | This enables the driver for the on-chip UARTs of the AT91RM9200 | ||
289 | processor. | ||
290 | |||
291 | config SERIAL_AT91_CONSOLE | ||
292 | bool "Support for console on AT91RM9200 serial port" | ||
293 | depends on SERIAL_AT91=y | ||
294 | select SERIAL_CORE_CONSOLE | ||
295 | help | ||
296 | Say Y here if you wish to use a UART on the AT91RM9200 as the system | ||
297 | console (the system console is the device which receives all kernel | ||
298 | messages and warnings and which allows logins in single user mode). | ||
299 | |||
300 | config SERIAL_AT91_TTYAT | ||
301 | bool "Install as device ttyAT0-4 instead of ttyS0-4" | ||
302 | depends on SERIAL_AT91=y | ||
303 | help | ||
304 | Say Y here if you wish to have the five internal AT91RM9200 UARTs | ||
305 | appear as /dev/ttyAT0-4 (major 240, minor 0-4) instead of the | ||
306 | normal /dev/ttyS0-4 (major 4, minor 64-68). This is necessary if | ||
307 | you also want other UARTs, such as external 8250/16C550 compatible | ||
308 | UARTs. | ||
309 | The ttySn nodes are legally reserved for the 8250 serial driver | ||
310 | but are often misused by other serial drivers. | ||
311 | |||
312 | To use this, you should create suitable ttyATn device nodes in | ||
313 | /dev/, and pass "console=ttyATn" to the kernel. | ||
314 | |||
315 | Say Y if you have an external 8250/16C550 UART. If unsure, say N. | ||
316 | |||
283 | config SERIAL_CLPS711X | 317 | config SERIAL_CLPS711X |
284 | tristate "CLPS711X serial port support" | 318 | tristate "CLPS711X serial port support" |
285 | depends on ARM && ARCH_CLPS711X | 319 | depends on ARM && ARCH_CLPS711X |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 137148bba4fa..24a583e482bb 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
@@ -56,3 +56,4 @@ obj-$(CONFIG_SERIAL_JSM) += jsm/ | |||
56 | obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o | 56 | obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o |
57 | obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o | 57 | obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o |
58 | obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o | 58 | obj-$(CONFIG_SERIAL_SGI_IOC4) += ioc4_serial.o |
59 | obj-$(CONFIG_SERIAL_AT91) += at91_serial.o | ||
diff --git a/drivers/serial/at91_serial.c b/drivers/serial/at91_serial.c new file mode 100644 index 000000000000..0e206063d685 --- /dev/null +++ b/drivers/serial/at91_serial.c | |||
@@ -0,0 +1,894 @@ | |||
1 | /* | ||
2 | * linux/drivers/char/at91_serial.c | ||
3 | * | ||
4 | * Driver for Atmel AT91RM9200 Serial ports | ||
5 | * | ||
6 | * Copyright (C) 2003 Rick Bronson | ||
7 | * | ||
8 | * Based on drivers/char/serial_sa1100.c, by Deep Blue Solutions Ltd. | ||
9 | * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation; either version 2 of the License, or | ||
14 | * (at your option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | * | ||
25 | */ | ||
26 | #include <linux/config.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/tty.h> | ||
29 | #include <linux/ioport.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/init.h> | ||
32 | #include <linux/serial.h> | ||
33 | #include <linux/console.h> | ||
34 | #include <linux/sysrq.h> | ||
35 | #include <linux/tty_flip.h> | ||
36 | |||
37 | #include <asm/io.h> | ||
38 | |||
39 | #include <asm/arch/at91rm9200_usart.h> | ||
40 | #include <asm/mach/serial_at91rm9200.h> | ||
41 | #include <asm/arch/board.h> | ||
42 | #include <asm/arch/pio.h> | ||
43 | |||
44 | |||
45 | #if defined(CONFIG_SERIAL_AT91_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) | ||
46 | #define SUPPORT_SYSRQ | ||
47 | #endif | ||
48 | |||
49 | #include <linux/serial_core.h> | ||
50 | |||
51 | #ifdef CONFIG_SERIAL_AT91_TTYAT | ||
52 | |||
53 | /* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we | ||
54 | * should coexist with the 8250 driver, such as if we have an external 16C550 | ||
55 | * UART. */ | ||
56 | #define SERIAL_AT91_MAJOR 204 | ||
57 | #define MINOR_START 154 | ||
58 | #define AT91_DEVICENAME "ttyAT" | ||
59 | |||
60 | #else | ||
61 | |||
62 | /* Use device name ttyS, major 4, minor 64-68. This is the usual serial port | ||
63 | * name, but it is legally reserved for the 8250 driver. */ | ||
64 | #define SERIAL_AT91_MAJOR TTY_MAJOR | ||
65 | #define MINOR_START 64 | ||
66 | #define AT91_DEVICENAME "ttyS" | ||
67 | |||
68 | #endif | ||
69 | |||
70 | #define AT91_VA_BASE_DBGU ((unsigned long) AT91_VA_BASE_SYS + AT91_DBGU) | ||
71 | #define AT91_ISR_PASS_LIMIT 256 | ||
72 | |||
73 | #define UART_PUT_CR(port,v) writel(v, (port)->membase + AT91_US_CR) | ||
74 | #define UART_GET_MR(port) readl((port)->membase + AT91_US_MR) | ||
75 | #define UART_PUT_MR(port,v) writel(v, (port)->membase + AT91_US_MR) | ||
76 | #define UART_PUT_IER(port,v) writel(v, (port)->membase + AT91_US_IER) | ||
77 | #define UART_PUT_IDR(port,v) writel(v, (port)->membase + AT91_US_IDR) | ||
78 | #define UART_GET_IMR(port) readl((port)->membase + AT91_US_IMR) | ||
79 | #define UART_GET_CSR(port) readl((port)->membase + AT91_US_CSR) | ||
80 | #define UART_GET_CHAR(port) readl((port)->membase + AT91_US_RHR) | ||
81 | #define UART_PUT_CHAR(port,v) writel(v, (port)->membase + AT91_US_THR) | ||
82 | #define UART_GET_BRGR(port) readl((port)->membase + AT91_US_BRGR) | ||
83 | #define UART_PUT_BRGR(port,v) writel(v, (port)->membase + AT91_US_BRGR) | ||
84 | #define UART_PUT_RTOR(port,v) writel(v, (port)->membase + AT91_US_RTOR) | ||
85 | |||
86 | // #define UART_GET_CR(port) readl((port)->membase + AT91_US_CR) // is write-only | ||
87 | |||
88 | /* PDC registers */ | ||
89 | #define UART_PUT_PTCR(port,v) writel(v, (port)->membase + AT91_PDC_PTCR) | ||
90 | #define UART_PUT_RPR(port,v) writel(v, (port)->membase + AT91_PDC_RPR) | ||
91 | #define UART_PUT_RCR(port,v) writel(v, (port)->membase + AT91_PDC_RCR) | ||
92 | #define UART_GET_RCR(port) readl((port)->membase + AT91_PDC_RCR) | ||
93 | #define UART_PUT_RNPR(port,v) writel(v, (port)->membase + AT91_PDC_RNPR) | ||
94 | #define UART_PUT_RNCR(port,v) writel(v, (port)->membase + AT91_PDC_RNCR) | ||
95 | |||
96 | |||
97 | static int (*at91_open)(struct uart_port *); | ||
98 | static void (*at91_close)(struct uart_port *); | ||
99 | |||
100 | #ifdef SUPPORT_SYSRQ | ||
101 | static struct console at91_console; | ||
102 | #endif | ||
103 | |||
104 | /* | ||
105 | * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty. | ||
106 | */ | ||
107 | static u_int at91_tx_empty(struct uart_port *port) | ||
108 | { | ||
109 | return (UART_GET_CSR(port) & AT91_US_TXEMPTY) ? TIOCSER_TEMT : 0; | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * Set state of the modem control output lines | ||
114 | */ | ||
115 | static void at91_set_mctrl(struct uart_port *port, u_int mctrl) | ||
116 | { | ||
117 | unsigned int control = 0; | ||
118 | |||
119 | /* | ||
120 | * Errata #39: RTS0 is not internally connected to PA21. We need to drive | ||
121 | * the pin manually. | ||
122 | */ | ||
123 | if (port->mapbase == AT91_VA_BASE_US0) { | ||
124 | if (mctrl & TIOCM_RTS) | ||
125 | at91_sys_write(AT91_PIOA + PIO_CODR, AT91_PA21_RTS0); | ||
126 | else | ||
127 | at91_sys_write(AT91_PIOA + PIO_SODR, AT91_PA21_RTS0); | ||
128 | } | ||
129 | |||
130 | if (mctrl & TIOCM_RTS) | ||
131 | control |= AT91_US_RTSEN; | ||
132 | else | ||
133 | control |= AT91_US_RTSDIS; | ||
134 | |||
135 | if (mctrl & TIOCM_DTR) | ||
136 | control |= AT91_US_DTREN; | ||
137 | else | ||
138 | control |= AT91_US_DTRDIS; | ||
139 | |||
140 | UART_PUT_CR(port,control); | ||
141 | } | ||
142 | |||
143 | /* | ||
144 | * Get state of the modem control input lines | ||
145 | */ | ||
146 | static u_int at91_get_mctrl(struct uart_port *port) | ||
147 | { | ||
148 | unsigned int status, ret = 0; | ||
149 | |||
150 | status = UART_GET_CSR(port); | ||
151 | |||
152 | /* | ||
153 | * The control signals are active low. | ||
154 | */ | ||
155 | if (!(status & AT91_US_DCD)) | ||
156 | ret |= TIOCM_CD; | ||
157 | if (!(status & AT91_US_CTS)) | ||
158 | ret |= TIOCM_CTS; | ||
159 | if (!(status & AT91_US_DSR)) | ||
160 | ret |= TIOCM_DSR; | ||
161 | if (!(status & AT91_US_RI)) | ||
162 | ret |= TIOCM_RI; | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * Stop transmitting. | ||
169 | */ | ||
170 | static void at91_stop_tx(struct uart_port *port) | ||
171 | { | ||
172 | UART_PUT_IDR(port, AT91_US_TXRDY); | ||
173 | port->read_status_mask &= ~AT91_US_TXRDY; | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * Start transmitting. | ||
178 | */ | ||
179 | static void at91_start_tx(struct uart_port *port) | ||
180 | { | ||
181 | port->read_status_mask |= AT91_US_TXRDY; | ||
182 | UART_PUT_IER(port, AT91_US_TXRDY); | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * Stop receiving - port is in process of being closed. | ||
187 | */ | ||
188 | static void at91_stop_rx(struct uart_port *port) | ||
189 | { | ||
190 | UART_PUT_IDR(port, AT91_US_RXRDY); | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | * Enable modem status interrupts | ||
195 | */ | ||
196 | static void at91_enable_ms(struct uart_port *port) | ||
197 | { | ||
198 | port->read_status_mask |= (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC); | ||
199 | UART_PUT_IER(port, AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC); | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * Control the transmission of a break signal | ||
204 | */ | ||
205 | static void at91_break_ctl(struct uart_port *port, int break_state) | ||
206 | { | ||
207 | if (break_state != 0) | ||
208 | UART_PUT_CR(port, AT91_US_STTBRK); /* start break */ | ||
209 | else | ||
210 | UART_PUT_CR(port, AT91_US_STPBRK); /* stop break */ | ||
211 | } | ||
212 | |||
213 | /* | ||
214 | * Characters received (called from interrupt handler) | ||
215 | */ | ||
216 | static void at91_rx_chars(struct uart_port *port, struct pt_regs *regs) | ||
217 | { | ||
218 | struct tty_struct *tty = port->info->tty; | ||
219 | unsigned int status, ch, flg; | ||
220 | |||
221 | status = UART_GET_CSR(port) & port->read_status_mask; | ||
222 | while (status & (AT91_US_RXRDY)) { | ||
223 | ch = UART_GET_CHAR(port); | ||
224 | |||
225 | if (tty->flip.count >= TTY_FLIPBUF_SIZE) | ||
226 | goto ignore_char; | ||
227 | port->icount.rx++; | ||
228 | |||
229 | flg = TTY_NORMAL; | ||
230 | |||
231 | /* | ||
232 | * note that the error handling code is | ||
233 | * out of the main execution path | ||
234 | */ | ||
235 | if (unlikely(status & (AT91_US_PARE | AT91_US_FRAME | AT91_US_OVRE))) { | ||
236 | UART_PUT_CR(port, AT91_US_RSTSTA); /* clear error */ | ||
237 | if (status & (AT91_US_PARE)) | ||
238 | port->icount.parity++; | ||
239 | if (status & (AT91_US_FRAME)) | ||
240 | port->icount.frame++; | ||
241 | if (status & (AT91_US_OVRE)) | ||
242 | port->icount.overrun++; | ||
243 | |||
244 | if (status & AT91_US_PARE) | ||
245 | flg = TTY_PARITY; | ||
246 | else if (status & AT91_US_FRAME) | ||
247 | flg = TTY_FRAME; | ||
248 | if (status & AT91_US_OVRE) { | ||
249 | /* | ||
250 | * overrun does *not* affect the character | ||
251 | * we read from the FIFO | ||
252 | */ | ||
253 | tty_insert_flip_char(tty, ch, flg); | ||
254 | ch = 0; | ||
255 | flg = TTY_OVERRUN; | ||
256 | } | ||
257 | #ifdef SUPPORT_SYSRQ | ||
258 | port->sysrq = 0; | ||
259 | #endif | ||
260 | } | ||
261 | |||
262 | if (uart_handle_sysrq_char(port, ch, regs)) | ||
263 | goto ignore_char; | ||
264 | |||
265 | tty_insert_flip_char(tty, ch, flg); | ||
266 | |||
267 | ignore_char: | ||
268 | status = UART_GET_CSR(port) & port->read_status_mask; | ||
269 | } | ||
270 | |||
271 | tty_flip_buffer_push(tty); | ||
272 | } | ||
273 | |||
274 | /* | ||
275 | * Transmit characters (called from interrupt handler) | ||
276 | */ | ||
277 | static void at91_tx_chars(struct uart_port *port) | ||
278 | { | ||
279 | struct circ_buf *xmit = &port->info->xmit; | ||
280 | |||
281 | if (port->x_char) { | ||
282 | UART_PUT_CHAR(port, port->x_char); | ||
283 | port->icount.tx++; | ||
284 | port->x_char = 0; | ||
285 | return; | ||
286 | } | ||
287 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) { | ||
288 | at91_stop_tx(port); | ||
289 | return; | ||
290 | } | ||
291 | |||
292 | while (UART_GET_CSR(port) & AT91_US_TXRDY) { | ||
293 | UART_PUT_CHAR(port, xmit->buf[xmit->tail]); | ||
294 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
295 | port->icount.tx++; | ||
296 | if (uart_circ_empty(xmit)) | ||
297 | break; | ||
298 | } | ||
299 | |||
300 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
301 | uart_write_wakeup(port); | ||
302 | |||
303 | if (uart_circ_empty(xmit)) | ||
304 | at91_stop_tx(port); | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | * Interrupt handler | ||
309 | */ | ||
310 | static irqreturn_t at91_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
311 | { | ||
312 | struct uart_port *port = dev_id; | ||
313 | unsigned int status, pending, pass_counter = 0; | ||
314 | |||
315 | status = UART_GET_CSR(port); | ||
316 | pending = status & port->read_status_mask; | ||
317 | if (pending) { | ||
318 | do { | ||
319 | if (pending & AT91_US_RXRDY) | ||
320 | at91_rx_chars(port, regs); | ||
321 | |||
322 | /* Clear the relevent break bits */ | ||
323 | if (pending & AT91_US_RXBRK) { | ||
324 | UART_PUT_CR(port, AT91_US_RSTSTA); | ||
325 | port->icount.brk++; | ||
326 | uart_handle_break(port); | ||
327 | } | ||
328 | |||
329 | // TODO: All reads to CSR will clear these interrupts! | ||
330 | if (pending & AT91_US_RIIC) port->icount.rng++; | ||
331 | if (pending & AT91_US_DSRIC) port->icount.dsr++; | ||
332 | if (pending & AT91_US_DCDIC) | ||
333 | uart_handle_dcd_change(port, !(status & AT91_US_DCD)); | ||
334 | if (pending & AT91_US_CTSIC) | ||
335 | uart_handle_cts_change(port, !(status & AT91_US_CTS)); | ||
336 | if (pending & (AT91_US_RIIC | AT91_US_DSRIC | AT91_US_DCDIC | AT91_US_CTSIC)) | ||
337 | wake_up_interruptible(&port->info->delta_msr_wait); | ||
338 | |||
339 | if (pending & AT91_US_TXRDY) | ||
340 | at91_tx_chars(port); | ||
341 | if (pass_counter++ > AT91_ISR_PASS_LIMIT) | ||
342 | break; | ||
343 | |||
344 | status = UART_GET_CSR(port); | ||
345 | pending = status & port->read_status_mask; | ||
346 | } while (pending); | ||
347 | } | ||
348 | return IRQ_HANDLED; | ||
349 | } | ||
350 | |||
351 | /* | ||
352 | * Perform initialization and enable port for reception | ||
353 | */ | ||
354 | static int at91_startup(struct uart_port *port) | ||
355 | { | ||
356 | int retval; | ||
357 | |||
358 | /* | ||
359 | * Ensure that no interrupts are enabled otherwise when | ||
360 | * request_irq() is called we could get stuck trying to | ||
361 | * handle an unexpected interrupt | ||
362 | */ | ||
363 | UART_PUT_IDR(port, -1); | ||
364 | |||
365 | /* | ||
366 | * Allocate the IRQ | ||
367 | */ | ||
368 | retval = request_irq(port->irq, at91_interrupt, SA_SHIRQ, "at91_serial", port); | ||
369 | if (retval) { | ||
370 | printk("at91_serial: at91_startup - Can't get irq\n"); | ||
371 | return retval; | ||
372 | } | ||
373 | |||
374 | /* | ||
375 | * If there is a specific "open" function (to register | ||
376 | * control line interrupts) | ||
377 | */ | ||
378 | if (at91_open) { | ||
379 | retval = at91_open(port); | ||
380 | if (retval) { | ||
381 | free_irq(port->irq, port); | ||
382 | return retval; | ||
383 | } | ||
384 | } | ||
385 | |||
386 | port->read_status_mask = AT91_US_RXRDY | AT91_US_TXRDY | AT91_US_OVRE | ||
387 | | AT91_US_FRAME | AT91_US_PARE | AT91_US_RXBRK; | ||
388 | /* | ||
389 | * Finally, enable the serial port | ||
390 | */ | ||
391 | UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); | ||
392 | UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); /* enable xmit & rcvr */ | ||
393 | UART_PUT_IER(port, AT91_US_RXRDY); /* do receive only */ | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | /* | ||
398 | * Disable the port | ||
399 | */ | ||
400 | static void at91_shutdown(struct uart_port *port) | ||
401 | { | ||
402 | /* | ||
403 | * Disable all interrupts, port and break condition. | ||
404 | */ | ||
405 | UART_PUT_CR(port, AT91_US_RSTSTA); | ||
406 | UART_PUT_IDR(port, -1); | ||
407 | |||
408 | /* | ||
409 | * Free the interrupt | ||
410 | */ | ||
411 | free_irq(port->irq, port); | ||
412 | |||
413 | /* | ||
414 | * If there is a specific "close" function (to unregister | ||
415 | * control line interrupts) | ||
416 | */ | ||
417 | if (at91_close) | ||
418 | at91_close(port); | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | * Power / Clock management. | ||
423 | */ | ||
424 | static void at91_serial_pm(struct uart_port *port, unsigned int state, unsigned int oldstate) | ||
425 | { | ||
426 | switch (state) { | ||
427 | case 0: | ||
428 | /* | ||
429 | * Enable the peripheral clock for this serial port. | ||
430 | * This is called on uart_open() or a resume event. | ||
431 | */ | ||
432 | at91_sys_write(AT91_PMC_PCER, 1 << port->irq); | ||
433 | break; | ||
434 | case 3: | ||
435 | /* | ||
436 | * Disable the peripheral clock for this serial port. | ||
437 | * This is called on uart_close() or a suspend event. | ||
438 | */ | ||
439 | if (port->irq != AT91_ID_SYS) /* is this a shared clock? */ | ||
440 | at91_sys_write(AT91_PMC_PCDR, 1 << port->irq); | ||
441 | break; | ||
442 | default: | ||
443 | printk(KERN_ERR "at91_serial: unknown pm %d\n", state); | ||
444 | } | ||
445 | } | ||
446 | |||
447 | /* | ||
448 | * Change the port parameters | ||
449 | */ | ||
450 | static void at91_set_termios(struct uart_port *port, struct termios * termios, struct termios * old) | ||
451 | { | ||
452 | unsigned long flags; | ||
453 | unsigned int mode, imr, quot, baud; | ||
454 | |||
455 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); | ||
456 | quot = uart_get_divisor(port, baud); | ||
457 | |||
458 | /* Get current mode register */ | ||
459 | mode = UART_GET_MR(port) & ~(AT91_US_CHRL | AT91_US_NBSTOP | AT91_US_PAR); | ||
460 | |||
461 | /* byte size */ | ||
462 | switch (termios->c_cflag & CSIZE) { | ||
463 | case CS5: | ||
464 | mode |= AT91_US_CHRL_5; | ||
465 | break; | ||
466 | case CS6: | ||
467 | mode |= AT91_US_CHRL_6; | ||
468 | break; | ||
469 | case CS7: | ||
470 | mode |= AT91_US_CHRL_7; | ||
471 | break; | ||
472 | default: | ||
473 | mode |= AT91_US_CHRL_8; | ||
474 | break; | ||
475 | } | ||
476 | |||
477 | /* stop bits */ | ||
478 | if (termios->c_cflag & CSTOPB) | ||
479 | mode |= AT91_US_NBSTOP_2; | ||
480 | |||
481 | /* parity */ | ||
482 | if (termios->c_cflag & PARENB) { | ||
483 | if (termios->c_cflag & CMSPAR) { /* Mark or Space parity */ | ||
484 | if (termios->c_cflag & PARODD) | ||
485 | mode |= AT91_US_PAR_MARK; | ||
486 | else | ||
487 | mode |= AT91_US_PAR_SPACE; | ||
488 | } | ||
489 | else if (termios->c_cflag & PARODD) | ||
490 | mode |= AT91_US_PAR_ODD; | ||
491 | else | ||
492 | mode |= AT91_US_PAR_EVEN; | ||
493 | } | ||
494 | else | ||
495 | mode |= AT91_US_PAR_NONE; | ||
496 | |||
497 | spin_lock_irqsave(&port->lock, flags); | ||
498 | |||
499 | port->read_status_mask |= AT91_US_OVRE; | ||
500 | if (termios->c_iflag & INPCK) | ||
501 | port->read_status_mask |= AT91_US_FRAME | AT91_US_PARE; | ||
502 | if (termios->c_iflag & (BRKINT | PARMRK)) | ||
503 | port->read_status_mask |= AT91_US_RXBRK; | ||
504 | |||
505 | /* | ||
506 | * Characters to ignore | ||
507 | */ | ||
508 | port->ignore_status_mask = 0; | ||
509 | if (termios->c_iflag & IGNPAR) | ||
510 | port->ignore_status_mask |= (AT91_US_FRAME | AT91_US_PARE); | ||
511 | if (termios->c_iflag & IGNBRK) { | ||
512 | port->ignore_status_mask |= AT91_US_RXBRK; | ||
513 | /* | ||
514 | * If we're ignoring parity and break indicators, | ||
515 | * ignore overruns too (for real raw support). | ||
516 | */ | ||
517 | if (termios->c_iflag & IGNPAR) | ||
518 | port->ignore_status_mask |= AT91_US_OVRE; | ||
519 | } | ||
520 | |||
521 | // TODO: Ignore all characters if CREAD is set. | ||
522 | |||
523 | /* update the per-port timeout */ | ||
524 | uart_update_timeout(port, termios->c_cflag, baud); | ||
525 | |||
526 | /* disable interrupts and drain transmitter */ | ||
527 | imr = UART_GET_IMR(port); /* get interrupt mask */ | ||
528 | UART_PUT_IDR(port, -1); /* disable all interrupts */ | ||
529 | while (!(UART_GET_CSR(port) & AT91_US_TXEMPTY)) { barrier(); } | ||
530 | |||
531 | /* disable receiver and transmitter */ | ||
532 | UART_PUT_CR(port, AT91_US_TXDIS | AT91_US_RXDIS); | ||
533 | |||
534 | /* set the parity, stop bits and data size */ | ||
535 | UART_PUT_MR(port, mode); | ||
536 | |||
537 | /* set the baud rate */ | ||
538 | UART_PUT_BRGR(port, quot); | ||
539 | UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); | ||
540 | UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); | ||
541 | |||
542 | /* restore interrupts */ | ||
543 | UART_PUT_IER(port, imr); | ||
544 | |||
545 | /* CTS flow-control and modem-status interrupts */ | ||
546 | if (UART_ENABLE_MS(port, termios->c_cflag)) | ||
547 | port->ops->enable_ms(port); | ||
548 | |||
549 | spin_unlock_irqrestore(&port->lock, flags); | ||
550 | } | ||
551 | |||
552 | /* | ||
553 | * Return string describing the specified port | ||
554 | */ | ||
555 | static const char *at91_type(struct uart_port *port) | ||
556 | { | ||
557 | return (port->type == PORT_AT91RM9200) ? "AT91_SERIAL" : NULL; | ||
558 | } | ||
559 | |||
560 | /* | ||
561 | * Release the memory region(s) being used by 'port'. | ||
562 | */ | ||
563 | static void at91_release_port(struct uart_port *port) | ||
564 | { | ||
565 | release_mem_region(port->mapbase, | ||
566 | (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K); | ||
567 | } | ||
568 | |||
569 | /* | ||
570 | * Request the memory region(s) being used by 'port'. | ||
571 | */ | ||
572 | static int at91_request_port(struct uart_port *port) | ||
573 | { | ||
574 | return request_mem_region(port->mapbase, | ||
575 | (port->mapbase == AT91_VA_BASE_DBGU) ? 512 : SZ_16K, | ||
576 | "at91_serial") != NULL ? 0 : -EBUSY; | ||
577 | |||
578 | } | ||
579 | |||
580 | /* | ||
581 | * Configure/autoconfigure the port. | ||
582 | */ | ||
583 | static void at91_config_port(struct uart_port *port, int flags) | ||
584 | { | ||
585 | if (flags & UART_CONFIG_TYPE) { | ||
586 | port->type = PORT_AT91RM9200; | ||
587 | at91_request_port(port); | ||
588 | } | ||
589 | } | ||
590 | |||
591 | /* | ||
592 | * Verify the new serial_struct (for TIOCSSERIAL). | ||
593 | */ | ||
594 | static int at91_verify_port(struct uart_port *port, struct serial_struct *ser) | ||
595 | { | ||
596 | int ret = 0; | ||
597 | if (ser->type != PORT_UNKNOWN && ser->type != PORT_AT91RM9200) | ||
598 | ret = -EINVAL; | ||
599 | if (port->irq != ser->irq) | ||
600 | ret = -EINVAL; | ||
601 | if (ser->io_type != SERIAL_IO_MEM) | ||
602 | ret = -EINVAL; | ||
603 | if (port->uartclk / 16 != ser->baud_base) | ||
604 | ret = -EINVAL; | ||
605 | if ((void *)port->mapbase != ser->iomem_base) | ||
606 | ret = -EINVAL; | ||
607 | if (port->iobase != ser->port) | ||
608 | ret = -EINVAL; | ||
609 | if (ser->hub6 != 0) | ||
610 | ret = -EINVAL; | ||
611 | return ret; | ||
612 | } | ||
613 | |||
614 | static struct uart_ops at91_pops = { | ||
615 | .tx_empty = at91_tx_empty, | ||
616 | .set_mctrl = at91_set_mctrl, | ||
617 | .get_mctrl = at91_get_mctrl, | ||
618 | .stop_tx = at91_stop_tx, | ||
619 | .start_tx = at91_start_tx, | ||
620 | .stop_rx = at91_stop_rx, | ||
621 | .enable_ms = at91_enable_ms, | ||
622 | .break_ctl = at91_break_ctl, | ||
623 | .startup = at91_startup, | ||
624 | .shutdown = at91_shutdown, | ||
625 | .set_termios = at91_set_termios, | ||
626 | .type = at91_type, | ||
627 | .release_port = at91_release_port, | ||
628 | .request_port = at91_request_port, | ||
629 | .config_port = at91_config_port, | ||
630 | .verify_port = at91_verify_port, | ||
631 | .pm = at91_serial_pm, | ||
632 | }; | ||
633 | |||
634 | static struct uart_port at91_ports[AT91_NR_UART]; | ||
635 | |||
636 | void __init at91_init_ports(void) | ||
637 | { | ||
638 | static int first = 1; | ||
639 | int i; | ||
640 | |||
641 | if (!first) | ||
642 | return; | ||
643 | first = 0; | ||
644 | |||
645 | for (i = 0; i < AT91_NR_UART; i++) { | ||
646 | at91_ports[i].iotype = UPIO_MEM; | ||
647 | at91_ports[i].flags = UPF_BOOT_AUTOCONF; | ||
648 | at91_ports[i].uartclk = at91_master_clock; | ||
649 | at91_ports[i].ops = &at91_pops; | ||
650 | at91_ports[i].fifosize = 1; | ||
651 | at91_ports[i].line = i; | ||
652 | } | ||
653 | } | ||
654 | |||
655 | void __init at91_register_uart_fns(struct at91rm9200_port_fns *fns) | ||
656 | { | ||
657 | if (fns->enable_ms) | ||
658 | at91_pops.enable_ms = fns->enable_ms; | ||
659 | if (fns->get_mctrl) | ||
660 | at91_pops.get_mctrl = fns->get_mctrl; | ||
661 | if (fns->set_mctrl) | ||
662 | at91_pops.set_mctrl = fns->set_mctrl; | ||
663 | at91_open = fns->open; | ||
664 | at91_close = fns->close; | ||
665 | at91_pops.pm = fns->pm; | ||
666 | at91_pops.set_wake = fns->set_wake; | ||
667 | } | ||
668 | |||
669 | /* | ||
670 | * Setup ports. | ||
671 | */ | ||
672 | void __init at91_register_uart(int idx, int port) | ||
673 | { | ||
674 | if ((idx < 0) || (idx >= AT91_NR_UART)) { | ||
675 | printk(KERN_ERR "%s: bad index number %d\n", __FUNCTION__, idx); | ||
676 | return; | ||
677 | } | ||
678 | |||
679 | switch (port) { | ||
680 | case 0: | ||
681 | at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US0; | ||
682 | at91_ports[idx].mapbase = AT91_VA_BASE_US0; | ||
683 | at91_ports[idx].irq = AT91_ID_US0; | ||
684 | AT91_CfgPIO_USART0(); | ||
685 | break; | ||
686 | case 1: | ||
687 | at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US1; | ||
688 | at91_ports[idx].mapbase = AT91_VA_BASE_US1; | ||
689 | at91_ports[idx].irq = AT91_ID_US1; | ||
690 | AT91_CfgPIO_USART1(); | ||
691 | break; | ||
692 | case 2: | ||
693 | at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US2; | ||
694 | at91_ports[idx].mapbase = AT91_VA_BASE_US2; | ||
695 | at91_ports[idx].irq = AT91_ID_US2; | ||
696 | AT91_CfgPIO_USART2(); | ||
697 | break; | ||
698 | case 3: | ||
699 | at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_US3; | ||
700 | at91_ports[idx].mapbase = AT91_VA_BASE_US3; | ||
701 | at91_ports[idx].irq = AT91_ID_US3; | ||
702 | AT91_CfgPIO_USART3(); | ||
703 | break; | ||
704 | case 4: | ||
705 | at91_ports[idx].membase = (void __iomem *) AT91_VA_BASE_DBGU; | ||
706 | at91_ports[idx].mapbase = AT91_VA_BASE_DBGU; | ||
707 | at91_ports[idx].irq = AT91_ID_SYS; | ||
708 | AT91_CfgPIO_DBGU(); | ||
709 | break; | ||
710 | default: | ||
711 | printk(KERN_ERR "%s : bad port number %d\n", __FUNCTION__, port); | ||
712 | } | ||
713 | } | ||
714 | |||
715 | #ifdef CONFIG_SERIAL_AT91_CONSOLE | ||
716 | |||
717 | /* | ||
718 | * Interrupts are disabled on entering | ||
719 | */ | ||
720 | static void at91_console_write(struct console *co, const char *s, u_int count) | ||
721 | { | ||
722 | struct uart_port *port = at91_ports + co->index; | ||
723 | unsigned int status, i, imr; | ||
724 | |||
725 | /* | ||
726 | * First, save IMR and then disable interrupts | ||
727 | */ | ||
728 | imr = UART_GET_IMR(port); /* get interrupt mask */ | ||
729 | UART_PUT_IDR(port, AT91_US_RXRDY | AT91_US_TXRDY); | ||
730 | |||
731 | /* | ||
732 | * Now, do each character | ||
733 | */ | ||
734 | for (i = 0; i < count; i++) { | ||
735 | do { | ||
736 | status = UART_GET_CSR(port); | ||
737 | } while (!(status & AT91_US_TXRDY)); | ||
738 | UART_PUT_CHAR(port, s[i]); | ||
739 | if (s[i] == '\n') { | ||
740 | do { | ||
741 | status = UART_GET_CSR(port); | ||
742 | } while (!(status & AT91_US_TXRDY)); | ||
743 | UART_PUT_CHAR(port, '\r'); | ||
744 | } | ||
745 | } | ||
746 | |||
747 | /* | ||
748 | * Finally, wait for transmitter to become empty | ||
749 | * and restore IMR | ||
750 | */ | ||
751 | do { | ||
752 | status = UART_GET_CSR(port); | ||
753 | } while (!(status & AT91_US_TXRDY)); | ||
754 | UART_PUT_IER(port, imr); /* set interrupts back the way they were */ | ||
755 | } | ||
756 | |||
757 | /* | ||
758 | * If the port was already initialised (eg, by a boot loader), try to determine | ||
759 | * the current setup. | ||
760 | */ | ||
761 | static void __init at91_console_get_options(struct uart_port *port, int *baud, int *parity, int *bits) | ||
762 | { | ||
763 | unsigned int mr, quot; | ||
764 | |||
765 | // TODO: CR is a write-only register | ||
766 | // unsigned int cr; | ||
767 | // | ||
768 | // cr = UART_GET_CR(port) & (AT91_US_RXEN | AT91_US_TXEN); | ||
769 | // if (cr == (AT91_US_RXEN | AT91_US_TXEN)) { | ||
770 | // /* ok, the port was enabled */ | ||
771 | // } | ||
772 | |||
773 | mr = UART_GET_MR(port) & AT91_US_CHRL; | ||
774 | if (mr == AT91_US_CHRL_8) | ||
775 | *bits = 8; | ||
776 | else | ||
777 | *bits = 7; | ||
778 | |||
779 | mr = UART_GET_MR(port) & AT91_US_PAR; | ||
780 | if (mr == AT91_US_PAR_EVEN) | ||
781 | *parity = 'e'; | ||
782 | else if (mr == AT91_US_PAR_ODD) | ||
783 | *parity = 'o'; | ||
784 | |||
785 | quot = UART_GET_BRGR(port); | ||
786 | *baud = port->uartclk / (16 * (quot)); | ||
787 | } | ||
788 | |||
789 | static int __init at91_console_setup(struct console *co, char *options) | ||
790 | { | ||
791 | struct uart_port *port; | ||
792 | int baud = 115200; | ||
793 | int bits = 8; | ||
794 | int parity = 'n'; | ||
795 | int flow = 'n'; | ||
796 | |||
797 | /* | ||
798 | * Check whether an invalid uart number has been specified, and | ||
799 | * if so, search for the first available port that does have | ||
800 | * console support. | ||
801 | */ | ||
802 | port = uart_get_console(at91_ports, AT91_NR_UART, co); | ||
803 | |||
804 | /* | ||
805 | * Enable the serial console, in-case bootloader did not do it. | ||
806 | */ | ||
807 | at91_sys_write(AT91_PMC_PCER, 1 << port->irq); /* enable clock */ | ||
808 | UART_PUT_IDR(port, -1); /* disable interrupts */ | ||
809 | UART_PUT_CR(port, AT91_US_RSTSTA | AT91_US_RSTRX); | ||
810 | UART_PUT_CR(port, AT91_US_TXEN | AT91_US_RXEN); | ||
811 | |||
812 | if (options) | ||
813 | uart_parse_options(options, &baud, &parity, &bits, &flow); | ||
814 | else | ||
815 | at91_console_get_options(port, &baud, &parity, &bits); | ||
816 | |||
817 | return uart_set_options(port, co, baud, parity, bits, flow); | ||
818 | } | ||
819 | |||
820 | static struct uart_driver at91_uart; | ||
821 | |||
822 | static struct console at91_console = { | ||
823 | .name = AT91_DEVICENAME, | ||
824 | .write = at91_console_write, | ||
825 | .device = uart_console_device, | ||
826 | .setup = at91_console_setup, | ||
827 | .flags = CON_PRINTBUFFER, | ||
828 | .index = -1, | ||
829 | .data = &at91_uart, | ||
830 | }; | ||
831 | |||
832 | #define AT91_CONSOLE_DEVICE &at91_console | ||
833 | |||
834 | static int __init at91_console_init(void) | ||
835 | { | ||
836 | at91_init_ports(); | ||
837 | |||
838 | at91_console.index = at91_console_port; | ||
839 | register_console(&at91_console); | ||
840 | return 0; | ||
841 | } | ||
842 | console_initcall(at91_console_init); | ||
843 | |||
844 | #else | ||
845 | #define AT91_CONSOLE_DEVICE NULL | ||
846 | #endif | ||
847 | |||
848 | static struct uart_driver at91_uart = { | ||
849 | .owner = THIS_MODULE, | ||
850 | .driver_name = AT91_DEVICENAME, | ||
851 | .dev_name = AT91_DEVICENAME, | ||
852 | .devfs_name = AT91_DEVICENAME, | ||
853 | .major = SERIAL_AT91_MAJOR, | ||
854 | .minor = MINOR_START, | ||
855 | .nr = AT91_NR_UART, | ||
856 | .cons = AT91_CONSOLE_DEVICE, | ||
857 | }; | ||
858 | |||
859 | static int __init at91_serial_init(void) | ||
860 | { | ||
861 | int ret, i; | ||
862 | |||
863 | at91_init_ports(); | ||
864 | |||
865 | ret = uart_register_driver(&at91_uart); | ||
866 | if (ret) | ||
867 | return ret; | ||
868 | |||
869 | for (i = 0; i < AT91_NR_UART; i++) { | ||
870 | if (at91_serial_map[i] >= 0) | ||
871 | uart_add_one_port(&at91_uart, &at91_ports[i]); | ||
872 | } | ||
873 | |||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | static void __exit at91_serial_exit(void) | ||
878 | { | ||
879 | int i; | ||
880 | |||
881 | for (i = 0; i < AT91_NR_UART; i++) { | ||
882 | if (at91_serial_map[i] >= 0) | ||
883 | uart_remove_one_port(&at91_uart, &at91_ports[i]); | ||
884 | } | ||
885 | |||
886 | uart_unregister_driver(&at91_uart); | ||
887 | } | ||
888 | |||
889 | module_init(at91_serial_init); | ||
890 | module_exit(at91_serial_exit); | ||
891 | |||
892 | MODULE_AUTHOR("Rick Bronson"); | ||
893 | MODULE_DESCRIPTION("AT91 generic serial port driver"); | ||
894 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 08c42c000188..be12623d8544 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c | |||
@@ -442,6 +442,7 @@ static char *serial_version = "$Revision: 1.25 $"; | |||
442 | #include <linux/init.h> | 442 | #include <linux/init.h> |
443 | #include <asm/uaccess.h> | 443 | #include <asm/uaccess.h> |
444 | #include <linux/kernel.h> | 444 | #include <linux/kernel.h> |
445 | #include <linux/mutex.h> | ||
445 | 446 | ||
446 | #include <asm/io.h> | 447 | #include <asm/io.h> |
447 | #include <asm/irq.h> | 448 | #include <asm/irq.h> |
@@ -1315,11 +1316,7 @@ static const struct control_pins e100_modem_pins[NR_PORTS] = | |||
1315 | * memory if large numbers of serial ports are open. | 1316 | * memory if large numbers of serial ports are open. |
1316 | */ | 1317 | */ |
1317 | static unsigned char *tmp_buf; | 1318 | static unsigned char *tmp_buf; |
1318 | #ifdef DECLARE_MUTEX | 1319 | static DEFINE_MUTEX(tmp_buf_mutex); |
1319 | static DECLARE_MUTEX(tmp_buf_sem); | ||
1320 | #else | ||
1321 | static struct semaphore tmp_buf_sem = MUTEX; | ||
1322 | #endif | ||
1323 | 1320 | ||
1324 | /* Calculate the chartime depending on baudrate, numbor of bits etc. */ | 1321 | /* Calculate the chartime depending on baudrate, numbor of bits etc. */ |
1325 | static void update_char_time(struct e100_serial * info) | 1322 | static void update_char_time(struct e100_serial * info) |
@@ -3661,7 +3658,7 @@ rs_raw_write(struct tty_struct * tty, int from_user, | |||
3661 | * design. | 3658 | * design. |
3662 | */ | 3659 | */ |
3663 | if (from_user) { | 3660 | if (from_user) { |
3664 | down(&tmp_buf_sem); | 3661 | mutex_lock(&tmp_buf_mutex); |
3665 | while (1) { | 3662 | while (1) { |
3666 | int c1; | 3663 | int c1; |
3667 | c = CIRC_SPACE_TO_END(info->xmit.head, | 3664 | c = CIRC_SPACE_TO_END(info->xmit.head, |
@@ -3692,7 +3689,7 @@ rs_raw_write(struct tty_struct * tty, int from_user, | |||
3692 | count -= c; | 3689 | count -= c; |
3693 | ret += c; | 3690 | ret += c; |
3694 | } | 3691 | } |
3695 | up(&tmp_buf_sem); | 3692 | mutex_unlock(&tmp_buf_mutex); |
3696 | } else { | 3693 | } else { |
3697 | cli(); | 3694 | cli(); |
3698 | while (count) { | 3695 | while (count) { |
diff --git a/drivers/serial/pmac_zilog.c b/drivers/serial/pmac_zilog.c index f330d6c0e0df..5f52883e64d2 100644 --- a/drivers/serial/pmac_zilog.c +++ b/drivers/serial/pmac_zilog.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #include <linux/pmu.h> | 60 | #include <linux/pmu.h> |
61 | #include <linux/bitops.h> | 61 | #include <linux/bitops.h> |
62 | #include <linux/sysrq.h> | 62 | #include <linux/sysrq.h> |
63 | #include <linux/mutex.h> | ||
63 | #include <asm/sections.h> | 64 | #include <asm/sections.h> |
64 | #include <asm/io.h> | 65 | #include <asm/io.h> |
65 | #include <asm/irq.h> | 66 | #include <asm/irq.h> |
@@ -96,7 +97,7 @@ MODULE_LICENSE("GPL"); | |||
96 | */ | 97 | */ |
97 | static struct uart_pmac_port pmz_ports[MAX_ZS_PORTS]; | 98 | static struct uart_pmac_port pmz_ports[MAX_ZS_PORTS]; |
98 | static int pmz_ports_count; | 99 | static int pmz_ports_count; |
99 | static DECLARE_MUTEX(pmz_irq_sem); | 100 | static DEFINE_MUTEX(pmz_irq_mutex); |
100 | 101 | ||
101 | static struct uart_driver pmz_uart_reg = { | 102 | static struct uart_driver pmz_uart_reg = { |
102 | .owner = THIS_MODULE, | 103 | .owner = THIS_MODULE, |
@@ -922,7 +923,7 @@ static int pmz_startup(struct uart_port *port) | |||
922 | if (uap->node == NULL) | 923 | if (uap->node == NULL) |
923 | return -ENODEV; | 924 | return -ENODEV; |
924 | 925 | ||
925 | down(&pmz_irq_sem); | 926 | mutex_lock(&pmz_irq_mutex); |
926 | 927 | ||
927 | uap->flags |= PMACZILOG_FLAG_IS_OPEN; | 928 | uap->flags |= PMACZILOG_FLAG_IS_OPEN; |
928 | 929 | ||
@@ -940,11 +941,11 @@ static int pmz_startup(struct uart_port *port) | |||
940 | dev_err(&uap->dev->ofdev.dev, | 941 | dev_err(&uap->dev->ofdev.dev, |
941 | "Unable to register zs interrupt handler.\n"); | 942 | "Unable to register zs interrupt handler.\n"); |
942 | pmz_set_scc_power(uap, 0); | 943 | pmz_set_scc_power(uap, 0); |
943 | up(&pmz_irq_sem); | 944 | mutex_unlock(&pmz_irq_mutex); |
944 | return -ENXIO; | 945 | return -ENXIO; |
945 | } | 946 | } |
946 | 947 | ||
947 | up(&pmz_irq_sem); | 948 | mutex_unlock(&pmz_irq_mutex); |
948 | 949 | ||
949 | /* Right now, we deal with delay by blocking here, I'll be | 950 | /* Right now, we deal with delay by blocking here, I'll be |
950 | * smarter later on | 951 | * smarter later on |
@@ -981,7 +982,7 @@ static void pmz_shutdown(struct uart_port *port) | |||
981 | if (uap->node == NULL) | 982 | if (uap->node == NULL) |
982 | return; | 983 | return; |
983 | 984 | ||
984 | down(&pmz_irq_sem); | 985 | mutex_lock(&pmz_irq_mutex); |
985 | 986 | ||
986 | /* Release interrupt handler */ | 987 | /* Release interrupt handler */ |
987 | free_irq(uap->port.irq, uap); | 988 | free_irq(uap->port.irq, uap); |
@@ -1002,7 +1003,7 @@ static void pmz_shutdown(struct uart_port *port) | |||
1002 | 1003 | ||
1003 | if (ZS_IS_CONS(uap) || ZS_IS_ASLEEP(uap)) { | 1004 | if (ZS_IS_CONS(uap) || ZS_IS_ASLEEP(uap)) { |
1004 | spin_unlock_irqrestore(&port->lock, flags); | 1005 | spin_unlock_irqrestore(&port->lock, flags); |
1005 | up(&pmz_irq_sem); | 1006 | mutex_unlock(&pmz_irq_mutex); |
1006 | return; | 1007 | return; |
1007 | } | 1008 | } |
1008 | 1009 | ||
@@ -1019,7 +1020,7 @@ static void pmz_shutdown(struct uart_port *port) | |||
1019 | 1020 | ||
1020 | spin_unlock_irqrestore(&port->lock, flags); | 1021 | spin_unlock_irqrestore(&port->lock, flags); |
1021 | 1022 | ||
1022 | up(&pmz_irq_sem); | 1023 | mutex_unlock(&pmz_irq_mutex); |
1023 | 1024 | ||
1024 | pmz_debug("pmz: shutdown() done.\n"); | 1025 | pmz_debug("pmz: shutdown() done.\n"); |
1025 | } | 1026 | } |
@@ -1591,7 +1592,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state) | |||
1591 | 1592 | ||
1592 | state = pmz_uart_reg.state + uap->port.line; | 1593 | state = pmz_uart_reg.state + uap->port.line; |
1593 | 1594 | ||
1594 | down(&pmz_irq_sem); | 1595 | mutex_lock(&pmz_irq_mutex); |
1595 | down(&state->sem); | 1596 | down(&state->sem); |
1596 | 1597 | ||
1597 | spin_lock_irqsave(&uap->port.lock, flags); | 1598 | spin_lock_irqsave(&uap->port.lock, flags); |
@@ -1624,7 +1625,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state) | |||
1624 | pmz_set_scc_power(uap, 0); | 1625 | pmz_set_scc_power(uap, 0); |
1625 | 1626 | ||
1626 | up(&state->sem); | 1627 | up(&state->sem); |
1627 | up(&pmz_irq_sem); | 1628 | mutex_unlock(&pmz_irq_mutex); |
1628 | 1629 | ||
1629 | pmz_debug("suspend, switching complete\n"); | 1630 | pmz_debug("suspend, switching complete\n"); |
1630 | 1631 | ||
@@ -1651,7 +1652,7 @@ static int pmz_resume(struct macio_dev *mdev) | |||
1651 | 1652 | ||
1652 | state = pmz_uart_reg.state + uap->port.line; | 1653 | state = pmz_uart_reg.state + uap->port.line; |
1653 | 1654 | ||
1654 | down(&pmz_irq_sem); | 1655 | mutex_lock(&pmz_irq_mutex); |
1655 | down(&state->sem); | 1656 | down(&state->sem); |
1656 | 1657 | ||
1657 | spin_lock_irqsave(&uap->port.lock, flags); | 1658 | spin_lock_irqsave(&uap->port.lock, flags); |
@@ -1685,7 +1686,7 @@ static int pmz_resume(struct macio_dev *mdev) | |||
1685 | 1686 | ||
1686 | bail: | 1687 | bail: |
1687 | up(&state->sem); | 1688 | up(&state->sem); |
1688 | up(&pmz_irq_sem); | 1689 | mutex_unlock(&pmz_irq_mutex); |
1689 | 1690 | ||
1690 | /* Right now, we deal with delay by blocking here, I'll be | 1691 | /* Right now, we deal with delay by blocking here, I'll be |
1691 | * smarter later on | 1692 | * smarter later on |
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 9589509fc5bd..2ca620900bcc 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/device.h> | 33 | #include <linux/device.h> |
34 | #include <linux/serial.h> /* for serial_state and serial_icounter_struct */ | 34 | #include <linux/serial.h> /* for serial_state and serial_icounter_struct */ |
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | #include <linux/mutex.h> | ||
36 | 37 | ||
37 | #include <asm/irq.h> | 38 | #include <asm/irq.h> |
38 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
@@ -47,7 +48,7 @@ | |||
47 | /* | 48 | /* |
48 | * This is used to lock changes in serial line configuration. | 49 | * This is used to lock changes in serial line configuration. |
49 | */ | 50 | */ |
50 | static DECLARE_MUTEX(port_sem); | 51 | static DEFINE_MUTEX(port_mutex); |
51 | 52 | ||
52 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) | 53 | #define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8) |
53 | 54 | ||
@@ -1472,7 +1473,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) | |||
1472 | { | 1473 | { |
1473 | struct uart_state *state; | 1474 | struct uart_state *state; |
1474 | 1475 | ||
1475 | down(&port_sem); | 1476 | mutex_lock(&port_mutex); |
1476 | state = drv->state + line; | 1477 | state = drv->state + line; |
1477 | if (down_interruptible(&state->sem)) { | 1478 | if (down_interruptible(&state->sem)) { |
1478 | state = ERR_PTR(-ERESTARTSYS); | 1479 | state = ERR_PTR(-ERESTARTSYS); |
@@ -1509,7 +1510,7 @@ static struct uart_state *uart_get(struct uart_driver *drv, int line) | |||
1509 | } | 1510 | } |
1510 | 1511 | ||
1511 | out: | 1512 | out: |
1512 | up(&port_sem); | 1513 | mutex_unlock(&port_mutex); |
1513 | return state; | 1514 | return state; |
1514 | } | 1515 | } |
1515 | 1516 | ||
@@ -2219,7 +2220,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) | |||
2219 | 2220 | ||
2220 | state = drv->state + port->line; | 2221 | state = drv->state + port->line; |
2221 | 2222 | ||
2222 | down(&port_sem); | 2223 | mutex_lock(&port_mutex); |
2223 | if (state->port) { | 2224 | if (state->port) { |
2224 | ret = -EINVAL; | 2225 | ret = -EINVAL; |
2225 | goto out; | 2226 | goto out; |
@@ -2255,7 +2256,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *port) | |||
2255 | register_console(port->cons); | 2256 | register_console(port->cons); |
2256 | 2257 | ||
2257 | out: | 2258 | out: |
2258 | up(&port_sem); | 2259 | mutex_unlock(&port_mutex); |
2259 | 2260 | ||
2260 | return ret; | 2261 | return ret; |
2261 | } | 2262 | } |
@@ -2279,7 +2280,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) | |||
2279 | printk(KERN_ALERT "Removing wrong port: %p != %p\n", | 2280 | printk(KERN_ALERT "Removing wrong port: %p != %p\n", |
2280 | state->port, port); | 2281 | state->port, port); |
2281 | 2282 | ||
2282 | down(&port_sem); | 2283 | mutex_lock(&port_mutex); |
2283 | 2284 | ||
2284 | /* | 2285 | /* |
2285 | * Remove the devices from devfs | 2286 | * Remove the devices from devfs |
@@ -2288,7 +2289,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port) | |||
2288 | 2289 | ||
2289 | uart_unconfigure_port(drv, state); | 2290 | uart_unconfigure_port(drv, state); |
2290 | state->port = NULL; | 2291 | state->port = NULL; |
2291 | up(&port_sem); | 2292 | mutex_unlock(&port_mutex); |
2292 | 2293 | ||
2293 | return 0; | 2294 | return 0; |
2294 | } | 2295 | } |
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 96969cb960a9..c30333694fde 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c | |||
@@ -785,6 +785,8 @@ static struct pcmcia_device_id serial_ids[] = { | |||
785 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"), | 785 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"), |
786 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"), | 786 | PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"), |
787 | PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */ | 787 | PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */ |
788 | PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */ | ||
789 | PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */ | ||
788 | PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"), | 790 | PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"), |
789 | PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"), | 791 | PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"), |
790 | PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), | 792 | PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), |
diff --git a/drivers/serial/serial_txx9.c b/drivers/serial/serial_txx9.c index fdd1f1915a42..ee98a867bc6d 100644 --- a/drivers/serial/serial_txx9.c +++ b/drivers/serial/serial_txx9.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <linux/tty_flip.h> | 52 | #include <linux/tty_flip.h> |
53 | #include <linux/serial_core.h> | 53 | #include <linux/serial_core.h> |
54 | #include <linux/serial.h> | 54 | #include <linux/serial.h> |
55 | #include <linux/mutex.h> | ||
55 | 56 | ||
56 | #include <asm/io.h> | 57 | #include <asm/io.h> |
57 | #include <asm/irq.h> | 58 | #include <asm/irq.h> |
@@ -1018,7 +1019,7 @@ static void serial_txx9_resume_port(int line) | |||
1018 | uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port); | 1019 | uart_resume_port(&serial_txx9_reg, &serial_txx9_ports[line].port); |
1019 | } | 1020 | } |
1020 | 1021 | ||
1021 | static DECLARE_MUTEX(serial_txx9_sem); | 1022 | static DEFINE_MUTEX(serial_txx9_mutex); |
1022 | 1023 | ||
1023 | /** | 1024 | /** |
1024 | * serial_txx9_register_port - register a serial port | 1025 | * serial_txx9_register_port - register a serial port |
@@ -1037,7 +1038,7 @@ static int __devinit serial_txx9_register_port(struct uart_port *port) | |||
1037 | struct uart_txx9_port *uart; | 1038 | struct uart_txx9_port *uart; |
1038 | int ret = -ENOSPC; | 1039 | int ret = -ENOSPC; |
1039 | 1040 | ||
1040 | down(&serial_txx9_sem); | 1041 | mutex_lock(&serial_txx9_mutex); |
1041 | for (i = 0; i < UART_NR; i++) { | 1042 | for (i = 0; i < UART_NR; i++) { |
1042 | uart = &serial_txx9_ports[i]; | 1043 | uart = &serial_txx9_ports[i]; |
1043 | if (uart->port.type == PORT_UNKNOWN) | 1044 | if (uart->port.type == PORT_UNKNOWN) |
@@ -1058,7 +1059,7 @@ static int __devinit serial_txx9_register_port(struct uart_port *port) | |||
1058 | if (ret == 0) | 1059 | if (ret == 0) |
1059 | ret = uart->port.line; | 1060 | ret = uart->port.line; |
1060 | } | 1061 | } |
1061 | up(&serial_txx9_sem); | 1062 | mutex_unlock(&serial_txx9_mutex); |
1062 | return ret; | 1063 | return ret; |
1063 | } | 1064 | } |
1064 | 1065 | ||
@@ -1073,7 +1074,7 @@ static void __devexit serial_txx9_unregister_port(int line) | |||
1073 | { | 1074 | { |
1074 | struct uart_txx9_port *uart = &serial_txx9_ports[line]; | 1075 | struct uart_txx9_port *uart = &serial_txx9_ports[line]; |
1075 | 1076 | ||
1076 | down(&serial_txx9_sem); | 1077 | mutex_lock(&serial_txx9_mutex); |
1077 | uart_remove_one_port(&serial_txx9_reg, &uart->port); | 1078 | uart_remove_one_port(&serial_txx9_reg, &uart->port); |
1078 | uart->port.flags = 0; | 1079 | uart->port.flags = 0; |
1079 | uart->port.type = PORT_UNKNOWN; | 1080 | uart->port.type = PORT_UNKNOWN; |
@@ -1082,7 +1083,7 @@ static void __devexit serial_txx9_unregister_port(int line) | |||
1082 | uart->port.membase = 0; | 1083 | uart->port.membase = 0; |
1083 | uart->port.dev = NULL; | 1084 | uart->port.dev = NULL; |
1084 | uart_add_one_port(&serial_txx9_reg, &uart->port); | 1085 | uart_add_one_port(&serial_txx9_reg, &uart->port); |
1085 | up(&serial_txx9_sem); | 1086 | mutex_unlock(&serial_txx9_mutex); |
1086 | } | 1087 | } |
1087 | 1088 | ||
1088 | /* | 1089 | /* |
diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 7bdab2a7f59c..94b229031198 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c | |||
@@ -175,8 +175,6 @@ int superhyway_register_driver(struct superhyway_driver *drv) | |||
175 | { | 175 | { |
176 | drv->drv.name = drv->name; | 176 | drv->drv.name = drv->name; |
177 | drv->drv.bus = &superhyway_bus_type; | 177 | drv->drv.bus = &superhyway_bus_type; |
178 | drv->drv.probe = superhyway_device_probe; | ||
179 | drv->drv.remove = superhyway_device_remove; | ||
180 | 178 | ||
181 | return driver_register(&drv->drv); | 179 | return driver_register(&drv->drv); |
182 | } | 180 | } |
@@ -213,6 +211,8 @@ struct bus_type superhyway_bus_type = { | |||
213 | #ifdef CONFIG_SYSFS | 211 | #ifdef CONFIG_SYSFS |
214 | .dev_attrs = superhyway_dev_attrs, | 212 | .dev_attrs = superhyway_dev_attrs, |
215 | #endif | 213 | #endif |
214 | .probe = superhyway_device_probe, | ||
215 | .remove = superhyway_device_remove, | ||
216 | }; | 216 | }; |
217 | 217 | ||
218 | static int __init superhyway_bus_init(void) | 218 | static int __init superhyway_bus_init(void) |
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig new file mode 100644 index 000000000000..b77dbd63e596 --- /dev/null +++ b/drivers/spi/Kconfig | |||
@@ -0,0 +1,109 @@ | |||
1 | # | ||
2 | # SPI driver configuration | ||
3 | # | ||
4 | # NOTE: the reason this doesn't show SPI slave support is mostly that | ||
5 | # nobody's needed a slave side API yet. The master-role API is not | ||
6 | # fully appropriate there, so it'd need some thought to do well. | ||
7 | # | ||
8 | menu "SPI support" | ||
9 | |||
10 | config SPI | ||
11 | bool "SPI support" | ||
12 | help | ||
13 | The "Serial Peripheral Interface" is a low level synchronous | ||
14 | protocol. Chips that support SPI can have data transfer rates | ||
15 | up to several tens of Mbit/sec. Chips are addressed with a | ||
16 | controller and a chipselect. Most SPI slaves don't support | ||
17 | dynamic device discovery; some are even write-only or read-only. | ||
18 | |||
19 | SPI is widely used by microcontollers to talk with sensors, | ||
20 | eeprom and flash memory, codecs and various other controller | ||
21 | chips, analog to digital (and d-to-a) converters, and more. | ||
22 | MMC and SD cards can be accessed using SPI protocol; and for | ||
23 | DataFlash cards used in MMC sockets, SPI must always be used. | ||
24 | |||
25 | SPI is one of a family of similar protocols using a four wire | ||
26 | interface (select, clock, data in, data out) including Microwire | ||
27 | (half duplex), SSP, SSI, and PSP. This driver framework should | ||
28 | work with most such devices and controllers. | ||
29 | |||
30 | config SPI_DEBUG | ||
31 | boolean "Debug support for SPI drivers" | ||
32 | depends on SPI && DEBUG_KERNEL | ||
33 | help | ||
34 | Say "yes" to enable debug messaging (like dev_dbg and pr_debug), | ||
35 | sysfs, and debugfs support in SPI controller and protocol drivers. | ||
36 | |||
37 | # | ||
38 | # MASTER side ... talking to discrete SPI slave chips including microcontrollers | ||
39 | # | ||
40 | |||
41 | config SPI_MASTER | ||
42 | # boolean "SPI Master Support" | ||
43 | boolean | ||
44 | default SPI | ||
45 | help | ||
46 | If your system has an master-capable SPI controller (which | ||
47 | provides the clock and chipselect), you can enable that | ||
48 | controller and the protocol drivers for the SPI slave chips | ||
49 | that are connected. | ||
50 | |||
51 | comment "SPI Master Controller Drivers" | ||
52 | depends on SPI_MASTER | ||
53 | |||
54 | config SPI_BITBANG | ||
55 | tristate "Bitbanging SPI master" | ||
56 | depends on SPI_MASTER && EXPERIMENTAL | ||
57 | help | ||
58 | With a few GPIO pins, your system can bitbang the SPI protocol. | ||
59 | Select this to get SPI support through I/O pins (GPIO, parallel | ||
60 | port, etc). Or, some systems' SPI master controller drivers use | ||
61 | this code to manage the per-word or per-transfer accesses to the | ||
62 | hardware shift registers. | ||
63 | |||
64 | This is library code, and is automatically selected by drivers that | ||
65 | need it. You only need to select this explicitly to support driver | ||
66 | modules that aren't part of this kernel tree. | ||
67 | |||
68 | config SPI_BUTTERFLY | ||
69 | tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)" | ||
70 | depends on SPI_MASTER && PARPORT && EXPERIMENTAL | ||
71 | select SPI_BITBANG | ||
72 | help | ||
73 | This uses a custom parallel port cable to connect to an AVR | ||
74 | Butterfly <http://www.atmel.com/products/avr/butterfly>, an | ||
75 | inexpensive battery powered microcontroller evaluation board. | ||
76 | This same cable can be used to flash new firmware. | ||
77 | |||
78 | config SPI_BUTTERFLY | ||
79 | tristate "Parallel port adapter for AVR Butterfly (DEVELOPMENT)" | ||
80 | depends on SPI_MASTER && PARPORT && EXPERIMENTAL | ||
81 | select SPI_BITBANG | ||
82 | help | ||
83 | This uses a custom parallel port cable to connect to an AVR | ||
84 | Butterfly <http://www.atmel.com/products/avr/butterfly>, an | ||
85 | inexpensive battery powered microcontroller evaluation board. | ||
86 | This same cable can be used to flash new firmware. | ||
87 | |||
88 | # | ||
89 | # Add new SPI master controllers in alphabetical order above this line | ||
90 | # | ||
91 | |||
92 | |||
93 | # | ||
94 | # There are lots of SPI device types, with sensors and memory | ||
95 | # being probably the most widely used ones. | ||
96 | # | ||
97 | comment "SPI Protocol Masters" | ||
98 | depends on SPI_MASTER | ||
99 | |||
100 | |||
101 | # | ||
102 | # Add new SPI protocol masters in alphabetical order above this line | ||
103 | # | ||
104 | |||
105 | |||
106 | # (slave support would go here) | ||
107 | |||
108 | endmenu # "SPI support" | ||
109 | |||
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile new file mode 100644 index 000000000000..c2c87e845abf --- /dev/null +++ b/drivers/spi/Makefile | |||
@@ -0,0 +1,25 @@ | |||
1 | # | ||
2 | # Makefile for kernel SPI drivers. | ||
3 | # | ||
4 | |||
5 | ifeq ($(CONFIG_SPI_DEBUG),y) | ||
6 | EXTRA_CFLAGS += -DDEBUG | ||
7 | endif | ||
8 | |||
9 | # small core, mostly translating board-specific | ||
10 | # config declarations into driver model code | ||
11 | obj-$(CONFIG_SPI_MASTER) += spi.o | ||
12 | |||
13 | # SPI master controller drivers (bus) | ||
14 | obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o | ||
15 | obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o | ||
16 | # ... add above this line ... | ||
17 | |||
18 | # SPI protocol drivers (device/link on bus) | ||
19 | # ... add above this line ... | ||
20 | |||
21 | # SPI slave controller drivers (upstream link) | ||
22 | # ... add above this line ... | ||
23 | |||
24 | # SPI slave drivers (protocol for that link) | ||
25 | # ... add above this line ... | ||
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c new file mode 100644 index 000000000000..791c4dc550ae --- /dev/null +++ b/drivers/spi/spi.c | |||
@@ -0,0 +1,642 @@ | |||
1 | /* | ||
2 | * spi.c - SPI init/core code | ||
3 | * | ||
4 | * Copyright (C) 2005 David Brownell | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/autoconf.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/device.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/cache.h> | ||
26 | #include <linux/spi/spi.h> | ||
27 | |||
28 | |||
29 | /* SPI bustype and spi_master class are registered after board init code | ||
30 | * provides the SPI device tables, ensuring that both are present by the | ||
31 | * time controller driver registration causes spi_devices to "enumerate". | ||
32 | */ | ||
33 | static void spidev_release(struct device *dev) | ||
34 | { | ||
35 | const struct spi_device *spi = to_spi_device(dev); | ||
36 | |||
37 | /* spi masters may cleanup for released devices */ | ||
38 | if (spi->master->cleanup) | ||
39 | spi->master->cleanup(spi); | ||
40 | |||
41 | spi_master_put(spi->master); | ||
42 | kfree(dev); | ||
43 | } | ||
44 | |||
45 | static ssize_t | ||
46 | modalias_show(struct device *dev, struct device_attribute *a, char *buf) | ||
47 | { | ||
48 | const struct spi_device *spi = to_spi_device(dev); | ||
49 | |||
50 | return snprintf(buf, BUS_ID_SIZE + 1, "%s\n", spi->modalias); | ||
51 | } | ||
52 | |||
53 | static struct device_attribute spi_dev_attrs[] = { | ||
54 | __ATTR_RO(modalias), | ||
55 | __ATTR_NULL, | ||
56 | }; | ||
57 | |||
58 | /* modalias support makes "modprobe $MODALIAS" new-style hotplug work, | ||
59 | * and the sysfs version makes coldplug work too. | ||
60 | */ | ||
61 | |||
62 | static int spi_match_device(struct device *dev, struct device_driver *drv) | ||
63 | { | ||
64 | const struct spi_device *spi = to_spi_device(dev); | ||
65 | |||
66 | return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0; | ||
67 | } | ||
68 | |||
69 | static int spi_uevent(struct device *dev, char **envp, int num_envp, | ||
70 | char *buffer, int buffer_size) | ||
71 | { | ||
72 | const struct spi_device *spi = to_spi_device(dev); | ||
73 | |||
74 | envp[0] = buffer; | ||
75 | snprintf(buffer, buffer_size, "MODALIAS=%s", spi->modalias); | ||
76 | envp[1] = NULL; | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | #ifdef CONFIG_PM | ||
81 | |||
82 | /* | ||
83 | * NOTE: the suspend() method for an spi_master controller driver | ||
84 | * should verify that all its child devices are marked as suspended; | ||
85 | * suspend requests delivered through sysfs power/state files don't | ||
86 | * enforce such constraints. | ||
87 | */ | ||
88 | static int spi_suspend(struct device *dev, pm_message_t message) | ||
89 | { | ||
90 | int value; | ||
91 | struct spi_driver *drv = to_spi_driver(dev->driver); | ||
92 | |||
93 | if (!drv->suspend) | ||
94 | return 0; | ||
95 | |||
96 | /* suspend will stop irqs and dma; no more i/o */ | ||
97 | value = drv->suspend(to_spi_device(dev), message); | ||
98 | if (value == 0) | ||
99 | dev->power.power_state = message; | ||
100 | return value; | ||
101 | } | ||
102 | |||
103 | static int spi_resume(struct device *dev) | ||
104 | { | ||
105 | int value; | ||
106 | struct spi_driver *drv = to_spi_driver(dev->driver); | ||
107 | |||
108 | if (!drv->resume) | ||
109 | return 0; | ||
110 | |||
111 | /* resume may restart the i/o queue */ | ||
112 | value = drv->resume(to_spi_device(dev)); | ||
113 | if (value == 0) | ||
114 | dev->power.power_state = PMSG_ON; | ||
115 | return value; | ||
116 | } | ||
117 | |||
118 | #else | ||
119 | #define spi_suspend NULL | ||
120 | #define spi_resume NULL | ||
121 | #endif | ||
122 | |||
123 | struct bus_type spi_bus_type = { | ||
124 | .name = "spi", | ||
125 | .dev_attrs = spi_dev_attrs, | ||
126 | .match = spi_match_device, | ||
127 | .uevent = spi_uevent, | ||
128 | .suspend = spi_suspend, | ||
129 | .resume = spi_resume, | ||
130 | }; | ||
131 | EXPORT_SYMBOL_GPL(spi_bus_type); | ||
132 | |||
133 | |||
134 | static int spi_drv_probe(struct device *dev) | ||
135 | { | ||
136 | const struct spi_driver *sdrv = to_spi_driver(dev->driver); | ||
137 | |||
138 | return sdrv->probe(to_spi_device(dev)); | ||
139 | } | ||
140 | |||
141 | static int spi_drv_remove(struct device *dev) | ||
142 | { | ||
143 | const struct spi_driver *sdrv = to_spi_driver(dev->driver); | ||
144 | |||
145 | return sdrv->remove(to_spi_device(dev)); | ||
146 | } | ||
147 | |||
148 | static void spi_drv_shutdown(struct device *dev) | ||
149 | { | ||
150 | const struct spi_driver *sdrv = to_spi_driver(dev->driver); | ||
151 | |||
152 | sdrv->shutdown(to_spi_device(dev)); | ||
153 | } | ||
154 | |||
155 | int spi_register_driver(struct spi_driver *sdrv) | ||
156 | { | ||
157 | sdrv->driver.bus = &spi_bus_type; | ||
158 | if (sdrv->probe) | ||
159 | sdrv->driver.probe = spi_drv_probe; | ||
160 | if (sdrv->remove) | ||
161 | sdrv->driver.remove = spi_drv_remove; | ||
162 | if (sdrv->shutdown) | ||
163 | sdrv->driver.shutdown = spi_drv_shutdown; | ||
164 | return driver_register(&sdrv->driver); | ||
165 | } | ||
166 | EXPORT_SYMBOL_GPL(spi_register_driver); | ||
167 | |||
168 | /*-------------------------------------------------------------------------*/ | ||
169 | |||
170 | /* SPI devices should normally not be created by SPI device drivers; that | ||
171 | * would make them board-specific. Similarly with SPI master drivers. | ||
172 | * Device registration normally goes into like arch/.../mach.../board-YYY.c | ||
173 | * with other readonly (flashable) information about mainboard devices. | ||
174 | */ | ||
175 | |||
176 | struct boardinfo { | ||
177 | struct list_head list; | ||
178 | unsigned n_board_info; | ||
179 | struct spi_board_info board_info[0]; | ||
180 | }; | ||
181 | |||
182 | static LIST_HEAD(board_list); | ||
183 | static DECLARE_MUTEX(board_lock); | ||
184 | |||
185 | |||
186 | /* On typical mainboards, this is purely internal; and it's not needed | ||
187 | * after board init creates the hard-wired devices. Some development | ||
188 | * platforms may not be able to use spi_register_board_info though, and | ||
189 | * this is exported so that for example a USB or parport based adapter | ||
190 | * driver could add devices (which it would learn about out-of-band). | ||
191 | */ | ||
192 | struct spi_device *__init_or_module | ||
193 | spi_new_device(struct spi_master *master, struct spi_board_info *chip) | ||
194 | { | ||
195 | struct spi_device *proxy; | ||
196 | struct device *dev = master->cdev.dev; | ||
197 | int status; | ||
198 | |||
199 | /* NOTE: caller did any chip->bus_num checks necessary */ | ||
200 | |||
201 | if (!spi_master_get(master)) | ||
202 | return NULL; | ||
203 | |||
204 | proxy = kzalloc(sizeof *proxy, GFP_KERNEL); | ||
205 | if (!proxy) { | ||
206 | dev_err(dev, "can't alloc dev for cs%d\n", | ||
207 | chip->chip_select); | ||
208 | goto fail; | ||
209 | } | ||
210 | proxy->master = master; | ||
211 | proxy->chip_select = chip->chip_select; | ||
212 | proxy->max_speed_hz = chip->max_speed_hz; | ||
213 | proxy->irq = chip->irq; | ||
214 | proxy->modalias = chip->modalias; | ||
215 | |||
216 | snprintf(proxy->dev.bus_id, sizeof proxy->dev.bus_id, | ||
217 | "%s.%u", master->cdev.class_id, | ||
218 | chip->chip_select); | ||
219 | proxy->dev.parent = dev; | ||
220 | proxy->dev.bus = &spi_bus_type; | ||
221 | proxy->dev.platform_data = (void *) chip->platform_data; | ||
222 | proxy->controller_data = chip->controller_data; | ||
223 | proxy->controller_state = NULL; | ||
224 | proxy->dev.release = spidev_release; | ||
225 | |||
226 | /* drivers may modify this default i/o setup */ | ||
227 | status = master->setup(proxy); | ||
228 | if (status < 0) { | ||
229 | dev_dbg(dev, "can't %s %s, status %d\n", | ||
230 | "setup", proxy->dev.bus_id, status); | ||
231 | goto fail; | ||
232 | } | ||
233 | |||
234 | /* driver core catches callers that misbehave by defining | ||
235 | * devices that already exist. | ||
236 | */ | ||
237 | status = device_register(&proxy->dev); | ||
238 | if (status < 0) { | ||
239 | dev_dbg(dev, "can't %s %s, status %d\n", | ||
240 | "add", proxy->dev.bus_id, status); | ||
241 | goto fail; | ||
242 | } | ||
243 | dev_dbg(dev, "registered child %s\n", proxy->dev.bus_id); | ||
244 | return proxy; | ||
245 | |||
246 | fail: | ||
247 | spi_master_put(master); | ||
248 | kfree(proxy); | ||
249 | return NULL; | ||
250 | } | ||
251 | EXPORT_SYMBOL_GPL(spi_new_device); | ||
252 | |||
253 | /* | ||
254 | * Board-specific early init code calls this (probably during arch_initcall) | ||
255 | * with segments of the SPI device table. Any device nodes are created later, | ||
256 | * after the relevant parent SPI controller (bus_num) is defined. We keep | ||
257 | * this table of devices forever, so that reloading a controller driver will | ||
258 | * not make Linux forget about these hard-wired devices. | ||
259 | * | ||
260 | * Other code can also call this, e.g. a particular add-on board might provide | ||
261 | * SPI devices through its expansion connector, so code initializing that board | ||
262 | * would naturally declare its SPI devices. | ||
263 | * | ||
264 | * The board info passed can safely be __initdata ... but be careful of | ||
265 | * any embedded pointers (platform_data, etc), they're copied as-is. | ||
266 | */ | ||
267 | int __init | ||
268 | spi_register_board_info(struct spi_board_info const *info, unsigned n) | ||
269 | { | ||
270 | struct boardinfo *bi; | ||
271 | |||
272 | bi = kmalloc(sizeof(*bi) + n * sizeof *info, GFP_KERNEL); | ||
273 | if (!bi) | ||
274 | return -ENOMEM; | ||
275 | bi->n_board_info = n; | ||
276 | memcpy(bi->board_info, info, n * sizeof *info); | ||
277 | |||
278 | down(&board_lock); | ||
279 | list_add_tail(&bi->list, &board_list); | ||
280 | up(&board_lock); | ||
281 | return 0; | ||
282 | } | ||
283 | EXPORT_SYMBOL_GPL(spi_register_board_info); | ||
284 | |||
285 | /* FIXME someone should add support for a __setup("spi", ...) that | ||
286 | * creates board info from kernel command lines | ||
287 | */ | ||
288 | |||
289 | static void __init_or_module | ||
290 | scan_boardinfo(struct spi_master *master) | ||
291 | { | ||
292 | struct boardinfo *bi; | ||
293 | struct device *dev = master->cdev.dev; | ||
294 | |||
295 | down(&board_lock); | ||
296 | list_for_each_entry(bi, &board_list, list) { | ||
297 | struct spi_board_info *chip = bi->board_info; | ||
298 | unsigned n; | ||
299 | |||
300 | for (n = bi->n_board_info; n > 0; n--, chip++) { | ||
301 | if (chip->bus_num != master->bus_num) | ||
302 | continue; | ||
303 | /* some controllers only have one chip, so they | ||
304 | * might not use chipselects. otherwise, the | ||
305 | * chipselects are numbered 0..max. | ||
306 | */ | ||
307 | if (chip->chip_select >= master->num_chipselect | ||
308 | && master->num_chipselect) { | ||
309 | dev_dbg(dev, "cs%d > max %d\n", | ||
310 | chip->chip_select, | ||
311 | master->num_chipselect); | ||
312 | continue; | ||
313 | } | ||
314 | (void) spi_new_device(master, chip); | ||
315 | } | ||
316 | } | ||
317 | up(&board_lock); | ||
318 | } | ||
319 | |||
320 | /*-------------------------------------------------------------------------*/ | ||
321 | |||
322 | static void spi_master_release(struct class_device *cdev) | ||
323 | { | ||
324 | struct spi_master *master; | ||
325 | |||
326 | master = container_of(cdev, struct spi_master, cdev); | ||
327 | kfree(master); | ||
328 | } | ||
329 | |||
330 | static struct class spi_master_class = { | ||
331 | .name = "spi_master", | ||
332 | .owner = THIS_MODULE, | ||
333 | .release = spi_master_release, | ||
334 | }; | ||
335 | |||
336 | |||
337 | /** | ||
338 | * spi_alloc_master - allocate SPI master controller | ||
339 | * @dev: the controller, possibly using the platform_bus | ||
340 | * @size: how much driver-private data to preallocate; the pointer to this | ||
341 | * memory is in the class_data field of the returned class_device, | ||
342 | * accessible with spi_master_get_devdata(). | ||
343 | * | ||
344 | * This call is used only by SPI master controller drivers, which are the | ||
345 | * only ones directly touching chip registers. It's how they allocate | ||
346 | * an spi_master structure, prior to calling spi_add_master(). | ||
347 | * | ||
348 | * This must be called from context that can sleep. It returns the SPI | ||
349 | * master structure on success, else NULL. | ||
350 | * | ||
351 | * The caller is responsible for assigning the bus number and initializing | ||
352 | * the master's methods before calling spi_add_master(); and (after errors | ||
353 | * adding the device) calling spi_master_put() to prevent a memory leak. | ||
354 | */ | ||
355 | struct spi_master * __init_or_module | ||
356 | spi_alloc_master(struct device *dev, unsigned size) | ||
357 | { | ||
358 | struct spi_master *master; | ||
359 | |||
360 | if (!dev) | ||
361 | return NULL; | ||
362 | |||
363 | master = kzalloc(size + sizeof *master, SLAB_KERNEL); | ||
364 | if (!master) | ||
365 | return NULL; | ||
366 | |||
367 | class_device_initialize(&master->cdev); | ||
368 | master->cdev.class = &spi_master_class; | ||
369 | master->cdev.dev = get_device(dev); | ||
370 | spi_master_set_devdata(master, &master[1]); | ||
371 | |||
372 | return master; | ||
373 | } | ||
374 | EXPORT_SYMBOL_GPL(spi_alloc_master); | ||
375 | |||
376 | /** | ||
377 | * spi_register_master - register SPI master controller | ||
378 | * @master: initialized master, originally from spi_alloc_master() | ||
379 | * | ||
380 | * SPI master controllers connect to their drivers using some non-SPI bus, | ||
381 | * such as the platform bus. The final stage of probe() in that code | ||
382 | * includes calling spi_register_master() to hook up to this SPI bus glue. | ||
383 | * | ||
384 | * SPI controllers use board specific (often SOC specific) bus numbers, | ||
385 | * and board-specific addressing for SPI devices combines those numbers | ||
386 | * with chip select numbers. Since SPI does not directly support dynamic | ||
387 | * device identification, boards need configuration tables telling which | ||
388 | * chip is at which address. | ||
389 | * | ||
390 | * This must be called from context that can sleep. It returns zero on | ||
391 | * success, else a negative error code (dropping the master's refcount). | ||
392 | * After a successful return, the caller is responsible for calling | ||
393 | * spi_unregister_master(). | ||
394 | */ | ||
395 | int __init_or_module | ||
396 | spi_register_master(struct spi_master *master) | ||
397 | { | ||
398 | static atomic_t dyn_bus_id = ATOMIC_INIT(0); | ||
399 | struct device *dev = master->cdev.dev; | ||
400 | int status = -ENODEV; | ||
401 | int dynamic = 0; | ||
402 | |||
403 | if (!dev) | ||
404 | return -ENODEV; | ||
405 | |||
406 | /* convention: dynamically assigned bus IDs count down from the max */ | ||
407 | if (master->bus_num == 0) { | ||
408 | master->bus_num = atomic_dec_return(&dyn_bus_id); | ||
409 | dynamic = 1; | ||
410 | } | ||
411 | |||
412 | /* register the device, then userspace will see it. | ||
413 | * registration fails if the bus ID is in use. | ||
414 | */ | ||
415 | snprintf(master->cdev.class_id, sizeof master->cdev.class_id, | ||
416 | "spi%u", master->bus_num); | ||
417 | status = class_device_add(&master->cdev); | ||
418 | if (status < 0) | ||
419 | goto done; | ||
420 | dev_dbg(dev, "registered master %s%s\n", master->cdev.class_id, | ||
421 | dynamic ? " (dynamic)" : ""); | ||
422 | |||
423 | /* populate children from any spi device tables */ | ||
424 | scan_boardinfo(master); | ||
425 | status = 0; | ||
426 | done: | ||
427 | return status; | ||
428 | } | ||
429 | EXPORT_SYMBOL_GPL(spi_register_master); | ||
430 | |||
431 | |||
432 | static int __unregister(struct device *dev, void *unused) | ||
433 | { | ||
434 | /* note: before about 2.6.14-rc1 this would corrupt memory: */ | ||
435 | spi_unregister_device(to_spi_device(dev)); | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | /** | ||
440 | * spi_unregister_master - unregister SPI master controller | ||
441 | * @master: the master being unregistered | ||
442 | * | ||
443 | * This call is used only by SPI master controller drivers, which are the | ||
444 | * only ones directly touching chip registers. | ||
445 | * | ||
446 | * This must be called from context that can sleep. | ||
447 | */ | ||
448 | void spi_unregister_master(struct spi_master *master) | ||
449 | { | ||
450 | (void) device_for_each_child(master->cdev.dev, NULL, __unregister); | ||
451 | class_device_unregister(&master->cdev); | ||
452 | master->cdev.dev = NULL; | ||
453 | } | ||
454 | EXPORT_SYMBOL_GPL(spi_unregister_master); | ||
455 | |||
456 | /** | ||
457 | * spi_busnum_to_master - look up master associated with bus_num | ||
458 | * @bus_num: the master's bus number | ||
459 | * | ||
460 | * This call may be used with devices that are registered after | ||
461 | * arch init time. It returns a refcounted pointer to the relevant | ||
462 | * spi_master (which the caller must release), or NULL if there is | ||
463 | * no such master registered. | ||
464 | */ | ||
465 | struct spi_master *spi_busnum_to_master(u16 bus_num) | ||
466 | { | ||
467 | if (bus_num) { | ||
468 | char name[8]; | ||
469 | struct kobject *bus; | ||
470 | |||
471 | snprintf(name, sizeof name, "spi%u", bus_num); | ||
472 | bus = kset_find_obj(&spi_master_class.subsys.kset, name); | ||
473 | if (bus) | ||
474 | return container_of(bus, struct spi_master, cdev.kobj); | ||
475 | } | ||
476 | return NULL; | ||
477 | } | ||
478 | EXPORT_SYMBOL_GPL(spi_busnum_to_master); | ||
479 | |||
480 | |||
481 | /*-------------------------------------------------------------------------*/ | ||
482 | |||
483 | static void spi_complete(void *arg) | ||
484 | { | ||
485 | complete(arg); | ||
486 | } | ||
487 | |||
488 | /** | ||
489 | * spi_sync - blocking/synchronous SPI data transfers | ||
490 | * @spi: device with which data will be exchanged | ||
491 | * @message: describes the data transfers | ||
492 | * | ||
493 | * This call may only be used from a context that may sleep. The sleep | ||
494 | * is non-interruptible, and has no timeout. Low-overhead controller | ||
495 | * drivers may DMA directly into and out of the message buffers. | ||
496 | * | ||
497 | * Note that the SPI device's chip select is active during the message, | ||
498 | * and then is normally disabled between messages. Drivers for some | ||
499 | * frequently-used devices may want to minimize costs of selecting a chip, | ||
500 | * by leaving it selected in anticipation that the next message will go | ||
501 | * to the same chip. (That may increase power usage.) | ||
502 | * | ||
503 | * Also, the caller is guaranteeing that the memory associated with the | ||
504 | * message will not be freed before this call returns. | ||
505 | * | ||
506 | * The return value is a negative error code if the message could not be | ||
507 | * submitted, else zero. When the value is zero, then message->status is | ||
508 | * also defined: it's the completion code for the transfer, either zero | ||
509 | * or a negative error code from the controller driver. | ||
510 | */ | ||
511 | int spi_sync(struct spi_device *spi, struct spi_message *message) | ||
512 | { | ||
513 | DECLARE_COMPLETION(done); | ||
514 | int status; | ||
515 | |||
516 | message->complete = spi_complete; | ||
517 | message->context = &done; | ||
518 | status = spi_async(spi, message); | ||
519 | if (status == 0) | ||
520 | wait_for_completion(&done); | ||
521 | message->context = NULL; | ||
522 | return status; | ||
523 | } | ||
524 | EXPORT_SYMBOL_GPL(spi_sync); | ||
525 | |||
526 | #define SPI_BUFSIZ (SMP_CACHE_BYTES) | ||
527 | |||
528 | static u8 *buf; | ||
529 | |||
530 | /** | ||
531 | * spi_write_then_read - SPI synchronous write followed by read | ||
532 | * @spi: device with which data will be exchanged | ||
533 | * @txbuf: data to be written (need not be dma-safe) | ||
534 | * @n_tx: size of txbuf, in bytes | ||
535 | * @rxbuf: buffer into which data will be read | ||
536 | * @n_rx: size of rxbuf, in bytes (need not be dma-safe) | ||
537 | * | ||
538 | * This performs a half duplex MicroWire style transaction with the | ||
539 | * device, sending txbuf and then reading rxbuf. The return value | ||
540 | * is zero for success, else a negative errno status code. | ||
541 | * This call may only be used from a context that may sleep. | ||
542 | * | ||
543 | * Parameters to this routine are always copied using a small buffer; | ||
544 | * performance-sensitive or bulk transfer code should instead use | ||
545 | * spi_{async,sync}() calls with dma-safe buffers. | ||
546 | */ | ||
547 | int spi_write_then_read(struct spi_device *spi, | ||
548 | const u8 *txbuf, unsigned n_tx, | ||
549 | u8 *rxbuf, unsigned n_rx) | ||
550 | { | ||
551 | static DECLARE_MUTEX(lock); | ||
552 | |||
553 | int status; | ||
554 | struct spi_message message; | ||
555 | struct spi_transfer x[2]; | ||
556 | u8 *local_buf; | ||
557 | |||
558 | /* Use preallocated DMA-safe buffer. We can't avoid copying here, | ||
559 | * (as a pure convenience thing), but we can keep heap costs | ||
560 | * out of the hot path ... | ||
561 | */ | ||
562 | if ((n_tx + n_rx) > SPI_BUFSIZ) | ||
563 | return -EINVAL; | ||
564 | |||
565 | spi_message_init(&message); | ||
566 | memset(x, 0, sizeof x); | ||
567 | if (n_tx) { | ||
568 | x[0].len = n_tx; | ||
569 | spi_message_add_tail(&x[0], &message); | ||
570 | } | ||
571 | if (n_rx) { | ||
572 | x[1].len = n_rx; | ||
573 | spi_message_add_tail(&x[1], &message); | ||
574 | } | ||
575 | |||
576 | /* ... unless someone else is using the pre-allocated buffer */ | ||
577 | if (down_trylock(&lock)) { | ||
578 | local_buf = kmalloc(SPI_BUFSIZ, GFP_KERNEL); | ||
579 | if (!local_buf) | ||
580 | return -ENOMEM; | ||
581 | } else | ||
582 | local_buf = buf; | ||
583 | |||
584 | memcpy(local_buf, txbuf, n_tx); | ||
585 | x[0].tx_buf = local_buf; | ||
586 | x[1].rx_buf = local_buf + n_tx; | ||
587 | |||
588 | /* do the i/o */ | ||
589 | status = spi_sync(spi, &message); | ||
590 | if (status == 0) { | ||
591 | memcpy(rxbuf, x[1].rx_buf, n_rx); | ||
592 | status = message.status; | ||
593 | } | ||
594 | |||
595 | if (x[0].tx_buf == buf) | ||
596 | up(&lock); | ||
597 | else | ||
598 | kfree(local_buf); | ||
599 | |||
600 | return status; | ||
601 | } | ||
602 | EXPORT_SYMBOL_GPL(spi_write_then_read); | ||
603 | |||
604 | /*-------------------------------------------------------------------------*/ | ||
605 | |||
606 | static int __init spi_init(void) | ||
607 | { | ||
608 | int status; | ||
609 | |||
610 | buf = kmalloc(SPI_BUFSIZ, SLAB_KERNEL); | ||
611 | if (!buf) { | ||
612 | status = -ENOMEM; | ||
613 | goto err0; | ||
614 | } | ||
615 | |||
616 | status = bus_register(&spi_bus_type); | ||
617 | if (status < 0) | ||
618 | goto err1; | ||
619 | |||
620 | status = class_register(&spi_master_class); | ||
621 | if (status < 0) | ||
622 | goto err2; | ||
623 | return 0; | ||
624 | |||
625 | err2: | ||
626 | bus_unregister(&spi_bus_type); | ||
627 | err1: | ||
628 | kfree(buf); | ||
629 | buf = NULL; | ||
630 | err0: | ||
631 | return status; | ||
632 | } | ||
633 | |||
634 | /* board_info is normally registered in arch_initcall(), | ||
635 | * but even essential drivers wait till later | ||
636 | * | ||
637 | * REVISIT only boardinfo really needs static linking. the rest (device and | ||
638 | * driver registration) _could_ be dynamically linked (modular) ... costs | ||
639 | * include needing to have boardinfo data structures be much more public. | ||
640 | */ | ||
641 | subsys_initcall(spi_init); | ||
642 | |||
diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c new file mode 100644 index 000000000000..f037e5593269 --- /dev/null +++ b/drivers/spi/spi_bitbang.c | |||
@@ -0,0 +1,472 @@ | |||
1 | /* | ||
2 | * spi_bitbang.c - polling/bitbanging SPI master controller driver utilities | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | |||
19 | #include <linux/config.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/spinlock.h> | ||
22 | #include <linux/workqueue.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/delay.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | |||
28 | #include <linux/spi/spi.h> | ||
29 | #include <linux/spi/spi_bitbang.h> | ||
30 | |||
31 | |||
32 | /*----------------------------------------------------------------------*/ | ||
33 | |||
34 | /* | ||
35 | * FIRST PART (OPTIONAL): word-at-a-time spi_transfer support. | ||
36 | * Use this for GPIO or shift-register level hardware APIs. | ||
37 | * | ||
38 | * spi_bitbang_cs is in spi_device->controller_state, which is unavailable | ||
39 | * to glue code. These bitbang setup() and cleanup() routines are always | ||
40 | * used, though maybe they're called from controller-aware code. | ||
41 | * | ||
42 | * chipselect() and friends may use use spi_device->controller_data and | ||
43 | * controller registers as appropriate. | ||
44 | * | ||
45 | * | ||
46 | * NOTE: SPI controller pins can often be used as GPIO pins instead, | ||
47 | * which means you could use a bitbang driver either to get hardware | ||
48 | * working quickly, or testing for differences that aren't speed related. | ||
49 | */ | ||
50 | |||
51 | struct spi_bitbang_cs { | ||
52 | unsigned nsecs; /* (clock cycle time)/2 */ | ||
53 | u32 (*txrx_word)(struct spi_device *spi, unsigned nsecs, | ||
54 | u32 word, u8 bits); | ||
55 | unsigned (*txrx_bufs)(struct spi_device *, | ||
56 | u32 (*txrx_word)( | ||
57 | struct spi_device *spi, | ||
58 | unsigned nsecs, | ||
59 | u32 word, u8 bits), | ||
60 | unsigned, struct spi_transfer *); | ||
61 | }; | ||
62 | |||
63 | static unsigned bitbang_txrx_8( | ||
64 | struct spi_device *spi, | ||
65 | u32 (*txrx_word)(struct spi_device *spi, | ||
66 | unsigned nsecs, | ||
67 | u32 word, u8 bits), | ||
68 | unsigned ns, | ||
69 | struct spi_transfer *t | ||
70 | ) { | ||
71 | unsigned bits = spi->bits_per_word; | ||
72 | unsigned count = t->len; | ||
73 | const u8 *tx = t->tx_buf; | ||
74 | u8 *rx = t->rx_buf; | ||
75 | |||
76 | while (likely(count > 0)) { | ||
77 | u8 word = 0; | ||
78 | |||
79 | if (tx) | ||
80 | word = *tx++; | ||
81 | word = txrx_word(spi, ns, word, bits); | ||
82 | if (rx) | ||
83 | *rx++ = word; | ||
84 | count -= 1; | ||
85 | } | ||
86 | return t->len - count; | ||
87 | } | ||
88 | |||
89 | static unsigned bitbang_txrx_16( | ||
90 | struct spi_device *spi, | ||
91 | u32 (*txrx_word)(struct spi_device *spi, | ||
92 | unsigned nsecs, | ||
93 | u32 word, u8 bits), | ||
94 | unsigned ns, | ||
95 | struct spi_transfer *t | ||
96 | ) { | ||
97 | unsigned bits = spi->bits_per_word; | ||
98 | unsigned count = t->len; | ||
99 | const u16 *tx = t->tx_buf; | ||
100 | u16 *rx = t->rx_buf; | ||
101 | |||
102 | while (likely(count > 1)) { | ||
103 | u16 word = 0; | ||
104 | |||
105 | if (tx) | ||
106 | word = *tx++; | ||
107 | word = txrx_word(spi, ns, word, bits); | ||
108 | if (rx) | ||
109 | *rx++ = word; | ||
110 | count -= 2; | ||
111 | } | ||
112 | return t->len - count; | ||
113 | } | ||
114 | |||
115 | static unsigned bitbang_txrx_32( | ||
116 | struct spi_device *spi, | ||
117 | u32 (*txrx_word)(struct spi_device *spi, | ||
118 | unsigned nsecs, | ||
119 | u32 word, u8 bits), | ||
120 | unsigned ns, | ||
121 | struct spi_transfer *t | ||
122 | ) { | ||
123 | unsigned bits = spi->bits_per_word; | ||
124 | unsigned count = t->len; | ||
125 | const u32 *tx = t->tx_buf; | ||
126 | u32 *rx = t->rx_buf; | ||
127 | |||
128 | while (likely(count > 3)) { | ||
129 | u32 word = 0; | ||
130 | |||
131 | if (tx) | ||
132 | word = *tx++; | ||
133 | word = txrx_word(spi, ns, word, bits); | ||
134 | if (rx) | ||
135 | *rx++ = word; | ||
136 | count -= 4; | ||
137 | } | ||
138 | return t->len - count; | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * spi_bitbang_setup - default setup for per-word I/O loops | ||
143 | */ | ||
144 | int spi_bitbang_setup(struct spi_device *spi) | ||
145 | { | ||
146 | struct spi_bitbang_cs *cs = spi->controller_state; | ||
147 | struct spi_bitbang *bitbang; | ||
148 | |||
149 | if (!spi->max_speed_hz) | ||
150 | return -EINVAL; | ||
151 | |||
152 | if (!cs) { | ||
153 | cs = kzalloc(sizeof *cs, SLAB_KERNEL); | ||
154 | if (!cs) | ||
155 | return -ENOMEM; | ||
156 | spi->controller_state = cs; | ||
157 | } | ||
158 | bitbang = spi_master_get_devdata(spi->master); | ||
159 | |||
160 | if (!spi->bits_per_word) | ||
161 | spi->bits_per_word = 8; | ||
162 | |||
163 | /* spi_transfer level calls that work per-word */ | ||
164 | if (spi->bits_per_word <= 8) | ||
165 | cs->txrx_bufs = bitbang_txrx_8; | ||
166 | else if (spi->bits_per_word <= 16) | ||
167 | cs->txrx_bufs = bitbang_txrx_16; | ||
168 | else if (spi->bits_per_word <= 32) | ||
169 | cs->txrx_bufs = bitbang_txrx_32; | ||
170 | else | ||
171 | return -EINVAL; | ||
172 | |||
173 | /* per-word shift register access, in hardware or bitbanging */ | ||
174 | cs->txrx_word = bitbang->txrx_word[spi->mode & (SPI_CPOL|SPI_CPHA)]; | ||
175 | if (!cs->txrx_word) | ||
176 | return -EINVAL; | ||
177 | |||
178 | /* nsecs = (clock period)/2 */ | ||
179 | cs->nsecs = (1000000000/2) / (spi->max_speed_hz); | ||
180 | if (cs->nsecs > MAX_UDELAY_MS * 1000) | ||
181 | return -EINVAL; | ||
182 | |||
183 | dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n", | ||
184 | __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA), | ||
185 | spi->bits_per_word, 2 * cs->nsecs); | ||
186 | |||
187 | /* NOTE we _need_ to call chipselect() early, ideally with adapter | ||
188 | * setup, unless the hardware defaults cooperate to avoid confusion | ||
189 | * between normal (active low) and inverted chipselects. | ||
190 | */ | ||
191 | |||
192 | /* deselect chip (low or high) */ | ||
193 | spin_lock(&bitbang->lock); | ||
194 | if (!bitbang->busy) { | ||
195 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | ||
196 | ndelay(cs->nsecs); | ||
197 | } | ||
198 | spin_unlock(&bitbang->lock); | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | EXPORT_SYMBOL_GPL(spi_bitbang_setup); | ||
203 | |||
204 | /** | ||
205 | * spi_bitbang_cleanup - default cleanup for per-word I/O loops | ||
206 | */ | ||
207 | void spi_bitbang_cleanup(const struct spi_device *spi) | ||
208 | { | ||
209 | kfree(spi->controller_state); | ||
210 | } | ||
211 | EXPORT_SYMBOL_GPL(spi_bitbang_cleanup); | ||
212 | |||
213 | static int spi_bitbang_bufs(struct spi_device *spi, struct spi_transfer *t) | ||
214 | { | ||
215 | struct spi_bitbang_cs *cs = spi->controller_state; | ||
216 | unsigned nsecs = cs->nsecs; | ||
217 | |||
218 | return cs->txrx_bufs(spi, cs->txrx_word, nsecs, t); | ||
219 | } | ||
220 | |||
221 | /*----------------------------------------------------------------------*/ | ||
222 | |||
223 | /* | ||
224 | * SECOND PART ... simple transfer queue runner. | ||
225 | * | ||
226 | * This costs a task context per controller, running the queue by | ||
227 | * performing each transfer in sequence. Smarter hardware can queue | ||
228 | * several DMA transfers at once, and process several controller queues | ||
229 | * in parallel; this driver doesn't match such hardware very well. | ||
230 | * | ||
231 | * Drivers can provide word-at-a-time i/o primitives, or provide | ||
232 | * transfer-at-a-time ones to leverage dma or fifo hardware. | ||
233 | */ | ||
234 | static void bitbang_work(void *_bitbang) | ||
235 | { | ||
236 | struct spi_bitbang *bitbang = _bitbang; | ||
237 | unsigned long flags; | ||
238 | |||
239 | spin_lock_irqsave(&bitbang->lock, flags); | ||
240 | bitbang->busy = 1; | ||
241 | while (!list_empty(&bitbang->queue)) { | ||
242 | struct spi_message *m; | ||
243 | struct spi_device *spi; | ||
244 | unsigned nsecs; | ||
245 | struct spi_transfer *t = NULL; | ||
246 | unsigned tmp; | ||
247 | unsigned cs_change; | ||
248 | int status; | ||
249 | |||
250 | m = container_of(bitbang->queue.next, struct spi_message, | ||
251 | queue); | ||
252 | list_del_init(&m->queue); | ||
253 | spin_unlock_irqrestore(&bitbang->lock, flags); | ||
254 | |||
255 | /* FIXME this is made-up ... the correct value is known to | ||
256 | * word-at-a-time bitbang code, and presumably chipselect() | ||
257 | * should enforce these requirements too? | ||
258 | */ | ||
259 | nsecs = 100; | ||
260 | |||
261 | spi = m->spi; | ||
262 | tmp = 0; | ||
263 | cs_change = 1; | ||
264 | status = 0; | ||
265 | |||
266 | list_for_each_entry (t, &m->transfers, transfer_list) { | ||
267 | if (bitbang->shutdown) { | ||
268 | status = -ESHUTDOWN; | ||
269 | break; | ||
270 | } | ||
271 | |||
272 | /* set up default clock polarity, and activate chip; | ||
273 | * this implicitly updates clock and spi modes as | ||
274 | * previously recorded for this device via setup(). | ||
275 | * (and also deselects any other chip that might be | ||
276 | * selected ...) | ||
277 | */ | ||
278 | if (cs_change) { | ||
279 | bitbang->chipselect(spi, BITBANG_CS_ACTIVE); | ||
280 | ndelay(nsecs); | ||
281 | } | ||
282 | cs_change = t->cs_change; | ||
283 | if (!t->tx_buf && !t->rx_buf && t->len) { | ||
284 | status = -EINVAL; | ||
285 | break; | ||
286 | } | ||
287 | |||
288 | /* transfer data. the lower level code handles any | ||
289 | * new dma mappings it needs. our caller always gave | ||
290 | * us dma-safe buffers. | ||
291 | */ | ||
292 | if (t->len) { | ||
293 | /* REVISIT dma API still needs a designated | ||
294 | * DMA_ADDR_INVALID; ~0 might be better. | ||
295 | */ | ||
296 | if (!m->is_dma_mapped) | ||
297 | t->rx_dma = t->tx_dma = 0; | ||
298 | status = bitbang->txrx_bufs(spi, t); | ||
299 | } | ||
300 | if (status != t->len) { | ||
301 | if (status > 0) | ||
302 | status = -EMSGSIZE; | ||
303 | break; | ||
304 | } | ||
305 | m->actual_length += status; | ||
306 | status = 0; | ||
307 | |||
308 | /* protocol tweaks before next transfer */ | ||
309 | if (t->delay_usecs) | ||
310 | udelay(t->delay_usecs); | ||
311 | |||
312 | if (!cs_change) | ||
313 | continue; | ||
314 | if (t->transfer_list.next == &m->transfers) | ||
315 | break; | ||
316 | |||
317 | /* sometimes a short mid-message deselect of the chip | ||
318 | * may be needed to terminate a mode or command | ||
319 | */ | ||
320 | ndelay(nsecs); | ||
321 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | ||
322 | ndelay(nsecs); | ||
323 | } | ||
324 | |||
325 | m->status = status; | ||
326 | m->complete(m->context); | ||
327 | |||
328 | /* normally deactivate chipselect ... unless no error and | ||
329 | * cs_change has hinted that the next message will probably | ||
330 | * be for this chip too. | ||
331 | */ | ||
332 | if (!(status == 0 && cs_change)) { | ||
333 | ndelay(nsecs); | ||
334 | bitbang->chipselect(spi, BITBANG_CS_INACTIVE); | ||
335 | ndelay(nsecs); | ||
336 | } | ||
337 | |||
338 | spin_lock_irqsave(&bitbang->lock, flags); | ||
339 | } | ||
340 | bitbang->busy = 0; | ||
341 | spin_unlock_irqrestore(&bitbang->lock, flags); | ||
342 | } | ||
343 | |||
344 | /** | ||
345 | * spi_bitbang_transfer - default submit to transfer queue | ||
346 | */ | ||
347 | int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m) | ||
348 | { | ||
349 | struct spi_bitbang *bitbang; | ||
350 | unsigned long flags; | ||
351 | |||
352 | m->actual_length = 0; | ||
353 | m->status = -EINPROGRESS; | ||
354 | |||
355 | bitbang = spi_master_get_devdata(spi->master); | ||
356 | if (bitbang->shutdown) | ||
357 | return -ESHUTDOWN; | ||
358 | |||
359 | spin_lock_irqsave(&bitbang->lock, flags); | ||
360 | list_add_tail(&m->queue, &bitbang->queue); | ||
361 | queue_work(bitbang->workqueue, &bitbang->work); | ||
362 | spin_unlock_irqrestore(&bitbang->lock, flags); | ||
363 | |||
364 | return 0; | ||
365 | } | ||
366 | EXPORT_SYMBOL_GPL(spi_bitbang_transfer); | ||
367 | |||
368 | /*----------------------------------------------------------------------*/ | ||
369 | |||
370 | /** | ||
371 | * spi_bitbang_start - start up a polled/bitbanging SPI master driver | ||
372 | * @bitbang: driver handle | ||
373 | * | ||
374 | * Caller should have zero-initialized all parts of the structure, and then | ||
375 | * provided callbacks for chip selection and I/O loops. If the master has | ||
376 | * a transfer method, its final step should call spi_bitbang_transfer; or, | ||
377 | * that's the default if the transfer routine is not initialized. It should | ||
378 | * also set up the bus number and number of chipselects. | ||
379 | * | ||
380 | * For i/o loops, provide callbacks either per-word (for bitbanging, or for | ||
381 | * hardware that basically exposes a shift register) or per-spi_transfer | ||
382 | * (which takes better advantage of hardware like fifos or DMA engines). | ||
383 | * | ||
384 | * Drivers using per-word I/O loops should use (or call) spi_bitbang_setup and | ||
385 | * spi_bitbang_cleanup to handle those spi master methods. Those methods are | ||
386 | * the defaults if the bitbang->txrx_bufs routine isn't initialized. | ||
387 | * | ||
388 | * This routine registers the spi_master, which will process requests in a | ||
389 | * dedicated task, keeping IRQs unblocked most of the time. To stop | ||
390 | * processing those requests, call spi_bitbang_stop(). | ||
391 | */ | ||
392 | int spi_bitbang_start(struct spi_bitbang *bitbang) | ||
393 | { | ||
394 | int status; | ||
395 | |||
396 | if (!bitbang->master || !bitbang->chipselect) | ||
397 | return -EINVAL; | ||
398 | |||
399 | INIT_WORK(&bitbang->work, bitbang_work, bitbang); | ||
400 | spin_lock_init(&bitbang->lock); | ||
401 | INIT_LIST_HEAD(&bitbang->queue); | ||
402 | |||
403 | if (!bitbang->master->transfer) | ||
404 | bitbang->master->transfer = spi_bitbang_transfer; | ||
405 | if (!bitbang->txrx_bufs) { | ||
406 | bitbang->use_dma = 0; | ||
407 | bitbang->txrx_bufs = spi_bitbang_bufs; | ||
408 | if (!bitbang->master->setup) { | ||
409 | bitbang->master->setup = spi_bitbang_setup; | ||
410 | bitbang->master->cleanup = spi_bitbang_cleanup; | ||
411 | } | ||
412 | } else if (!bitbang->master->setup) | ||
413 | return -EINVAL; | ||
414 | |||
415 | /* this task is the only thing to touch the SPI bits */ | ||
416 | bitbang->busy = 0; | ||
417 | bitbang->workqueue = create_singlethread_workqueue( | ||
418 | bitbang->master->cdev.dev->bus_id); | ||
419 | if (bitbang->workqueue == NULL) { | ||
420 | status = -EBUSY; | ||
421 | goto err1; | ||
422 | } | ||
423 | |||
424 | /* driver may get busy before register() returns, especially | ||
425 | * if someone registered boardinfo for devices | ||
426 | */ | ||
427 | status = spi_register_master(bitbang->master); | ||
428 | if (status < 0) | ||
429 | goto err2; | ||
430 | |||
431 | return status; | ||
432 | |||
433 | err2: | ||
434 | destroy_workqueue(bitbang->workqueue); | ||
435 | err1: | ||
436 | return status; | ||
437 | } | ||
438 | EXPORT_SYMBOL_GPL(spi_bitbang_start); | ||
439 | |||
440 | /** | ||
441 | * spi_bitbang_stop - stops the task providing spi communication | ||
442 | */ | ||
443 | int spi_bitbang_stop(struct spi_bitbang *bitbang) | ||
444 | { | ||
445 | unsigned limit = 500; | ||
446 | |||
447 | spin_lock_irq(&bitbang->lock); | ||
448 | bitbang->shutdown = 0; | ||
449 | while (!list_empty(&bitbang->queue) && limit--) { | ||
450 | spin_unlock_irq(&bitbang->lock); | ||
451 | |||
452 | dev_dbg(bitbang->master->cdev.dev, "wait for queue\n"); | ||
453 | msleep(10); | ||
454 | |||
455 | spin_lock_irq(&bitbang->lock); | ||
456 | } | ||
457 | spin_unlock_irq(&bitbang->lock); | ||
458 | if (!list_empty(&bitbang->queue)) { | ||
459 | dev_err(bitbang->master->cdev.dev, "queue didn't empty\n"); | ||
460 | return -EBUSY; | ||
461 | } | ||
462 | |||
463 | destroy_workqueue(bitbang->workqueue); | ||
464 | |||
465 | spi_unregister_master(bitbang->master); | ||
466 | |||
467 | return 0; | ||
468 | } | ||
469 | EXPORT_SYMBOL_GPL(spi_bitbang_stop); | ||
470 | |||
471 | MODULE_LICENSE("GPL"); | ||
472 | |||
diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c new file mode 100644 index 000000000000..79a3c59615ab --- /dev/null +++ b/drivers/spi/spi_butterfly.c | |||
@@ -0,0 +1,423 @@ | |||
1 | /* | ||
2 | * spi_butterfly.c - parport-to-butterfly adapter | ||
3 | * | ||
4 | * Copyright (C) 2005 David Brownell | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
19 | */ | ||
20 | #include <linux/config.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/platform_device.h> | ||
25 | #include <linux/parport.h> | ||
26 | |||
27 | #include <linux/spi/spi.h> | ||
28 | #include <linux/spi/spi_bitbang.h> | ||
29 | #include <linux/spi/flash.h> | ||
30 | |||
31 | #include <linux/mtd/partitions.h> | ||
32 | |||
33 | |||
34 | /* | ||
35 | * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card | ||
36 | * with a battery powered AVR microcontroller and lots of goodies. You | ||
37 | * can use GCC to develop firmware for this. | ||
38 | * | ||
39 | * See Documentation/spi/butterfly for information about how to build | ||
40 | * and use this custom parallel port cable. | ||
41 | */ | ||
42 | |||
43 | #undef HAVE_USI /* nyet */ | ||
44 | |||
45 | |||
46 | /* DATA output bits (pins 2..9 == D0..D7) */ | ||
47 | #define butterfly_nreset (1 << 1) /* pin 3 */ | ||
48 | |||
49 | #define spi_sck_bit (1 << 0) /* pin 2 */ | ||
50 | #define spi_mosi_bit (1 << 7) /* pin 9 */ | ||
51 | |||
52 | #define usi_sck_bit (1 << 3) /* pin 5 */ | ||
53 | #define usi_mosi_bit (1 << 4) /* pin 6 */ | ||
54 | |||
55 | #define vcc_bits ((1 << 6) | (1 << 5)) /* pins 7, 8 */ | ||
56 | |||
57 | /* STATUS input bits */ | ||
58 | #define spi_miso_bit PARPORT_STATUS_BUSY /* pin 11 */ | ||
59 | |||
60 | #define usi_miso_bit PARPORT_STATUS_PAPEROUT /* pin 12 */ | ||
61 | |||
62 | /* CONTROL output bits */ | ||
63 | #define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */ | ||
64 | /* USI uses no chipselect */ | ||
65 | |||
66 | |||
67 | |||
68 | static inline struct butterfly *spidev_to_pp(struct spi_device *spi) | ||
69 | { | ||
70 | return spi->controller_data; | ||
71 | } | ||
72 | |||
73 | static inline int is_usidev(struct spi_device *spi) | ||
74 | { | ||
75 | #ifdef HAVE_USI | ||
76 | return spi->chip_select != 1; | ||
77 | #else | ||
78 | return 0; | ||
79 | #endif | ||
80 | } | ||
81 | |||
82 | |||
83 | struct butterfly { | ||
84 | /* REVISIT ... for now, this must be first */ | ||
85 | struct spi_bitbang bitbang; | ||
86 | |||
87 | struct parport *port; | ||
88 | struct pardevice *pd; | ||
89 | |||
90 | u8 lastbyte; | ||
91 | |||
92 | struct spi_device *dataflash; | ||
93 | struct spi_device *butterfly; | ||
94 | struct spi_board_info info[2]; | ||
95 | |||
96 | }; | ||
97 | |||
98 | /*----------------------------------------------------------------------*/ | ||
99 | |||
100 | /* | ||
101 | * these routines may be slower than necessary because they're hiding | ||
102 | * the fact that there are two different SPI busses on this cable: one | ||
103 | * to the DataFlash chip (or AVR SPI controller), the other to the | ||
104 | * AVR USI controller. | ||
105 | */ | ||
106 | |||
107 | static inline void | ||
108 | setsck(struct spi_device *spi, int is_on) | ||
109 | { | ||
110 | struct butterfly *pp = spidev_to_pp(spi); | ||
111 | u8 bit, byte = pp->lastbyte; | ||
112 | |||
113 | if (is_usidev(spi)) | ||
114 | bit = usi_sck_bit; | ||
115 | else | ||
116 | bit = spi_sck_bit; | ||
117 | |||
118 | if (is_on) | ||
119 | byte |= bit; | ||
120 | else | ||
121 | byte &= ~bit; | ||
122 | parport_write_data(pp->port, byte); | ||
123 | pp->lastbyte = byte; | ||
124 | } | ||
125 | |||
126 | static inline void | ||
127 | setmosi(struct spi_device *spi, int is_on) | ||
128 | { | ||
129 | struct butterfly *pp = spidev_to_pp(spi); | ||
130 | u8 bit, byte = pp->lastbyte; | ||
131 | |||
132 | if (is_usidev(spi)) | ||
133 | bit = usi_mosi_bit; | ||
134 | else | ||
135 | bit = spi_mosi_bit; | ||
136 | |||
137 | if (is_on) | ||
138 | byte |= bit; | ||
139 | else | ||
140 | byte &= ~bit; | ||
141 | parport_write_data(pp->port, byte); | ||
142 | pp->lastbyte = byte; | ||
143 | } | ||
144 | |||
145 | static inline int getmiso(struct spi_device *spi) | ||
146 | { | ||
147 | struct butterfly *pp = spidev_to_pp(spi); | ||
148 | int value; | ||
149 | u8 bit; | ||
150 | |||
151 | if (is_usidev(spi)) | ||
152 | bit = usi_miso_bit; | ||
153 | else | ||
154 | bit = spi_miso_bit; | ||
155 | |||
156 | /* only STATUS_BUSY is NOT negated */ | ||
157 | value = !(parport_read_status(pp->port) & bit); | ||
158 | return (bit == PARPORT_STATUS_BUSY) ? value : !value; | ||
159 | } | ||
160 | |||
161 | static void butterfly_chipselect(struct spi_device *spi, int value) | ||
162 | { | ||
163 | struct butterfly *pp = spidev_to_pp(spi); | ||
164 | |||
165 | /* set default clock polarity */ | ||
166 | if (value) | ||
167 | setsck(spi, spi->mode & SPI_CPOL); | ||
168 | |||
169 | /* no chipselect on this USI link config */ | ||
170 | if (is_usidev(spi)) | ||
171 | return; | ||
172 | |||
173 | /* here, value == "activate or not" */ | ||
174 | |||
175 | /* most PARPORT_CONTROL_* bits are negated */ | ||
176 | if (spi_cs_bit == PARPORT_CONTROL_INIT) | ||
177 | value = !value; | ||
178 | |||
179 | /* here, value == "bit value to write in control register" */ | ||
180 | |||
181 | parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); | ||
182 | } | ||
183 | |||
184 | |||
185 | /* we only needed to implement one mode here, and choose SPI_MODE_0 */ | ||
186 | |||
187 | #define spidelay(X) do{}while(0) | ||
188 | //#define spidelay ndelay | ||
189 | |||
190 | #define EXPAND_BITBANG_TXRX | ||
191 | #include <linux/spi/spi_bitbang.h> | ||
192 | |||
193 | static u32 | ||
194 | butterfly_txrx_word_mode0(struct spi_device *spi, | ||
195 | unsigned nsecs, | ||
196 | u32 word, u8 bits) | ||
197 | { | ||
198 | return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); | ||
199 | } | ||
200 | |||
201 | /*----------------------------------------------------------------------*/ | ||
202 | |||
203 | /* override default partitioning with cmdlinepart */ | ||
204 | static struct mtd_partition partitions[] = { { | ||
205 | /* JFFS2 wants partitions of 4*N blocks for this device ... */ | ||
206 | |||
207 | /* sector 0 = 8 pages * 264 bytes/page (1 block) | ||
208 | * sector 1 = 248 pages * 264 bytes/page | ||
209 | */ | ||
210 | .name = "bookkeeping", // 66 KB | ||
211 | .offset = 0, | ||
212 | .size = (8 + 248) * 264, | ||
213 | // .mask_flags = MTD_WRITEABLE, | ||
214 | }, { | ||
215 | /* sector 2 = 256 pages * 264 bytes/page | ||
216 | * sectors 3-5 = 512 pages * 264 bytes/page | ||
217 | */ | ||
218 | .name = "filesystem", // 462 KB | ||
219 | .offset = MTDPART_OFS_APPEND, | ||
220 | .size = MTDPART_SIZ_FULL, | ||
221 | } }; | ||
222 | |||
223 | static struct flash_platform_data flash = { | ||
224 | .name = "butterflash", | ||
225 | .parts = partitions, | ||
226 | .nr_parts = ARRAY_SIZE(partitions), | ||
227 | }; | ||
228 | |||
229 | |||
230 | /* REVISIT remove this ugly global and its "only one" limitation */ | ||
231 | static struct butterfly *butterfly; | ||
232 | |||
233 | static void butterfly_attach(struct parport *p) | ||
234 | { | ||
235 | struct pardevice *pd; | ||
236 | int status; | ||
237 | struct butterfly *pp; | ||
238 | struct spi_master *master; | ||
239 | struct platform_device *pdev; | ||
240 | |||
241 | if (butterfly) | ||
242 | return; | ||
243 | |||
244 | /* REVISIT: this just _assumes_ a butterfly is there ... no probe, | ||
245 | * and no way to be selective about what it binds to. | ||
246 | */ | ||
247 | |||
248 | /* FIXME where should master->cdev.dev come from? | ||
249 | * e.g. /sys/bus/pnp0/00:0b, some PCI thing, etc | ||
250 | * setting up a platform device like this is an ugly kluge... | ||
251 | */ | ||
252 | pdev = platform_device_register_simple("butterfly", -1, NULL, 0); | ||
253 | |||
254 | master = spi_alloc_master(&pdev->dev, sizeof *pp); | ||
255 | if (!master) { | ||
256 | status = -ENOMEM; | ||
257 | goto done; | ||
258 | } | ||
259 | pp = spi_master_get_devdata(master); | ||
260 | |||
261 | /* | ||
262 | * SPI and bitbang hookup | ||
263 | * | ||
264 | * use default setup(), cleanup(), and transfer() methods; and | ||
265 | * only bother implementing mode 0. Start it later. | ||
266 | */ | ||
267 | master->bus_num = 42; | ||
268 | master->num_chipselect = 2; | ||
269 | |||
270 | pp->bitbang.master = spi_master_get(master); | ||
271 | pp->bitbang.chipselect = butterfly_chipselect; | ||
272 | pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0; | ||
273 | |||
274 | /* | ||
275 | * parport hookup | ||
276 | */ | ||
277 | pp->port = p; | ||
278 | pd = parport_register_device(p, "spi_butterfly", | ||
279 | NULL, NULL, NULL, | ||
280 | 0 /* FLAGS */, pp); | ||
281 | if (!pd) { | ||
282 | status = -ENOMEM; | ||
283 | goto clean0; | ||
284 | } | ||
285 | pp->pd = pd; | ||
286 | |||
287 | status = parport_claim(pd); | ||
288 | if (status < 0) | ||
289 | goto clean1; | ||
290 | |||
291 | /* | ||
292 | * Butterfly reset, powerup, run firmware | ||
293 | */ | ||
294 | pr_debug("%s: powerup/reset Butterfly\n", p->name); | ||
295 | |||
296 | /* nCS for dataflash (this bit is inverted on output) */ | ||
297 | parport_frob_control(pp->port, spi_cs_bit, 0); | ||
298 | |||
299 | /* stabilize power with chip in reset (nRESET), and | ||
300 | * both spi_sck_bit and usi_sck_bit clear (CPOL=0) | ||
301 | */ | ||
302 | pp->lastbyte |= vcc_bits; | ||
303 | parport_write_data(pp->port, pp->lastbyte); | ||
304 | msleep(5); | ||
305 | |||
306 | /* take it out of reset; assume long reset delay */ | ||
307 | pp->lastbyte |= butterfly_nreset; | ||
308 | parport_write_data(pp->port, pp->lastbyte); | ||
309 | msleep(100); | ||
310 | |||
311 | |||
312 | /* | ||
313 | * Start SPI ... for now, hide that we're two physical busses. | ||
314 | */ | ||
315 | status = spi_bitbang_start(&pp->bitbang); | ||
316 | if (status < 0) | ||
317 | goto clean2; | ||
318 | |||
319 | /* Bus 1 lets us talk to at45db041b (firmware disables AVR) | ||
320 | * or AVR (firmware resets at45, acts as spi slave) | ||
321 | */ | ||
322 | pp->info[0].max_speed_hz = 15 * 1000 * 1000; | ||
323 | strcpy(pp->info[0].modalias, "mtd_dataflash"); | ||
324 | pp->info[0].platform_data = &flash; | ||
325 | pp->info[0].chip_select = 1; | ||
326 | pp->info[0].controller_data = pp; | ||
327 | pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]); | ||
328 | if (pp->dataflash) | ||
329 | pr_debug("%s: dataflash at %s\n", p->name, | ||
330 | pp->dataflash->dev.bus_id); | ||
331 | |||
332 | #ifdef HAVE_USI | ||
333 | /* even more custom AVR firmware */ | ||
334 | pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000; | ||
335 | strcpy(pp->info[1].modalias, "butterfly"); | ||
336 | // pp->info[1].platform_data = ... TBD ... ; | ||
337 | pp->info[1].chip_select = 2, | ||
338 | pp->info[1].controller_data = pp; | ||
339 | pp->butterfly = spi_new_device(pp->bitbang.master, &pp->info[1]); | ||
340 | if (pp->butterfly) | ||
341 | pr_debug("%s: butterfly at %s\n", p->name, | ||
342 | pp->butterfly->dev.bus_id); | ||
343 | |||
344 | /* FIXME setup ACK for the IRQ line ... */ | ||
345 | #endif | ||
346 | |||
347 | // dev_info(_what?_, ...) | ||
348 | pr_info("%s: AVR Butterfly\n", p->name); | ||
349 | butterfly = pp; | ||
350 | return; | ||
351 | |||
352 | clean2: | ||
353 | /* turn off VCC */ | ||
354 | parport_write_data(pp->port, 0); | ||
355 | |||
356 | parport_release(pp->pd); | ||
357 | clean1: | ||
358 | parport_unregister_device(pd); | ||
359 | clean0: | ||
360 | (void) spi_master_put(pp->bitbang.master); | ||
361 | done: | ||
362 | platform_device_unregister(pdev); | ||
363 | pr_debug("%s: butterfly probe, fail %d\n", p->name, status); | ||
364 | } | ||
365 | |||
366 | static void butterfly_detach(struct parport *p) | ||
367 | { | ||
368 | struct butterfly *pp; | ||
369 | struct platform_device *pdev; | ||
370 | int status; | ||
371 | |||
372 | /* FIXME this global is ugly ... but, how to quickly get from | ||
373 | * the parport to the "struct butterfly" associated with it? | ||
374 | * "old school" driver-internal device lists? | ||
375 | */ | ||
376 | if (!butterfly || butterfly->port != p) | ||
377 | return; | ||
378 | pp = butterfly; | ||
379 | butterfly = NULL; | ||
380 | |||
381 | #ifdef HAVE_USI | ||
382 | spi_unregister_device(pp->butterfly); | ||
383 | pp->butterfly = NULL; | ||
384 | #endif | ||
385 | spi_unregister_device(pp->dataflash); | ||
386 | pp->dataflash = NULL; | ||
387 | |||
388 | status = spi_bitbang_stop(&pp->bitbang); | ||
389 | |||
390 | /* turn off VCC */ | ||
391 | parport_write_data(pp->port, 0); | ||
392 | msleep(10); | ||
393 | |||
394 | parport_release(pp->pd); | ||
395 | parport_unregister_device(pp->pd); | ||
396 | |||
397 | pdev = to_platform_device(pp->bitbang.master->cdev.dev); | ||
398 | |||
399 | (void) spi_master_put(pp->bitbang.master); | ||
400 | |||
401 | platform_device_unregister(pdev); | ||
402 | } | ||
403 | |||
404 | static struct parport_driver butterfly_driver = { | ||
405 | .name = "spi_butterfly", | ||
406 | .attach = butterfly_attach, | ||
407 | .detach = butterfly_detach, | ||
408 | }; | ||
409 | |||
410 | |||
411 | static int __init butterfly_init(void) | ||
412 | { | ||
413 | return parport_register_driver(&butterfly_driver); | ||
414 | } | ||
415 | device_initcall(butterfly_init); | ||
416 | |||
417 | static void __exit butterfly_exit(void) | ||
418 | { | ||
419 | parport_unregister_driver(&butterfly_driver); | ||
420 | } | ||
421 | module_exit(butterfly_exit); | ||
422 | |||
423 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 8f402f85e1ca..afc84cfb61f9 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c | |||
@@ -2534,9 +2534,6 @@ static struct usb_gadget_driver eth_driver = { | |||
2534 | .driver = { | 2534 | .driver = { |
2535 | .name = (char *) shortname, | 2535 | .name = (char *) shortname, |
2536 | .owner = THIS_MODULE, | 2536 | .owner = THIS_MODULE, |
2537 | // .shutdown = ... | ||
2538 | // .suspend = ... | ||
2539 | // .resume = ... | ||
2540 | }, | 2537 | }, |
2541 | }; | 2538 | }; |
2542 | 2539 | ||
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index c6c279de832e..9a4edc5657aa 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -1738,9 +1738,6 @@ static struct usb_gadget_driver gadgetfs_driver = { | |||
1738 | 1738 | ||
1739 | .driver = { | 1739 | .driver = { |
1740 | .name = (char *) shortname, | 1740 | .name = (char *) shortname, |
1741 | // .shutdown = ... | ||
1742 | // .suspend = ... | ||
1743 | // .resume = ... | ||
1744 | }, | 1741 | }, |
1745 | }; | 1742 | }; |
1746 | 1743 | ||
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 2e6926b33455..ba9acd531024 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c | |||
@@ -374,9 +374,6 @@ static struct usb_gadget_driver gs_gadget_driver = { | |||
374 | .disconnect = gs_disconnect, | 374 | .disconnect = gs_disconnect, |
375 | .driver = { | 375 | .driver = { |
376 | .name = GS_SHORT_NAME, | 376 | .name = GS_SHORT_NAME, |
377 | /* .shutdown = ... */ | ||
378 | /* .suspend = ... */ | ||
379 | /* .resume = ... */ | ||
380 | }, | 377 | }, |
381 | }; | 378 | }; |
382 | 379 | ||
diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 6c58636e914b..2fc110d3ad5a 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c | |||
@@ -1303,9 +1303,6 @@ static struct usb_gadget_driver zero_driver = { | |||
1303 | .driver = { | 1303 | .driver = { |
1304 | .name = (char *) shortname, | 1304 | .name = (char *) shortname, |
1305 | .owner = THIS_MODULE, | 1305 | .owner = THIS_MODULE, |
1306 | // .shutdown = ... | ||
1307 | // .suspend = ... | ||
1308 | // .resume = ... | ||
1309 | }, | 1306 | }, |
1310 | }; | 1307 | }; |
1311 | 1308 | ||
diff --git a/drivers/usb/input/Kconfig b/drivers/usb/input/Kconfig index 509dd0a04c54..5246b35301de 100644 --- a/drivers/usb/input/Kconfig +++ b/drivers/usb/input/Kconfig | |||
@@ -37,6 +37,16 @@ config USB_HIDINPUT | |||
37 | 37 | ||
38 | If unsure, say Y. | 38 | If unsure, say Y. |
39 | 39 | ||
40 | config USB_HIDINPUT_POWERBOOK | ||
41 | bool "Enable support for iBook/PowerBook special keys" | ||
42 | default n | ||
43 | depends on USB_HIDINPUT | ||
44 | help | ||
45 | Say Y here if you want support for the special keys (Fn, Numlock) on | ||
46 | Apple iBooks and PowerBooks. | ||
47 | |||
48 | If unsure, say N. | ||
49 | |||
40 | config HID_FF | 50 | config HID_FF |
41 | bool "Force feedback support (EXPERIMENTAL)" | 51 | bool "Force feedback support (EXPERIMENTAL)" |
42 | depends on USB_HIDINPUT && EXPERIMENTAL | 52 | depends on USB_HIDINPUT && EXPERIMENTAL |
diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 5f52979af1c7..a91e72c41415 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c | |||
@@ -1450,6 +1450,9 @@ void hid_init_reports(struct hid_device *hid) | |||
1450 | #define USB_VENDOR_ID_APPLE 0x05ac | 1450 | #define USB_VENDOR_ID_APPLE 0x05ac |
1451 | #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 | 1451 | #define USB_DEVICE_ID_APPLE_POWERMOUSE 0x0304 |
1452 | 1452 | ||
1453 | #define USB_VENDOR_ID_CHERRY 0x046a | ||
1454 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 | ||
1455 | |||
1453 | /* | 1456 | /* |
1454 | * Alphabetically sorted blacklist by quirk type. | 1457 | * Alphabetically sorted blacklist by quirk type. |
1455 | */ | 1458 | */ |
@@ -1580,6 +1583,16 @@ static const struct hid_blacklist { | |||
1580 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, | 1583 | { USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD }, |
1581 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, | 1584 | { USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD }, |
1582 | 1585 | ||
1586 | { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, | ||
1587 | |||
1588 | { USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1589 | { USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1590 | { USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1591 | { USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1592 | { USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1593 | { USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1594 | { USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, | ||
1595 | |||
1583 | { 0, 0 } | 1596 | { 0, 0 } |
1584 | }; | 1597 | }; |
1585 | 1598 | ||
@@ -1626,6 +1639,20 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) | |||
1626 | usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); | 1639 | usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma); |
1627 | } | 1640 | } |
1628 | 1641 | ||
1642 | /* | ||
1643 | * Cherry Cymotion keyboard have an invalid HID report descriptor, | ||
1644 | * that needs fixing before we can parse it. | ||
1645 | */ | ||
1646 | |||
1647 | static void hid_fixup_cymotion_descriptor(char *rdesc, int rsize) | ||
1648 | { | ||
1649 | if (rsize >= 17 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { | ||
1650 | info("Fixing up Cherry Cymotion report descriptor"); | ||
1651 | rdesc[11] = rdesc[16] = 0xff; | ||
1652 | rdesc[12] = rdesc[17] = 0x03; | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1629 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) | 1656 | static struct hid_device *usb_hid_configure(struct usb_interface *intf) |
1630 | { | 1657 | { |
1631 | struct usb_host_interface *interface = intf->cur_altsetting; | 1658 | struct usb_host_interface *interface = intf->cur_altsetting; |
@@ -1673,6 +1700,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf) | |||
1673 | return NULL; | 1700 | return NULL; |
1674 | } | 1701 | } |
1675 | 1702 | ||
1703 | if ((quirks & HID_QUIRK_CYMOTION)) | ||
1704 | hid_fixup_cymotion_descriptor(rdesc, rsize); | ||
1705 | |||
1676 | #ifdef DEBUG_DATA | 1706 | #ifdef DEBUG_DATA |
1677 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); | 1707 | printk(KERN_DEBUG __FILE__ ": report descriptor (size %u, read %d) = ", rsize, n); |
1678 | for (n = 0; n < rsize; n++) | 1708 | for (n = 0; n < rsize; n++) |
diff --git a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c index 192a03b28971..cb0d80f49252 100644 --- a/drivers/usb/input/hid-input.c +++ b/drivers/usb/input/hid-input.c | |||
@@ -73,6 +73,160 @@ static const struct { | |||
73 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) | 73 | #define map_key_clear(c) do { map_key(c); clear_bit(c, bit); } while (0) |
74 | #define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) | 74 | #define map_ff_effect(c) do { set_bit(c, input->ffbit); } while (0) |
75 | 75 | ||
76 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | ||
77 | |||
78 | struct hidinput_key_translation { | ||
79 | u16 from; | ||
80 | u16 to; | ||
81 | u8 flags; | ||
82 | }; | ||
83 | |||
84 | #define POWERBOOK_FLAG_FKEY 0x01 | ||
85 | |||
86 | static struct hidinput_key_translation powerbook_fn_keys[] = { | ||
87 | { KEY_BACKSPACE, KEY_DELETE }, | ||
88 | { KEY_F1, KEY_BRIGHTNESSDOWN, POWERBOOK_FLAG_FKEY }, | ||
89 | { KEY_F2, KEY_BRIGHTNESSUP, POWERBOOK_FLAG_FKEY }, | ||
90 | { KEY_F3, KEY_MUTE, POWERBOOK_FLAG_FKEY }, | ||
91 | { KEY_F4, KEY_VOLUMEDOWN, POWERBOOK_FLAG_FKEY }, | ||
92 | { KEY_F5, KEY_VOLUMEUP, POWERBOOK_FLAG_FKEY }, | ||
93 | { KEY_F6, KEY_NUMLOCK, POWERBOOK_FLAG_FKEY }, | ||
94 | { KEY_F7, KEY_SWITCHVIDEOMODE, POWERBOOK_FLAG_FKEY }, | ||
95 | { KEY_F8, KEY_KBDILLUMTOGGLE, POWERBOOK_FLAG_FKEY }, | ||
96 | { KEY_F9, KEY_KBDILLUMDOWN, POWERBOOK_FLAG_FKEY }, | ||
97 | { KEY_F10, KEY_KBDILLUMUP, POWERBOOK_FLAG_FKEY }, | ||
98 | { KEY_UP, KEY_PAGEUP }, | ||
99 | { KEY_DOWN, KEY_PAGEDOWN }, | ||
100 | { KEY_LEFT, KEY_HOME }, | ||
101 | { KEY_RIGHT, KEY_END }, | ||
102 | { } | ||
103 | }; | ||
104 | |||
105 | static struct hidinput_key_translation powerbook_numlock_keys[] = { | ||
106 | { KEY_J, KEY_KP1 }, | ||
107 | { KEY_K, KEY_KP2 }, | ||
108 | { KEY_L, KEY_KP3 }, | ||
109 | { KEY_U, KEY_KP4 }, | ||
110 | { KEY_I, KEY_KP5 }, | ||
111 | { KEY_O, KEY_KP6 }, | ||
112 | { KEY_7, KEY_KP7 }, | ||
113 | { KEY_8, KEY_KP8 }, | ||
114 | { KEY_9, KEY_KP9 }, | ||
115 | { KEY_M, KEY_KP0 }, | ||
116 | { KEY_DOT, KEY_KPDOT }, | ||
117 | { KEY_SLASH, KEY_KPPLUS }, | ||
118 | { KEY_SEMICOLON, KEY_KPMINUS }, | ||
119 | { KEY_P, KEY_KPASTERISK }, | ||
120 | { KEY_MINUS, KEY_KPEQUAL }, | ||
121 | { KEY_0, KEY_KPSLASH }, | ||
122 | { KEY_F6, KEY_NUMLOCK }, | ||
123 | { KEY_KPENTER, KEY_KPENTER }, | ||
124 | { KEY_BACKSPACE, KEY_BACKSPACE }, | ||
125 | { } | ||
126 | }; | ||
127 | |||
128 | static int usbhid_pb_fnmode = 1; | ||
129 | module_param_named(pb_fnmode, usbhid_pb_fnmode, int, 0644); | ||
130 | MODULE_PARM_DESC(pb_fnmode, | ||
131 | "Mode of fn key on PowerBooks (0 = disabled, 1 = fkeyslast, 2 = fkeysfirst)"); | ||
132 | |||
133 | static struct hidinput_key_translation *find_translation(struct hidinput_key_translation *table, u16 from) | ||
134 | { | ||
135 | struct hidinput_key_translation *trans; | ||
136 | |||
137 | /* Look for the translation */ | ||
138 | for (trans = table; trans->from; trans++) | ||
139 | if (trans->from == from) | ||
140 | return trans; | ||
141 | |||
142 | return NULL; | ||
143 | } | ||
144 | |||
145 | static int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, | ||
146 | struct hid_usage *usage, __s32 value) | ||
147 | { | ||
148 | struct hidinput_key_translation *trans; | ||
149 | |||
150 | if (usage->code == KEY_FN) { | ||
151 | if (value) hid->quirks |= HID_QUIRK_POWERBOOK_FN_ON; | ||
152 | else hid->quirks &= ~HID_QUIRK_POWERBOOK_FN_ON; | ||
153 | |||
154 | input_event(input, usage->type, usage->code, value); | ||
155 | |||
156 | return 1; | ||
157 | } | ||
158 | |||
159 | if (usbhid_pb_fnmode) { | ||
160 | int do_translate; | ||
161 | |||
162 | trans = find_translation(powerbook_fn_keys, usage->code); | ||
163 | if (trans) { | ||
164 | if (test_bit(usage->code, hid->pb_pressed_fn)) | ||
165 | do_translate = 1; | ||
166 | else if (trans->flags & POWERBOOK_FLAG_FKEY) | ||
167 | do_translate = | ||
168 | (usbhid_pb_fnmode == 2 && (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)) || | ||
169 | (usbhid_pb_fnmode == 1 && !(hid->quirks & HID_QUIRK_POWERBOOK_FN_ON)); | ||
170 | else | ||
171 | do_translate = (hid->quirks & HID_QUIRK_POWERBOOK_FN_ON); | ||
172 | |||
173 | if (do_translate) { | ||
174 | if (value) | ||
175 | set_bit(usage->code, hid->pb_pressed_fn); | ||
176 | else | ||
177 | clear_bit(usage->code, hid->pb_pressed_fn); | ||
178 | |||
179 | input_event(input, usage->type, trans->to, value); | ||
180 | |||
181 | return 1; | ||
182 | } | ||
183 | } | ||
184 | |||
185 | if (test_bit(usage->code, hid->pb_pressed_numlock) || | ||
186 | test_bit(LED_NUML, input->led)) { | ||
187 | trans = find_translation(powerbook_numlock_keys, usage->code); | ||
188 | |||
189 | if (trans) { | ||
190 | if (value) | ||
191 | set_bit(usage->code, hid->pb_pressed_numlock); | ||
192 | else | ||
193 | clear_bit(usage->code, hid->pb_pressed_numlock); | ||
194 | |||
195 | input_event(input, usage->type, trans->to, value); | ||
196 | } | ||
197 | |||
198 | return 1; | ||
199 | } | ||
200 | } | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static void hidinput_pb_setup(struct input_dev *input) | ||
206 | { | ||
207 | struct hidinput_key_translation *trans; | ||
208 | |||
209 | set_bit(KEY_NUMLOCK, input->keybit); | ||
210 | |||
211 | /* Enable all needed keys */ | ||
212 | for (trans = powerbook_fn_keys; trans->from; trans++) | ||
213 | set_bit(trans->to, input->keybit); | ||
214 | |||
215 | for (trans = powerbook_numlock_keys; trans->from; trans++) | ||
216 | set_bit(trans->to, input->keybit); | ||
217 | } | ||
218 | #else | ||
219 | static inline int hidinput_pb_event(struct hid_device *hid, struct input_dev *input, | ||
220 | struct hid_usage *usage, __s32 value) | ||
221 | { | ||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static inline void hidinput_pb_setup(struct input_dev *input) | ||
226 | { | ||
227 | } | ||
228 | #endif | ||
229 | |||
76 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, | 230 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, |
77 | struct hid_usage *usage) | 231 | struct hid_usage *usage) |
78 | { | 232 | { |
@@ -135,8 +289,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
135 | case HID_UP_SIMULATION: | 289 | case HID_UP_SIMULATION: |
136 | 290 | ||
137 | switch (usage->hid & 0xffff) { | 291 | switch (usage->hid & 0xffff) { |
138 | case 0xba: map_abs(ABS_RUDDER); break; | 292 | case 0xba: map_abs(ABS_RUDDER); break; |
139 | case 0xbb: map_abs(ABS_THROTTLE); break; | 293 | case 0xbb: map_abs(ABS_THROTTLE); break; |
294 | case 0xc4: map_abs(ABS_GAS); break; | ||
295 | case 0xc5: map_abs(ABS_BRAKE); break; | ||
296 | case 0xc8: map_abs(ABS_WHEEL); break; | ||
140 | default: goto ignore; | 297 | default: goto ignore; |
141 | } | 298 | } |
142 | break; | 299 | break; |
@@ -289,11 +446,19 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
289 | case 0x226: map_key_clear(KEY_STOP); break; | 446 | case 0x226: map_key_clear(KEY_STOP); break; |
290 | case 0x227: map_key_clear(KEY_REFRESH); break; | 447 | case 0x227: map_key_clear(KEY_REFRESH); break; |
291 | case 0x22a: map_key_clear(KEY_BOOKMARKS); break; | 448 | case 0x22a: map_key_clear(KEY_BOOKMARKS); break; |
449 | case 0x233: map_key_clear(KEY_SCROLLUP); break; | ||
450 | case 0x234: map_key_clear(KEY_SCROLLDOWN); break; | ||
292 | case 0x238: map_rel(REL_HWHEEL); break; | 451 | case 0x238: map_rel(REL_HWHEEL); break; |
293 | case 0x279: map_key_clear(KEY_REDO); break; | 452 | case 0x279: map_key_clear(KEY_REDO); break; |
294 | case 0x289: map_key_clear(KEY_REPLY); break; | 453 | case 0x289: map_key_clear(KEY_REPLY); break; |
295 | case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; | 454 | case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; |
296 | case 0x28c: map_key_clear(KEY_SEND); break; | 455 | case 0x28c: map_key_clear(KEY_SEND); break; |
456 | |||
457 | /* Reported on a Cherry Cymotion keyboard */ | ||
458 | case 0x301: map_key_clear(KEY_PROG1); break; | ||
459 | case 0x302: map_key_clear(KEY_PROG2); break; | ||
460 | case 0x303: map_key_clear(KEY_PROG3); break; | ||
461 | |||
297 | default: goto ignore; | 462 | default: goto ignore; |
298 | } | 463 | } |
299 | break; | 464 | break; |
@@ -325,7 +490,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel | |||
325 | 490 | ||
326 | set_bit(EV_REP, input->evbit); | 491 | set_bit(EV_REP, input->evbit); |
327 | switch(usage->hid & HID_USAGE) { | 492 | switch(usage->hid & HID_USAGE) { |
328 | case 0x003: map_key_clear(KEY_FN); break; | 493 | case 0x003: |
494 | /* The fn key on Apple PowerBooks */ | ||
495 | map_key_clear(KEY_FN); | ||
496 | hidinput_pb_setup(input); | ||
497 | break; | ||
498 | |||
329 | default: goto ignore; | 499 | default: goto ignore; |
330 | } | 500 | } |
331 | break; | 501 | break; |
@@ -482,6 +652,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
482 | return; | 652 | return; |
483 | } | 653 | } |
484 | 654 | ||
655 | if ((hid->quirks & HID_QUIRK_POWERBOOK_HAS_FN) && hidinput_pb_event(hid, input, usage, value)) | ||
656 | return; | ||
657 | |||
485 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { | 658 | if (usage->hat_min < usage->hat_max || usage->hat_dir) { |
486 | int hat_dir = usage->hat_dir; | 659 | int hat_dir = usage->hat_dir; |
487 | if (!hat_dir) | 660 | if (!hat_dir) |
@@ -524,7 +697,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct | |||
524 | return; | 697 | return; |
525 | } | 698 | } |
526 | 699 | ||
527 | if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ | 700 | if ((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UNKNOWN */ |
528 | return; | 701 | return; |
529 | 702 | ||
530 | input_event(input, usage->type, usage->code, value); | 703 | input_event(input, usage->type, usage->code, value); |
diff --git a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h index ee48a2276104..8b0d4346ce9c 100644 --- a/drivers/usb/input/hid.h +++ b/drivers/usb/input/hid.h | |||
@@ -235,17 +235,20 @@ struct hid_item { | |||
235 | * HID device quirks. | 235 | * HID device quirks. |
236 | */ | 236 | */ |
237 | 237 | ||
238 | #define HID_QUIRK_INVERT 0x001 | 238 | #define HID_QUIRK_INVERT 0x00000001 |
239 | #define HID_QUIRK_NOTOUCH 0x002 | 239 | #define HID_QUIRK_NOTOUCH 0x00000002 |
240 | #define HID_QUIRK_IGNORE 0x004 | 240 | #define HID_QUIRK_IGNORE 0x00000004 |
241 | #define HID_QUIRK_NOGET 0x008 | 241 | #define HID_QUIRK_NOGET 0x00000008 |
242 | #define HID_QUIRK_HIDDEV 0x010 | 242 | #define HID_QUIRK_HIDDEV 0x00000010 |
243 | #define HID_QUIRK_BADPAD 0x020 | 243 | #define HID_QUIRK_BADPAD 0x00000020 |
244 | #define HID_QUIRK_MULTI_INPUT 0x040 | 244 | #define HID_QUIRK_MULTI_INPUT 0x00000040 |
245 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x080 | 245 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_7 0x00000080 |
246 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x100 | 246 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_5 0x00000100 |
247 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x200 | 247 | #define HID_QUIRK_2WHEEL_MOUSE_HACK_ON 0x00000200 |
248 | #define HID_QUIRK_2WHEEL_POWERMOUSE 0x400 | 248 | #define HID_QUIRK_2WHEEL_POWERMOUSE 0x00000400 |
249 | #define HID_QUIRK_CYMOTION 0x00000800 | ||
250 | #define HID_QUIRK_POWERBOOK_HAS_FN 0x00001000 | ||
251 | #define HID_QUIRK_POWERBOOK_FN_ON 0x00002000 | ||
249 | 252 | ||
250 | /* | 253 | /* |
251 | * This is the global environment of the parser. This information is | 254 | * This is the global environment of the parser. This information is |
@@ -431,6 +434,11 @@ struct hid_device { /* device report descriptor */ | |||
431 | void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ | 434 | void (*ff_exit)(struct hid_device*); /* Called by hid_exit_ff(hid) */ |
432 | int (*ff_event)(struct hid_device *hid, struct input_dev *input, | 435 | int (*ff_event)(struct hid_device *hid, struct input_dev *input, |
433 | unsigned int type, unsigned int code, int value); | 436 | unsigned int type, unsigned int code, int value); |
437 | |||
438 | #ifdef CONFIG_USB_HIDINPUT_POWERBOOK | ||
439 | unsigned long pb_pressed_fn[NBITS(KEY_MAX)]; | ||
440 | unsigned long pb_pressed_numlock[NBITS(KEY_MAX)]; | ||
441 | #endif | ||
434 | }; | 442 | }; |
435 | 443 | ||
436 | #define HID_GLOBAL_STACK_SIZE 4 | 444 | #define HID_GLOBAL_STACK_SIZE 4 |
diff --git a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c index 19e015d171aa..d9d9f656b8c9 100644 --- a/drivers/usb/input/pid.c +++ b/drivers/usb/input/pid.c | |||
@@ -259,7 +259,7 @@ static int hid_pid_upload_effect(struct input_dev *dev, | |||
259 | int hid_pid_init(struct hid_device *hid) | 259 | int hid_pid_init(struct hid_device *hid) |
260 | { | 260 | { |
261 | struct hid_ff_pid *private; | 261 | struct hid_ff_pid *private; |
262 | struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list); | 262 | struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); |
263 | struct input_dev *input_dev = hidinput->input; | 263 | struct input_dev *input_dev = hidinput->input; |
264 | 264 | ||
265 | private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); | 265 | private = hid->ff_private = kzalloc(sizeof(struct hid_ff_pid), GFP_KERNEL); |
diff --git a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c index 48df4cfd5a42..d3e15df9e815 100644 --- a/drivers/usb/input/wacom.c +++ b/drivers/usb/input/wacom.c | |||
@@ -95,7 +95,7 @@ MODULE_LICENSE(DRIVER_LICENSE); | |||
95 | enum { | 95 | enum { |
96 | PENPARTNER = 0, | 96 | PENPARTNER = 0, |
97 | GRAPHIRE, | 97 | GRAPHIRE, |
98 | G4, | 98 | WACOM_G4, |
99 | PL, | 99 | PL, |
100 | INTUOS, | 100 | INTUOS, |
101 | INTUOS3, | 101 | INTUOS3, |
@@ -373,7 +373,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
373 | 373 | ||
374 | case 2: /* Mouse with wheel */ | 374 | case 2: /* Mouse with wheel */ |
375 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); | 375 | input_report_key(dev, BTN_MIDDLE, data[1] & 0x04); |
376 | if (wacom->features->type == G4) { | 376 | if (wacom->features->type == WACOM_G4) { |
377 | rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); | 377 | rw = data[7] & 0x04 ? -(data[7] & 0x03) : (data[7] & 0x03); |
378 | input_report_rel(dev, REL_WHEEL, rw); | 378 | input_report_rel(dev, REL_WHEEL, rw); |
379 | } else | 379 | } else |
@@ -385,7 +385,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
385 | id = CURSOR_DEVICE_ID; | 385 | id = CURSOR_DEVICE_ID; |
386 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); | 386 | input_report_key(dev, BTN_LEFT, data[1] & 0x01); |
387 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); | 387 | input_report_key(dev, BTN_RIGHT, data[1] & 0x02); |
388 | if (wacom->features->type == G4) | 388 | if (wacom->features->type == WACOM_G4) |
389 | input_report_abs(dev, ABS_DISTANCE, data[6]); | 389 | input_report_abs(dev, ABS_DISTANCE, data[6]); |
390 | else | 390 | else |
391 | input_report_abs(dev, ABS_DISTANCE, data[7]); | 391 | input_report_abs(dev, ABS_DISTANCE, data[7]); |
@@ -410,7 +410,7 @@ static void wacom_graphire_irq(struct urb *urb, struct pt_regs *regs) | |||
410 | input_sync(dev); | 410 | input_sync(dev); |
411 | 411 | ||
412 | /* send pad data */ | 412 | /* send pad data */ |
413 | if (wacom->features->type == G4) { | 413 | if (wacom->features->type == WACOM_G4) { |
414 | /* fist time sending pad data */ | 414 | /* fist time sending pad data */ |
415 | if (wacom->tool[1] != BTN_TOOL_FINGER) { | 415 | if (wacom->tool[1] != BTN_TOOL_FINGER) { |
416 | wacom->id[1] = 0; | 416 | wacom->id[1] = 0; |
@@ -713,8 +713,8 @@ static struct wacom_features wacom_features[] = { | |||
713 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 713 | { "Wacom Graphire2 5x7", 8, 13918, 10206, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
714 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 714 | { "Wacom Graphire3", 8, 10208, 7424, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
715 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 715 | { "Wacom Graphire3 6x8", 8, 16704, 12064, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
716 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, G4, wacom_graphire_irq }, | 716 | { "Wacom Graphire4 4x5", 8, 10208, 7424, 511, 32, WACOM_G4, wacom_graphire_irq }, |
717 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, G4, wacom_graphire_irq }, | 717 | { "Wacom Graphire4 6x8", 8, 16704, 12064, 511, 32, WACOM_G4, wacom_graphire_irq }, |
718 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 718 | { "Wacom Volito", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
719 | { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, | 719 | { "Wacom PenStation2", 8, 3250, 2320, 255, 32, GRAPHIRE, wacom_graphire_irq }, |
720 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, | 720 | { "Wacom Volito2 4x5", 8, 5104, 3712, 511, 32, GRAPHIRE, wacom_graphire_irq }, |
@@ -859,7 +859,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i | |||
859 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); | 859 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, wacom->features->pressure_max, 0, 0); |
860 | 860 | ||
861 | switch (wacom->features->type) { | 861 | switch (wacom->features->type) { |
862 | case G4: | 862 | case WACOM_G4: |
863 | input_dev->evbit[0] |= BIT(EV_MSC); | 863 | input_dev->evbit[0] |= BIT(EV_MSC); |
864 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); | 864 | input_dev->mscbit[0] |= BIT(MSC_SERIAL); |
865 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); | 865 | input_dev->keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER); |
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c index 664139afcfa9..e9f9f4bafa17 100644 --- a/drivers/usb/serial/bus.c +++ b/drivers/usb/serial/bus.c | |||
@@ -37,11 +37,6 @@ static int usb_serial_device_match (struct device *dev, struct device_driver *dr | |||
37 | return 0; | 37 | return 0; |
38 | } | 38 | } |
39 | 39 | ||
40 | struct bus_type usb_serial_bus_type = { | ||
41 | .name = "usb-serial", | ||
42 | .match = usb_serial_device_match, | ||
43 | }; | ||
44 | |||
45 | static int usb_serial_device_probe (struct device *dev) | 40 | static int usb_serial_device_probe (struct device *dev) |
46 | { | 41 | { |
47 | struct usb_serial_driver *driver; | 42 | struct usb_serial_driver *driver; |
@@ -109,14 +104,18 @@ exit: | |||
109 | return retval; | 104 | return retval; |
110 | } | 105 | } |
111 | 106 | ||
107 | struct bus_type usb_serial_bus_type = { | ||
108 | .name = "usb-serial", | ||
109 | .match = usb_serial_device_match, | ||
110 | .probe = usb_serial_device_probe, | ||
111 | .remove = usb_serial_device_remove, | ||
112 | }; | ||
113 | |||
112 | int usb_serial_bus_register(struct usb_serial_driver *driver) | 114 | int usb_serial_bus_register(struct usb_serial_driver *driver) |
113 | { | 115 | { |
114 | int retval; | 116 | int retval; |
115 | 117 | ||
116 | driver->driver.bus = &usb_serial_bus_type; | 118 | driver->driver.bus = &usb_serial_bus_type; |
117 | driver->driver.probe = usb_serial_device_probe; | ||
118 | driver->driver.remove = usb_serial_device_remove; | ||
119 | |||
120 | retval = driver_register(&driver->driver); | 119 | retval = driver_register(&driver->driver); |
121 | 120 | ||
122 | return retval; | 121 | return retval; |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 9ffff1938239..0eb883f44ada 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -43,8 +43,6 @@ static int debug; | |||
43 | #define PL2303_BUF_SIZE 1024 | 43 | #define PL2303_BUF_SIZE 1024 |
44 | #define PL2303_TMP_BUF_SIZE 1024 | 44 | #define PL2303_TMP_BUF_SIZE 1024 |
45 | 45 | ||
46 | static DECLARE_MUTEX(pl2303_tmp_buf_sem); | ||
47 | |||
48 | struct pl2303_buf { | 46 | struct pl2303_buf { |
49 | unsigned int buf_size; | 47 | unsigned int buf_size; |
50 | char *buf_buf; | 48 | char *buf_buf; |
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index d549e215f3c5..2c42a812655a 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c | |||
@@ -590,6 +590,8 @@ static u_short maxfmode, chipset; | |||
590 | #define highw(x) ((u_long)(x)>>16 & 0xffff) | 590 | #define highw(x) ((u_long)(x)>>16 & 0xffff) |
591 | #define loww(x) ((u_long)(x) & 0xffff) | 591 | #define loww(x) ((u_long)(x) & 0xffff) |
592 | 592 | ||
593 | #define custom amiga_custom | ||
594 | |||
593 | #define VBlankOn() custom.intena = IF_SETCLR|IF_COPER | 595 | #define VBlankOn() custom.intena = IF_SETCLR|IF_COPER |
594 | #define VBlankOff() custom.intena = IF_COPER | 596 | #define VBlankOff() custom.intena = IF_COPER |
595 | 597 | ||
@@ -1164,8 +1166,8 @@ static void ami_update_display(void); | |||
1164 | static void ami_init_display(void); | 1166 | static void ami_init_display(void); |
1165 | static void ami_do_blank(void); | 1167 | static void ami_do_blank(void); |
1166 | static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix); | 1168 | static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix); |
1167 | static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data); | 1169 | static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data); |
1168 | static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data); | 1170 | static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data); |
1169 | static int ami_get_cursorstate(struct fb_cursorstate *state); | 1171 | static int ami_get_cursorstate(struct fb_cursorstate *state); |
1170 | static int ami_set_cursorstate(struct fb_cursorstate *state); | 1172 | static int ami_set_cursorstate(struct fb_cursorstate *state); |
1171 | static void ami_set_sprite(void); | 1173 | static void ami_set_sprite(void); |
@@ -2179,6 +2181,7 @@ static int amifb_ioctl(struct inode *inode, struct file *file, | |||
2179 | struct fb_var_cursorinfo var; | 2181 | struct fb_var_cursorinfo var; |
2180 | struct fb_cursorstate state; | 2182 | struct fb_cursorstate state; |
2181 | } crsr; | 2183 | } crsr; |
2184 | void __user *argp = (void __user *)arg; | ||
2182 | int i; | 2185 | int i; |
2183 | 2186 | ||
2184 | switch (cmd) { | 2187 | switch (cmd) { |
@@ -2186,33 +2189,32 @@ static int amifb_ioctl(struct inode *inode, struct file *file, | |||
2186 | i = ami_get_fix_cursorinfo(&crsr.fix); | 2189 | i = ami_get_fix_cursorinfo(&crsr.fix); |
2187 | if (i) | 2190 | if (i) |
2188 | return i; | 2191 | return i; |
2189 | return copy_to_user((void *)arg, &crsr.fix, | 2192 | return copy_to_user(argp, &crsr.fix, |
2190 | sizeof(crsr.fix)) ? -EFAULT : 0; | 2193 | sizeof(crsr.fix)) ? -EFAULT : 0; |
2191 | 2194 | ||
2192 | case FBIOGET_VCURSORINFO: | 2195 | case FBIOGET_VCURSORINFO: |
2193 | i = ami_get_var_cursorinfo(&crsr.var, | 2196 | i = ami_get_var_cursorinfo(&crsr.var, |
2194 | ((struct fb_var_cursorinfo *)arg)->data); | 2197 | ((struct fb_var_cursorinfo __user *)arg)->data); |
2195 | if (i) | 2198 | if (i) |
2196 | return i; | 2199 | return i; |
2197 | return copy_to_user((void *)arg, &crsr.var, | 2200 | return copy_to_user(argp, &crsr.var, |
2198 | sizeof(crsr.var)) ? -EFAULT : 0; | 2201 | sizeof(crsr.var)) ? -EFAULT : 0; |
2199 | 2202 | ||
2200 | case FBIOPUT_VCURSORINFO: | 2203 | case FBIOPUT_VCURSORINFO: |
2201 | if (copy_from_user(&crsr.var, (void *)arg, | 2204 | if (copy_from_user(&crsr.var, argp, sizeof(crsr.var))) |
2202 | sizeof(crsr.var))) | ||
2203 | return -EFAULT; | 2205 | return -EFAULT; |
2204 | return ami_set_var_cursorinfo(&crsr.var, | 2206 | return ami_set_var_cursorinfo(&crsr.var, |
2205 | ((struct fb_var_cursorinfo *)arg)->data); | 2207 | ((struct fb_var_cursorinfo __user *)arg)->data); |
2206 | 2208 | ||
2207 | case FBIOGET_CURSORSTATE: | 2209 | case FBIOGET_CURSORSTATE: |
2208 | i = ami_get_cursorstate(&crsr.state); | 2210 | i = ami_get_cursorstate(&crsr.state); |
2209 | if (i) | 2211 | if (i) |
2210 | return i; | 2212 | return i; |
2211 | return copy_to_user((void *)arg, &crsr.state, | 2213 | return copy_to_user(argp, &crsr.state, |
2212 | sizeof(crsr.state)) ? -EFAULT : 0; | 2214 | sizeof(crsr.state)) ? -EFAULT : 0; |
2213 | 2215 | ||
2214 | case FBIOPUT_CURSORSTATE: | 2216 | case FBIOPUT_CURSORSTATE: |
2215 | if (copy_from_user(&crsr.state, (void *)arg, | 2217 | if (copy_from_user(&crsr.state, argp, |
2216 | sizeof(crsr.state))) | 2218 | sizeof(crsr.state))) |
2217 | return -EFAULT; | 2219 | return -EFAULT; |
2218 | return ami_set_cursorstate(&crsr.state); | 2220 | return ami_set_cursorstate(&crsr.state); |
@@ -3325,7 +3327,7 @@ static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix) | |||
3325 | return 0; | 3327 | return 0; |
3326 | } | 3328 | } |
3327 | 3329 | ||
3328 | static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data) | 3330 | static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data) |
3329 | { | 3331 | { |
3330 | struct amifb_par *par = ¤tpar; | 3332 | struct amifb_par *par = ¤tpar; |
3331 | register u_short *lspr, *sspr; | 3333 | register u_short *lspr, *sspr; |
@@ -3347,14 +3349,14 @@ static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data) | |||
3347 | var->yspot = par->crsr.spot_y; | 3349 | var->yspot = par->crsr.spot_y; |
3348 | if (size > var->height*var->width) | 3350 | if (size > var->height*var->width) |
3349 | return -ENAMETOOLONG; | 3351 | return -ENAMETOOLONG; |
3350 | if (!access_ok(VERIFY_WRITE, (void *)data, size)) | 3352 | if (!access_ok(VERIFY_WRITE, data, size)) |
3351 | return -EFAULT; | 3353 | return -EFAULT; |
3352 | delta = 1<<par->crsr.fmode; | 3354 | delta = 1<<par->crsr.fmode; |
3353 | lspr = lofsprite + (delta<<1); | 3355 | lspr = lofsprite + (delta<<1); |
3354 | if (par->bplcon0 & BPC0_LACE) | 3356 | if (par->bplcon0 & BPC0_LACE) |
3355 | sspr = shfsprite + (delta<<1); | 3357 | sspr = shfsprite + (delta<<1); |
3356 | else | 3358 | else |
3357 | sspr = 0; | 3359 | sspr = NULL; |
3358 | for (height = (short)var->height-1; height >= 0; height--) { | 3360 | for (height = (short)var->height-1; height >= 0; height--) { |
3359 | bits = 0; words = delta; datawords = 0; | 3361 | bits = 0; words = delta; datawords = 0; |
3360 | for (width = (short)var->width-1; width >= 0; width--) { | 3362 | for (width = (short)var->width-1; width >= 0; width--) { |
@@ -3400,7 +3402,7 @@ static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data) | |||
3400 | return 0; | 3402 | return 0; |
3401 | } | 3403 | } |
3402 | 3404 | ||
3403 | static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data) | 3405 | static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data) |
3404 | { | 3406 | { |
3405 | struct amifb_par *par = ¤tpar; | 3407 | struct amifb_par *par = ¤tpar; |
3406 | register u_short *lspr, *sspr; | 3408 | register u_short *lspr, *sspr; |
@@ -3427,7 +3429,7 @@ static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data) | |||
3427 | return -EINVAL; | 3429 | return -EINVAL; |
3428 | if (!var->height) | 3430 | if (!var->height) |
3429 | return -EINVAL; | 3431 | return -EINVAL; |
3430 | if (!access_ok(VERIFY_READ, (void *)data, var->width*var->height)) | 3432 | if (!access_ok(VERIFY_READ, data, var->width*var->height)) |
3431 | return -EFAULT; | 3433 | return -EFAULT; |
3432 | delta = 1<<fmode; | 3434 | delta = 1<<fmode; |
3433 | lofsprite = shfsprite = (u_short *)spritememory; | 3435 | lofsprite = shfsprite = (u_short *)spritememory; |
@@ -3442,13 +3444,13 @@ static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char *data) | |||
3442 | if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE) | 3444 | if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE) |
3443 | return -EINVAL; | 3445 | return -EINVAL; |
3444 | memset(lspr, 0, (var->height+2)<<fmode<<2); | 3446 | memset(lspr, 0, (var->height+2)<<fmode<<2); |
3445 | sspr = 0; | 3447 | sspr = NULL; |
3446 | } | 3448 | } |
3447 | for (height = (short)var->height-1; height >= 0; height--) { | 3449 | for (height = (short)var->height-1; height >= 0; height--) { |
3448 | bits = 16; words = delta; datawords = 0; | 3450 | bits = 16; words = delta; datawords = 0; |
3449 | for (width = (short)var->width-1; width >= 0; width--) { | 3451 | for (width = (short)var->width-1; width >= 0; width--) { |
3450 | unsigned long tdata = 0; | 3452 | unsigned long tdata = 0; |
3451 | get_user(tdata, (char *)data); | 3453 | get_user(tdata, data); |
3452 | data++; | 3454 | data++; |
3453 | #ifdef __mc68000__ | 3455 | #ifdef __mc68000__ |
3454 | asm volatile ( | 3456 | asm volatile ( |
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index e370125e4fbc..ed81005cbdba 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c | |||
@@ -3501,7 +3501,7 @@ err_release_mem: | |||
3501 | 3501 | ||
3502 | static int __devinit atyfb_atari_probe(void) | 3502 | static int __devinit atyfb_atari_probe(void) |
3503 | { | 3503 | { |
3504 | struct aty_par *par; | 3504 | struct atyfb_par *par; |
3505 | struct fb_info *info; | 3505 | struct fb_info *info; |
3506 | int m64_num; | 3506 | int m64_num; |
3507 | u32 clock_r; | 3507 | u32 clock_r; |
diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index cfc748e94272..e6cbd9de944a 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c | |||
@@ -609,18 +609,19 @@ void __init macfb_setup(char *options) | |||
609 | } | 609 | } |
610 | } | 610 | } |
611 | 611 | ||
612 | void __init macfb_init(void) | 612 | static int __init macfb_init(void) |
613 | { | 613 | { |
614 | int video_cmap_len, video_is_nubus = 0; | 614 | int video_cmap_len, video_is_nubus = 0; |
615 | struct nubus_dev* ndev = NULL; | 615 | struct nubus_dev* ndev = NULL; |
616 | char *option = NULL; | 616 | char *option = NULL; |
617 | int err; | ||
617 | 618 | ||
618 | if (fb_get_options("macfb", &option)) | 619 | if (fb_get_options("macfb", &option)) |
619 | return -ENODEV; | 620 | return -ENODEV; |
620 | macfb_setup(option); | 621 | macfb_setup(option); |
621 | 622 | ||
622 | if (!MACH_IS_MAC) | 623 | if (!MACH_IS_MAC) |
623 | return; | 624 | return -ENODEV; |
624 | 625 | ||
625 | /* There can only be one internal video controller anyway so | 626 | /* There can only be one internal video controller anyway so |
626 | we're not too worried about this */ | 627 | we're not too worried about this */ |
@@ -958,11 +959,11 @@ void __init macfb_init(void) | |||
958 | 959 | ||
959 | fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0); | 960 | fb_alloc_cmap(&fb_info.cmap, video_cmap_len, 0); |
960 | 961 | ||
961 | if (register_framebuffer(&fb_info) < 0) | 962 | err = register_framebuffer(&fb_info); |
962 | return; | 963 | if (!err) |
963 | 964 | printk("fb%d: %s frame buffer device\n", | |
964 | printk("fb%d: %s frame buffer device\n", | 965 | fb_info.node, fb_info.fix.id); |
965 | fb_info.node, fb_info.fix.id); | 966 | return err; |
966 | } | 967 | } |
967 | 968 | ||
968 | module_init(macfb_init); | 969 | module_init(macfb_init); |
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index 1a409c2c320c..7aa2d3de6d37 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c | |||
@@ -45,7 +45,7 @@ proc_bus_zorro_lseek(struct file *file, loff_t off, int whence) | |||
45 | } | 45 | } |
46 | 46 | ||
47 | static ssize_t | 47 | static ssize_t |
48 | proc_bus_zorro_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos) | 48 | proc_bus_zorro_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) |
49 | { | 49 | { |
50 | struct inode *ino = file->f_dentry->d_inode; | 50 | struct inode *ino = file->f_dentry->d_inode; |
51 | struct proc_dir_entry *dp = PDE(ino); | 51 | struct proc_dir_entry *dp = PDE(ino); |
diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index ccba227676f2..fcbee748c592 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c | |||
@@ -77,7 +77,6 @@ int zorro_register_driver(struct zorro_driver *drv) | |||
77 | /* initialize common driver fields */ | 77 | /* initialize common driver fields */ |
78 | drv->driver.name = drv->name; | 78 | drv->driver.name = drv->name; |
79 | drv->driver.bus = &zorro_bus_type; | 79 | drv->driver.bus = &zorro_bus_type; |
80 | drv->driver.probe = zorro_device_probe; | ||
81 | 80 | ||
82 | /* register with core */ | 81 | /* register with core */ |
83 | count = driver_register(&drv->driver); | 82 | count = driver_register(&drv->driver); |
@@ -132,7 +131,8 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv) | |||
132 | 131 | ||
133 | struct bus_type zorro_bus_type = { | 132 | struct bus_type zorro_bus_type = { |
134 | .name = "zorro", | 133 | .name = "zorro", |
135 | .match = zorro_bus_match | 134 | .match = zorro_bus_match, |
135 | .probe = zorro_device_probe, | ||
136 | }; | 136 | }; |
137 | 137 | ||
138 | 138 | ||