aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan Abbott <abbotti@mev.co.uk>2014-07-31 10:57:27 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-08-01 18:00:18 -0400
commit27fc26f99e63bcbe42176f08eaf590bff81a2e1c (patch)
tree8b76c9b1809117598cc9795bcff9110333312842
parent96d4b0d5636b1810042eabedf766f35b548f1672 (diff)
staging: comedi: ii_pci20kc: request and ioremap memory
The "ii_pci20kc" module is a comedi driver for Intelligent Instruments PCI-20001C carrier board and modules. Despite the name, this is actually an ISA board and uses 1K of ISA memory space (below 1M) for the main board plus up to three modules. The address is set by hardware jumpers. When the board is attached to Comedi via the `COMEDI_DEVCONFIG` ioctl and the driver's legacy "attach" handler, the base address is passed in. The driver currently uses that address as-is, which is a bad idea. It doesn't even reserve the memory region. Fix that by sanity checking the passed in address, reserving the memory region and ioremapping it. Replace the current "detach" handler `comedi_legacy_detach()` with a new handler `ii20k_detach()` which unmaps the memory and releases the region. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/staging/comedi/drivers/ii_pci20kc.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/drivers/staging/comedi/drivers/ii_pci20kc.c b/drivers/staging/comedi/drivers/ii_pci20kc.c
index b1f44b31162b..687db433e131 100644
--- a/drivers/staging/comedi/drivers/ii_pci20kc.c
+++ b/drivers/staging/comedi/drivers/ii_pci20kc.c
@@ -33,6 +33,7 @@
33/* 33/*
34 * Register I/O map 34 * Register I/O map
35 */ 35 */
36#define II20K_SIZE 0x400
36#define II20K_MOD_OFFSET 0x100 37#define II20K_MOD_OFFSET 0x100
37#define II20K_ID_REG 0x00 38#define II20K_ID_REG 0x00
38#define II20K_ID_MOD1_EMPTY (1 << 7) 39#define II20K_ID_MOD1_EMPTY (1 << 7)
@@ -439,12 +440,29 @@ static int ii20k_attach(struct comedi_device *dev,
439 struct comedi_devconfig *it) 440 struct comedi_devconfig *it)
440{ 441{
441 struct comedi_subdevice *s; 442 struct comedi_subdevice *s;
443 unsigned int membase;
442 unsigned char id; 444 unsigned char id;
443 bool has_dio; 445 bool has_dio;
444 int ret; 446 int ret;
445 447
446 /* FIXME: this doesn't seem right, should 'mmio' be ioremap'ed? */ 448 membase = it->options[0];
447 dev->mmio = (void __iomem *)(unsigned long)it->options[0]; 449 if (!membase || (membase & ~(0x100000 - II20K_SIZE))) {
450 dev_warn(dev->class_dev,
451 "%s: invalid memory address specified\n",
452 dev->board_name);
453 return -EINVAL;
454 }
455
456 if (!request_mem_region(membase, II20K_SIZE, dev->board_name)) {
457 dev_warn(dev->class_dev, "%s: I/O mem conflict (%#x,%u)\n",
458 dev->board_name, membase, II20K_SIZE);
459 return -EIO;
460 }
461 dev->iobase = membase; /* actually, a memory address */
462
463 dev->mmio = ioremap(membase, II20K_SIZE);
464 if (!dev->mmio)
465 return -ENOMEM;
448 466
449 id = readb(dev->mmio + II20K_ID_REG); 467 id = readb(dev->mmio + II20K_ID_REG);
450 switch (id & II20K_ID_MASK) { 468 switch (id & II20K_ID_MASK) {
@@ -509,11 +527,19 @@ static int ii20k_attach(struct comedi_device *dev,
509 return 0; 527 return 0;
510} 528}
511 529
530static void ii20k_detach(struct comedi_device *dev)
531{
532 if (dev->mmio)
533 iounmap(dev->mmio);
534 if (dev->iobase) /* actually, a memory address */
535 release_mem_region(dev->iobase, II20K_SIZE);
536}
537
512static struct comedi_driver ii20k_driver = { 538static struct comedi_driver ii20k_driver = {
513 .driver_name = "ii_pci20kc", 539 .driver_name = "ii_pci20kc",
514 .module = THIS_MODULE, 540 .module = THIS_MODULE,
515 .attach = ii20k_attach, 541 .attach = ii20k_attach,
516 .detach = comedi_legacy_detach, 542 .detach = ii20k_detach,
517}; 543};
518module_comedi_driver(ii20k_driver); 544module_comedi_driver(ii20k_driver);
519 545