blob: c2a3524a5411d34e070eb3b047d2a707913f6d43 [file] [log] [blame]
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001/*
2 * Copyright (C) 2006-2007 PA Semi, Inc
3 *
4 * Driver for the PA Semi PWRficient onchip 1G/10G Ethernet MACs
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include <linux/init.h>
21#include <linux/module.h>
22#include <linux/pci.h>
23#include <linux/interrupt.h>
24#include <linux/dmaengine.h>
25#include <linux/delay.h>
26#include <linux/netdevice.h>
27#include <linux/etherdevice.h>
28#include <asm/dma-mapping.h>
29#include <linux/in.h>
30#include <linux/skbuff.h>
31
32#include <linux/ip.h>
33#include <linux/tcp.h>
34#include <net/checksum.h>
35
Olof Johansson771f7402007-05-08 00:47:21 -050036#include <asm/irq.h>
37
Olof Johanssonf5cd7872007-01-31 21:43:54 -060038#include "pasemi_mac.h"
39
40
41/* TODO list
42 *
43 * - Get rid of pci_{read,write}_config(), map registers with ioremap
44 * for performance
45 * - PHY support
46 * - Multicast support
47 * - Large MTU support
48 * - Other performance improvements
49 */
50
51
52/* Must be a power of two */
53#define RX_RING_SIZE 512
54#define TX_RING_SIZE 512
55
Olof Johanssonceb51362007-05-08 00:47:49 -050056#define DEFAULT_MSG_ENABLE \
57 (NETIF_MSG_DRV | \
58 NETIF_MSG_PROBE | \
59 NETIF_MSG_LINK | \
60 NETIF_MSG_TIMER | \
61 NETIF_MSG_IFDOWN | \
62 NETIF_MSG_IFUP | \
63 NETIF_MSG_RX_ERR | \
64 NETIF_MSG_TX_ERR)
65
Olof Johanssonfc9e4d22007-10-02 16:25:53 -050066#define TX_RING(mac, num) ((mac)->tx->ring[(num) & (TX_RING_SIZE-1)])
67#define TX_RING_INFO(mac, num) ((mac)->tx->ring_info[(num) & (TX_RING_SIZE-1)])
68#define RX_RING(mac, num) ((mac)->rx->ring[(num) & (RX_RING_SIZE-1)])
69#define RX_RING_INFO(mac, num) ((mac)->rx->ring_info[(num) & (RX_RING_SIZE-1)])
Olof Johanssonf5cd7872007-01-31 21:43:54 -060070#define RX_BUFF(mac, num) ((mac)->rx->buffers[(num) & (RX_RING_SIZE-1)])
71
Olof Johansson021fa222007-08-22 09:13:11 -050072#define RING_USED(ring) (((ring)->next_to_fill - (ring)->next_to_clean) \
73 & ((ring)->size - 1))
74#define RING_AVAIL(ring) ((ring->size) - RING_USED(ring))
75
Olof Johanssonf5cd7872007-01-31 21:43:54 -060076#define BUF_SIZE 1646 /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
77
Olof Johanssonceb51362007-05-08 00:47:49 -050078MODULE_LICENSE("GPL");
79MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
80MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
81
82static int debug = -1; /* -1 == use DEFAULT_MSG_ENABLE as value */
83module_param(debug, int, 0);
84MODULE_PARM_DESC(debug, "PA Semi MAC bitmapped debugging message enable value");
Olof Johanssonf5cd7872007-01-31 21:43:54 -060085
86static struct pasdma_status *dma_status;
87
Olof Johanssona85b9422007-09-15 13:40:59 -070088static void write_iob_reg(struct pasemi_mac *mac, unsigned int reg,
89 unsigned int val)
90{
Olof Johanssonb6e05a12007-09-15 13:44:07 -070091 out_le32(mac->iob_regs+reg, val);
Olof Johanssona85b9422007-09-15 13:40:59 -070092}
93
94static unsigned int read_mac_reg(struct pasemi_mac *mac, unsigned int reg)
95{
Olof Johanssonb6e05a12007-09-15 13:44:07 -070096 return in_le32(mac->regs+reg);
Olof Johanssona85b9422007-09-15 13:40:59 -070097}
98
99static void write_mac_reg(struct pasemi_mac *mac, unsigned int reg,
100 unsigned int val)
101{
Olof Johanssonb6e05a12007-09-15 13:44:07 -0700102 out_le32(mac->regs+reg, val);
Olof Johanssona85b9422007-09-15 13:40:59 -0700103}
104
105static unsigned int read_dma_reg(struct pasemi_mac *mac, unsigned int reg)
106{
Olof Johanssonb6e05a12007-09-15 13:44:07 -0700107 return in_le32(mac->dma_regs+reg);
Olof Johanssona85b9422007-09-15 13:40:59 -0700108}
109
110static void write_dma_reg(struct pasemi_mac *mac, unsigned int reg,
111 unsigned int val)
112{
Olof Johanssonb6e05a12007-09-15 13:44:07 -0700113 out_le32(mac->dma_regs+reg, val);
Olof Johanssona85b9422007-09-15 13:40:59 -0700114}
115
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600116static int pasemi_get_mac_addr(struct pasemi_mac *mac)
117{
118 struct pci_dev *pdev = mac->pdev;
119 struct device_node *dn = pci_device_to_OF_node(pdev);
olof@lixom.net1af7f052007-05-12 14:57:46 -0500120 int len;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600121 const u8 *maddr;
122 u8 addr[6];
123
124 if (!dn) {
125 dev_dbg(&pdev->dev,
126 "No device node for mac, not configuring\n");
127 return -ENOENT;
128 }
129
olof@lixom.net1af7f052007-05-12 14:57:46 -0500130 maddr = of_get_property(dn, "local-mac-address", &len);
Olof Johanssona5fd22e2007-05-08 00:48:02 -0500131
olof@lixom.net1af7f052007-05-12 14:57:46 -0500132 if (maddr && len == 6) {
133 memcpy(mac->mac_addr, maddr, 6);
134 return 0;
135 }
136
137 /* Some old versions of firmware mistakenly uses mac-address
138 * (and as a string) instead of a byte array in local-mac-address.
139 */
140
Olof Johanssona5fd22e2007-05-08 00:48:02 -0500141 if (maddr == NULL)
Linus Torvalds90287802007-05-08 11:57:17 -0700142 maddr = of_get_property(dn, "mac-address", NULL);
Olof Johanssona5fd22e2007-05-08 00:48:02 -0500143
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600144 if (maddr == NULL) {
145 dev_warn(&pdev->dev,
146 "no mac address in device tree, not configuring\n");
147 return -ENOENT;
148 }
149
olof@lixom.net1af7f052007-05-12 14:57:46 -0500150
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600151 if (sscanf(maddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &addr[0],
152 &addr[1], &addr[2], &addr[3], &addr[4], &addr[5]) != 6) {
153 dev_warn(&pdev->dev,
154 "can't parse mac address, not configuring\n");
155 return -EINVAL;
156 }
157
olof@lixom.net1af7f052007-05-12 14:57:46 -0500158 memcpy(mac->mac_addr, addr, 6);
159
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600160 return 0;
161}
162
163static int pasemi_mac_setup_rx_resources(struct net_device *dev)
164{
165 struct pasemi_mac_rxring *ring;
166 struct pasemi_mac *mac = netdev_priv(dev);
167 int chan_id = mac->dma_rxch;
168
169 ring = kzalloc(sizeof(*ring), GFP_KERNEL);
170
171 if (!ring)
172 goto out_ring;
173
174 spin_lock_init(&ring->lock);
175
Olof Johansson021fa222007-08-22 09:13:11 -0500176 ring->size = RX_RING_SIZE;
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500177 ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600178 RX_RING_SIZE, GFP_KERNEL);
179
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500180 if (!ring->ring_info)
181 goto out_ring_info;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600182
183 /* Allocate descriptors */
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500184 ring->ring = dma_alloc_coherent(&mac->dma_pdev->dev,
185 RX_RING_SIZE * sizeof(u64),
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600186 &ring->dma, GFP_KERNEL);
187
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500188 if (!ring->ring)
189 goto out_ring_desc;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600190
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500191 memset(ring->ring, 0, RX_RING_SIZE * sizeof(u64));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600192
193 ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev,
194 RX_RING_SIZE * sizeof(u64),
195 &ring->buf_dma, GFP_KERNEL);
196 if (!ring->buffers)
197 goto out_buffers;
198
199 memset(ring->buffers, 0, RX_RING_SIZE * sizeof(u64));
200
Olof Johanssona85b9422007-09-15 13:40:59 -0700201 write_dma_reg(mac, PAS_DMA_RXCHAN_BASEL(chan_id), PAS_DMA_RXCHAN_BASEL_BRBL(ring->dma));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600202
Olof Johanssona85b9422007-09-15 13:40:59 -0700203 write_dma_reg(mac, PAS_DMA_RXCHAN_BASEU(chan_id),
204 PAS_DMA_RXCHAN_BASEU_BRBH(ring->dma >> 32) |
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500205 PAS_DMA_RXCHAN_BASEU_SIZ(RX_RING_SIZE >> 3));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600206
Olof Johanssona85b9422007-09-15 13:40:59 -0700207 write_dma_reg(mac, PAS_DMA_RXCHAN_CFG(chan_id),
Olof Johanssonc0efd522007-08-22 09:12:52 -0500208 PAS_DMA_RXCHAN_CFG_HBU(2));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600209
Olof Johanssona85b9422007-09-15 13:40:59 -0700210 write_dma_reg(mac, PAS_DMA_RXINT_BASEL(mac->dma_if),
211 PAS_DMA_RXINT_BASEL_BRBL(__pa(ring->buffers)));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600212
Olof Johanssona85b9422007-09-15 13:40:59 -0700213 write_dma_reg(mac, PAS_DMA_RXINT_BASEU(mac->dma_if),
214 PAS_DMA_RXINT_BASEU_BRBH(__pa(ring->buffers) >> 32) |
215 PAS_DMA_RXINT_BASEU_SIZ(RX_RING_SIZE >> 3));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600216
Olof Johanssonc0efd522007-08-22 09:12:52 -0500217 write_dma_reg(mac, PAS_DMA_RXINT_CFG(mac->dma_if),
218 PAS_DMA_RXINT_CFG_DHL(2));
219
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600220 ring->next_to_fill = 0;
221 ring->next_to_clean = 0;
222
223 snprintf(ring->irq_name, sizeof(ring->irq_name),
224 "%s rx", dev->name);
225 mac->rx = ring;
226
227 return 0;
228
229out_buffers:
230 dma_free_coherent(&mac->dma_pdev->dev,
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500231 RX_RING_SIZE * sizeof(u64),
232 mac->rx->ring, mac->rx->dma);
233out_ring_desc:
234 kfree(ring->ring_info);
235out_ring_info:
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600236 kfree(ring);
237out_ring:
238 return -ENOMEM;
239}
240
241
242static int pasemi_mac_setup_tx_resources(struct net_device *dev)
243{
244 struct pasemi_mac *mac = netdev_priv(dev);
245 u32 val;
246 int chan_id = mac->dma_txch;
247 struct pasemi_mac_txring *ring;
248
249 ring = kzalloc(sizeof(*ring), GFP_KERNEL);
250 if (!ring)
251 goto out_ring;
252
253 spin_lock_init(&ring->lock);
254
Olof Johansson021fa222007-08-22 09:13:11 -0500255 ring->size = TX_RING_SIZE;
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500256 ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600257 TX_RING_SIZE, GFP_KERNEL);
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500258 if (!ring->ring_info)
259 goto out_ring_info;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600260
261 /* Allocate descriptors */
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500262 ring->ring = dma_alloc_coherent(&mac->dma_pdev->dev,
263 TX_RING_SIZE * sizeof(u64),
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600264 &ring->dma, GFP_KERNEL);
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500265 if (!ring->ring)
266 goto out_ring_desc;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600267
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500268 memset(ring->ring, 0, TX_RING_SIZE * sizeof(u64));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600269
Olof Johanssona85b9422007-09-15 13:40:59 -0700270 write_dma_reg(mac, PAS_DMA_TXCHAN_BASEL(chan_id),
271 PAS_DMA_TXCHAN_BASEL_BRBL(ring->dma));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600272 val = PAS_DMA_TXCHAN_BASEU_BRBH(ring->dma >> 32);
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500273 val |= PAS_DMA_TXCHAN_BASEU_SIZ(TX_RING_SIZE >> 3);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600274
Olof Johanssona85b9422007-09-15 13:40:59 -0700275 write_dma_reg(mac, PAS_DMA_TXCHAN_BASEU(chan_id), val);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600276
Olof Johanssona85b9422007-09-15 13:40:59 -0700277 write_dma_reg(mac, PAS_DMA_TXCHAN_CFG(chan_id),
278 PAS_DMA_TXCHAN_CFG_TY_IFACE |
279 PAS_DMA_TXCHAN_CFG_TATTR(mac->dma_if) |
280 PAS_DMA_TXCHAN_CFG_UP |
281 PAS_DMA_TXCHAN_CFG_WT(2));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600282
Olof Johansson021fa222007-08-22 09:13:11 -0500283 ring->next_to_fill = 0;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600284 ring->next_to_clean = 0;
285
286 snprintf(ring->irq_name, sizeof(ring->irq_name),
287 "%s tx", dev->name);
288 mac->tx = ring;
289
290 return 0;
291
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500292out_ring_desc:
293 kfree(ring->ring_info);
294out_ring_info:
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600295 kfree(ring);
296out_ring:
297 return -ENOMEM;
298}
299
300static void pasemi_mac_free_tx_resources(struct net_device *dev)
301{
302 struct pasemi_mac *mac = netdev_priv(dev);
303 unsigned int i;
304 struct pasemi_mac_buffer *info;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600305
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500306 for (i = 0; i < TX_RING_SIZE; i += 2) {
307 info = &TX_RING_INFO(mac, i+1);
308 if (info->dma && info->skb) {
309 pci_unmap_single(mac->dma_pdev,
310 info->dma,
311 info->skb->len,
312 PCI_DMA_TODEVICE);
313 dev_kfree_skb_any(info->skb);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600314 }
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500315 TX_RING(mac, i) = 0;
316 TX_RING(mac, i+1) = 0;
317 info->dma = 0;
318 info->skb = NULL;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600319 }
320
321 dma_free_coherent(&mac->dma_pdev->dev,
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500322 TX_RING_SIZE * sizeof(u64),
323 mac->tx->ring, mac->tx->dma);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600324
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500325 kfree(mac->tx->ring_info);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600326 kfree(mac->tx);
327 mac->tx = NULL;
328}
329
330static void pasemi_mac_free_rx_resources(struct net_device *dev)
331{
332 struct pasemi_mac *mac = netdev_priv(dev);
333 unsigned int i;
334 struct pasemi_mac_buffer *info;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600335
336 for (i = 0; i < RX_RING_SIZE; i++) {
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500337 info = &RX_RING_INFO(mac, i);
338 if (info->skb && info->dma) {
339 pci_unmap_single(mac->dma_pdev,
340 info->dma,
341 info->skb->len,
342 PCI_DMA_FROMDEVICE);
343 dev_kfree_skb_any(info->skb);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600344 }
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500345 info->dma = 0;
346 info->skb = NULL;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600347 }
348
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500349 for (i = 0; i < RX_RING_SIZE; i++)
350 RX_RING(mac, i) = 0;
351
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600352 dma_free_coherent(&mac->dma_pdev->dev,
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500353 RX_RING_SIZE * sizeof(u64),
354 mac->rx->ring, mac->rx->dma);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600355
356 dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64),
357 mac->rx->buffers, mac->rx->buf_dma);
358
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500359 kfree(mac->rx->ring_info);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600360 kfree(mac->rx);
361 mac->rx = NULL;
362}
363
Olof Johansson928773c2007-09-26 16:25:06 -0500364static void pasemi_mac_replenish_rx_ring(struct net_device *dev, int limit)
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600365{
366 struct pasemi_mac *mac = netdev_priv(dev);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600367 int start = mac->rx->next_to_fill;
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500368 unsigned int fill, count;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600369
Olof Johanssoncd4ceb22007-05-08 00:47:45 -0500370 if (limit <= 0)
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600371 return;
372
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500373 fill = start;
Olof Johansson928773c2007-09-26 16:25:06 -0500374 for (count = 0; count < limit; count++) {
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500375 struct pasemi_mac_buffer *info = &RX_RING_INFO(mac, fill);
376 u64 *buff = &RX_BUFF(mac, fill);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600377 struct sk_buff *skb;
378 dma_addr_t dma;
379
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500380 /* Entry in use? */
381 WARN_ON(*buff);
382
Olof Johansson9f05cfe2007-05-08 00:47:37 -0500383 /* skb might still be in there for recycle on short receives */
384 if (info->skb)
385 skb = info->skb;
386 else
387 skb = dev_alloc_skb(BUF_SIZE);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600388
Olof Johansson9f05cfe2007-05-08 00:47:37 -0500389 if (unlikely(!skb))
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600390 break;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600391
Olof Johansson18eec692007-10-02 16:25:14 -0500392 dma = pci_map_single(mac->dma_pdev, skb->data, BUF_SIZE,
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600393 PCI_DMA_FROMDEVICE);
394
Olof Johanssoncd4ceb22007-05-08 00:47:45 -0500395 if (unlikely(dma_mapping_error(dma))) {
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600396 dev_kfree_skb_irq(info->skb);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600397 break;
398 }
399
400 info->skb = skb;
401 info->dma = dma;
402 *buff = XCT_RXB_LEN(BUF_SIZE) | XCT_RXB_ADDR(dma);
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500403 fill++;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600404 }
405
406 wmb();
407
Olof Johansson928773c2007-09-26 16:25:06 -0500408 write_dma_reg(mac, PAS_DMA_RXCHAN_INCR(mac->dma_rxch), count);
409 write_dma_reg(mac, PAS_DMA_RXINT_INCR(mac->dma_if), count);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600410
Olof Johansson928773c2007-09-26 16:25:06 -0500411 mac->rx->next_to_fill += count;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600412}
413
Olof Johansson1b0335ea2007-05-08 00:47:26 -0500414static void pasemi_mac_restart_rx_intr(struct pasemi_mac *mac)
415{
Olof Johansson52a94352007-05-12 18:01:09 -0500416 unsigned int reg, pcnt;
Olof Johansson1b0335ea2007-05-08 00:47:26 -0500417 /* Re-enable packet count interrupts: finally
418 * ack the packet count interrupt we got in rx_intr.
419 */
420
Olof Johansson52a94352007-05-12 18:01:09 -0500421 pcnt = *mac->rx_status & PAS_STATUS_PCNT_M;
Olof Johansson1b0335ea2007-05-08 00:47:26 -0500422
Olof Johansson52a94352007-05-12 18:01:09 -0500423 reg = PAS_IOB_DMA_RXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_RXCH_RESET_PINTC;
Olof Johansson1b0335ea2007-05-08 00:47:26 -0500424
Olof Johanssona85b9422007-09-15 13:40:59 -0700425 write_iob_reg(mac, PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch), reg);
Olof Johansson1b0335ea2007-05-08 00:47:26 -0500426}
427
428static void pasemi_mac_restart_tx_intr(struct pasemi_mac *mac)
429{
Olof Johansson52a94352007-05-12 18:01:09 -0500430 unsigned int reg, pcnt;
Olof Johansson1b0335ea2007-05-08 00:47:26 -0500431
432 /* Re-enable packet count interrupts */
Olof Johansson52a94352007-05-12 18:01:09 -0500433 pcnt = *mac->tx_status & PAS_STATUS_PCNT_M;
Olof Johansson1b0335ea2007-05-08 00:47:26 -0500434
Olof Johansson52a94352007-05-12 18:01:09 -0500435 reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC;
Olof Johansson1b0335ea2007-05-08 00:47:26 -0500436
Olof Johanssona85b9422007-09-15 13:40:59 -0700437 write_iob_reg(mac, PAS_IOB_DMA_TXCH_RESET(mac->dma_txch), reg);
Olof Johansson1b0335ea2007-05-08 00:47:26 -0500438}
439
440
Olof Johansson69c29d82007-10-02 16:24:51 -0500441static inline void pasemi_mac_rx_error(struct pasemi_mac *mac, u64 macrx)
442{
443 unsigned int rcmdsta, ccmdsta;
444
445 if (!netif_msg_rx_err(mac))
446 return;
447
448 rcmdsta = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
449 ccmdsta = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
450
451 printk(KERN_ERR "pasemi_mac: rx error. macrx %016lx, rx status %lx\n",
452 macrx, *mac->rx_status);
453
454 printk(KERN_ERR "pasemi_mac: rcmdsta %08x ccmdsta %08x\n",
455 rcmdsta, ccmdsta);
456}
457
458static inline void pasemi_mac_tx_error(struct pasemi_mac *mac, u64 mactx)
459{
460 unsigned int cmdsta;
461
462 if (!netif_msg_tx_err(mac))
463 return;
464
465 cmdsta = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
466
467 printk(KERN_ERR "pasemi_mac: tx error. mactx 0x%016lx, "\
468 "tx status 0x%016lx\n", mactx, *mac->tx_status);
469
470 printk(KERN_ERR "pasemi_mac: tcmdsta 0x%08x\n", cmdsta);
471}
472
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600473static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
474{
Olof Johanssoncd4ceb22007-05-08 00:47:45 -0500475 unsigned int n;
476 int count;
Olof Johanssoncd4ceb22007-05-08 00:47:45 -0500477 struct pasemi_mac_buffer *info;
478 struct sk_buff *skb;
479 unsigned int i, len;
480 u64 macrx;
481 dma_addr_t dma;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600482
483 spin_lock(&mac->rx->lock);
484
Olof Johanssoncd4ceb22007-05-08 00:47:45 -0500485 n = mac->rx->next_to_clean;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600486
Olof Johanssoncd4ceb22007-05-08 00:47:45 -0500487 for (count = limit; count; count--) {
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600488
489 rmb();
490
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500491 macrx = RX_RING(mac, n);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600492
Olof Johansson69c29d82007-10-02 16:24:51 -0500493 if ((macrx & XCT_MACRX_E) ||
494 (*mac->rx_status & PAS_STATUS_ERROR))
495 pasemi_mac_rx_error(mac, macrx);
496
Olof Johanssoncd4ceb22007-05-08 00:47:45 -0500497 if (!(macrx & XCT_MACRX_O))
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600498 break;
499
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600500 info = NULL;
501
502 /* We have to scan for our skb since there's no way
503 * to back-map them from the descriptor, and if we
504 * have several receive channels then they might not
505 * show up in the same order as they were put on the
506 * interface ring.
507 */
508
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500509 dma = (RX_RING(mac, n+1) & XCT_PTR_ADDR_M);
510 for (i = mac->rx->next_to_fill;
511 i < (mac->rx->next_to_fill + RX_RING_SIZE);
512 i++) {
513 info = &RX_RING_INFO(mac, i);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600514 if (info->dma == dma)
515 break;
516 }
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500517
Olof Johansson26fcfa92007-08-22 09:12:59 -0500518 prefetchw(info);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600519
Olof Johansson9f05cfe2007-05-08 00:47:37 -0500520 skb = info->skb;
Olof Johansson26fcfa92007-08-22 09:12:59 -0500521 prefetchw(skb);
Olof Johansson9f05cfe2007-05-08 00:47:37 -0500522 info->dma = 0;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600523
Olof Johanssoncd4ceb22007-05-08 00:47:45 -0500524 pci_unmap_single(mac->dma_pdev, dma, skb->len,
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600525 PCI_DMA_FROMDEVICE);
526
Olof Johanssoncd4ceb22007-05-08 00:47:45 -0500527 len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600528
Olof Johansson9f05cfe2007-05-08 00:47:37 -0500529 if (len < 256) {
530 struct sk_buff *new_skb =
531 netdev_alloc_skb(mac->netdev, len + NET_IP_ALIGN);
532 if (new_skb) {
533 skb_reserve(new_skb, NET_IP_ALIGN);
Olof Johansson73344862007-08-22 09:12:55 -0500534 memcpy(new_skb->data, skb->data, len);
Olof Johansson9f05cfe2007-05-08 00:47:37 -0500535 /* save the skb in buffer_info as good */
536 skb = new_skb;
537 }
538 /* else just continue with the old one */
539 } else
540 info->skb = NULL;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600541
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500542 /* Need to zero it out since hardware doesn't, since the
543 * replenish loop uses it to tell when it's done.
544 */
545 RX_BUFF(mac, i) = 0;
546
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600547 skb_put(skb, len);
548
Olof Johansson26fcfa92007-08-22 09:12:59 -0500549 if (likely((macrx & XCT_MACRX_HTY_M) == XCT_MACRX_HTY_IPV4_OK)) {
Olof Johansson38bf3182007-08-22 09:13:24 -0500550 skb->ip_summed = CHECKSUM_UNNECESSARY;
Olof Johanssoncd4ceb22007-05-08 00:47:45 -0500551 skb->csum = (macrx & XCT_MACRX_CSUM_M) >>
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600552 XCT_MACRX_CSUM_S;
553 } else
554 skb->ip_summed = CHECKSUM_NONE;
555
Jeff Garzik09f75cd2007-10-03 17:41:50 -0700556 mac->netdev->stats.rx_bytes += len;
557 mac->netdev->stats.rx_packets++;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600558
Olof Johansson26fcfa92007-08-22 09:12:59 -0500559 skb->protocol = eth_type_trans(skb, mac->netdev);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600560 netif_receive_skb(skb);
561
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500562 RX_RING(mac, n) = 0;
563 RX_RING(mac, n+1) = 0;
Olof Johanssoncd4ceb22007-05-08 00:47:45 -0500564
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500565 n += 2;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600566 }
567
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500568 mac->rx->next_to_clean = n;
Olof Johansson928773c2007-09-26 16:25:06 -0500569 pasemi_mac_replenish_rx_ring(mac->netdev, limit-count);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600570
571 spin_unlock(&mac->rx->lock);
572
573 return count;
574}
575
576static int pasemi_mac_clean_tx(struct pasemi_mac *mac)
577{
578 int i;
579 struct pasemi_mac_buffer *info;
Olof Johansson02df6cf2007-08-22 09:13:03 -0500580 unsigned int start, count, limit;
581 unsigned int total_count;
Olof Johanssonca7e2352007-09-26 16:23:59 -0500582 unsigned long flags;
Olof Johansson02df6cf2007-08-22 09:13:03 -0500583 struct sk_buff *skbs[32];
584 dma_addr_t dmas[32];
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600585
Olof Johansson02df6cf2007-08-22 09:13:03 -0500586 total_count = 0;
587restart:
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600588 spin_lock_irqsave(&mac->tx->lock, flags);
589
590 start = mac->tx->next_to_clean;
Olof Johansson021fa222007-08-22 09:13:11 -0500591 limit = min(mac->tx->next_to_fill, start+32);
Olof Johansson02df6cf2007-08-22 09:13:03 -0500592
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600593 count = 0;
594
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500595 for (i = start; i < limit; i += 2) {
596 u64 mactx = TX_RING(mac, i);
597 if ((mactx & XCT_MACTX_E) ||
Olof Johansson69c29d82007-10-02 16:24:51 -0500598 (*mac->tx_status & PAS_STATUS_ERROR))
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500599 pasemi_mac_tx_error(mac, mactx);
Olof Johansson69c29d82007-10-02 16:24:51 -0500600
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500601 if (unlikely(mactx & XCT_MACTX_O))
Olof Johansson02df6cf2007-08-22 09:13:03 -0500602 /* Not yet transmitted */
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600603 break;
604
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500605 info = &TX_RING_INFO(mac, i+1);
Olof Johansson02df6cf2007-08-22 09:13:03 -0500606 skbs[count] = info->skb;
607 dmas[count] = info->dma;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600608
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600609 info->dma = 0;
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500610 TX_RING(mac, i) = 0;
611 TX_RING(mac, i+1) = 0;
612
Olof Johansson02df6cf2007-08-22 09:13:03 -0500613
614 count++;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600615 }
Olof Johanssonfc9e4d22007-10-02 16:25:53 -0500616 mac->tx->next_to_clean += count * 2;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600617 spin_unlock_irqrestore(&mac->tx->lock, flags);
Olof Johansson0ce68c72007-04-28 15:36:40 -0500618 netif_wake_queue(mac->netdev);
619
Olof Johansson02df6cf2007-08-22 09:13:03 -0500620 for (i = 0; i < count; i++) {
621 pci_unmap_single(mac->dma_pdev, dmas[i],
622 skbs[i]->len, PCI_DMA_TODEVICE);
623 dev_kfree_skb_irq(skbs[i]);
624 }
625
626 total_count += count;
627
628 /* If the batch was full, try to clean more */
629 if (count == 32)
630 goto restart;
631
632 return total_count;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600633}
634
635
636static irqreturn_t pasemi_mac_rx_intr(int irq, void *data)
637{
638 struct net_device *dev = data;
639 struct pasemi_mac *mac = netdev_priv(dev);
640 unsigned int reg;
641
Olof Johansson6dfa7522007-05-08 00:47:32 -0500642 if (!(*mac->rx_status & PAS_STATUS_CAUSE_M))
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600643 return IRQ_NONE;
644
Olof Johansson6dfa7522007-05-08 00:47:32 -0500645 /* Don't reset packet count so it won't fire again but clear
646 * all others.
647 */
648
Olof Johansson6dfa7522007-05-08 00:47:32 -0500649 reg = 0;
650 if (*mac->rx_status & PAS_STATUS_SOFT)
651 reg |= PAS_IOB_DMA_RXCH_RESET_SINTC;
652 if (*mac->rx_status & PAS_STATUS_ERROR)
653 reg |= PAS_IOB_DMA_RXCH_RESET_DINTC;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600654 if (*mac->rx_status & PAS_STATUS_TIMER)
655 reg |= PAS_IOB_DMA_RXCH_RESET_TINTC;
656
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700657 netif_rx_schedule(dev, &mac->napi);
Olof Johansson6dfa7522007-05-08 00:47:32 -0500658
Olof Johanssona85b9422007-09-15 13:40:59 -0700659 write_iob_reg(mac, PAS_IOB_DMA_RXCH_RESET(mac->dma_rxch), reg);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600660
661 return IRQ_HANDLED;
662}
663
664static irqreturn_t pasemi_mac_tx_intr(int irq, void *data)
665{
666 struct net_device *dev = data;
667 struct pasemi_mac *mac = netdev_priv(dev);
Olof Johansson52a94352007-05-12 18:01:09 -0500668 unsigned int reg, pcnt;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600669
Olof Johansson6dfa7522007-05-08 00:47:32 -0500670 if (!(*mac->tx_status & PAS_STATUS_CAUSE_M))
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600671 return IRQ_NONE;
672
673 pasemi_mac_clean_tx(mac);
674
Olof Johansson52a94352007-05-12 18:01:09 -0500675 pcnt = *mac->tx_status & PAS_STATUS_PCNT_M;
676
677 reg = PAS_IOB_DMA_TXCH_RESET_PCNT(pcnt) | PAS_IOB_DMA_TXCH_RESET_PINTC;
Olof Johansson6dfa7522007-05-08 00:47:32 -0500678
679 if (*mac->tx_status & PAS_STATUS_SOFT)
680 reg |= PAS_IOB_DMA_TXCH_RESET_SINTC;
681 if (*mac->tx_status & PAS_STATUS_ERROR)
682 reg |= PAS_IOB_DMA_TXCH_RESET_DINTC;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600683
Olof Johanssona85b9422007-09-15 13:40:59 -0700684 write_iob_reg(mac, PAS_IOB_DMA_TXCH_RESET(mac->dma_txch), reg);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600685
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600686 return IRQ_HANDLED;
687}
688
Olof Johanssonbb6e9592007-05-08 00:47:54 -0500689static void pasemi_adjust_link(struct net_device *dev)
690{
691 struct pasemi_mac *mac = netdev_priv(dev);
692 int msg;
693 unsigned int flags;
694 unsigned int new_flags;
695
696 if (!mac->phydev->link) {
697 /* If no link, MAC speed settings don't matter. Just report
698 * link down and return.
699 */
700 if (mac->link && netif_msg_link(mac))
701 printk(KERN_INFO "%s: Link is down.\n", dev->name);
702
703 netif_carrier_off(dev);
704 mac->link = 0;
705
706 return;
707 } else
708 netif_carrier_on(dev);
709
Olof Johanssona85b9422007-09-15 13:40:59 -0700710 flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
Olof Johanssonbb6e9592007-05-08 00:47:54 -0500711 new_flags = flags & ~(PAS_MAC_CFG_PCFG_HD | PAS_MAC_CFG_PCFG_SPD_M |
712 PAS_MAC_CFG_PCFG_TSR_M);
713
714 if (!mac->phydev->duplex)
715 new_flags |= PAS_MAC_CFG_PCFG_HD;
716
717 switch (mac->phydev->speed) {
718 case 1000:
719 new_flags |= PAS_MAC_CFG_PCFG_SPD_1G |
720 PAS_MAC_CFG_PCFG_TSR_1G;
721 break;
722 case 100:
723 new_flags |= PAS_MAC_CFG_PCFG_SPD_100M |
724 PAS_MAC_CFG_PCFG_TSR_100M;
725 break;
726 case 10:
727 new_flags |= PAS_MAC_CFG_PCFG_SPD_10M |
728 PAS_MAC_CFG_PCFG_TSR_10M;
729 break;
730 default:
731 printk("Unsupported speed %d\n", mac->phydev->speed);
732 }
733
734 /* Print on link or speed/duplex change */
735 msg = mac->link != mac->phydev->link || flags != new_flags;
736
737 mac->duplex = mac->phydev->duplex;
738 mac->speed = mac->phydev->speed;
739 mac->link = mac->phydev->link;
740
741 if (new_flags != flags)
Olof Johanssona85b9422007-09-15 13:40:59 -0700742 write_mac_reg(mac, PAS_MAC_CFG_PCFG, new_flags);
Olof Johanssonbb6e9592007-05-08 00:47:54 -0500743
744 if (msg && netif_msg_link(mac))
745 printk(KERN_INFO "%s: Link is up at %d Mbps, %s duplex.\n",
746 dev->name, mac->speed, mac->duplex ? "full" : "half");
747}
748
749static int pasemi_mac_phy_init(struct net_device *dev)
750{
751 struct pasemi_mac *mac = netdev_priv(dev);
752 struct device_node *dn, *phy_dn;
753 struct phy_device *phydev;
754 unsigned int phy_id;
755 const phandle *ph;
756 const unsigned int *prop;
757 struct resource r;
758 int ret;
759
760 dn = pci_device_to_OF_node(mac->pdev);
Linus Torvalds90287802007-05-08 11:57:17 -0700761 ph = of_get_property(dn, "phy-handle", NULL);
Olof Johanssonbb6e9592007-05-08 00:47:54 -0500762 if (!ph)
763 return -ENODEV;
764 phy_dn = of_find_node_by_phandle(*ph);
765
Linus Torvalds90287802007-05-08 11:57:17 -0700766 prop = of_get_property(phy_dn, "reg", NULL);
Olof Johanssonbb6e9592007-05-08 00:47:54 -0500767 ret = of_address_to_resource(phy_dn->parent, 0, &r);
768 if (ret)
769 goto err;
770
771 phy_id = *prop;
772 snprintf(mac->phy_id, BUS_ID_SIZE, PHY_ID_FMT, (int)r.start, phy_id);
773
774 of_node_put(phy_dn);
775
776 mac->link = 0;
777 mac->speed = 0;
778 mac->duplex = -1;
779
780 phydev = phy_connect(dev, mac->phy_id, &pasemi_adjust_link, 0, PHY_INTERFACE_MODE_SGMII);
781
782 if (IS_ERR(phydev)) {
783 printk(KERN_ERR "%s: Could not attach to phy\n", dev->name);
784 return PTR_ERR(phydev);
785 }
786
787 mac->phydev = phydev;
788
789 return 0;
790
791err:
792 of_node_put(phy_dn);
793 return -ENODEV;
794}
795
796
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600797static int pasemi_mac_open(struct net_device *dev)
798{
799 struct pasemi_mac *mac = netdev_priv(dev);
Olof Johansson771f7402007-05-08 00:47:21 -0500800 int base_irq;
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600801 unsigned int flags;
802 int ret;
803
804 /* enable rx section */
Olof Johanssona85b9422007-09-15 13:40:59 -0700805 write_dma_reg(mac, PAS_DMA_COM_RXCMD, PAS_DMA_COM_RXCMD_EN);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600806
807 /* enable tx section */
Olof Johanssona85b9422007-09-15 13:40:59 -0700808 write_dma_reg(mac, PAS_DMA_COM_TXCMD, PAS_DMA_COM_TXCMD_EN);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600809
810 flags = PAS_MAC_CFG_TXP_FCE | PAS_MAC_CFG_TXP_FPC(3) |
811 PAS_MAC_CFG_TXP_SL(3) | PAS_MAC_CFG_TXP_COB(0xf) |
812 PAS_MAC_CFG_TXP_TIFT(8) | PAS_MAC_CFG_TXP_TIFG(12);
813
Olof Johanssona85b9422007-09-15 13:40:59 -0700814 write_mac_reg(mac, PAS_MAC_CFG_TXP, flags);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600815
Olof Johanssona85b9422007-09-15 13:40:59 -0700816 write_iob_reg(mac, PAS_IOB_DMA_RXCH_CFG(mac->dma_rxch),
817 PAS_IOB_DMA_RXCH_CFG_CNTTH(0));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600818
Olof Johanssona85b9422007-09-15 13:40:59 -0700819 write_iob_reg(mac, PAS_IOB_DMA_TXCH_CFG(mac->dma_txch),
Olof Johansson02df6cf2007-08-22 09:13:03 -0500820 PAS_IOB_DMA_TXCH_CFG_CNTTH(128));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600821
Olof Johansson1b0335ea2007-05-08 00:47:26 -0500822 /* Clear out any residual packet count state from firmware */
823 pasemi_mac_restart_rx_intr(mac);
824 pasemi_mac_restart_tx_intr(mac);
825
Olof Johansson6dfa7522007-05-08 00:47:32 -0500826 /* 0xffffff is max value, about 16ms */
Olof Johanssona85b9422007-09-15 13:40:59 -0700827 write_iob_reg(mac, PAS_IOB_DMA_COM_TIMEOUTCFG,
828 PAS_IOB_DMA_COM_TIMEOUTCFG_TCNT(0xffffff));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600829
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600830 ret = pasemi_mac_setup_rx_resources(dev);
831 if (ret)
832 goto out_rx_resources;
833
834 ret = pasemi_mac_setup_tx_resources(dev);
835 if (ret)
836 goto out_tx_resources;
837
Olof Johanssona85b9422007-09-15 13:40:59 -0700838 write_mac_reg(mac, PAS_MAC_IPC_CHNL,
839 PAS_MAC_IPC_CHNL_DCHNO(mac->dma_rxch) |
840 PAS_MAC_IPC_CHNL_BCH(mac->dma_rxch));
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600841
842 /* enable rx if */
Olof Johanssona85b9422007-09-15 13:40:59 -0700843 write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
844 PAS_DMA_RXINT_RCMDSTA_EN);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600845
846 /* enable rx channel */
Olof Johanssona85b9422007-09-15 13:40:59 -0700847 write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch),
848 PAS_DMA_RXCHAN_CCMDSTA_EN |
849 PAS_DMA_RXCHAN_CCMDSTA_DU);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600850
851 /* enable tx channel */
Olof Johanssona85b9422007-09-15 13:40:59 -0700852 write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch),
853 PAS_DMA_TXCHAN_TCMDSTA_EN);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600854
Olof Johansson928773c2007-09-26 16:25:06 -0500855 pasemi_mac_replenish_rx_ring(dev, RX_RING_SIZE);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600856
Olof Johansson36033762007-09-26 16:24:42 -0500857 flags = PAS_MAC_CFG_PCFG_S1 | PAS_MAC_CFG_PCFG_PE |
858 PAS_MAC_CFG_PCFG_PR | PAS_MAC_CFG_PCFG_CE;
859
860 if (mac->type == MAC_TYPE_GMAC)
861 flags |= PAS_MAC_CFG_PCFG_TSR_1G | PAS_MAC_CFG_PCFG_SPD_1G;
862 else
863 flags |= PAS_MAC_CFG_PCFG_TSR_10G | PAS_MAC_CFG_PCFG_SPD_10G;
864
865 /* Enable interface in MAC */
866 write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
867
Olof Johanssonbb6e9592007-05-08 00:47:54 -0500868 ret = pasemi_mac_phy_init(dev);
869 /* Some configs don't have PHYs (XAUI etc), so don't complain about
870 * failed init due to -ENODEV.
871 */
872 if (ret && ret != -ENODEV)
873 dev_warn(&mac->pdev->dev, "phy init failed: %d\n", ret);
874
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600875 netif_start_queue(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700876 napi_enable(&mac->napi);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600877
Olof Johansson771f7402007-05-08 00:47:21 -0500878 /* Interrupts are a bit different for our DMA controller: While
879 * it's got one a regular PCI device header, the interrupt there
880 * is really the base of the range it's using. Each tx and rx
881 * channel has it's own interrupt source.
882 */
883
884 base_irq = virq_to_hw(mac->dma_pdev->irq);
885
886 mac->tx_irq = irq_create_mapping(NULL, base_irq + mac->dma_txch);
887 mac->rx_irq = irq_create_mapping(NULL, base_irq + 20 + mac->dma_txch);
888
889 ret = request_irq(mac->tx_irq, &pasemi_mac_tx_intr, IRQF_DISABLED,
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600890 mac->tx->irq_name, dev);
891 if (ret) {
892 dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n",
Olof Johansson771f7402007-05-08 00:47:21 -0500893 base_irq + mac->dma_txch, ret);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600894 goto out_tx_int;
895 }
896
Olof Johansson771f7402007-05-08 00:47:21 -0500897 ret = request_irq(mac->rx_irq, &pasemi_mac_rx_intr, IRQF_DISABLED,
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600898 mac->rx->irq_name, dev);
899 if (ret) {
900 dev_err(&mac->pdev->dev, "request_irq of irq %d failed: %d\n",
Olof Johansson771f7402007-05-08 00:47:21 -0500901 base_irq + 20 + mac->dma_rxch, ret);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600902 goto out_rx_int;
903 }
904
Olof Johanssonbb6e9592007-05-08 00:47:54 -0500905 if (mac->phydev)
906 phy_start(mac->phydev);
907
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600908 return 0;
909
910out_rx_int:
Olof Johansson771f7402007-05-08 00:47:21 -0500911 free_irq(mac->tx_irq, dev);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600912out_tx_int:
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700913 napi_disable(&mac->napi);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600914 netif_stop_queue(dev);
915 pasemi_mac_free_tx_resources(dev);
916out_tx_resources:
917 pasemi_mac_free_rx_resources(dev);
918out_rx_resources:
919
920 return ret;
921}
922
923#define MAX_RETRIES 5000
924
925static int pasemi_mac_close(struct net_device *dev)
926{
927 struct pasemi_mac *mac = netdev_priv(dev);
928 unsigned int stat;
929 int retries;
930
Olof Johanssonbb6e9592007-05-08 00:47:54 -0500931 if (mac->phydev) {
932 phy_stop(mac->phydev);
933 phy_disconnect(mac->phydev);
934 }
935
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600936 netif_stop_queue(dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700937 napi_disable(&mac->napi);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600938
939 /* Clean out any pending buffers */
940 pasemi_mac_clean_tx(mac);
941 pasemi_mac_clean_rx(mac, RX_RING_SIZE);
942
943 /* Disable interface */
Olof Johanssona85b9422007-09-15 13:40:59 -0700944 write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch), PAS_DMA_TXCHAN_TCMDSTA_ST);
945 write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if), PAS_DMA_RXINT_RCMDSTA_ST);
946 write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), PAS_DMA_RXCHAN_CCMDSTA_ST);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600947
948 for (retries = 0; retries < MAX_RETRIES; retries++) {
Olof Johanssona85b9422007-09-15 13:40:59 -0700949 stat = read_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch));
Olof Johansson0ce68c72007-04-28 15:36:40 -0500950 if (!(stat & PAS_DMA_TXCHAN_TCMDSTA_ACT))
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600951 break;
952 cond_resched();
953 }
954
Olof Johansson0ce68c72007-04-28 15:36:40 -0500955 if (stat & PAS_DMA_TXCHAN_TCMDSTA_ACT)
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600956 dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n");
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600957
958 for (retries = 0; retries < MAX_RETRIES; retries++) {
Olof Johanssona85b9422007-09-15 13:40:59 -0700959 stat = read_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch));
Olof Johansson0ce68c72007-04-28 15:36:40 -0500960 if (!(stat & PAS_DMA_RXCHAN_CCMDSTA_ACT))
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600961 break;
962 cond_resched();
963 }
964
Olof Johansson0ce68c72007-04-28 15:36:40 -0500965 if (stat & PAS_DMA_RXCHAN_CCMDSTA_ACT)
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600966 dev_err(&mac->dma_pdev->dev, "Failed to stop rx channel\n");
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600967
968 for (retries = 0; retries < MAX_RETRIES; retries++) {
Olof Johanssona85b9422007-09-15 13:40:59 -0700969 stat = read_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
Olof Johansson0ce68c72007-04-28 15:36:40 -0500970 if (!(stat & PAS_DMA_RXINT_RCMDSTA_ACT))
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600971 break;
972 cond_resched();
973 }
974
Olof Johansson0ce68c72007-04-28 15:36:40 -0500975 if (stat & PAS_DMA_RXINT_RCMDSTA_ACT)
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600976 dev_err(&mac->dma_pdev->dev, "Failed to stop rx interface\n");
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600977
978 /* Then, disable the channel. This must be done separately from
979 * stopping, since you can't disable when active.
980 */
981
Olof Johanssona85b9422007-09-15 13:40:59 -0700982 write_dma_reg(mac, PAS_DMA_TXCHAN_TCMDSTA(mac->dma_txch), 0);
983 write_dma_reg(mac, PAS_DMA_RXCHAN_CCMDSTA(mac->dma_rxch), 0);
984 write_dma_reg(mac, PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600985
Olof Johansson771f7402007-05-08 00:47:21 -0500986 free_irq(mac->tx_irq, dev);
987 free_irq(mac->rx_irq, dev);
Olof Johanssonf5cd7872007-01-31 21:43:54 -0600988
989 /* Free resources */
990 pasemi_mac_free_rx_resources(dev);
991 pasemi_mac_free_tx_resources(dev);
992
993 return 0;
994}
995
996static int pasemi_mac_start_tx(struct sk_buff *skb, struct net_device *dev)
997{
998 struct pasemi_mac *mac = netdev_priv(dev);
999 struct pasemi_mac_txring *txring;
Olof Johansson26fcfa92007-08-22 09:12:59 -05001000 u64 dflags, mactx, ptr;
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001001 dma_addr_t map;
Olof Johanssonca7e2352007-09-26 16:23:59 -05001002 unsigned long flags;
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001003
1004 dflags = XCT_MACTX_O | XCT_MACTX_ST | XCT_MACTX_SS | XCT_MACTX_CRC_PAD;
1005
1006 if (skb->ip_summed == CHECKSUM_PARTIAL) {
Arnaldo Carvalho de Melod56f90a2007-04-10 20:50:43 -07001007 const unsigned char *nh = skb_network_header(skb);
1008
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -07001009 switch (ip_hdr(skb)->protocol) {
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001010 case IPPROTO_TCP:
1011 dflags |= XCT_MACTX_CSUM_TCP;
Arnaldo Carvalho de Melocfe1fc72007-03-16 17:26:39 -03001012 dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
Arnaldo Carvalho de Melod56f90a2007-04-10 20:50:43 -07001013 dflags |= XCT_MACTX_IPO(nh - skb->data);
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001014 break;
1015 case IPPROTO_UDP:
1016 dflags |= XCT_MACTX_CSUM_UDP;
Arnaldo Carvalho de Melocfe1fc72007-03-16 17:26:39 -03001017 dflags |= XCT_MACTX_IPH(skb_network_header_len(skb) >> 2);
Arnaldo Carvalho de Melod56f90a2007-04-10 20:50:43 -07001018 dflags |= XCT_MACTX_IPO(nh - skb->data);
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001019 break;
1020 }
1021 }
1022
1023 map = pci_map_single(mac->dma_pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
1024
1025 if (dma_mapping_error(map))
1026 return NETDEV_TX_BUSY;
1027
Olof Johansson26fcfa92007-08-22 09:12:59 -05001028 mactx = dflags | XCT_MACTX_LLEN(skb->len);
1029 ptr = XCT_PTR_LEN(skb->len) | XCT_PTR_ADDR(map);
1030
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001031 txring = mac->tx;
1032
1033 spin_lock_irqsave(&txring->lock, flags);
1034
Olof Johanssonfc9e4d22007-10-02 16:25:53 -05001035 if (RING_AVAIL(txring) <= 2) {
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001036 spin_unlock_irqrestore(&txring->lock, flags);
1037 pasemi_mac_clean_tx(mac);
Olof Johansson52a94352007-05-12 18:01:09 -05001038 pasemi_mac_restart_tx_intr(mac);
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001039 spin_lock_irqsave(&txring->lock, flags);
1040
Olof Johanssonfc9e4d22007-10-02 16:25:53 -05001041 if (RING_AVAIL(txring) <= 2) {
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001042 /* Still no room -- stop the queue and wait for tx
1043 * intr when there's room.
1044 */
1045 netif_stop_queue(dev);
1046 goto out_err;
1047 }
1048 }
1049
Olof Johanssonfc9e4d22007-10-02 16:25:53 -05001050 TX_RING(mac, txring->next_to_fill) = mactx;
1051 TX_RING(mac, txring->next_to_fill+1) = ptr;
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001052
Olof Johanssonfc9e4d22007-10-02 16:25:53 -05001053 TX_RING_INFO(mac, txring->next_to_fill+1).dma = map;
1054 TX_RING_INFO(mac, txring->next_to_fill+1).skb = skb;
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001055
Olof Johanssonfc9e4d22007-10-02 16:25:53 -05001056 txring->next_to_fill += 2;
1057
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001058 dev->stats.tx_packets++;
1059 dev->stats.tx_bytes += skb->len;
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001060
1061 spin_unlock_irqrestore(&txring->lock, flags);
1062
Olof Johanssona85b9422007-09-15 13:40:59 -07001063 write_dma_reg(mac, PAS_DMA_TXCHAN_INCR(mac->dma_txch), 1);
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001064
1065 return NETDEV_TX_OK;
1066
1067out_err:
1068 spin_unlock_irqrestore(&txring->lock, flags);
1069 pci_unmap_single(mac->dma_pdev, map, skb->len, PCI_DMA_TODEVICE);
1070 return NETDEV_TX_BUSY;
1071}
1072
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001073static void pasemi_mac_set_rx_mode(struct net_device *dev)
1074{
1075 struct pasemi_mac *mac = netdev_priv(dev);
1076 unsigned int flags;
1077
Olof Johanssona85b9422007-09-15 13:40:59 -07001078 flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001079
1080 /* Set promiscuous */
1081 if (dev->flags & IFF_PROMISC)
1082 flags |= PAS_MAC_CFG_PCFG_PR;
1083 else
1084 flags &= ~PAS_MAC_CFG_PCFG_PR;
1085
Olof Johanssona85b9422007-09-15 13:40:59 -07001086 write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001087}
1088
1089
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001090static int pasemi_mac_poll(struct napi_struct *napi, int budget)
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001091{
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001092 struct pasemi_mac *mac = container_of(napi, struct pasemi_mac, napi);
1093 struct net_device *dev = mac->netdev;
1094 int pkts;
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001095
Olof Johansson829185e2007-09-15 13:53:19 -07001096 pasemi_mac_clean_tx(mac);
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001097 pkts = pasemi_mac_clean_rx(mac, budget);
1098 if (pkts < budget) {
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001099 /* all done, no more packets present */
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001100 netif_rx_complete(dev, napi);
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001101
Olof Johansson1b0335ea2007-05-08 00:47:26 -05001102 pasemi_mac_restart_rx_intr(mac);
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001103 }
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001104 return pkts;
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001105}
1106
Olof Johanssonb6e05a12007-09-15 13:44:07 -07001107static void __iomem * __devinit map_onedev(struct pci_dev *p, int index)
1108{
1109 struct device_node *dn;
1110 void __iomem *ret;
1111
1112 dn = pci_device_to_OF_node(p);
1113 if (!dn)
1114 goto fallback;
1115
1116 ret = of_iomap(dn, index);
1117 if (!ret)
1118 goto fallback;
1119
1120 return ret;
1121fallback:
1122 /* This is hardcoded and ugly, but we have some firmware versions
1123 * that don't provide the register space in the device tree. Luckily
1124 * they are at well-known locations so we can just do the math here.
1125 */
1126 return ioremap(0xe0000000 + (p->devfn << 12), 0x2000);
1127}
1128
1129static int __devinit pasemi_mac_map_regs(struct pasemi_mac *mac)
1130{
1131 struct resource res;
1132 struct device_node *dn;
1133 int err;
1134
1135 mac->dma_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa007, NULL);
1136 if (!mac->dma_pdev) {
1137 dev_err(&mac->pdev->dev, "Can't find DMA Controller\n");
1138 return -ENODEV;
1139 }
1140
1141 mac->iob_pdev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa001, NULL);
1142 if (!mac->iob_pdev) {
1143 dev_err(&mac->pdev->dev, "Can't find I/O Bridge\n");
1144 return -ENODEV;
1145 }
1146
1147 mac->regs = map_onedev(mac->pdev, 0);
1148 mac->dma_regs = map_onedev(mac->dma_pdev, 0);
1149 mac->iob_regs = map_onedev(mac->iob_pdev, 0);
1150
1151 if (!mac->regs || !mac->dma_regs || !mac->iob_regs) {
1152 dev_err(&mac->pdev->dev, "Can't map registers\n");
1153 return -ENODEV;
1154 }
1155
1156 /* The dma status structure is located in the I/O bridge, and
1157 * is cache coherent.
1158 */
1159 if (!dma_status) {
1160 dn = pci_device_to_OF_node(mac->iob_pdev);
1161 if (dn)
1162 err = of_address_to_resource(dn, 1, &res);
1163 if (!dn || err) {
1164 /* Fallback for old firmware */
1165 res.start = 0xfd800000;
1166 res.end = res.start + 0x1000;
1167 }
1168 dma_status = __ioremap(res.start, res.end-res.start, 0);
1169 }
1170
1171 return 0;
1172}
1173
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001174static int __devinit
1175pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1176{
1177 static int index = 0;
1178 struct net_device *dev;
1179 struct pasemi_mac *mac;
1180 int err;
Joe Perches0795af52007-10-03 17:59:30 -07001181 DECLARE_MAC_BUF(mac_buf);
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001182
1183 err = pci_enable_device(pdev);
1184 if (err)
1185 return err;
1186
1187 dev = alloc_etherdev(sizeof(struct pasemi_mac));
1188 if (dev == NULL) {
1189 dev_err(&pdev->dev,
1190 "pasemi_mac: Could not allocate ethernet device.\n");
1191 err = -ENOMEM;
1192 goto out_disable_device;
1193 }
1194
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001195 pci_set_drvdata(pdev, dev);
1196 SET_NETDEV_DEV(dev, &pdev->dev);
1197
1198 mac = netdev_priv(dev);
1199
1200 mac->pdev = pdev;
1201 mac->netdev = dev;
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001202
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001203 netif_napi_add(dev, &mac->napi, pasemi_mac_poll, 64);
1204
Olof Johansson6fba8482007-09-15 13:51:11 -07001205 dev->features = NETIF_F_HW_CSUM | NETIF_F_LLTX;
Stephen Hemmingerbea33482007-10-03 16:41:36 -07001206
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001207 /* These should come out of the device tree eventually */
1208 mac->dma_txch = index;
1209 mac->dma_rxch = index;
1210
1211 /* We probe GMAC before XAUI, but the DMA interfaces are
1212 * in XAUI, GMAC order.
1213 */
1214 if (index < 4)
1215 mac->dma_if = index + 2;
1216 else
1217 mac->dma_if = index - 4;
1218 index++;
1219
1220 switch (pdev->device) {
1221 case 0xa005:
1222 mac->type = MAC_TYPE_GMAC;
1223 break;
1224 case 0xa006:
1225 mac->type = MAC_TYPE_XAUI;
1226 break;
1227 default:
1228 err = -ENODEV;
1229 goto out;
1230 }
1231
1232 /* get mac addr from device tree */
1233 if (pasemi_get_mac_addr(mac) || !is_valid_ether_addr(mac->mac_addr)) {
1234 err = -ENODEV;
1235 goto out;
1236 }
1237 memcpy(dev->dev_addr, mac->mac_addr, sizeof(mac->mac_addr));
1238
1239 dev->open = pasemi_mac_open;
1240 dev->stop = pasemi_mac_close;
1241 dev->hard_start_xmit = pasemi_mac_start_tx;
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001242 dev->set_multicast_list = pasemi_mac_set_rx_mode;
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001243
Olof Johanssonb6e05a12007-09-15 13:44:07 -07001244 err = pasemi_mac_map_regs(mac);
1245 if (err)
1246 goto out;
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001247
1248 mac->rx_status = &dma_status->rx_sta[mac->dma_rxch];
1249 mac->tx_status = &dma_status->tx_sta[mac->dma_txch];
1250
Olof Johanssonceb51362007-05-08 00:47:49 -05001251 mac->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE);
1252
Olof Johanssonbb6e9592007-05-08 00:47:54 -05001253 /* Enable most messages by default */
1254 mac->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
1255
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001256 err = register_netdev(dev);
1257
1258 if (err) {
1259 dev_err(&mac->pdev->dev, "register_netdev failed with error %d\n",
1260 err);
1261 goto out;
Olof Johansson69c29d82007-10-02 16:24:51 -05001262 } else if netif_msg_probe(mac)
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001263 printk(KERN_INFO "%s: PA Semi %s: intf %d, txch %d, rxch %d, "
Joe Perches0795af52007-10-03 17:59:30 -07001264 "hw addr %s\n",
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001265 dev->name, mac->type == MAC_TYPE_GMAC ? "GMAC" : "XAUI",
1266 mac->dma_if, mac->dma_txch, mac->dma_rxch,
Joe Perches0795af52007-10-03 17:59:30 -07001267 print_mac(mac_buf, dev->dev_addr));
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001268
1269 return err;
1270
1271out:
Olof Johanssonb6e05a12007-09-15 13:44:07 -07001272 if (mac->iob_pdev)
1273 pci_dev_put(mac->iob_pdev);
1274 if (mac->dma_pdev)
1275 pci_dev_put(mac->dma_pdev);
1276 if (mac->dma_regs)
1277 iounmap(mac->dma_regs);
1278 if (mac->iob_regs)
1279 iounmap(mac->iob_regs);
1280 if (mac->regs)
1281 iounmap(mac->regs);
1282
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001283 free_netdev(dev);
1284out_disable_device:
1285 pci_disable_device(pdev);
1286 return err;
1287
1288}
1289
1290static void __devexit pasemi_mac_remove(struct pci_dev *pdev)
1291{
1292 struct net_device *netdev = pci_get_drvdata(pdev);
1293 struct pasemi_mac *mac;
1294
1295 if (!netdev)
1296 return;
1297
1298 mac = netdev_priv(netdev);
1299
1300 unregister_netdev(netdev);
1301
1302 pci_disable_device(pdev);
1303 pci_dev_put(mac->dma_pdev);
1304 pci_dev_put(mac->iob_pdev);
1305
Olof Johanssonb6e05a12007-09-15 13:44:07 -07001306 iounmap(mac->regs);
1307 iounmap(mac->dma_regs);
1308 iounmap(mac->iob_regs);
1309
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001310 pci_set_drvdata(pdev, NULL);
1311 free_netdev(netdev);
1312}
1313
1314static struct pci_device_id pasemi_mac_pci_tbl[] = {
1315 { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa005) },
1316 { PCI_DEVICE(PCI_VENDOR_ID_PASEMI, 0xa006) },
olof@lixom.netfd178252007-05-12 14:57:36 -05001317 { },
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001318};
1319
1320MODULE_DEVICE_TABLE(pci, pasemi_mac_pci_tbl);
1321
1322static struct pci_driver pasemi_mac_driver = {
1323 .name = "pasemi_mac",
1324 .id_table = pasemi_mac_pci_tbl,
1325 .probe = pasemi_mac_probe,
1326 .remove = __devexit_p(pasemi_mac_remove),
1327};
1328
1329static void __exit pasemi_mac_cleanup_module(void)
1330{
1331 pci_unregister_driver(&pasemi_mac_driver);
1332 __iounmap(dma_status);
1333 dma_status = NULL;
1334}
1335
1336int pasemi_mac_init_module(void)
1337{
1338 return pci_register_driver(&pasemi_mac_driver);
1339}
1340
Olof Johanssonf5cd7872007-01-31 21:43:54 -06001341module_init(pasemi_mac_init_module);
1342module_exit(pasemi_mac_cleanup_module);