diff options
Diffstat (limited to 'drivers/net/skge.c')
| -rw-r--r-- | drivers/net/skge.c | 232 |
1 files changed, 136 insertions, 96 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 5ca5a1b546a1..536dd1cf7f79 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
| @@ -44,12 +44,13 @@ | |||
| 44 | #include "skge.h" | 44 | #include "skge.h" |
| 45 | 45 | ||
| 46 | #define DRV_NAME "skge" | 46 | #define DRV_NAME "skge" |
| 47 | #define DRV_VERSION "1.5" | 47 | #define DRV_VERSION "1.6" |
| 48 | #define PFX DRV_NAME " " | 48 | #define PFX DRV_NAME " " |
| 49 | 49 | ||
| 50 | #define DEFAULT_TX_RING_SIZE 128 | 50 | #define DEFAULT_TX_RING_SIZE 128 |
| 51 | #define DEFAULT_RX_RING_SIZE 512 | 51 | #define DEFAULT_RX_RING_SIZE 512 |
| 52 | #define MAX_TX_RING_SIZE 1024 | 52 | #define MAX_TX_RING_SIZE 1024 |
| 53 | #define TX_LOW_WATER (MAX_SKB_FRAGS + 1) | ||
| 53 | #define MAX_RX_RING_SIZE 4096 | 54 | #define MAX_RX_RING_SIZE 4096 |
| 54 | #define RX_COPY_THRESHOLD 128 | 55 | #define RX_COPY_THRESHOLD 128 |
| 55 | #define RX_BUF_SIZE 1536 | 56 | #define RX_BUF_SIZE 1536 |
| @@ -401,7 +402,7 @@ static int skge_set_ring_param(struct net_device *dev, | |||
| 401 | int err; | 402 | int err; |
| 402 | 403 | ||
| 403 | if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE || | 404 | if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE || |
| 404 | p->tx_pending < MAX_SKB_FRAGS+1 || p->tx_pending > MAX_TX_RING_SIZE) | 405 | p->tx_pending < TX_LOW_WATER || p->tx_pending > MAX_TX_RING_SIZE) |
| 405 | return -EINVAL; | 406 | return -EINVAL; |
| 406 | 407 | ||
| 407 | skge->rx_ring.count = p->rx_pending; | 408 | skge->rx_ring.count = p->rx_pending; |
| @@ -603,7 +604,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) | |||
| 603 | struct skge_hw *hw = skge->hw; | 604 | struct skge_hw *hw = skge->hw; |
| 604 | int port = skge->port; | 605 | int port = skge->port; |
| 605 | 606 | ||
| 606 | spin_lock_bh(&hw->phy_lock); | 607 | mutex_lock(&hw->phy_mutex); |
| 607 | if (hw->chip_id == CHIP_ID_GENESIS) { | 608 | if (hw->chip_id == CHIP_ID_GENESIS) { |
| 608 | switch (mode) { | 609 | switch (mode) { |
| 609 | case LED_MODE_OFF: | 610 | case LED_MODE_OFF: |
| @@ -663,7 +664,7 @@ static void skge_led(struct skge_port *skge, enum led_mode mode) | |||
| 663 | PHY_M_LED_MO_RX(MO_LED_ON)); | 664 | PHY_M_LED_MO_RX(MO_LED_ON)); |
| 664 | } | 665 | } |
| 665 | } | 666 | } |
| 666 | spin_unlock_bh(&hw->phy_lock); | 667 | mutex_unlock(&hw->phy_mutex); |
| 667 | } | 668 | } |
| 668 | 669 | ||
| 669 | /* blink LED's for finding board */ | 670 | /* blink LED's for finding board */ |
| @@ -2038,7 +2039,7 @@ static void skge_phy_reset(struct skge_port *skge) | |||
| 2038 | netif_stop_queue(skge->netdev); | 2039 | netif_stop_queue(skge->netdev); |
| 2039 | netif_carrier_off(skge->netdev); | 2040 | netif_carrier_off(skge->netdev); |
| 2040 | 2041 | ||
| 2041 | spin_lock_bh(&hw->phy_lock); | 2042 | mutex_lock(&hw->phy_mutex); |
| 2042 | if (hw->chip_id == CHIP_ID_GENESIS) { | 2043 | if (hw->chip_id == CHIP_ID_GENESIS) { |
| 2043 | genesis_reset(hw, port); | 2044 | genesis_reset(hw, port); |
| 2044 | genesis_mac_init(hw, port); | 2045 | genesis_mac_init(hw, port); |
| @@ -2046,7 +2047,7 @@ static void skge_phy_reset(struct skge_port *skge) | |||
| 2046 | yukon_reset(hw, port); | 2047 | yukon_reset(hw, port); |
| 2047 | yukon_init(hw, port); | 2048 | yukon_init(hw, port); |
| 2048 | } | 2049 | } |
| 2049 | spin_unlock_bh(&hw->phy_lock); | 2050 | mutex_unlock(&hw->phy_mutex); |
| 2050 | } | 2051 | } |
| 2051 | 2052 | ||
| 2052 | /* Basic MII support */ | 2053 | /* Basic MII support */ |
| @@ -2067,12 +2068,12 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 2067 | /* fallthru */ | 2068 | /* fallthru */ |
| 2068 | case SIOCGMIIREG: { | 2069 | case SIOCGMIIREG: { |
| 2069 | u16 val = 0; | 2070 | u16 val = 0; |
| 2070 | spin_lock_bh(&hw->phy_lock); | 2071 | mutex_lock(&hw->phy_mutex); |
| 2071 | if (hw->chip_id == CHIP_ID_GENESIS) | 2072 | if (hw->chip_id == CHIP_ID_GENESIS) |
| 2072 | err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); | 2073 | err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); |
| 2073 | else | 2074 | else |
| 2074 | err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); | 2075 | err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); |
| 2075 | spin_unlock_bh(&hw->phy_lock); | 2076 | mutex_unlock(&hw->phy_mutex); |
| 2076 | data->val_out = val; | 2077 | data->val_out = val; |
| 2077 | break; | 2078 | break; |
| 2078 | } | 2079 | } |
| @@ -2081,14 +2082,14 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 2081 | if (!capable(CAP_NET_ADMIN)) | 2082 | if (!capable(CAP_NET_ADMIN)) |
| 2082 | return -EPERM; | 2083 | return -EPERM; |
| 2083 | 2084 | ||
| 2084 | spin_lock_bh(&hw->phy_lock); | 2085 | mutex_lock(&hw->phy_mutex); |
| 2085 | if (hw->chip_id == CHIP_ID_GENESIS) | 2086 | if (hw->chip_id == CHIP_ID_GENESIS) |
| 2086 | err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f, | 2087 | err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f, |
| 2087 | data->val_in); | 2088 | data->val_in); |
| 2088 | else | 2089 | else |
| 2089 | err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f, | 2090 | err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f, |
| 2090 | data->val_in); | 2091 | data->val_in); |
| 2091 | spin_unlock_bh(&hw->phy_lock); | 2092 | mutex_unlock(&hw->phy_mutex); |
| 2092 | break; | 2093 | break; |
| 2093 | } | 2094 | } |
| 2094 | return err; | 2095 | return err; |
| @@ -2191,12 +2192,12 @@ static int skge_up(struct net_device *dev) | |||
| 2191 | goto free_rx_ring; | 2192 | goto free_rx_ring; |
| 2192 | 2193 | ||
| 2193 | /* Initialize MAC */ | 2194 | /* Initialize MAC */ |
| 2194 | spin_lock_bh(&hw->phy_lock); | 2195 | mutex_lock(&hw->phy_mutex); |
| 2195 | if (hw->chip_id == CHIP_ID_GENESIS) | 2196 | if (hw->chip_id == CHIP_ID_GENESIS) |
| 2196 | genesis_mac_init(hw, port); | 2197 | genesis_mac_init(hw, port); |
| 2197 | else | 2198 | else |
| 2198 | yukon_mac_init(hw, port); | 2199 | yukon_mac_init(hw, port); |
| 2199 | spin_unlock_bh(&hw->phy_lock); | 2200 | mutex_unlock(&hw->phy_mutex); |
| 2200 | 2201 | ||
| 2201 | /* Configure RAMbuffers */ | 2202 | /* Configure RAMbuffers */ |
| 2202 | chunk = hw->ram_size / ((hw->ports + 1)*2); | 2203 | chunk = hw->ram_size / ((hw->ports + 1)*2); |
| @@ -2302,21 +2303,20 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
| 2302 | { | 2303 | { |
| 2303 | struct skge_port *skge = netdev_priv(dev); | 2304 | struct skge_port *skge = netdev_priv(dev); |
| 2304 | struct skge_hw *hw = skge->hw; | 2305 | struct skge_hw *hw = skge->hw; |
| 2305 | struct skge_ring *ring = &skge->tx_ring; | ||
| 2306 | struct skge_element *e; | 2306 | struct skge_element *e; |
| 2307 | struct skge_tx_desc *td; | 2307 | struct skge_tx_desc *td; |
| 2308 | int i; | 2308 | int i; |
| 2309 | u32 control, len; | 2309 | u32 control, len; |
| 2310 | u64 map; | 2310 | u64 map; |
| 2311 | unsigned long flags; | ||
| 2311 | 2312 | ||
| 2312 | skb = skb_padto(skb, ETH_ZLEN); | 2313 | skb = skb_padto(skb, ETH_ZLEN); |
| 2313 | if (!skb) | 2314 | if (!skb) |
| 2314 | return NETDEV_TX_OK; | 2315 | return NETDEV_TX_OK; |
| 2315 | 2316 | ||
| 2316 | if (!spin_trylock(&skge->tx_lock)) { | 2317 | if (!spin_trylock_irqsave(&skge->tx_lock, flags)) |
| 2317 | /* Collision - tell upper layer to requeue */ | 2318 | /* Collision - tell upper layer to requeue */ |
| 2318 | return NETDEV_TX_LOCKED; | 2319 | return NETDEV_TX_LOCKED; |
| 2319 | } | ||
| 2320 | 2320 | ||
| 2321 | if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) { | 2321 | if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) { |
| 2322 | if (!netif_queue_stopped(dev)) { | 2322 | if (!netif_queue_stopped(dev)) { |
| @@ -2325,12 +2325,13 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
| 2325 | printk(KERN_WARNING PFX "%s: ring full when queue awake!\n", | 2325 | printk(KERN_WARNING PFX "%s: ring full when queue awake!\n", |
| 2326 | dev->name); | 2326 | dev->name); |
| 2327 | } | 2327 | } |
| 2328 | spin_unlock(&skge->tx_lock); | 2328 | spin_unlock_irqrestore(&skge->tx_lock, flags); |
| 2329 | return NETDEV_TX_BUSY; | 2329 | return NETDEV_TX_BUSY; |
| 2330 | } | 2330 | } |
| 2331 | 2331 | ||
| 2332 | e = ring->to_use; | 2332 | e = skge->tx_ring.to_use; |
| 2333 | td = e->desc; | 2333 | td = e->desc; |
| 2334 | BUG_ON(td->control & BMU_OWN); | ||
| 2334 | e->skb = skb; | 2335 | e->skb = skb; |
| 2335 | len = skb_headlen(skb); | 2336 | len = skb_headlen(skb); |
| 2336 | map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); | 2337 | map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); |
| @@ -2371,8 +2372,10 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
| 2371 | frag->size, PCI_DMA_TODEVICE); | 2372 | frag->size, PCI_DMA_TODEVICE); |
| 2372 | 2373 | ||
| 2373 | e = e->next; | 2374 | e = e->next; |
| 2374 | e->skb = NULL; | 2375 | e->skb = skb; |
| 2375 | tf = e->desc; | 2376 | tf = e->desc; |
| 2377 | BUG_ON(tf->control & BMU_OWN); | ||
| 2378 | |||
| 2376 | tf->dma_lo = map; | 2379 | tf->dma_lo = map; |
| 2377 | tf->dma_hi = (u64) map >> 32; | 2380 | tf->dma_hi = (u64) map >> 32; |
| 2378 | pci_unmap_addr_set(e, mapaddr, map); | 2381 | pci_unmap_addr_set(e, mapaddr, map); |
| @@ -2389,56 +2392,68 @@ static int skge_xmit_frame(struct sk_buff *skb, struct net_device *dev) | |||
| 2389 | 2392 | ||
| 2390 | skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START); | 2393 | skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START); |
| 2391 | 2394 | ||
| 2392 | if (netif_msg_tx_queued(skge)) | 2395 | if (unlikely(netif_msg_tx_queued(skge))) |
| 2393 | printk(KERN_DEBUG "%s: tx queued, slot %td, len %d\n", | 2396 | printk(KERN_DEBUG "%s: tx queued, slot %td, len %d\n", |
| 2394 | dev->name, e - ring->start, skb->len); | 2397 | dev->name, e - skge->tx_ring.start, skb->len); |
| 2395 | 2398 | ||
| 2396 | ring->to_use = e->next; | 2399 | skge->tx_ring.to_use = e->next; |
| 2397 | if (skge_avail(&skge->tx_ring) <= MAX_SKB_FRAGS + 1) { | 2400 | if (skge_avail(&skge->tx_ring) <= TX_LOW_WATER) { |
| 2398 | pr_debug("%s: transmit queue full\n", dev->name); | 2401 | pr_debug("%s: transmit queue full\n", dev->name); |
| 2399 | netif_stop_queue(dev); | 2402 | netif_stop_queue(dev); |
| 2400 | } | 2403 | } |
| 2401 | 2404 | ||
| 2402 | mmiowb(); | 2405 | spin_unlock_irqrestore(&skge->tx_lock, flags); |
| 2403 | spin_unlock(&skge->tx_lock); | ||
| 2404 | 2406 | ||
| 2405 | dev->trans_start = jiffies; | 2407 | dev->trans_start = jiffies; |
| 2406 | 2408 | ||
| 2407 | return NETDEV_TX_OK; | 2409 | return NETDEV_TX_OK; |
| 2408 | } | 2410 | } |
| 2409 | 2411 | ||
| 2410 | static void skge_tx_complete(struct skge_port *skge, struct skge_element *last) | 2412 | |
| 2413 | /* Free resources associated with this reing element */ | ||
| 2414 | static void skge_tx_free(struct skge_port *skge, struct skge_element *e, | ||
| 2415 | u32 control) | ||
| 2411 | { | 2416 | { |
| 2412 | struct pci_dev *pdev = skge->hw->pdev; | 2417 | struct pci_dev *pdev = skge->hw->pdev; |
| 2413 | struct skge_element *e; | ||
| 2414 | 2418 | ||
| 2415 | for (e = skge->tx_ring.to_clean; e != last; e = e->next) { | 2419 | BUG_ON(!e->skb); |
| 2416 | struct sk_buff *skb = e->skb; | ||
| 2417 | int i; | ||
| 2418 | 2420 | ||
| 2419 | e->skb = NULL; | 2421 | /* skb header vs. fragment */ |
| 2422 | if (control & BMU_STF) | ||
| 2420 | pci_unmap_single(pdev, pci_unmap_addr(e, mapaddr), | 2423 | pci_unmap_single(pdev, pci_unmap_addr(e, mapaddr), |
| 2421 | skb_headlen(skb), PCI_DMA_TODEVICE); | 2424 | pci_unmap_len(e, maplen), |
| 2425 | PCI_DMA_TODEVICE); | ||
| 2426 | else | ||
| 2427 | pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr), | ||
| 2428 | pci_unmap_len(e, maplen), | ||
| 2429 | PCI_DMA_TODEVICE); | ||
| 2422 | 2430 | ||
| 2423 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 2431 | if (control & BMU_EOF) { |
| 2424 | e = e->next; | 2432 | if (unlikely(netif_msg_tx_done(skge))) |
| 2425 | pci_unmap_page(pdev, pci_unmap_addr(e, mapaddr), | 2433 | printk(KERN_DEBUG PFX "%s: tx done slot %td\n", |
| 2426 | skb_shinfo(skb)->frags[i].size, | 2434 | skge->netdev->name, e - skge->tx_ring.start); |
| 2427 | PCI_DMA_TODEVICE); | ||
| 2428 | } | ||
| 2429 | 2435 | ||
| 2430 | dev_kfree_skb(skb); | 2436 | dev_kfree_skb_any(e->skb); |
| 2431 | } | 2437 | } |
| 2432 | skge->tx_ring.to_clean = e; | 2438 | e->skb = NULL; |
| 2433 | } | 2439 | } |
| 2434 | 2440 | ||
| 2441 | /* Free all buffers in transmit ring */ | ||
| 2435 | static void skge_tx_clean(struct skge_port *skge) | 2442 | static void skge_tx_clean(struct skge_port *skge) |
| 2436 | { | 2443 | { |
| 2444 | struct skge_element *e; | ||
| 2445 | unsigned long flags; | ||
| 2446 | |||
| 2447 | spin_lock_irqsave(&skge->tx_lock, flags); | ||
| 2448 | for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { | ||
| 2449 | struct skge_tx_desc *td = e->desc; | ||
| 2450 | skge_tx_free(skge, e, td->control); | ||
| 2451 | td->control = 0; | ||
| 2452 | } | ||
| 2437 | 2453 | ||
| 2438 | spin_lock_bh(&skge->tx_lock); | 2454 | skge->tx_ring.to_clean = e; |
| 2439 | skge_tx_complete(skge, skge->tx_ring.to_use); | ||
| 2440 | netif_wake_queue(skge->netdev); | 2455 | netif_wake_queue(skge->netdev); |
| 2441 | spin_unlock_bh(&skge->tx_lock); | 2456 | spin_unlock_irqrestore(&skge->tx_lock, flags); |
| 2442 | } | 2457 | } |
| 2443 | 2458 | ||
| 2444 | static void skge_tx_timeout(struct net_device *dev) | 2459 | static void skge_tx_timeout(struct net_device *dev) |
| @@ -2664,32 +2679,28 @@ resubmit: | |||
| 2664 | return NULL; | 2679 | return NULL; |
| 2665 | } | 2680 | } |
| 2666 | 2681 | ||
| 2667 | static void skge_tx_done(struct skge_port *skge) | 2682 | /* Free all buffers in Tx ring which are no longer owned by device */ |
| 2683 | static void skge_txirq(struct net_device *dev) | ||
| 2668 | { | 2684 | { |
| 2685 | struct skge_port *skge = netdev_priv(dev); | ||
| 2669 | struct skge_ring *ring = &skge->tx_ring; | 2686 | struct skge_ring *ring = &skge->tx_ring; |
| 2670 | struct skge_element *e, *last; | 2687 | struct skge_element *e; |
| 2688 | |||
| 2689 | rmb(); | ||
| 2671 | 2690 | ||
| 2672 | spin_lock(&skge->tx_lock); | 2691 | spin_lock(&skge->tx_lock); |
| 2673 | last = ring->to_clean; | ||
| 2674 | for (e = ring->to_clean; e != ring->to_use; e = e->next) { | 2692 | for (e = ring->to_clean; e != ring->to_use; e = e->next) { |
| 2675 | struct skge_tx_desc *td = e->desc; | 2693 | struct skge_tx_desc *td = e->desc; |
| 2676 | 2694 | ||
| 2677 | if (td->control & BMU_OWN) | 2695 | if (td->control & BMU_OWN) |
| 2678 | break; | 2696 | break; |
| 2679 | 2697 | ||
| 2680 | if (td->control & BMU_EOF) { | 2698 | skge_tx_free(skge, e, td->control); |
| 2681 | last = e->next; | ||
| 2682 | if (unlikely(netif_msg_tx_done(skge))) | ||
| 2683 | printk(KERN_DEBUG PFX "%s: tx done slot %td\n", | ||
| 2684 | skge->netdev->name, e - ring->start); | ||
| 2685 | } | ||
| 2686 | } | 2699 | } |
| 2700 | skge->tx_ring.to_clean = e; | ||
| 2687 | 2701 | ||
| 2688 | skge_tx_complete(skge, last); | 2702 | if (netif_queue_stopped(skge->netdev) |
| 2689 | 2703 | && skge_avail(&skge->tx_ring) > TX_LOW_WATER) | |
| 2690 | skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); | ||
| 2691 | |||
| 2692 | if (skge_avail(&skge->tx_ring) > MAX_SKB_FRAGS + 1) | ||
| 2693 | netif_wake_queue(skge->netdev); | 2704 | netif_wake_queue(skge->netdev); |
| 2694 | 2705 | ||
| 2695 | spin_unlock(&skge->tx_lock); | 2706 | spin_unlock(&skge->tx_lock); |
| @@ -2704,8 +2715,6 @@ static int skge_poll(struct net_device *dev, int *budget) | |||
| 2704 | int to_do = min(dev->quota, *budget); | 2715 | int to_do = min(dev->quota, *budget); |
| 2705 | int work_done = 0; | 2716 | int work_done = 0; |
| 2706 | 2717 | ||
| 2707 | skge_tx_done(skge); | ||
| 2708 | |||
| 2709 | for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) { | 2718 | for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) { |
| 2710 | struct skge_rx_desc *rd = e->desc; | 2719 | struct skge_rx_desc *rd = e->desc; |
| 2711 | struct sk_buff *skb; | 2720 | struct sk_buff *skb; |
| @@ -2737,10 +2746,12 @@ static int skge_poll(struct net_device *dev, int *budget) | |||
| 2737 | return 1; /* not done */ | 2746 | return 1; /* not done */ |
| 2738 | 2747 | ||
| 2739 | netif_rx_complete(dev); | 2748 | netif_rx_complete(dev); |
| 2740 | mmiowb(); | ||
| 2741 | 2749 | ||
| 2742 | hw->intr_mask |= skge->port == 0 ? (IS_R1_F|IS_XA1_F) : (IS_R2_F|IS_XA2_F); | 2750 | spin_lock_irq(&hw->hw_lock); |
| 2751 | hw->intr_mask |= rxirqmask[skge->port]; | ||
| 2743 | skge_write32(hw, B0_IMSK, hw->intr_mask); | 2752 | skge_write32(hw, B0_IMSK, hw->intr_mask); |
| 2753 | mmiowb(); | ||
| 2754 | spin_unlock_irq(&hw->hw_lock); | ||
| 2744 | 2755 | ||
| 2745 | return 0; | 2756 | return 0; |
| 2746 | } | 2757 | } |
| @@ -2847,16 +2858,16 @@ static void skge_error_irq(struct skge_hw *hw) | |||
| 2847 | } | 2858 | } |
| 2848 | 2859 | ||
| 2849 | /* | 2860 | /* |
| 2850 | * Interrupt from PHY are handled in tasklet (soft irq) | 2861 | * Interrupt from PHY are handled in work queue |
| 2851 | * because accessing phy registers requires spin wait which might | 2862 | * because accessing phy registers requires spin wait which might |
| 2852 | * cause excess interrupt latency. | 2863 | * cause excess interrupt latency. |
| 2853 | */ | 2864 | */ |
| 2854 | static void skge_extirq(unsigned long data) | 2865 | static void skge_extirq(void *arg) |
| 2855 | { | 2866 | { |
| 2856 | struct skge_hw *hw = (struct skge_hw *) data; | 2867 | struct skge_hw *hw = arg; |
| 2857 | int port; | 2868 | int port; |
| 2858 | 2869 | ||
| 2859 | spin_lock(&hw->phy_lock); | 2870 | mutex_lock(&hw->phy_mutex); |
| 2860 | for (port = 0; port < hw->ports; port++) { | 2871 | for (port = 0; port < hw->ports; port++) { |
| 2861 | struct net_device *dev = hw->dev[port]; | 2872 | struct net_device *dev = hw->dev[port]; |
| 2862 | struct skge_port *skge = netdev_priv(dev); | 2873 | struct skge_port *skge = netdev_priv(dev); |
| @@ -2868,10 +2879,12 @@ static void skge_extirq(unsigned long data) | |||
| 2868 | bcom_phy_intr(skge); | 2879 | bcom_phy_intr(skge); |
| 2869 | } | 2880 | } |
| 2870 | } | 2881 | } |
| 2871 | spin_unlock(&hw->phy_lock); | 2882 | mutex_unlock(&hw->phy_mutex); |
| 2872 | 2883 | ||
| 2884 | spin_lock_irq(&hw->hw_lock); | ||
| 2873 | hw->intr_mask |= IS_EXT_REG; | 2885 | hw->intr_mask |= IS_EXT_REG; |
| 2874 | skge_write32(hw, B0_IMSK, hw->intr_mask); | 2886 | skge_write32(hw, B0_IMSK, hw->intr_mask); |
| 2887 | spin_unlock_irq(&hw->hw_lock); | ||
| 2875 | } | 2888 | } |
| 2876 | 2889 | ||
| 2877 | static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) | 2890 | static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) |
| @@ -2884,54 +2897,68 @@ static irqreturn_t skge_intr(int irq, void *dev_id, struct pt_regs *regs) | |||
| 2884 | if (status == 0) | 2897 | if (status == 0) |
| 2885 | return IRQ_NONE; | 2898 | return IRQ_NONE; |
| 2886 | 2899 | ||
| 2900 | spin_lock(&hw->hw_lock); | ||
| 2901 | status &= hw->intr_mask; | ||
| 2887 | if (status & IS_EXT_REG) { | 2902 | if (status & IS_EXT_REG) { |
| 2888 | hw->intr_mask &= ~IS_EXT_REG; | 2903 | hw->intr_mask &= ~IS_EXT_REG; |
| 2889 | tasklet_schedule(&hw->ext_tasklet); | 2904 | schedule_work(&hw->phy_work); |
| 2890 | } | 2905 | } |
| 2891 | 2906 | ||
| 2892 | if (status & (IS_R1_F|IS_XA1_F)) { | 2907 | if (status & IS_XA1_F) { |
| 2893 | skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F); | 2908 | skge_write8(hw, Q_ADDR(Q_XA1, Q_CSR), CSR_IRQ_CL_F); |
| 2894 | hw->intr_mask &= ~(IS_R1_F|IS_XA1_F); | 2909 | skge_txirq(hw->dev[0]); |
| 2895 | netif_rx_schedule(hw->dev[0]); | ||
| 2896 | } | 2910 | } |
| 2897 | 2911 | ||
| 2898 | if (status & (IS_R2_F|IS_XA2_F)) { | 2912 | if (status & IS_R1_F) { |
| 2899 | skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F); | 2913 | skge_write8(hw, Q_ADDR(Q_R1, Q_CSR), CSR_IRQ_CL_F); |
| 2900 | hw->intr_mask &= ~(IS_R2_F|IS_XA2_F); | 2914 | hw->intr_mask &= ~IS_R1_F; |
| 2901 | netif_rx_schedule(hw->dev[1]); | 2915 | netif_rx_schedule(hw->dev[0]); |
| 2902 | } | 2916 | } |
| 2903 | 2917 | ||
| 2904 | if (likely((status & hw->intr_mask) == 0)) | 2918 | if (status & IS_PA_TO_TX1) |
| 2905 | return IRQ_HANDLED; | 2919 | skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1); |
| 2906 | 2920 | ||
| 2907 | if (status & IS_PA_TO_RX1) { | 2921 | if (status & IS_PA_TO_RX1) { |
| 2908 | struct skge_port *skge = netdev_priv(hw->dev[0]); | 2922 | struct skge_port *skge = netdev_priv(hw->dev[0]); |
| 2909 | ++skge->net_stats.rx_over_errors; | ||
| 2910 | skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1); | ||
| 2911 | } | ||
| 2912 | 2923 | ||
| 2913 | if (status & IS_PA_TO_RX2) { | ||
| 2914 | struct skge_port *skge = netdev_priv(hw->dev[1]); | ||
| 2915 | ++skge->net_stats.rx_over_errors; | 2924 | ++skge->net_stats.rx_over_errors; |
| 2916 | skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2); | 2925 | skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1); |
| 2917 | } | 2926 | } |
| 2918 | 2927 | ||
| 2919 | if (status & IS_PA_TO_TX1) | ||
| 2920 | skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1); | ||
| 2921 | |||
| 2922 | if (status & IS_PA_TO_TX2) | ||
| 2923 | skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2); | ||
| 2924 | 2928 | ||
| 2925 | if (status & IS_MAC1) | 2929 | if (status & IS_MAC1) |
| 2926 | skge_mac_intr(hw, 0); | 2930 | skge_mac_intr(hw, 0); |
| 2927 | 2931 | ||
| 2928 | if (status & IS_MAC2) | 2932 | if (hw->dev[1]) { |
| 2929 | skge_mac_intr(hw, 1); | 2933 | if (status & IS_XA2_F) { |
| 2934 | skge_write8(hw, Q_ADDR(Q_XA2, Q_CSR), CSR_IRQ_CL_F); | ||
| 2935 | skge_txirq(hw->dev[1]); | ||
| 2936 | } | ||
| 2937 | |||
| 2938 | if (status & IS_R2_F) { | ||
| 2939 | skge_write8(hw, Q_ADDR(Q_R2, Q_CSR), CSR_IRQ_CL_F); | ||
| 2940 | hw->intr_mask &= ~IS_R2_F; | ||
| 2941 | netif_rx_schedule(hw->dev[1]); | ||
| 2942 | } | ||
| 2943 | |||
| 2944 | if (status & IS_PA_TO_RX2) { | ||
| 2945 | struct skge_port *skge = netdev_priv(hw->dev[1]); | ||
| 2946 | ++skge->net_stats.rx_over_errors; | ||
| 2947 | skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2); | ||
| 2948 | } | ||
| 2949 | |||
| 2950 | if (status & IS_PA_TO_TX2) | ||
| 2951 | skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2); | ||
| 2952 | |||
| 2953 | if (status & IS_MAC2) | ||
| 2954 | skge_mac_intr(hw, 1); | ||
| 2955 | } | ||
| 2930 | 2956 | ||
| 2931 | if (status & IS_HW_ERR) | 2957 | if (status & IS_HW_ERR) |
| 2932 | skge_error_irq(hw); | 2958 | skge_error_irq(hw); |
| 2933 | 2959 | ||
| 2934 | skge_write32(hw, B0_IMSK, hw->intr_mask); | 2960 | skge_write32(hw, B0_IMSK, hw->intr_mask); |
| 2961 | spin_unlock(&hw->hw_lock); | ||
| 2935 | 2962 | ||
| 2936 | return IRQ_HANDLED; | 2963 | return IRQ_HANDLED; |
| 2937 | } | 2964 | } |
| @@ -2957,7 +2984,7 @@ static int skge_set_mac_address(struct net_device *dev, void *p) | |||
| 2957 | if (!is_valid_ether_addr(addr->sa_data)) | 2984 | if (!is_valid_ether_addr(addr->sa_data)) |
| 2958 | return -EADDRNOTAVAIL; | 2985 | return -EADDRNOTAVAIL; |
| 2959 | 2986 | ||
| 2960 | spin_lock_bh(&hw->phy_lock); | 2987 | mutex_lock(&hw->phy_mutex); |
| 2961 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | 2988 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); |
| 2962 | memcpy_toio(hw->regs + B2_MAC_1 + port*8, | 2989 | memcpy_toio(hw->regs + B2_MAC_1 + port*8, |
| 2963 | dev->dev_addr, ETH_ALEN); | 2990 | dev->dev_addr, ETH_ALEN); |
| @@ -2970,7 +2997,7 @@ static int skge_set_mac_address(struct net_device *dev, void *p) | |||
| 2970 | gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); | 2997 | gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); |
| 2971 | gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); | 2998 | gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); |
| 2972 | } | 2999 | } |
| 2973 | spin_unlock_bh(&hw->phy_lock); | 3000 | mutex_unlock(&hw->phy_mutex); |
| 2974 | 3001 | ||
| 2975 | return 0; | 3002 | return 0; |
| 2976 | } | 3003 | } |
| @@ -3082,6 +3109,7 @@ static int skge_reset(struct skge_hw *hw) | |||
| 3082 | else | 3109 | else |
| 3083 | hw->ram_size = t8 * 4096; | 3110 | hw->ram_size = t8 * 4096; |
| 3084 | 3111 | ||
| 3112 | spin_lock_init(&hw->hw_lock); | ||
| 3085 | hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1; | 3113 | hw->intr_mask = IS_HW_ERR | IS_EXT_REG | IS_PORT_1; |
| 3086 | if (hw->ports > 1) | 3114 | if (hw->ports > 1) |
| 3087 | hw->intr_mask |= IS_PORT_2; | 3115 | hw->intr_mask |= IS_PORT_2; |
| @@ -3150,14 +3178,14 @@ static int skge_reset(struct skge_hw *hw) | |||
| 3150 | 3178 | ||
| 3151 | skge_write32(hw, B0_IMSK, hw->intr_mask); | 3179 | skge_write32(hw, B0_IMSK, hw->intr_mask); |
| 3152 | 3180 | ||
| 3153 | spin_lock_bh(&hw->phy_lock); | 3181 | mutex_lock(&hw->phy_mutex); |
| 3154 | for (i = 0; i < hw->ports; i++) { | 3182 | for (i = 0; i < hw->ports; i++) { |
| 3155 | if (hw->chip_id == CHIP_ID_GENESIS) | 3183 | if (hw->chip_id == CHIP_ID_GENESIS) |
| 3156 | genesis_reset(hw, i); | 3184 | genesis_reset(hw, i); |
| 3157 | else | 3185 | else |
| 3158 | yukon_reset(hw, i); | 3186 | yukon_reset(hw, i); |
| 3159 | } | 3187 | } |
| 3160 | spin_unlock_bh(&hw->phy_lock); | 3188 | mutex_unlock(&hw->phy_mutex); |
| 3161 | 3189 | ||
| 3162 | return 0; | 3190 | return 0; |
| 3163 | } | 3191 | } |
| @@ -3305,8 +3333,8 @@ static int __devinit skge_probe(struct pci_dev *pdev, | |||
| 3305 | } | 3333 | } |
| 3306 | 3334 | ||
| 3307 | hw->pdev = pdev; | 3335 | hw->pdev = pdev; |
| 3308 | spin_lock_init(&hw->phy_lock); | 3336 | mutex_init(&hw->phy_mutex); |
| 3309 | tasklet_init(&hw->ext_tasklet, skge_extirq, (unsigned long) hw); | 3337 | INIT_WORK(&hw->phy_work, skge_extirq, hw); |
| 3310 | 3338 | ||
| 3311 | hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); | 3339 | hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); |
| 3312 | if (!hw->regs) { | 3340 | if (!hw->regs) { |
| @@ -3334,6 +3362,14 @@ static int __devinit skge_probe(struct pci_dev *pdev, | |||
| 3334 | if ((dev = skge_devinit(hw, 0, using_dac)) == NULL) | 3362 | if ((dev = skge_devinit(hw, 0, using_dac)) == NULL) |
| 3335 | goto err_out_led_off; | 3363 | goto err_out_led_off; |
| 3336 | 3364 | ||
| 3365 | if (!is_valid_ether_addr(dev->dev_addr)) { | ||
| 3366 | printk(KERN_ERR PFX "%s: bad (zero?) ethernet address in rom\n", | ||
| 3367 | pci_name(pdev)); | ||
| 3368 | err = -EIO; | ||
| 3369 | goto err_out_free_netdev; | ||
| 3370 | } | ||
| 3371 | |||
| 3372 | |||
| 3337 | err = register_netdev(dev); | 3373 | err = register_netdev(dev); |
| 3338 | if (err) { | 3374 | if (err) { |
| 3339 | printk(KERN_ERR PFX "%s: cannot register net device\n", | 3375 | printk(KERN_ERR PFX "%s: cannot register net device\n", |
| @@ -3388,11 +3424,15 @@ static void __devexit skge_remove(struct pci_dev *pdev) | |||
| 3388 | dev0 = hw->dev[0]; | 3424 | dev0 = hw->dev[0]; |
| 3389 | unregister_netdev(dev0); | 3425 | unregister_netdev(dev0); |
| 3390 | 3426 | ||
| 3427 | spin_lock_irq(&hw->hw_lock); | ||
| 3428 | hw->intr_mask = 0; | ||
| 3391 | skge_write32(hw, B0_IMSK, 0); | 3429 | skge_write32(hw, B0_IMSK, 0); |
| 3430 | spin_unlock_irq(&hw->hw_lock); | ||
| 3431 | |||
| 3392 | skge_write16(hw, B0_LED, LED_STAT_OFF); | 3432 | skge_write16(hw, B0_LED, LED_STAT_OFF); |
| 3393 | skge_write8(hw, B0_CTST, CS_RST_SET); | 3433 | skge_write8(hw, B0_CTST, CS_RST_SET); |
| 3394 | 3434 | ||
| 3395 | tasklet_kill(&hw->ext_tasklet); | 3435 | flush_scheduled_work(); |
| 3396 | 3436 | ||
| 3397 | free_irq(pdev->irq, hw); | 3437 | free_irq(pdev->irq, hw); |
| 3398 | pci_release_regions(pdev); | 3438 | pci_release_regions(pdev); |
