aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/atm/eni.c
diff options
context:
space:
mode:
authorfrançois romieu <romieu@fr.zoreil.com>2012-03-15 21:52:04 -0400
committerDavid S. Miller <davem@davemloft.net>2012-03-17 02:13:20 -0400
commit126a3fd251b244eabd9ab9dcb32b8b6f999c1b91 (patch)
treedb496f9ba4536215e9be58745565a426c090aebb /drivers/atm/eni.c
parent4823cd388dd68015e254d1449bd63ffe47d83fa7 (diff)
eni: fix driver remove function and driver probe error path.
- add eni_do_release() to balance eni_do_init - turn the zeroes DMA area into a per device data Signed-off-by: Francois Romieu <romieu@fr.zoreil.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/atm/eni.c')
-rw-r--r--drivers/atm/eni.c98
1 files changed, 63 insertions, 35 deletions
diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c
index 485a11a6de96..6ff612d099c3 100644
--- a/drivers/atm/eni.c
+++ b/drivers/atm/eni.c
@@ -156,9 +156,6 @@ static int tx_complete = 0,dma_complete = 0,queued = 0,requeued = 0,
156 156
157static struct atm_dev *eni_boards = NULL; 157static struct atm_dev *eni_boards = NULL;
158 158
159static u32 *cpu_zeroes = NULL; /* aligned "magic" zeroes */
160static dma_addr_t zeroes;
161
162/* Read/write registers on card */ 159/* Read/write registers on card */
163#define eni_in(r) readl(eni_dev->reg+(r)*4) 160#define eni_in(r) readl(eni_dev->reg+(r)*4)
164#define eni_out(v,r) writel((v),eni_dev->reg+(r)*4) 161#define eni_out(v,r) writel((v),eni_dev->reg+(r)*4)
@@ -1138,8 +1135,10 @@ DPRINTK("doing direct send\n"); /* @@@ well, this doesn't work anyway */
1138 skb_shinfo(skb)->frags[i].page_offset, 1135 skb_shinfo(skb)->frags[i].page_offset,
1139 skb_frag_size(&skb_shinfo(skb)->frags[i])); 1136 skb_frag_size(&skb_shinfo(skb)->frags[i]));
1140 } 1137 }
1141 if (skb->len & 3) 1138 if (skb->len & 3) {
1142 put_dma(tx->index,eni_dev->dma,&j,zeroes,4-(skb->len & 3)); 1139 put_dma(tx->index, eni_dev->dma, &j, eni_dev->zero.dma,
1140 4 - (skb->len & 3));
1141 }
1143 /* JK for AAL5 trailer - AAL0 doesn't need it, but who cares ... */ 1142 /* JK for AAL5 trailer - AAL0 doesn't need it, but who cares ... */
1144 eni_dev->dma[j++] = (((tx->tx_pos+size) & (tx->words-1)) << 1143 eni_dev->dma[j++] = (((tx->tx_pos+size) & (tx->words-1)) <<
1145 MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) | 1144 MID_DMA_COUNT_SHIFT) | (tx->index << MID_DMA_CHAN_SHIFT) |
@@ -1728,6 +1727,7 @@ static int __devinit eni_do_init(struct atm_dev *dev)
1728 "mapping\n",dev->number); 1727 "mapping\n",dev->number);
1729 return error; 1728 return error;
1730 } 1729 }
1730 eni_dev->ioaddr = base;
1731 eni_dev->base_diff = real_base - (unsigned long) base; 1731 eni_dev->base_diff = real_base - (unsigned long) base;
1732 /* id may not be present in ASIC Tonga boards - check this @@@ */ 1732 /* id may not be present in ASIC Tonga boards - check this @@@ */
1733 if (!eni_dev->asic) { 1733 if (!eni_dev->asic) {
@@ -1789,6 +1789,14 @@ unmap:
1789 goto out; 1789 goto out;
1790} 1790}
1791 1791
1792static void eni_do_release(struct atm_dev *dev)
1793{
1794 struct eni_dev *ed = ENI_DEV(dev);
1795
1796 dev->phy->stop(dev);
1797 dev->phy = NULL;
1798 iounmap(ed->ioaddr);
1799}
1792 1800
1793static int __devinit eni_start(struct atm_dev *dev) 1801static int __devinit eni_start(struct atm_dev *dev)
1794{ 1802{
@@ -2220,48 +2228,60 @@ static const struct atmdev_ops ops = {
2220 2228
2221 2229
2222static int __devinit eni_init_one(struct pci_dev *pci_dev, 2230static int __devinit eni_init_one(struct pci_dev *pci_dev,
2223 const struct pci_device_id *ent) 2231 const struct pci_device_id *ent)
2224{ 2232{
2225 struct atm_dev *dev; 2233 struct atm_dev *dev;
2226 struct eni_dev *eni_dev; 2234 struct eni_dev *eni_dev;
2227 int error = -ENOMEM; 2235 struct eni_zero *zero;
2236 int rc;
2237
2238 rc = pci_enable_device(pci_dev);
2239 if (rc < 0)
2240 goto out;
2228 2241
2229 DPRINTK("eni_init_one\n"); 2242 rc = -ENOMEM;
2243 eni_dev = kmalloc(sizeof(struct eni_dev), GFP_KERNEL);
2244 if (!eni_dev)
2245 goto err_disable;
2230 2246
2231 if (pci_enable_device(pci_dev)) { 2247 zero = &eni_dev->zero;
2232 error = -EIO; 2248 zero->addr = pci_alloc_consistent(pci_dev, ENI_ZEROES_SIZE, &zero->dma);
2233 goto out0; 2249 if (!zero->addr)
2234 } 2250 goto err_kfree;
2235 2251
2236 eni_dev = kmalloc(sizeof(struct eni_dev),GFP_KERNEL);
2237 if (!eni_dev) goto out0;
2238 if (!cpu_zeroes) {
2239 cpu_zeroes = pci_alloc_consistent(pci_dev,ENI_ZEROES_SIZE,
2240 &zeroes);
2241 if (!cpu_zeroes) goto out1;
2242 }
2243 dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL); 2252 dev = atm_dev_register(DEV_LABEL, &pci_dev->dev, &ops, -1, NULL);
2244 if (!dev) goto out2; 2253 if (!dev)
2254 goto err_free_consistent;
2255
2256 dev->dev_data = eni_dev;
2245 pci_set_drvdata(pci_dev, dev); 2257 pci_set_drvdata(pci_dev, dev);
2246 eni_dev->pci_dev = pci_dev; 2258 eni_dev->pci_dev = pci_dev;
2247 dev->dev_data = eni_dev;
2248 eni_dev->asic = ent->driver_data; 2259 eni_dev->asic = ent->driver_data;
2249 error = eni_do_init(dev); 2260
2250 if (error) goto out3; 2261 rc = eni_do_init(dev);
2251 error = eni_start(dev); 2262 if (rc < 0)
2252 if (error) goto out3; 2263 goto err_unregister;
2264
2265 rc = eni_start(dev);
2266 if (rc < 0)
2267 goto err_eni_release;
2268
2253 eni_dev->more = eni_boards; 2269 eni_dev->more = eni_boards;
2254 eni_boards = dev; 2270 eni_boards = dev;
2255 return 0; 2271out:
2256out3: 2272 return rc;
2273
2274err_eni_release:
2275 eni_do_release(dev);
2276err_unregister:
2257 atm_dev_deregister(dev); 2277 atm_dev_deregister(dev);
2258out2: 2278err_free_consistent:
2259 pci_free_consistent(eni_dev->pci_dev,ENI_ZEROES_SIZE,cpu_zeroes,zeroes); 2279 pci_free_consistent(pci_dev, ENI_ZEROES_SIZE, zero->addr, zero->dma);
2260 cpu_zeroes = NULL; 2280err_kfree:
2261out1:
2262 kfree(eni_dev); 2281 kfree(eni_dev);
2263out0: 2282err_disable:
2264 return error; 2283 pci_disable_device(pci_dev);
2284 goto out;
2265} 2285}
2266 2286
2267 2287
@@ -2273,9 +2293,17 @@ static struct pci_device_id eni_pci_tbl[] = {
2273MODULE_DEVICE_TABLE(pci,eni_pci_tbl); 2293MODULE_DEVICE_TABLE(pci,eni_pci_tbl);
2274 2294
2275 2295
2276static void __devexit eni_remove_one(struct pci_dev *pci_dev) 2296static void __devexit eni_remove_one(struct pci_dev *pdev)
2277{ 2297{
2278 /* grrr */ 2298 struct atm_dev *dev = pci_get_drvdata(pdev);
2299 struct eni_dev *ed = ENI_DEV(dev);
2300 struct eni_zero *zero = &ed->zero;
2301
2302 eni_do_release(dev);
2303 atm_dev_deregister(dev);
2304 pci_free_consistent(pdev, ENI_ZEROES_SIZE, zero->addr, zero->dma);
2305 kfree(ed);
2306 pci_disable_device(pdev);
2279} 2307}
2280 2308
2281 2309