diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/phantom.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/drivers/misc/phantom.c b/drivers/misc/phantom.c index 35b139b0e5f2..4b5959b2c934 100644 --- a/drivers/misc/phantom.c +++ b/drivers/misc/phantom.c | |||
@@ -47,6 +47,7 @@ struct phantom_device { | |||
47 | struct cdev cdev; | 47 | struct cdev cdev; |
48 | 48 | ||
49 | struct mutex open_lock; | 49 | struct mutex open_lock; |
50 | spinlock_t ioctl_lock; | ||
50 | }; | 51 | }; |
51 | 52 | ||
52 | static unsigned char phantom_devices[PHANTOM_MAX_MINORS]; | 53 | static unsigned char phantom_devices[PHANTOM_MAX_MINORS]; |
@@ -71,8 +72,8 @@ static int phantom_status(struct phantom_device *dev, unsigned long newstat) | |||
71 | * File ops | 72 | * File ops |
72 | */ | 73 | */ |
73 | 74 | ||
74 | static int phantom_ioctl(struct inode *inode, struct file *file, u_int cmd, | 75 | static long phantom_ioctl(struct file *file, unsigned int cmd, |
75 | u_long arg) | 76 | unsigned long arg) |
76 | { | 77 | { |
77 | struct phantom_device *dev = file->private_data; | 78 | struct phantom_device *dev = file->private_data; |
78 | struct phm_regs rs; | 79 | struct phm_regs rs; |
@@ -92,24 +93,30 @@ static int phantom_ioctl(struct inode *inode, struct file *file, u_int cmd, | |||
92 | if (r.reg > 7) | 93 | if (r.reg > 7) |
93 | return -EINVAL; | 94 | return -EINVAL; |
94 | 95 | ||
96 | spin_lock(&dev->ioctl_lock); | ||
95 | if (r.reg == PHN_CONTROL && (r.value & PHN_CTL_IRQ) && | 97 | if (r.reg == PHN_CONTROL && (r.value & PHN_CTL_IRQ) && |
96 | phantom_status(dev, dev->status | PHB_RUNNING)) | 98 | phantom_status(dev, dev->status | PHB_RUNNING)){ |
99 | spin_unlock(&dev->ioctl_lock); | ||
97 | return -ENODEV; | 100 | return -ENODEV; |
101 | } | ||
98 | 102 | ||
99 | pr_debug("phantom: writing %x to %u\n", r.value, r.reg); | 103 | pr_debug("phantom: writing %x to %u\n", r.value, r.reg); |
100 | iowrite32(r.value, dev->iaddr + r.reg); | 104 | iowrite32(r.value, dev->iaddr + r.reg); |
101 | 105 | ||
102 | if (r.reg == PHN_CONTROL && !(r.value & PHN_CTL_IRQ)) | 106 | if (r.reg == PHN_CONTROL && !(r.value & PHN_CTL_IRQ)) |
103 | phantom_status(dev, dev->status & ~PHB_RUNNING); | 107 | phantom_status(dev, dev->status & ~PHB_RUNNING); |
108 | spin_unlock(&dev->ioctl_lock); | ||
104 | break; | 109 | break; |
105 | case PHN_SET_REGS: | 110 | case PHN_SET_REGS: |
106 | if (copy_from_user(&rs, argp, sizeof(rs))) | 111 | if (copy_from_user(&rs, argp, sizeof(rs))) |
107 | return -EFAULT; | 112 | return -EFAULT; |
108 | 113 | ||
109 | pr_debug("phantom: SRS %u regs %x\n", rs.count, rs.mask); | 114 | pr_debug("phantom: SRS %u regs %x\n", rs.count, rs.mask); |
115 | spin_lock(&dev->ioctl_lock); | ||
110 | for (i = 0; i < min(rs.count, 8U); i++) | 116 | for (i = 0; i < min(rs.count, 8U); i++) |
111 | if ((1 << i) & rs.mask) | 117 | if ((1 << i) & rs.mask) |
112 | iowrite32(rs.values[i], dev->oaddr + i); | 118 | iowrite32(rs.values[i], dev->oaddr + i); |
119 | spin_unlock(&dev->ioctl_lock); | ||
113 | break; | 120 | break; |
114 | case PHN_GET_REG: | 121 | case PHN_GET_REG: |
115 | if (copy_from_user(&r, argp, sizeof(r))) | 122 | if (copy_from_user(&r, argp, sizeof(r))) |
@@ -128,9 +135,11 @@ static int phantom_ioctl(struct inode *inode, struct file *file, u_int cmd, | |||
128 | return -EFAULT; | 135 | return -EFAULT; |
129 | 136 | ||
130 | pr_debug("phantom: GRS %u regs %x\n", rs.count, rs.mask); | 137 | pr_debug("phantom: GRS %u regs %x\n", rs.count, rs.mask); |
138 | spin_lock(&dev->ioctl_lock); | ||
131 | for (i = 0; i < min(rs.count, 8U); i++) | 139 | for (i = 0; i < min(rs.count, 8U); i++) |
132 | if ((1 << i) & rs.mask) | 140 | if ((1 << i) & rs.mask) |
133 | rs.values[i] = ioread32(dev->iaddr + i); | 141 | rs.values[i] = ioread32(dev->iaddr + i); |
142 | spin_unlock(&dev->ioctl_lock); | ||
134 | 143 | ||
135 | if (copy_to_user(argp, &rs, sizeof(rs))) | 144 | if (copy_to_user(argp, &rs, sizeof(rs))) |
136 | return -EFAULT; | 145 | return -EFAULT; |
@@ -199,7 +208,7 @@ static unsigned int phantom_poll(struct file *file, poll_table *wait) | |||
199 | static struct file_operations phantom_file_ops = { | 208 | static struct file_operations phantom_file_ops = { |
200 | .open = phantom_open, | 209 | .open = phantom_open, |
201 | .release = phantom_release, | 210 | .release = phantom_release, |
202 | .ioctl = phantom_ioctl, | 211 | .unlocked_ioctl = phantom_ioctl, |
203 | .poll = phantom_poll, | 212 | .poll = phantom_poll, |
204 | }; | 213 | }; |
205 | 214 | ||
@@ -282,6 +291,7 @@ static int __devinit phantom_probe(struct pci_dev *pdev, | |||
282 | } | 291 | } |
283 | 292 | ||
284 | mutex_init(&pht->open_lock); | 293 | mutex_init(&pht->open_lock); |
294 | spin_lock_init(&pht->ioctl_lock); | ||
285 | init_waitqueue_head(&pht->wait); | 295 | init_waitqueue_head(&pht->wait); |
286 | cdev_init(&pht->cdev, &phantom_file_ops); | 296 | cdev_init(&pht->cdev, &phantom_file_ops); |
287 | pht->cdev.owner = THIS_MODULE; | 297 | pht->cdev.owner = THIS_MODULE; |