.. | .. |
---|
16 | 16 | #include <linux/interrupt.h> |
---|
17 | 17 | #include <linux/ip.h> |
---|
18 | 18 | #include <linux/tcp.h> |
---|
19 | | -#include <linux/skbuff.h> |
---|
20 | 19 | #include <linux/ethtool.h> |
---|
21 | 20 | #include <linux/if_ether.h> |
---|
22 | 21 | #include <linux/crc32.h> |
---|
.. | .. |
---|
45 | 44 | |
---|
46 | 45 | #define DRIVER_NAME "rockchip_gmac_uio_drv" |
---|
47 | 46 | #define DRIVER_VERSION "0.1" |
---|
48 | | -#define STMMAC_ALIGN(x) ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16) |
---|
49 | 47 | |
---|
50 | 48 | #define TC_DEFAULT 64 |
---|
51 | | -#define DEFAULT_BUFSIZE 1536 |
---|
52 | | -#define STMMAC_RX_COPYBREAK 256 |
---|
53 | | - |
---|
54 | | -static int buf_sz = DEFAULT_BUFSIZE; |
---|
55 | 49 | static int tc = TC_DEFAULT; |
---|
| 50 | + |
---|
| 51 | +#define DEFAULT_BUFSIZE 1536 |
---|
| 52 | +static int buf_sz = DEFAULT_BUFSIZE; |
---|
| 53 | + |
---|
| 54 | +#define STMMAC_RX_COPYBREAK 256 |
---|
56 | 55 | |
---|
57 | 56 | /** |
---|
58 | 57 | * rockchip_gmac_uio_pdev_info |
---|
.. | .. |
---|
120 | 119 | |
---|
121 | 120 | /* Free DMA regions of consistent memory previously allocated */ |
---|
122 | 121 | if (!priv->extend_desc) |
---|
123 | | - dma_free_coherent(priv->device, |
---|
124 | | - DMA_RX_SIZE * sizeof(struct dma_desc), |
---|
| 122 | + dma_free_coherent(priv->device, priv->dma_rx_size * |
---|
| 123 | + sizeof(struct dma_desc), |
---|
125 | 124 | rx_q->dma_rx, rx_q->dma_rx_phy); |
---|
126 | 125 | else |
---|
127 | | - dma_free_coherent(priv->device, DMA_RX_SIZE * |
---|
| 126 | + dma_free_coherent(priv->device, priv->dma_rx_size * |
---|
128 | 127 | sizeof(struct dma_extended_desc), |
---|
129 | 128 | rx_q->dma_erx, rx_q->dma_rx_phy); |
---|
130 | 129 | } |
---|
.. | .. |
---|
142 | 141 | /* Free TX queue resources */ |
---|
143 | 142 | for (queue = 0; queue < tx_count; queue++) { |
---|
144 | 143 | struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; |
---|
| 144 | + size_t size; |
---|
| 145 | + void *addr; |
---|
145 | 146 | |
---|
146 | | - /* Free DMA regions of consistent memory previously allocated */ |
---|
147 | | - if (!priv->extend_desc) |
---|
148 | | - dma_free_coherent(priv->device, |
---|
149 | | - DMA_TX_SIZE * sizeof(struct dma_desc), |
---|
150 | | - tx_q->dma_tx, tx_q->dma_tx_phy); |
---|
151 | | - else |
---|
152 | | - dma_free_coherent(priv->device, DMA_TX_SIZE * |
---|
153 | | - sizeof(struct dma_extended_desc), |
---|
154 | | - tx_q->dma_etx, tx_q->dma_tx_phy); |
---|
| 147 | + if (priv->extend_desc) { |
---|
| 148 | + size = sizeof(struct dma_extended_desc); |
---|
| 149 | + addr = tx_q->dma_etx; |
---|
| 150 | + } else if (tx_q->tbs & STMMAC_TBS_AVAIL) { |
---|
| 151 | + size = sizeof(struct dma_edesc); |
---|
| 152 | + addr = tx_q->dma_entx; |
---|
| 153 | + } else { |
---|
| 154 | + size = sizeof(struct dma_desc); |
---|
| 155 | + addr = tx_q->dma_tx; |
---|
| 156 | + } |
---|
| 157 | + |
---|
| 158 | + size *= priv->dma_tx_size; |
---|
| 159 | + |
---|
| 160 | + dma_free_coherent(priv->device, size, addr, tx_q->dma_tx_phy); |
---|
155 | 161 | } |
---|
156 | 162 | } |
---|
157 | 163 | |
---|
.. | .. |
---|
173 | 179 | for (queue = 0; queue < rx_count; queue++) { |
---|
174 | 180 | struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; |
---|
175 | 181 | |
---|
176 | | - rx_q->queue_index = queue; |
---|
177 | | - rx_q->priv_data = priv; |
---|
178 | | - |
---|
179 | 182 | if (priv->extend_desc) { |
---|
180 | | - rx_q->dma_erx = dma_zalloc_coherent(priv->device, |
---|
181 | | - DMA_RX_SIZE * |
---|
182 | | - sizeof(struct |
---|
183 | | - dma_extended_desc), |
---|
184 | | - &rx_q->dma_rx_phy, |
---|
185 | | - GFP_KERNEL); |
---|
186 | | - if (!rx_q->dma_erx) |
---|
187 | | - goto err_dma; |
---|
188 | | - |
---|
189 | | - } else { |
---|
190 | | - rx_q->dma_rx = dma_zalloc_coherent(priv->device, |
---|
191 | | - DMA_RX_SIZE * |
---|
192 | | - sizeof(struct |
---|
193 | | - dma_desc), |
---|
| 183 | + rx_q->dma_erx = dma_alloc_coherent(priv->device, |
---|
| 184 | + priv->dma_rx_size * |
---|
| 185 | + sizeof(struct dma_extended_desc), |
---|
194 | 186 | &rx_q->dma_rx_phy, |
---|
195 | 187 | GFP_KERNEL); |
---|
| 188 | + if (!rx_q->dma_erx) |
---|
| 189 | + goto err_dma; |
---|
| 190 | + } else { |
---|
| 191 | + rx_q->dma_rx = dma_alloc_coherent(priv->device, |
---|
| 192 | + priv->dma_rx_size * |
---|
| 193 | + sizeof(struct dma_desc), |
---|
| 194 | + &rx_q->dma_rx_phy, |
---|
| 195 | + GFP_KERNEL); |
---|
196 | 196 | if (!rx_q->dma_rx) |
---|
197 | 197 | goto err_dma; |
---|
198 | 198 | } |
---|
.. | .. |
---|
223 | 223 | /* TX queues buffers and DMA */ |
---|
224 | 224 | for (queue = 0; queue < tx_count; queue++) { |
---|
225 | 225 | struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; |
---|
| 226 | + size_t size; |
---|
| 227 | + void *addr; |
---|
226 | 228 | |
---|
227 | 229 | tx_q->queue_index = queue; |
---|
228 | 230 | tx_q->priv_data = priv; |
---|
229 | 231 | |
---|
230 | | - if (priv->extend_desc) { |
---|
231 | | - tx_q->dma_etx = dma_zalloc_coherent(priv->device, |
---|
232 | | - DMA_TX_SIZE * |
---|
233 | | - sizeof(struct |
---|
234 | | - dma_extended_desc), |
---|
235 | | - &tx_q->dma_tx_phy, |
---|
236 | | - GFP_KERNEL); |
---|
237 | | - if (!tx_q->dma_etx) |
---|
238 | | - goto err_dma; |
---|
239 | | - } else { |
---|
240 | | - tx_q->dma_tx = dma_zalloc_coherent(priv->device, |
---|
241 | | - DMA_TX_SIZE * |
---|
242 | | - sizeof(struct |
---|
243 | | - dma_desc), |
---|
244 | | - &tx_q->dma_tx_phy, |
---|
245 | | - GFP_KERNEL); |
---|
246 | | - if (!tx_q->dma_tx) |
---|
247 | | - goto err_dma; |
---|
248 | | - } |
---|
| 232 | + if (priv->extend_desc) |
---|
| 233 | + size = sizeof(struct dma_extended_desc); |
---|
| 234 | + else if (tx_q->tbs & STMMAC_TBS_AVAIL) |
---|
| 235 | + size = sizeof(struct dma_edesc); |
---|
| 236 | + else |
---|
| 237 | + size = sizeof(struct dma_desc); |
---|
| 238 | + |
---|
| 239 | + size *= priv->dma_tx_size; |
---|
| 240 | + |
---|
| 241 | + addr = dma_alloc_coherent(priv->device, size, |
---|
| 242 | + &tx_q->dma_tx_phy, GFP_KERNEL); |
---|
| 243 | + if (!addr) |
---|
| 244 | + goto err_dma; |
---|
| 245 | + |
---|
| 246 | + if (priv->extend_desc) |
---|
| 247 | + tx_q->dma_etx = addr; |
---|
| 248 | + else if (tx_q->tbs & STMMAC_TBS_AVAIL) |
---|
| 249 | + tx_q->dma_entx = addr; |
---|
| 250 | + else |
---|
| 251 | + tx_q->dma_tx = addr; |
---|
249 | 252 | } |
---|
250 | 253 | |
---|
251 | 254 | return 0; |
---|
252 | 255 | |
---|
253 | 256 | err_dma: |
---|
254 | 257 | uio_free_dma_tx_desc_resources(priv); |
---|
255 | | - |
---|
256 | 258 | return ret; |
---|
257 | 259 | } |
---|
258 | 260 | |
---|
.. | .. |
---|
291 | 293 | } |
---|
292 | 294 | |
---|
293 | 295 | /** |
---|
294 | | - * uio_hw_fix_mac_speed - callback for speed selection |
---|
295 | | - * @priv: driver private structure |
---|
296 | | - * Description: on some platforms (e.g. ST), some HW system configuration |
---|
297 | | - * registers have to be set according to the link speed negotiated. |
---|
298 | | - */ |
---|
299 | | -static inline void uio_hw_fix_mac_speed(struct stmmac_priv *priv) |
---|
300 | | -{ |
---|
301 | | - struct net_device *ndev = priv->dev; |
---|
302 | | - struct phy_device *phydev = ndev->phydev; |
---|
303 | | - |
---|
304 | | - if (likely(priv->plat->fix_mac_speed)) |
---|
305 | | - priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed); |
---|
306 | | -} |
---|
307 | | - |
---|
308 | | -/** |
---|
309 | | - * uio_mac_flow_ctrl - Configure flow control in all queues |
---|
310 | | - * @priv: driver private structure |
---|
311 | | - * Description: It is used for configuring the flow control in all queues |
---|
312 | | - */ |
---|
313 | | -static void uio_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex) |
---|
314 | | -{ |
---|
315 | | - u32 tx_cnt = priv->plat->tx_queues_to_use; |
---|
316 | | - |
---|
317 | | - stmmac_flow_ctrl(priv, priv->hw, duplex, priv->flow_ctrl, |
---|
318 | | - priv->pause, tx_cnt); |
---|
319 | | -} |
---|
320 | | - |
---|
321 | | -/** |
---|
322 | | - * uio_adjust_link - adjusts the link parameters |
---|
323 | | - * @dev: net device structure |
---|
324 | | - * Description: this is the helper called by the physical abstraction layer |
---|
325 | | - * drivers to communicate the phy link status. According the speed and duplex |
---|
326 | | - * this driver can invoke registered glue-logic as well. |
---|
327 | | - * It also invoke the eee initialization because it could happen when switch |
---|
328 | | - * on different networks (that are eee capable). |
---|
329 | | - */ |
---|
330 | | -static void uio_adjust_link(struct net_device *dev) |
---|
331 | | -{ |
---|
332 | | - struct stmmac_priv *priv = netdev_priv(dev); |
---|
333 | | - struct phy_device *phydev = dev->phydev; |
---|
334 | | - bool new_state = false; |
---|
335 | | - |
---|
336 | | - if (!phydev) |
---|
337 | | - return; |
---|
338 | | - |
---|
339 | | - mutex_lock(&priv->lock); |
---|
340 | | - |
---|
341 | | - if (phydev->link) { |
---|
342 | | - u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG); |
---|
343 | | - |
---|
344 | | - /* Now we make sure that we can be in full duplex mode. |
---|
345 | | - * If not, we operate in half-duplex mode. |
---|
346 | | - */ |
---|
347 | | - if (phydev->duplex != priv->oldduplex) { |
---|
348 | | - new_state = true; |
---|
349 | | - if (!phydev->duplex) |
---|
350 | | - ctrl &= ~priv->hw->link.duplex; |
---|
351 | | - else |
---|
352 | | - ctrl |= priv->hw->link.duplex; |
---|
353 | | - priv->oldduplex = phydev->duplex; |
---|
354 | | - } |
---|
355 | | - /* Flow Control operation */ |
---|
356 | | - if (phydev->pause) |
---|
357 | | - uio_mac_flow_ctrl(priv, phydev->duplex); |
---|
358 | | - |
---|
359 | | - if (phydev->speed != priv->speed) { |
---|
360 | | - new_state = true; |
---|
361 | | - ctrl &= ~priv->hw->link.speed_mask; |
---|
362 | | - switch (phydev->speed) { |
---|
363 | | - case SPEED_1000: |
---|
364 | | - ctrl |= priv->hw->link.speed1000; |
---|
365 | | - break; |
---|
366 | | - case SPEED_100: |
---|
367 | | - ctrl |= priv->hw->link.speed100; |
---|
368 | | - break; |
---|
369 | | - case SPEED_10: |
---|
370 | | - ctrl |= priv->hw->link.speed10; |
---|
371 | | - break; |
---|
372 | | - default: |
---|
373 | | - netif_warn(priv, link, priv->dev, |
---|
374 | | - "broken speed: %d\n", phydev->speed); |
---|
375 | | - phydev->speed = SPEED_UNKNOWN; |
---|
376 | | - break; |
---|
377 | | - } |
---|
378 | | - if (phydev->speed != SPEED_UNKNOWN) |
---|
379 | | - uio_hw_fix_mac_speed(priv); |
---|
380 | | - priv->speed = phydev->speed; |
---|
381 | | - } |
---|
382 | | - |
---|
383 | | - writel(ctrl, priv->ioaddr + MAC_CTRL_REG); |
---|
384 | | - |
---|
385 | | - if (!priv->oldlink) { |
---|
386 | | - new_state = true; |
---|
387 | | - priv->oldlink = true; |
---|
388 | | - } |
---|
389 | | - } else if (priv->oldlink) { |
---|
390 | | - new_state = true; |
---|
391 | | - priv->oldlink = false; |
---|
392 | | - priv->speed = SPEED_UNKNOWN; |
---|
393 | | - priv->oldduplex = DUPLEX_UNKNOWN; |
---|
394 | | - } |
---|
395 | | - |
---|
396 | | - if (new_state && netif_msg_link(priv)) |
---|
397 | | - phy_print_status(phydev); |
---|
398 | | - |
---|
399 | | - mutex_unlock(&priv->lock); |
---|
400 | | - |
---|
401 | | - if (phydev->is_pseudo_fixed_link) |
---|
402 | | - /* Stop PHY layer to call the hook to adjust the link in case |
---|
403 | | - * of a switch is attached to the stmmac driver. |
---|
404 | | - */ |
---|
405 | | - phydev->irq = PHY_IGNORE_INTERRUPT; |
---|
406 | | -} |
---|
407 | | - |
---|
408 | | -/** |
---|
409 | 296 | * rockchip_gmac_uio_init_phy - PHY initialization |
---|
410 | 297 | * @dev: net device structure |
---|
411 | 298 | * Description: it initializes the driver's PHY state, and attaches the PHY |
---|
.. | .. |
---|
416 | 303 | static int rockchip_gmac_uio_init_phy(struct net_device *dev) |
---|
417 | 304 | { |
---|
418 | 305 | struct stmmac_priv *priv = netdev_priv(dev); |
---|
419 | | - u32 tx_cnt = priv->plat->tx_queues_to_use; |
---|
420 | | - struct phy_device *phydev; |
---|
421 | | - char phy_id_fmt[MII_BUS_ID_SIZE + 3]; |
---|
422 | | - char bus_id[MII_BUS_ID_SIZE]; |
---|
423 | | - int interface = priv->plat->interface; |
---|
424 | | - int max_speed = priv->plat->max_speed; |
---|
| 306 | + struct device_node *node; |
---|
| 307 | + int ret; |
---|
425 | 308 | |
---|
426 | | - priv->oldlink = false; |
---|
427 | | - priv->speed = SPEED_UNKNOWN; |
---|
428 | | - priv->oldduplex = DUPLEX_UNKNOWN; |
---|
| 309 | + node = priv->plat->phylink_node; |
---|
429 | 310 | |
---|
430 | | - if (priv->plat->integrated_phy_power) |
---|
431 | | - priv->plat->integrated_phy_power(priv->plat->bsp_priv, true); |
---|
| 311 | + if (node) |
---|
| 312 | + ret = phylink_of_phy_connect(priv->phylink, node, 0); |
---|
432 | 313 | |
---|
433 | | - if (priv->mii) |
---|
434 | | - stmmac_mdio_reset(priv->mii); |
---|
| 314 | + /* Some DT bindings do not set-up the PHY handle. Let's try to |
---|
| 315 | + * manually parse it |
---|
| 316 | + */ |
---|
| 317 | + if (!node || ret) { |
---|
| 318 | + int addr = priv->plat->phy_addr; |
---|
| 319 | + struct phy_device *phydev; |
---|
435 | 320 | |
---|
436 | | - if (priv->plat->phy_node) { |
---|
437 | | - phydev = of_phy_connect(dev, priv->plat->phy_node, |
---|
438 | | - &uio_adjust_link, 0, interface); |
---|
439 | | - } else { |
---|
440 | | - snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", |
---|
441 | | - priv->plat->bus_id); |
---|
442 | | - |
---|
443 | | - snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, |
---|
444 | | - priv->plat->phy_addr); |
---|
445 | | - netdev_dbg(priv->dev, "%s: trying to attach to %s\n", __func__, |
---|
446 | | - phy_id_fmt); |
---|
447 | | - |
---|
448 | | - phydev = phy_connect(dev, phy_id_fmt, &uio_adjust_link, |
---|
449 | | - interface); |
---|
450 | | - } |
---|
451 | | - |
---|
452 | | - if (IS_ERR_OR_NULL(phydev)) { |
---|
453 | | - netdev_err(priv->dev, "Could not attach to PHY\n"); |
---|
454 | | - if (!phydev) |
---|
| 321 | + phydev = mdiobus_get_phy(priv->mii, addr); |
---|
| 322 | + if (!phydev) { |
---|
| 323 | + netdev_err(priv->dev, "no phy at addr %d\n", addr); |
---|
455 | 324 | return -ENODEV; |
---|
| 325 | + } |
---|
456 | 326 | |
---|
457 | | - return PTR_ERR(phydev); |
---|
| 327 | + ret = phylink_connect_phy(priv->phylink, phydev); |
---|
458 | 328 | } |
---|
459 | 329 | |
---|
460 | | - /* Stop Advertising 1000BASE Capability if interface is not GMII */ |
---|
461 | | - if (interface == PHY_INTERFACE_MODE_MII || |
---|
462 | | - interface == PHY_INTERFACE_MODE_RMII || |
---|
463 | | - (max_speed < 1000 && max_speed > 0)) |
---|
464 | | - phydev->advertising &= ~(SUPPORTED_1000baseT_Half | |
---|
465 | | - SUPPORTED_1000baseT_Full); |
---|
| 330 | + if (!priv->plat->pmt) { |
---|
| 331 | + struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; |
---|
466 | 332 | |
---|
467 | | - /* Half-duplex mode not supported with multiqueue |
---|
468 | | - * half-duplex can only works with single queue |
---|
469 | | - */ |
---|
470 | | - if (tx_cnt > 1) |
---|
471 | | - phydev->supported &= ~(SUPPORTED_1000baseT_Half | |
---|
472 | | - SUPPORTED_100baseT_Half | |
---|
473 | | - SUPPORTED_10baseT_Half); |
---|
474 | | - |
---|
475 | | - /* Broken HW is sometimes missing the pull-up resistor on the |
---|
476 | | - * MDIO line, which results in reads to non-existent devices returning |
---|
477 | | - * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent |
---|
478 | | - * device as well. |
---|
479 | | - * Note: phydev->phy_id is the result of reading the UID PHY registers. |
---|
480 | | - */ |
---|
481 | | - if (!priv->plat->phy_node && phydev->phy_id == 0) { |
---|
482 | | - phy_disconnect(phydev); |
---|
483 | | - return -ENODEV; |
---|
| 333 | + phylink_ethtool_get_wol(priv->phylink, &wol); |
---|
| 334 | + device_set_wakeup_capable(priv->device, !!wol.supported); |
---|
484 | 335 | } |
---|
485 | 336 | |
---|
486 | | - /* uio_adjust_link will change this to PHY_IGNORE_INTERRUPT to avoid |
---|
487 | | - * subsequent PHY polling, make sure we force a link transition if |
---|
488 | | - * we have a UP/DOWN/UP transition |
---|
489 | | - */ |
---|
490 | | - if (phydev->is_pseudo_fixed_link) |
---|
491 | | - phydev->irq = PHY_POLL; |
---|
492 | | - |
---|
493 | | - phy_attached_info(phydev); |
---|
494 | | - return 0; |
---|
| 337 | + return ret; |
---|
495 | 338 | } |
---|
496 | 339 | |
---|
497 | 340 | /** |
---|
.. | .. |
---|
545 | 388 | rx_q->dma_rx_phy, chan); |
---|
546 | 389 | |
---|
547 | 390 | rx_q->rx_tail_addr = rx_q->dma_rx_phy + |
---|
548 | | - (DMA_RX_SIZE * sizeof(struct dma_desc)); |
---|
| 391 | + (priv->dma_rx_size * |
---|
| 392 | + sizeof(struct dma_desc)); |
---|
549 | 393 | stmmac_set_rx_tail_ptr(priv, priv->ioaddr, |
---|
550 | 394 | rx_q->rx_tail_addr, chan); |
---|
551 | 395 | } |
---|
.. | .. |
---|
574 | 418 | /* set TX ring length */ |
---|
575 | 419 | for (chan = 0; chan < tx_channels_count; chan++) |
---|
576 | 420 | stmmac_set_tx_ring_len(priv, priv->ioaddr, |
---|
577 | | - (DMA_TX_SIZE - 1), chan); |
---|
| 421 | + (priv->dma_tx_size - 1), chan); |
---|
578 | 422 | |
---|
579 | 423 | /* set RX ring length */ |
---|
580 | 424 | for (chan = 0; chan < rx_channels_count; chan++) |
---|
581 | 425 | stmmac_set_rx_ring_len(priv, priv->ioaddr, |
---|
582 | | - (DMA_RX_SIZE - 1), chan); |
---|
| 426 | + (priv->dma_rx_size - 1), chan); |
---|
583 | 427 | } |
---|
584 | 428 | |
---|
585 | 429 | /** |
---|
.. | .. |
---|
617 | 461 | continue; |
---|
618 | 462 | |
---|
619 | 463 | stmmac_config_cbs(priv, priv->hw, |
---|
620 | | - priv->plat->tx_queues_cfg[queue].send_slope, |
---|
621 | | - priv->plat->tx_queues_cfg[queue].idle_slope, |
---|
622 | | - priv->plat->tx_queues_cfg[queue].high_credit, |
---|
623 | | - priv->plat->tx_queues_cfg[queue].low_credit, |
---|
624 | | - queue); |
---|
| 464 | + priv->plat->tx_queues_cfg[queue].send_slope, |
---|
| 465 | + priv->plat->tx_queues_cfg[queue].idle_slope, |
---|
| 466 | + priv->plat->tx_queues_cfg[queue].high_credit, |
---|
| 467 | + priv->plat->tx_queues_cfg[queue].low_credit, |
---|
| 468 | + queue); |
---|
625 | 469 | } |
---|
626 | 470 | } |
---|
627 | 471 | |
---|
.. | .. |
---|
703 | 547 | } |
---|
704 | 548 | } |
---|
705 | 549 | |
---|
| 550 | +static void uio_mac_config_rss(struct stmmac_priv *priv) |
---|
| 551 | +{ |
---|
| 552 | + if (!priv->dma_cap.rssen || !priv->plat->rss_en) { |
---|
| 553 | + priv->rss.enable = false; |
---|
| 554 | + return; |
---|
| 555 | + } |
---|
| 556 | + |
---|
| 557 | + if (priv->dev->features & NETIF_F_RXHASH) |
---|
| 558 | + priv->rss.enable = true; |
---|
| 559 | + else |
---|
| 560 | + priv->rss.enable = false; |
---|
| 561 | + |
---|
| 562 | + stmmac_rss_configure(priv, priv->hw, &priv->rss, |
---|
| 563 | + priv->plat->rx_queues_to_use); |
---|
| 564 | +} |
---|
| 565 | + |
---|
706 | 566 | /** |
---|
707 | 567 | * uio_mac_enable_rx_queues - Enable MAC rx queues |
---|
708 | 568 | * @priv: driver private structure |
---|
.. | .. |
---|
764 | 624 | /* Set RX routing */ |
---|
765 | 625 | if (rx_queues_count > 1) |
---|
766 | 626 | uio_mac_config_rx_queues_routing(priv); |
---|
| 627 | + |
---|
| 628 | + /* Receive Side Scaling */ |
---|
| 629 | + if (rx_queues_count > 1) |
---|
| 630 | + uio_mac_config_rss(priv); |
---|
767 | 631 | } |
---|
768 | 632 | |
---|
769 | 633 | static void uio_safety_feat_configuration(struct stmmac_priv *priv) |
---|
770 | 634 | { |
---|
771 | 635 | if (priv->dma_cap.asp) { |
---|
772 | 636 | netdev_info(priv->dev, "Enabling Safety Features\n"); |
---|
773 | | - stmmac_safety_feat_config(priv, priv->ioaddr, |
---|
774 | | - priv->dma_cap.asp); |
---|
| 637 | + stmmac_safety_feat_config(priv, priv->ioaddr, priv->dma_cap.asp); |
---|
775 | 638 | } else { |
---|
776 | 639 | netdev_info(priv->dev, "No Safety Features support found\n"); |
---|
777 | 640 | } |
---|
.. | .. |
---|
840 | 703 | } |
---|
841 | 704 | |
---|
842 | 705 | /** |
---|
843 | | - * rockchip_gmac_uio_mmc_setup: setup the Mac Management Counters (MMC) |
---|
844 | | - * @priv: driver private structure |
---|
845 | | - * Description: this masks the MMC irq, in fact, the counters are managed in SW. |
---|
846 | | - */ |
---|
847 | | -static void rockchip_gmac_uio_mmc_setup(struct stmmac_priv *priv) |
---|
848 | | -{ |
---|
849 | | - unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET | |
---|
850 | | - MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET; |
---|
851 | | - |
---|
852 | | - dwmac_mmc_intr_all_mask(priv->mmcaddr); |
---|
853 | | - |
---|
854 | | - if (priv->dma_cap.rmon) { |
---|
855 | | - dwmac_mmc_ctrl(priv->mmcaddr, mode); |
---|
856 | | - memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); |
---|
857 | | - } else { |
---|
858 | | - netdev_info(priv->dev, "No MAC Management Counters available\n"); |
---|
859 | | - } |
---|
860 | | -} |
---|
861 | | - |
---|
862 | | -/** |
---|
863 | 706 | * rockchip_gmac_uio_hw_setup - setup mac in a usable state. |
---|
864 | 707 | * @dev : pointer to the device structure. |
---|
865 | 708 | * @init_ptp: initialize PTP if set |
---|
.. | .. |
---|
923 | 766 | /* Set the HW DMA mode and the COE */ |
---|
924 | 767 | uio_dma_operation_mode(priv); |
---|
925 | 768 | |
---|
926 | | - rockchip_gmac_uio_mmc_setup(priv); |
---|
927 | | - |
---|
928 | 769 | if (priv->hw->pcs) |
---|
929 | 770 | stmmac_pcs_ctrl_ane(priv, priv->hw, 1, priv->hw->ps, 0); |
---|
930 | 771 | |
---|
931 | 772 | /* set TX and RX rings length */ |
---|
932 | 773 | uio_set_rings_length(priv); |
---|
| 774 | + |
---|
| 775 | + return 0; |
---|
| 776 | +} |
---|
| 777 | + |
---|
| 778 | +static int uio_set_bfsize(int mtu, int bufsize) |
---|
| 779 | +{ |
---|
| 780 | + int ret = bufsize; |
---|
| 781 | + |
---|
| 782 | + if (mtu >= BUF_SIZE_8KiB) |
---|
| 783 | + ret = BUF_SIZE_16KiB; |
---|
| 784 | + else if (mtu >= BUF_SIZE_4KiB) |
---|
| 785 | + ret = BUF_SIZE_8KiB; |
---|
| 786 | + else if (mtu >= BUF_SIZE_2KiB) |
---|
| 787 | + ret = BUF_SIZE_4KiB; |
---|
| 788 | + else if (mtu > DEFAULT_BUFSIZE) |
---|
| 789 | + ret = BUF_SIZE_2KiB; |
---|
| 790 | + else |
---|
| 791 | + ret = DEFAULT_BUFSIZE; |
---|
933 | 792 | |
---|
934 | 793 | return ret; |
---|
935 | 794 | } |
---|
.. | .. |
---|
946 | 805 | static int uio_open(struct net_device *dev) |
---|
947 | 806 | { |
---|
948 | 807 | struct stmmac_priv *priv = netdev_priv(dev); |
---|
| 808 | + int bfsize = 0; |
---|
949 | 809 | int ret; |
---|
950 | 810 | |
---|
951 | | - if (priv->hw->pcs != STMMAC_PCS_RGMII && |
---|
952 | | - priv->hw->pcs != STMMAC_PCS_TBI && |
---|
953 | | - priv->hw->pcs != STMMAC_PCS_RTBI) { |
---|
| 811 | + if (priv->hw->pcs != STMMAC_PCS_TBI && |
---|
| 812 | + priv->hw->pcs != STMMAC_PCS_RTBI && |
---|
| 813 | + !priv->hw->xpcs) { |
---|
954 | 814 | ret = rockchip_gmac_uio_init_phy(dev); |
---|
955 | 815 | if (ret) { |
---|
956 | 816 | netdev_err(priv->dev, |
---|
.. | .. |
---|
961 | 821 | } |
---|
962 | 822 | |
---|
963 | 823 | /* Extra statistics */ |
---|
964 | | - memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats)); |
---|
965 | 824 | priv->xstats.threshold = tc; |
---|
966 | 825 | |
---|
967 | | - priv->dma_buf_sz = STMMAC_ALIGN(buf_sz); |
---|
| 826 | + bfsize = stmmac_set_16kib_bfsize(priv, dev->mtu); |
---|
| 827 | + if (bfsize < 0) |
---|
| 828 | + bfsize = 0; |
---|
| 829 | + |
---|
| 830 | + if (bfsize < BUF_SIZE_16KiB) |
---|
| 831 | + bfsize = uio_set_bfsize(dev->mtu, priv->dma_buf_sz); |
---|
| 832 | + |
---|
| 833 | + priv->dma_buf_sz = bfsize; |
---|
| 834 | + buf_sz = bfsize; |
---|
| 835 | + |
---|
968 | 836 | priv->rx_copybreak = STMMAC_RX_COPYBREAK; |
---|
| 837 | + |
---|
| 838 | + if (!priv->dma_tx_size) |
---|
| 839 | + priv->dma_tx_size = DMA_DEFAULT_TX_SIZE; |
---|
| 840 | + if (!priv->dma_rx_size) |
---|
| 841 | + priv->dma_rx_size = DMA_DEFAULT_RX_SIZE; |
---|
969 | 842 | |
---|
970 | 843 | ret = uio_alloc_dma_desc_resources(priv); |
---|
971 | 844 | if (ret < 0) { |
---|
.. | .. |
---|
980 | 853 | goto init_error; |
---|
981 | 854 | } |
---|
982 | 855 | |
---|
983 | | - if (dev->phydev) |
---|
984 | | - phy_start(dev->phydev); |
---|
| 856 | + phylink_start(priv->phylink); |
---|
| 857 | + /* We may have called phylink_speed_down before */ |
---|
| 858 | + phylink_speed_up(priv->phylink); |
---|
985 | 859 | |
---|
986 | 860 | return 0; |
---|
987 | 861 | |
---|
988 | 862 | init_error: |
---|
989 | 863 | uio_free_dma_desc_resources(priv); |
---|
990 | 864 | dma_desc_error: |
---|
991 | | - if (dev->phydev) |
---|
992 | | - phy_disconnect(dev->phydev); |
---|
| 865 | + phylink_disconnect_phy(priv->phylink); |
---|
993 | 866 | return ret; |
---|
994 | 867 | } |
---|
995 | 868 | |
---|
.. | .. |
---|
1091 | 964 | |
---|
1092 | 965 | uio->mem[1].name = "eth_rx_bd"; |
---|
1093 | 966 | uio->mem[1].addr = priv->rx_queue[0].dma_rx_phy; |
---|
1094 | | - uio->mem[1].size = DMA_RX_SIZE * sizeof(struct dma_desc); |
---|
| 967 | + uio->mem[1].size = priv->dma_rx_size * sizeof(struct dma_desc); |
---|
1095 | 968 | uio->mem[1].memtype = UIO_MEM_PHYS; |
---|
1096 | 969 | |
---|
1097 | 970 | uio->mem[2].name = "eth_tx_bd"; |
---|
1098 | 971 | uio->mem[2].addr = priv->tx_queue[0].dma_tx_phy; |
---|
1099 | | - uio->mem[2].size = DMA_TX_SIZE * sizeof(struct dma_desc); |
---|
| 972 | + uio->mem[2].size = priv->dma_tx_size * sizeof(struct dma_desc); |
---|
1100 | 973 | uio->mem[2].memtype = UIO_MEM_PHYS; |
---|
1101 | 974 | |
---|
1102 | 975 | uio->open = rockchip_gmac_uio_open; |
---|
.. | .. |
---|
1148 | 1021 | |
---|
1149 | 1022 | if (netdev) { |
---|
1150 | 1023 | rtnl_lock(); |
---|
1151 | | - dev_open(netdev); |
---|
| 1024 | + dev_open(netdev, NULL); |
---|
1152 | 1025 | rtnl_unlock(); |
---|
1153 | 1026 | } |
---|
1154 | 1027 | |
---|
.. | .. |
---|
1175 | 1048 | MODULE_LICENSE("GPL"); |
---|
1176 | 1049 | MODULE_AUTHOR("ROCKCHIP"); |
---|
1177 | 1050 | MODULE_DESCRIPTION("ROCKCHIP GMAC UIO Driver"); |
---|
1178 | | - |
---|