aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/proc.c')
-rw-r--r--drivers/pci/proc.c41
1 files changed, 27 insertions, 14 deletions
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index f82710a8694d..098360d7ff81 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -202,6 +202,8 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
202 202
203#ifdef HAVE_PCI_MMAP 203#ifdef HAVE_PCI_MMAP
204 case PCIIOC_MMAP_IS_IO: 204 case PCIIOC_MMAP_IS_IO:
205 if (!arch_can_pci_mmap_io())
206 return -EINVAL;
205 fpriv->mmap_state = pci_mmap_io; 207 fpriv->mmap_state = pci_mmap_io;
206 break; 208 break;
207 209
@@ -210,14 +212,15 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
210 break; 212 break;
211 213
212 case PCIIOC_WRITE_COMBINE: 214 case PCIIOC_WRITE_COMBINE:
213 if (arg) 215 if (arch_can_pci_mmap_wc()) {
214 fpriv->write_combine = 1; 216 if (arg)
215 else 217 fpriv->write_combine = 1;
216 fpriv->write_combine = 0; 218 else
217 break; 219 fpriv->write_combine = 0;
218 220 break;
221 }
222 /* If arch decided it can't, fall through... */
219#endif /* HAVE_PCI_MMAP */ 223#endif /* HAVE_PCI_MMAP */
220
221 default: 224 default:
222 ret = -EINVAL; 225 ret = -EINVAL;
223 break; 226 break;
@@ -231,25 +234,35 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
231{ 234{
232 struct pci_dev *dev = PDE_DATA(file_inode(file)); 235 struct pci_dev *dev = PDE_DATA(file_inode(file));
233 struct pci_filp_private *fpriv = file->private_data; 236 struct pci_filp_private *fpriv = file->private_data;
234 int i, ret, write_combine; 237 int i, ret, write_combine = 0, res_bit = IORESOURCE_MEM;
235 238
236 if (!capable(CAP_SYS_RAWIO)) 239 if (!capable(CAP_SYS_RAWIO))
237 return -EPERM; 240 return -EPERM;
238 241
242 if (fpriv->mmap_state == pci_mmap_io) {
243 if (!arch_can_pci_mmap_io())
244 return -EINVAL;
245 res_bit = IORESOURCE_IO;
246 }
247
239 /* Make sure the caller is mapping a real resource for this device */ 248 /* Make sure the caller is mapping a real resource for this device */
240 for (i = 0; i < PCI_ROM_RESOURCE; i++) { 249 for (i = 0; i < PCI_ROM_RESOURCE; i++) {
241 if (pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS)) 250 if (dev->resource[i].flags & res_bit &&
251 pci_mmap_fits(dev, i, vma, PCI_MMAP_PROCFS))
242 break; 252 break;
243 } 253 }
244 254
245 if (i >= PCI_ROM_RESOURCE) 255 if (i >= PCI_ROM_RESOURCE)
246 return -ENODEV; 256 return -ENODEV;
247 257
248 if (fpriv->mmap_state == pci_mmap_mem) 258 if (fpriv->mmap_state == pci_mmap_mem &&
249 write_combine = fpriv->write_combine; 259 fpriv->write_combine) {
250 else 260 if (dev->resource[i].flags & IORESOURCE_PREFETCH)
251 write_combine = 0; 261 write_combine = 1;
252 ret = pci_mmap_page_range(dev, vma, 262 else
263 return -EINVAL;
264 }
265 ret = pci_mmap_page_range(dev, i, vma,
253 fpriv->mmap_state, write_combine); 266 fpriv->mmap_state, write_combine);
254 if (ret < 0) 267 if (ret < 0)
255 return ret; 268 return ret;