| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * sonic.c |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 47 | 48 | |
|---|
| 48 | 49 | if (version_printed++ == 0) |
|---|
| 49 | 50 | netif_dbg(lp, drv, dev, "%s", version); |
|---|
| 51 | +} |
|---|
| 52 | + |
|---|
| 53 | +static int sonic_alloc_descriptors(struct net_device *dev) |
|---|
| 54 | +{ |
|---|
| 55 | + struct sonic_local *lp = netdev_priv(dev); |
|---|
| 56 | + |
|---|
| 57 | + /* Allocate a chunk of memory for the descriptors. Note that this |
|---|
| 58 | + * must not cross a 64K boundary. It is smaller than one page which |
|---|
| 59 | + * means that page alignment is a sufficient condition. |
|---|
| 60 | + */ |
|---|
| 61 | + lp->descriptors = |
|---|
| 62 | + dma_alloc_coherent(lp->device, |
|---|
| 63 | + SIZEOF_SONIC_DESC * |
|---|
| 64 | + SONIC_BUS_SCALE(lp->dma_bitmode), |
|---|
| 65 | + &lp->descriptors_laddr, GFP_KERNEL); |
|---|
| 66 | + |
|---|
| 67 | + if (!lp->descriptors) |
|---|
| 68 | + return -ENOMEM; |
|---|
| 69 | + |
|---|
| 70 | + lp->cda = lp->descriptors; |
|---|
| 71 | + lp->tda = lp->cda + SIZEOF_SONIC_CDA * |
|---|
| 72 | + SONIC_BUS_SCALE(lp->dma_bitmode); |
|---|
| 73 | + lp->rda = lp->tda + SIZEOF_SONIC_TD * SONIC_NUM_TDS * |
|---|
| 74 | + SONIC_BUS_SCALE(lp->dma_bitmode); |
|---|
| 75 | + lp->rra = lp->rda + SIZEOF_SONIC_RD * SONIC_NUM_RDS * |
|---|
| 76 | + SONIC_BUS_SCALE(lp->dma_bitmode); |
|---|
| 77 | + |
|---|
| 78 | + lp->cda_laddr = lp->descriptors_laddr; |
|---|
| 79 | + lp->tda_laddr = lp->cda_laddr + SIZEOF_SONIC_CDA * |
|---|
| 80 | + SONIC_BUS_SCALE(lp->dma_bitmode); |
|---|
| 81 | + lp->rda_laddr = lp->tda_laddr + SIZEOF_SONIC_TD * SONIC_NUM_TDS * |
|---|
| 82 | + SONIC_BUS_SCALE(lp->dma_bitmode); |
|---|
| 83 | + lp->rra_laddr = lp->rda_laddr + SIZEOF_SONIC_RD * SONIC_NUM_RDS * |
|---|
| 84 | + SONIC_BUS_SCALE(lp->dma_bitmode); |
|---|
| 85 | + |
|---|
| 86 | + return 0; |
|---|
| 50 | 87 | } |
|---|
| 51 | 88 | |
|---|
| 52 | 89 | /* |
|---|
| .. | .. |
|---|
| 106 | 143 | /* |
|---|
| 107 | 144 | * Initialize the SONIC |
|---|
| 108 | 145 | */ |
|---|
| 109 | | - sonic_init(dev); |
|---|
| 146 | + sonic_init(dev, true); |
|---|
| 110 | 147 | |
|---|
| 111 | 148 | netif_start_queue(dev); |
|---|
| 112 | 149 | |
|---|
| .. | .. |
|---|
| 116 | 153 | } |
|---|
| 117 | 154 | |
|---|
| 118 | 155 | /* Wait for the SONIC to become idle. */ |
|---|
| 119 | | -static void sonic_quiesce(struct net_device *dev, u16 mask) |
|---|
| 156 | +static void sonic_quiesce(struct net_device *dev, u16 mask, bool may_sleep) |
|---|
| 120 | 157 | { |
|---|
| 121 | 158 | struct sonic_local * __maybe_unused lp = netdev_priv(dev); |
|---|
| 122 | 159 | int i; |
|---|
| .. | .. |
|---|
| 126 | 163 | bits = SONIC_READ(SONIC_CMD) & mask; |
|---|
| 127 | 164 | if (!bits) |
|---|
| 128 | 165 | return; |
|---|
| 129 | | - if (irqs_disabled() || in_interrupt()) |
|---|
| 166 | + if (!may_sleep) |
|---|
| 130 | 167 | udelay(20); |
|---|
| 131 | 168 | else |
|---|
| 132 | 169 | usleep_range(100, 200); |
|---|
| .. | .. |
|---|
| 150 | 187 | * stop the SONIC, disable interrupts |
|---|
| 151 | 188 | */ |
|---|
| 152 | 189 | SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS); |
|---|
| 153 | | - sonic_quiesce(dev, SONIC_CR_ALL); |
|---|
| 190 | + sonic_quiesce(dev, SONIC_CR_ALL, true); |
|---|
| 154 | 191 | |
|---|
| 155 | 192 | SONIC_WRITE(SONIC_IMR, 0); |
|---|
| 156 | 193 | SONIC_WRITE(SONIC_ISR, 0x7fff); |
|---|
| .. | .. |
|---|
| 183 | 220 | return 0; |
|---|
| 184 | 221 | } |
|---|
| 185 | 222 | |
|---|
| 186 | | -static void sonic_tx_timeout(struct net_device *dev) |
|---|
| 223 | +static void sonic_tx_timeout(struct net_device *dev, unsigned int txqueue) |
|---|
| 187 | 224 | { |
|---|
| 188 | 225 | struct sonic_local *lp = netdev_priv(dev); |
|---|
| 189 | 226 | int i; |
|---|
| .. | .. |
|---|
| 192 | 229 | * disable all interrupts before releasing DMA buffers |
|---|
| 193 | 230 | */ |
|---|
| 194 | 231 | SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS); |
|---|
| 195 | | - sonic_quiesce(dev, SONIC_CR_ALL); |
|---|
| 232 | + sonic_quiesce(dev, SONIC_CR_ALL, false); |
|---|
| 196 | 233 | |
|---|
| 197 | 234 | SONIC_WRITE(SONIC_IMR, 0); |
|---|
| 198 | 235 | SONIC_WRITE(SONIC_ISR, 0x7fff); |
|---|
| .. | .. |
|---|
| 209 | 246 | } |
|---|
| 210 | 247 | } |
|---|
| 211 | 248 | /* Try to restart the adaptor. */ |
|---|
| 212 | | - sonic_init(dev); |
|---|
| 249 | + sonic_init(dev, false); |
|---|
| 213 | 250 | lp->stats.tx_errors++; |
|---|
| 214 | 251 | netif_trans_update(dev); /* prevent tx timeout */ |
|---|
| 215 | 252 | netif_wake_queue(dev); |
|---|
| .. | .. |
|---|
| 255 | 292 | */ |
|---|
| 256 | 293 | |
|---|
| 257 | 294 | laddr = dma_map_single(lp->device, skb->data, length, DMA_TO_DEVICE); |
|---|
| 258 | | - if (!laddr) { |
|---|
| 295 | + if (dma_mapping_error(lp->device, laddr)) { |
|---|
| 259 | 296 | pr_err_ratelimited("%s: failed to map tx DMA buffer.\n", dev->name); |
|---|
| 260 | 297 | dev_kfree_skb_any(skb); |
|---|
| 261 | 298 | return NETDEV_TX_OK; |
|---|
| .. | .. |
|---|
| 263 | 300 | |
|---|
| 264 | 301 | spin_lock_irqsave(&lp->lock, flags); |
|---|
| 265 | 302 | |
|---|
| 266 | | - entry = lp->next_tx; |
|---|
| 303 | + entry = (lp->eol_tx + 1) & SONIC_TDS_MASK; |
|---|
| 267 | 304 | |
|---|
| 268 | 305 | sonic_tda_put(dev, entry, SONIC_TD_STATUS, 0); /* clear status */ |
|---|
| 269 | 306 | sonic_tda_put(dev, entry, SONIC_TD_FRAG_COUNT, 1); /* single fragment */ |
|---|
| .. | .. |
|---|
| 274 | 311 | sonic_tda_put(dev, entry, SONIC_TD_LINK, |
|---|
| 275 | 312 | sonic_tda_get(dev, entry, SONIC_TD_LINK) | SONIC_EOL); |
|---|
| 276 | 313 | |
|---|
| 277 | | - wmb(); |
|---|
| 278 | | - lp->tx_len[entry] = length; |
|---|
| 279 | | - lp->tx_laddr[entry] = laddr; |
|---|
| 280 | | - lp->tx_skb[entry] = skb; |
|---|
| 281 | | - |
|---|
| 282 | | - wmb(); |
|---|
| 283 | | - sonic_tda_put(dev, lp->eol_tx, SONIC_TD_LINK, |
|---|
| 284 | | - sonic_tda_get(dev, lp->eol_tx, SONIC_TD_LINK) & ~SONIC_EOL); |
|---|
| 285 | | - lp->eol_tx = entry; |
|---|
| 286 | | - |
|---|
| 287 | | - lp->next_tx = (entry + 1) & SONIC_TDS_MASK; |
|---|
| 288 | | - if (lp->tx_skb[lp->next_tx] != NULL) { |
|---|
| 289 | | - /* The ring is full, the ISR has yet to process the next TD. */ |
|---|
| 290 | | - netif_dbg(lp, tx_queued, dev, "%s: stopping queue\n", __func__); |
|---|
| 291 | | - netif_stop_queue(dev); |
|---|
| 292 | | - /* after this packet, wait for ISR to free up some TDAs */ |
|---|
| 293 | | - } else netif_start_queue(dev); |
|---|
| 314 | + sonic_tda_put(dev, lp->eol_tx, SONIC_TD_LINK, ~SONIC_EOL & |
|---|
| 315 | + sonic_tda_get(dev, lp->eol_tx, SONIC_TD_LINK)); |
|---|
| 294 | 316 | |
|---|
| 295 | 317 | netif_dbg(lp, tx_queued, dev, "%s: issuing Tx command\n", __func__); |
|---|
| 296 | 318 | |
|---|
| 297 | 319 | SONIC_WRITE(SONIC_CMD, SONIC_CR_TXP); |
|---|
| 320 | + |
|---|
| 321 | + lp->tx_len[entry] = length; |
|---|
| 322 | + lp->tx_laddr[entry] = laddr; |
|---|
| 323 | + lp->tx_skb[entry] = skb; |
|---|
| 324 | + |
|---|
| 325 | + lp->eol_tx = entry; |
|---|
| 326 | + |
|---|
| 327 | + entry = (entry + 1) & SONIC_TDS_MASK; |
|---|
| 328 | + if (lp->tx_skb[entry]) { |
|---|
| 329 | + /* The ring is full, the ISR has yet to process the next TD. */ |
|---|
| 330 | + netif_dbg(lp, tx_queued, dev, "%s: stopping queue\n", __func__); |
|---|
| 331 | + netif_stop_queue(dev); |
|---|
| 332 | + /* after this packet, wait for ISR to free up some TDAs */ |
|---|
| 333 | + } |
|---|
| 298 | 334 | |
|---|
| 299 | 335 | spin_unlock_irqrestore(&lp->lock, flags); |
|---|
| 300 | 336 | |
|---|
| .. | .. |
|---|
| 370 | 406 | } |
|---|
| 371 | 407 | |
|---|
| 372 | 408 | /* We must free the original skb */ |
|---|
| 373 | | - dev_kfree_skb_irq(lp->tx_skb[entry]); |
|---|
| 409 | + dev_consume_skb_irq(lp->tx_skb[entry]); |
|---|
| 374 | 410 | lp->tx_skb[entry] = NULL; |
|---|
| 375 | 411 | /* and unmap DMA buffer */ |
|---|
| 376 | 412 | dma_unmap_single(lp->device, lp->tx_laddr[entry], lp->tx_len[entry], DMA_TO_DEVICE); |
|---|
| .. | .. |
|---|
| 473 | 509 | |
|---|
| 474 | 510 | *new_addr = dma_map_single(lp->device, skb_put(*new_skb, SONIC_RBSIZE), |
|---|
| 475 | 511 | SONIC_RBSIZE, DMA_FROM_DEVICE); |
|---|
| 476 | | - if (!*new_addr) { |
|---|
| 512 | + if (dma_mapping_error(lp->device, *new_addr)) { |
|---|
| 477 | 513 | dev_kfree_skb(*new_skb); |
|---|
| 478 | 514 | *new_skb = NULL; |
|---|
| 479 | 515 | return false; |
|---|
| .. | .. |
|---|
| 593 | 629 | |
|---|
| 594 | 630 | if (rbe) |
|---|
| 595 | 631 | SONIC_WRITE(SONIC_ISR, SONIC_INT_RBE); |
|---|
| 596 | | - /* |
|---|
| 597 | | - * If any worth-while packets have been received, netif_rx() |
|---|
| 598 | | - * has done a mark_bh(NET_BH) for us and will work on them |
|---|
| 599 | | - * when we get to the bottom-half routine. |
|---|
| 600 | | - */ |
|---|
| 601 | 632 | } |
|---|
| 602 | 633 | |
|---|
| 603 | 634 | |
|---|
| .. | .. |
|---|
| 661 | 692 | |
|---|
| 662 | 693 | /* LCAM and TXP commands can't be used simultaneously */ |
|---|
| 663 | 694 | spin_lock_irqsave(&lp->lock, flags); |
|---|
| 664 | | - sonic_quiesce(dev, SONIC_CR_TXP); |
|---|
| 695 | + sonic_quiesce(dev, SONIC_CR_TXP, false); |
|---|
| 665 | 696 | SONIC_WRITE(SONIC_CMD, SONIC_CR_LCAM); |
|---|
| 666 | | - sonic_quiesce(dev, SONIC_CR_LCAM); |
|---|
| 697 | + sonic_quiesce(dev, SONIC_CR_LCAM, false); |
|---|
| 667 | 698 | spin_unlock_irqrestore(&lp->lock, flags); |
|---|
| 668 | 699 | } |
|---|
| 669 | 700 | } |
|---|
| .. | .. |
|---|
| 677 | 708 | /* |
|---|
| 678 | 709 | * Initialize the SONIC ethernet controller. |
|---|
| 679 | 710 | */ |
|---|
| 680 | | -static int sonic_init(struct net_device *dev) |
|---|
| 711 | +static int sonic_init(struct net_device *dev, bool may_sleep) |
|---|
| 681 | 712 | { |
|---|
| 682 | 713 | struct sonic_local *lp = netdev_priv(dev); |
|---|
| 683 | 714 | int i; |
|---|
| .. | .. |
|---|
| 699 | 730 | */ |
|---|
| 700 | 731 | SONIC_WRITE(SONIC_CMD, 0); |
|---|
| 701 | 732 | SONIC_WRITE(SONIC_CMD, SONIC_CR_RXDIS | SONIC_CR_STP); |
|---|
| 702 | | - sonic_quiesce(dev, SONIC_CR_ALL); |
|---|
| 733 | + sonic_quiesce(dev, SONIC_CR_ALL, may_sleep); |
|---|
| 703 | 734 | |
|---|
| 704 | 735 | /* |
|---|
| 705 | 736 | * initialize the receive resource area |
|---|
| .. | .. |
|---|
| 728 | 759 | netif_dbg(lp, ifup, dev, "%s: issuing RRRA command\n", __func__); |
|---|
| 729 | 760 | |
|---|
| 730 | 761 | SONIC_WRITE(SONIC_CMD, SONIC_CR_RRRA); |
|---|
| 731 | | - sonic_quiesce(dev, SONIC_CR_RRRA); |
|---|
| 762 | + sonic_quiesce(dev, SONIC_CR_RRRA, may_sleep); |
|---|
| 732 | 763 | |
|---|
| 733 | 764 | /* |
|---|
| 734 | 765 | * Initialize the receive descriptors so that they |
|---|
| .. | .. |
|---|
| 779 | 810 | |
|---|
| 780 | 811 | SONIC_WRITE(SONIC_UTDA, lp->tda_laddr >> 16); |
|---|
| 781 | 812 | SONIC_WRITE(SONIC_CTDA, lp->tda_laddr & 0xffff); |
|---|
| 782 | | - lp->cur_tx = lp->next_tx = 0; |
|---|
| 813 | + lp->cur_tx = 0; |
|---|
| 783 | 814 | lp->eol_tx = SONIC_NUM_TDS - 1; |
|---|
| 784 | 815 | |
|---|
| 785 | 816 | /* |
|---|
| .. | .. |
|---|
| 803 | 834 | * load the CAM |
|---|
| 804 | 835 | */ |
|---|
| 805 | 836 | SONIC_WRITE(SONIC_CMD, SONIC_CR_LCAM); |
|---|
| 806 | | - sonic_quiesce(dev, SONIC_CR_LCAM); |
|---|
| 837 | + sonic_quiesce(dev, SONIC_CR_LCAM, may_sleep); |
|---|
| 807 | 838 | |
|---|
| 808 | 839 | /* |
|---|
| 809 | 840 | * enable receiver, disable loopback |
|---|