diff options
| author | David S. Miller <davem@davemloft.net> | 2014-09-29 14:36:33 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-09-29 14:36:33 -0400 |
| commit | 2b7fc477b0423cbcc7be8ad8652e3552198de418 (patch) | |
| tree | 58f6e51300fb344252e171ce4b167498e6be81e3 | |
| parent | 41c91996d99394a75912aa5bfda300b85789ed43 (diff) | |
| parent | 5b85bad2a473a8b90cac93d21ab024ba221a8b09 (diff) | |
Merge branch 'arcnet-EAE'
Michael Grzeschik says:
====================
ARCNET: add support for EAE multi interfac card
this series adds support for the PLX Bridge based multi interface
pci cards and adds support to change device address on com200xx chips
during runtime.
This series is based on v3.17-rc7.
It is fixed for build against com20020_cs.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/arcnet/arcnet.c | 2 | ||||
| -rw-r--r-- | drivers/net/arcnet/com20020-pci.c | 369 | ||||
| -rw-r--r-- | drivers/net/arcnet/com20020.c | 14 | ||||
| -rw-r--r-- | drivers/net/arcnet/com20020_cs.c | 4 | ||||
| -rw-r--r-- | include/linux/com20020.h | 29 |
5 files changed, 330 insertions, 88 deletions
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index 3b790de6c976..09de683c167e 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c | |||
| @@ -777,7 +777,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) | |||
| 777 | ACOMMAND(CFLAGScmd | RESETclear); | 777 | ACOMMAND(CFLAGScmd | RESETclear); |
| 778 | AINTMASK(0); | 778 | AINTMASK(0); |
| 779 | spin_unlock(&lp->lock); | 779 | spin_unlock(&lp->lock); |
| 780 | return IRQ_HANDLED; | 780 | return retval; |
| 781 | } | 781 | } |
| 782 | 782 | ||
| 783 | BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", | 783 | BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n", |
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c index 7bb292e59559..6c99ff0b0bdd 100644 --- a/drivers/net/arcnet/com20020-pci.c +++ b/drivers/net/arcnet/com20020-pci.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/pci.h> | 38 | #include <linux/pci.h> |
| 39 | #include <linux/arcdevice.h> | 39 | #include <linux/arcdevice.h> |
| 40 | #include <linux/com20020.h> | 40 | #include <linux/com20020.h> |
| 41 | #include <linux/list.h> | ||
| 41 | 42 | ||
| 42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
| 43 | 44 | ||
| @@ -61,115 +62,317 @@ module_param(clockp, int, 0); | |||
| 61 | module_param(clockm, int, 0); | 62 | module_param(clockm, int, 0); |
| 62 | MODULE_LICENSE("GPL"); | 63 | MODULE_LICENSE("GPL"); |
| 63 | 64 | ||
| 65 | static void com20020pci_remove(struct pci_dev *pdev); | ||
| 66 | |||
| 64 | static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | 67 | static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) |
| 65 | { | 68 | { |
| 69 | struct com20020_pci_card_info *ci; | ||
| 66 | struct net_device *dev; | 70 | struct net_device *dev; |
| 67 | struct arcnet_local *lp; | 71 | struct arcnet_local *lp; |
| 68 | int ioaddr, err; | 72 | struct com20020_priv *priv; |
| 73 | int i, ioaddr, ret; | ||
| 74 | struct resource *r; | ||
| 69 | 75 | ||
| 70 | if (pci_enable_device(pdev)) | 76 | if (pci_enable_device(pdev)) |
| 71 | return -EIO; | 77 | return -EIO; |
| 72 | dev = alloc_arcdev(device); | ||
| 73 | if (!dev) | ||
| 74 | return -ENOMEM; | ||
| 75 | 78 | ||
| 76 | dev->netdev_ops = &com20020_netdev_ops; | 79 | priv = devm_kzalloc(&pdev->dev, sizeof(struct com20020_priv), |
| 80 | GFP_KERNEL); | ||
| 81 | ci = (struct com20020_pci_card_info *)id->driver_data; | ||
| 82 | priv->ci = ci; | ||
| 77 | 83 | ||
| 78 | lp = netdev_priv(dev); | 84 | INIT_LIST_HEAD(&priv->list_dev); |
| 79 | 85 | ||
| 80 | pci_set_drvdata(pdev, dev); | ||
| 81 | 86 | ||
| 82 | // SOHARD needs PCI base addr 4 | 87 | for (i = 0; i < ci->devcount; i++) { |
| 83 | if (pdev->vendor==0x10B5) { | 88 | struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i]; |
| 84 | BUGMSG(D_NORMAL, "SOHARD\n"); | 89 | struct com20020_dev *card; |
| 85 | ioaddr = pci_resource_start(pdev, 4); | ||
| 86 | } | ||
| 87 | else { | ||
| 88 | BUGMSG(D_NORMAL, "Contemporary Controls\n"); | ||
| 89 | ioaddr = pci_resource_start(pdev, 2); | ||
| 90 | } | ||
| 91 | 90 | ||
| 92 | if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com20020-pci")) { | 91 | dev = alloc_arcdev(device); |
| 93 | BUGMSG(D_INIT, "IO region %xh-%xh already allocated.\n", | 92 | if (!dev) { |
| 94 | ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); | 93 | ret = -ENOMEM; |
| 95 | err = -EBUSY; | 94 | goto out_port; |
| 96 | goto out_dev; | 95 | } |
| 97 | } | ||
| 98 | 96 | ||
| 99 | // Dummy access after Reset | 97 | dev->netdev_ops = &com20020_netdev_ops; |
| 100 | // ARCNET controller needs this access to detect bustype | 98 | |
| 101 | outb(0x00,ioaddr+1); | 99 | lp = netdev_priv(dev); |
| 102 | inb(ioaddr+1); | 100 | |
| 103 | 101 | BUGMSG(D_NORMAL, "%s Controls\n", ci->name); | |
| 104 | dev->base_addr = ioaddr; | 102 | ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset; |
| 105 | dev->irq = pdev->irq; | 103 | |
| 106 | dev->dev_addr[0] = node; | 104 | r = devm_request_region(&pdev->dev, ioaddr, cm->size, |
| 107 | lp->card_name = "PCI COM20020"; | 105 | "com20020-pci"); |
| 108 | lp->card_flags = id->driver_data; | 106 | if (!r) { |
| 109 | lp->backplane = backplane; | 107 | pr_err("IO region %xh-%xh already allocated.\n", |
| 110 | lp->clockp = clockp & 7; | 108 | ioaddr, ioaddr + cm->size - 1); |
| 111 | lp->clockm = clockm & 3; | 109 | ret = -EBUSY; |
| 112 | lp->timeout = timeout; | 110 | goto out_port; |
| 113 | lp->hw.owner = THIS_MODULE; | 111 | } |
| 114 | 112 | ||
| 115 | if (ASTATUS() == 0xFF) { | 113 | /* Dummy access after Reset |
| 116 | BUGMSG(D_NORMAL, "IO address %Xh was reported by PCI BIOS, " | 114 | * ARCNET controller needs |
| 117 | "but seems empty!\n", ioaddr); | 115 | * this access to detect bustype |
| 118 | err = -EIO; | 116 | */ |
| 119 | goto out_port; | 117 | outb(0x00, ioaddr + 1); |
| 120 | } | 118 | inb(ioaddr + 1); |
| 121 | if (com20020_check(dev)) { | 119 | |
| 122 | err = -EIO; | 120 | dev->base_addr = ioaddr; |
| 123 | goto out_port; | 121 | dev->dev_addr[0] = node; |
| 122 | dev->irq = pdev->irq; | ||
| 123 | lp->card_name = "PCI COM20020"; | ||
| 124 | lp->card_flags = ci->flags; | ||
| 125 | lp->backplane = backplane; | ||
| 126 | lp->clockp = clockp & 7; | ||
| 127 | lp->clockm = clockm & 3; | ||
| 128 | lp->timeout = timeout; | ||
| 129 | lp->hw.owner = THIS_MODULE; | ||
| 130 | |||
| 131 | if (ASTATUS() == 0xFF) { | ||
| 132 | pr_err("IO address %Xh is empty!\n", ioaddr); | ||
| 133 | ret = -EIO; | ||
| 134 | goto out_port; | ||
| 135 | } | ||
| 136 | if (com20020_check(dev)) { | ||
| 137 | ret = -EIO; | ||
| 138 | goto out_port; | ||
| 139 | } | ||
| 140 | |||
| 141 | card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev), | ||
| 142 | GFP_KERNEL); | ||
| 143 | if (!card) { | ||
| 144 | pr_err("%s out of memory!\n", __func__); | ||
| 145 | return -ENOMEM; | ||
| 146 | } | ||
| 147 | |||
| 148 | card->index = i; | ||
| 149 | card->pci_priv = priv; | ||
| 150 | card->dev = dev; | ||
| 151 | |||
| 152 | dev_set_drvdata(&dev->dev, card); | ||
| 153 | |||
| 154 | ret = com20020_found(dev, IRQF_SHARED); | ||
| 155 | if (ret) | ||
| 156 | goto out_port; | ||
| 157 | |||
| 158 | list_add(&card->list, &priv->list_dev); | ||
| 124 | } | 159 | } |
| 125 | 160 | ||
| 126 | if ((err = com20020_found(dev, IRQF_SHARED)) != 0) | 161 | pci_set_drvdata(pdev, priv); |
| 127 | goto out_port; | ||
| 128 | 162 | ||
| 129 | return 0; | 163 | return 0; |
| 130 | 164 | ||
| 131 | out_port: | 165 | out_port: |
| 132 | release_region(ioaddr, ARCNET_TOTAL_SIZE); | 166 | com20020pci_remove(pdev); |
| 133 | out_dev: | 167 | return ret; |
| 134 | free_netdev(dev); | ||
| 135 | return err; | ||
| 136 | } | 168 | } |
| 137 | 169 | ||
