| .. | .. |
|---|
| 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 | | - |
|---|