Commit ef1ea0b424d09452b27f5cb1a0c108b645cb25e0

Authored by Olof Johansson
Committed by David S. Miller
1 parent 5cea73b0f7

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>

Showing 2 changed files with 172 additions and 72 deletions Side-by-side Diff

drivers/net/pasemi_mac.c
... ... @@ -62,6 +62,10 @@
62 62  
63 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 69 #define DEFAULT_MSG_ENABLE \
66 70 (NETIF_MSG_DRV | \
67 71 NETIF_MSG_PROBE | \
... ... @@ -82,8 +86,6 @@
82 86 & ((ring)->size - 1))
83 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   -
87 89 MODULE_LICENSE("GPL");
88 90 MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
89 91 MODULE_DESCRIPTION("PA Semi PWRficient Ethernet driver");
... ... @@ -175,6 +177,24 @@
175 177 return -1;
176 178 }
177 179  
  180 +static 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 +
  189 +static 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 +
178 198 static int pasemi_get_mac_addr(struct pasemi_mac *mac)
179 199 {
180 200 struct pci_dev *pdev = mac->pdev;
... ... @@ -480,7 +500,7 @@
480 500  
481 501 }
482 502  
483   -static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac)
  503 +static void pasemi_mac_free_rx_buffers(struct pasemi_mac *mac)
484 504 {
485 505 struct pasemi_mac_rxring *rx = rx_ring(mac);
486 506 unsigned int i;
487 507  
... ... @@ -500,8 +520,13 @@
500 520 }
501 521  
502 522 for (i = 0; i < RX_RING_SIZE; i++)
503   - RX_DESC(rx, i) = 0;
  523 + RX_BUFF(rx, i) = 0;
  524 +}
504 525  
  526 +static void pasemi_mac_free_rx_resources(struct pasemi_mac *mac)
  527 +{
  528 + pasemi_mac_free_rx_buffers(mac);
  529 +
505 530 dma_free_coherent(&mac->dma_pdev->dev, RX_RING_SIZE * sizeof(u64),
506 531 rx_ring(mac)->buffers, rx_ring(mac)->buf_dma);
507 532  
508 533  
... ... @@ -530,14 +555,14 @@
530 555 /* Entry in use? */
531 556 WARN_ON(*buff);
532 557  
533   - skb = dev_alloc_skb(BUF_SIZE);
  558 + skb = dev_alloc_skb(mac->bufsz);
534 559 skb_reserve(skb, LOCAL_SKB_ALIGN);
535 560  
536 561 if (unlikely(!skb))
537 562 break;
538 563  
539 564 dma = pci_map_single(mac->dma_pdev, skb->data,
540   - BUF_SIZE - LOCAL_SKB_ALIGN,
  565 + mac->bufsz - LOCAL_SKB_ALIGN,
541 566 PCI_DMA_FROMDEVICE);
542 567  
543 568 if (unlikely(dma_mapping_error(dma))) {
... ... @@ -547,7 +572,7 @@
547 572  
548 573 info->skb = skb;
549 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 576 fill++;
552 577 }
553 578  
... ... @@ -677,7 +702,7 @@
677 702  
678 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 706 PCI_DMA_FROMDEVICE);
682 707  
683 708 if (macrx & XCT_MACRX_CRC) {
... ... @@ -901,24 +926,6 @@
901 926 return IRQ_HANDLED;
902 927 }
903 928  
904   -static 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   -
913   -static 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   -
922 929 static void pasemi_adjust_link(struct net_device *dev)
923 930 {
924 931 struct pasemi_mac *mac = netdev_priv(dev);
925 932  
... ... @@ -1175,11 +1182,71 @@
1175 1182  
1176 1183 #define MAX_RETRIES 5000
1177 1184  
  1185 +static 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 +
  1207 +static 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 +
  1227 +static 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 +
1178 1246 static int pasemi_mac_close(struct net_device *dev)
1179 1247 {
1180 1248 struct pasemi_mac *mac = netdev_priv(dev);
1181 1249 unsigned int sta;
1182   - int retries;
1183 1250 int rxch, txch;
1184 1251  
1185 1252 rxch = rx_ring(mac)->chan.chno;
1186 1253  
... ... @@ -1217,52 +1284,10 @@
1217 1284 pasemi_mac_clean_tx(tx_ring(mac));
1218 1285 pasemi_mac_clean_rx(rx_ring(mac), RX_RING_SIZE);
1219 1286  
1220   - /* Disable interface */
1221   - write_dma_reg(PAS_DMA_TXCHAN_TCMDSTA(txch),
1222   - PAS_DMA_TXCHAN_TCMDSTA_ST);
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);
  1287 + pasemi_mac_pause_txchan(mac);
  1288 + pasemi_mac_pause_rxint(mac);
  1289 + pasemi_mac_pause_rxchan(mac);
1227 1290  
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   -
1266 1291 free_irq(mac->tx->chan.irq, mac->tx);
1267 1292 free_irq(mac->rx->chan.irq, mac->rx);
1268 1293  
... ... @@ -1415,6 +1440,62 @@
1415 1440 return pkts;
1416 1441 }
1417 1442  
  1443 +static 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 +
1418 1499 static int __devinit
1419 1500 pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1420 1501 {
... ... @@ -1503,6 +1584,11 @@
1503 1584 dev->hard_start_xmit = pasemi_mac_start_tx;
1504 1585 dev->set_multicast_list = pasemi_mac_set_rx_mode;
1505 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 1593 if (err)
1508 1594 goto out;
drivers/net/pasemi_mac.h
... ... @@ -59,6 +59,7 @@
59 59 struct phy_device *phydev;
60 60 struct napi_struct napi;
61 61  
  62 + int bufsz; /* RX ring buffer size */
62 63 u8 type;
63 64 #define MAC_TYPE_GMAC 1
64 65 #define MAC_TYPE_XAUI 2
... ... @@ -96,6 +97,7 @@
96 97 /* MAC CFG register offsets */
97 98 enum {
98 99 PAS_MAC_CFG_PCFG = 0x80,
  100 + PAS_MAC_CFG_MACCFG = 0x84,
99 101 PAS_MAC_CFG_ADR0 = 0x8c,
100 102 PAS_MAC_CFG_ADR1 = 0x90,
101 103 PAS_MAC_CFG_TXP = 0x98,
... ... @@ -132,6 +134,18 @@
132 134 #define PAS_MAC_CFG_PCFG_SPD_100M 0x00000001
133 135 #define PAS_MAC_CFG_PCFG_SPD_1G 0x00000002
134 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 149 #define PAS_MAC_CFG_TXP_FCF 0x01000000
136 150 #define PAS_MAC_CFG_TXP_FCE 0x00800000
137 151 #define PAS_MAC_CFG_TXP_FC 0x00400000