aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2008-01-23 14:56:47 -0500
committerDavid S. Miller <davem@davemloft.net>2008-02-03 07:27:54 -0500
commitef1ea0b424d09452b27f5cb1a0c108b645cb25e0 (patch)
tree71987b531b7dc1f00d9e0c7a34259444fc2088e9 /drivers
parent5cea73b0f7d4d49e276b0c4842465890d00de861 (diff)
pasemi_mac: add support for setting MTU
Currently keeping it at 1500 bytes or below since jumbo frames need special checksum offload on TX. Signed-off-by: Olof Johansson <olof@lixom.net> Signed-off-by: Jeff Garzik <jeff@garzik.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/pasemi_mac.c230
-rw-r--r--drivers/net/pasemi_mac.h14
2 files changed, 172 insertions, 72 deletions
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index 59dea3f829fc..059c6b04dc8f 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -62,6 +62,10 @@
62 62
63#define LRO_MAX_AGGR 64 63#define LRO_MAX_AGGR 64
64 64
65#define PE_MIN_MTU 64
66#define PE_MAX_MTU 1500
67#define PE_DEF_MTU ETH_DATA_LEN
68
65#define DEFAULT_MSG_ENABLE \ 69#define DEFAULT_MSG_ENABLE \
66 (NETIF_MSG_DRV | \ 70 (NETIF_MSG_DRV | \
67 NETIF_MSG_PROBE | \ 71 NETIF_MSG_PROBE | \
@@ -82,8 +86,6 @@
82 & ((ring)->size - 1)) 86 & ((ring)->size - 1))
83#define RING_AVAIL(ring) ((ring->size) - RING_USED(ring)) 87#define RING_AVAIL(ring) ((ring->size) - RING_USED(ring))
84 88
85#define BUF_SIZE 1646 /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
86
87MODULE_LICENSE("GPL"); 89MODULE_LICENSE("GPL");
88MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>"); 90MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
89MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver"); 91MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
@@ -175,6 +177,24 @@ static int mac_to_intf(struct pasemi_mac *mac)
175 return -1; 177 return -1;
176} 178}
177 179
180static void pasemi_mac_intf_disable(struct pasemi_mac *mac)
181{
182 unsigned int flags;
183
184 flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
185 flags &= ~PAS_MAC_CFG_PCFG_PE;
186 write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
187}
188
189static void pasemi_mac_intf_enable(struct pasemi_mac *mac)
190{
191 unsigned int flags;
192
193 flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
194 flags |= PAS_MAC_CFG_PCFG_PE;
195 write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
196}
197
178static int pasemi_get_mac_addr(struct pasemi_mac *mac) 198static int pasemi_get_mac_addr(struct pasemi_mac *mac)
179{ 199{
180 struct pci_dev *pdev = mac->pdev; 200 struct pci_dev *pdev = mac->pdev;
@@ -480,7 +500,7 @@ static void pasemi_mac_free_tx_resources(struct pasemi_mac *mac)
480 500
481} 501}
482 502
483static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac) 503static void pasemi_mac_free_rx_buffers(struct pasemi_mac *mac)
484{ 504{
485 struct pasemi_mac_rxring *rx = rx_ring(mac); 505 struct pasemi_mac_rxring *rx = rx_ring(mac);
486 unsigned int i; 506 unsigned int i;
@@ -500,7 +520,12 @@ static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac)
500 } 520 }
501 521
502 for (i = 0; i < RX_RING_SIZE; i++) 522 for (i = 0; i < RX_RING_SIZE; i++)
503 RX_DESC(rx, i) = 0; 523 RX_BUFF(rx, i) = 0;
524}
525
526static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac)
527{
528 pasemi_mac_free_rx_buffers(mac);
504 529
505 dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64), 530 dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64),
506 rx_ring(mac)->buffers, rx_ring(mac)->buf_dma); 531 rx_ring(mac)->buffers, rx_ring(mac)->buf_dma);
@@ -530,14 +555,14 @@ static void pasemi_mac_replenish_rx_ring(const struct net_device *dev,
530 /* Entry in use? */ 555 /* Entry in use? */
531 WARN_ON(*buff); 556 WARN_ON(*buff);
532 557
533 skb = dev_alloc_skb(BUF_SIZE); 558 skb = dev_alloc_skb(mac->bufsz);
534 skb_reserve(skb, LOCAL_SKB_ALIGN); 559 skb_reserve(skb, LOCAL_SKB_ALIGN);
535 560
536 if (unlikely(!skb)) 561 if (unlikely(!skb))
537 break; 562 break;
538 563
539 dma = pci_map_single(mac->dma_pdev, skb->data, 564 dma = pci_map_single(mac->dma_pdev, skb->data,
540 BUF_SIZE - LOCAL_SKB_ALIGN, 565 mac->bufsz - LOCAL_SKB_ALIGN,
541 PCI_DMA_FROMDEVICE); 566 PCI_DMA_FROMDEVICE);
542 567
543 if (unlikely(dma_mapping_error(dma))) { 568 if (unlikely(dma_mapping_error(dma))) {
@@ -547,7 +572,7 @@ static void pasemi_mac_replenish_rx_ring(const struct net_device *dev,
547 572
548 info->skb = skb; 573 info->skb = skb;
549 info->dma = dma; 574 info->dma = dma;
550 *buff = XCT_RXB_LEN(BUF_SIZE) | XCT_RXB_ADDR(dma); 575 *buff = XCT_RXB_LEN(mac->bufsz) | XCT_RXB_ADDR(dma);
551 fill++; 576 fill++;
552 } 577 }
553 578
@@ -677,7 +702,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac_rxring *rx,
677 702
678 len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S; 703 len = (macrx & XCT_MACRX_LLEN_M) >> XCT_MACRX_LLEN_S;
679 704
680 pci_unmap_single(pdev, dma, BUF_SIZE-LOCAL_SKB_ALIGN, 705 pci_unmap_single(pdev, dma, mac->bufsz - LOCAL_SKB_ALIGN,
681 PCI_DMA_FROMDEVICE); 706 PCI_DMA_FROMDEVICE);
682 707
683 if (macrx & XCT_MACRX_CRC) { 708 if (macrx & XCT_MACRX_CRC) {
@@ -901,24 +926,6 @@ static irqreturn_t pasemi_mac_tx_intr(int irq, void *data)
901 return IRQ_HANDLED; 926 return IRQ_HANDLED;
902} 927}
903 928
904static void pasemi_mac_intf_disable(struct pasemi_mac *mac)
905{
906 unsigned int flags;
907
908 flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
909 flags &= ~PAS_MAC_CFG_PCFG_PE;
910 write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
911}
912
913static void pasemi_mac_intf_enable(struct pasemi_mac *mac)
914{
915 unsigned int flags;
916
917 flags = read_mac_reg(mac, PAS_MAC_CFG_PCFG);
918 flags |= PAS_MAC_CFG_PCFG_PE;
919 write_mac_reg(mac, PAS_MAC_CFG_PCFG, flags);
920}
921
922static void pasemi_adjust_link(struct net_device *dev) 929static void pasemi_adjust_link(struct net_device *dev)
923{ 930{
924 struct pasemi_mac *mac = netdev_priv(dev); 931 struct pasemi_mac *mac = netdev_priv(dev);
@@ -1175,11 +1182,71 @@ out_rx_resources:
1175 1182
1176#define MAX_RETRIES 5000 1183#define MAX_RETRIES 5000
1177 1184
1185static void pasemi_mac_pause_txchan(struct pasemi_mac *mac)
1186{
1187 unsigned int sta, retries;
1188 int txch = tx_ring(mac)->chan.chno;
1189
1190 write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch),
1191 PAS_DMA_TXCHAN_TCMDSTA_ST);
1192
1193 for (retries = 0; retries < MAX_RETRIES; retries++) {
1194 sta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch));
1195 if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT))
1196 break;
1197 cond_resched();
1198 }
1199
1200 if (sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)
1201 dev_err(&mac->dma_pdev->dev,
1202 "Failed to stop tx channel, tcmdsta %08x\n", sta);
1203
1204 write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch), 0);
1205}
1206
1207static void pasemi_mac_pause_rxchan(struct pasemi_mac *mac)
1208{
1209 unsigned int sta, retries;
1210 int rxch = rx_ring(mac)->chan.chno;
1211
1212 write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch),
1213 PAS_DMA_RXCHAN_CCMDSTA_ST);
1214 for (retries = 0; retries < MAX_RETRIES; retries++) {
1215 sta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch));
1216 if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT))
1217 break;
1218 cond_resched();
1219 }
1220
1221 if (sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)
1222 dev_err(&mac->dma_pdev->dev,
1223 "Failed to stop rx channel, ccmdsta 08%x\n", sta);
1224 write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch), 0);
1225}
1226
1227static void pasemi_mac_pause_rxint(struct pasemi_mac *mac)
1228{
1229 unsigned int sta, retries;
1230
1231 write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
1232 PAS_DMA_RXINT_RCMDSTA_ST);
1233 for (retries = 0; retries < MAX_RETRIES; retries++) {
1234 sta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
1235 if (!(sta & PAS_DMA_RXINT_RCMDSTA_ACT))
1236 break;
1237 cond_resched();
1238 }
1239
1240 if (sta & PAS_DMA_RXINT_RCMDSTA_ACT)
1241 dev_err(&mac->dma_pdev->dev,
1242 "Failed to stop rx interface, rcmdsta %08x\n", sta);
1243 write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
1244}
1245
1178static int pasemi_mac_close(struct net_device *dev) 1246static int pasemi_mac_close(struct net_device *dev)
1179{ 1247{
1180 struct pasemi_mac *mac = netdev_priv(dev); 1248 struct pasemi_mac *mac = netdev_priv(dev);
1181 unsigned int sta; 1249 unsigned int sta;
1182 int retries;
1183 int rxch, txch; 1250 int rxch, txch;
1184 1251
1185 rxch = rx_ring(mac)->chan.chno; 1252 rxch = rx_ring(mac)->chan.chno;
@@ -1217,51 +1284,9 @@ static int pasemi_mac_close(struct net_device *dev)
1217 pasemi_mac_clean_tx(tx_ring(mac)); 1284 pasemi_mac_clean_tx(tx_ring(mac));
1218 pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE); 1285 pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
1219 1286
1220 /* Disable interface */ 1287 pasemi_mac_pause_txchan(mac);
1221 write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch), 1288 pasemi_mac_pause_rxint(mac);
1222 PAS_DMA_TXCHAN_TCMDSTA_ST); 1289 pasemi_mac_pause_rxchan(mac);
1223 write_dma_reg( PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
1224 PAS_DMA_RXINT_RCMDSTA_ST);
1225 write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch),
1226 PAS_DMA_RXCHAN_CCMDSTA_ST);
1227
1228 for (retries = 0; retries < MAX_RETRIES; retries++) {
1229 sta = read_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(rxch));
1230 if (!(sta & PAS_DMA_TXCHAN_TCMDSTA_ACT))
1231 break;
1232 cond_resched();
1233 }
1234
1235 if (sta & PAS_DMA_TXCHAN_TCMDSTA_ACT)
1236 dev_err(&mac->dma_pdev->dev, "Failed to stop tx channel\n");
1237
1238 for (retries = 0; retries < MAX_RETRIES; retries++) {
1239 sta = read_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch));
1240 if (!(sta & PAS_DMA_RXCHAN_CCMDSTA_ACT))
1241 break;
1242 cond_resched();
1243 }
1244
1245 if (sta & PAS_DMA_RXCHAN_CCMDSTA_ACT)
1246 dev_err(&mac->dma_pdev->dev, "Failed to stop rx channel\n");
1247
1248 for (retries = 0; retries < MAX_RETRIES; retries++) {
1249 sta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
1250 if (!(sta & PAS_DMA_RXINT_RCMDSTA_ACT))
1251 break;
1252 cond_resched();
1253 }
1254
1255 if (sta & PAS_DMA_RXINT_RCMDSTA_ACT)
1256 dev_err(&mac->dma_pdev->dev, "Failed to stop rx interface\n");
1257
1258 /* Then, disable the channel. This must be done separately from
1259 * stopping, since you can't disable when active.
1260 */
1261
1262 write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch), 0);
1263 write_dma_reg(PAS_DMA_RXCHAN_CCMDSTA(rxch), 0);
1264 write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if), 0);
1265 1290
1266 free_irq(mac->tx->chan.irq, mac->tx); 1291 free_irq(mac->tx->chan.irq, mac->tx);
1267 free_irq(mac->rx->chan.irq, mac->rx); 1292 free_irq(mac->rx->chan.irq, mac->rx);
@@ -1415,6 +1440,62 @@ static int pasemi_mac_poll(struct napi_struct *napi, int budget)
1415 return pkts; 1440 return pkts;
1416} 1441}
1417 1442
1443static int pasemi_mac_change_mtu(struct net_device *dev, int new_mtu)
1444{
1445 struct pasemi_mac *mac = netdev_priv(dev);
1446 unsigned int reg;
1447 unsigned int rcmdsta;
1448 int running;
1449
1450 if (new_mtu < PE_MIN_MTU || new_mtu > PE_MAX_MTU)
1451 return -EINVAL;
1452
1453 running = netif_running(dev);
1454
1455 if (running) {
1456 /* Need to stop the interface, clean out all already
1457 * received buffers, free all unused buffers on the RX
1458 * interface ring, then finally re-fill the rx ring with
1459 * the new-size buffers and restart.
1460 */
1461
1462 napi_disable(&mac->napi);
1463 netif_tx_disable(dev);
1464 pasemi_mac_intf_disable(mac);
1465
1466 rcmdsta = read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if));
1467 pasemi_mac_pause_rxint(mac);
1468 pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
1469 pasemi_mac_free_rx_buffers(mac);
1470 }
1471
1472 /* Change maxf, i.e. what size frames are accepted.
1473 * Need room for ethernet header and CRC word
1474 */
1475 reg = read_mac_reg(mac, PAS_MAC_CFG_MACCFG);
1476 reg &= ~PAS_MAC_CFG_MACCFG_MAXF_M;
1477 reg |= PAS_MAC_CFG_MACCFG_MAXF(new_mtu + ETH_HLEN + 4);
1478 write_mac_reg(mac, PAS_MAC_CFG_MACCFG, reg);
1479
1480 dev->mtu = new_mtu;
1481 /* MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
1482 mac->bufsz = new_mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
1483
1484 if (running) {
1485 write_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if),
1486 rcmdsta | PAS_DMA_RXINT_RCMDSTA_EN);
1487
1488 rx_ring(mac)->next_to_fill = 0;
1489 pasemi_mac_replenish_rx_ring(dev, RX_RING_SIZE-1);
1490
1491 napi_enable(&mac->napi);
1492 netif_start_queue(dev);
1493 pasemi_mac_intf_enable(mac);
1494 }
1495
1496 return 0;
1497}
1498
1418static int __devinit 1499static int __devinit
1419pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 1500pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1420{ 1501{
@@ -1503,6 +1584,11 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1503 dev->hard_start_xmit = pasemi_mac_start_tx; 1584 dev->hard_start_xmit = pasemi_mac_start_tx;
1504 dev->set_multicast_list = pasemi_mac_set_rx_mode; 1585 dev->set_multicast_list = pasemi_mac_set_rx_mode;
1505 dev->set_mac_address = pasemi_mac_set_mac_addr; 1586 dev->set_mac_address = pasemi_mac_set_mac_addr;
1587 dev->mtu = PE_DEF_MTU;
1588 /* 1500 MTU + ETH_HLEN + VLAN_HLEN + 2 64B cachelines */
1589 mac->bufsz = dev->mtu + ETH_HLEN + ETH_FCS_LEN + LOCAL_SKB_ALIGN + 128;
1590
1591 dev->change_mtu = pasemi_mac_change_mtu;
1506 1592
1507 if (err) 1593 if (err)
1508 goto out; 1594 goto out;
diff --git a/drivers/net/pasemi_mac.h b/drivers/net/pasemi_mac.h
index 39d325940a76..99e7b9329a6f 100644
--- a/drivers/net/pasemi_mac.h
+++ b/drivers/net/pasemi_mac.h
@@ -59,6 +59,7 @@ struct pasemi_mac {
59 struct phy_device *phydev; 59 struct phy_device *phydev;
60 struct napi_struct napi; 60 struct napi_struct napi;
61 61
62 int bufsz; /* RX ring buffer size */
62 u8 type; 63 u8 type;
63#define MAC_TYPE_GMAC 1 64#define MAC_TYPE_GMAC 1
64#define MAC_TYPE_XAUI 2 65#define MAC_TYPE_XAUI 2
@@ -96,6 +97,7 @@ struct pasemi_mac_buffer {
96/* MAC CFG register offsets */ 97/* MAC CFG register offsets */
97enum { 98enum {
98 PAS_MAC_CFG_PCFG = 0x80, 99 PAS_MAC_CFG_PCFG = 0x80,
100 PAS_MAC_CFG_MACCFG = 0x84,
99 PAS_MAC_CFG_ADR0 = 0x8c, 101 PAS_MAC_CFG_ADR0 = 0x8c,
100 PAS_MAC_CFG_ADR1 = 0x90, 102 PAS_MAC_CFG_ADR1 = 0x90,
101 PAS_MAC_CFG_TXP = 0x98, 103 PAS_MAC_CFG_TXP = 0x98,
@@ -132,6 +134,18 @@ enum {
132#define PAS_MAC_CFG_PCFG_SPD_100M 0x00000001 134#define PAS_MAC_CFG_PCFG_SPD_100M 0x00000001
133#define PAS_MAC_CFG_PCFG_SPD_1G 0x00000002 135#define PAS_MAC_CFG_PCFG_SPD_1G 0x00000002
134#define PAS_MAC_CFG_PCFG_SPD_10G 0x00000003 136#define PAS_MAC_CFG_PCFG_SPD_10G 0x00000003
137
138#define PAS_MAC_CFG_MACCFG_TXT_M 0x70000000
139#define PAS_MAC_CFG_MACCFG_TXT_S 28
140#define PAS_MAC_CFG_MACCFG_PRES_M 0x0f000000
141#define PAS_MAC_CFG_MACCFG_PRES_S 24
142#define PAS_MAC_CFG_MACCFG_MAXF_M 0x00ffff00
143#define PAS_MAC_CFG_MACCFG_MAXF_S 8
144#define PAS_MAC_CFG_MACCFG_MAXF(x) (((x) << PAS_MAC_CFG_MACCFG_MAXF_S) & \
145 PAS_MAC_CFG_MACCFG_MAXF_M)
146#define PAS_MAC_CFG_MACCFG_MINF_M 0x000000ff
147#define PAS_MAC_CFG_MACCFG_MINF_S 0
148
135#define PAS_MAC_CFG_TXP_FCF 0x01000000 149#define PAS_MAC_CFG_TXP_FCF 0x01000000
136#define PAS_MAC_CFG_TXP_FCE 0x00800000 150#define PAS_MAC_CFG_TXP_FCE 0x00800000
137#define PAS_MAC_CFG_TXP_FC 0x00400000 151#define PAS_MAC_CFG_TXP_FC 0x00400000