diff options
Diffstat (limited to 'drivers/staging/octeon')
-rw-r--r-- | drivers/staging/octeon/ethernet-mdio.c | 28 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-mem.c | 4 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-rgmii.c | 291 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-rx.c | 60 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-spi.c | 2 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-tx.c | 62 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet.c | 68 | ||||
-rw-r--r-- | drivers/staging/octeon/octeon-ethernet.h | 5 |
8 files changed, 161 insertions, 359 deletions
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index fd9b3d899..e13a4ab46 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c @@ -118,13 +118,20 @@ void cvm_oct_adjust_link(struct net_device *dev) struct octeon_ethernet *priv = netdev_priv(dev); cvmx_helper_link_info_t link_info; + link_info.u64 = 0; + link_info.s.link_up = priv->phydev->link ? 1 : 0; + link_info.s.full_duplex = priv->phydev->duplex ? 1 : 0; + link_info.s.speed = priv->phydev->speed; + priv->link_info = link_info.u64; + + /* + * The polling task need to know about link status changes. + */ + if (priv->poll) + priv->poll(dev); + if (priv->last_link != priv->phydev->link) { priv->last_link = priv->phydev->link; - link_info.u64 = 0; - link_info.s.link_up = priv->last_link ? 1 : 0; - link_info.s.full_duplex = priv->phydev->duplex ? 1 : 0; - link_info.s.speed = priv->phydev->speed; - cvmx_helper_link_set(priv->port, link_info); cvm_oct_note_carrier(priv, link_info); } @@ -174,13 +181,22 @@ int cvm_oct_phy_setup_device(struct net_device *dev) goto no_phy; phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0); + if (!phy_node && of_phy_is_fixed_link(priv->of_node)) { + int rc; + + rc = of_phy_register_fixed_link(priv->of_node); + if (rc) + return rc; + + phy_node = of_node_get(priv->of_node); + } if (!phy_node) goto no_phy; priv->phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0, PHY_INTERFACE_MODE_GMII); - if (priv->phydev == NULL) + if (!priv->phydev) return -ENODEV; priv->last_link = 0; diff --git a/drivers/staging/octeon/ethernet-mem.c b/drivers/staging/octeon/ethernet-mem.c index 5a5cdb3cd..d6172e4da 100644 --- a/drivers/staging/octeon/ethernet-mem.c +++ b/drivers/staging/octeon/ethernet-mem.c @@ -34,7 +34,7 @@ static int cvm_oct_fill_hw_skbuff(int pool, int size, int elements) while (freed) { struct sk_buff *skb = dev_alloc_skb(size + 256); - if (unlikely(skb == NULL)) + if (unlikely(!skb)) break; skb_reserve(skb, 256 - (((unsigned long)skb->data) & 0x7f)); *(struct sk_buff **)(skb->data - sizeof(void *)) = skb; @@ -98,7 +98,7 @@ static int cvm_oct_fill_hw_memory(int pool, int size, int elements) * just before the block. */ memory = kmalloc(size + 256, GFP_ATOMIC); - if (unlikely(memory == NULL)) { + if (unlikely(!memory)) { pr_warn("Unable to allocate %u bytes for FPA pool %d\n", elements * size, pool); break; diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index 1055ee14b..91b148cfc 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c @@ -30,8 +30,6 @@ static DEFINE_SPINLOCK(global_register_lock); -static int number_rgmii_ports; - static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable) { union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl; @@ -63,251 +61,106 @@ static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable) gmxx_rxx_int_reg.u64); } -static void cvm_oct_rgmii_poll(struct net_device *dev) +static void cvm_oct_check_preamble_errors(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); - unsigned long flags = 0; cvmx_helper_link_info_t link_info; - int use_global_register_lock = (priv->phydev == NULL); + unsigned long flags; + + link_info.u64 = priv->link_info; - BUG_ON(in_interrupt()); - if (use_global_register_lock) { + /* + * Take the global register lock since we are going to + * touch registers that affect more than one port. + */ + spin_lock_irqsave(&global_register_lock, flags); + + if (link_info.s.speed == 10 && priv->last_speed == 10) { /* - * Take the global register lock since we are going to - * touch registers that affect more than one port. + * Read the GMXX_RXX_INT_REG[PCTERR] bit and see if we are + * getting preamble errors. */ - spin_lock_irqsave(&global_register_lock, flags); - } else { - mutex_lock(&priv->phydev->mdio.bus->mdio_lock); - } + int interface = INTERFACE(priv->port); + int index = INDEX(priv->port); + union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; - link_info = cvmx_helper_link_get(priv->port); - if (link_info.u64 == priv->link_info) { - if (link_info.s.speed == 10) { + gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG + (index, interface)); + if (gmxx_rxx_int_reg.s.pcterr) { /* - * Read the GMXX_RXX_INT_REG[PCTERR] bit and - * see if we are getting preamble errors. + * We are getting preamble errors at 10Mbps. Most + * likely the PHY is giving us packets with misaligned + * preambles. In order to get these packets we need to + * disable preamble checking and do it in software. */ - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg; - - gmxx_rxx_int_reg.u64 = - cvmx_read_csr(CVMX_GMXX_RXX_INT_REG - (index, interface)); - if (gmxx_rxx_int_reg.s.pcterr) { - /* - * We are getting preamble errors at - * 10Mbps. Most likely the PHY is - * giving us packets with mis aligned - * preambles. In order to get these - * packets we need to disable preamble - * checking and do it in software. - */ - cvm_oct_set_hw_preamble(priv, false); - printk_ratelimited("%s: Using 10Mbps with software preamble removal\n", - dev->name); - } + cvm_oct_set_hw_preamble(priv, false); + printk_ratelimited("%s: Using 10Mbps with software preamble removal\n", + dev->name); } - - if (use_global_register_lock) - spin_unlock_irqrestore(&global_register_lock, flags); - else - mutex_unlock(&priv->phydev->mdio.bus->mdio_lock); - return; - } - - /* Since the 10Mbps preamble workaround is allowed we need to enable - * preamble checking, FCS stripping, and clear error bits on - * every speed change. If errors occur during 10Mbps operation - * the above code will change this stuff - */ - cvm_oct_set_hw_preamble(priv, true); - - if (priv->phydev == NULL) { - link_info = cvmx_helper_link_autoconf(priv->port); - priv->link_info = link_info.u64; - } - - if (use_global_register_lock) - spin_unlock_irqrestore(&global_register_lock, flags); - else - mutex_unlock(&priv->phydev->mdio.bus->mdio_lock); - - if (priv->phydev == NULL) { - /* Tell core. */ - if (link_info.s.link_up) { - if (!netif_carrier_ok(dev)) - netif_carrier_on(dev); - } else if (netif_carrier_ok(dev)) { - netif_carrier_off(dev); - } - cvm_oct_note_carrier(priv, link_info); + } else { + /* + * Since the 10Mbps preamble workaround is allowed we need to + * enable preamble checking, FCS stripping, and clear error + * bits on every speed change. If errors occur during 10Mbps + * operation the above code will change this stuff + */ + if (priv->last_speed != link_info.s.speed) + cvm_oct_set_hw_preamble(priv, true); + priv->last_speed = link_info.s.speed; } + spin_unlock_irqrestore(&global_register_lock, flags); } -static int cmv_oct_rgmii_gmx_interrupt(int interface) +static void cvm_oct_rgmii_poll(struct net_device *dev) { - int index; - int count = 0; - - /* Loop through every port of this interface */ - for (index = 0; - index < cvmx_helper_ports_on_interface(interface); - index++) { - union cvmx_gmxx_rxx_int_reg gmx_rx_int_reg; + struct octeon_ethernet *priv = netdev_priv(dev); + cvmx_helper_link_info_t link_info; + bool status_change; - /* Read the GMX interrupt status bits */ - gmx_rx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG - (index, interface)); - gmx_rx_int_reg.u64 &= cvmx_read_csr(CVMX_GMXX_RXX_INT_EN - (index, interface)); + link_info = cvmx_helper_link_autoconf(priv->port); + status_change = priv->link_info != link_info.u64; + priv->link_info = link_info.u64; - /* Poll the port if inband status changed */ - if (gmx_rx_int_reg.s.phy_dupx || gmx_rx_int_reg.s.phy_link || - gmx_rx_int_reg.s.phy_spd) { - struct net_device *dev = - cvm_oct_device[cvmx_helper_get_ipd_port - (interface, index)]; - struct octeon_ethernet *priv = netdev_priv(dev); + cvm_oct_check_preamble_errors(dev); - if (dev && !atomic_read(&cvm_oct_poll_queue_stopping)) - queue_work(cvm_oct_poll_queue, - &priv->port_work); + if (likely(!status_change)) + return; - gmx_rx_int_reg.u64 = 0; - gmx_rx_int_reg.s.phy_dupx = 1; - gmx_rx_int_reg.s.phy_link = 1; - gmx_rx_int_reg.s.phy_spd = 1; - cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), - gmx_rx_int_reg.u64); - count++; - } + /* Tell core. */ + if (link_info.s.link_up) { + if (!netif_carrier_ok(dev)) + netif_carrier_on(dev); + } else if (netif_carrier_ok(dev)) { + netif_carrier_off(dev); } - return count; -} - -static irqreturn_t cvm_oct_rgmii_rml_interrupt(int cpl, void *dev_id) -{ - union cvmx_npi_rsl_int_blocks rsl_int_blocks; - int count = 0; - - rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS); - - /* Check and see if this interrupt was caused by the GMX0 block */ - if (rsl_int_blocks.s.gmx0) - count += cmv_oct_rgmii_gmx_interrupt(0); - - /* Check and see if this interrupt was caused by the GMX1 block */ - if (rsl_int_blocks.s.gmx1) - count += cmv_oct_rgmii_gmx_interrupt(1); - - return count ? IRQ_HANDLED : IRQ_NONE; + cvm_oct_note_carrier(priv, link_info); } int cvm_oct_rgmii_open(struct net_device *dev) { - return cvm_oct_common_open(dev, cvm_oct_rgmii_poll); -} - -static void cvm_oct_rgmii_immediate_poll(struct work_struct *work) -{ - struct octeon_ethernet *priv = - container_of(work, struct octeon_ethernet, port_work); - cvm_oct_rgmii_poll(cvm_oct_device[priv->port]); -} - -int cvm_oct_rgmii_init(struct net_device *dev) -{ struct octeon_ethernet *priv = netdev_priv(dev); - int r; - - cvm_oct_common_init(dev); - INIT_WORK(&priv->port_work, cvm_oct_rgmii_immediate_poll); - /* - * Due to GMX errata in CN3XXX series chips, it is necessary - * to take the link down immediately when the PHY changes - * state. In order to do this we call the poll function every - * time the RGMII inband status changes. This may cause - * problems if the PHY doesn't implement inband status - * properly. - */ - if (number_rgmii_ports == 0) { - r = request_irq(OCTEON_IRQ_RML, cvm_oct_rgmii_rml_interrupt, - IRQF_SHARED, "RGMII", &number_rgmii_ports); - if (r != 0) - return r; - } - number_rgmii_ports++; - - /* - * Only true RGMII ports need to be polled. In GMII mode, port - * 0 is really a RGMII port. - */ - if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) - && (priv->port == 0)) - || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { + int ret; - if (!octeon_is_simulation()) { + ret = cvm_oct_common_open(dev, cvm_oct_rgmii_poll); + if (ret) + return ret; - union cvmx_gmxx_rxx_int_en gmx_rx_int_en; - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - - /* - * Enable interrupts on inband status changes - * for this port. - */ - gmx_rx_int_en.u64 = 0; - gmx_rx_int_en.s.phy_dupx = 1; - gmx_rx_int_en.s.phy_link = 1; - gmx_rx_int_en.s.phy_spd = 1; - cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), - gmx_rx_int_en.u64); + if (priv->phydev) { + /* + * In phydev mode, we need still periodic polling for the + * preamble error checking, and we also need to call this + * function on every link state change. + * + * Only true RGMII ports need to be polled. In GMII mode, port + * 0 is really a RGMII port. + */ + if ((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII && + priv->port == 0) || + (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { + priv->poll = cvm_oct_check_preamble_errors; + cvm_oct_check_preamble_errors(dev); } } return 0; } - -void cvm_oct_rgmii_uninit(struct net_device *dev) -{ - struct octeon_ethernet *priv = netdev_priv(dev); - - cvm_oct_common_uninit(dev); - - /* - * Only true RGMII ports need to be polled. In GMII mode, port - * 0 is really a RGMII port. - */ - if (((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) - && (priv->port == 0)) - || (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) { - - if (!octeon_is_simulation()) { - - union cvmx_gmxx_rxx_int_en gmx_rx_int_en; - int interface = INTERFACE(priv->port); - int index = INDEX(priv->port); - - /* - * Disable interrupts on inband status changes - * for this port. - */ - gmx_rx_int_en.u64 = - cvmx_read_csr(CVMX_GMXX_RXX_INT_EN - (index, interface)); - gmx_rx_int_en.s.phy_dupx = 0; - gmx_rx_int_en.s.phy_link = 0; - gmx_rx_int_en.s.phy_spd = 0; - cvmx_write_csr(CVMX_GMXX_RXX_INT_EN(index, interface), - gmx_rx_int_en.u64); - } - } - - /* Remove the interrupt handler when the last port is removed. */ - number_rgmii_ports--; - if (number_rgmii_ports == 0) - free_irq(OCTEON_IRQ_RML, &number_rgmii_ports); - cancel_work_sync(&priv->port_work); -} diff --git a/drivers/staging/octeon/ethernet-rx.c b/drivers/staging/octeon/ethernet-rx.c index 6aed3cf6c..b6993b0b8 100644 --- a/drivers/staging/octeon/ethernet-rx.c +++ b/drivers/staging/octeon/ethernet-rx.c @@ -26,8 +26,6 @@ #include <net/xfrm.h> #endif /* CONFIG_XFRM */ -#include <linux/atomic.h> - #include <asm/octeon/octeon.h> #include "ethernet-defines.h" @@ -103,7 +101,6 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work) gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface)); if (gmxx_rxx_frm_ctl.s.pre_chk == 0) { - u8 *ptr = cvmx_phys_to_ptr(work->packet_ptr.s.addr); int i = 0; @@ -116,17 +113,11 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work) } if (*ptr == 0xd5) { - /* - printk_ratelimited("Port %d received 0xd5 preamble\n", - port); - */ + /* Port received 0xd5 preamble */ work->packet_ptr.s.addr += i + 1; work->word1.len -= i + 5; } else if ((*ptr & 0xf) == 0xd) { - /* - printk_ratelimited("Port %d received 0x?d preamble\n", - port); - */ + /* Port received 0xd preamble */ work->packet_ptr.s.addr += i; work->word1.len -= i + 4; for (i = 0; i < work->word1.len; i++) { @@ -138,9 +129,6 @@ static inline int cvm_oct_check_rcv_error(cvmx_wqe_t *work) } else { printk_ratelimited("Port %d unknown preamble, packet dropped\n", port); - /* - cvmx_helper_dump_packet(work); - */ cvm_oct_free_work(work); return 1; } @@ -211,7 +199,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) prefetch(work); did_work_request = 0; - if (work == NULL) { + if (!work) { if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { cvmx_write_csr(CVMX_SSO_WQ_IQ_DIS, 1ull << pow_receive_group); @@ -227,7 +215,8 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) } break; } - pskb = (struct sk_buff **)(cvm_oct_get_buffer_ptr(work->packet_ptr) - + pskb = (struct sk_buff **) + (cvm_oct_get_buffer_ptr(work->packet_ptr) - sizeof(void *)); prefetch(pskb); @@ -309,7 +298,9 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) while (segments--) { union cvmx_buf_ptr next_ptr = - *(union cvmx_buf_ptr *)cvmx_phys_to_ptr(segment_ptr.s.addr - 8); + *(union cvmx_buf_ptr *) + cvmx_phys_to_ptr( + segment_ptr.s.addr - 8); /* * Octeon Errata PKI-100: The segment size is @@ -333,7 +324,8 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) segment_size = len; /* Copy the data into the packet */ memcpy(skb_put(skb, segment_size), - cvmx_phys_to_ptr(segment_ptr.s.addr), + cvmx_phys_to_ptr( + segment_ptr.s.addr), segment_size); len -= segment_size; segment_ptr = next_ptr; @@ -364,32 +356,16 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) /* Increment RX stats for virtual ports */ if (port >= CVMX_PIP_NUM_INPUT_PORTS) { -#ifdef CONFIG_64BIT - atomic64_add(1, - (atomic64_t *)&priv->stats.rx_packets); - atomic64_add(skb->len, - (atomic64_t *)&priv->stats.rx_bytes); -#else - atomic_add(1, - (atomic_t *)&priv->stats.rx_packets); - atomic_add(skb->len, - (atomic_t *)&priv->stats.rx_bytes); -#endif + priv->stats.rx_packets++; + priv->stats.rx_bytes += skb->len; } netif_receive_skb(skb); } else { - /* Drop any packet received for a device that isn't up */ /* - printk_ratelimited("%s: Device not up, packet dropped\n", - dev->name); - */ -#ifdef CONFIG_64BIT - atomic64_add(1, - (atomic64_t *)&priv->stats.rx_dropped); -#else - atomic_add(1, - (atomic_t *)&priv->stats.rx_dropped); -#endif + * Drop any packet received for a device that + * isn't up. + */ + priv->stats.rx_dropped++; dev_kfree_skb_irq(skb); } } else { @@ -433,7 +409,7 @@ static int cvm_oct_napi_poll(struct napi_struct *napi, int budget) } cvm_oct_rx_refill_pool(0); - if (rx_count < budget && napi != NULL) { + if (rx_count < budget && napi) { /* No more work */ napi_complete(napi); enable_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group); @@ -466,7 +442,7 @@ void cvm_oct_rx_initialize(void) } } - if (NULL == dev_for_napi) + if (!dev_for_napi) panic("No net_devices were allocated."); netif_napi_add(dev_for_napi, &cvm_oct_napi, cvm_oct_napi_poll, diff --git a/drivers/staging/octeon/ethernet-spi.c b/drivers/staging/octeon/ethernet-spi.c index 2ae1944b3..063dcd075 100644 --- a/drivers/staging/octeon/ethernet-spi.c +++ b/drivers/staging/octeon/ethernet-spi.c @@ -167,9 +167,7 @@ static void cvm_oct_spi_poll(struct net_device *dev) int interface; for (interface = 0; interface < 2; interface++) { - if ((priv->port == interface * 16) && need_retrain[interface]) { - if (cvmx_spi_restart_interface (interface, CVMX_SPI_MODE_DUPLEX, 10) == 0) { need_retrain[interface] = 0; diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c index c053c4a47..ffe9bd77a 100644 --- a/drivers/staging/octeon/ethernet-tx.c +++ b/drivers/staging/octeon/ethernet-tx.c @@ -95,12 +95,10 @@ static void cvm_oct_free_tx_skbs(struct net_device *dev) for (qos = 0; qos < queues_per_port; qos++) { if (skb_queue_len(&priv->tx_free_list[qos]) == 0) continue; - skb_to_free = cvmx_fau_fetch_and_add32(priv->fau+qos*4, + skb_to_free = cvmx_fau_fetch_and_add32(priv->fau + qos * 4, MAX_SKB_TO_FREE); skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, - priv->fau+qos*4); - - + priv->fau + qos * 4); total_freed += skb_to_free; if (skb_to_free > 0) { struct sk_buff *to_free_list = NULL; @@ -126,7 +124,7 @@ static void cvm_oct_free_tx_skbs(struct net_device *dev) } total_remaining += skb_queue_len(&priv->tx_free_list[qos]); } - if (total_freed >= 0 && netif_queue_stopped(dev)) + if (total_remaining < MAX_OUT_QUEUE_DEPTH && netif_queue_stopped(dev)) netif_wake_queue(dev); if (total_remaining) cvm_oct_kick_tx_poll_watchdog(); @@ -176,8 +174,9 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) qos = 0; else if (qos >= cvmx_pko_get_num_queues(priv->port)) qos = 0; - } else + } else { qos = 0; + } if (USE_ASYNC_IOBDMA) { /* Save scratch in case userspace is using it */ @@ -309,55 +308,38 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev) #if REUSE_SKBUFFS_WITHOUT_FREE fpa_head = skb->head + 256 - ((unsigned long)skb->head & 0x7f); if (unlikely(skb->data < fpa_head)) { - /* - * printk("TX buffer beginning can't meet FPA - * alignment constraints\n"); - */ + /* TX buffer beginning can't meet FPA alignment constraints */ goto dont_put_skbuff_in_hw; } if (unlikely ((skb_end_pointer(skb) - fpa_head) < CVMX_FPA_PACKET_POOL_SIZE)) { - /* - printk("TX buffer isn't large enough for the FPA\n"); - */ + /* TX buffer isn't large enough for the FPA */ goto dont_put_skbuff_in_hw; } if (unlikely(skb_shared(skb))) { - /* - printk("TX buffer sharing data with someone else\n"); - */ + /* TX buffer sharing data with someone else */ goto dont_put_skbuff_in_hw; } if (unlikely(skb_cloned(skb))) { - /* - printk("TX buffer has been cloned\n"); - */ + /* TX buffer has been cloned */ goto dont_put_skbuff_in_hw; } if (unlikely(skb_header_cloned(skb))) { - /* - printk("TX buffer header has been cloned\n"); - */ + /* TX buffer header has been cloned */ goto dont_put_skbuff_in_hw; } if (unlikely(skb->destructor)) { - /* - printk("TX buffer has a destructor\n"); - */ + /* TX buffer has a destructor */ goto dont_put_skbuff_in_hw; } if (unlikely(skb_shinfo(skb)->nr_frags)) { - /* - printk("TX buffer has fragments\n"); - */ + /* TX buffer has fragments */ goto dont_put_skbuff_in_hw; } if (unlikely (skb->truesize != sizeof(*skb) + skb_end_offset(skb))) { - /* - printk("TX buffer truesize has been changed\n"); - */ + /* TX buffer truesize has been changed */ goto dont_put_skbuff_in_hw; } @@ -403,7 +385,7 @@ dont_put_skbuff_in_hw: ((ip_hdr(skb)->protocol == IPPROTO_TCP) || (ip_hdr(skb)->protocol == IPPROTO_UDP))) { /* Use hardware checksum calc */ - pko_command.s.ipoffp1 = sizeof(struct ethhdr) + 1; + pko_command.s.ipoffp1 = skb_network_offset(skb) + 1; } if (USE_ASYNC_IOBDMA) { @@ -419,7 +401,8 @@ dont_put_skbuff_in_hw: cvmx_fau_fetch_and_add32(FAU_NUM_PACKET_BUFFERS_TO_FREE, 0); } - skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, priv->fau+qos*4); + skb_to_free = cvm_oct_adjust_skb_to_free(skb_to_free, + priv->fau + qos * 4); /* * If we're sending faster than the receive can free them then @@ -430,7 +413,7 @@ dont_put_skbuff_in_hw: if (pko_command.s.dontfree) { queue_type = QUEUE_CORE; - pko_command.s.reg0 = priv->fau+qos*4; + pko_command.s.reg0 = priv->fau + qos * 4; } else { queue_type = QUEUE_HW; } @@ -443,7 +426,6 @@ dont_put_skbuff_in_hw: /* Drop this packet if we have too many already queued to the HW */ if (unlikely(skb_queue_len(&priv->tx_free_list[qos]) >= MAX_OUT_QUEUE_DEPTH)) { - if (dev->tx_queue_len != 0) { /* Drop the lock when notifying the core. */ spin_unlock_irqrestore(&priv->tx_free_list[qos].lock, @@ -559,7 +541,7 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev) /* Get a packet buffer */ packet_buffer = cvmx_fpa_alloc(CVMX_FPA_PACKET_POOL); - if (unlikely(packet_buffer == NULL)) { + if (unlikely(!packet_buffer)) { printk_ratelimited("%s: Failed to allocate a packet buffer\n", dev->name); cvmx_fpa_free(work, CVMX_FPA_WQE_POOL, 1); @@ -617,8 +599,8 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev) work->word2.s.dec_ipcomp = 0; /* FIXME */ #endif work->word2.s.tcp_or_udp = - (ip_hdr(skb)->protocol == IPPROTO_TCP) - || (ip_hdr(skb)->protocol == IPPROTO_UDP); + (ip_hdr(skb)->protocol == IPPROTO_TCP) || + (ip_hdr(skb)->protocol == IPPROTO_UDP); #if 0 /* FIXME */ work->word2.s.dec_ipsec = 0; @@ -629,8 +611,8 @@ int cvm_oct_xmit_pow(struct sk_buff *skb, struct net_device *dev) /* No error, packet is internal */ work->word2.s.L4_error = 0; #endif - work->word2.s.is_frag = !((ip_hdr(skb)->frag_off == 0) - || (ip_hdr(skb)->frag_off == + work->word2.s.is_frag = !((ip_hdr(skb)->frag_off == 0) || + (ip_hdr(skb)->frag_off == 1 << 14)); #if 0 /* Assume Linux is sending a good packet */ diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index f69fb5cc7..271e1b8d8 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c @@ -86,10 +86,6 @@ int rx_napi_weight = 32; module_param(rx_napi_weight, int, 0444); MODULE_PARM_DESC(rx_napi_weight, "The NAPI WEIGHT parameter."); -/* - * cvm_oct_poll_queue - Workqueue for polling operations. - */ -struct workqueue_struct *cvm_oct_poll_queue; /* * cvm_oct_poll_queue_stopping - flag to indicate polling should stop. @@ -121,8 +117,7 @@ static void cvm_oct_rx_refill_worker(struct work_struct *work) cvm_oct_rx_refill_pool(num_packet_buffers / 2); if (!atomic_read(&cvm_oct_poll_queue_stopping)) - queue_delayed_work(cvm_oct_poll_queue, - &cvm_oct_rx_refill_work, HZ); + schedule_delayed_work(&cvm_oct_rx_refill_work, HZ); } static void cvm_oct_periodic_worker(struct work_struct *work) @@ -138,8 +133,7 @@ static void cvm_oct_periodic_worker(struct work_struct *work) cvm_oct_device[priv->port]); if (!atomic_read(&cvm_oct_poll_queue_stopping)) - queue_delayed_work(cvm_oct_poll_queue, - &priv->port_periodic_work, HZ); + schedule_delayed_work(&priv->port_periodic_work, HZ); } static void cvm_oct_configure_common_hw(void) @@ -226,18 +220,7 @@ static struct net_device_stats *cvm_oct_common_get_stats(struct net_device *dev) priv->stats.multicast += rx_status.multicast_packets; priv->stats.rx_crc_errors += rx_status.inb_errors; priv->stats.rx_frame_errors += rx_status.fcs_align_err_packets; - - /* - * The drop counter must be incremented atomically - * since the RX tasklet also increments it. - */ -#ifdef CONFIG_64BIT - atomic64_add(rx_status.dropped_packets, - (atomic64_t *)&priv->stats.rx_dropped); -#else - atomic_add(rx_status.dropped_packets, - (atomic_t *)&priv->stats.rx_dropped); -#endif + priv->stats.rx_dropped += rx_status.dropped_packets; } return &priv->stats; @@ -265,22 +248,22 @@ static int cvm_oct_common_change_mtu(struct net_device *dev, int new_mtu) * Limit the MTU to make sure the ethernet packets are between * 64 bytes and 65535 bytes. */ - if ((new_mtu + 14 + 4 + vlan_bytes < 64) - || (new_mtu + 14 + 4 + vlan_bytes > 65392)) { + if ((new_mtu + 14 + 4 + vlan_bytes < 64) || + (new_mtu + 14 + 4 + vlan_bytes > 65392)) { pr_err("MTU must be between %d and %d.\n", 64 - 14 - 4 - vlan_bytes, 65392 - 14 - 4 - vlan_bytes); return -EINVAL; } dev->mtu = new_mtu; - if ((interface < 2) - && (cvmx_helper_interface_get_mode(interface) != + if ((interface < 2) && + (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) { /* Add ethernet header and FCS, and VLAN if configured. */ int max_packet = new_mtu + 14 + 4 + vlan_bytes; - if (OCTEON_IS_MODEL(OCTEON_CN3XXX) - || OCTEON_IS_MODEL(OCTEON_CN58XX)) { + if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || + OCTEON_IS_MODEL(OCTEON_CN58XX)) { /* Signal errors on packets larger than the MTU */ cvmx_write_csr(CVMX_GMXX_RXX_FRM_MAX(index, interface), max_packet); @@ -319,8 +302,8 @@ static void cvm_oct_common_set_multicast_list(struct net_device *dev) int interface = INTERFACE(priv->port); int index = INDEX(priv->port); - if ((interface < 2) - && (cvmx_helper_interface_get_mode(interface) != + if ((interface < 2) && + (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) { union cvmx_gmxx_rxx_adr_ctl control; @@ -371,8 +354,8 @@ static int cvm_oct_set_mac_filter(struct net_device *dev) int interface = INTERFACE(priv->port); int index = INDEX(priv->port); - if ((interface < 2) - && (cvmx_helper_interface_get_mode(interface) != + if ((interface < 2) && + (cvmx_helper_interface_get_mode(interface) != CVMX_HELPER_INTERFACE_MODE_SPI)) { int i; u8 *ptr = dev->dev_addr; @@ -445,8 +428,8 @@ int cvm_oct_common_init(struct net_device *dev) * Force the interface to use the POW send if always_use_pow * was specified or it is in the pow send list. */ - if ((pow_send_group != -1) - && (always_use_pow || strstr(pow_send_list, dev->name))) + if ((pow_send_group != -1) && + (always_use_pow || strstr(pow_send_list, dev->name))) priv->queue = -1; if (priv->queue != -1) @@ -557,6 +540,7 @@ static const struct net_device_ops cvm_oct_npi_netdev_ops = { .ndo_poll_controller = cvm_oct_poll_controller, #endif }; + static const struct net_device_ops cvm_oct_xaui_netdev_ops = { .ndo_init = cvm_oct_common_init, .ndo_uninit = cvm_oct_common_uninit, @@ -572,6 +556,7 @@ static const struct net_device_ops cvm_oct_xaui_netdev_ops = { .ndo_poll_controller = cvm_oct_poll_controller, #endif }; + static const struct net_device_ops cvm_oct_sgmii_netdev_ops = { .ndo_init = cvm_oct_sgmii_init, .ndo_uninit = cvm_oct_common_uninit, @@ -587,6 +572,7 @@ static const struct net_device_ops cvm_oct_sgmii_netdev_ops = { .ndo_poll_controller = cvm_oct_poll_controller, #endif }; + static const struct net_device_ops cvm_oct_spi_netdev_ops = { .ndo_init = cvm_oct_spi_init, .ndo_uninit = cvm_oct_spi_uninit, @@ -600,9 +586,10 @@ static const struct net_device_ops cvm_oct_spi_netdev_ops = { .ndo_poll_controller = cvm_oct_poll_controller, #endif }; + static const struct net_device_ops cvm_oct_rgmii_netdev_ops = { - .ndo_init = cvm_oct_rgmii_init, - .ndo_uninit = cvm_oct_rgmii_uninit, + .ndo_init = cvm_oct_common_init, + .ndo_uninit = cvm_oct_common_uninit, .ndo_open = cvm_oct_rgmii_open, .ndo_stop = cvm_oct_common_stop, .ndo_start_xmit = cvm_oct_xmit, @@ -615,6 +602,7 @@ static const struct net_device_ops cvm_oct_rgmii_netdev_ops = { .ndo_poll_controller = cvm_oct_poll_controller, #endif }; + static const struct net_device_ops cvm_oct_pow_netdev_ops = { .ndo_init = cvm_oct_common_init, .ndo_start_xmit = cvm_oct_xmit_pow, @@ -677,11 +665,6 @@ static int cvm_oct_probe(struct platform_device *pdev) return -EINVAL; } - cvm_oct_poll_queue = create_singlethread_workqueue("octeon-ethernet"); - if (!cvm_oct_poll_queue) { - pr_err("octeon-ethernet: Cannot create workqueue"); - return -ENOMEM; - } cvm_oct_configure_common_hw(); @@ -790,7 +773,6 @@ static int cvm_oct_probe(struct platform_device *pdev) cvmx_fau_atomic_write32(priv->fau + qos * 4, 0); switch (priv->imode) { - /* These types don't support ports to IPD/PKO */ case CVMX_HELPER_INTERFACE_MODE_DISABLED: case CVMX_HELPER_INTERFACE_MODE_PCIE: @@ -840,8 +822,7 @@ static int cvm_oct_probe(struct platform_device *pdev) fau -= cvmx_pko_get_num_queues(priv->port) * sizeof(u32); - queue_delayed_work(cvm_oct_poll_queue, - &priv->port_periodic_work, HZ); + schedule_delayed_work(&priv->port_periodic_work, HZ); } } } @@ -854,7 +835,7 @@ static int cvm_oct_probe(struct platform_device *pdev) */ cvm_oct_tx_poll_interval = 150 * (octeon_get_clock_rate() / 1000000); - queue_delayed_work(cvm_oct_poll_queue, &cvm_oct_rx_refill_work, HZ); + schedule_delayed_work(&cvm_oct_rx_refill_work, HZ); return 0; } @@ -897,7 +878,6 @@ static int cvm_oct_remove(struct platform_device *pdev) } } - destroy_workqueue(cvm_oct_poll_queue); cvmx_pko_shutdown(); diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index fdf24d120..6275c15e0 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h @@ -41,20 +41,18 @@ struct octeon_ethernet { /* Device statistics */ struct net_device_stats stats; struct phy_device *phydev; + unsigned int last_speed; unsigned int last_link; /* Last negotiated link state */ u64 link_info; /* Called periodically to check link status */ void (*poll)(struct net_device *dev); struct delayed_work port_periodic_work; - struct work_struct port_work; /* may be unused. */ struct device_node *of_node; }; int cvm_oct_free_work(void *work_queue_entry); -int cvm_oct_rgmii_init(struct net_device *dev); -void cvm_oct_rgmii_uninit(struct net_device *dev); int cvm_oct_rgmii_open(struct net_device *dev); int cvm_oct_sgmii_init(struct net_device *dev); @@ -78,7 +76,6 @@ extern int pow_send_group; extern int pow_receive_group; extern char pow_send_list[]; extern struct net_device *cvm_oct_device[]; -extern struct workqueue_struct *cvm_oct_poll_queue; extern atomic_t cvm_oct_poll_queue_stopping; extern u64 cvm_oct_tx_poll_interval; |