diff options
Diffstat (limited to 'drivers/staging/ipack')
-rw-r--r-- | drivers/staging/ipack/TODO | 11 | ||||
-rw-r--r-- | drivers/staging/ipack/bridges/tpci200.c | 473 | ||||
-rw-r--r-- | drivers/staging/ipack/bridges/tpci200.h | 5 | ||||
-rw-r--r-- | drivers/staging/ipack/devices/ipoctal.c | 79 | ||||
-rw-r--r-- | drivers/staging/ipack/devices/ipoctal.h | 39 | ||||
-rw-r--r-- | drivers/staging/ipack/ipack.c | 46 |
6 files changed, 163 insertions, 490 deletions
diff --git a/drivers/staging/ipack/TODO b/drivers/staging/ipack/TODO index 3a45a53afd88..b21d33ab144a 100644 --- a/drivers/staging/ipack/TODO +++ b/drivers/staging/ipack/TODO @@ -3,7 +3,7 @@ Introduction ============ -These drivers add support for IndustryPack devices: carrier and mezzanine +These drivers add support for IndustryPack devices: carrier and IP module boards. The ipack driver is just an abstraction of the bus providing the common @@ -15,10 +15,6 @@ TODO TPCI-200 -------- -* It receives the name of the mezzanine plugged in each slot by SYSFS. - No autodetection supported yet, because the mezzanine driver could not be - loaded at the time that the tpci200 driver loads. - * It has a linked list with the tpci200 devices it is managing. Get rid of it and use driver_for_each_device() instead. @@ -35,7 +31,7 @@ Ipack ----- * The structures and API exported can be improved a lot. For example, the - way to unregistering mezzanine devices, doing the mezzanine driver a call to + way to unregistering IP module devices, doing the IP module driver a call to remove_device() to notify the carrier driver, or the opposite with the call to the ipack_driver_ops' remove() function could be improved. @@ -43,4 +39,5 @@ Ipack Contact ======= -Contact: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
\ No newline at end of file +Contact: Samuel Iglesias Gonsalvez <siglesias@igalia.com> +Mailing List: industrypack-devel@lists.sourceforge.net diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index ad2870750235..2b83fa8e550a 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -11,8 +11,6 @@ * Software Foundation; version 2 of the License. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/module.h> #include "tpci200.h" @@ -36,10 +34,8 @@ static struct tpci200_board *check_slot(struct ipack_device *dev) struct tpci200_board *tpci200; int found = 0; - if (dev == NULL) { - pr_info("Slot doesn't exist.\n"); + if (dev == NULL) return NULL; - } list_for_each_entry(tpci200, &tpci200_list, list) { if (tpci200->number == dev->bus_nr) { @@ -49,20 +45,14 @@ static struct tpci200_board *check_slot(struct ipack_device *dev) } if (!found) { - pr_err("Carrier not found\n"); + dev_err(&dev->dev, "Carrier not found\n"); return NULL; } if (dev->slot >= TPCI200_NB_SLOT) { - pr_info("Slot [%d:%d] doesn't exist! Last tpci200 slot is %d.\n", - dev->bus_nr, dev->slot, TPCI200_NB_SLOT-1); - return NULL; - } - - BUG_ON(tpci200->slots == NULL); - if (tpci200->slots[dev->slot].dev == NULL) { - pr_info("Slot [%d:%d] is not registered !\n", dev->bus_nr, - dev->slot); + dev_info(&dev->dev, + "Slot [%d:%d] doesn't exist! Last tpci200 slot is %d.\n", + dev->bus_nr, dev->slot, TPCI200_NB_SLOT-1); return NULL; } @@ -123,14 +113,15 @@ static struct ipack_addr_space *get_slot_address_space(struct ipack_device *dev, addr = &dev->mem_space; break; default: - pr_err("Slot [%d:%d] space number %d doesn't exist !\n", - dev->bus_nr, dev->slot, space); + dev_err(&dev->dev, + "Slot [%d:%d] space number %d doesn't exist !\n", + dev->bus_nr, dev->slot, space); return NULL; break; } if ((addr->size == 0) || (addr->address == NULL)) { - pr_err("Error, slot space not mapped !\n"); + dev_err(&dev->dev, "Error, slot space not mapped !\n"); return NULL; } @@ -152,7 +143,7 @@ static int tpci200_read8(struct ipack_device *dev, int space, return -EINVAL; if (offset >= addr->size) { - pr_err("Error, slot space offset error !\n"); + dev_err(&dev->dev, "Error, slot space offset error !\n"); return -EFAULT; } @@ -176,7 +167,7 @@ static int tpci200_read16(struct ipack_device *dev, int space, return -EINVAL; if ((offset+2) >= addr->size) { - pr_err("Error, slot space offset error !\n"); + dev_err(&dev->dev, "Error, slot space offset error !\n"); return -EFAULT; } *value = __tpci200_read16(addr->address, offset); @@ -199,7 +190,7 @@ static int tpci200_read32(struct ipack_device *dev, int space, return -EINVAL; if ((offset+4) >= addr->size) { - pr_err("Error, slot space offset error !\n"); + dev_err(&dev->dev, "Error, slot space offset error !\n"); return -EFAULT; } @@ -223,7 +214,7 @@ static int tpci200_write8(struct ipack_device *dev, int space, return -EINVAL; if (offset >= addr->size) { - pr_err("Error, slot space offset error !\n"); + dev_err(&dev->dev, "Error, slot space offset error !\n"); return -EFAULT; } @@ -247,7 +238,7 @@ static int tpci200_write16(struct ipack_device *dev, int space, return -EINVAL; if ((offset+2) >= addr->size) { - pr_err("Error, slot space offset error !\n"); + dev_err(&dev->dev, "Error, slot space offset error !\n"); return -EFAULT; } @@ -271,7 +262,7 @@ static int tpci200_write32(struct ipack_device *dev, int space, return -EINVAL; if ((offset+4) >= addr->size) { - pr_err("Error, slot space offset error !\n"); + dev_err(&dev->dev, "Error, slot space offset error !\n"); return -EFAULT; } @@ -297,8 +288,6 @@ static void tpci200_unregister(struct tpci200_board *tpci200) pci_disable_device(tpci200->info->pdev); pci_dev_put(tpci200->info->pdev); - kfree(tpci200->info); - for (i = 0; i < TPCI200_NB_SLOT; i++) { tpci200->slots[i].io_phys.address = NULL; tpci200->slots[i].io_phys.size = 0; @@ -313,13 +302,10 @@ static irqreturn_t tpci200_interrupt(int irq, void *dev_id) { struct tpci200_board *tpci200 = (struct tpci200_board *) dev_id; int i; - unsigned long flags; unsigned short status_reg, reg_value; unsigned short unhandled_ints = 0; irqreturn_t ret = IRQ_NONE; - spin_lock_irqsave(&tpci200->info->access_lock, flags); - /* Read status register */ status_reg = readw(tpci200->info->interface_regs + TPCI200_STATUS_REG); @@ -347,8 +333,9 @@ static irqreturn_t tpci200_interrupt(int irq, void *dev_id) if (unhandled_ints) { for (i = 0; i < TPCI200_NB_SLOT; i++) { if (unhandled_ints & ((TPCI200_INT0_EN | TPCI200_INT1_EN) << (2*i))) { - pr_info("No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n", - tpci200->number, i); + dev_info(&tpci200->slots[i].dev->dev, + "No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n", + tpci200->number, i); reg_value = readw( tpci200->info->interface_regs + control_reg[i]); @@ -361,211 +348,12 @@ static irqreturn_t tpci200_interrupt(int irq, void *dev_id) } } - spin_unlock_irqrestore(&tpci200->info->access_lock, flags); return ret; } -#ifdef CONFIG_SYSFS - -static struct ipack_device *tpci200_slot_register(unsigned int tpci200_number, - unsigned int slot_position) -{ - int found = 0; - struct ipack_device *dev; - struct tpci200_board *tpci200; - - list_for_each_entry(tpci200, &tpci200_list, list) { - if (tpci200->number == tpci200_number) { - found = 1; - break; - } - } - - if (!found) { - pr_err("carrier board not found for the device\n"); - return NULL; - } - - if (slot_position >= TPCI200_NB_SLOT) { - pr_info("Slot [%d:%d] doesn't exist!\n", tpci200_number, - slot_position); - return NULL; - } - - if (mutex_lock_interruptible(&tpci200->mutex)) - return NULL; - - if (tpci200->slots[slot_position].dev != NULL) { - pr_err("Slot [%d:%d] already installed !\n", tpci200_number, - slot_position); - goto err_unlock; - } - - /* - * Give the same IRQ number as the slot number. - * The TPCI200 has assigned his own two IRQ by PCI bus driver - */ - dev = ipack_device_register(tpci200->info->ipack_bus, - slot_position, slot_position); - if (dev == NULL) { - pr_info("Slot [%d:%d] Unable to register an ipack device\n", - tpci200_number, slot_position); - goto err_unlock; - } - - tpci200->slots[slot_position].dev = dev; - mutex_unlock(&tpci200->mutex); - return dev; - -err_unlock: - mutex_unlock(&tpci200->mutex); - return NULL; -} - -static ssize_t tpci200_store_board(struct device *pdev, const char *buf, - size_t count, int slot) -{ - struct tpci200_board *card = dev_get_drvdata(pdev); - struct ipack_device *dev = card->slots[slot].dev; - - if (dev != NULL) - return -EBUSY; - - dev = tpci200_slot_register(card->number, slot); - if (dev == NULL) - return -ENODEV; - - return count; -} - -static ssize_t tpci200_show_board(struct device *pdev, char *buf, int slot) -{ - struct tpci200_board *card = dev_get_drvdata(pdev); - struct ipack_device *dev = card->slots[slot].dev; - - if (dev != NULL) - return snprintf(buf, PAGE_SIZE, "%s\n", dev_name(&dev->dev)); - else - return snprintf(buf, PAGE_SIZE, "none\n"); -} - -static ssize_t tpci200_show_description(struct device *pdev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, - "TEWS tpci200 carrier PCI for Industry-pack mezzanines.\n"); -} - -static ssize_t tpci200_show_board_slot0(struct device *pdev, - struct device_attribute *attr, - char *buf) -{ - return tpci200_show_board(pdev, buf, 0); -} - -static ssize_t tpci200_store_board_slot0(struct device *pdev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return tpci200_store_board(pdev, buf, count, 0); -} - -static ssize_t tpci200_show_board_slot1(struct device *pdev, - struct device_attribute *attr, - char *buf) -{ - return tpci200_show_board(pdev, buf, 1); -} - -static ssize_t tpci200_store_board_slot1(struct device *pdev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return tpci200_store_board(pdev, buf, count, 1); -} - -static ssize_t tpci200_show_board_slot2(struct device *pdev, - struct device_attribute *attr, - char *buf) -{ - return tpci200_show_board(pdev, buf, 2); -} - -static ssize_t tpci200_store_board_slot2(struct device *pdev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return tpci200_store_board(pdev, buf, count, 2); -} - - -static ssize_t tpci200_show_board_slot3(struct device *pdev, - struct device_attribute *attr, - char *buf) -{ - return tpci200_show_board(pdev, buf, 3); -} - -static ssize_t tpci200_store_board_slot3(struct device *pdev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - return tpci200_store_board(pdev, buf, count, 3); -} - -/* Declaration of the device attributes for the TPCI200 */ -static DEVICE_ATTR(description, S_IRUGO, - tpci200_show_description, NULL); -static DEVICE_ATTR(board_slot0, S_IRUGO | S_IWUSR, - tpci200_show_board_slot0, tpci200_store_board_slot0); -static DEVICE_ATTR(board_slot1, S_IRUGO | S_IWUSR, - tpci200_show_board_slot1, tpci200_store_board_slot1); -static DEVICE_ATTR(board_slot2, S_IRUGO | S_IWUSR, - tpci200_show_board_slot2, tpci200_store_board_slot2); -static DEVICE_ATTR(board_slot3, S_IRUGO | S_IWUSR, - tpci200_show_board_slot3, tpci200_store_board_slot3); - -static struct attribute *tpci200_attrs[] = { - &dev_attr_description.attr, - &dev_attr_board_slot0.attr, - &dev_attr_board_slot1.attr, - &dev_attr_board_slot2.attr, - &dev_attr_board_slot3.attr, - NULL, -}; - -static struct attribute_group tpci200_attr_group = { - .attrs = tpci200_attrs, -}; - -static int tpci200_create_sysfs_files(struct tpci200_board *card) -{ - return sysfs_create_group(&card->info->pdev->dev.kobj, - &tpci200_attr_group); -} - -static void tpci200_remove_sysfs_files(struct tpci200_board *card) -{ - sysfs_remove_group(&card->info->pdev->dev.kobj, &tpci200_attr_group); -} - -#else - -static int tpci200_create_sysfs_files(struct tpci200_board *card) -{ - return 0; -} - -static void tpci200_remove_sysfs_files(struct tpci200_board *card) -{ -} - -#endif /* CONFIG_SYSFS */ - static int tpci200_register(struct tpci200_board *tpci200) { - int i; + int i; int res; unsigned long ioidint_base; unsigned long mem_base; @@ -574,20 +362,15 @@ static int tpci200_register(struct tpci200_board *tpci200) if (pci_enable_device(tpci200->info->pdev) < 0) return -ENODEV; - if (tpci200_create_sysfs_files(tpci200) < 0) { - pr_err("failed creating sysfs files\n"); - res = -EFAULT; - goto out_disable_pci; - } - /* Request IP interface register (Bar 2) */ res = pci_request_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR, "Carrier IP interface registers"); if (res) { - pr_err("(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !", - tpci200->info->pdev->bus->number, - tpci200->info->pdev->devfn); - goto out_remove_sysfs; + dev_err(&tpci200->info->pdev->dev, + "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !", + tpci200->info->pdev->bus->number, + tpci200->info->pdev->devfn); + goto out_disable_pci; } /* Request IO ID INT space (Bar 3) */ @@ -595,9 +378,10 @@ static int tpci200_register(struct tpci200_board *tpci200) TPCI200_IO_ID_INT_SPACES_BAR, "Carrier IO ID INT space"); if (res) { - pr_err("(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !", - tpci200->info->pdev->bus->number, - tpci200->info->pdev->devfn); + dev_err(&tpci200->info->pdev->dev, + "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !", + tpci200->info->pdev->bus->number, + tpci200->info->pdev->devfn); goto out_release_ip_space; } @@ -605,9 +389,10 @@ static int tpci200_register(struct tpci200_board *tpci200) res = pci_request_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR, "Carrier MEM space"); if (res) { - pr_err("(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!", - tpci200->info->pdev->bus->number, - tpci200->info->pdev->devfn); + dev_err(&tpci200->info->pdev->dev, + "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!", + tpci200->info->pdev->bus->number, + tpci200->info->pdev->devfn); goto out_release_ioid_int_space; } @@ -625,7 +410,6 @@ static int tpci200_register(struct tpci200_board *tpci200) TPCI200_MEM8_SPACE_BAR), TPCI200_MEM8_SIZE); - spin_lock_init(&tpci200->info->access_lock); ioidint_base = pci_resource_start(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); mem_base = pci_resource_start(tpci200->info->pdev, @@ -665,11 +449,11 @@ static int tpci200_register(struct tpci200_board *tpci200) tpci200_interrupt, IRQF_SHARED, KBUILD_MODNAME, (void *) tpci200); if (res) { - pr_err("(bn 0x%X, sn 0x%X) unable to register IRQ !", - tpci200->info->pdev->bus->number, - tpci200->info->pdev->devfn); - tpci200_unregister(tpci200); - goto out_err; + dev_err(&tpci200->info->pdev->dev, + "(bn 0x%X, sn 0x%X) unable to register IRQ !", + tpci200->info->pdev->bus->number, + tpci200->info->pdev->devfn); + goto out_release_ioid_int_space; } return 0; @@ -678,11 +462,8 @@ out_release_ioid_int_space: pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR); out_release_ip_space: pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR); -out_remove_sysfs: - tpci200_remove_sysfs_files(tpci200); out_disable_pci: pci_disable_device(tpci200->info->pdev); -out_err: return res; } @@ -726,24 +507,19 @@ static void __tpci200_free_irq(struct tpci200_board *tpci200, static int tpci200_free_irq(struct ipack_device *dev) { - int res; struct slot_irq *slot_irq; struct tpci200_board *tpci200; tpci200 = check_slot(dev); - if (tpci200 == NULL) { - res = -EINVAL; - goto out; - } + if (tpci200 == NULL) + return -EINVAL; - if (mutex_lock_interruptible(&tpci200->mutex)) { - res = -ERESTARTSYS; - goto out; - } + if (mutex_lock_interruptible(&tpci200->mutex)) + return -ERESTARTSYS; if (tpci200->slots[dev->slot].irq == NULL) { - res = -EINVAL; - goto out_unlock; + mutex_unlock(&tpci200->mutex); + return -EINVAL; } __tpci200_free_irq(tpci200, dev); @@ -751,60 +527,56 @@ static int tpci200_free_irq(struct ipack_device *dev) tpci200->slots[dev->slot].irq = NULL; kfree(slot_irq); -out_unlock: mutex_unlock(&tpci200->mutex); -out: - return res; + return 0; } static int tpci200_slot_unmap_space(struct ipack_device *dev, int space) { - int res; struct ipack_addr_space *virt_addr_space; struct tpci200_board *tpci200; tpci200 = check_slot(dev); - if (tpci200 == NULL) { - res = -EINVAL; - goto out; - } + if (tpci200 == NULL) + return -EINVAL; - if (mutex_lock_interruptible(&tpci200->mutex)) { - res = -ERESTARTSYS; - goto out; - } + if (mutex_lock_interruptible(&tpci200->mutex)) + return -ERESTARTSYS; switch (space) { case IPACK_IO_SPACE: if (dev->io_space.address == NULL) { - pr_info("Slot [%d:%d] IO space not mapped !\n", - dev->bus_nr, dev->slot); + dev_info(&dev->dev, + "Slot [%d:%d] IO space not mapped !\n", + dev->bus_nr, dev->slot); goto out_unlock; } virt_addr_space = &dev->io_space; break; case IPACK_ID_SPACE: if (dev->id_space.address == NULL) { - pr_info("Slot [%d:%d] ID space not mapped !\n", - dev->bus_nr, dev->slot); + dev_info(&dev->dev, + "Slot [%d:%d] ID space not mapped !\n", + dev->bus_nr, dev->slot); goto out_unlock; } virt_addr_space = &dev->id_space; break; case IPACK_MEM_SPACE: if (dev->mem_space.address == NULL) { - pr_info("Slot [%d:%d] MEM space not mapped !\n", - dev->bus_nr, dev->slot); - goto out_unlock; + dev_info(&dev->dev, + "Slot [%d:%d] MEM space not mapped !\n", + dev->bus_nr, dev->slot); + goto out_unlock; } virt_addr_space = &dev->mem_space; break; default: - pr_err("Slot [%d:%d] space number %d doesn't exist !\n", - dev->bus_nr, dev->slot, space); - res = -EINVAL; - goto out_unlock; - break; + dev_err(&dev->dev, + "Slot [%d:%d] space number %d doesn't exist !\n", + dev->bus_nr, dev->slot, space); + mutex_unlock(&tpci200->mutex); + return -EINVAL; } iounmap(virt_addr_space->address); @@ -813,8 +585,7 @@ static int tpci200_slot_unmap_space(struct ipack_device *dev, int space) virt_addr_space->size = 0; out_unlock: mutex_unlock(&tpci200->mutex); -out: - return res; + return 0; } static int tpci200_slot_unregister(struct ipack_device *dev) @@ -843,28 +614,25 @@ static int tpci200_slot_unregister(struct ipack_device *dev) static int tpci200_slot_map_space(struct ipack_device *dev, unsigned int memory_size, int space) { - int res; + int res = 0; unsigned int size_to_map; void __iomem *phys_address; struct ipack_addr_space *virt_addr_space; struct tpci200_board *tpci200; tpci200 = check_slot(dev); - if (tpci200 == NULL) { - res = -EINVAL; - goto out; - } + if (tpci200 == NULL) + return -EINVAL; - if (mutex_lock_interruptible(&tpci200->mutex)) { - res = -ERESTARTSYS; - goto out; - } + if (mutex_lock_interruptible(&tpci200->mutex)) + return -ERESTARTSYS; switch (space) { case IPACK_IO_SPACE: if (dev->io_space.address != NULL) { - pr_err("Slot [%d:%d] IO space already mapped !\n", - tpci200->number, dev->slot); + dev_err(&dev->dev, + "Slot [%d:%d] IO space already mapped !\n", + tpci200->number, dev->slot); res = -EINVAL; goto out_unlock; } @@ -875,8 +643,9 @@ static int tpci200_slot_map_space(struct ipack_device *dev, break; case IPACK_ID_SPACE: if (dev->id_space.address != NULL) { - pr_err("Slot [%d:%d] ID space already mapped !\n", - tpci200->number, dev->slot); + dev_err(&dev->dev, + "Slot [%d:%d] ID space already mapped !\n", + tpci200->number, dev->slot); res = -EINVAL; goto out_unlock; } @@ -887,17 +656,19 @@ static int tpci200_slot_map_space(struct ipack_device *dev, break; case IPACK_MEM_SPACE: if (dev->mem_space.address != NULL) { - pr_err("Slot [%d:%d] MEM space already mapped !\n", - tpci200->number, dev->slot); + dev_err(&dev->dev, + "Slot [%d:%d] MEM space already mapped !\n", + tpci200->number, dev->slot); res = -EINVAL; goto out_unlock; } virt_addr_space = &dev->mem_space; if (memory_size > tpci200->slots[dev->slot].mem_phys.size) { - pr_err("Slot [%d:%d] request is 0x%X memory, only 0x%X available !\n", - dev->bus_nr, dev->slot, memory_size, - tpci200->slots[dev->slot].mem_phys.size); + dev_err(&dev->dev, + "Slot [%d:%d] request is 0x%X memory, only 0x%X available !\n", + dev->bus_nr, dev->slot, memory_size, + tpci200->slots[dev->slot].mem_phys.size); res = -EINVAL; goto out_unlock; } @@ -906,11 +677,10 @@ static int tpci200_slot_map_space(struct ipack_device *dev, size_to_map = memory_size; break; default: - pr_err("Slot [%d:%d] space %d doesn't exist !\n", - tpci200->number, dev->slot, space); + dev_err(&dev->dev, "Slot [%d:%d] space %d doesn't exist !\n", + tpci200->number, dev->slot, space); res = -EINVAL; goto out_unlock; - break; } virt_addr_space->size = size_to_map; @@ -919,7 +689,6 @@ static int tpci200_slot_map_space(struct ipack_device *dev, out_unlock: mutex_unlock(&tpci200->mutex); -out: return res; } @@ -931,27 +700,25 @@ static int tpci200_request_irq(struct ipack_device *dev, int vector, struct tpci200_board *tpci200; tpci200 = check_slot(dev); - if (tpci200 == NULL) { - res = -EINVAL; - goto out; - } + if (tpci200 == NULL) + return -EINVAL; - if (mutex_lock_interruptible(&tpci200->mutex)) { - res = -ERESTARTSYS; - goto out; - } + if (mutex_lock_interruptible(&tpci200->mutex)) + return -ERESTARTSYS; if (tpci200->slots[dev->slot].irq != NULL) { - pr_err("Slot [%d:%d] IRQ already registered !\n", dev->bus_nr, - dev->slot); + dev_err(&dev->dev, + "Slot [%d:%d] IRQ already registered !\n", dev->bus_nr, + dev->slot); res = -EINVAL; goto out_unlock; } slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL); if (slot_irq == NULL) { - pr_err("Slot [%d:%d] unable to allocate memory for IRQ !\n", - dev->bus_nr, dev->slot); + dev_err(&dev->dev, + "Slot [%d:%d] unable to allocate memory for IRQ !\n", + dev->bus_nr, dev->slot); res = -ENOMEM; goto out_unlock; } @@ -965,32 +732,21 @@ static int tpci200_request_irq(struct ipack_device *dev, int vector, slot_irq->vector = vector; slot_irq->handler = handler; slot_irq->arg = arg; - slot_irq->name = dev_name(&dev->dev); tpci200->slots[dev->slot].irq = slot_irq; res = __tpci200_request_irq(tpci200, dev); out_unlock: mutex_unlock(&tpci200->mutex); -out: return res; } -static void tpci200_slot_remove(struct tpci200_slot *slot) -{ - if ((slot->dev == NULL) || - (slot->dev->driver->ops->remove == NULL)) - return; - - slot->dev->driver->ops->remove(slot->dev); -} - static void tpci200_uninstall(struct tpci200_board *tpci200) { int i; for (i = 0; i < TPCI200_NB_SLOT; i++) - tpci200_slot_remove(&tpci200->slots[i]); + tpci200_slot_unregister(tpci200->slots[i].dev); tpci200_unregister(tpci200); kfree(tpci200->slots); @@ -1016,29 +772,24 @@ static int tpci200_install(struct tpci200_board *tpci200) tpci200->slots = kzalloc( TPCI200_NB_SLOT * sizeof(struct tpci200_slot), GFP_KERNEL); - if (tpci200->slots == NULL) { - res = -ENOMEM; - goto out_err; - } + if (tpci200->slots == NULL) + return -ENOMEM; res = tpci200_register(tpci200); - if (res) - goto out_free; + if (res) { + kfree(tpci200->slots); + tpci200->slots = NULL; + return res; + } mutex_init(&tpci200->mutex); return 0; - -out_free: - kfree(tpci200->slots); - tpci200->slots = NULL; -out_err: - return res; } static int tpci200_pciprobe(struct pci_dev *pdev, const struct pci_device_id *id) { - int ret; + int ret, i; struct tpci200_board *tpci200; tpci200 = kzalloc(sizeof(struct tpci200_board), GFP_KERNEL); @@ -1058,7 +809,7 @@ static int tpci200_pciprobe(struct pci_dev *pdev, /* register the device and initialize it */ ret = tpci200_install(tpci200); if (ret) { - pr_err("Error during tpci200 install !\n"); + dev_err(&pdev->dev, "Error during tpci200 install !\n"); kfree(tpci200->info); kfree(tpci200); return -ENODEV; @@ -1069,7 +820,8 @@ static int tpci200_pciprobe(struct pci_dev *pdev, TPCI200_NB_SLOT, &tpci200_bus_ops); if (!tpci200->info->ipack_bus) { - pr_err("error registering the carrier on ipack driver\n"); + dev_err(&pdev->dev, + "error registering the carrier on ipack driver\n"); tpci200_uninstall(tpci200); kfree(tpci200->info); kfree(tpci200); @@ -1081,13 +833,20 @@ static int tpci200_pciprobe(struct pci_dev *pdev, dev_set_drvdata(&pdev->dev, tpci200); /* add the registered device in an internal linked list */ list_add_tail(&tpci200->list, &tpci200_list); + + /* + * Give the same IRQ number as the slot number. + * The TPCI200 has assigned his own two IRQ by PCI bus driver + */ + for (i = 0; i < TPCI200_NB_SLOT; i++) + tpci200->slots[i].dev = + ipack_device_register(tpci200->info->ipack_bus, i, i); return ret; } static void __tpci200_pci_remove(struct tpci200_board *tpci200) { tpci200_uninstall(tpci200); - tpci200_remove_sysfs_files(tpci200); list_del(&tpci200->list); ipack_bus_unregister(tpci200->info->ipack_bus); kfree(tpci200->info); @@ -1107,12 +866,14 @@ static void __devexit tpci200_pci_remove(struct pci_dev *dev) } } -static struct pci_device_id tpci200_idtable[2] = { +static DEFINE_PCI_DEVICE_TABLE(tpci200_idtable) = { { TPCI200_VENDOR_ID, TPCI200_DEVICE_ID, TPCI200_SUBVENDOR_ID, TPCI200_SUBDEVICE_ID }, { 0, }, }; +MODULE_DEVICE_TABLE(pci, tpci200_idtable); + static struct pci_driver tpci200_pci_drv = { .name = "tpci200", .id_table = tpci200_idtable, diff --git a/drivers/staging/ipack/bridges/tpci200.h b/drivers/staging/ipack/bridges/tpci200.h index 0b547eedddc2..d04510a89be4 100644 --- a/drivers/staging/ipack/bridges/tpci200.h +++ b/drivers/staging/ipack/bridges/tpci200.h @@ -14,7 +14,6 @@ #ifndef _TPCI200_H_ #define _TPCI200_H_ -#include <linux/version.h> #include <linux/limits.h> #include <linux/pci.h> #include <linux/spinlock.h> @@ -106,14 +105,12 @@ * @vector Vector number * @handler Handler called when IRQ arrives * @arg Handler argument - * @name IRQ name * */ struct slot_irq { int vector; int (*handler)(void *); void *arg; - const char *name; }; /** @@ -139,7 +136,6 @@ struct tpci200_slot { * @interface_regs Pointer to IP interface space (Bar 2) * @ioidint_space Pointer to IP ID, IO and INT space (Bar 3) * @mem8_space Pointer to MEM space (Bar 4) - * @access_lock Mutex lock for simultaneous access * */ struct tpci200_infos { @@ -148,7 +144,6 @@ struct tpci200_infos { void __iomem *interface_regs; void __iomem *ioidint_space; void __iomem *mem8_space; - spinlock_t access_lock; struct ipack_bus_device *ipack_bus; }; struct tpci200_board { diff --git a/drivers/staging/ipack/devices/ipoctal.c b/drivers/staging/ipack/devices/ipoctal.c index 29f6fa841d23..fd0e30132ca2 100644 --- a/drivers/staging/ipack/devices/ipoctal.c +++ b/drivers/staging/ipack/devices/ipoctal.c @@ -11,20 +11,14 @@ * Software Foundation; version 2 of the License. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/device.h> #include <linux/module.h> -#include <linux/moduleparam.h> #include <linux/interrupt.h> -#include <linux/fs.h> -#include <linux/delay.h> #include <linux/sched.h> #include <linux/tty.h> #include <linux/serial.h> #include <linux/tty_flip.h> #include <linux/slab.h> -#include <linux/uaccess.h> #include <linux/atomic.h> #include "../ipack.h" #include "ipoctal.h" @@ -48,12 +42,9 @@ struct ipoctal { struct scc2698_channel *chan_regs; struct scc2698_block *block_regs; struct ipoctal_stats chan_stats[NR_CHANNELS]; - char *buffer[NR_CHANNELS]; unsigned int nb_bytes[NR_CHANNELS]; unsigned int count_wr[NR_CHANNELS]; - struct ipoctal_config chan_config[NR_CHANNELS]; wait_queue_head_t queue[NR_CHANNELS]; - unsigned short error_flag[NR_CHANNELS]; spinlock_t lock[NR_CHANNELS]; unsigned int pointer_read[NR_CHANNELS]; unsigned int pointer_write[NR_CHANNELS]; @@ -116,14 +107,13 @@ static int ipoctal_port_activate(struct tty_port *port, struct tty_struct *tty) ipoctal = ipoctal_find_board(tty); if (ipoctal == NULL) { - pr_err("Device not found. Major %d\n", tty->driver->major); + dev_err(tty->dev, "Device not found. Major %d\n", + tty->driver->major); return -ENODEV; } ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, CR_ENABLE_RX); - tty->driver_data = ipoctal; - return 0; } @@ -136,13 +126,16 @@ static int ipoctal_open(struct tty_struct *tty, struct file *file) ipoctal = ipoctal_find_board(tty); if (ipoctal == NULL) { - pr_err("Device not found. Major %d\n", tty->driver->major); + dev_err(tty->dev, "Device not found. Major %d\n", + tty->driver->major); return -ENODEV; } if (atomic_read(&ipoctal->open[channel])) return -EBUSY; + tty->driver_data = ipoctal; + res = tty_port_open(&ipoctal->tty_port[channel], tty, file); if (res) return res; @@ -276,23 +269,19 @@ static int ipoctal_irq_handler(void *arg) CR_CMD_RESET_ERR_STATUS); if (sr & SR_OVERRUN_ERROR) { - ipoctal->error_flag[channel] |= UART_OVERRUN; ipoctal->chan_stats[channel].overrun_err++; /* Overrun doesn't affect the current character*/ tty_insert_flip_char(tty, 0, TTY_OVERRUN); } if (sr & SR_PARITY_ERROR) { - ipoctal->error_flag[channel] |= UART_PARITY; ipoctal->chan_stats[channel].parity_err++; flag = TTY_PARITY; } if (sr & SR_FRAMING_ERROR) { - ipoctal->error_flag[channel] |= UART_FRAMING; ipoctal->chan_stats[channel].framing_err++; flag = TTY_FRAME; } if (sr & SR_RECEIVED_BREAK) { - ipoctal->error_flag[channel] |= UART_BREAK; ipoctal->chan_stats[channel].rcv_break++; flag = TTY_BREAK; } @@ -310,8 +299,8 @@ static int ipoctal_irq_handler(void *arg) ipoctal->nb_bytes[channel] = 0; continue; } - spin_lock(&ipoctal->lock[channel]); - value = ipoctal->buffer[channel][*pointer_write]; + + value = ipoctal->tty_port[channel].xmit_buf[*pointer_write]; ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.thr, value); @@ -320,7 +309,6 @@ static int ipoctal_irq_handler(void *arg) (*pointer_write)++; *pointer_write = *pointer_write % PAGE_SIZE; ipoctal->nb_bytes[channel]--; - spin_unlock(&ipoctal->lock[channel]); if ((ipoctal->nb_bytes[channel] == 0) && (waitqueue_active(&ipoctal->queue[channel]))) { @@ -381,7 +369,9 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0, IPACK_ID_SPACE); if (res) { - pr_err("Unable to map slot [%d:%d] ID space!\n", bus_nr, slot); + dev_err(&ipoctal->dev->dev, + "Unable to map slot [%d:%d] ID space!\n", + bus_nr, slot); return res; } @@ -396,14 +386,18 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0, IPACK_IO_SPACE); if (res) { - pr_err("Unable to map slot [%d:%d] IO space!\n", bus_nr, slot); + dev_err(&ipoctal->dev->dev, + "Unable to map slot [%d:%d] IO space!\n", + bus_nr, slot); goto out_unregister_id_space; } res = ipoctal->dev->bus->ops->map_space(ipoctal->dev, 0x8000, IPACK_MEM_SPACE); if (res) { - pr_err("Unable to map slot [%d:%d] MEM space!\n", bus_nr, slot); + dev_err(&ipoctal->dev->dev, + "Unable to map slot [%d:%d] MEM space!\n", + bus_nr, slot); goto out_unregister_io_space; } @@ -417,6 +411,20 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, for (i = 0; i < NR_CHANNELS ; i++) { ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[i].u.w.cr, CR_DISABLE_RX | CR_DISABLE_TX); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[i].u.w.cr, + CR_CMD_RESET_RX); + ipoctal_write_cr_cmd(ipoctal, &ipoctal->chan_regs[i].u.w.cr, + CR_CMD_RESET_TX); + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[i].u.w.mr, + MR1_CHRL_8_BITS | MR1_ERROR_CHAR | + MR1_RxINT_RxRDY); /* mr1 */ + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[i].u.w.mr, + 0); /* mr2 */ + ipoctal_write_io_reg(ipoctal, + &ipoctal->chan_regs[i].u.w.csr, + TX_CLK_9600 | RX_CLK_9600); } for (i = 0; i < IP_OCTAL_NB_BLOCKS; i++) { @@ -441,7 +449,8 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, */ ipoctal->dev->bus->ops->request_irq(ipoctal->dev, vector, ipoctal_irq_handler, ipoctal); - ipoctal->dev->bus->ops->write8(ipoctal->dev, IPACK_ID_SPACE, 0, vector); + ipoctal->dev->bus->ops->write8(ipoctal->dev, IPACK_MEM_SPACE, 0, + vector); /* Register the TTY device */ @@ -472,7 +481,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, tty_set_operations(tty, &ipoctal_fops); res = tty_register_driver(tty); if (res) { - pr_err("Can't register tty driver.\n"); + dev_err(&ipoctal->dev->dev, "Can't register tty driver.\n"); put_tty_driver(tty); goto out_unregister_slot_unmap; } @@ -488,7 +497,6 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, ipoctal_reset_stats(&ipoctal->chan_stats[i]); ipoctal->nb_bytes[i] = 0; init_waitqueue_head(&ipoctal->queue[i]); - ipoctal->error_flag[i] = UART_NOERROR; spin_lock_init(&ipoctal->lock[i]); ipoctal->pointer_read[i] = 0; @@ -547,8 +555,6 @@ static int ipoctal_write(struct ipoctal *ipoctal, unsigned int channel, ipoctal_copy_write_buffer(ipoctal, channel, buf, count); - ipoctal->error_flag[channel] = UART_NOERROR; - /* As the IP-OCTAL 485 only supports half duplex, do it manually */ if (ipoctal->board_id == IP_OCTAL_485_ID) { ipoctal_write_io_reg(ipoctal, @@ -665,22 +671,18 @@ static void ipoctal_set_termios(struct tty_struct *tty, if (cflag & CRTSCTS) { mr1 |= MR1_RxRTS_CONTROL_ON; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_ON; - ipoctal->chan_config[channel].flow_control = 1; } else { mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF; - ipoctal->chan_config[channel].flow_control = 0; } break; case IP_OCTAL_422_ID: mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_OFF | MR2_CTS_ENABLE_TX_OFF; - ipoctal->chan_config[channel].flow_control = 0; break; case IP_OCTAL_485_ID: mr1 |= MR1_RxRTS_CONTROL_OFF; mr2 |= MR2_TxRTS_CONTROL_ON | MR2_CTS_ENABLE_TX_OFF; - ipoctal->chan_config[channel].flow_control = 0; break; default: return; @@ -744,12 +746,6 @@ static void ipoctal_set_termios(struct tty_struct *tty, ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.mr, mr2); ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.csr, csr); - /* save the setup in the structure */ - ipoctal->chan_config[channel].baud = tty_get_baud_rate(tty); - ipoctal->chan_config[channel].bits_per_char = cflag & CSIZE; - ipoctal->chan_config[channel].parity = cflag & PARENB; - ipoctal->chan_config[channel].stop_bits = cflag & CSTOPB; - /* Enable again the RX */ ipoctal_write_io_reg(ipoctal, &ipoctal->chan_regs[channel].u.w.cr, CR_ENABLE_RX); @@ -853,11 +849,6 @@ static void __ipoctal_remove(struct ipoctal *ipoctal) tty_unregister_driver(ipoctal->tty_drv); put_tty_driver(ipoctal->tty_drv); - - /* Tell the carrier board to free all the resources for this device */ - if (ipoctal->dev->bus->ops->remove_device != NULL) - ipoctal->dev->bus->ops->remove_device(ipoctal->dev); - list_del(&ipoctal->list); kfree(ipoctal); } @@ -889,7 +880,7 @@ static void __exit ipoctal_exit(void) struct ipoctal *p, *next; list_for_each_entry_safe(p, next, &ipoctal_list, list) - __ipoctal_remove(p); + p->dev->bus->ops->remove_device(p->dev); ipack_driver_unregister(&driver); } diff --git a/drivers/staging/ipack/devices/ipoctal.h b/drivers/staging/ipack/devices/ipoctal.h index 266f3617069d..c5b4ed46516f 100644 --- a/drivers/staging/ipack/devices/ipoctal.h +++ b/drivers/staging/ipack/devices/ipoctal.h @@ -20,45 +20,6 @@ #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK)) /** - * enum uart_parity_e - UART supported parity. - */ -enum uart_parity_e { - UART_NONE = 0, - UART_ODD = 1, - UART_EVEN = 2, -}; - -/** - * enum uart_error - UART error type - * - */ -enum uart_error { - UART_NOERROR = 0, /* No error during transmission */ - UART_TIMEOUT = 1 << 0, /* Timeout error */ - UART_OVERRUN = 1 << 1, /* Overrun error */ - UART_PARITY = 1 << 2, /* Parity error */ - UART_FRAMING = 1 << 3, /* Framing error */ - UART_BREAK = 1 << 4, /* Received break */ -}; - -/** - * struct ipoctal_config - Serial configuration - * - * @baud: Baud rate - * @stop_bits: Stop bits (1 or 2) - * @bits_per_char: data size in bits - * @parity - * @flow_control: Flow control management (RTS/CTS) (0 disabled, 1 enabled) - */ -struct ipoctal_config { - unsigned int baud; - unsigned int stop_bits; - unsigned int bits_per_char; - unsigned short parity; - unsigned int flow_control; -}; - -/** * struct ipoctal_stats -- Stats since last reset * * @tx: Number of transmitted bytes diff --git a/drivers/staging/ipack/ipack.c b/drivers/staging/ipack/ipack.c index 2b4fa51bf167..c1cd97a4d9ce 100644 --- a/drivers/staging/ipack/ipack.c +++ b/drivers/staging/ipack/ipack.c @@ -9,25 +9,15 @@ * Software Foundation; version 2 of the License. */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/module.h> -#include <linux/mutex.h> #include <linux/slab.h> +#include <linux/idr.h> #include "ipack.h" #define to_ipack_dev(device) container_of(device, struct ipack_device, dev) #define to_ipack_driver(drv) container_of(drv, struct ipack_driver, driver) -/* used when allocating bus numbers */ -#define IPACK_MAXBUS 64 - -static DEFINE_MUTEX(ipack_mutex); - -struct ipack_busmap { - unsigned long busmap[IPACK_MAXBUS / (8*sizeof(unsigned long))]; -}; -static struct ipack_busmap busmap; +static DEFINE_IDA(ipack_ida); static void ipack_device_release(struct device *dev) { @@ -48,7 +38,7 @@ static int ipack_bus_match(struct device *device, struct device_driver *driver) if (ret) dev->driver = drv; - return 0; + return ret; } static int ipack_bus_probe(struct device *device) @@ -79,26 +69,6 @@ static struct bus_type ipack_bus_type = { .remove = ipack_bus_remove, }; -static int ipack_assign_bus_number(void) -{ - int busnum; - - mutex_lock(&ipack_mutex); - busnum = find_next_zero_bit(busmap.busmap, IPACK_MAXBUS, 1); - - if (busnum >= IPACK_MAXBUS) { - pr_err("too many buses\n"); - busnum = -1; - goto error_find_busnum; - } - - set_bit(busnum, busmap.busmap); - -error_find_busnum: - mutex_unlock(&ipack_mutex); - return busnum; -} - struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots, struct ipack_bus_ops *ops) { @@ -109,7 +79,7 @@ struct ipack_bus_device *ipack_bus_register(struct device *parent, int slots, if (!bus) return NULL; - bus_nr = ipack_assign_bus_number(); + bus_nr = ida_simple_get(&ipack_ida, 0, 0, GFP_KERNEL); if (bus_nr < 0) { kfree(bus); return NULL; @@ -125,9 +95,7 @@ EXPORT_SYMBOL_GPL(ipack_bus_register); int ipack_bus_unregister(struct ipack_bus_device *bus) { - mutex_lock(&ipack_mutex); - clear_bit(bus->bus_nr, busmap.busmap); - mutex_unlock(&ipack_mutex); + ida_simple_remove(&ipack_ida, bus->bus_nr); kfree(bus); return 0; } @@ -171,8 +139,6 @@ struct ipack_device *ipack_device_register(struct ipack_bus_device *bus, ret = device_register(&dev->dev); if (ret < 0) { - pr_err("error registering the device.\n"); - dev->driver->ops->remove(dev); kfree(dev); return NULL; } @@ -189,12 +155,14 @@ EXPORT_SYMBOL_GPL(ipack_device_unregister); static int __init ipack_init(void) { + ida_init(&ipack_ida); return bus_register(&ipack_bus_type); } static void __exit ipack_exit(void) { bus_unregister(&ipack_bus_type); + ida_destroy(&ipack_ida); } module_init(ipack_init); |