diff options
Diffstat (limited to 'drivers/net')
58 files changed, 1571 insertions, 1068 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index b3d70a7a5262..5dca77e0ffed 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1317,9 +1317,10 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) slave_dev->name); } - /* already enslaved */ - if (slave_dev->flags & IFF_SLAVE) { - netdev_dbg(bond_dev, "Error: Device was already enslaved\n"); + /* already in-use? */ + if (netdev_is_rx_handler_busy(slave_dev)) { + netdev_err(bond_dev, + "Error: Device is in use and cannot be enslaved\n"); return -EBUSY; } diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index ad535a854e5c..eab132778e67 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -21,6 +21,7 @@ #include <linux/slab.h> #include <linux/netdevice.h> #include <linux/if_arp.h> +#include <linux/workqueue.h> #include <linux/can.h> #include <linux/can/dev.h> #include <linux/can/skb.h> @@ -471,9 +472,8 @@ EXPORT_SYMBOL_GPL(can_free_echo_skb); /* * CAN device restart for bus-off recovery */ -static void can_restart(unsigned long data) +static void can_restart(struct net_device *dev) { - struct net_device *dev = (struct net_device *)data; struct can_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct sk_buff *skb; @@ -513,6 +513,14 @@ restart: netdev_err(dev, "Error %d during restart", err); } +static void can_restart_work(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct can_priv *priv = container_of(dwork, struct can_priv, restart_work); + + can_restart(priv->dev); +} + int can_restart_now(struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); @@ -526,8 +534,8 @@ int can_restart_now(struct net_device *dev) if (priv->state != CAN_STATE_BUS_OFF) return -EBUSY; - /* Runs as soon as possible in the timer context */ - mod_timer(&priv->restart_timer, jiffies); + cancel_delayed_work_sync(&priv->restart_work); + can_restart(dev); return 0; } @@ -548,8 +556,8 @@ void can_bus_off(struct net_device *dev) netif_carrier_off(dev); if (priv->restart_ms) - mod_timer(&priv->restart_timer, - jiffies + (priv->restart_ms * HZ) / 1000); + schedule_delayed_work(&priv->restart_work, + msecs_to_jiffies(priv->restart_ms)); } EXPORT_SYMBOL_GPL(can_bus_off); @@ -658,6 +666,7 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max) return NULL; priv = netdev_priv(dev); + priv->dev = dev; if (echo_skb_max) { priv->echo_skb_max = echo_skb_max; @@ -667,7 +676,7 @@ struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max) priv->state = CAN_STATE_STOPPED; - init_timer(&priv->restart_timer); + INIT_DELAYED_WORK(&priv->restart_work, can_restart_work); return dev; } @@ -748,8 +757,6 @@ int open_candev(struct net_device *dev) if (!netif_carrier_ok(dev)) netif_carrier_on(dev); - setup_timer(&priv->restart_timer, can_restart, (unsigned long)dev); - return 0; } EXPORT_SYMBOL_GPL(open_candev); @@ -764,7 +771,7 @@ void close_candev(struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); - del_timer_sync(&priv->restart_timer); + cancel_delayed_work_sync(&priv->restart_work); can_flush_echo_skb(dev); } EXPORT_SYMBOL_GPL(close_candev); diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 41c0fc9f3b14..16f7cadda5c3 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -1268,11 +1268,10 @@ static int __maybe_unused flexcan_suspend(struct device *device) struct flexcan_priv *priv = netdev_priv(dev); int err; - err = flexcan_chip_disable(priv); - if (err) - return err; - if (netif_running(dev)) { + err = flexcan_chip_disable(priv); + if (err) + return err; netif_stop_queue(dev); netif_device_detach(dev); } @@ -1285,13 +1284,17 @@ static int __maybe_unused flexcan_resume(struct device *device) { struct net_device *dev = dev_get_drvdata(device); struct flexcan_priv *priv = netdev_priv(dev); + int err; priv->can.state = CAN_STATE_ERROR_ACTIVE; if (netif_running(dev)) { netif_device_attach(dev); netif_start_queue(dev); + err = flexcan_chip_enable(priv); + if (err) + return err; } - return flexcan_chip_enable(priv); + return 0; } static SIMPLE_DEV_PM_OPS(flexcan_pm_ops, flexcan_suspend, flexcan_resume); diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 6f946fedbb77..0864f05633a2 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -1137,6 +1137,7 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phydev) { struct bcm_sf2_priv *priv = ds_to_priv(ds); + struct ethtool_eee *p = &priv->port_sts[port].eee; u32 id_mode_dis = 0, port_mode; const char *str = NULL; u32 reg; @@ -1211,6 +1212,9 @@ force_link: reg |= DUPLX_MODE; core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port)); + + if (!phydev->is_pseudo_fixed_link) + p->eee_enabled = bcm_sf2_eee_init(ds, port, phydev); } static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/bcm_sf2.h b/drivers/net/dsa/bcm_sf2.h index 6bba1c98d764..c7994e372284 100644 --- a/drivers/net/dsa/bcm_sf2.h +++ b/drivers/net/dsa/bcm_sf2.h @@ -187,8 +187,8 @@ static inline void name##_writeq(struct bcm_sf2_priv *priv, u64 val, \ static inline void intrl2_##which##_mask_clear(struct bcm_sf2_priv *priv, \ u32 mask) \ { \ - intrl2_##which##_writel(priv, mask, INTRL2_CPU_MASK_CLEAR); \ priv->irq##which##_mask &= ~(mask); \ + intrl2_##which##_writel(priv, mask, INTRL2_CPU_MASK_CLEAR); \ } \ static inline void intrl2_##which##_mask_set(struct bcm_sf2_priv *priv, \ u32 mask) \ diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index c32f5d32f811..b56c9c581359 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -314,6 +314,10 @@ static void bgmac_dma_rx_enable(struct bgmac *bgmac, u32 ctl; ctl = bgmac_read(bgmac, ring->mmio_base + BGMAC_DMA_RX_CTL); + + /* preserve ONLY bits 16-17 from current hardware value */ + ctl &= BGMAC_DMA_RX_ADDREXT_MASK; + if (bgmac->core->id.rev >= 4) { ctl &= ~BGMAC_DMA_RX_BL_MASK; ctl |= BGMAC_DMA_RX_BL_128 << BGMAC_DMA_RX_BL_SHIFT; @@ -324,7 +328,6 @@ static void bgmac_dma_rx_enable(struct bgmac *bgmac, ctl &= ~BGMAC_DMA_RX_PT_MASK; ctl |= BGMAC_DMA_RX_PT_1 << BGMAC_DMA_RX_PT_SHIFT; } - ctl &= BGMAC_DMA_RX_ADDREXT_MASK; ctl |= BGMAC_DMA_RX_ENABLE; ctl |= BGMAC_DMA_RX_PARITY_DISABLE; ctl |= BGMAC_DMA_RX_OVERFLOW_CONT; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 2e611dc5f162..1c8123816745 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -14819,6 +14819,10 @@ static int bnx2x_get_fc_npiv(struct net_device *dev, } offset = SHMEM2_RD(bp, fc_npiv_nvram_tbl_addr[BP_PORT(bp)]); + if (!offset) { + DP(BNX2X_MSG_MCP, "No FC-NPIV in NVRAM\n"); + goto out; + } DP(BNX2X_MSG_MCP, "Offset of FC-NPIV in NVRAM: %08x\n", offset); /* Read the table contents from nvram */ diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 0fb3f8de88e9..91627561c58d 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1168,6 +1168,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, struct bcmgenet_tx_ring *ring) { struct bcmgenet_priv *priv = netdev_priv(dev); + struct device *kdev = &priv->pdev->dev; struct enet_cb *tx_cb_ptr; struct netdev_queue *txq; unsigned int pkts_compl = 0; @@ -1195,7 +1196,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, pkts_compl++; dev->stats.tx_packets++; dev->stats.tx_bytes += tx_cb_ptr->skb->len; - dma_unmap_single(&dev->dev, + dma_unmap_single(kdev, dma_unmap_addr(tx_cb_ptr, dma_addr), dma_unmap_len(tx_cb_ptr, dma_len), DMA_TO_DEVICE); @@ -1203,7 +1204,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, } else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) { dev->stats.tx_bytes += dma_unmap_len(tx_cb_ptr, dma_len); - dma_unmap_page(&dev->dev, + dma_unmap_page(kdev, dma_unmap_addr(tx_cb_ptr, dma_addr), dma_unmap_len(tx_cb_ptr, dma_len), DMA_TO_DEVICE); @@ -1754,6 +1755,7 @@ static int bcmgenet_alloc_rx_buffers(struct bcmgenet_priv *priv, static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv) { + struct device *kdev = &priv->pdev->dev; struct enet_cb *cb; int i; @@ -1761,7 +1763,7 @@ static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv) cb = &priv->rx_cbs[i]; if (dma_unmap_addr(cb, dma_addr)) { - dma_unmap_single(&priv->dev->dev, + dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr), priv->rx_buf_len, DMA_FROM_DEVICE); dma_unmap_addr_set(cb, dma_addr, 0); diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index ca5ac5d6f4e6..49056c33be74 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -18142,14 +18142,14 @@ static pci_ers_result_t tg3_io_error_detected(struct pci_dev *pdev, rtnl_lock(); - /* We needn't recover from permanent error */ - if (state == pci_channel_io_frozen) - tp->pcierr_recovery = true; - /* We probably don't have netdev yet */ if (!netdev || !netif_running(netdev)) goto done; + /* We needn't recover from permanent error */ + if (state == pci_channel_io_frozen) + tp->pcierr_recovery = true; + tg3_phy_stop(tp); tg3_netif_stop(tp); @@ -18246,7 +18246,7 @@ static void tg3_io_resume(struct pci_dev *pdev) rtnl_lock(); - if (!netif_running(netdev)) + if (!netdev || !netif_running(netdev)) goto done; tg3_full_lock(tp, 0); diff --git a/drivers/net/ethernet/cavium/thunder/nic_reg.h b/drivers/net/ethernet/cavium/thunder/nic_reg.h index afb10e326b4f..fab35a593898 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_reg.h +++ b/drivers/net/ethernet/cavium/thunder/nic_reg.h @@ -170,7 +170,6 @@ #define NIC_QSET_SQ_0_7_DOOR (0x010838) #define NIC_QSET_SQ_0_7_STATUS (0x010840) #define NIC_QSET_SQ_0_7_DEBUG (0x010848) -#define NIC_QSET_SQ_0_7_CNM_CHG (0x010860) #define NIC_QSET_SQ_0_7_STAT_0_1 (0x010900) #define NIC_QSET_RBDR_0_1_CFG (0x010C00) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c index a12b2e38cf61..ff1d777f3ed9 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c @@ -380,7 +380,10 @@ static void nicvf_get_regs(struct net_device *dev, p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DOOR, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STATUS, q); p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DEBUG, q); - p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_CNM_CHG, q); + /* Padding, was NIC_QSET_SQ_0_7_CNM_CHG, which + * produces bus errors when read + */ + p[i++] = 0; p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STAT_0_1, q); reg_offset = NIC_QSET_SQ_0_7_STAT_0_1 | (1 << 3); p[i++] = nicvf_queue_reg_read(nic, reg_offset, q); diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index f6147ffc7fbc..ab716042bdd2 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -944,11 +944,11 @@ fec_restart(struct net_device *ndev) * enet-mac reset will reset mac address registers too, * so need to reconfigure it. */ - if (fep->quirks & FEC_QUIRK_ENET_MAC) { - memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); - writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW); - writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH); - } + memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN); + writel((__force u32)cpu_to_be32(temp_mac[0]), + fep->hwp + FEC_ADDR_LOW); + writel((__force u32)cpu_to_be32(temp_mac[1]), + fep->hwp + FEC_ADDR_HIGH); /* Clear any outstanding interrupt. */ writel(0xffffffff, fep->hwp + FEC_IEVENT); diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index 2d74c6e4d7b6..1cf715c72683 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -302,13 +302,15 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc, void *buffer, u16 buf_len) { struct i40e_aq_desc *aq_desc = (struct i40e_aq_desc *)desc; - u16 len = le16_to_cpu(aq_desc->datalen); + u16 len; u8 *buf = (u8 *)buffer; u16 i = 0; if ((!(mask & hw->debug_mask)) || (desc == NULL)) return; + len = le16_to_cpu(aq_desc->datalen); + i40e_debug(hw, mask, "AQ CMD: opcode 0x%04X, flags 0x%04X, datalen 0x%04X, retval 0x%04X\n", le16_to_cpu(aq_desc->opcode), diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 2215bebe208e..4edbab6ca7ef 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -8595,7 +8595,7 @@ static int i40e_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, return 0; return ndo_dflt_bridge_getlink(skb, pid, seq, dev, veb->bridge_mode, - nlflags, 0, 0, filter_mask, NULL); + 0, 0, nlflags, filter_mask, NULL); } #define I40E_MAX_TUNNEL_HDR_LEN 80 @@ -10853,6 +10853,12 @@ static pci_ers_result_t i40e_pci_error_detected(struct pci_dev *pdev, dev_info(&pdev->dev, "%s: error %d\n", __func__, error); + if (!pf) { + dev_info(&pdev->dev, + "Cannot recover - error happened during device probe\n"); + return PCI_ERS_RESULT_DISCONNECT; + } + /* shutdown all operations */ if (!test_bit(__I40E_SUSPENDED, &pf->state)) { rtnl_lock(); diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 5606a043063e..4b62aa1f9ff8 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -5220,6 +5220,19 @@ static SIMPLE_DEV_PM_OPS(sky2_pm_ops, sky2_suspend, sky2_resume); static void sky2_shutdown(struct pci_dev *pdev) { + struct sky2_hw *hw = pci_get_drvdata(pdev); + int port; + + for (port = 0; port < hw->ports; port++) { + struct net_device *ndev = hw->dev[port]; + + rtnl_lock(); + if (netif_running(ndev)) { + dev_close(ndev); + netif_device_detach(ndev); + } + rtnl_unlock(); + } sky2_suspend(&pdev->dev); pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev)); pci_set_power_state(pdev, PCI_D3hot); diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index 67e9633ea9c7..232191417b93 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -2282,7 +2282,7 @@ static int mlx4_en_set_vf_mac(struct net_device *dev, int queue, u8 *mac) struct mlx4_en_dev *mdev = en_priv->mdev; u64 mac_u64 = mlx4_mac_to_u64(mac); - if (!is_valid_ether_addr(mac)) + if (is_multicast_ether_addr(mac)) return -EINVAL; return mlx4_set_vf_mac(mdev->dev, en_priv->port, queue, mac_u64); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index 037fc4cdf5af..cc199063612a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -143,13 +143,14 @@ static struct mlx5_cmd_layout *get_inst(struct mlx5_cmd *cmd, int idx) return cmd->cmd_buf + (idx << cmd->log_stride); } -static u8 xor8_buf(void *buf, int len) +static u8 xor8_buf(void *buf, size_t offset, int len) { u8 *ptr = buf; u8 sum = 0; int i; + int end = len + offset; - for (i = 0; i < len; i++) + for (i = offset; i < end; i++) sum ^= ptr[i]; return sum; @@ -157,41 +158,49 @@ static u8 xor8_buf(void *buf, int len) static int verify_block_sig(struct mlx5_cmd_prot_block *block) { - if (xor8_buf(block->rsvd0, sizeof(*block) - sizeof(block->data) - 1) != 0xff) + size_t rsvd0_off = offsetof(struct mlx5_cmd_prot_block, rsvd0); + int xor_len = sizeof(*block) - sizeof(block->data) - 1; + + if (xor8_buf(block, rsvd0_off, xor_len) != 0xff) return -EINVAL; - if (xor8_buf(block, sizeof(*block)) != 0xff) + if (xor8_buf(block, 0, sizeof(*block)) != 0xff) return -EINVAL; return 0; } -static void calc_block_sig(struct mlx5_cmd_prot_block *block, u8 token, - int csum) +static void calc_block_sig(struct mlx5_cmd_prot_block *block) { - block->token = token; - if (csum) { - block->ctrl_sig = ~xor8_buf(block->rsvd0, sizeof(*block) - - sizeof(block->data) - 2); - block->sig = ~xor8_buf(block, sizeof(*block) - 1); - } + int ctrl_xor_len = sizeof(*block) - sizeof(block->data) - 2; + size_t rsvd0_off = offsetof(struct mlx5_cmd_prot_block, rsvd0); + + block->ctrl_sig = ~xor8_buf(block, rsvd0_off, ctrl_xor_len); + block->sig = ~xor8_buf(block, 0, sizeof(*block) - 1); } -static void calc_chain_sig(struct mlx5_cmd_msg *msg, u8 token, int csum) +static void calc_chain_sig(struct mlx5_cmd_msg *msg) { struct mlx5_cmd_mailbox *next = msg->next; - - while (next) { - calc_block_sig(next->buf, token, csum); + int size = msg->len; + int blen = size - min_t(int, sizeof(msg->first.data), size); + int n = (blen + MLX5_CMD_DATA_BLOCK_SIZE - 1) + / MLX5_CMD_DATA_BLOCK_SIZE; + int i = 0; + + for (i = 0; i < n && next; i++) { + calc_block_sig(next->buf); next = next->next; } } static void set_signature(struct mlx5_cmd_work_ent *ent, int csum) { - ent->lay->sig = ~xor8_buf(ent->lay, sizeof(*ent->lay)); - calc_chain_sig(ent->in, ent->token, csum); - calc_chain_sig(ent->out, ent->token, csum); + ent->lay->sig = ~xor8_buf(ent->lay, 0, sizeof(*ent->lay)); + if (csum) { + calc_chain_sig(ent->in); + calc_chain_sig(ent->out); + } } static void poll_timeout(struct mlx5_cmd_work_ent *ent) @@ -222,12 +231,17 @@ static int verify_signature(struct mlx5_cmd_work_ent *ent) struct mlx5_cmd_mailbox *next = ent->out->next; int err; u8 sig; + int size = ent->out->len; + int blen = size - min_t(int, sizeof(ent->out->first.data), size); + int n = (blen + MLX5_CMD_DATA_BLOCK_SIZE - 1) + / MLX5_CMD_DATA_BLOCK_SIZE; + int i = 0; - sig = xor8_buf(ent->lay, sizeof(*ent->lay)); + sig = xor8_buf(ent->lay, 0, sizeof(*ent->lay)); if (sig != 0xff) return -EINVAL; - while (next) { + for (i = 0; i < n && next; i++) { err = verify_block_sig(next->buf); if (err) return err; @@ -641,7 +655,6 @@ static void cmd_work_handler(struct work_struct *work) spin_unlock_irqrestore(&cmd->alloc_lock, flags); } - ent->token = alloc_token(cmd); cmd->ent_arr[ent->idx] = ent; lay = get_inst(cmd, ent->idx); ent->lay = lay; @@ -755,7 +768,8 @@ static u8 *get_status_ptr(struct mlx5_outbox_hdr *out) static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, struct mlx5_cmd_msg *out, void *uout, int uout_size, mlx5_cmd_cbk_t callback, - void *context, int page_queue, u8 *status) + void *context, int page_queue, u8 *status, + u8 token) { struct mlx5_cmd *cmd = &dev->cmd; struct mlx5_cmd_work_ent *ent; @@ -772,6 +786,8 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in, if (IS_ERR(ent)) return PTR_ERR(ent); + ent->token = token; + if (!callback) init_completion(&ent->done); @@ -844,7 +860,8 @@ static const struct file_operations fops = { .write = dbg_write, }; -static int mlx5_copy_to_msg(struct mlx5_cmd_msg *to, void *from, int size) +static int mlx5_copy_to_msg(struct mlx5_cmd_msg *to, void *from, int size, + u8 token) { struct mlx5_cmd_prot_block *block; struct mlx5_cmd_mailbox *next; @@ -870,6 +887,7 @@ static int mlx5_copy_to_msg(struct mlx5_cmd_msg *to, void *from, int size) memcpy(block->data, from, copy); from += copy; size -= copy; + block->token = token; next = next->next; } @@ -939,7 +957,8 @@ static void free_cmd_box(struct mlx5_core_dev *dev, } static struct mlx5_cmd_msg *mlx5_alloc_cmd_msg(struct mlx5_core_dev *dev, - gfp_t flags, int size) + gfp_t flags, int size, + u8 token) { struct mlx5_cmd_mailbox *tmp, *head = NULL; struct mlx5_cmd_prot_block *block; @@ -968,6 +987,7 @@ static struct mlx5_cmd_msg *mlx5_alloc_cmd_msg(struct mlx5_core_dev *dev, tmp->next = head; block->next = cpu_to_be64(tmp->next ? tmp->next->dma : 0); block->block_num = cpu_to_be32(n - i - 1); + block->token = token; head = tmp; } msg->next = head; @@ -1351,7 +1371,7 @@ static struct mlx5_cmd_msg *alloc_msg(struct mlx5_core_dev *dev, int in_size, } if (IS_ERR(msg)) - msg = mlx5_alloc_cmd_msg(dev, gfp, in_size); + msg = mlx5_alloc_cmd_msg(dev, gfp, in_size, 0); return msg; } @@ -1376,6 +1396,7 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, int err; u8 status = 0; u32 drv_synd; + u8 token; if (pci_channel_offline(dev->pdev) || dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { @@ -1394,20 +1415,22 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, return err; } - err = mlx5_copy_to_msg(inb, in, in_size); + token = alloc_token(&dev->cmd); + + err = mlx5_copy_to_msg(inb, in, in_size, token); if (err) { mlx5_core_warn(dev, "err %d\n", err); goto out_in; } - outb = mlx5_alloc_cmd_msg(dev, gfp, out_size); + outb = mlx5_alloc_cmd_msg(dev, gfp, out_size, token); if (IS_ERR(outb)) { err = PTR_ERR(outb); goto out_in; } err = mlx5_cmd_invoke(dev, inb, outb, out, out_size, callback, context, - pages_queue, &status); + pages_queue, &status, token); if (err) goto out_out; @@ -1475,7 +1498,7 @@ static int create_msg_cache(struct mlx5_core_dev *dev) INIT_LIST_HEAD(&cmd->cache.med.head); for (i = 0; i < NUM_LONG_LISTS; i++) { - msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, LONG_LIST_SIZE); + msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, LONG_LIST_SIZE, 0); if (IS_ERR(msg)) { err = PTR_ERR(msg); goto ex_err; @@ -1485,7 +1508,7 @@ static int create_msg_cache(struct mlx5_core_dev *dev) } for (i = 0; i < NUM_MED_LISTS; i++) { - msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, MED_LIST_SIZE); + msg = mlx5_alloc_cmd_msg(dev, GFP_KERNEL, MED_LIST_SIZE, 0); if (IS_ERR(msg)) { err = PTR_ERR(msg); goto ex_err; diff --git a/drivers/net/ethernet/msm/msm_rmnet_mhi.c b/drivers/net/ethernet/msm/msm_rmnet_mhi.c index 50d8e72a96c8..9117ea7d08c0 100644 --- a/drivers/net/ethernet/msm/msm_rmnet_mhi.c +++ b/drivers/net/ethernet/msm/msm_rmnet_mhi.c @@ -26,18 +26,16 @@ #include <linux/ipc_logging.h> #include <linux/device.h> #include <linux/errno.h> +#include <linux/of_device.h> #define RMNET_MHI_DRIVER_NAME "rmnet_mhi" #define RMNET_MHI_DEV_NAME "rmnet_mhi%d" #define MHI_DEFAULT_MTU 8000 -#define MHI_DEFAULT_MRU 8000 #define MHI_MAX_MRU 0xFFFF #define MHI_NAPI_WEIGHT_VALUE 12 #define MHI_RX_HEADROOM 64 #define WATCHDOG_TIMEOUT (30 * HZ) -#define MHI_RMNET_DEVICE_COUNT 1 #define RMNET_IPC_LOG_PAGES (100) -#define IS_INBOUND(_chan) (((u32)(_chan)) % 2) enum DBG_LVL { MSG_VERBOSE = 0x1, @@ -49,110 +47,69 @@ enum DBG_LVL { MSG_reserved = 0x80000000 }; +struct debug_params { + enum DBG_LVL rmnet_msg_lvl; + enum DBG_LVL rmnet_ipc_log_lvl; + u64 tx_interrupts_count; + u64 rx_interrupts_count; + u64 tx_ring_full_count; + u64 tx_queued_packets_count; + u64 rx_interrupts_in_masked_irq; + u64 rx_napi_skb_burst_min; + u64 rx_napi_skb_burst_max; + u64 tx_cb_skb_free_burst_min; + u64 tx_cb_skb_free_burst_max; + u64 rx_napi_budget_overflow; + u64 rx_fragmentation; +}; + struct __packed mhi_skb_priv { dma_addr_t dma_addr; size_t dma_size; }; -enum DBG_LVL rmnet_msg_lvl = MSG_CRITICAL; - -#ifdef CONFIG_MSM_MHI_DEBUG -enum DBG_LVL rmnet_ipc_log_lvl = MSG_VERBOSE; -#else -enum DBG_LVL rmnet_ipc_log_lvl = MSG_ERROR; -#endif - -module_param(rmnet_msg_lvl , uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(rmnet_msg_lvl, "dbg lvl"); -module_param(rmnet_ipc_log_lvl, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(rmnet_ipc_log_lvl, "dbg lvl"); - -unsigned int mru = MHI_DEFAULT_MRU; -module_param(mru, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(mru, "MRU interface setting"); - -void *rmnet_ipc_log; - -#define rmnet_log(_msg_lvl, _msg, ...) do { \ - if ((_msg_lvl) >= rmnet_msg_lvl) \ +#define rmnet_log(rmnet_mhi_ptr, _msg_lvl, _msg, ...) do { \ + if ((_msg_lvl) >= rmnet_mhi_ptr->debug.rmnet_msg_lvl) \ pr_alert("[%s] " _msg, __func__, ##__VA_ARGS__);\ - if (rmnet_ipc_log && ((_msg_lvl) >= rmnet_ipc_log_lvl)) \ - ipc_log_string(rmnet_ipc_log, \ + if (rmnet_mhi_ptr->rmnet_ipc_log && \ + ((_msg_lvl) >= rmnet_mhi_ptr->debug.rmnet_ipc_log_lvl)) \ + ipc_log_string(rmnet_mhi_ptr->rmnet_ipc_log, \ "[%s] " _msg, __func__, ##__VA_ARGS__); \ } while (0) -unsigned long tx_interrupts_count[MHI_RMNET_DEVICE_COUNT]; -module_param_array(tx_interrupts_count, ulong, 0, S_IRUGO); -MODULE_PARM_DESC(tx_interrupts_count, "Tx interrupts"); - -unsigned long rx_interrupts_count[MHI_RMNET_DEVICE_COUNT]; -module_param_array(rx_interrupts_count, ulong, 0, S_IRUGO); -MODULE_PARM_DESC(rx_interrupts_count, "RX interrupts"); - -unsigned long tx_ring_full_count[MHI_RMNET_DEVICE_COUNT]; -module_param_array(tx_ring_full_count, ulong, 0, S_IRUGO); -MODULE_PARM_DESC(tx_ring_full_count, "RING FULL errors from MHI Core"); - - -unsigned long tx_queued_packets_count[MHI_RMNET_DEVICE_COUNT]; -module_param_array(tx_queued_packets_count, ulong, 0, S_IRUGO); -MODULE_PARM_DESC(tx_queued_packets_count, "TX packets queued in MHI core"); - -unsigned long rx_interrupts_in_masked_irq[MHI_RMNET_DEVICE_COUNT]; -module_param_array(rx_interrupts_in_masked_irq, ulong, 0, S_IRUGO); -MODULE_PARM_DESC(rx_interrupts_in_masked_irq, - "RX interrupts while IRQs are masked"); - -unsigned long rx_napi_skb_burst_min[MHI_RMNET_DEVICE_COUNT]; -module_param_array(rx_napi_skb_burst_min, ulong, 0, S_IRUGO); -MODULE_PARM_DESC(rx_napi_skb_burst_min, "MIN SKBs sent to NS during NAPI"); - -unsigned long rx_napi_skb_burst_max[MHI_RMNET_DEVICE_COUNT]; -module_param_array(rx_napi_skb_burst_max, ulong, 0, S_IRUGO); -MODULE_PARM_DESC(rx_napi_skb_burst_max, "MAX SKBs sent to NS during NAPI"); - -unsigned long tx_cb_skb_free_burst_min[MHI_RMNET_DEVICE_COUNT]; -module_param_array(tx_cb_skb_free_burst_min, ulong, 0, S_IRUGO); -MODULE_PARM_DESC(tx_cb_skb_free_burst_min, "MIN SKBs freed during TX CB"); - -unsigned long tx_cb_skb_free_burst_max[MHI_RMNET_DEVICE_COUNT]; -module_param_array(tx_cb_skb_free_burst_max, ulong, 0, S_IRUGO); -MODULE_PARM_DESC(tx_cb_skb_free_burst_max, "MAX SKBs freed during TX CB"); - -unsigned long rx_napi_budget_overflow[MHI_RMNET_DEVICE_COUNT]; -module_param_array(rx_napi_budget_overflow, ulong, 0, S_IRUGO); -MODULE_PARM_DESC(rx_napi_budget_overflow, - "Budget hit with more items to read counter"); - -unsigned long rx_fragmentation[MHI_RMNET_DEVICE_COUNT]; -module_param_array(rx_fragmentation, ulong, 0, S_IRUGO); -MODULE_PARM_DESC(rx_fragmentation, - "Number of fragmented packets received"); - struct rmnet_mhi_private { - int dev_index; + struct list_head node; struct mhi_client_handle *tx_client_handle; struct mhi_client_handle *rx_client_handle; enum MHI_CLIENT_CHANNEL tx_channel; enum MHI_CLIENT_CHANNEL rx_channel; struct sk_buff_head tx_buffers; struct sk_buff_head rx_buffers; - uint32_t mru; + atomic_t rx_pool_len; + u32 mru; struct napi_struct napi; gfp_t allocation_flags; uint32_t tx_buffers_max; uint32_t rx_buffers_max; + u32 alloc_fail; u32 tx_enabled; u32 rx_enabled; u32 mhi_enabled; + struct platform_device *pdev; struct net_device *dev; atomic_t irq_masked_cntr; - rwlock_t out_chan_full_lock; + spinlock_t out_chan_full_lock; /* tx queue lock */ atomic_t pending_data; struct sk_buff *frag_skb; + struct work_struct alloc_work; + /* lock to queue hardware and internal queue */ + spinlock_t alloc_lock; + void *rmnet_ipc_log; + struct debug_params debug; + struct dentry *dentry; }; -static struct rmnet_mhi_private rmnet_mhi_ctxt_list[MHI_RMNET_DEVICE_COUNT]; +static LIST_HEAD(rmnet_mhi_ctxt_list); static int rmnet_mhi_process_fragment(struct rmnet_mhi_private *rmnet_mhi_ptr, struct sk_buff *skb, int frag) @@ -184,7 +141,7 @@ static int rmnet_mhi_process_fragment(struct rmnet_mhi_private *rmnet_mhi_ptr, if (frag) { /* This is the first fragment */ rmnet_mhi_ptr->frag_skb = skb; - rx_fragmentation[rmnet_mhi_ptr->dev_index]++; + rmnet_mhi_ptr->debug.rx_fragmentation++; } else { netif_receive_skb(skb); } @@ -196,8 +153,10 @@ static void rmnet_mhi_internal_clean_unmap_buffers(struct net_device *dev, enum dma_data_direction dir) { struct mhi_skb_priv *skb_priv; + struct rmnet_mhi_private *rmnet_mhi_ptr = + *(struct rmnet_mhi_private **)netdev_priv(dev); - rmnet_log(MSG_INFO, "Entered\n"); + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Entered\n"); while (!skb_queue_empty(queue)) { struct sk_buff *skb = skb_dequeue(queue); skb_priv = (struct mhi_skb_priv *)(skb->cb); @@ -205,7 +164,7 @@ static void rmnet_mhi_internal_clean_unmap_buffers(struct net_device *dev, kfree_skb(skb); } } - rmnet_log(MSG_INFO, "Exited\n"); + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Exited\n"); } static __be16 rmnet_mhi_ip_type_trans(struct sk_buff *skb) @@ -228,6 +187,83 @@ static __be16 rmnet_mhi_ip_type_trans(struct sk_buff *skb) return protocol; } +static int rmnet_alloc_rx(struct rmnet_mhi_private *rmnet_mhi_ptr, + gfp_t alloc_flags) +{ + u32 cur_mru = rmnet_mhi_ptr->mru; + struct mhi_skb_priv *skb_priv; + unsigned long flags; + int ret; + struct sk_buff *skb; + + while (atomic_read(&rmnet_mhi_ptr->rx_pool_len) < + rmnet_mhi_ptr->rx_buffers_max) { + skb = alloc_skb(cur_mru, alloc_flags); + if (!skb) { + rmnet_log(rmnet_mhi_ptr, + MSG_INFO, + "SKB Alloc failed with flags:0x%x\n", + alloc_flags); + return -ENOMEM; + } + skb_priv = (struct mhi_skb_priv *)(skb->cb); + skb_priv->dma_size = cur_mru - MHI_RX_HEADROOM; + skb_priv->dma_addr = 0; + skb_reserve(skb, MHI_RX_HEADROOM); + + /* These steps must be in atomic context */ + spin_lock_irqsave(&rmnet_mhi_ptr->alloc_lock, flags); + + /* It's possible by the time alloc_skb (GFP_KERNEL) + * returns we already called rmnet_alloc_rx + * in atomic context and allocated memory using + * GFP_ATOMIC and returned. + */ + if (unlikely(atomic_read(&rmnet_mhi_ptr->rx_pool_len) >= + rmnet_mhi_ptr->rx_buffers_max)) { + spin_unlock_irqrestore(&rmnet_mhi_ptr->alloc_lock, + flags); + dev_kfree_skb_any(skb); + return 0; + } + + ret = mhi_queue_xfer( + rmnet_mhi_ptr->rx_client_handle, + skb->data, + skb_priv->dma_size, + MHI_EOT); + if (unlikely(ret != 0)) { + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "mhi_queue_xfer failed, error %d", ret); + spin_unlock_irqrestore(&rmnet_mhi_ptr->alloc_lock, + flags); + dev_kfree_skb_any(skb); + return ret; + } + skb_queue_tail(&rmnet_mhi_ptr->rx_buffers, skb); + atomic_inc(&rmnet_mhi_ptr->rx_pool_len); + spin_unlock_irqrestore(&rmnet_mhi_ptr->alloc_lock, flags); + } + + return 0; +} + +static void rmnet_mhi_alloc_work(struct work_struct *work) +{ + struct rmnet_mhi_private *rmnet_mhi_ptr = container_of(work, + struct rmnet_mhi_private, + alloc_work); + int ret; + + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Entered\n"); + ret = rmnet_alloc_rx(rmnet_mhi_ptr, + rmnet_mhi_ptr->allocation_flags); + + WARN_ON(ret == -ENOMEM); + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Exit\n"); +} + static int rmnet_mhi_poll(struct napi_struct *napi, int budget) { int received_packets = 0; @@ -238,20 +274,22 @@ static int rmnet_mhi_poll(struct napi_struct *napi, int budget) bool should_reschedule = true; struct sk_buff *skb; struct mhi_skb_priv *skb_priv; - int r, cur_mru; + int r; + + rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Entered\n"); - rmnet_log(MSG_VERBOSE, "Entered\n"); - rmnet_mhi_ptr->mru = mru; while (received_packets < budget) { struct mhi_result *result = mhi_poll(rmnet_mhi_ptr->rx_client_handle); if (result->transaction_status == -ENOTCONN) { - rmnet_log(MSG_INFO, + rmnet_log(rmnet_mhi_ptr, + MSG_INFO, "Transaction status not ready, continuing\n"); break; } else if (result->transaction_status != 0 && result->transaction_status != -EOVERFLOW) { - rmnet_log(MSG_CRITICAL, + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, "mhi_poll failed, error %d\n", result->transaction_status); break; @@ -259,15 +297,15 @@ static int rmnet_mhi_poll(struct napi_struct *napi, int budget) /* Nothing more to read, or out of buffers in MHI layer */ if (unlikely(!result->buf_addr || !result->bytes_xferd)) { - rmnet_log(MSG_CRITICAL, - "Not valid buff not rescheduling\n"); should_reschedule = false; break; } + atomic_dec(&rmnet_mhi_ptr->rx_pool_len); skb = skb_dequeue(&(rmnet_mhi_ptr->rx_buffers)); if (unlikely(!skb)) { - rmnet_log(MSG_CRITICAL, + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, "No RX buffers to match"); break; } @@ -285,7 +323,7 @@ static int rmnet_mhi_poll(struct napi_struct *napi, int budget) else r = rmnet_mhi_process_fragment(rmnet_mhi_ptr, skb, 0); if (r) { - rmnet_log(MSG_CRITICAL, + rmnet_log(rmnet_mhi_ptr, MSG_CRITICAL, "Failed to process fragmented packet ret %d", r); BUG(); @@ -296,45 +334,18 @@ static int rmnet_mhi_poll(struct napi_struct *napi, int budget) dev->stats.rx_packets++; dev->stats.rx_bytes += result->bytes_xferd; - /* Need to allocate a new buffer instead of this one */ - cur_mru = rmnet_mhi_ptr->mru; - skb = alloc_skb(cur_mru, GFP_ATOMIC); - if (unlikely(!skb)) { - rmnet_log(MSG_CRITICAL, - "Can't allocate a new RX buffer for MHI"); - break; - } - skb_priv = (struct mhi_skb_priv *)(skb->cb); - skb_priv->dma_size = cur_mru; - - rmnet_log(MSG_VERBOSE, - "Allocated SKB of MRU 0x%x, SKB_DATA 0%p SKB_LEN 0x%x\n", - rmnet_mhi_ptr->mru, skb->data, skb->len); - /* Reserve headroom, tail == data */ - skb_reserve(skb, MHI_RX_HEADROOM); - skb_priv->dma_size -= MHI_RX_HEADROOM; - skb_priv->dma_addr = 0; - - rmnet_log(MSG_VERBOSE, - "Mapped SKB %p to DMA Addr 0x%lx, DMA_SIZE: 0x%lx\n", - skb->data, - (uintptr_t)skb->data, - (uintptr_t)skb_priv->dma_size); - - - res = mhi_queue_xfer( - rmnet_mhi_ptr->rx_client_handle, - skb->data, skb_priv->dma_size, MHI_EOT); - - if (unlikely(0 != res)) { - rmnet_log(MSG_CRITICAL, - "mhi_queue_xfer failed, error %d", res); - dev_kfree_skb_irq(skb); - break; - } - skb_queue_tail(&rmnet_mhi_ptr->rx_buffers, skb); } /* while (received_packets < budget) or any other error */ + /* Queue new buffers */ + res = rmnet_alloc_rx(rmnet_mhi_ptr, GFP_ATOMIC); + if (res == -ENOMEM) { + rmnet_log(rmnet_mhi_ptr, + MSG_INFO, + "out of mem, queuing bg worker\n"); + rmnet_mhi_ptr->alloc_fail++; + schedule_work(&rmnet_mhi_ptr->alloc_work); + } + napi_complete(napi); /* We got a NULL descriptor back */ @@ -342,22 +353,24 @@ static int rmnet_mhi_poll(struct napi_struct *napi, int budget) if (atomic_read(&rmnet_mhi_ptr->irq_masked_cntr)) { atomic_dec(&rmnet_mhi_ptr->irq_masked_cntr); mhi_unmask_irq(rmnet_mhi_ptr->rx_client_handle); + mhi_set_lpm(rmnet_mhi_ptr->rx_client_handle, true); } } else { if (received_packets == budget) - rx_napi_budget_overflow[rmnet_mhi_ptr->dev_index]++; + rmnet_mhi_ptr->debug.rx_napi_budget_overflow++; napi_reschedule(napi); } - rx_napi_skb_burst_min[rmnet_mhi_ptr->dev_index] = - min((unsigned long)received_packets, - rx_napi_skb_burst_min[rmnet_mhi_ptr->dev_index]); + rmnet_mhi_ptr->debug.rx_napi_skb_burst_min = + min((u64)received_packets, + rmnet_mhi_ptr->debug.rx_napi_skb_burst_min); - rx_napi_skb_burst_max[rmnet_mhi_ptr->dev_index] = - max((unsigned long)received_packets, - rx_napi_skb_burst_max[rmnet_mhi_ptr->dev_index]); + rmnet_mhi_ptr->debug.rx_napi_skb_burst_max = + max((u64)received_packets, + rmnet_mhi_ptr->debug.rx_napi_skb_burst_max); - rmnet_log(MSG_VERBOSE, "Exited, polled %d pkts\n", received_packets); + rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, + "Exited, polled %d pkts\n", received_packets); return received_packets; } @@ -365,7 +378,8 @@ void rmnet_mhi_clean_buffers(struct net_device *dev) { struct rmnet_mhi_private *rmnet_mhi_ptr = *(struct rmnet_mhi_private **)netdev_priv(dev); - rmnet_log(MSG_INFO, "Entered\n"); + + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Entered\n"); /* Clean TX buffers */ rmnet_mhi_internal_clean_unmap_buffers(dev, &rmnet_mhi_ptr->tx_buffers, @@ -375,16 +389,16 @@ void rmnet_mhi_clean_buffers(struct net_device *dev) rmnet_mhi_internal_clean_unmap_buffers(dev, &rmnet_mhi_ptr->rx_buffers, DMA_FROM_DEVICE); - rmnet_log(MSG_INFO, "Exited\n"); + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Exited\n"); } static int rmnet_mhi_disable_channels(struct rmnet_mhi_private *rmnet_mhi_ptr) { - rmnet_log(MSG_INFO, "Closing MHI TX channel\n"); + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Closing MHI TX channel\n"); mhi_close_channel(rmnet_mhi_ptr->tx_client_handle); - rmnet_log(MSG_INFO, "Closing MHI RX channel\n"); + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Closing MHI RX channel\n"); mhi_close_channel(rmnet_mhi_ptr->rx_client_handle); - rmnet_log(MSG_INFO, "Clearing Pending TX buffers.\n"); + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Clearing Pending TX buffers.\n"); rmnet_mhi_clean_buffers(rmnet_mhi_ptr->dev); rmnet_mhi_ptr->tx_client_handle = NULL; rmnet_mhi_ptr->rx_client_handle = NULL; @@ -394,52 +408,19 @@ static int rmnet_mhi_disable_channels(struct rmnet_mhi_private *rmnet_mhi_ptr) static int rmnet_mhi_init_inbound(struct rmnet_mhi_private *rmnet_mhi_ptr) { - u32 i; int res; - struct mhi_skb_priv *rx_priv; - u32 cur_mru = rmnet_mhi_ptr->mru; - struct sk_buff *skb; - rmnet_log(MSG_INFO, "Entered\n"); + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Entered\n"); rmnet_mhi_ptr->tx_buffers_max = mhi_get_max_desc( rmnet_mhi_ptr->tx_client_handle); rmnet_mhi_ptr->rx_buffers_max = mhi_get_max_desc( rmnet_mhi_ptr->rx_client_handle); + atomic_set(&rmnet_mhi_ptr->rx_pool_len, 0); + res = rmnet_alloc_rx(rmnet_mhi_ptr, + rmnet_mhi_ptr->allocation_flags); - for (i = 0; i < rmnet_mhi_ptr->rx_buffers_max; i++) { - - skb = alloc_skb(cur_mru, rmnet_mhi_ptr->allocation_flags); - - if (!skb) { - rmnet_log(MSG_CRITICAL, - "SKB allocation failure during open"); - return -ENOMEM; - } - rx_priv = (struct mhi_skb_priv *)(skb->cb); - - skb_reserve(skb, MHI_RX_HEADROOM); - rx_priv->dma_size = cur_mru - MHI_RX_HEADROOM; - rx_priv->dma_addr = 0; - skb_queue_tail(&rmnet_mhi_ptr->rx_buffers, skb); - } - - /* Submit the RX buffers */ - for (i = 0; i < rmnet_mhi_ptr->rx_buffers_max; i++) { - skb = skb_dequeue(&rmnet_mhi_ptr->rx_buffers); - rx_priv = (struct mhi_skb_priv *)(skb->cb); - res = mhi_queue_xfer(rmnet_mhi_ptr->rx_client_handle, - skb->data, - rx_priv->dma_size, - MHI_EOT); - if (0 != res) { - rmnet_log(MSG_CRITICAL, - "mhi_queue_xfer failed, error %d", res); - return -EIO; - } - skb_queue_tail(&rmnet_mhi_ptr->rx_buffers, skb); - } - rmnet_log(MSG_INFO, "Exited\n"); - return 0; + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Exited with %d\n", res); + return res; } static void rmnet_mhi_tx_cb(struct mhi_result *result) @@ -451,9 +432,9 @@ static void rmnet_mhi_tx_cb(struct mhi_result *result) rmnet_mhi_ptr = result->user_data; dev = rmnet_mhi_ptr->dev; - tx_interrupts_count[rmnet_mhi_ptr->dev_index]++; + rmnet_mhi_ptr->debug.tx_interrupts_count++; - rmnet_log(MSG_VERBOSE, "Entered\n"); + rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Entered\n"); if (!result->buf_addr || !result->bytes_xferd) return; /* Free the buffers which are TX'd up to the provided address */ @@ -461,7 +442,8 @@ static void rmnet_mhi_tx_cb(struct mhi_result *result) struct sk_buff *skb = skb_dequeue(&(rmnet_mhi_ptr->tx_buffers)); if (!skb) { - rmnet_log(MSG_CRITICAL, + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, "NULL buffer returned, error"); break; } else { @@ -482,20 +464,21 @@ static void rmnet_mhi_tx_cb(struct mhi_result *result) */ } } /* While TX queue is not empty */ - tx_cb_skb_free_burst_min[rmnet_mhi_ptr->dev_index] = - min(burst_counter, - tx_cb_skb_free_burst_min[rmnet_mhi_ptr->dev_index]); - tx_cb_skb_free_burst_max[rmnet_mhi_ptr->dev_index] = - max(burst_counter, - tx_cb_skb_free_burst_max[rmnet_mhi_ptr->dev_index]); + rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_min = + min((u64)burst_counter, + rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_min); + + rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_max = + max((u64)burst_counter, + rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_max); /* In case we couldn't write again, now we can! */ - read_lock_irqsave(&rmnet_mhi_ptr->out_chan_full_lock, flags); - rmnet_log(MSG_VERBOSE, "Waking up queue\n"); + spin_lock_irqsave(&rmnet_mhi_ptr->out_chan_full_lock, flags); + rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Waking up queue\n"); netif_wake_queue(dev); - read_unlock_irqrestore(&rmnet_mhi_ptr->out_chan_full_lock, flags); - rmnet_log(MSG_VERBOSE, "Exited\n"); + spin_unlock_irqrestore(&rmnet_mhi_ptr->out_chan_full_lock, flags); + rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Exited\n"); } static void rmnet_mhi_rx_cb(struct mhi_result *result) @@ -505,17 +488,18 @@ static void rmnet_mhi_rx_cb(struct mhi_result *result) rmnet_mhi_ptr = result->user_data; dev = rmnet_mhi_ptr->dev; - rmnet_log(MSG_VERBOSE, "Entered\n"); - rx_interrupts_count[rmnet_mhi_ptr->dev_index]++; + rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Entered\n"); + rmnet_mhi_ptr->debug.rx_interrupts_count++; if (napi_schedule_prep(&(rmnet_mhi_ptr->napi))) { mhi_mask_irq(rmnet_mhi_ptr->rx_client_handle); atomic_inc(&rmnet_mhi_ptr->irq_masked_cntr); + mhi_set_lpm(rmnet_mhi_ptr->rx_client_handle, false); __napi_schedule(&(rmnet_mhi_ptr->napi)); } else { - rx_interrupts_in_masked_irq[rmnet_mhi_ptr->dev_index]++; + rmnet_mhi_ptr->debug.rx_interrupts_in_masked_irq++; } - rmnet_log(MSG_VERBOSE, "Exited\n"); + rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Exited\n"); } static int rmnet_mhi_open(struct net_device *dev) @@ -523,11 +507,19 @@ static int rmnet_mhi_open(struct net_device *dev) struct rmnet_mhi_private *rmnet_mhi_ptr = *(struct rmnet_mhi_private **)netdev_priv(dev); - rmnet_log(MSG_INFO, - "Opened net dev interface for MHI chans %d and %d\n", - rmnet_mhi_ptr->tx_channel, - rmnet_mhi_ptr->rx_channel); - netif_start_queue(dev); + rmnet_log(rmnet_mhi_ptr, + MSG_INFO, + "Opened net dev interface for MHI chans %d and %d\n", + rmnet_mhi_ptr->tx_channel, + rmnet_mhi_ptr->rx_channel); + + /* tx queue may not necessarily be stopped already + * so stop the queue if tx path is not enabled + */ + if (!rmnet_mhi_ptr->tx_client_handle) + netif_stop_queue(dev); + else + netif_start_queue(dev); /* Poll to check if any buffers are accumulated in the * transport buffers @@ -535,9 +527,10 @@ static int rmnet_mhi_open(struct net_device *dev) if (napi_schedule_prep(&(rmnet_mhi_ptr->napi))) { mhi_mask_irq(rmnet_mhi_ptr->rx_client_handle); atomic_inc(&rmnet_mhi_ptr->irq_masked_cntr); + mhi_set_lpm(rmnet_mhi_ptr->rx_client_handle, false); __napi_schedule(&(rmnet_mhi_ptr->napi)); } else { - rx_interrupts_in_masked_irq[rmnet_mhi_ptr->dev_index]++; + rmnet_mhi_ptr->debug.rx_interrupts_in_masked_irq++; } return 0; @@ -575,14 +568,17 @@ static int rmnet_mhi_stop(struct net_device *dev) { struct rmnet_mhi_private *rmnet_mhi_ptr = *(struct rmnet_mhi_private **)netdev_priv(dev); + netif_stop_queue(dev); - rmnet_log(MSG_VERBOSE, "Entered\n"); + rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Entered\n"); if (atomic_read(&rmnet_mhi_ptr->irq_masked_cntr)) { mhi_unmask_irq(rmnet_mhi_ptr->rx_client_handle); atomic_dec(&rmnet_mhi_ptr->irq_masked_cntr); - rmnet_log(MSG_ERROR, "IRQ was masked, unmasking...\n"); + rmnet_log(rmnet_mhi_ptr, + MSG_ERROR, + "IRQ was masked, unmasking...\n"); } - rmnet_log(MSG_VERBOSE, "Exited\n"); + rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Exited\n"); return 0; } @@ -601,61 +597,53 @@ static int rmnet_mhi_xmit(struct sk_buff *skb, struct net_device *dev) *(struct rmnet_mhi_private **)netdev_priv(dev); int res = 0; unsigned long flags; - int retry = 0; struct mhi_skb_priv *tx_priv; - rmnet_log(MSG_VERBOSE, "Entered chan %d\n", rmnet_mhi_ptr->tx_channel); + rmnet_log(rmnet_mhi_ptr, + MSG_VERBOSE, + "Entered chan %d\n", + rmnet_mhi_ptr->tx_channel); tx_priv = (struct mhi_skb_priv *)(skb->cb); tx_priv->dma_size = skb->len; tx_priv->dma_addr = 0; - do { - retry = 0; - res = mhi_queue_xfer(rmnet_mhi_ptr->tx_client_handle, - skb->data, - skb->len, - MHI_EOT); - - if (-ENOSPC == res) { - write_lock_irqsave(&rmnet_mhi_ptr->out_chan_full_lock, - flags); - if (!mhi_get_free_desc( - rmnet_mhi_ptr->tx_client_handle)) { - /* Stop writing until we can write again */ - tx_ring_full_count[rmnet_mhi_ptr->dev_index]++; - netif_stop_queue(dev); - rmnet_log(MSG_VERBOSE, "Stopping Queue\n"); - write_unlock_irqrestore( - &rmnet_mhi_ptr->out_chan_full_lock, - flags); - goto rmnet_mhi_xmit_error_cleanup; - } else { - retry = 1; - } - write_unlock_irqrestore( - &rmnet_mhi_ptr->out_chan_full_lock, - flags); - } - } while (retry); - if (0 != res) { + if (mhi_get_free_desc(rmnet_mhi_ptr->tx_client_handle) <= 0) { + rmnet_log(rmnet_mhi_ptr, + MSG_VERBOSE, + "Stopping Queue\n"); + spin_lock_irqsave(&rmnet_mhi_ptr->out_chan_full_lock, + flags); + rmnet_mhi_ptr->debug.tx_ring_full_count++; + netif_stop_queue(dev); + spin_unlock_irqrestore(&rmnet_mhi_ptr->out_chan_full_lock, + flags); + return NETDEV_TX_BUSY; + } + res = mhi_queue_xfer(rmnet_mhi_ptr->tx_client_handle, + skb->data, + skb->len, + MHI_EOT); + + if (res != 0) { + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "Failed to queue with reason:%d\n", + res); + spin_lock_irqsave(&rmnet_mhi_ptr->out_chan_full_lock, + flags); netif_stop_queue(dev); - rmnet_log(MSG_CRITICAL, - "mhi_queue_xfer failed, error %d\n", res); - goto rmnet_mhi_xmit_error_cleanup; + spin_unlock_irqrestore(&rmnet_mhi_ptr->out_chan_full_lock, + flags); + return NETDEV_TX_BUSY; } skb_queue_tail(&(rmnet_mhi_ptr->tx_buffers), skb); - dev->trans_start = jiffies; + rmnet_mhi_ptr->debug.tx_queued_packets_count++; - tx_queued_packets_count[rmnet_mhi_ptr->dev_index]++; - rmnet_log(MSG_VERBOSE, "Exited\n"); - return 0; - -rmnet_mhi_xmit_error_cleanup: - rmnet_log(MSG_VERBOSE, "Ring full\n"); - return NETDEV_TX_BUSY; + rmnet_log(rmnet_mhi_ptr, MSG_VERBOSE, "Exited\n"); + return NETDEV_TX_OK; } static int rmnet_mhi_ioctl_extended(struct net_device *dev, struct ifreq *ifr) @@ -670,24 +658,27 @@ static int rmnet_mhi_ioctl_extended(struct net_device *dev, struct ifreq *ifr) sizeof(struct rmnet_ioctl_extended_s)); if (rc) { - rmnet_log(MSG_CRITICAL, - "copy_from_user failed ,error %d", rc); + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "copy_from_user failed ,error %d", + rc); return rc; } switch (ext_cmd.extended_ioctl) { case RMNET_IOCTL_SET_MRU: - if ((0 > ext_cmd.u.data) || (ext_cmd.u.data > MHI_MAX_MRU)) { - rmnet_log(MSG_CRITICAL, - "Can't set MRU, value %u is invalid\n", - ext_cmd.u.data); + if (!ext_cmd.u.data || ext_cmd.u.data > MHI_MAX_MRU) { + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "Can't set MRU, value %u is invalid\n", + ext_cmd.u.data); return -EINVAL; } - rmnet_log(MSG_INFO, - "MRU change request to 0x%x\n", - ext_cmd.u.data); - mru = ext_cmd.u.data; - rmnet_mhi_ptr->mru = mru; + rmnet_log(rmnet_mhi_ptr, + MSG_INFO, + "MRU change request to 0x%x\n", + ext_cmd.u.data); + rmnet_mhi_ptr->mru = ext_cmd.u.data; break; case RMNET_IOCTL_GET_EPID: ext_cmd.u.data = @@ -706,7 +697,8 @@ static int rmnet_mhi_ioctl_extended(struct net_device *dev, struct ifreq *ifr) mhi_set_lpm(rmnet_mhi_ptr->tx_client_handle, ext_cmd.u.data); } else { - rmnet_log(MSG_ERROR, + rmnet_log(rmnet_mhi_ptr, + MSG_ERROR, "Cannot set LPM value, MHI is not up.\n"); return -ENODEV; } @@ -720,9 +712,10 @@ static int rmnet_mhi_ioctl_extended(struct net_device *dev, struct ifreq *ifr) sizeof(struct rmnet_ioctl_extended_s)); if (rc) - rmnet_log(MSG_CRITICAL, - "copy_to_user failed, error %d\n", - rc); + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "copy_to_user failed, error %d\n", + rc); return rc; } @@ -801,50 +794,49 @@ static int rmnet_mhi_enable_iface(struct rmnet_mhi_private *rmnet_mhi_ptr) struct rmnet_mhi_private **rmnet_mhi_ctxt = NULL; int r = 0; - memset(tx_interrupts_count, 0, sizeof(tx_interrupts_count)); - memset(rx_interrupts_count, 0, sizeof(rx_interrupts_count)); - memset(rx_interrupts_in_masked_irq, 0, - sizeof(rx_interrupts_in_masked_irq)); - memset(rx_napi_skb_burst_min, 0, sizeof(rx_napi_skb_burst_min)); - memset(rx_napi_skb_burst_max, 0, sizeof(rx_napi_skb_burst_max)); - memset(tx_cb_skb_free_burst_min, 0, sizeof(tx_cb_skb_free_burst_min)); - memset(tx_cb_skb_free_burst_max, 0, sizeof(tx_cb_skb_free_burst_max)); - memset(tx_ring_full_count, 0, sizeof(tx_ring_full_count)); - memset(tx_queued_packets_count, 0, sizeof(tx_queued_packets_count)); - memset(rx_napi_budget_overflow, 0, sizeof(rx_napi_budget_overflow)); - - rmnet_log(MSG_INFO, "Entered.\n"); - - if (rmnet_mhi_ptr == NULL) { - rmnet_log(MSG_CRITICAL, "Bad input args.\n"); - return -EINVAL; - } - - rx_napi_skb_burst_min[rmnet_mhi_ptr->dev_index] = UINT_MAX; - tx_cb_skb_free_burst_min[rmnet_mhi_ptr->dev_index] = UINT_MAX; + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Entered.\n"); + + rmnet_mhi_ptr->debug.tx_interrupts_count = 0; + rmnet_mhi_ptr->debug.rx_interrupts_count = 0; + rmnet_mhi_ptr->debug.rx_interrupts_in_masked_irq = 0; + rmnet_mhi_ptr->debug.rx_napi_skb_burst_min = 0; + rmnet_mhi_ptr->debug.rx_napi_skb_burst_max = 0; + rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_min = 0; + rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_max = 0; + rmnet_mhi_ptr->debug.tx_ring_full_count = 0; + rmnet_mhi_ptr->debug.tx_queued_packets_count = 0; + rmnet_mhi_ptr->debug.rx_napi_budget_overflow = 0; + rmnet_mhi_ptr->debug.rx_napi_skb_burst_min = UINT_MAX; + rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_min = UINT_MAX; skb_queue_head_init(&(rmnet_mhi_ptr->tx_buffers)); skb_queue_head_init(&(rmnet_mhi_ptr->rx_buffers)); if (rmnet_mhi_ptr->tx_client_handle != NULL) { - rmnet_log(MSG_INFO, - "Opening TX channel\n"); + rmnet_log(rmnet_mhi_ptr, + MSG_INFO, + "Opening TX channel\n"); r = mhi_open_channel(rmnet_mhi_ptr->tx_client_handle); if (r != 0) { - rmnet_log(MSG_CRITICAL, - "Failed to start TX chan ret %d\n", r); + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "Failed to start TX chan ret %d\n", + r); goto mhi_tx_chan_start_fail; } else { rmnet_mhi_ptr->tx_enabled = 1; } } if (rmnet_mhi_ptr->rx_client_handle != NULL) { - rmnet_log(MSG_INFO, - "Opening RX channel\n"); + rmnet_log(rmnet_mhi_ptr, + MSG_INFO, + "Opening RX channel\n"); r = mhi_open_channel(rmnet_mhi_ptr->rx_client_handle); if (r != 0) { - rmnet_log(MSG_CRITICAL, - "Failed to start RX chan ret %d\n", r); + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "Failed to start RX chan ret %d\n", + r); goto mhi_rx_chan_start_fail; } else { rmnet_mhi_ptr->rx_enabled = 1; @@ -855,11 +847,13 @@ static int rmnet_mhi_enable_iface(struct rmnet_mhi_private *rmnet_mhi_ptr) RMNET_MHI_DEV_NAME, NET_NAME_PREDICTABLE, rmnet_mhi_setup); if (!rmnet_mhi_ptr->dev) { - rmnet_log(MSG_CRITICAL, "Network device allocation failed\n"); + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "Network device allocation failed\n"); ret = -ENOMEM; goto net_dev_alloc_fail; } - + SET_NETDEV_DEV(rmnet_mhi_ptr->dev, &rmnet_mhi_ptr->pdev->dev); rmnet_mhi_ctxt = netdev_priv(rmnet_mhi_ptr->dev); *rmnet_mhi_ctxt = rmnet_mhi_ptr; @@ -872,8 +866,10 @@ static int rmnet_mhi_enable_iface(struct rmnet_mhi_private *rmnet_mhi_ptr) r = rmnet_mhi_init_inbound(rmnet_mhi_ptr); if (r) { - rmnet_log(MSG_CRITICAL, - "Failed to init inbound ret %d\n", r); + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "Failed to init inbound ret %d\n", + r); } netif_napi_add(rmnet_mhi_ptr->dev, &(rmnet_mhi_ptr->napi), @@ -882,13 +878,14 @@ static int rmnet_mhi_enable_iface(struct rmnet_mhi_private *rmnet_mhi_ptr) rmnet_mhi_ptr->mhi_enabled = 1; ret = register_netdev(rmnet_mhi_ptr->dev); if (ret) { - rmnet_log(MSG_CRITICAL, + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, "Network device registration failed\n"); goto net_dev_reg_fail; } napi_enable(&(rmnet_mhi_ptr->napi)); - rmnet_log(MSG_INFO, "Exited.\n"); + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Exited.\n"); return 0; @@ -901,7 +898,7 @@ net_dev_alloc_fail: mhi_rx_chan_start_fail: mhi_close_channel(rmnet_mhi_ptr->tx_client_handle); mhi_tx_chan_start_fail: - rmnet_log(MSG_INFO, "Exited ret %d.\n", ret); + rmnet_log(rmnet_mhi_ptr, MSG_INFO, "Exited ret %d.\n", ret); return ret; } @@ -911,52 +908,60 @@ static void rmnet_mhi_cb(struct mhi_cb_info *cb_info) struct mhi_result *result; int r = 0; - if (NULL != cb_info && NULL != cb_info->result) { - result = cb_info->result; - rmnet_mhi_ptr = result->user_data; - } else { - rmnet_log(MSG_CRITICAL, - "Invalid data in MHI callback, quitting\n"); + if (!cb_info || !cb_info->result) { + pr_err("%s: Invalid data in MHI callback\n", __func__); return; } + result = cb_info->result; + rmnet_mhi_ptr = result->user_data; + switch (cb_info->cb_reason) { case MHI_CB_MHI_DISABLED: - rmnet_log(MSG_CRITICAL, - "Got MHI_DISABLED notification. Stopping stack\n"); + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "Got MHI_DISABLED notification. Stopping stack\n"); if (rmnet_mhi_ptr->mhi_enabled) { rmnet_mhi_ptr->mhi_enabled = 0; /* Ensure MHI is disabled before other mem ops */ wmb(); while (atomic_read(&rmnet_mhi_ptr->pending_data)) { - rmnet_log(MSG_CRITICAL, - "Waiting for channels to stop.\n"); + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "Waiting for channels to stop.\n"); msleep(25); } rmnet_mhi_disable(rmnet_mhi_ptr); } break; case MHI_CB_MHI_ENABLED: - rmnet_log(MSG_CRITICAL, - "Got MHI_ENABLED notification. Starting stack\n"); - if (IS_INBOUND(cb_info->chan)) + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "Got MHI_ENABLED notification. Starting stack\n"); + if (cb_info->chan == rmnet_mhi_ptr->rx_channel) rmnet_mhi_ptr->rx_enabled = 1; else rmnet_mhi_ptr->tx_enabled = 1; - if (rmnet_mhi_ptr->tx_enabled && - rmnet_mhi_ptr->rx_enabled) { - rmnet_log(MSG_INFO, - "Both RX/TX are enabled, enabling iface.\n"); + if ((rmnet_mhi_ptr->tx_enabled && rmnet_mhi_ptr->rx_enabled) || + (rmnet_mhi_ptr->tx_enabled && + !rmnet_mhi_ptr->rx_client_handle) || + (rmnet_mhi_ptr->rx_enabled && + !rmnet_mhi_ptr->tx_client_handle)) { + rmnet_log(rmnet_mhi_ptr, + MSG_INFO, + "enabling iface.\n"); r = rmnet_mhi_enable_iface(rmnet_mhi_ptr); if (r) - rmnet_log(MSG_CRITICAL, - "Failed to enable iface for chan %d\n", - cb_info->chan); + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "Failed to enable iface for chan %d\n", + cb_info->chan); else - rmnet_log(MSG_INFO, - "Enabled iface for chan %d\n", - cb_info->chan); + rmnet_log(rmnet_mhi_ptr, + MSG_INFO, + "Enabled iface for chan %d\n", + cb_info->chan); } break; case MHI_CB_XFER: @@ -964,7 +969,7 @@ static void rmnet_mhi_cb(struct mhi_cb_info *cb_info) /* Flush pending data is set before any other mem operations */ wmb(); if (rmnet_mhi_ptr->mhi_enabled) { - if (IS_INBOUND(cb_info->chan)) + if (cb_info->chan == rmnet_mhi_ptr->rx_channel) rmnet_mhi_rx_cb(cb_info->result); else rmnet_mhi_tx_cb(cb_info->result); @@ -978,64 +983,261 @@ static void rmnet_mhi_cb(struct mhi_cb_info *cb_info) static struct mhi_client_info_t rmnet_mhi_info = {rmnet_mhi_cb}; -static int __init rmnet_mhi_init(void) +#ifdef CONFIG_DEBUG_FS +struct dentry *dentry; + +static void rmnet_mhi_create_debugfs(struct rmnet_mhi_private *rmnet_mhi_ptr) { + char node_name[15]; int i; - int res = 0; - struct rmnet_mhi_private *rmnet_mhi_ptr = 0; - rmnet_ipc_log = ipc_log_context_create(RMNET_IPC_LOG_PAGES, - "mhi_rmnet", 0); - - for (i = 0; i < MHI_RMNET_DEVICE_COUNT; i++) { - rmnet_mhi_ptr = &rmnet_mhi_ctxt_list[i]; - - rmnet_mhi_ptr->tx_channel = MHI_CLIENT_IP_HW_0_OUT + - (enum MHI_CLIENT_CHANNEL)(i * 2); - rmnet_mhi_ptr->rx_channel = MHI_CLIENT_IP_HW_0_IN + - (enum MHI_CLIENT_CHANNEL)((i * 2)); - - rmnet_mhi_ptr->tx_client_handle = 0; - rmnet_mhi_ptr->rx_client_handle = 0; - rwlock_init(&rmnet_mhi_ptr->out_chan_full_lock); - - rmnet_mhi_ptr->mru = MHI_DEFAULT_MRU; - rmnet_mhi_ptr->dev_index = i; - - res = mhi_register_channel( - &(rmnet_mhi_ptr->tx_client_handle), - rmnet_mhi_ptr->tx_channel, 0, - &rmnet_mhi_info, rmnet_mhi_ptr); - - if (0 != res) { - rmnet_mhi_ptr->tx_client_handle = 0; - rmnet_log(MSG_CRITICAL, - "mhi_register_channel failed chan %d ret %d\n", - rmnet_mhi_ptr->tx_channel, res); + const umode_t mode = (S_IRUSR | S_IWUSR); + struct dentry *file; + + const struct { + char *name; + u64 *ptr; + } debugfs_table[] = { + { + "tx_interrupts_count", + &rmnet_mhi_ptr->debug.tx_interrupts_count + }, + { + "rx_interrupts_count", + &rmnet_mhi_ptr->debug.rx_interrupts_count + }, + { + "tx_ring_full_count", + &rmnet_mhi_ptr->debug.tx_ring_full_count + }, + { + "tx_queued_packets_count", + &rmnet_mhi_ptr->debug.tx_queued_packets_count + }, + { + "rx_interrupts_in_masked_irq", + &rmnet_mhi_ptr-> + debug.rx_interrupts_in_masked_irq + }, + { + "rx_napi_skb_burst_min", + &rmnet_mhi_ptr->debug.rx_napi_skb_burst_min + }, + { + "rx_napi_skb_burst_max", + &rmnet_mhi_ptr->debug.rx_napi_skb_burst_max + }, + { + "tx_cb_skb_free_burst_min", + &rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_min + }, + { + "tx_cb_skb_free_burst_max", + &rmnet_mhi_ptr->debug.tx_cb_skb_free_burst_max + }, + { + "rx_napi_budget_overflow", + &rmnet_mhi_ptr->debug.rx_napi_budget_overflow + }, + { + "rx_fragmentation", + &rmnet_mhi_ptr->debug.rx_fragmentation + }, + { + NULL, NULL + }, + }; + + snprintf(node_name, sizeof(node_name), "%s%d", + RMNET_MHI_DRIVER_NAME, rmnet_mhi_ptr->pdev->id); + + if (IS_ERR_OR_NULL(dentry)) + return; + + rmnet_mhi_ptr->dentry = debugfs_create_dir(node_name, dentry); + if (IS_ERR_OR_NULL(rmnet_mhi_ptr->dentry)) + return; + + file = debugfs_create_u32("msg_lvl", + mode, + rmnet_mhi_ptr->dentry, + (u32 *)&rmnet_mhi_ptr->debug.rmnet_msg_lvl); + if (IS_ERR_OR_NULL(file)) + return; + + file = debugfs_create_u32("ipc_log_lvl", + mode, + rmnet_mhi_ptr->dentry, + (u32 *)&rmnet_mhi_ptr-> + debug.rmnet_ipc_log_lvl); + if (IS_ERR_OR_NULL(file)) + return; + + file = debugfs_create_u32("mru", + mode, + rmnet_mhi_ptr->dentry, + &rmnet_mhi_ptr->mru); + if (IS_ERR_OR_NULL(file)) + return; + + /* Add debug stats table */ + for (i = 0; debugfs_table[i].name; i++) { + file = debugfs_create_u64(debugfs_table[i].name, + mode, + rmnet_mhi_ptr->dentry, + debugfs_table[i].ptr); + if (IS_ERR_OR_NULL(file)) + return; + } +} + +static void rmnet_mhi_create_debugfs_dir(void) +{ + dentry = debugfs_create_dir(RMNET_MHI_DRIVER_NAME, 0); +} +#else +static void rmnet_mhi_create_debugfs(struct rmnet_mhi_private *rmnet_mhi_ptr) +{ +} + +static void rmnet_mhi_create_debugfs_dir(void) +{ +} +#endif + +static int rmnet_mhi_probe(struct platform_device *pdev) +{ + int rc; + u32 channel; + struct rmnet_mhi_private *rmnet_mhi_ptr; + char node_name[15]; + + if (unlikely(!pdev->dev.of_node)) + return -ENODEV; + + pdev->id = of_alias_get_id(pdev->dev.of_node, "mhi_rmnet"); + if (unlikely(pdev->id < 0)) + return -ENODEV; + + rmnet_mhi_ptr = kzalloc(sizeof(*rmnet_mhi_ptr), GFP_KERNEL); + if (unlikely(!rmnet_mhi_ptr)) + return -ENOMEM; + rmnet_mhi_ptr->pdev = pdev; + spin_lock_init(&rmnet_mhi_ptr->out_chan_full_lock); + + rc = of_property_read_u32(pdev->dev.of_node, + "qcom,mhi-mru", + &rmnet_mhi_ptr->mru); + if (unlikely(rc)) { + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "failed to get valid mru\n"); + goto probe_fail; + } + + rc = of_property_read_u32(pdev->dev.of_node, + "qcom,mhi-tx-channel", + &channel); + if (rc == 0) { + rmnet_mhi_ptr->tx_channel = channel; + rc = mhi_register_channel(&rmnet_mhi_ptr->tx_client_handle, + rmnet_mhi_ptr->tx_channel, + 0, + &rmnet_mhi_info, + rmnet_mhi_ptr); + if (unlikely(rc)) { + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "mhi_register_channel failed chan %d ret %d\n", + rmnet_mhi_ptr->tx_channel, + rc); + goto probe_fail; } - res = mhi_register_channel( - &(rmnet_mhi_ptr->rx_client_handle), - rmnet_mhi_ptr->rx_channel, 0, - &rmnet_mhi_info, rmnet_mhi_ptr); - - if (0 != res) { - rmnet_mhi_ptr->rx_client_handle = 0; - rmnet_log(MSG_CRITICAL, - "mhi_register_channel failed chan %d, ret %d\n", - rmnet_mhi_ptr->rx_channel, res); + } + + rc = of_property_read_u32(pdev->dev.of_node, + "qcom,mhi-rx-channel", + &channel); + if (rc == 0) { + rmnet_mhi_ptr->rx_channel = channel; + rc = mhi_register_channel(&rmnet_mhi_ptr->rx_client_handle, + rmnet_mhi_ptr->rx_channel, + 0, + &rmnet_mhi_info, + rmnet_mhi_ptr); + if (unlikely(rc)) { + rmnet_log(rmnet_mhi_ptr, + MSG_CRITICAL, + "mhi_register_channel failed chan %d ret %d\n", + rmnet_mhi_ptr->rx_channel, + rc); + goto probe_fail; } + + INIT_WORK(&rmnet_mhi_ptr->alloc_work, rmnet_mhi_alloc_work); + spin_lock_init(&rmnet_mhi_ptr->alloc_lock); } + + /* We must've have @ least one valid channel */ + if (!rmnet_mhi_ptr->rx_client_handle && + !rmnet_mhi_ptr->tx_client_handle) { + rmnet_log(rmnet_mhi_ptr, MSG_CRITICAL, + "No registered channels\n"); + rc = -ENODEV; + goto probe_fail; + } + + snprintf(node_name, sizeof(node_name), "%s%d", + RMNET_MHI_DRIVER_NAME, pdev->id); + rmnet_mhi_ptr->rmnet_ipc_log = + ipc_log_context_create(RMNET_IPC_LOG_PAGES, + node_name, 0); + rmnet_mhi_ptr->debug.rmnet_msg_lvl = MSG_CRITICAL; + +#ifdef CONFIG_MSM_MHI_DEBUG + rmnet_mhi_ptr->debug.rmnet_ipc_log_lvl = MSG_VERBOSE; +#else + rmnet_mhi_ptr->debug.rmnet_ipc_log_lvl = MSG_ERROR; +#endif + + rmnet_mhi_create_debugfs(rmnet_mhi_ptr); + list_add_tail(&rmnet_mhi_ptr->node, &rmnet_mhi_ctxt_list); return 0; + +probe_fail: + kfree(rmnet_mhi_ptr); + return rc; +} + +static const struct of_device_id msm_mhi_match_table[] = { + {.compatible = "qcom,mhi-rmnet"}, + {}, +}; + +static struct platform_driver rmnet_mhi_driver = { + .probe = rmnet_mhi_probe, + .driver = { + .name = RMNET_MHI_DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = msm_mhi_match_table, + }, +}; + +static int __init rmnet_mhi_init(void) +{ + rmnet_mhi_create_debugfs_dir(); + + return platform_driver_register(&rmnet_mhi_driver); } static void __exit rmnet_mhi_exit(void) { struct rmnet_mhi_private *rmnet_mhi_ptr = 0; - int index = 0; - for (index = 0; index < MHI_RMNET_DEVICE_COUNT; index++) { - rmnet_mhi_ptr = &rmnet_mhi_ctxt_list[index]; - mhi_deregister_channel(rmnet_mhi_ptr->tx_client_handle); - mhi_deregister_channel(rmnet_mhi_ptr->rx_client_handle); + list_for_each_entry(rmnet_mhi_ptr, &rmnet_mhi_ctxt_list, node) { + if (rmnet_mhi_ptr->tx_client_handle) + mhi_deregister_channel(rmnet_mhi_ptr->tx_client_handle); + if (rmnet_mhi_ptr->rx_client_handle) + mhi_deregister_channel(rmnet_mhi_ptr->rx_client_handle); } } diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 36fc9427418f..480f3dae0780 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -832,7 +832,7 @@ static struct sh_eth_cpu_data r7s72100_data = { .ecsr_value = ECSR_ICD, .ecsipr_value = ECSIPR_ICDIP, - .eesipr_value = 0xff7f009f, + .eesipr_value = 0xe77f009f, .tx_check = EESR_TC1 | EESR_FTC, .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 0e2fc1a844ab..23a038810083 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -540,7 +540,7 @@ static inline void smc_rcv(struct net_device *dev) #define smc_special_lock(lock, flags) spin_lock_irqsave(lock, flags) #define smc_special_unlock(lock, flags) spin_unlock_irqrestore(lock, flags) #else -#define smc_special_trylock(lock, flags) (flags == flags) +#define smc_special_trylock(lock, flags) ((void)flags, true) #define smc_special_lock(lock, flags) do { flags = 0; } while (0) #define smc_special_unlock(lock, flags) do { flags = 0; } while (0) #endif @@ -2269,6 +2269,13 @@ static int smc_drv_probe(struct platform_device *pdev) if (pd) { memcpy(&lp->cfg, pd, sizeof(lp->cfg)); lp->io_shift = SMC91X_IO_SHIFT(lp->cfg.flags); + + if (!SMC_8BIT(lp) && !SMC_16BIT(lp)) { + dev_err(&pdev->dev, + "at least one of 8-bit or 16-bit access support is required.\n"); + ret = -ENXIO; + goto out_free_netdev; + } } #if IS_BUILTIN(CONFIG_OF) diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index a3c129e1e40a..29df0465daf4 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h @@ -37,6 +37,27 @@ #include <linux/smc91x.h> /* + * Any 16-bit access is performed with two 8-bit accesses if the hardware + * can't do it directly. Most registers are 16-bit so those are mandatory. + */ +#define SMC_outw_b(x, a, r) \ + do { \ + unsigned int __val16 = (x); \ + unsigned int __reg = (r); \ + SMC_outb(__val16, a, __reg); \ + SMC_outb(__val16 >> 8, a, __reg + (1 << SMC_IO_SHIFT)); \ + } while (0) + +#define SMC_inw_b(a, r) \ + ({ \ + unsigned int __val16; \ + unsigned int __reg = r; \ + __val16 = SMC_inb(a, __reg); \ + __val16 |= SMC_inb(a, __reg + (1 << SMC_IO_SHIFT)) << 8; \ + __val16; \ + }) + +/* * Define your architecture specific bus configuration parameters here. */ @@ -55,10 +76,30 @@ #define SMC_IO_SHIFT (lp->io_shift) #define SMC_inb(a, r) readb((a) + (r)) -#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_inw(a, r) \ + ({ \ + unsigned int __smc_r = r; \ + SMC_16BIT(lp) ? readw((a) + __smc_r) : \ + SMC_8BIT(lp) ? SMC_inw_b(a, __smc_r) : \ + ({ BUG(); 0; }); \ + }) + #define SMC_inl(a, r) readl((a) + (r)) #define SMC_outb(v, a, r) writeb(v, (a) + (r)) +#define SMC_outw(v, a, r) \ + do { \ + unsigned int __v = v, __smc_r = r; \ + if (SMC_16BIT(lp)) \ + __SMC_outw(__v, a, __smc_r); \ + else if (SMC_8BIT(lp)) \ + SMC_outw_b(__v, a, __smc_r); \ + else \ + BUG(); \ + } while (0) + #define SMC_outl(v, a, r) writel(v, (a) + (r)) +#define SMC_insb(a, r, p, l) readsb((a) + (r), p, l) +#define SMC_outsb(a, r, p, l) writesb((a) + (r), p, l) #define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) #define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) #define SMC_insl(a, r, p, l) readsl((a) + (r), p, l) @@ -66,7 +107,7 @@ #define SMC_IRQ_FLAGS (-1) /* from resource */ /* We actually can't write halfwords properly if not word aligned */ -static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg) +static inline void __SMC_outw(u16 val, void __iomem *ioaddr, int reg) { if ((machine_is_mainstone() || machine_is_stargate2() || machine_is_pxa_idp()) && reg & 2) { @@ -405,24 +446,8 @@ smc_pxa_dma_insw(void __iomem *ioaddr, struct smc_local *lp, int reg, int dma, #if ! SMC_CAN_USE_16BIT -/* - * Any 16-bit access is performed with two 8-bit accesses if the hardware - * can't do it directly. Most registers are 16-bit so those are mandatory. - */ -#define SMC_outw(x, ioaddr, reg) \ - do { \ - unsigned int __val16 = (x); \ - SMC_outb( __val16, ioaddr, reg ); \ - SMC_outb( __val16 >> 8, ioaddr, reg + (1 << SMC_IO_SHIFT));\ - } while (0) -#define SMC_inw(ioaddr, reg) \ - ({ \ - unsigned int __val16; \ - __val16 = SMC_inb( ioaddr, reg ); \ - __val16 |= SMC_inb( ioaddr, reg + (1 << SMC_IO_SHIFT)) << 8; \ - __val16; \ - }) - +#define SMC_outw(x, ioaddr, reg) SMC_outw_b(x, ioaddr, reg) +#define SMC_inw(ioaddr, reg) SMC_inw_b(ioaddr, reg) #define SMC_insw(a, r, p, l) BUG() #define SMC_outsw(a, r, p, l) BUG() diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 69e31e2a68fc..f0961cbaf87e 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -440,7 +440,7 @@ static struct sk_buff **geneve_gro_receive(struct sk_buff **head, skb_gro_pull(skb, gh_len); skb_gro_postpull_rcsum(skb, gh, gh_len); - pp = ptype->callbacks.gro_receive(head, skb); + pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb); out_unlock: rcu_read_unlock(); @@ -815,7 +815,6 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, struct geneve_dev *geneve = netdev_priv(dev); struct geneve_sock *gs4 = geneve->sock4; struct rtable *rt = NULL; - const struct iphdr *iip; /* interior IP header */ int err = -EINVAL; struct flowi4 fl4; __u8 tos, ttl; @@ -842,8 +841,6 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); skb_reset_mac_header(skb); - iip = ip_hdr(skb); - if (info) { const struct ip_tunnel_key *key = &info->key; u8 *opts = NULL; @@ -859,7 +856,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (unlikely(err)) goto err; - tos = ip_tunnel_ecn_encap(key->tos, iip, skb); + tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb); ttl = key->ttl; df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; } else { @@ -869,7 +866,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (unlikely(err)) goto err; - tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, iip, skb); + tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb); ttl = geneve->ttl; if (!ttl && IN_MULTICAST(ntohl(fl4.daddr))) ttl = 1; @@ -903,7 +900,6 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, struct geneve_dev *geneve = netdev_priv(dev); struct geneve_sock *gs6 = geneve->sock6; struct dst_entry *dst = NULL; - const struct iphdr *iip; /* interior IP header */ int err = -EINVAL; struct flowi6 fl6; __u8 prio, ttl; @@ -927,8 +923,6 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); skb_reset_mac_header(skb); - iip = ip_hdr(skb); - if (info) { const struct ip_tunnel_key *key = &info->key; u8 *opts = NULL; @@ -945,7 +939,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (unlikely(err)) goto err; - prio = ip_tunnel_ecn_encap(key->tos, iip, skb); + prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb); ttl = key->ttl; } else { udp_csum = false; @@ -954,7 +948,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, if (unlikely(err)) goto err; - prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, iip, skb); + prio = ip_tunnel_ecn_encap(fl6.flowi6_tos, ip_hdr(skb), skb); ttl = geneve->ttl; if (!ttl && ipv6_addr_is_multicast(&fl6.daddr)) ttl = 1; diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 47cd306dbb3c..bba0ca786aaa 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -640,8 +640,10 @@ phy_err: int phy_start_interrupts(struct phy_device *phydev) { atomic_set(&phydev->irq_disable, 0); - if (request_irq(phydev->irq, phy_interrupt, 0, "phy_interrupt", - phydev) < 0) { + if (request_irq(phydev->irq, phy_interrupt, + IRQF_SHARED, + "phy_interrupt", + phydev) < 0) { pr_warn("%s: Can't get IRQ %d (PHY)\n", phydev->bus->name, phydev->irq); phydev->irq = PHY_POLL; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 935e0b45e151..dd7b7d64c90a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -862,10 +862,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC))) goto drop; - if (skb->sk && sk_fullsock(skb->sk)) { - sock_tx_timestamp(skb->sk, &skb_shinfo(skb)->tx_flags); - sw_tx_timestamp(skb); - } + skb_tx_timestamp(skb); /* Orphan the skb - required as we might hang on to it * for indefinite time. diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index f94ab786088f..0e2a19e58923 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1465,6 +1465,11 @@ static void virtnet_free_queues(struct virtnet_info *vi) netif_napi_del(&vi->rq[i].napi); } + /* We called napi_hash_del() before netif_napi_del(), + * we need to respect an RCU grace period before freeing vi->rq + */ + synchronize_net(); + kfree(vi->rq); kfree(vi->sq); } diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 003780901628..6fa8e165878e 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -593,7 +593,7 @@ static struct sk_buff **vxlan_gro_receive(struct sk_buff **head, } } - pp = eth_gro_receive(head, skb); + pp = call_gro_receive(eth_gro_receive, head, skb); out: skb_gro_remcsum_cleanup(skb, &grc); diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index f1ead7c28823..b8a3a1ecabaa 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -21,7 +21,7 @@ /* * Support for Copy Engine hardware, which is mainly used for - * communication between Host and Target over a PCIe interconnect. + * communication between Host and Target over a PCIe/SNOC/AHB interconnect. */ /* @@ -32,7 +32,7 @@ * Each ring consists of a number of descriptors which specify * an address, length, and meta-data. * - * Typically, one side of the PCIe interconnect (Host or Target) + * Typically, one side of the PCIe/AHB/SNOC interconnect (Host or Target) * controls one ring and the other side controls the other ring. * The source side chooses when to initiate a transfer and it * chooses what to send (buffer address, length). The destination @@ -62,215 +62,294 @@ static inline void ath10k_ce_dest_ring_write_index_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ar->bus_write32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS, n); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + + ar_opaque->bus_ops->write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->dst_wr_index_addr, n); } static inline u32 ath10k_ce_dest_ring_write_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { - return ar->bus_read32(ar, ce_ctrl_addr + DST_WR_INDEX_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + + return ar_opaque->bus_ops->read32(ar, + ce_ctrl_addr + ar->hw_ce_regs->dst_wr_index_addr); } static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ar->bus_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + + ar_opaque->bus_ops->write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->sr_wr_index_addr, n); } static inline u32 ath10k_ce_src_ring_write_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { - return ar->bus_read32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + + return ar_opaque->bus_ops->read32(ar, + ce_ctrl_addr + ar->hw_ce_regs->sr_wr_index_addr); } static inline u32 ath10k_ce_src_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { - return ar->bus_read32(ar, ce_ctrl_addr + CURRENT_SRRI_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + + return ar_opaque->bus_ops->read32(ar, + ce_ctrl_addr + ar->hw_ce_regs->current_srri_addr); } static inline void ath10k_ce_shadow_src_ring_write_index_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ar->bus_write32(ar, shadow_sr_wr_ind_addr(ar, ce_ctrl_addr), n); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + + ar_opaque->bus_ops->write32(ar, shadow_sr_wr_ind_addr(ar, + ce_ctrl_addr), n); } static inline void ath10k_ce_shadow_dest_ring_write_index_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ar->bus_write32(ar, shadow_dst_wr_ind_addr(ar, ce_ctrl_addr), n); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + + ar_opaque->bus_ops->write32(ar, shadow_dst_wr_ind_addr(ar, + ce_ctrl_addr), + n); } static inline void ath10k_ce_src_ring_base_addr_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int addr) { - ar->bus_write32(ar, ce_ctrl_addr + SR_BA_ADDRESS, addr); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + + ar_opaque->bus_ops->write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->sr_base_addr, addr); } static inline void ath10k_ce_src_ring_size_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ar->bus_write32(ar, ce_ctrl_addr + SR_SIZE_ADDRESS, n); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + + ar_opaque->bus_ops->write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->sr_size_addr, n); } static inline void ath10k_ce_src_ring_dmax_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 ctrl1_addr = ar->bus_read32((ar), - (ce_ctrl_addr) + CE_CTRL1_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs; - ar->bus_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS, - (ctrl1_addr & ~CE_CTRL1_DMAX_LENGTH_MASK) | - CE_CTRL1_DMAX_LENGTH_SET(n)); + u32 ctrl1_addr = ar_opaque->bus_ops->read32((ar), + (ce_ctrl_addr) + ctrl_regs->addr); + + ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + ctrl_regs->addr, + (ctrl1_addr & ~(ctrl_regs->dmax->mask)) | + ctrl_regs->dmax->set(n, ctrl_regs->dmax)); } static inline void ath10k_ce_src_ring_byte_swap_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 ctrl1_addr = ar->bus_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs; + + u32 ctrl1_addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + + ctrl_regs->addr); - ar->bus_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS, - (ctrl1_addr & ~CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) | - CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(n)); + ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + ctrl_regs->addr, + (ctrl1_addr & ~(ctrl_regs->src_ring->mask)) | + ctrl_regs->src_ring->set(n, ctrl_regs->src_ring)); } static inline void ath10k_ce_dest_ring_byte_swap_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 ctrl1_addr = ar->bus_read32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_ctrl1 *ctrl_regs = ar->hw_ce_regs->ctrl1_regs; - ar->bus_write32(ar, ce_ctrl_addr + CE_CTRL1_ADDRESS, - (ctrl1_addr & ~CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) | - CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(n)); + u32 ctrl1_addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + + ctrl_regs->addr); + + ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + ctrl_regs->addr, + (ctrl1_addr & ~(ctrl_regs->dst_ring->mask)) | + ctrl_regs->dst_ring->set(n, ctrl_regs->dst_ring)); } static inline u32 ath10k_ce_dest_ring_read_index_get(struct ath10k *ar, u32 ce_ctrl_addr) { - return ar->bus_read32(ar, ce_ctrl_addr + CURRENT_DRRI_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + + return ar_opaque->bus_ops->read32(ar, + ce_ctrl_addr + ar->hw_ce_regs->current_drri_addr); } static inline void ath10k_ce_dest_ring_base_addr_set(struct ath10k *ar, u32 ce_ctrl_addr, u32 addr) { - ar->bus_write32(ar, ce_ctrl_addr + DR_BA_ADDRESS, addr); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + + ar_opaque->bus_ops->write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->dr_base_addr, addr); } static inline void ath10k_ce_dest_ring_size_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - ar->bus_write32(ar, ce_ctrl_addr + DR_SIZE_ADDRESS, n); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + + ar_opaque->bus_ops->write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->dr_size_addr, n); } static inline void ath10k_ce_src_ring_highmark_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 addr = ar->bus_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr; + u32 addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + srcr_wm->addr); - ar->bus_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS, - (addr & ~SRC_WATERMARK_HIGH_MASK) | - SRC_WATERMARK_HIGH_SET(n)); + ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + srcr_wm->addr, + (addr & ~(srcr_wm->wm_high->mask)) | + (srcr_wm->wm_high->set(n, srcr_wm->wm_high))); } static inline void ath10k_ce_src_ring_lowmark_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 addr = ar->bus_read32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_dst_src_wm_regs *srcr_wm = ar->hw_ce_regs->wm_srcr; + u32 addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + srcr_wm->addr); - ar->bus_write32(ar, ce_ctrl_addr + SRC_WATERMARK_ADDRESS, - (addr & ~SRC_WATERMARK_LOW_MASK) | - SRC_WATERMARK_LOW_SET(n)); + ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + srcr_wm->addr, + (addr & ~(srcr_wm->wm_low->mask)) | + (srcr_wm->wm_low->set(n, srcr_wm->wm_low))); } static inline void ath10k_ce_dest_ring_highmark_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 addr = ar->bus_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr; + u32 addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + dstr_wm->addr); - ar->bus_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS, - (addr & ~DST_WATERMARK_HIGH_MASK) | - DST_WATERMARK_HIGH_SET(n)); + ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + dstr_wm->addr, + (addr & ~(dstr_wm->wm_high->mask)) | + (dstr_wm->wm_high->set(n, dstr_wm->wm_high))); } static inline void ath10k_ce_dest_ring_lowmark_set(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int n) { - u32 addr = ar->bus_read32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_dst_src_wm_regs *dstr_wm = ar->hw_ce_regs->wm_dstr; + u32 addr = ar_opaque->bus_ops->read32(ar, ce_ctrl_addr + dstr_wm->addr); - ar->bus_write32(ar, ce_ctrl_addr + DST_WATERMARK_ADDRESS, - (addr & ~DST_WATERMARK_LOW_MASK) | - DST_WATERMARK_LOW_SET(n)); + ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + dstr_wm->addr, + (addr & ~(dstr_wm->wm_low->mask)) | + (dstr_wm->wm_low->set(n, dstr_wm->wm_low))); } static inline void ath10k_ce_copy_complete_inter_enable(struct ath10k *ar, u32 ce_ctrl_addr) { - u32 host_ie_addr = ar->bus_read32(ar, - ce_ctrl_addr + HOST_IE_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie; - ar->bus_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS, - host_ie_addr | HOST_IE_COPY_COMPLETE_MASK); + u32 host_ie_addr = ar_opaque->bus_ops->read32(ar, + ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr); + + ar_opaque->bus_ops->write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr, + host_ie_addr | host_ie->copy_complete->mask); } static inline void ath10k_ce_copy_complete_intr_disable(struct ath10k *ar, u32 ce_ctrl_addr) { - u32 host_ie_addr = ar->bus_read32(ar, - ce_ctrl_addr + HOST_IE_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_host_ie *host_ie = ar->hw_ce_regs->host_ie; + + u32 host_ie_addr = ar_opaque->bus_ops->read32(ar, + ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr); - ar->bus_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS, - host_ie_addr & ~HOST_IE_COPY_COMPLETE_MASK); + ar_opaque->bus_ops->write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr, + host_ie_addr & ~(host_ie->copy_complete->mask)); } static inline void ath10k_ce_watermark_intr_disable(struct ath10k *ar, u32 ce_ctrl_addr) { - u32 host_ie_addr = ar->bus_read32(ar, - ce_ctrl_addr + HOST_IE_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs; - ar->bus_write32(ar, ce_ctrl_addr + HOST_IE_ADDRESS, - host_ie_addr & ~CE_WATERMARK_MASK); + u32 host_ie_addr = ar_opaque->bus_ops->read32(ar, + ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr); + + ar_opaque->bus_ops->write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->host_ie_addr, + host_ie_addr & ~(wm_regs->wm_mask)); } static inline void ath10k_ce_error_intr_enable(struct ath10k *ar, u32 ce_ctrl_addr) { - u32 misc_ie_addr = ar->bus_read32(ar, - ce_ctrl_addr + MISC_IE_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs; + + u32 misc_ie_addr = ar_opaque->bus_ops->read32(ar, + ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr); - ar->bus_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS, - misc_ie_addr | CE_ERROR_MASK); + ar_opaque->bus_ops->write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr, + misc_ie_addr | misc_regs->err_mask); } static inline void ath10k_ce_error_intr_disable(struct ath10k *ar, u32 ce_ctrl_addr) { - u32 misc_ie_addr = ar->bus_read32(ar, - ce_ctrl_addr + MISC_IE_ADDRESS); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_misc_regs *misc_regs = ar->hw_ce_regs->misc_regs; + + u32 misc_ie_addr = ar_opaque->bus_ops->read32(ar, + ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr); - ar->bus_write32(ar, ce_ctrl_addr + MISC_IE_ADDRESS, - misc_ie_addr & ~CE_ERROR_MASK); + ar_opaque->bus_ops->write32(ar, + ce_ctrl_addr + ar->hw_ce_regs->misc_ie_addr, + misc_ie_addr & ~(misc_regs->err_mask)); } static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar, u32 ce_ctrl_addr, unsigned int mask) { - ar->bus_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs; + + ar_opaque->bus_ops->write32(ar, ce_ctrl_addr + wm_regs->addr, mask); } u32 shadow_sr_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr) @@ -339,6 +418,21 @@ u32 shadow_dst_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr) return addr; } +static inline void ath10k_ce_snoc_addr_config(struct ce_desc *sdesc, + dma_addr_t buffer, + unsigned int flags) +{ + __le32 *addr = (__le32 *)&sdesc->addr; + + flags |= upper_32_bits(buffer) & CE_DESC_FLAGS_GET_MASK; + addr[0] = __cpu_to_le32(buffer); + addr[1] = flags; + if (flags & CE_SEND_FLAG_GATHER) + addr[1] |= CE_WCN3990_DESC_FLAGS_GATHER; + else + addr[1] &= ~CE_WCN3990_DESC_FLAGS_GATHER; +} + /* * Guts of ath10k_ce_send, used by both ath10k_ce_send and * ath10k_ce_sendlist_send. @@ -382,17 +476,10 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, if (flags & CE_SEND_FLAG_BYTE_SWAP) desc_flags |= CE_DESC_FLAGS_BYTE_SWAP; - if (QCA_REV_WCN3990(ar)) { - flags |= upper_32_bits(buffer) & CE_DESC_FLAGS_GET_MASK; - sdesc.addr_lo = __cpu_to_le32(buffer); - sdesc.addr_hi = flags; - if (flags & CE_SEND_FLAG_GATHER) - sdesc.addr_hi |= CE_WCN3990_DESC_FLAGS_GATHER; - else - sdesc.addr_hi &= ~CE_WCN3990_DESC_FLAGS_GATHER; - } else { + if (QCA_REV_WCN3990(ar)) + ath10k_ce_snoc_addr_config(&sdesc, buffer, flags); + else sdesc.addr = __cpu_to_le32(buffer); - } sdesc.nbytes = __cpu_to_le16(nbytes); sdesc.flags = __cpu_to_le16(desc_flags); @@ -422,10 +509,11 @@ exit: void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe) { struct ath10k *ar = pipe->ar; + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); struct ath10k_ce_ring *src_ring = pipe->src_ring; u32 ctrl_addr = pipe->ctrl_addr; - lockdep_assert_held(&ar->ce_lock); + lockdep_assert_held(&ar_opaque->ce_lock); /* * This function must be called only if there is an incomplete @@ -453,12 +541,13 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state, unsigned int flags) { struct ath10k *ar = ce_state->ar; + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); int ret; - spin_lock_bh(&ar->ce_lock); + spin_lock_bh(&ar_opaque->ce_lock); ret = ath10k_ce_send_nolock(ce_state, per_transfer_context, buffer, nbytes, transfer_id, flags); - spin_unlock_bh(&ar->ce_lock); + spin_unlock_bh(&ar_opaque->ce_lock); return ret; } @@ -466,13 +555,14 @@ int ath10k_ce_send(struct ath10k_ce_pipe *ce_state, int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe) { struct ath10k *ar = pipe->ar; + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); int delta; - spin_lock_bh(&ar->ce_lock); + spin_lock_bh(&ar_opaque->ce_lock); delta = CE_RING_DELTA(pipe->src_ring->nentries_mask, pipe->src_ring->write_index, pipe->src_ring->sw_index - 1); - spin_unlock_bh(&ar->ce_lock); + spin_unlock_bh(&ar_opaque->ce_lock); return delta; } @@ -480,12 +570,13 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe) int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe) { struct ath10k *ar = pipe->ar; + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); struct ath10k_ce_ring *dest_ring = pipe->dest_ring; unsigned int nentries_mask = dest_ring->nentries_mask; unsigned int write_index = dest_ring->write_index; unsigned int sw_index = dest_ring->sw_index; - lockdep_assert_held(&ar->ce_lock); + lockdep_assert_held(&ar_opaque->ce_lock); return CE_RING_DELTA(nentries_mask, write_index, sw_index - 1); } @@ -494,6 +585,7 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, dma_addr_t paddr) { struct ath10k *ar = pipe->ar; + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); struct ath10k_ce_ring *dest_ring = pipe->dest_ring; unsigned int nentries_mask = dest_ring->nentries_mask; unsigned int write_index = dest_ring->write_index; @@ -502,7 +594,7 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, write_index); u32 ctrl_addr = pipe->ctrl_addr; - lockdep_assert_held(&ar->ce_lock); + lockdep_assert_held(&ar_opaque->ce_lock); if ((pipe->id != 5) && CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0) @@ -542,11 +634,12 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, dma_addr_t paddr) { struct ath10k *ar = pipe->ar; + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); int ret; - spin_lock_bh(&ar->ce_lock); + spin_lock_bh(&ar_opaque->ce_lock); ret = __ath10k_ce_rx_post_buf(pipe, ctx, paddr); - spin_unlock_bh(&ar->ce_lock); + spin_unlock_bh(&ar_opaque->ce_lock); return ret; } @@ -609,13 +702,14 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, unsigned int *nbytesp) { struct ath10k *ar = ce_state->ar; + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); int ret; - spin_lock_bh(&ar->ce_lock); + spin_lock_bh(&ar_opaque->ce_lock); ret = ath10k_ce_completed_recv_next_nolock(ce_state, per_transfer_contextp, nbytesp); - spin_unlock_bh(&ar->ce_lock); + spin_unlock_bh(&ar_opaque->ce_lock); return ret; } @@ -630,6 +724,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, unsigned int write_index; int ret; struct ath10k *ar; + struct bus_opaque *ar_opaque; dest_ring = ce_state->dest_ring; @@ -637,8 +732,9 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, return -EIO; ar = ce_state->ar; + ar_opaque = ath10k_bus_priv(ar); - spin_lock_bh(&ar->ce_lock); + spin_lock_bh(&ar_opaque->ce_lock); nentries_mask = dest_ring->nentries_mask; sw_index = dest_ring->sw_index; @@ -666,7 +762,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, ret = -EIO; } - spin_unlock_bh(&ar->ce_lock); + spin_unlock_bh(&ar_opaque->ce_lock); return ret; } @@ -734,6 +830,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, unsigned int write_index; int ret; struct ath10k *ar; + struct bus_opaque *ar_opaque; src_ring = ce_state->src_ring; @@ -741,8 +838,9 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, return -EIO; ar = ce_state->ar; + ar_opaque = ath10k_bus_priv(ar); - spin_lock_bh(&ar->ce_lock); + spin_lock_bh(&ar_opaque->ce_lock); nentries_mask = src_ring->nentries_mask; sw_index = src_ring->sw_index; @@ -773,7 +871,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, ret = -EIO; } - spin_unlock_bh(&ar->ce_lock); + spin_unlock_bh(&ar_opaque->ce_lock); return ret; } @@ -782,12 +880,13 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, void **per_transfer_contextp) { struct ath10k *ar = ce_state->ar; + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); int ret; - spin_lock_bh(&ar->ce_lock); + spin_lock_bh(&ar_opaque->ce_lock); ret = ath10k_ce_completed_send_next_nolock(ce_state, per_transfer_contextp); - spin_unlock_bh(&ar->ce_lock); + spin_unlock_bh(&ar_opaque->ce_lock); return ret; } @@ -800,17 +899,18 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, */ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) { - struct ath10k_ce_pipe *ce_state = - ((struct ath10k_ce_pipe *)ar->ce_states + ce_id); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_ce_pipe *ce_state = &ar_opaque->ce_states[ce_id]; + struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs; u32 ctrl_addr = ce_state->ctrl_addr; - spin_lock_bh(&ar->ce_lock); + spin_lock_bh(&ar_opaque->ce_lock); /* Clear the copy-complete interrupts that will be handled here. */ ath10k_ce_engine_int_status_clear(ar, ctrl_addr, - HOST_IS_COPY_COMPLETE_MASK); + wm_regs->cc_mask); - spin_unlock_bh(&ar->ce_lock); + spin_unlock_bh(&ar_opaque->ce_lock); if (ce_state->recv_cb) ce_state->recv_cb(ce_state); @@ -818,15 +918,15 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) if (ce_state->send_cb) ce_state->send_cb(ce_state); - spin_lock_bh(&ar->ce_lock); + spin_lock_bh(&ar_opaque->ce_lock); /* * Misc CE interrupts are not being handled, but still need * to be cleared. */ - ath10k_ce_engine_int_status_clear(ar, ctrl_addr, CE_WATERMARK_MASK); + ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->wm_mask); - spin_unlock_bh(&ar->ce_lock); + spin_unlock_bh(&ar_opaque->ce_lock); } /* @@ -840,11 +940,12 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar) int ce_id; u32 intr_summary; struct ath10k_ce_pipe *ce_state; + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); if (ar->target_version == ATH10K_HW_WCN3990) intr_summary = 0xFFF; else - intr_summary = CE_INTERRUPT_SUMMARY(ar); + intr_summary = CE_INTERRUPT_SUMMARY(ar, ar_opaque); for (ce_id = 0; intr_summary && (ce_id < CE_COUNT); ce_id++) { if (intr_summary & (1 << ce_id)) @@ -853,7 +954,7 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar) /* no intr pending on this CE */ continue; - ce_state = ((struct ath10k_ce_pipe *)ar->ce_states + ce_id); + ce_state = &ar_opaque->ce_states[ce_id]; if (ce_state->send_cb || ce_state->recv_cb) ath10k_ce_per_engine_service(ar, ce_id); } @@ -899,42 +1000,47 @@ int ath10k_ce_disable_interrupts(struct ath10k *ar) void ath10k_ce_enable_interrupts(struct ath10k *ar) { + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); int ce_id; + struct ath10k_ce_pipe *ce_state; /* Skip the last copy engine, CE7 the diagnostic window, as that * uses polling and isn't initialized for interrupts. */ - for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++) - ath10k_ce_per_engine_handler_adjust( - ((struct ath10k_ce_pipe *)ar->ce_states + ce_id)); + for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++) { + ce_state = &ar_opaque->ce_states[ce_id]; + ath10k_ce_per_engine_handler_adjust(ce_state); + } } void ath10k_ce_enable_per_ce_interrupts(struct ath10k *ar, unsigned int ce_id) { u32 offset; u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); - offset = HOST_IE_ADDRESS + ctrl_addr; - ar->bus_write32(ar, offset, 1); - ar->bus_read32(ar, offset); + offset = ar->hw_ce_regs->host_ie_addr + ctrl_addr; + ar_opaque->bus_ops->write32(ar, offset, 1); + ar_opaque->bus_ops->read32(ar, offset); } void ath10k_ce_disable_per_ce_interrupts(struct ath10k *ar, unsigned int ce_id) { u32 offset; u32 ctrl_addr = ath10k_ce_base_address(ar, ce_id); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); - offset = HOST_IE_ADDRESS + ctrl_addr; - ar->bus_write32(ar, offset, 0); - ar->bus_read32(ar, offset); + offset = ar->hw_ce_regs->host_ie_addr + ctrl_addr; + ar_opaque->bus_ops->write32(ar, offset, 0); + ar_opaque->bus_ops->read32(ar, offset); } static int ath10k_ce_init_src_ring(struct ath10k *ar, unsigned int ce_id, const struct ce_attr *attr) { - struct ath10k_ce_pipe *ce_state = - ((struct ath10k_ce_pipe *)ar->ce_states + ce_id); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_ce_pipe *ce_state = &ar_opaque->ce_states[ce_id]; struct ath10k_ce_ring *src_ring = ce_state->src_ring; u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id); @@ -970,8 +1076,8 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, unsigned int ce_id, const struct ce_attr *attr) { - struct ath10k_ce_pipe *ce_state = - ((struct ath10k_ce_pipe *)ar->ce_states + ce_id); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_ce_pipe *ce_state = &ar_opaque->ce_states[ce_id]; struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; u32 nentries, ctrl_addr = ath10k_ce_base_address(ar, ce_id); @@ -1178,8 +1284,8 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id) int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, const struct ce_attr *attr) { - struct ath10k_ce_pipe *ce_state = - ((struct ath10k_ce_pipe *)ar->ce_states + ce_id); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_ce_pipe *ce_state = &ar_opaque->ce_states[ce_id]; int ret; /* @@ -1235,8 +1341,8 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id) { - struct ath10k_ce_pipe *ce_state = - ((struct ath10k_ce_pipe *)ar->ce_states + ce_id); + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); + struct ath10k_ce_pipe *ce_state = &ar_opaque->ce_states[ce_id]; if (ce_state->src_ring) { kfree(ce_state->src_ring->shadow_base_unaligned); diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 160a13e681df..936f0698c0f0 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -58,13 +58,7 @@ struct ce_desc { }; #else struct ce_desc { - union { - __le64 addr; - struct { - __le32 addr_lo; - __le32 addr_hi; - }; - }; + __le64 addr; u16 nbytes; /* length in register map */ u16 flags; /* fw_metadata_high */ u32 toeplitz_hash_result; @@ -201,6 +195,24 @@ struct ce_attr; u32 shadow_sr_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr); u32 shadow_dst_wr_ind_addr(struct ath10k *ar, u32 ctrl_addr); +struct ath10k_bus_ops { + u32 (*read32)(struct ath10k *ar, u32 offset); + void (*write32)(struct ath10k *ar, u32 offset, u32 value); + int (*get_num_banks)(struct ath10k *ar); +}; + +static inline struct bus_opaque *ath10k_bus_priv(struct ath10k *ar) +{ + return (struct bus_opaque *)ar->drv_priv; +} + +struct bus_opaque { + /* protects CE info */ + spinlock_t ce_lock; + const struct ath10k_bus_ops *bus_ops; + struct ath10k_ce_pipe ce_states[CE_COUNT_MAX]; +}; + /*==================Send====================*/ /* ath10k_ce_send flags */ @@ -344,311 +356,6 @@ struct ce_attr { void (*recv_cb)(struct ath10k_ce_pipe *); }; -#ifndef CONFIG_ATH10K_SNOC -#define SR_BA_ADDRESS 0x0000 -#define SR_SIZE_ADDRESS 0x0004 -#define DR_BA_ADDRESS 0x0008 -#define DR_SIZE_ADDRESS 0x000c -#define CE_CMD_ADDRESS 0x0018 - -#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MSB 17 -#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 17 -#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00020000 -#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(x) \ - (((0 | (x)) << CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) & \ - CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) - -#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MSB 16 -#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 -#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00010000 -#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_GET(x) \ - (((x) & CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) >> \ - CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) -#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(x) \ - (((0 | (x)) << CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) & \ - CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) - -#define CE_CTRL1_DMAX_LENGTH_MSB 15 -#define CE_CTRL1_DMAX_LENGTH_LSB 0 -#define CE_CTRL1_DMAX_LENGTH_MASK 0x0000ffff -#define CE_CTRL1_DMAX_LENGTH_GET(x) \ - (((x) & CE_CTRL1_DMAX_LENGTH_MASK) >> CE_CTRL1_DMAX_LENGTH_LSB) -#define CE_CTRL1_DMAX_LENGTH_SET(x) \ - (((0 | (x)) << CE_CTRL1_DMAX_LENGTH_LSB) & CE_CTRL1_DMAX_LENGTH_MASK) - -#define CE_CTRL1_ADDRESS 0x0010 -#define CE_CTRL1_HW_MASK 0x0007ffff -#define CE_CTRL1_SW_MASK 0x0007ffff -#define CE_CTRL1_HW_WRITE_MASK 0x00000000 -#define CE_CTRL1_SW_WRITE_MASK 0x0007ffff -#define CE_CTRL1_RSTMASK 0xffffffff -#define CE_CTRL1_RESET 0x00000080 - -#define CE_CMD_HALT_STATUS_MSB 3 -#define CE_CMD_HALT_STATUS_LSB 3 -#define CE_CMD_HALT_STATUS_MASK 0x00000008 -#define CE_CMD_HALT_STATUS_GET(x) \ - (((x) & CE_CMD_HALT_STATUS_MASK) >> CE_CMD_HALT_STATUS_LSB) -#define CE_CMD_HALT_STATUS_SET(x) \ - (((0 | (x)) << CE_CMD_HALT_STATUS_LSB) & CE_CMD_HALT_STATUS_MASK) -#define CE_CMD_HALT_STATUS_RESET 0 -#define CE_CMD_HALT_MSB 0 -#define CE_CMD_HALT_MASK 0x00000001 - -#define HOST_IE_COPY_COMPLETE_MSB 0 -#define HOST_IE_COPY_COMPLETE_LSB 0 -#define HOST_IE_COPY_COMPLETE_MASK 0x00000001 -#define HOST_IE_COPY_COMPLETE_GET(x) \ - (((x) & HOST_IE_COPY_COMPLETE_MASK) >> HOST_IE_COPY_COMPLETE_LSB) -#define HOST_IE_COPY_COMPLETE_SET(x) \ - (((0 | (x)) << HOST_IE_COPY_COMPLETE_LSB) & HOST_IE_COPY_COMPLETE_MASK) -#define HOST_IE_COPY_COMPLETE_RESET 0 -#define HOST_IE_ADDRESS 0x002c - -#define HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 -#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 -#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 -#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 -#define HOST_IS_COPY_COMPLETE_MASK 0x00000001 -#define HOST_IS_ADDRESS 0x0030 - -#define MISC_IE_ADDRESS 0x0034 - -#define MISC_IS_AXI_ERR_MASK 0x00000400 - -#define MISC_IS_DST_ADDR_ERR_MASK 0x00000200 -#define MISC_IS_SRC_LEN_ERR_MASK 0x00000100 -#define MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 -#define MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 -#define MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 - -#define MISC_IS_ADDRESS 0x0038 - -#define SR_WR_INDEX_ADDRESS 0x003c - -#define DST_WR_INDEX_ADDRESS 0x0040 - -#define CURRENT_SRRI_ADDRESS 0x0044 - -#define CURRENT_DRRI_ADDRESS 0x0048 - -#define SRC_WATERMARK_LOW_MSB 31 -#define SRC_WATERMARK_LOW_LSB 16 -#define SRC_WATERMARK_LOW_MASK 0xffff0000 -#define SRC_WATERMARK_LOW_GET(x) \ - (((x) & SRC_WATERMARK_LOW_MASK) >> SRC_WATERMARK_LOW_LSB) -#define SRC_WATERMARK_LOW_SET(x) \ - (((0 | (x)) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK) -#define SRC_WATERMARK_LOW_RESET 0 -#define SRC_WATERMARK_HIGH_MSB 15 -#define SRC_WATERMARK_HIGH_LSB 0 -#define SRC_WATERMARK_HIGH_MASK 0x0000ffff -#define SRC_WATERMARK_HIGH_GET(x) \ - (((x) & SRC_WATERMARK_HIGH_MASK) >> SRC_WATERMARK_HIGH_LSB) -#define SRC_WATERMARK_HIGH_SET(x) \ - (((0 | (x)) << SRC_WATERMARK_HIGH_LSB) & SRC_WATERMARK_HIGH_MASK) -#define SRC_WATERMARK_HIGH_RESET 0 -#define SRC_WATERMARK_ADDRESS 0x004c - -#define DST_WATERMARK_LOW_LSB 16 -#define DST_WATERMARK_LOW_MASK 0xffff0000 -#define DST_WATERMARK_LOW_SET(x) \ - (((0 | (x)) << DST_WATERMARK_LOW_LSB) & DST_WATERMARK_LOW_MASK) -#define DST_WATERMARK_LOW_RESET 0 -#define DST_WATERMARK_HIGH_MSB 15 -#define DST_WATERMARK_HIGH_LSB 0 -#define DST_WATERMARK_HIGH_MASK 0x0000ffff -#define DST_WATERMARK_HIGH_GET(x) \ - (((x) & DST_WATERMARK_HIGH_MASK) >> DST_WATERMARK_HIGH_LSB) -#define DST_WATERMARK_HIGH_SET(x) \ - (((0 | (x)) << DST_WATERMARK_HIGH_LSB) & DST_WATERMARK_HIGH_MASK) -#define DST_WATERMARK_HIGH_RESET 0 -#define DST_WATERMARK_ADDRESS 0x0050 - -#else -#define WCN3990_CE0_SR_BA_LOW (0x00240000) -#define WCN3990_CE1_SR_BA_LOW (0x00241000) -#define WCN3990_CE2_SR_BA_LOW (0x00242000) -#define WCN3990_CE3_SR_BA_LOW (0x00243000) -#define WCN3990_CE4_SR_BA_LOW (0x00244000) -#define WCN3990_CE5_SR_BA_LOW (0x00245000) -#define WCN3990_CE6_SR_BA_LOW (0x00246000) -#define WCN3990_CE7_SR_BA_LOW (0x00247000) -#define WCN3990_CE8_SR_BA_LOW (0x00248000) -#define WCN3990_CE9_SR_BA_LOW (0x00249000) -#define WCN3990_CE10_SR_BA_LOW (0x0024A000) -#define WCN3990_CE11_SR_BA_LOW (0x0024B000) -#define WCN3990_CE0_DR_BA_LOW (0x0024000C) -#define WNC3990_CE0_DR_SIZE (0x00240014) -#define WCN3990_CE0_CE_CTRL1 (0x00240018) -#define WCN3990_CE0_HOST_IE (0x0024002C) -#define WCN3990_CE0_HOST_IS (0x00240030) -#define WCN3990_CE0_MISC_IE (0x00240034) -#define WCN3990_CE0_MISC_IS (0x00240038) -#define WCN3990_CE0_SRC_WR_INDEX (0x0024003C) -#define WCN3990_CE0_CURRENT_SRRI (0x00240044) -#define WCN3990_CE0_CURRENT_DRRI (0x00240048) -#define WCN3990_CE0_SRC_WATERMARK (0x0024004C) -#define WCN3990_CE0_DST_WATERMARK (0x00240050) -#define WCN3990_CE0_SR_SIZE (0x00240008) -#define HOST_IE_COPY_COMPLETE_MASK (0x00000001) -#define WCN3990_CE_WRAPPER_HOST_INTERRUPT_SUMMARY 0x0024C000 -#define WCN3990_CE_WRAPPER_INDEX_BASE_LOW 0x0024C004 -#define WCN3990_CE_WRAPPER_INDEX_BASE_HIGH 0x0024C008 -#define CE_CTRL1_IDX_UPD_EN 0x00080000 - -#define WCN3990_CE_WRAPPER_BASE_ADDRESS \ - WCN3990_CE_WRAPPER_HOST_INTERRUPT_SUMMARY -#define WCN3990_CE0_BASE_ADDRESS \ - WCN3990_CE0_SR_BA_LOW -#define WCN3990_CE1_BASE_ADDRESS \ - WCN3990_CE1_SR_BA_LOW -#define WCN3990_CE2_BASE_ADDRESS \ - WCN3990_CE2_SR_BA_LOW -#define WCN3990_CE3_BASE_ADDRESS \ - WCN3990_CE3_SR_BA_LOW -#define WCN3990_CE4_BASE_ADDRESS \ - WCN3990_CE4_SR_BA_LOW -#define WCN3990_CE5_BASE_ADDRESS \ - WCN3990_CE5_SR_BA_LOW -#define WCN3990_CE6_BASE_ADDRESS \ - WCN3990_CE6_SR_BA_LOW -#define WCN3990_CE7_BASE_ADDRESS \ - WCN3990_CE7_SR_BA_LOW -#define WCN3990_CE8_BASE_ADDRESS \ - WCN3990_CE8_SR_BA_LOW -#define WCN3990_CE9_BASE_ADDRESS \ - WCN3990_CE9_SR_BA_LOW -#define WCN3990_CE10_BASE_ADDRESS \ - WCN3990_CE10_SR_BA_LOW -#define WCN3990_CE11_BASE_ADDRESS \ - WCN3990_CE11_SR_BA_LOW - -#define SR_BA_ADDRESS (WCN3990_CE0_SR_BA_LOW\ - - WCN3990_CE0_BASE_ADDRESS) -#define SR_SIZE_ADDRESS (WCN3990_CE0_SR_SIZE \ - - WCN3990_CE0_BASE_ADDRESS) -#define DR_BA_ADDRESS (WCN3990_CE0_DR_BA_LOW\ - - WCN3990_CE0_BASE_ADDRESS) -#define DR_SIZE_ADDRESS (WNC3990_CE0_DR_SIZE\ - - WCN3990_CE0_BASE_ADDRESS) -#define WCN3990_CE_DDR_ADDRESS_FOR_RRI_LOW \ - (WCN3990_CE_WRAPPER_INDEX_BASE_LOW - WCN3990_CE_WRAPPER_BASE_ADDRESS) - -#define WCN3990_CE_DDR_ADDRESS_FOR_RRI_HIGH \ - (WCN3990_CE_WRAPPER_INDEX_BASE_HIGH - WCN3990_CE_WRAPPER_BASE_ADDRESS) - -#define CE_RRI_LOW (WCN3990_CE_WRAPPER_BASE_ADDRESS \ - + WCN3990_CE_DDR_ADDRESS_FOR_RRI_LOW) - -#define CE_RRI_HIGH (WCN3990_CE_WRAPPER_BASE_ADDRESS \ - + WCN3990_CE_DDR_ADDRESS_FOR_RRI_HIGH) - -#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MSB 18 -#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB 18 - -#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK 0x00040000 -#define CE_CTRL1_DST_RING_BYTE_SWAP_EN_SET(x) \ - (((0 | (x)) << CE_CTRL1_DST_RING_BYTE_SWAP_EN_LSB) & \ - CE_CTRL1_DST_RING_BYTE_SWAP_EN_MASK) - -#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MSB 16 -#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB 16 - -#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK 0x00020000 -#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_GET(x) \ - (((x) & CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) >> \ - CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) -#define CE_CTRL1_SRC_RING_BYTE_SWAP_EN_SET(x) \ - (((0 | (x)) << CE_CTRL1_SRC_RING_BYTE_SWAP_EN_LSB) & \ - CE_CTRL1_SRC_RING_BYTE_SWAP_EN_MASK) - -#define CE_CTRL1_DMAX_LENGTH_MSB 0 -#define CE_CTRL1_DMAX_LENGTH_LSB 0 - -#define CE_CTRL1_DMAX_LENGTH_MASK 0x0000FFFF -#define CE_CTRL1_DMAX_LENGTH_GET(x) \ - (((x) & CE_CTRL1_DMAX_LENGTH_MASK) >> CE_CTRL1_DMAX_LENGTH_LSB) -#define CE_CTRL1_DMAX_LENGTH_SET(x) \ - (((0 | (x)) << CE_CTRL1_DMAX_LENGTH_LSB) & CE_CTRL1_DMAX_LENGTH_MASK) - -#define CE_CTRL1_ADDRESS (WCN3990_CE0_CE_CTRL1 \ - - WCN3990_CE0_BASE_ADDRESS) - -#define HOST_IE_ADDRESS (WCN3990_CE0_HOST_IE\ - - WCN3990_CE0_BASE_ADDRESS) - -#define HOST_IS_DST_RING_LOW_WATERMARK_MASK 0x00000010 -#define HOST_IS_DST_RING_HIGH_WATERMARK_MASK 0x00000008 -#define HOST_IS_SRC_RING_LOW_WATERMARK_MASK 0x00000004 -#define HOST_IS_SRC_RING_HIGH_WATERMARK_MASK 0x00000002 -#define HOST_IS_COPY_COMPLETE_MASK 0x00000001 -#define HOST_IS_ADDRESS (WCN3990_CE0_HOST_IS \ - - WCN3990_CE0_BASE_ADDRESS) -#define MISC_IE_ADDRESS (WCN3990_CE0_MISC_IE \ - - WCN3990_CE0_BASE_ADDRESS) - -#define MISC_IS_AXI_ERR_MASK 0x00000100 -#define MISC_IS_DST_ADDR_ERR_MASK 0x00000200 -#define MISC_IS_SRC_LEN_ERR_MASK 0x00000100 -#define MISC_IS_DST_MAX_LEN_VIO_MASK 0x00000080 -#define MISC_IS_DST_RING_OVERFLOW_MASK 0x00000040 -#define MISC_IS_SRC_RING_OVERFLOW_MASK 0x00000020 -#define MISC_IS_ADDRESS (WCN3990_CE0_MISC_IS \ - - WCN3990_CE0_BASE_ADDRESS) - -#define SR_WR_INDEX_ADDRESS 0x3C -#define DST_WR_INDEX_ADDRESS 0x40 - -#define CURRENT_SRRI_ADDRESS (WCN3990_CE0_CURRENT_SRRI\ - - WCN3990_CE0_BASE_ADDRESS) -#define CURRENT_DRRI_ADDRESS (WCN3990_CE0_CURRENT_DRRI\ - - WCN3990_CE0_BASE_ADDRESS) - -#define SRC_WATERMARK_LOW_MSB 0 -#define SRC_WATERMARK_LOW_LSB 16 - -#define SRC_WATERMARK_LOW_MASK 0xffff0000 -#define SRC_WATERMARK_LOW_GET(x) \ - (((x) & SRC_WATERMARK_LOW_MASK) >> SRC_WATERMARK_LOW_LSB) -#define SRC_WATERMARK_LOW_SET(x) \ - (((0 | (x)) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK) - -#define SRC_WATERMARK_LOW_RESET 0 -#define SRC_WATERMARK_HIGH_MSB 15 -#define SRC_WATERMARK_HIGH_LSB 0 -#define SRC_WATERMARK_HIGH_MASK 0x0000ffff -#define SRC_WATERMARK_HIGH_GET(x) \ - (((x) & SRC_WATERMARK_HIGH_MASK) >> SRC_WATERMARK_HIGH_LSB) -#define SRC_WATERMARK_HIGH_SET(x) \ - (((0 | (x)) << SRC_WATERMARK_HIGH_LSB) & SRC_WATERMARK_HIGH_MASK) - -#define SRC_WATERMARK_HIGH_RESET 0 -#define SRC_WATERMARK_ADDRESS (WCN3990_CE0_SRC_WATERMARK\ - - WCN3990_CE0_BASE_ADDRESS) - -#define DST_WATERMARK_LOW_LSB 16 -#define DST_WATERMARK_LOW_MASK 0xffff0000 -#define DST_WATERMARK_LOW_SET(x) \ - (((0 | (x)) << DST_WATERMARK_LOW_LSB) & DST_WATERMARK_LOW_MASK) -#define DST_WATERMARK_LOW_RESET 0 -#define DST_WATERMARK_HIGH_MSB 15 -#define DST_WATERMARK_HIGH_LSB 0 -#define DST_WATERMARK_HIGH_MASK 0x0000ffff -#define DST_WATERMARK_HIGH_GET(x) \ - (((x) & DST_WATERMARK_HIGH_MASK) >> DST_WATERMARK_HIGH_LSB) -#define DST_WATERMARK_HIGH_SET(x) \ - (((0 | (x)) << DST_WATERMARK_HIGH_LSB) & DST_WATERMARK_HIGH_MASK) -#define DST_WATERMARK_HIGH_RESET 0 -#define DST_WATERMARK_ADDRESS (WCN3990_CE0_DST_WATERMARK \ - - WCN3990_CE0_BASE_ADDRESS) - -#define BITS0_TO_31(val) ((uint32_t)((uint64_t)(val)\ - & (uint64_t)(0xFFFFFFFF))) -#define BITS32_TO_35(val) ((uint32_t)(((uint64_t)(val)\ - & (uint64_t)(0xF00000000)) >> 32)) -#endif - #define COPY_ENGINE_ID(COPY_ENGINE_BASE_ADDRESS) ((COPY_ENGINE_BASE_ADDRESS \ - CE0_BASE_ADDRESS) / (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS)) @@ -657,18 +364,6 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id; } -#define CE_WATERMARK_MASK (HOST_IS_SRC_RING_LOW_WATERMARK_MASK | \ - HOST_IS_SRC_RING_HIGH_WATERMARK_MASK | \ - HOST_IS_DST_RING_LOW_WATERMARK_MASK | \ - HOST_IS_DST_RING_HIGH_WATERMARK_MASK) - -#define CE_ERROR_MASK (MISC_IS_AXI_ERR_MASK | \ - MISC_IS_DST_ADDR_ERR_MASK | \ - MISC_IS_SRC_LEN_ERR_MASK | \ - MISC_IS_DST_MAX_LEN_VIO_MASK | \ - MISC_IS_DST_RING_OVERFLOW_MASK | \ - MISC_IS_SRC_RING_OVERFLOW_MASK) - #define CE_SRC_RING_TO_DESC(baddr, idx) \ (&(((struct ce_desc *)baddr)[idx])) @@ -692,9 +387,9 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) #define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 -#define CE_INTERRUPT_SUMMARY(ar) \ +#define CE_INTERRUPT_SUMMARY(ar, ar_opaque) \ CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET( \ - ar->bus_read32((ar), CE_WRAPPER_BASE_ADDRESS + \ + ar_opaque->bus_ops->read32((ar), CE_WRAPPER_BASE_ADDRESS + \ CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)) #endif /* _CE_H_ */ diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 052ebd7dd26b..d37ed66d767b 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -2324,28 +2324,34 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, case ATH10K_HW_QCA988X: case ATH10K_HW_QCA9887: ar->regs = &qca988x_regs; + ar->hw_ce_regs = &qcax_ce_regs; ar->hw_values = &qca988x_values; break; case ATH10K_HW_QCA6174: case ATH10K_HW_QCA9377: ar->regs = &qca6174_regs; + ar->hw_ce_regs = &qcax_ce_regs; ar->hw_values = &qca6174_values; break; case ATH10K_HW_QCA99X0: case ATH10K_HW_QCA9984: ar->regs = &qca99x0_regs; + ar->hw_ce_regs = &qcax_ce_regs; ar->hw_values = &qca99x0_values; break; case ATH10K_HW_QCA9888: ar->regs = &qca99x0_regs; + ar->hw_ce_regs = &qcax_ce_regs; ar->hw_values = &qca9888_values; break; case ATH10K_HW_QCA4019: ar->regs = &qca4019_regs; + ar->hw_ce_regs = &qcax_ce_regs; ar->hw_values = &qca4019_values; break; case ATH10K_HW_WCN3990: ar->regs = &wcn3990_regs; + ar->hw_ce_regs = &wcn3990_ce_regs; ar->hw_values = &wcn3990_values; /* WCN3990 chip set is non bmi based */ ar->is_bmi = false; diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index bb2c5fb9a125..21c63d5d3ead 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -740,6 +740,7 @@ struct ath10k { struct completion target_suspend; const struct ath10k_hw_regs *regs; + const struct ath10k_hw_ce_regs *hw_ce_regs; const struct ath10k_hw_values *hw_values; struct ath10k_shadow_reg_value *shadow_reg_value; struct ath10k_shadow_reg_address *shadow_reg_address; @@ -923,10 +924,6 @@ struct ath10k { struct net_device napi_dev; struct napi_struct napi; - void (*bus_write32)(void *ar, u32 offset, u32 value); - u32 (*bus_read32)(void *ar, u32 offset); - spinlock_t ce_lock; /* lock for CE access */ - void *ce_states; struct fw_flag *fw_flags; /* set for bmi chip sets */ bool is_bmi; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 82a4c67f3672..c36c2481856b 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -1909,7 +1909,7 @@ int ath10k_debug_start(struct ath10k *ar) ath10k_warn(ar, "failed to disable pktlog: %d\n", ret); } - if (ar->debug.nf_cal_period) { + if (ar->debug.nf_cal_period && !QCA_REV_WCN3990(ar)) { ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period, ar->debug.nf_cal_period); @@ -1926,7 +1926,8 @@ void ath10k_debug_stop(struct ath10k *ar) { lockdep_assert_held(&ar->conf_mutex); - ath10k_debug_cal_data_fetch(ar); + if (!QCA_REV_WCN3990(ar)) + ath10k_debug_cal_data_fetch(ar); /* Must not use _sync to avoid deadlock, we do that in * ath10k_debug_destroy(). The check for htt_stats_mask is to avoid @@ -2419,15 +2420,18 @@ int ath10k_debug_register(struct ath10k *ar) debugfs_create_file("fw_dbglog", S_IRUSR | S_IWUSR, ar->debug.debugfs_phy, ar, &fops_fw_dbglog); - debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy, - ar, &fops_cal_data); + if (!QCA_REV_WCN3990(ar)) { + debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy, + ar, &fops_cal_data); + + debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR, + ar->debug.debugfs_phy, ar, + &fops_nf_cal_period); + } debugfs_create_file("ani_enable", S_IRUSR | S_IWUSR, ar->debug.debugfs_phy, ar, &fops_ani_enable); - debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR, - ar->debug.debugfs_phy, ar, &fops_nf_cal_period); - if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) { debugfs_create_file("dfs_simulate_radar", S_IWUSR, ar->debug.debugfs_phy, ar, diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index 861446a41066..65723124985e 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h @@ -74,9 +74,9 @@ struct ath10k_hif_ops { u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id); - u32 (*read32)(void *ar, u32 address); + u32 (*read32)(struct ath10k *ar, u32 address); - void (*write32)(void *ar, u32 address, u32 value); + void (*write32)(struct ath10k *ar, u32 address, u32 value); /* Power up the device and enter BMI transfer mode for FW download */ int (*power_up)(struct ath10k *ar); diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index b2678984f2de..6dd396430f19 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -541,6 +541,7 @@ struct htt_rx_indication_hdr { #define HTT_RX_INDICATION_INFO2_SERVICE_LSB 24 #define HTT_WCN3990_PADDR_MASK 0x1F +#define HTT_WCN3990_ARCH_PADDR_MASK 0x1FFFFFFFFF enum htt_rx_legacy_rate { HTT_RX_OFDM_48 = 0, @@ -865,8 +866,7 @@ struct htt_rx_offload_ind { struct htt_rx_in_ord_msdu_desc { #ifdef CONFIG_ATH10K_SNOC - __le32 msdu_paddr_lo; - __le32 msdu_paddr_hi; + __le64 msdu_paddr; #else __le32 msdu_paddr; #endif diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index cbb61267eb10..ddf097e3a143 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -429,9 +429,8 @@ static int ath10k_htt_rx_pop_paddr_list(struct ath10k_htt *htt, while (msdu_count--) { #ifdef CONFIG_ATH10K_SNOC - paddr = __le32_to_cpu(msdu_desc->msdu_paddr_lo); - paddr |= ((u64)(msdu_desc->msdu_paddr_hi & - HTT_WCN3990_PADDR_MASK) << 32); + paddr = __le64_to_cpu(msdu_desc->msdu_paddr); + paddr &= HTT_WCN3990_ARCH_PADDR_MASK; #else paddr = __le32_to_cpu(msdu_desc->msdu_paddr); #endif diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index 1a8f3a388ce2..1d37b2c8426b 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -164,6 +164,301 @@ const struct ath10k_hw_regs wcn3990_regs = { .pcie_intr_fw_mask = 0x00100000, }; +static unsigned int +ath10k_set_ring_byte(unsigned int offset, + struct ath10k_hw_ce_regs_addr_map *addr_map) +{ + return (((0 | (offset)) << addr_map->lsb) & addr_map->mask); +} + +static unsigned int +ath10k_get_ring_byte(unsigned int offset, + struct ath10k_hw_ce_regs_addr_map *addr_map) +{ + return (((offset) & addr_map->mask) >> (addr_map->lsb)); +} + +struct ath10k_hw_ce_regs_addr_map wcn3990_src_ring = { + .msb = 0x00000010, + .lsb = 0x00000010, + .mask = 0x00020000, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_regs_addr_map wcn3990_dst_ring = { + .msb = 0x00000012, + .lsb = 0x00000012, + .mask = 0x00040000, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_regs_addr_map wcn3990_dmax = { + .msb = 0x00000000, + .lsb = 0x00000000, + .mask = 0x0000ffff, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_ctrl1 wcn3990_ctrl1 = { + .addr = 0x00000018, + .src_ring = &wcn3990_src_ring, + .dst_ring = &wcn3990_dst_ring, + .dmax = &wcn3990_dmax, +}; + +struct ath10k_hw_ce_regs_addr_map wcn3990_host_ie_cc = { + .mask = 0x00000001, +}; + +struct ath10k_hw_ce_host_ie wcn3990_host_ie = { + .copy_complete = &wcn3990_host_ie_cc, +}; + +struct ath10k_hw_ce_host_wm_regs wcn3990_wm_reg = { + .dstr_lmask = 0x00000010, + .dstr_hmask = 0x00000008, + .srcr_lmask = 0x00000004, + .srcr_hmask = 0x00000002, + .cc_mask = 0x00000001, + .wm_mask = 0x0000001E, + .addr = 0x00000030, +}; + +struct ath10k_hw_ce_misc_regs wcn3990_misc_reg = { + .axi_err = 0x00000100, + .dstr_add_err = 0x00000200, + .srcr_len_err = 0x00000100, + .dstr_mlen_vio = 0x00000080, + .dstr_overflow = 0x00000040, + .srcr_overflow = 0x00000020, + .err_mask = 0x000003E0, + .addr = 0x00000038, +}; + +struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_low = { + .msb = 0x00000000, + .lsb = 0x00000010, + .mask = 0xffff0000, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_regs_addr_map wcn3990_src_wm_high = { + .msb = 0x0000000f, + .lsb = 0x00000000, + .mask = 0x0000ffff, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_src_ring = { + .addr = 0x0000004c, + .low_rst = 0x00000000, + .high_rst = 0x00000000, + .wm_low = &wcn3990_src_wm_low, + .wm_high = &wcn3990_src_wm_high, +}; + +struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_low = { + .lsb = 0x00000010, + .mask = 0xffff0000, + .set = &ath10k_set_ring_byte, +}; + +struct ath10k_hw_ce_regs_addr_map wcn3990_dst_wm_high = { + .msb = 0x0000000f, + .lsb = 0x00000000, + .mask = 0x0000ffff, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_dst_ring = { + .addr = 0x00000050, + .low_rst = 0x00000000, + .high_rst = 0x00000000, + .wm_low = &wcn3990_dst_wm_low, + .wm_high = &wcn3990_dst_wm_high, +}; + +struct ath10k_hw_ce_regs wcn3990_ce_regs = { + .sr_base_addr = 0x00000000, + .sr_size_addr = 0x00000008, + .dr_base_addr = 0x0000000c, + .dr_size_addr = 0x00000014, + .misc_ie_addr = 0x00000034, + .sr_wr_index_addr = 0x0000003c, + .dst_wr_index_addr = 0x00000040, + .current_srri_addr = 0x00000044, + .current_drri_addr = 0x00000048, + .ddr_addr_for_rri_low = 0x00000004, + .ddr_addr_for_rri_high = 0x00000008, + .ce_rri_low = 0x0024C004, + .ce_rri_high = 0x0024C008, + .host_ie_addr = 0x0000002c, + .ctrl1_regs = &wcn3990_ctrl1, + .host_ie = &wcn3990_host_ie, + .wm_regs = &wcn3990_wm_reg, + .misc_regs = &wcn3990_misc_reg, + .wm_srcr = &wcn3990_wm_src_ring, + .wm_dstr = &wcn3990_wm_dst_ring, +}; + +struct ath10k_hw_ce_regs_addr_map qcax_src_ring = { + .msb = 0x00000010, + .lsb = 0x00000010, + .mask = 0x00010000, + .set = &ath10k_set_ring_byte, +}; + +struct ath10k_hw_ce_regs_addr_map qcax_dst_ring = { + .msb = 0x00000011, + .lsb = 0x00000011, + .mask = 0x00020000, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_regs_addr_map qcax_dmax = { + .msb = 0x0000000f, + .lsb = 0x00000000, + .mask = 0x0000ffff, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_ctrl1 qcax_ctrl1 = { + .addr = 0x00000010, + .hw_mask = 0x0007ffff, + .sw_mask = 0x0007ffff, + .hw_wr_mask = 0x00000000, + .sw_wr_mask = 0x0007ffff, + .reset_mask = 0xffffffff, + .reset = 0x00000080, + .src_ring = &qcax_src_ring, + .dst_ring = &qcax_dst_ring, + .dmax = &qcax_dmax, +}; + +struct ath10k_hw_ce_regs_addr_map qcax_cmd_halt_status = { + .msb = 0x00000003, + .lsb = 0x00000003, + .mask = 0x00000008, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_cmd_halt qcax_cmd_halt = { + .msb = 0x00000000, + .mask = 0x00000001, + .status_reset = 0x00000000, + .status = &qcax_cmd_halt_status, +}; + +struct ath10k_hw_ce_regs_addr_map qcax_host_ie_cc = { + .msb = 0x00000000, + .lsb = 0x00000000, + .mask = 0x00000001, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_host_ie qcax_host_ie = { + .copy_complete_reset = 0x00000000, + .copy_complete = &qcax_host_ie_cc, +}; + +struct ath10k_hw_ce_host_wm_regs qcax_wm_reg = { + .dstr_lmask = 0x00000010, + .dstr_hmask = 0x00000008, + .srcr_lmask = 0x00000004, + .srcr_hmask = 0x00000002, + .cc_mask = 0x00000001, + .wm_mask = 0x0000001E, + .addr = 0x00000030, +}; + +struct ath10k_hw_ce_misc_regs qcax_misc_reg = { + .axi_err = 0x00000400, + .dstr_add_err = 0x00000200, + .srcr_len_err = 0x00000100, + .dstr_mlen_vio = 0x00000080, + .dstr_overflow = 0x00000040, + .srcr_overflow = 0x00000020, + .err_mask = 0x000007E0, + .addr = 0x00000038, +}; + +struct ath10k_hw_ce_regs_addr_map qcax_src_wm_low = { + .msb = 0x0000001f, + .lsb = 0x00000010, + .mask = 0xffff0000, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_regs_addr_map qcax_src_wm_high = { + .msb = 0x0000000f, + .lsb = 0x00000000, + .mask = 0x0000ffff, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_src_ring = { + .addr = 0x0000004c, + .low_rst = 0x00000000, + .high_rst = 0x00000000, + .wm_low = &qcax_src_wm_low, + .wm_high = &qcax_src_wm_high, +}; + +struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_low = { + .lsb = 0x00000010, + .mask = 0xffff0000, + .set = &ath10k_set_ring_byte, +}; + +struct ath10k_hw_ce_regs_addr_map qcax_dst_wm_high = { + .msb = 0x0000000f, + .lsb = 0x00000000, + .mask = 0x0000ffff, + .set = &ath10k_set_ring_byte, + .get = &ath10k_get_ring_byte, +}; + +struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_dst_ring = { + .addr = 0x00000050, + .low_rst = 0x00000000, + .high_rst = 0x00000000, + .wm_low = &qcax_dst_wm_low, + .wm_high = &qcax_dst_wm_high, +}; + +struct ath10k_hw_ce_regs qcax_ce_regs = { + .sr_base_addr = 0x00000000, + .sr_size_addr = 0x00000004, + .dr_base_addr = 0x00000008, + .dr_size_addr = 0x0000000c, + .ce_cmd_addr = 0x00000018, + .misc_ie_addr = 0x00000034, + .sr_wr_index_addr = 0x0000003c, + .dst_wr_index_addr = 0x00000040, + .current_srri_addr = 0x00000044, + .current_drri_addr = 0x00000048, + .host_ie_addr = 0x0000002c, + .ctrl1_regs = &qcax_ctrl1, + .cmd_halt = &qcax_cmd_halt, + .host_ie = &qcax_host_ie, + .wm_regs = &qcax_wm_reg, + .misc_regs = &qcax_misc_reg, + .wm_srcr = &qcax_wm_src_ring, + .wm_dstr = &qcax_wm_dst_ring, +}; + const struct ath10k_hw_values qca988x_values = { .rtc_state_val_on = 3, .ce_count = 8, diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index ce87f8112928..0f2422480c4e 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -268,6 +268,98 @@ extern const struct ath10k_hw_regs qca99x0_regs; extern const struct ath10k_hw_regs qca4019_regs; extern const struct ath10k_hw_regs wcn3990_regs; +struct ath10k_hw_ce_regs_addr_map { + u32 msb; + u32 lsb; + u32 mask; + unsigned int (*set)(unsigned int offset, + struct ath10k_hw_ce_regs_addr_map *addr_map); + unsigned int (*get)(unsigned int offset, + struct ath10k_hw_ce_regs_addr_map *addr_map); +}; + +struct ath10k_hw_ce_ctrl1 { + u32 addr; + u32 hw_mask; + u32 sw_mask; + u32 hw_wr_mask; + u32 sw_wr_mask; + u32 reset_mask; + u32 reset; + struct ath10k_hw_ce_regs_addr_map *src_ring; + struct ath10k_hw_ce_regs_addr_map *dst_ring; + struct ath10k_hw_ce_regs_addr_map *dmax; +}; + +struct ath10k_hw_ce_cmd_halt { + u32 status_reset; + u32 msb; + u32 mask; + struct ath10k_hw_ce_regs_addr_map *status; +}; + +struct ath10k_hw_ce_host_ie { + u32 copy_complete_reset; + struct ath10k_hw_ce_regs_addr_map *copy_complete; +}; + +struct ath10k_hw_ce_host_wm_regs { + u32 dstr_lmask; + u32 dstr_hmask; + u32 srcr_lmask; + u32 srcr_hmask; + u32 cc_mask; + u32 wm_mask; + u32 addr; +}; + +struct ath10k_hw_ce_misc_regs { + u32 axi_err; + u32 dstr_add_err; + u32 srcr_len_err; + u32 dstr_mlen_vio; + u32 dstr_overflow; + u32 srcr_overflow; + u32 err_mask; + u32 addr; +}; + +struct ath10k_hw_ce_dst_src_wm_regs { + u32 addr; + u32 low_rst; + u32 high_rst; + struct ath10k_hw_ce_regs_addr_map *wm_low; + struct ath10k_hw_ce_regs_addr_map *wm_high; +}; + +struct ath10k_hw_ce_regs { + u32 sr_base_addr; + u32 sr_size_addr; + u32 dr_base_addr; + u32 dr_size_addr; + u32 ce_cmd_addr; + u32 misc_ie_addr; + u32 sr_wr_index_addr; + u32 dst_wr_index_addr; + u32 current_srri_addr; + u32 current_drri_addr; + u32 ddr_addr_for_rri_low; + u32 ddr_addr_for_rri_high; + u32 ce_rri_low; + u32 ce_rri_high; + u32 host_ie_addr; + struct ath10k_hw_ce_host_wm_regs *wm_regs; + struct ath10k_hw_ce_misc_regs *misc_regs; + struct ath10k_hw_ce_ctrl1 *ctrl1_regs; + struct ath10k_hw_ce_cmd_halt *cmd_halt; + struct ath10k_hw_ce_host_ie *host_ie; + struct ath10k_hw_ce_dst_src_wm_regs *wm_srcr; + struct ath10k_hw_ce_dst_src_wm_regs *wm_dstr; +}; + +extern struct ath10k_hw_ce_regs wcn3990_ce_regs; +extern struct ath10k_hw_ce_regs qcax_ce_regs; + extern struct fw_flag wcn3990_fw_flags; struct ath10k_hw_values { diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 072e008900e6..9e607b2fa2d4 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -669,18 +669,18 @@ static u32 ath10k_bus_pci_read32(struct ath10k *ar, u32 offset) return val; } -inline void ath10k_pci_write32(void *ar, u32 offset, u32 value) +inline void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - ar_pci->bus_ops->write32(ar, offset, value); + ar_pci->opaque_ctx.bus_ops->write32(ar, offset, value); } -inline u32 ath10k_pci_read32(void *ar, u32 offset) +inline u32 ath10k_pci_read32(struct ath10k *ar, u32 offset) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - return ar_pci->bus_ops->read32(ar, offset); + return ar_pci->opaque_ctx.bus_ops->read32(ar, offset); } u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr) @@ -780,9 +780,9 @@ static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe) ATH10K_SKB_RXCB(skb)->paddr = paddr; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar_pci->opaque_ctx.ce_lock); ret = __ath10k_ce_rx_post_buf(ce_pipe, skb, paddr); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar_pci->opaque_ctx.ce_lock); if (ret) { dma_unmap_single(ar->dev, paddr, skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); @@ -806,9 +806,9 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) if (!ce_pipe->dest_ring) return; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar_pci->opaque_ctx.ce_lock); num = __ath10k_ce_rx_num_free_bufs(ce_pipe); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar_pci->opaque_ctx.ce_lock); while (num >= 0) { ret = __ath10k_pci_rx_post_buf(pipe); @@ -886,7 +886,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, void *data_buf = NULL; int i; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar_pci->opaque_ctx.ce_lock); ce_diag = ar_pci->ce_diag; @@ -987,7 +987,7 @@ done: dma_free_coherent(ar->dev, alloc_nbytes, data_buf, ce_data_base); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar_pci->opaque_ctx.ce_lock); return ret; } @@ -1044,7 +1044,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, dma_addr_t ce_data_base = 0; int i; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar_pci->opaque_ctx.ce_lock); ce_diag = ar_pci->ce_diag; @@ -1148,7 +1148,7 @@ done: ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n", address, ret); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar_pci->opaque_ctx.ce_lock); return ret; } @@ -1351,7 +1351,7 @@ int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, unsigned int write_index; int err, i = 0; - spin_lock_bh(&ar_pci->ce_lock); + spin_lock_bh(&ar_pci->opaque_ctx.ce_lock); nentries_mask = src_ring->nentries_mask; sw_index = src_ring->sw_index; @@ -1397,14 +1397,14 @@ int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, if (err) goto err; - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar_pci->opaque_ctx.ce_lock); return 0; err: for (; i > 0; i--) __ath10k_ce_send_revert(ce_pipe); - spin_unlock_bh(&ar_pci->ce_lock); + spin_unlock_bh(&ar_pci->opaque_ctx.ce_lock); return err; } @@ -1990,7 +1990,7 @@ static int ath10k_bus_get_num_banks(struct ath10k *ar) { struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); - return ar_pci->bus_ops->get_num_banks(ar); + return ar_pci->opaque_ctx.bus_ops->get_num_banks(ar); } int ath10k_pci_init_config(struct ath10k *ar) @@ -2165,7 +2165,7 @@ int ath10k_pci_alloc_pipes(struct ath10k *ar) for (i = 0; i < CE_COUNT; i++) { pipe = &ar_pci->pipe_info[i]; - pipe->ce_hdl = &ar_pci->ce_states[i]; + pipe->ce_hdl = &ar_pci->opaque_ctx.ce_states[i]; pipe->pipe_num = i; pipe->hif_ce_state = ar; @@ -2792,6 +2792,7 @@ static int ath10k_pci_napi_poll(struct napi_struct *ctx, int budget) { struct ath10k *ar = container_of(ctx, struct ath10k, napi); int done = 0; + struct bus_opaque *ar_opaque = ath10k_bus_priv(ar); if (ath10k_pci_has_fw_crashed(ar)) { ath10k_pci_fw_crashed_clear(ar); @@ -2814,7 +2815,7 @@ static int ath10k_pci_napi_poll(struct napi_struct *ctx, int budget) * interrupts safer to check for pending interrupts for * immediate servicing. */ - if (CE_INTERRUPT_SUMMARY(ar)) { + if (CE_INTERRUPT_SUMMARY(ar, ar_opaque)) { napi_reschedule(ctx); goto out; } @@ -3132,7 +3133,7 @@ int ath10k_pci_setup_resource(struct ath10k *ar) struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); int ret; - spin_lock_init(&ar_pci->ce_lock); + spin_lock_init(&ar_pci->opaque_ctx.ce_lock); spin_lock_init(&ar_pci->ps_lock); setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, @@ -3243,7 +3244,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar_pci->ar = ar; ar->dev_id = pci_dev->device; ar_pci->pci_ps = pci_ps; - ar_pci->bus_ops = &ath10k_pci_bus_ops; + ar_pci->opaque_ctx.bus_ops = &ath10k_pci_bus_ops; ar_pci->pci_soft_reset = pci_soft_reset; ar_pci->pci_hard_reset = pci_hard_reset; @@ -3252,14 +3253,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar->id.subsystem_vendor = pdev->subsystem_vendor; ar->id.subsystem_device = pdev->subsystem_device; - spin_lock_init(&ar_pci->ce_lock); spin_lock_init(&ar_pci->ps_lock); - - ar->bus_write32 = ath10k_pci_write32; - ar->bus_read32 = ath10k_pci_read32; - ar->ce_lock = ar_pci->ce_lock; - ar->ce_states = ar_pci->ce_states; - setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, (unsigned long)ar); setup_timer(&ar_pci->ps_timer, ath10k_pci_ps_timer, diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 06d0bd3993d3..22730c700af3 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -155,12 +155,6 @@ struct ath10k_pci_supp_chip { u32 rev_id; }; -struct ath10k_bus_ops { - u32 (*read32)(struct ath10k *ar, u32 offset); - void (*write32)(struct ath10k *ar, u32 offset, u32 value); - int (*get_num_banks)(struct ath10k *ar); -}; - enum ath10k_pci_irq_mode { ATH10K_PCI_IRQ_AUTO = 0, ATH10K_PCI_IRQ_LEGACY = 1, @@ -168,6 +162,7 @@ enum ath10k_pci_irq_mode { }; struct ath10k_pci { + struct bus_opaque opaque_ctx; struct pci_dev *pdev; struct device *dev; struct ath10k *ar; @@ -182,11 +177,6 @@ struct ath10k_pci { /* Copy Engine used for Diagnostic Accesses */ struct ath10k_ce_pipe *ce_diag; - /* FIXME: document what this really protects */ - spinlock_t ce_lock; - - /* Map CE id to ce_state */ - struct ath10k_ce_pipe ce_states[CE_COUNT_MAX]; struct timer_list rx_post_retry; /* Due to HW quirks it is recommended to disable ASPM during device @@ -230,8 +220,6 @@ struct ath10k_pci { */ bool pci_ps; - const struct ath10k_bus_ops *bus_ops; - /* Chip specific pci reset routine used to do a safe reset */ int (*pci_soft_reset)(struct ath10k *ar); @@ -263,11 +251,11 @@ static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) /* Wait up to this many Ms for a Diagnostic Access CE operation to complete */ #define DIAG_ACCESS_CE_TIMEOUT_MS 10 -void ath10k_pci_write32(void *ar, u32 offset, u32 value); +void ath10k_pci_write32(struct ath10k *ar, u32 offset, u32 value); void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val); void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val); -u32 ath10k_pci_read32(void *ar, u32 offset); +u32 ath10k_pci_read32(struct ath10k *ar, u32 offset); u32 ath10k_pci_soc_read32(struct ath10k *ar, u32 addr); u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr); diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 6c8797d5e5fc..081e44b3277a 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -413,9 +413,9 @@ static struct ath10k_shadow_reg_cfg target_shadow_reg_cfg_map[] = { { 11, WCN3990_DST_WR_INDEX_OFFSET}, }; -void ath10k_snoc_write32(void *ar, u32 offset, u32 value) +void ath10k_snoc_write32(struct ath10k *ar, u32 offset, u32 value) { - struct ath10k_snoc *ar_snoc = ath10k_snoc_priv((struct ath10k *)ar); + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); if (!ar_snoc) return; @@ -423,9 +423,9 @@ void ath10k_snoc_write32(void *ar, u32 offset, u32 value) iowrite32(value, ar_snoc->mem + offset); } -u32 ath10k_snoc_read32(void *ar, u32 offset) +u32 ath10k_snoc_read32(struct ath10k *ar, u32 offset) { - struct ath10k_snoc *ar_snoc = ath10k_snoc_priv((struct ath10k *)ar); + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); u32 val; if (!ar_snoc) @@ -462,9 +462,9 @@ static int __ath10k_snoc_rx_post_buf(struct ath10k_snoc_pipe *pipe) ATH10K_SKB_RXCB(skb)->paddr = paddr; - spin_lock_bh(&ar_snoc->ce_lock); + spin_lock_bh(&ar_snoc->opaque_ctx.ce_lock); ret = __ath10k_ce_rx_post_buf(ce_pipe, skb, paddr); - spin_unlock_bh(&ar_snoc->ce_lock); + spin_unlock_bh(&ar_snoc->opaque_ctx.ce_lock); if (ret) { dma_unmap_single(ar->dev, paddr, skb->len + skb_tailroom(skb), DMA_FROM_DEVICE); @@ -488,9 +488,9 @@ static void ath10k_snoc_rx_post_pipe(struct ath10k_snoc_pipe *pipe) if (!ce_pipe->dest_ring) return; - spin_lock_bh(&ar_snoc->ce_lock); + spin_lock_bh(&ar_snoc->opaque_ctx.ce_lock); num = __ath10k_ce_rx_num_free_bufs(ce_pipe); - spin_unlock_bh(&ar_snoc->ce_lock); + spin_unlock_bh(&ar_snoc->opaque_ctx.ce_lock); while (num--) { ret = __ath10k_snoc_rx_post_buf(pipe); if (ret) { @@ -638,7 +638,7 @@ static int ath10k_snoc_hif_tx_sg(struct ath10k *ar, u8 pipe_id, snoc_pipe = &ar_snoc->pipe_info[pipe_id]; ce_pipe = snoc_pipe->ce_hdl; src_ring = ce_pipe->src_ring; - spin_lock_bh(&ar_snoc->ce_lock); + spin_lock_bh(&ar_snoc->opaque_ctx.ce_lock); nentries_mask = src_ring->nentries_mask; sw_index = src_ring->sw_index; @@ -678,14 +678,14 @@ static int ath10k_snoc_hif_tx_sg(struct ath10k *ar, u8 pipe_id, if (err) goto err; - spin_unlock_bh(&ar_snoc->ce_lock); + spin_unlock_bh(&ar_snoc->opaque_ctx.ce_lock); return 0; err: for (; i > 0; i--) __ath10k_ce_send_revert(ce_pipe); - spin_unlock_bh(&ar_snoc->ce_lock); + spin_unlock_bh(&ar_snoc->opaque_ctx.ce_lock); return err; } @@ -882,7 +882,7 @@ static int ath10k_snoc_alloc_pipes(struct ath10k *ar) for (i = 0; i < CE_COUNT; i++) { pipe = &ar_snoc->pipe_info[i]; - pipe->ce_hdl = &ar_snoc->ce_states[i]; + pipe->ce_hdl = &ar_snoc->opaque_ctx.ce_states[i]; pipe->pipe_num = i; pipe->hif_ce_state = ar; @@ -1184,6 +1184,11 @@ static const struct ath10k_hif_ops ath10k_snoc_hif_ops = { .write32 = ath10k_snoc_write32, }; +static const struct ath10k_bus_ops ath10k_snoc_bus_ops = { + .read32 = ath10k_snoc_read32, + .write32 = ath10k_snoc_write32, +}; + static int ath10k_snoc_probe(struct platform_device *pdev) { int ret; @@ -1210,11 +1215,8 @@ static int ath10k_snoc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, ar); ar_snoc->ar = ar; - spin_lock_init(&ar_snoc->ce_lock); - ar->bus_write32 = ath10k_snoc_write32; - ar->bus_read32 = ath10k_snoc_read32; - ar->ce_lock = ar_snoc->ce_lock; - ar->ce_states = ar_snoc->ce_states; + spin_lock_init(&ar_snoc->opaque_ctx.ce_lock); + ar_snoc->opaque_ctx.bus_ops = &ath10k_snoc_bus_ops; ath10k_snoc_resource_init(ar); ar->target_version = ATH10K_HW_WCN3990; diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h index 1754a3e91a00..0a5f5bff37ec 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.h +++ b/drivers/net/wireless/ath/ath10k/snoc.h @@ -103,6 +103,7 @@ struct ath10k_target_info { * @is_driver_probed: flag to indicate driver state */ struct ath10k_snoc { + struct bus_opaque opaque_ctx; struct platform_device *dev; struct ath10k *ar; void __iomem *mem; @@ -110,9 +111,6 @@ struct ath10k_snoc { struct ath10k_target_info target_info; size_t mem_len; struct ath10k_snoc_pipe pipe_info[CE_COUNT_MAX]; - /* protects CE info */ - spinlock_t ce_lock; - struct ath10k_ce_pipe ce_states[CE_COUNT_MAX]; struct timer_list rx_post_retry; u32 ce_irqs[CE_COUNT_MAX]; u32 *vaddr_rri_on_ddr; @@ -191,10 +189,10 @@ static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar) return (struct ath10k_snoc *)ar->drv_priv; } -void ath10k_snoc_write32(void *ar, u32 offset, u32 value); +void ath10k_snoc_write32(struct ath10k *ar, u32 offset, u32 value); void ath10k_snoc_soc_write32(struct ath10k *ar, u32 addr, u32 val); void ath10k_snoc_reg_write32(struct ath10k *ar, u32 addr, u32 val); -u32 ath10k_snoc_read32(void *ar, u32 offset); +u32 ath10k_snoc_read32(struct ath10k *ar, u32 offset); u32 ath10k_snoc_soc_read32(struct ath10k *ar, u32 addr); u32 ath10k_snoc_reg_read32(struct ath10k *ar, u32 addr); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 8b4561e8ce1a..ef493271c712 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -4176,7 +4176,7 @@ static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah, if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9531(ah)) ar9003_hw_internal_regulator_apply(ah); ar9003_hw_apply_tuning_caps(ah); - ar9003_hw_apply_minccapwr_thresh(ah, chan); + ar9003_hw_apply_minccapwr_thresh(ah, is2ghz); ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz); ar9003_hw_thermometer_apply(ah); ar9003_hw_thermo_cal_apply(ah); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 1bdeacf7b257..bc70ce62bc03 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -869,8 +869,8 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE); - hw->wiphy->iface_combinations = if_comb; - hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); + hw->wiphy->iface_combinations = if_comb; + hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); } hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 5cc0ddc254eb..7be31f27266c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1550,13 +1550,13 @@ static int ath9k_sta_state(struct ieee80211_hw *hw, struct ath_common *common = ath9k_hw_common(sc->sc_ah); int ret = 0; - if (old_state == IEEE80211_STA_AUTH && - new_state == IEEE80211_STA_ASSOC) { + if (old_state == IEEE80211_STA_NOTEXIST && + new_state == IEEE80211_STA_NONE) { ret = ath9k_sta_add(hw, vif, sta); ath_dbg(common, CONFIG, "Add station: %pM\n", sta->addr); - } else if (old_state == IEEE80211_STA_ASSOC && - new_state == IEEE80211_STA_AUTH) { + } else if (old_state == IEEE80211_STA_NONE && + new_state == IEEE80211_STA_NOTEXIST) { ret = ath9k_sta_remove(hw, vif, sta); ath_dbg(common, CONFIG, "Remove station: %pM\n", sta->addr); diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 75ae474367f9..fe6d5ab7f95b 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -705,9 +705,6 @@ static int wil_target_reset(struct wil6210_priv *wil) wil_s(wil, RGF_DMA_OFUL_NID_0, BIT_DMA_OFUL_NID_0_RX_EXT_TR_EN | BIT_DMA_OFUL_NID_0_RX_EXT_A3_SRC); - /* Enable fix for PCIe HW bug, set "No snoop" for RX transactions */ - wil_s(wil, RGF_DMA_PEDI_DIF, BIT_DMA_WR_CMD_ATTR_NO_SNOOP); - wil_dbg_misc(wil, "Reset completed in %d ms\n", delay * RST_DELAY); return 0; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 410a6645d316..59cef6c69fe8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c @@ -726,8 +726,10 @@ int brcmf_sdiod_recv_chain(struct brcmf_sdio_dev *sdiodev, return -ENOMEM; err = brcmf_sdiod_buffrw(sdiodev, SDIO_FUNC_2, false, addr, glom_skb); - if (err) + if (err) { + brcmu_pkt_buf_free_skb(glom_skb); goto done; + } skb_queue_walk(pktq, skb) { memcpy(skb->data, glom_skb->data, skb->len); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index deb5f78dcacc..70a6985334d5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -2408,7 +2408,7 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) WL_BSS_INFO_MAX); if (err) { brcmf_err("Failed to get bss info (%d)\n", err); - return; + goto out_kfree; } si->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); si->bss_param.beacon_interval = le16_to_cpu(buf->bss_le.beacon_period); @@ -2420,6 +2420,9 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si) si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; if (capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) si->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; + +out_kfree: + kfree(buf); } static s32 @@ -4099,7 +4102,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, (u8 *)&settings->beacon.head[ie_offset], settings->beacon.head_len - ie_offset, WLAN_EID_SSID); - if (!ssid_ie) + if (!ssid_ie || ssid_ie->len > IEEE80211_MAX_SSID_LEN) return -EINVAL; memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len); diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c index 796f5f9d5d5a..b7df576bb84d 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c @@ -1079,8 +1079,10 @@ bool dma_rxfill(struct dma_pub *pub) pa = dma_map_single(di->dmadev, p->data, di->rxbufsize, DMA_FROM_DEVICE); - if (dma_mapping_error(di->dmadev, pa)) + if (dma_mapping_error(di->dmadev, pa)) { + brcmu_pkt_buf_free_skb(p); return false; + } /* save the free packet pointer */ di->rxp[rxout] = p; diff --git a/drivers/net/wireless/brcm80211/brcmsmac/stf.c b/drivers/net/wireless/brcm80211/brcmsmac/stf.c index dd9162722495..0ab865de1491 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/stf.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/stf.c @@ -87,7 +87,7 @@ void brcms_c_stf_ss_algo_channel_get(struct brcms_c_info *wlc, u16 *ss_algo_channel, u16 chanspec) { - struct tx_power power; + struct tx_power power = { }; u8 siso_mcs_id, cdd_mcs_id, stbc_mcs_id; /* Clear previous settings */ diff --git a/drivers/net/wireless/iwlegacy/3945.c b/drivers/net/wireless/iwlegacy/3945.c index 93bdf684babe..ae047ab7a4df 100644 --- a/drivers/net/wireless/iwlegacy/3945.c +++ b/drivers/net/wireless/iwlegacy/3945.c @@ -1019,12 +1019,13 @@ il3945_hw_txq_ctx_free(struct il_priv *il) int txq_id; /* Tx queues */ - if (il->txq) + if (il->txq) { for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) if (txq_id == IL39_CMD_QUEUE_NUM) il_cmd_queue_free(il); else il_tx_queue_free(il, txq_id); + } /* free tx queue structure */ il_free_txq_mem(il); diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c index 20e6aa910700..c148085742a0 100644 --- a/drivers/net/wireless/iwlwifi/dvm/calib.c +++ b/drivers/net/wireless/iwlwifi/dvm/calib.c @@ -901,7 +901,7 @@ static void iwlagn_gain_computation(struct iwl_priv *priv, /* bound gain by 2 bits value max, 3rd bit is sign */ data->delta_gain_code[i] = min(abs(delta_g), - (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); + (s32) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); if (delta_g < 0) /* diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 610c442c7ab2..9584f950fd2f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c @@ -935,7 +935,8 @@ int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm, u8 conf_id) } mvm->fw_dbg_conf = conf_id; - return ret; + + return 0; } static int iwl_mvm_config_ltr(struct iwl_mvm *mvm) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index f96ab2f4b90e..ce12717e656a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -3992,8 +3992,8 @@ static int iwl_mvm_mac_get_survey(struct ieee80211_hw *hw, int idx, if (idx != 0) return -ENOENT; - if (fw_has_capa(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS)) + if (!fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS)) return -ENOENT; mutex_lock(&mvm->mutex); @@ -4039,8 +4039,8 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw, struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - if (fw_has_capa(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS)) + if (!fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS)) return; /* if beacon filtering isn't on mac80211 does it anyway */ diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c index b0f59fdd287c..d7d72adb6343 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/iwlwifi/mvm/sf.c @@ -215,7 +215,7 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, enum iwl_sf_state new_state) { struct iwl_sf_cfg_cmd sf_cmd = { - .state = cpu_to_le32(SF_FULL_ON), + .state = cpu_to_le32(new_state), }; struct ieee80211_sta *sta; int ret = 0; diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index d58c094f2f04..f7e6a09926dd 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -475,48 +475,64 @@ static const struct pci_device_id iwl_hw_card_ids[] = { MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); #ifdef CONFIG_ACPI -#define SPL_METHOD "SPLC" -#define SPL_DOMAINTYPE_MODULE BIT(0) -#define SPL_DOMAINTYPE_WIFI BIT(1) -#define SPL_DOMAINTYPE_WIGIG BIT(2) -#define SPL_DOMAINTYPE_RFEM BIT(3) +#define ACPI_SPLC_METHOD "SPLC" +#define ACPI_SPLC_DOMAIN_WIFI (0x07) -static u64 splx_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splx) +static u64 splc_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splc) { - union acpi_object *limits, *domain_type, *power_limit; - - if (splx->type != ACPI_TYPE_PACKAGE || - splx->package.count != 2 || - splx->package.elements[0].type != ACPI_TYPE_INTEGER || - splx->package.elements[0].integer.value != 0) { - IWL_ERR(trans, "Unsupported splx structure\n"); + union acpi_object *data_pkg, *dflt_pwr_limit; + int i; + + /* We need at least two elements, one for the revision and one + * for the data itself. Also check that the revision is + * supported (currently only revision 0). + */ + if (splc->type != ACPI_TYPE_PACKAGE || + splc->package.count < 2 || + splc->package.elements[0].type != ACPI_TYPE_INTEGER || + splc->package.elements[0].integer.value != 0) { + IWL_DEBUG_INFO(trans, + "Unsupported structure returned by the SPLC method. Ignoring.\n"); return 0; } - limits = &splx->package.elements[1]; - if (limits->type != ACPI_TYPE_PACKAGE || - limits->package.count < 2 || - limits->package.elements[0].type != ACPI_TYPE_INTEGER || - limits->package.elements[1].type != ACPI_TYPE_INTEGER) { - IWL_ERR(trans, "Invalid limits element\n"); - return 0; + /* loop through all the packages to find the one for WiFi */ + for (i = 1; i < splc->package.count; i++) { + union acpi_object *domain; + + data_pkg = &splc->package.elements[i]; + + /* Skip anything that is not a package with the right + * amount of elements (i.e. at least 2 integers). + */ + if (data_pkg->type != ACPI_TYPE_PACKAGE || + data_pkg->package.count < 2 || + data_pkg->package.elements[0].type != ACPI_TYPE_INTEGER || + data_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) + continue; + + domain = &data_pkg->package.elements[0]; + if (domain->integer.value == ACPI_SPLC_DOMAIN_WIFI) + break; + + data_pkg = NULL; } - domain_type = &limits->package.elements[0]; - power_limit = &limits->package.elements[1]; - if (!(domain_type->integer.value & SPL_DOMAINTYPE_WIFI)) { - IWL_DEBUG_INFO(trans, "WiFi power is not limited\n"); + if (!data_pkg) { + IWL_DEBUG_INFO(trans, + "No element for the WiFi domain returned by the SPLC method.\n"); return 0; } - return power_limit->integer.value; + dflt_pwr_limit = &data_pkg->package.elements[1]; + return dflt_pwr_limit->integer.value; } static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev) { acpi_handle pxsx_handle; acpi_handle handle; - struct acpi_buffer splx = {ACPI_ALLOCATE_BUFFER, NULL}; + struct acpi_buffer splc = {ACPI_ALLOCATE_BUFFER, NULL}; acpi_status status; pxsx_handle = ACPI_HANDLE(&pdev->dev); @@ -527,23 +543,24 @@ static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev) } /* Get the method's handle */ - status = acpi_get_handle(pxsx_handle, (acpi_string)SPL_METHOD, &handle); + status = acpi_get_handle(pxsx_handle, (acpi_string)ACPI_SPLC_METHOD, + &handle); if (ACPI_FAILURE(status)) { - IWL_DEBUG_INFO(trans, "SPL method not found\n"); + IWL_DEBUG_INFO(trans, "SPLC method not found\n"); return; } /* Call SPLC with no arguments */ - status = acpi_evaluate_object(handle, NULL, NULL, &splx); + status = acpi_evaluate_object(handle, NULL, NULL, &splc); if (ACPI_FAILURE(status)) { IWL_ERR(trans, "SPLC invocation failed (0x%x)\n", status); return; } - trans->dflt_pwr_limit = splx_get_pwr_limit(trans, splx.pointer); + trans->dflt_pwr_limit = splc_get_pwr_limit(trans, splc.pointer); IWL_DEBUG_INFO(trans, "Default power limit set to %lld\n", trans->dflt_pwr_limit); - kfree(splx.pointer); + kfree(splc.pointer); } #else /* CONFIG_ACPI */ diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index a8c8a4a7420b..8dfe6b2bc703 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c @@ -1508,9 +1508,9 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, /* start the TFD with the scratchbuf */ scratch_size = min_t(int, copy_size, IWL_HCMD_SCRATCHBUF_SIZE); - memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size); + memcpy(&txq->scratchbufs[idx], &out_cmd->hdr, scratch_size); iwl_pcie_txq_build_tfd(trans, txq, - iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr), + iwl_pcie_get_scratchbuf_dma(txq, idx), scratch_size, true); /* map first command fragment, if any remains */ diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 4073116e6e9f..c3331d6201c3 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -2144,8 +2144,9 @@ done: is_scanning_required = 1; } else { mwifiex_dbg(priv->adapter, MSG, - "info: trying to associate to '%s' bssid %pM\n", - (char *)req_ssid.ssid, bss->bssid); + "info: trying to associate to '%.*s' bssid %pM\n", + req_ssid.ssid_len, (char *)req_ssid.ssid, + bss->bssid); memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN); break; } @@ -2202,8 +2203,8 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, } mwifiex_dbg(adapter, INFO, - "info: Trying to associate to %s and bssid %pM\n", - (char *)sme->ssid, sme->bssid); + "info: Trying to associate to %.*s and bssid %pM\n", + (int)sme->ssid_len, (char *)sme->ssid, sme->bssid); ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, priv->bss_mode, sme->channel, sme, 0); @@ -2333,8 +2334,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, } mwifiex_dbg(priv->adapter, MSG, - "info: trying to join to %s and bssid %pM\n", - (char *)params->ssid, params->bssid); + "info: trying to join to %.*s and bssid %pM\n", + params->ssid_len, (char *)params->ssid, params->bssid); mwifiex_set_ibss_params(priv, params); diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 3cda1f956f0b..6378dfd3b4e8 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -661,9 +661,8 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN, sizeof(priv->assoc_rsp_buf)); - memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size); - assoc_rsp->a_id = cpu_to_le16(aid); + memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size); if (status_code) { priv->adapter->dbg.num_cmd_assoc_failure++; diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c index 5be34118e0af..f67e7e5b13e1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/regd.c +++ b/drivers/net/wireless/realtek/rtlwifi/regd.c @@ -345,9 +345,9 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select( return &rtl_regdom_no_midband; case COUNTRY_CODE_IC: return &rtl_regdom_11; - case COUNTRY_CODE_ETSI: case COUNTRY_CODE_TELEC_NETGEAR: return &rtl_regdom_60_64; + case COUNTRY_CODE_ETSI: case COUNTRY_CODE_SPAIN: case COUNTRY_CODE_FRANCE: case COUNTRY_CODE_ISRAEL: @@ -406,6 +406,8 @@ static u8 channel_plan_to_country_code(u8 channelplan) return COUNTRY_CODE_WORLD_WIDE_13; case 0x22: return COUNTRY_CODE_IC; + case 0x25: + return COUNTRY_CODE_ETSI; case 0x32: return COUNTRY_CODE_TELEC_NETGEAR; case 0x41: |
