diff options
Diffstat (limited to 'drivers')
48 files changed, 556 insertions, 192 deletions
diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c index 1828ed8cae7a..c4867576be00 100644 --- a/drivers/bluetooth/btmrvl_debugfs.c +++ b/drivers/bluetooth/btmrvl_debugfs.c @@ -35,15 +35,9 @@ static ssize_t btmrvl_hscfgcmd_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct btmrvl_private *priv = file->private_data; - char buf[16]; long result, ret; - memset(buf, 0, sizeof(buf)); - - if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) - return -EFAULT; - - ret = kstrtol(buf, 10, &result); + ret = kstrtol_from_user(ubuf, count, 10, &result); if (ret) return ret; @@ -81,15 +75,9 @@ static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct btmrvl_private *priv = file->private_data; - char buf[16]; long result, ret; - memset(buf, 0, sizeof(buf)); - - if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) - return -EFAULT; - - ret = kstrtol(buf, 10, &result); + ret = kstrtol_from_user(ubuf, count, 10, &result); if (ret) return ret; @@ -127,15 +115,9 @@ static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct btmrvl_private *priv = file->private_data; - char buf[16]; long result, ret; - memset(buf, 0, sizeof(buf)); - - if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) - return -EFAULT; - - ret = kstrtol(buf, 10, &result); + ret = kstrtol_from_user(ubuf, count, 10, &result); if (ret) return ret; @@ -167,35 +149,6 @@ static const struct file_operations btmrvl_hscmd_fops = { .llseek = default_llseek, }; -static ssize_t btmrvl_fwdump_write(struct file *file, const char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct btmrvl_private *priv = file->private_data; - char buf[16]; - bool result; - - memset(buf, 0, sizeof(buf)); - - if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) - return -EFAULT; - - if (strtobool(buf, &result)) - return -EINVAL; - - if (!result) - return -EINVAL; - - btmrvl_firmware_dump(priv); - - return count; -} - -static const struct file_operations btmrvl_fwdump_fops = { - .write = btmrvl_fwdump_write, - .open = simple_open, - .llseek = default_llseek, -}; - void btmrvl_debugfs_init(struct hci_dev *hdev) { struct btmrvl_private *priv = hci_get_drvdata(hdev); @@ -226,8 +179,6 @@ void btmrvl_debugfs_init(struct hci_dev *hdev) priv, &btmrvl_hscmd_fops); debugfs_create_file("hscfgcmd", 0644, dbg->config_dir, priv, &btmrvl_hscfgcmd_fops); - debugfs_create_file("fw_dump", 0200, dbg->config_dir, - priv, &btmrvl_fwdump_fops); dbg->status_dir = debugfs_create_dir("status", hdev->debugfs); debugfs_create_u8("curpsmode", 0444, dbg->status_dir, diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index fc3caf4541ba..f0454541e5fd 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h @@ -110,7 +110,6 @@ struct btmrvl_private { u8 *payload, u16 nb); int (*hw_wakeup_firmware)(struct btmrvl_private *priv); int (*hw_process_int_status)(struct btmrvl_private *priv); - void (*firmware_dump)(struct btmrvl_private *priv); spinlock_t driver_lock; /* spinlock used by driver */ #ifdef CONFIG_DEBUG_FS void *debugfs_data; @@ -183,7 +182,6 @@ int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv); int btmrvl_enable_ps(struct btmrvl_private *priv); int btmrvl_prepare_command(struct btmrvl_private *priv); int btmrvl_enable_hs(struct btmrvl_private *priv); -void btmrvl_firmware_dump(struct btmrvl_private *priv); #ifdef CONFIG_DEBUG_FS void btmrvl_debugfs_init(struct hci_dev *hdev); diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index f6c694a1b9b0..708ad21683eb 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -358,12 +358,6 @@ int btmrvl_prepare_command(struct btmrvl_private *priv) return ret; } -void btmrvl_firmware_dump(struct btmrvl_private *priv) -{ - if (priv->firmware_dump) - priv->firmware_dump(priv); -} - static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb) { int ret = 0; diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 6f99b9f3d57f..888bac49a87b 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -1311,9 +1311,11 @@ rdwr_status btmrvl_sdio_rdwr_firmware(struct btmrvl_private *priv, } /* This function dump sdio register and memory data */ -static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv) +static void btmrvl_sdio_coredump(struct device *dev) { - struct btmrvl_sdio_card *card = priv->btmrvl_dev.card; + struct sdio_func *func = dev_to_sdio_func(dev); + struct btmrvl_sdio_card *card; + struct btmrvl_private *priv; int ret = 0; unsigned int reg, reg_start, reg_end; enum rdwr_status stat; @@ -1321,6 +1323,9 @@ static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv) u8 dump_num = 0, idx, i, read_reg, doneflag = 0; u32 memory_size, fw_dump_len = 0; + card = sdio_get_drvdata(func); + priv = card->priv; + /* dump sdio register first */ btmrvl_sdio_dump_regs(priv); @@ -1547,7 +1552,6 @@ static int btmrvl_sdio_probe(struct sdio_func *func, priv->hw_host_to_card = btmrvl_sdio_host_to_card; priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw; priv->hw_process_int_status = btmrvl_sdio_process_int_status; - priv->firmware_dump = btmrvl_sdio_dump_firmware; if (btmrvl_register_hdev(priv)) { BT_ERR("Register hdev failed!"); @@ -1717,6 +1721,7 @@ static struct sdio_driver bt_mrvl_sdio = { .remove = btmrvl_sdio_remove, .drv = { .owner = THIS_MODULE, + .coredump = btmrvl_sdio_coredump, .pm = &btmrvl_sdio_pm_ops, } }; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 91882f54c7bd..f73a27ea28cc 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -373,6 +373,9 @@ static const struct usb_device_id blacklist_table[] = { /* Additional Realtek 8723BU Bluetooth devices */ { USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK }, + /* Additional Realtek 8723DE Bluetooth devices */ + { USB_DEVICE(0x2ff8, 0xb011), .driver_info = BTUSB_REALTEK }, + /* Additional Realtek 8821AE Bluetooth devices */ { USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK }, @@ -381,6 +384,7 @@ static const struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK }, /* Additional Realtek 8822BE Bluetooth devices */ + { USB_DEVICE(0x13d3, 0x3526), .driver_info = BTUSB_REALTEK }, { USB_DEVICE(0x0b05, 0x185c), .driver_info = BTUSB_REALTEK }, /* Silicon Wave based devices */ @@ -408,6 +412,13 @@ static const struct dmi_system_id btusb_needs_reset_resume_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9360"), }, }, + { + /* Dell Inspiron 5565 (QCA ROME device 0cf3:e009) */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 5565"), + }, + }, {} }; @@ -2499,11 +2510,9 @@ static const struct qca_device_info qca_devices_table[] = { { 0x00000302, 28, 4, 18 }, /* Rome 3.2 */ }; -static int btusb_qca_send_vendor_req(struct hci_dev *hdev, u8 request, +static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request, void *data, u16 size) { - struct btusb_data *btdata = hci_get_drvdata(hdev); - struct usb_device *udev = btdata->udev; int pipe, err; u8 *buf; @@ -2518,7 +2527,7 @@ static int btusb_qca_send_vendor_req(struct hci_dev *hdev, u8 request, err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, buf, size, USB_CTRL_SET_TIMEOUT); if (err < 0) { - bt_dev_err(hdev, "Failed to access otp area (%d)", err); + dev_err(&udev->dev, "Failed to access otp area (%d)", err); goto done; } @@ -2668,20 +2677,38 @@ static int btusb_setup_qca_load_nvm(struct hci_dev *hdev, return err; } +/* identify the ROM version and check whether patches are needed */ +static bool btusb_qca_need_patch(struct usb_device *udev) +{ + struct qca_version ver; + + if (btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver, + sizeof(ver)) < 0) + return false; + /* only low ROM versions need patches */ + return !(le32_to_cpu(ver.rom_version) & ~0xffffU); +} + static int btusb_setup_qca(struct hci_dev *hdev) { + struct btusb_data *btdata = hci_get_drvdata(hdev); + struct usb_device *udev = btdata->udev; const struct qca_device_info *info = NULL; struct qca_version ver; u32 ver_rom; u8 status; int i, err; - err = btusb_qca_send_vendor_req(hdev, QCA_GET_TARGET_VERSION, &ver, + err = btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver, sizeof(ver)); if (err < 0) return err; ver_rom = le32_to_cpu(ver.rom_version); + /* Don't care about high ROM versions */ + if (ver_rom & ~0xffffU) + return 0; + for (i = 0; i < ARRAY_SIZE(qca_devices_table); i++) { if (ver_rom == qca_devices_table[i].rom_version) info = &qca_devices_table[i]; @@ -2691,7 +2718,7 @@ static int btusb_setup_qca(struct hci_dev *hdev) return -ENODEV; } - err = btusb_qca_send_vendor_req(hdev, QCA_CHECK_STATUS, &status, + err = btusb_qca_send_vendor_req(udev, QCA_CHECK_STATUS, &status, sizeof(status)); if (err < 0) return err; @@ -2905,7 +2932,8 @@ static int btusb_probe(struct usb_interface *intf, /* Old firmware would otherwise let ath3k driver load * patch and sysconfig files */ - if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001) + if (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x0001 && + !btusb_qca_need_patch(udev)) return -ENODEV; } @@ -3067,6 +3095,7 @@ static int btusb_probe(struct usb_interface *intf, } if (id->driver_info & BTUSB_ATH3012) { + data->setup_on_usb = btusb_setup_qca; hdev->set_bdaddr = btusb_set_bdaddr_ath3012; set_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks); set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks); diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c index f06f0f1132fb..ddbd8c6a0ceb 100644 --- a/drivers/bluetooth/hci_bcm.c +++ b/drivers/bluetooth/hci_bcm.c @@ -380,10 +380,6 @@ static int bcm_open(struct hci_uart *hu) mutex_lock(&bcm_device_lock); if (hu->serdev) { - err = serdev_device_open(hu->serdev); - if (err) - goto err_free; - bcm->dev = serdev_device_get_drvdata(hu->serdev); goto out; } @@ -420,13 +416,10 @@ out: return 0; err_unset_hu: - if (hu->serdev) - serdev_device_close(hu->serdev); #ifdef CONFIG_PM - else + if (!hu->serdev) bcm->dev->hu = NULL; #endif -err_free: mutex_unlock(&bcm_device_lock); hu->priv = NULL; kfree(bcm); @@ -445,7 +438,6 @@ static int bcm_close(struct hci_uart *hu) mutex_lock(&bcm_device_lock); if (hu->serdev) { - serdev_device_close(hu->serdev); bdev = serdev_device_get_drvdata(hu->serdev); } else if (bcm_device_exists(bcm->dev)) { bdev = bcm->dev; diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 954213e5daa5..963bb0309e25 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -195,7 +195,7 @@ restart: clear_bit(HCI_UART_SENDING, &hu->tx_state); } -static void hci_uart_init_work(struct work_struct *work) +void hci_uart_init_work(struct work_struct *work) { struct hci_uart *hu = container_of(work, struct hci_uart, init_ready); int err; @@ -229,15 +229,6 @@ int hci_uart_init_ready(struct hci_uart *hu) } /* ------- Interface to HCI layer ------ */ -/* Initialize device */ -static int hci_uart_open(struct hci_dev *hdev) -{ - BT_DBG("%s %p", hdev->name, hdev); - - /* Nothing to do for UART driver */ - return 0; -} - /* Reset device */ static int hci_uart_flush(struct hci_dev *hdev) { @@ -264,6 +255,17 @@ static int hci_uart_flush(struct hci_dev *hdev) return 0; } +/* Initialize device */ +static int hci_uart_open(struct hci_dev *hdev) +{ + BT_DBG("%s %p", hdev->name, hdev); + + /* Undo clearing this from hci_uart_close() */ + hdev->flush = hci_uart_flush; + + return 0; +} + /* Close device */ static int hci_uart_close(struct hci_dev *hdev) { diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 27e414b4e3a2..3e767f245ed5 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -141,7 +141,6 @@ static int ll_open(struct hci_uart *hu) if (hu->serdev) { struct ll_device *lldev = serdev_device_get_drvdata(hu->serdev); - serdev_device_open(hu->serdev); if (!IS_ERR(lldev->ext_clk)) clk_prepare_enable(lldev->ext_clk); } @@ -179,8 +178,6 @@ static int ll_close(struct hci_uart *hu) gpiod_set_value_cansleep(lldev->enable_gpio, 0); clk_disable_unprepare(lldev->ext_clk); - - serdev_device_close(hu->serdev); } hu->priv = NULL; diff --git a/drivers/bluetooth/hci_nokia.c b/drivers/bluetooth/hci_nokia.c index 3539fd03f47e..14d159e2042d 100644 --- a/drivers/bluetooth/hci_nokia.c +++ b/drivers/bluetooth/hci_nokia.c @@ -477,8 +477,6 @@ static int nokia_open(struct hci_uart *hu) dev_dbg(dev, "protocol open"); - serdev_device_open(hu->serdev); - pm_runtime_enable(dev); return 0; @@ -513,7 +511,6 @@ static int nokia_close(struct hci_uart *hu) gpiod_set_value(btdev->wakeup_bt, 0); pm_runtime_disable(&btdev->serdev->dev); - serdev_device_close(btdev->serdev); return 0; } diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index f05382b5a65d..51790dd02afb 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -910,7 +910,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate) */ set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout(msecs_to_jiffies(BAUDRATE_SETTLE_TIMEOUT_MS)); - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_RUNNING); return 0; } diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index e0e6461b9200..aa2543b3c286 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -101,14 +101,6 @@ static void hci_uart_write_work(struct work_struct *work) /* ------- Interface to HCI layer ------ */ -/* Initialize device */ -static int hci_uart_open(struct hci_dev *hdev) -{ - BT_DBG("%s %p", hdev->name, hdev); - - return 0; -} - /* Reset device */ static int hci_uart_flush(struct hci_dev *hdev) { @@ -129,6 +121,17 @@ static int hci_uart_flush(struct hci_dev *hdev) return 0; } +/* Initialize device */ +static int hci_uart_open(struct hci_dev *hdev) +{ + BT_DBG("%s %p", hdev->name, hdev); + + /* Undo clearing this from hci_uart_close() */ + hdev->flush = hci_uart_flush; + + return 0; +} + /* Close device */ static int hci_uart_close(struct hci_dev *hdev) { @@ -204,9 +207,8 @@ static int hci_uart_setup(struct hci_dev *hdev) return 0; } - if (skb->len != sizeof(*ver)) { + if (skb->len != sizeof(*ver)) bt_dev_err(hdev, "Event length mismatch for version info"); - } kfree_skb(skb); return 0; @@ -282,10 +284,14 @@ int hci_uart_register_device(struct hci_uart *hu, serdev_device_set_client_ops(hu->serdev, &hci_serdev_client_ops); - err = p->open(hu); + err = serdev_device_open(hu->serdev); if (err) return err; + err = p->open(hu); + if (err) + goto err_open; + hu->proto = p; set_bit(HCI_UART_PROTO_READY, &hu->flags); @@ -302,6 +308,7 @@ int hci_uart_register_device(struct hci_uart *hu, hdev->bus = HCI_UART; hci_set_drvdata(hdev, hu); + INIT_WORK(&hu->init_ready, hci_uart_init_work); INIT_WORK(&hu->write_work, hci_uart_write_work); percpu_init_rwsem(&hu->proto_lock); @@ -351,6 +358,8 @@ err_register: err_alloc: clear_bit(HCI_UART_PROTO_READY, &hu->flags); p->close(hu); +err_open: + serdev_device_close(hu->serdev); return err; } EXPORT_SYMBOL_GPL(hci_uart_register_device); @@ -365,5 +374,6 @@ void hci_uart_unregister_device(struct hci_uart *hu) cancel_work_sync(&hu->write_work); hu->proto->close(hu); + serdev_device_close(hu->serdev); } EXPORT_SYMBOL_GPL(hci_uart_unregister_device); diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h index 66e8c68e4607..00cab2fd7a1b 100644 --- a/drivers/bluetooth/hci_uart.h +++ b/drivers/bluetooth/hci_uart.h @@ -116,6 +116,7 @@ void hci_uart_unregister_device(struct hci_uart *hu); int hci_uart_tx_wakeup(struct hci_uart *hu); int hci_uart_init_ready(struct hci_uart *hu); +void hci_uart_init_work(struct work_struct *work); void hci_uart_set_baudrate(struct hci_uart *hu, unsigned int speed); void hci_uart_set_flow_control(struct hci_uart *hu, bool enable); void hci_uart_set_speeds(struct hci_uart *hu, unsigned int init_speed, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c index 8cfce95c82fc..39cd3a27fe77 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c @@ -107,7 +107,7 @@ static int aq_fw2x_update_link_status(struct aq_hw_s *self) return 0; } -int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) +static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) { int err = 0; u32 h = 0U; diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 9ffc4a8c5fc7..3853296d78c1 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -384,7 +384,7 @@ static int bnx2_register_cnic(struct net_device *dev, struct cnic_ops *ops, struct bnx2 *bp = netdev_priv(dev); struct cnic_eth_dev *cp = &bp->cnic_eth_dev; - if (ops == NULL) + if (!ops) return -EINVAL; if (cp->drv_state & CNIC_DRV_STATE_REGD) @@ -755,13 +755,13 @@ bnx2_alloc_tx_mem(struct bnx2 *bp) struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; txr->tx_buf_ring = kzalloc(SW_TXBD_RING_SIZE, GFP_KERNEL); - if (txr->tx_buf_ring == NULL) + if (!txr->tx_buf_ring) return -ENOMEM; txr->tx_desc_ring = dma_alloc_coherent(&bp->pdev->dev, TXBD_RING_SIZE, &txr->tx_desc_mapping, GFP_KERNEL); - if (txr->tx_desc_ring == NULL) + if (!txr->tx_desc_ring) return -ENOMEM; } return 0; @@ -779,7 +779,7 @@ bnx2_alloc_rx_mem(struct bnx2 *bp) rxr->rx_buf_ring = vzalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring); - if (rxr->rx_buf_ring == NULL) + if (!rxr->rx_buf_ring) return -ENOMEM; for (j = 0; j < bp->rx_max_ring; j++) { @@ -788,7 +788,7 @@ bnx2_alloc_rx_mem(struct bnx2 *bp) RXBD_RING_SIZE, &rxr->rx_desc_mapping[j], GFP_KERNEL); - if (rxr->rx_desc_ring[j] == NULL) + if (!rxr->rx_desc_ring[j]) return -ENOMEM; } @@ -796,7 +796,7 @@ bnx2_alloc_rx_mem(struct bnx2 *bp) if (bp->rx_pg_ring_size) { rxr->rx_pg_ring = vzalloc(SW_RXPG_RING_SIZE * bp->rx_max_pg_ring); - if (rxr->rx_pg_ring == NULL) + if (!rxr->rx_pg_ring) return -ENOMEM; } @@ -807,7 +807,7 @@ bnx2_alloc_rx_mem(struct bnx2 *bp) RXBD_RING_SIZE, &rxr->rx_pg_desc_mapping[j], GFP_KERNEL); - if (rxr->rx_pg_desc_ring[j] == NULL) + if (!rxr->rx_pg_desc_ring[j]) return -ENOMEM; } @@ -845,7 +845,7 @@ bnx2_alloc_stats_blk(struct net_device *dev) sizeof(struct statistics_block); status_blk = dma_zalloc_coherent(&bp->pdev->dev, bp->status_stats_size, &bp->status_blk_mapping, GFP_KERNEL); - if (status_blk == NULL) + if (!status_blk) return -ENOMEM; bp->status_blk = status_blk; @@ -914,7 +914,7 @@ bnx2_alloc_mem(struct bnx2 *bp) BNX2_PAGE_SIZE, &bp->ctx_blk_mapping[i], GFP_KERNEL); - if (bp->ctx_blk[i] == NULL) + if (!bp->ctx_blk[i]) goto alloc_mem_err; } } @@ -2667,7 +2667,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp) u32 val; good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL); - if (good_mbuf == NULL) + if (!good_mbuf) return -ENOMEM; BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS, @@ -3225,7 +3225,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) if (len <= bp->rx_copy_thresh) { skb = netdev_alloc_skb(bp->dev, len + 6); - if (skb == NULL) { + if (!skb) { bnx2_reuse_rx_data(bp, rxr, data, sw_ring_cons, sw_ring_prod); goto next_rx; @@ -3285,7 +3285,7 @@ next_rx: sw_cons = BNX2_NEXT_RX_BD(sw_cons); sw_prod = BNX2_NEXT_RX_BD(sw_prod); - if ((rx_pkt == budget)) + if (rx_pkt == budget) break; /* Refresh hw_cons to see if there is new work */ @@ -4561,7 +4561,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, if (align_start || align_end) { align_buf = kmalloc(len32, GFP_KERNEL); - if (align_buf == NULL) + if (!align_buf) return -ENOMEM; if (align_start) { memcpy(align_buf, start, 4); @@ -4575,7 +4575,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, if (!(bp->flash_info->flags & BNX2_NV_BUFFERED)) { flash_buffer = kmalloc(264, GFP_KERNEL); - if (flash_buffer == NULL) { + if (!flash_buffer) { rc = -ENOMEM; goto nvram_write_end; } @@ -5440,7 +5440,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp) struct bnx2_tx_ring_info *txr = &bnapi->tx_ring; int j; - if (txr->tx_buf_ring == NULL) + if (!txr->tx_buf_ring) continue; for (j = 0; j < BNX2_TX_DESC_CNT; ) { @@ -5448,7 +5448,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp) struct sk_buff *skb = tx_buf->skb; int k, last; - if (skb == NULL) { + if (!skb) { j = BNX2_NEXT_TX_BD(j); continue; } @@ -5485,14 +5485,14 @@ bnx2_free_rx_skbs(struct bnx2 *bp) struct bnx2_rx_ring_info *rxr = &bnapi->rx_ring; int j; - if (rxr->rx_buf_ring == NULL) + if (!rxr->rx_buf_ring) return; for (j = 0; j < bp->rx_max_ring_idx; j++) { struct bnx2_sw_bd *rx_buf = &rxr->rx_buf_ring[j]; u8 *data = rx_buf->data; - if (data == NULL) + if (!data) continue; dma_unmap_single(&bp->pdev->dev, @@ -6826,7 +6826,7 @@ bnx2_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats) { struct bnx2 *bp = netdev_priv(dev); - if (bp->stats_blk == NULL) + if (!bp->stats_blk) return; net_stats->rx_packets = @@ -7217,7 +7217,7 @@ bnx2_get_eeprom_len(struct net_device *dev) { struct bnx2 *bp = netdev_priv(dev); - if (bp->flash_info == NULL) + if (!bp->flash_info) return 0; return (int) bp->flash_size; @@ -7678,7 +7678,7 @@ bnx2_get_ethtool_stats(struct net_device *dev, u32 *temp_stats = (u32 *) bp->temp_stats_blk; u8 *stats_len_arr = NULL; - if (hw_stats == NULL) { + if (!hw_stats) { memset(buf, 0, sizeof(u64) * BNX2_NUM_STATS); return; } @@ -8121,7 +8121,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->temp_stats_blk = kzalloc(sizeof(struct statistics_block), GFP_KERNEL); - if (bp->temp_stats_blk == NULL) { + if (!bp->temp_stats_blk) { rc = -ENOMEM; goto err_out; } diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c index e988caa797cb..20b6e1b3f5e3 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c @@ -620,7 +620,7 @@ static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size, { size_t len = nelem * elem_size; void *s = NULL; - void *p = dma_alloc_coherent(&pdev->dev, len, phys, GFP_KERNEL); + void *p = dma_zalloc_coherent(&pdev->dev, len, phys, GFP_KERNEL); if (!p) return NULL; @@ -633,7 +633,6 @@ static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size, } *(void **)metadata = s; } - memset(p, 0, len); return p; } diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 276f22357f81..7a271feec5e7 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -694,7 +694,7 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size, { size_t len = nelem * elem_size + stat_size; void *s = NULL; - void *p = dma_alloc_coherent(dev, len, phys, GFP_KERNEL); + void *p = dma_zalloc_coherent(dev, len, phys, GFP_KERNEL); if (!p) return NULL; @@ -708,7 +708,6 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size, } if (metadata) *(void **)metadata = s; - memset(p, 0, len); return p; } diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c index dfce5df7538e..3007e1ac1e61 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/sge.c @@ -756,7 +756,7 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t hwsize, * Allocate the hardware ring and PCI DMA bus address space for said. */ size_t hwlen = nelem * hwsize + stat_size; - void *hwring = dma_alloc_coherent(dev, hwlen, busaddrp, GFP_KERNEL); + void *hwring = dma_zalloc_coherent(dev, hwlen, busaddrp, GFP_KERNEL); if (!hwring) return NULL; @@ -776,11 +776,6 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t hwsize, *(void **)swringp = swring; } - /* - * Zero out the hardware ring and return its address as our function - * value. - */ - memset(hwring, 0, hwlen); return hwring; } diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c index bd3f6e4d1341..ff9eb45f67f8 100644 --- a/drivers/net/ethernet/cortina/gemini.c +++ b/drivers/net/ethernet/cortina/gemini.c @@ -539,7 +539,7 @@ static int gmac_setup_txqs(struct net_device *netdev) } if (port->txq_dma_base & ~DMA_Q_BASE_MASK) { - dev_warn(geth->dev, "TX queue base it not aligned\n"); + dev_warn(geth->dev, "TX queue base is not aligned\n"); kfree(skb_tab); return -ENOMEM; } @@ -680,7 +680,7 @@ static int gmac_setup_rxq(struct net_device *netdev) if (!port->rxq_ring) return -ENOMEM; if (port->rxq_dma_base & ~NONTOE_QHDR0_BASE_MASK) { - dev_warn(geth->dev, "RX queue base it not aligned\n"); + dev_warn(geth->dev, "RX queue base is not aligned\n"); return -ENOMEM; } @@ -905,7 +905,7 @@ static int geth_setup_freeq(struct gemini_ethernet *geth) if (!geth->freeq_ring) return -ENOMEM; if (geth->freeq_dma_base & ~DMA_Q_BASE_MASK) { - dev_warn(geth->dev, "queue ring base it not aligned\n"); + dev_warn(geth->dev, "queue ring base is not aligned\n"); goto err_freeq; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index e0bc79ea3d88..85e1d14514fc 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -1648,6 +1648,15 @@ int hns_dsaf_rm_mac_addr( mac_entry->addr); } +static void hns_dsaf_setup_mc_mask(struct dsaf_device *dsaf_dev, + u8 port_num, u8 *mask, u8 *addr) +{ + if (MAC_IS_BROADCAST(addr)) + memset(mask, 0xff, ETH_ALEN); + else + memcpy(mask, dsaf_dev->mac_cb[port_num]->mc_mask, ETH_ALEN); +} + static void hns_dsaf_mc_mask_bit_clear(char *dst, const char *src) { u16 *a = (u16 *)dst; @@ -1676,7 +1685,6 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, struct dsaf_drv_tbl_tcam_key tmp_mac_key; struct dsaf_tbl_tcam_data tcam_data; u8 mc_addr[ETH_ALEN]; - u8 *mc_mask; int mskid; /*chechk mac addr */ @@ -1687,9 +1695,12 @@ int hns_dsaf_add_mac_mc_port(struct dsaf_device *dsaf_dev, } ether_addr_copy(mc_addr, mac_entry->addr); - mc_mask = dsaf_dev->mac_cb[mac_entry->in_port_num]->mc_mask; if (!AE_IS_VER1(dsaf_dev->dsaf_ver)) { + u8 mc_mask[ETH_ALEN]; + /* prepare for key data setting */ + hns_dsaf_setup_mc_mask(dsaf_dev, mac_entry->in_port_num, + mc_mask, mac_entry->addr); hns_dsaf_mc_mask_bit_clear(mc_addr, mc_mask); /* config key mask */ @@ -1844,7 +1855,6 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, struct dsaf_drv_tbl_tcam_key mask_key, tmp_mac_key; struct dsaf_tbl_tcam_data *pmask_key = NULL; u8 mc_addr[ETH_ALEN]; - u8 *mc_mask; if (!(void *)mac_entry) { dev_err(dsaf_dev->dev, @@ -1861,14 +1871,17 @@ int hns_dsaf_del_mac_mc_port(struct dsaf_device *dsaf_dev, /* always mask vlan_id field */ ether_addr_copy(mc_addr, mac_entry->addr); - mc_mask = dsaf_dev->mac_cb[mac_entry->in_port_num]->mc_mask; if (!AE_IS_VER1(dsaf_dev->dsaf_ver)) { + u8 mc_mask[ETH_ALEN]; + /* prepare for key data setting */ + hns_dsaf_setup_mc_mask(dsaf_dev, mac_entry->in_port_num, + mc_mask, mac_entry->addr); hns_dsaf_mc_mask_bit_clear(mc_addr, mc_mask); /* config key mask */ - hns_dsaf_set_mac_key(dsaf_dev, &mask_key, 0x00, 0xff, mc_addr); + hns_dsaf_set_mac_key(dsaf_dev, &mask_key, 0x00, 0xff, mc_mask); mask_key.high.val = le32_to_cpu(mask_key.high.val); mask_key.low.val = le32_to_cpu(mask_key.low.val); diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 45622bffd81a..0319ed9ef8b8 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -141,7 +141,7 @@ void mvpp2_percpu_write_relaxed(struct mvpp2 *priv, int cpu, writel_relaxed(data, priv->swth_base[cpu] + offset); } -u32 mvpp2_percpu_read_relaxed(struct mvpp2 *priv, int cpu, +static u32 mvpp2_percpu_read_relaxed(struct mvpp2 *priv, int cpu, u32 offset) { return readl_relaxed(priv->swth_base[cpu] + offset); diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index 3ef3406ff4cb..10fcc22f4590 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c @@ -614,9 +614,9 @@ int __mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int index_at_dup_port = -1; for (i = MLX4_VLAN_REGULAR; i < MLX4_MAX_VLAN_NUM; i++) { - if ((vlan == (MLX4_VLAN_MASK & be32_to_cpu(table->entries[i])))) + if (vlan == (MLX4_VLAN_MASK & be32_to_cpu(table->entries[i]))) index_at_port = i; - if ((vlan == (MLX4_VLAN_MASK & be32_to_cpu(dup_table->entries[i])))) + if (vlan == (MLX4_VLAN_MASK & be32_to_cpu(dup_table->entries[i]))) index_at_dup_port = i; } /* check that same vlan is not in the tables at different indices */ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c index da3f7f527360..3d187d88cc7c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c @@ -191,7 +191,9 @@ mlxsw_sp_span_entry_bridge_8021q(const struct net_device *br_dev, if (br_vlan_get_info(edev, vid, &vinfo)) return NULL; - if (!(vinfo.flags & BRIDGE_VLAN_INFO_UNTAGGED)) + if (vinfo.flags & BRIDGE_VLAN_INFO_UNTAGGED) + *p_vid = 0; + else *p_vid = vid; return edev; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index 8a15ac49cb5a..e97652c40d13 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1856,7 +1856,7 @@ static int mlxsw_sp_port_obj_del(struct net_device *dev, break; } - mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp); + mlxsw_sp_span_respin_schedule(mlxsw_sp_port->mlxsw_sp); return err; } diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c index 820b226d6ff8..b5b5ff725426 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_cxt.c +++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c @@ -47,6 +47,7 @@ #include "qed_hsi.h" #include "qed_hw.h" #include "qed_init_ops.h" +#include "qed_rdma.h" #include "qed_reg_addr.h" #include "qed_sriov.h" @@ -426,7 +427,7 @@ static void qed_cxt_set_srq_count(struct qed_hwfn *p_hwfn, u32 num_srqs) p_mgr->srq_count = num_srqs; } -static u32 qed_cxt_get_srq_count(struct qed_hwfn *p_hwfn) +u32 qed_cxt_get_srq_count(struct qed_hwfn *p_hwfn) { struct qed_cxt_mngr *p_mgr = p_hwfn->p_cxt_mngr; @@ -936,14 +937,13 @@ static int qed_cxt_src_t2_alloc(struct qed_hwfn *p_hwfn) u32 size = min_t(u32, total_size, psz); void **p_virt = &p_mngr->t2[i].p_virt; - *p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, - size, - &p_mngr->t2[i].p_phys, GFP_KERNEL); + *p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev, + size, &p_mngr->t2[i].p_phys, + GFP_KERNEL); if (!p_mngr->t2[i].p_virt) { rc = -ENOMEM; goto t2_fail; } - memset(*p_virt, 0, size); p_mngr->t2[i].size = size; total_size -= size; } @@ -2071,7 +2071,7 @@ static void qed_rdma_set_pf_params(struct qed_hwfn *p_hwfn, u32 num_cons, num_qps, num_srqs; enum protocol_type proto; - num_srqs = min_t(u32, 32 * 1024, p_params->num_srqs); + num_srqs = min_t(u32, QED_RDMA_MAX_SRQS, p_params->num_srqs); if (p_hwfn->mcp_info->func_info.protocol == QED_PCI_ETH_RDMA) { DP_NOTICE(p_hwfn, diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.h b/drivers/net/ethernet/qlogic/qed/qed_cxt.h index a4e95869889f..758a8b4c0de8 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_cxt.h +++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.h @@ -235,6 +235,7 @@ u32 qed_cxt_get_proto_tid_count(struct qed_hwfn *p_hwfn, enum protocol_type type); u32 qed_cxt_get_proto_cid_start(struct qed_hwfn *p_hwfn, enum protocol_type type); +u32 qed_cxt_get_srq_count(struct qed_hwfn *p_hwfn); int qed_cxt_free_proto_ilt(struct qed_hwfn *p_hwfn, enum protocol_type proto); #define QED_CTX_WORKING_MEM 0 diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h index 8e1e6e1eb40e..b9704be53537 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h +++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h @@ -9725,6 +9725,8 @@ enum iwarp_eqe_async_opcode { IWARP_EVENT_TYPE_ASYNC_EXCEPTION_DETECTED, IWARP_EVENT_TYPE_ASYNC_QP_IN_ERROR_STATE, IWARP_EVENT_TYPE_ASYNC_CQ_OVERFLOW, + IWARP_EVENT_TYPE_ASYNC_SRQ_EMPTY, + IWARP_EVENT_TYPE_ASYNC_SRQ_LIMIT, MAX_IWARP_EQE_ASYNC_OPCODE }; @@ -11996,6 +11998,7 @@ struct public_port { #define EEE_REMOTE_TW_RX_MASK 0xffff0000 #define EEE_REMOTE_TW_RX_OFFSET 16 + u32 reserved1; u32 oem_cfg_port; #define OEM_CFG_CHANNEL_TYPE_MASK 0x00000003 #define OEM_CFG_CHANNEL_TYPE_OFFSET 0 diff --git a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c index 2a2b1018ed1d..474e6cff5b97 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_iwarp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_iwarp.c @@ -271,6 +271,8 @@ int qed_iwarp_create_qp(struct qed_hwfn *p_hwfn, p_ramrod->sq_num_pages = qp->sq_num_pages; p_ramrod->rq_num_pages = qp->rq_num_pages; + p_ramrod->srq_id.srq_idx = cpu_to_le16(qp->srq_id); + p_ramrod->srq_id.opaque_fid = cpu_to_le16(p_hwfn->hw_info.opaque_fid); p_ramrod->qp_handle_for_cqe.hi = cpu_to_le32(qp->qp_handle.hi); p_ramrod->qp_handle_for_cqe.lo = cpu_to_le32(qp->qp_handle.lo); @@ -3004,8 +3006,11 @@ static int qed_iwarp_async_event(struct qed_hwfn *p_hwfn, union event_ring_data *data, u8 fw_return_code) { + struct qed_rdma_events events = p_hwfn->p_rdma_info->events; struct regpair *fw_handle = &data->rdma_data.async_handle; struct qed_iwarp_ep *ep = NULL; + u16 srq_offset; + u16 srq_id; u16 cid; ep = (struct qed_iwarp_ep *)(uintptr_t)HILO_64(fw_handle->hi, @@ -3067,6 +3072,24 @@ static int qed_iwarp_async_event(struct qed_hwfn *p_hwfn, qed_iwarp_cid_cleaned(p_hwfn, cid); break; + case IWARP_EVENT_TYPE_ASYNC_SRQ_EMPTY: + DP_NOTICE(p_hwfn, "IWARP_EVENT_TYPE_ASYNC_SRQ_EMPTY\n"); + srq_offset = p_hwfn->p_rdma_info->srq_id_offset; + /* FW assigns value that is no greater than u16 */ + srq_id = ((u16)le32_to_cpu(fw_handle->lo)) - srq_offset; + events.affiliated_event(events.context, + QED_IWARP_EVENT_SRQ_EMPTY, + &srq_id); + break; + case IWARP_EVENT_TYPE_ASYNC_SRQ_LIMIT: + DP_NOTICE(p_hwfn, "IWARP_EVENT_TYPE_ASYNC_SRQ_LIMIT\n"); + srq_offset = p_hwfn->p_rdma_info->srq_id_offset; + /* FW assigns value that is no greater than u16 */ + srq_id = ((u16)le32_to_cpu(fw_handle->lo)) - srq_offset; + events.affiliated_event(events.context, + QED_IWARP_EVENT_SRQ_LIMIT, + &srq_id); + break; case IWARP_EVENT_TYPE_ASYNC_CQ_OVERFLOW: DP_NOTICE(p_hwfn, "IWARP_EVENT_TYPE_ASYNC_CQ_OVERFLOW\n"); diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 68c4399ffd50..b04d57ca5176 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -64,6 +64,7 @@ #define QED_ROCE_QPS (8192) #define QED_ROCE_DPIS (8) +#define QED_RDMA_SRQS QED_ROCE_QPS static char version[] = "QLogic FastLinQ 4xxxx Core Module qed " DRV_MODULE_VERSION "\n"; @@ -922,6 +923,7 @@ static void qed_update_pf_params(struct qed_dev *cdev, if (IS_ENABLED(CONFIG_QED_RDMA)) { params->rdma_pf_params.num_qps = QED_ROCE_QPS; params->rdma_pf_params.min_dpis = QED_ROCE_DPIS; + params->rdma_pf_params.num_srqs = QED_RDMA_SRQS; /* divide by 3 the MRs to avoid MF ILT overflow */ params->rdma_pf_params.gl_pi = QED_ROCE_PROTOCOL_INDEX; } diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 2612e3e458d9..6f9927d1a501 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -1514,9 +1514,10 @@ void qed_mcp_read_ufp_config(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) } qed_mcp_get_shmem_func(p_hwfn, p_ptt, &shmem_info, MCP_PF_ID(p_hwfn)); - val = (port_cfg & OEM_CFG_FUNC_TC_MASK) >> OEM_CFG_FUNC_TC_OFFSET; + val = (shmem_info.oem_cfg_func & OEM_CFG_FUNC_TC_MASK) >> + OEM_CFG_FUNC_TC_OFFSET; p_hwfn->ufp_info.tc = (u8)val; - val = (port_cfg & OEM_CFG_FUNC_HOST_PRI_CTRL_MASK) >> + val = (shmem_info.oem_cfg_func & OEM_CFG_FUNC_HOST_PRI_CTRL_MASK) >> OEM_CFG_FUNC_HOST_PRI_CTRL_OFFSET; if (val == OEM_CFG_FUNC_HOST_PRI_CTRL_VNIC) { p_hwfn->ufp_info.pri_type = QED_UFP_PRI_VNIC; diff --git a/drivers/net/ethernet/qlogic/qed/qed_rdma.c b/drivers/net/ethernet/qlogic/qed/qed_rdma.c index a411f9c702a1..b8705107a93a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_rdma.c +++ b/drivers/net/ethernet/qlogic/qed/qed_rdma.c @@ -259,15 +259,29 @@ static int qed_rdma_alloc(struct qed_hwfn *p_hwfn, goto free_cid_map; } + /* Allocate bitmap for srqs */ + p_rdma_info->num_srqs = qed_cxt_get_srq_count(p_hwfn); + rc = qed_rdma_bmap_alloc(p_hwfn, &p_rdma_info->srq_map, + p_rdma_info->num_srqs, "SRQ"); + if (rc) { + DP_VERBOSE(p_hwfn, QED_MSG_RDMA, + "Failed to allocate srq bitmap, rc = %d\n", rc); + goto free_real_cid_map; + } + if (QED_IS_IWARP_PERSONALITY(p_hwfn)) rc = qed_iwarp_alloc(p_hwfn); if (rc) - goto free_cid_map; + goto free_srq_map; DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "Allocation successful\n"); return 0; +free_srq_map: + kfree(p_rdma_info->srq_map.bitmap); +free_real_cid_map: + kfree(p_rdma_info->real_cid_map.bitmap); free_cid_map: kfree(p_rdma_info->cid_map.bitmap); free_tid_map: @@ -351,6 +365,8 @@ static void qed_rdma_resc_free(struct qed_hwfn *p_hwfn) qed_rdma_bmap_free(p_hwfn, &p_hwfn->p_rdma_info->cq_map, 1); qed_rdma_bmap_free(p_hwfn, &p_hwfn->p_rdma_info->toggle_bits, 0); qed_rdma_bmap_free(p_hwfn, &p_hwfn->p_rdma_info->tid_map, 1); + qed_rdma_bmap_free(p_hwfn, &p_hwfn->p_rdma_info->srq_map, 1); + qed_rdma_bmap_free(p_hwfn, &p_hwfn->p_rdma_info->real_cid_map, 1); kfree(p_rdma_info->port); kfree(p_rdma_info->dev); @@ -431,6 +447,12 @@ static void qed_rdma_init_devinfo(struct qed_hwfn *p_hwfn, if (cdev->rdma_max_sge) dev->max_sge = min_t(u32, cdev->rdma_max_sge, dev->max_sge); + dev->max_srq_sge = QED_RDMA_MAX_SGE_PER_SRQ_WQE; + if (p_hwfn->cdev->rdma_max_srq_sge) { + dev->max_srq_sge = min_t(u32, + p_hwfn->cdev->rdma_max_srq_sge, + dev->max_srq_sge); + } dev->max_inline = ROCE_REQ_MAX_INLINE_DATA_SIZE; dev->max_inline = (cdev->rdma_max_inline) ? @@ -474,6 +496,8 @@ static void qed_rdma_init_devinfo(struct qed_hwfn *p_hwfn, dev->max_mr_mw_fmr_size = dev->max_mr_mw_fmr_pbl * PAGE_SIZE; dev->max_pkey = QED_RDMA_MAX_P_KEY; + dev->max_srq = p_hwfn->p_rdma_info->num_srqs; + dev->max_srq_wr = QED_RDMA_MAX_SRQ_WQE_ELEM; dev->max_qp_resp_rd_atomic_resc = RDMA_RING_PAGE_SIZE / (RDMA_RESP_RD_ATOMIC_ELM_SIZE * 2); dev->max_qp_req_rd_atomic_resc = RDMA_RING_PAGE_SIZE / @@ -1628,6 +1652,155 @@ static void *qed_rdma_get_rdma_ctx(struct qed_dev *cdev) return QED_LEADING_HWFN(cdev); } +static int qed_rdma_modify_srq(void *rdma_cxt, + struct qed_rdma_modify_srq_in_params *in_params) +{ + struct rdma_srq_modify_ramrod_data *p_ramrod; + struct qed_sp_init_data init_data = {}; + struct qed_hwfn *p_hwfn = rdma_cxt; + struct qed_spq_entry *p_ent; + u16 opaque_fid; + int rc; + + init_data.opaque_fid = p_hwfn->hw_info.opaque_fid; + init_data.comp_mode = QED_SPQ_MODE_EBLOCK; + + rc = qed_sp_init_request(p_hwfn, &p_ent, + RDMA_RAMROD_MODIFY_SRQ, + p_hwfn->p_rdma_info->proto, &init_data); + if (rc) + return rc; + + p_ramrod = &p_ent->ramrod.rdma_modify_srq; + p_ramrod->srq_id.srq_idx = cpu_to_le16(in_params->srq_id); + opaque_fid = p_hwfn->hw_info.opaque_fid; + p_ramrod->srq_id.opaque_fid = cpu_to_le16(opaque_fid); + p_ramrod->wqe_limit = cpu_to_le32(in_params->wqe_limit); + + rc = qed_spq_post(p_hwfn, p_ent, NULL); + if (rc) + return rc; + + DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "modified SRQ id = %x", + in_params->srq_id); + + return rc; +} + +static int +qed_rdma_destroy_srq(void *rdma_cxt, + struct qed_rdma_destroy_srq_in_params *in_params) +{ + struct rdma_srq_destroy_ramrod_data *p_ramrod; + struct qed_sp_init_data init_data = {}; + struct qed_hwfn *p_hwfn = rdma_cxt; + struct qed_spq_entry *p_ent; + struct qed_bmap *bmap; + u16 opaque_fid; + int rc; + + opaque_fid = p_hwfn->hw_info.opaque_fid; + + init_data.opaque_fid = opaque_fid; + init_data.comp_mode = QED_SPQ_MODE_EBLOCK; + + rc = qed_sp_init_request(p_hwfn, &p_ent, + RDMA_RAMROD_DESTROY_SRQ, + p_hwfn->p_rdma_info->proto, &init_data); + if (rc) + return rc; + + p_ramrod = &p_ent->ramrod.rdma_destroy_srq; + p_ramrod->srq_id.srq_idx = cpu_to_le16(in_params->srq_id); + p_ramrod->srq_id.opaque_fid = cpu_to_le16(opaque_fid); + + rc = qed_spq_post(p_hwfn, p_ent, NULL); + if (rc) + return rc; + + bmap = &p_hwfn->p_rdma_info->srq_map; + + spin_lock_bh(&p_hwfn->p_rdma_info->lock); + qed_bmap_release_id(p_hwfn, bmap, in_params->srq_id); + spin_unlock_bh(&p_hwfn->p_rdma_info->lock); + + DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "SRQ destroyed Id = %x", + in_params->srq_id); + + return rc; +} + +static int +qed_rdma_create_srq(void *rdma_cxt, + struct qed_rdma_create_srq_in_params *in_params, + struct qed_rdma_create_srq_out_params *out_params) +{ + struct rdma_srq_create_ramrod_data *p_ramrod; + struct qed_sp_init_data init_data = {}; + struct qed_hwfn *p_hwfn = rdma_cxt; + enum qed_cxt_elem_type elem_type; + struct qed_spq_entry *p_ent; + u16 opaque_fid, srq_id; + struct qed_bmap *bmap; + u32 returned_id; + int rc; + + bmap = &p_hwfn->p_rdma_info->srq_map; + spin_lock_bh(&p_hwfn->p_rdma_info->lock); + rc = qed_rdma_bmap_alloc_id(p_hwfn, bmap, &returned_id); + spin_unlock_bh(&p_hwfn->p_rdma_info->lock); + + if (rc) { + DP_NOTICE(p_hwfn, "failed to allocate srq id\n"); + return rc; + } + + elem_type = QED_ELEM_SRQ; + rc = qed_cxt_dynamic_ilt_alloc(p_hwfn, elem_type, returned_id); + if (rc) + goto err; + /* returned id is no greater than u16 */ + srq_id = (u16)returned_id; + opaque_fid = p_hwfn->hw_info.opaque_fid; + + opaque_fid = p_hwfn->hw_info.opaque_fid; + init_data.opaque_fid = opaque_fid; + init_data.comp_mode = QED_SPQ_MODE_EBLOCK; + + rc = qed_sp_init_request(p_hwfn, &p_ent, + RDMA_RAMROD_CREATE_SRQ, + p_hwfn->p_rdma_info->proto, &init_data); + if (rc) + goto err; + + p_ramrod = &p_ent->ramrod.rdma_create_srq; + DMA_REGPAIR_LE(p_ramrod->pbl_base_addr, in_params->pbl_base_addr); + p_ramrod->pages_in_srq_pbl = cpu_to_le16(in_params->num_pages); + p_ramrod->pd_id = cpu_to_le16(in_params->pd_id); + p_ramrod->srq_id.srq_idx = cpu_to_le16(srq_id); + p_ramrod->srq_id.opaque_fid = cpu_to_le16(opaque_fid); + p_ramrod->page_size = cpu_to_le16(in_params->page_size); + DMA_REGPAIR_LE(p_ramrod->producers_addr, in_params->prod_pair_addr); + + rc = qed_spq_post(p_hwfn, p_ent, NULL); + if (rc) + goto err; + + out_params->srq_id = srq_id; + + DP_VERBOSE(p_hwfn, QED_MSG_RDMA, + "SRQ created Id = %x\n", out_params->srq_id); + + return rc; + +err: + spin_lock_bh(&p_hwfn->p_rdma_info->lock); + qed_bmap_release_id(p_hwfn, bmap, returned_id); + spin_unlock_bh(&p_hwfn->p_rdma_info->lock); + + return rc; +} + bool qed_rdma_allocated_qps(struct qed_hwfn *p_hwfn) { bool result; @@ -1773,6 +1946,9 @@ static const struct qed_rdma_ops qed_rdma_ops_pass = { .rdma_free_tid = &qed_rdma_free_tid, .rdma_register_tid = &qed_rdma_register_tid, .rdma_deregister_tid = &qed_rdma_deregister_tid, + .rdma_create_srq = &qed_rdma_create_srq, + .rdma_modify_srq = &qed_rdma_modify_srq, + .rdma_destroy_srq = &qed_rdma_destroy_srq, .ll2_acquire_connection = &qed_ll2_acquire_connection, .ll2_establish_connection = &qed_ll2_establish_connection, .ll2_terminate_connection = &qed_ll2_terminate_connection, diff --git a/drivers/net/ethernet/qlogic/qed/qed_rdma.h b/drivers/net/ethernet/qlogic/qed/qed_rdma.h index 18ec9cbd84f5..6f722ee8ee94 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_rdma.h +++ b/drivers/net/ethernet/qlogic/qed/qed_rdma.h @@ -96,6 +96,8 @@ struct qed_rdma_info { u8 num_cnqs; u32 num_qps; u32 num_mrs; + u32 num_srqs; + u16 srq_id_offset; u16 queue_zone_base; u16 max_queue_zones; enum protocol_type proto; diff --git a/drivers/net/ethernet/qlogic/qed/qed_roce.c b/drivers/net/ethernet/qlogic/qed/qed_roce.c index 6acfd43c1a4f..ee57fcdc698d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_roce.c +++ b/drivers/net/ethernet/qlogic/qed/qed_roce.c @@ -65,6 +65,8 @@ qed_roce_async_event(struct qed_hwfn *p_hwfn, u8 fw_event_code, u16 echo, union event_ring_data *data, u8 fw_return_code) { + struct qed_rdma_events events = p_hwfn->p_rdma_info->events; + if (fw_event_code == ROCE_ASYNC_EVENT_DESTROY_QP_DONE) { u16 icid = (u16)le32_to_cpu(data->rdma_data.rdma_destroy_qp_data.cid); @@ -75,11 +77,18 @@ qed_roce_async_event(struct qed_hwfn *p_hwfn, */ qed_roce_free_real_icid(p_hwfn, icid); } else { - struct qed_rdma_events *events = &p_hwfn->p_rdma_info->events; + if (fw_event_code == ROCE_ASYNC_EVENT_SRQ_EMPTY || + fw_event_code == ROCE_ASYNC_EVENT_SRQ_LIMIT) { + u16 srq_id = (u16)data->rdma_data.async_handle.lo; + + events.affiliated_event(events.context, fw_event_code, + &srq_id); + } else { + union rdma_eqe_data rdata = data->rdma_data; - events->affiliated_event(p_hwfn->p_rdma_info->events.context, - fw_event_code, - (void *)&data->rdma_data.async_handle); + events.affiliated_event(events.context, fw_event_code, + (void *)&rdata.async_handle); + } } return 0; diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index d9cadfb1bc4a..e9007b613f17 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -460,6 +460,17 @@ static u32 sh_eth_tsu_read(struct sh_eth_private *mdp, int enum_index) return ioread32(mdp->tsu_addr + offset); } +static void sh_eth_soft_swap(char *src, int len) +{ +#ifdef __LITTLE_ENDIAN + u32 *p = (u32 *)src; + u32 *maxp = p + DIV_ROUND_UP(len, sizeof(u32)); + + for (; p < maxp; p++) + *p = swab32(*p); +#endif +} + static void sh_eth_select_mii(struct net_device *ndev) { struct sh_eth_private *mdp = netdev_priv(ndev); diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 5dee19b61aee..726c55a82dd7 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -560,18 +560,6 @@ struct sh_eth_private { unsigned wol_enabled:1; }; -static inline void sh_eth_soft_swap(char *src, int len) -{ -#ifdef __LITTLE_ENDIAN__ - u32 *p = (u32 *)src; - u32 *maxp; - maxp = p + ((len + sizeof(u32) - 1) / sizeof(u32)); - - for (; p < maxp; p++) - *p = swab32(*p); -#endif -} - static inline void *sh_eth_tsu_get_offset(struct sh_eth_private *mdp, int enum_index) { diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index a679cb729d1d..78fd0f8b8e81 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -346,6 +346,8 @@ struct dma_features { /* TX and RX number of queues */ unsigned int number_rx_queues; unsigned int number_tx_queues; + /* PPS output */ + unsigned int pps_out_num; /* Alternate (enhanced) DESC mode */ unsigned int enh_desc; /* TX and RX FIFO sizes */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h index 6330a55953df..eb013d54025a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h @@ -187,6 +187,7 @@ enum power_event { #define GMAC_HW_RXFIFOSIZE GENMASK(4, 0) /* MAC HW features2 bitmap */ +#define GMAC_HW_FEAT_PPSOUTNUM GENMASK(26, 24) #define GMAC_HW_FEAT_TXCHCNT GENMASK(21, 18) #define GMAC_HW_FEAT_RXCHCNT GENMASK(15, 12) #define GMAC_HW_FEAT_TXQCNT GENMASK(9, 6) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index a7121a7d9391..7e5d5db0d516 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -796,6 +796,7 @@ const struct stmmac_ops dwmac510_ops = { .safety_feat_irq_status = dwmac5_safety_feat_irq_status, .safety_feat_dump = dwmac5_safety_feat_dump, .rxp_config = dwmac5_rxp_config, + .flex_pps_config = dwmac5_flex_pps_config, }; int dwmac4_setup(struct stmmac_priv *priv) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c index bf8e5a16f11c..d37f17ca62fe 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c @@ -373,6 +373,8 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr, ((hw_cap & GMAC_HW_FEAT_RXQCNT) >> 0) + 1; dma_cap->number_tx_queues = ((hw_cap & GMAC_HW_FEAT_TXQCNT) >> 6) + 1; + /* PPS output */ + dma_cap->pps_out_num = (hw_cap & GMAC_HW_FEAT_PPSOUTNUM) >> 24; /* IEEE 1588-2002 */ dma_cap->time_stamp = 0; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c index b2becb80a697..3f4f3132e16b 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac5.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac5.c @@ -8,6 +8,7 @@ #include "dwmac4.h" #include "dwmac5.h" #include "stmmac.h" +#include "stmmac_ptp.h" struct dwmac5_error_desc { bool valid; @@ -494,3 +495,57 @@ re_enable: writel(old_val, ioaddr + GMAC_CONFIG); return ret; } + +int dwmac5_flex_pps_config(void __iomem *ioaddr, int index, + struct stmmac_pps_cfg *cfg, bool enable, + u32 sub_second_inc, u32 systime_flags) +{ + u32 tnsec = readl(ioaddr + MAC_PPSx_TARGET_TIME_NSEC(index)); + u32 val = readl(ioaddr + MAC_PPS_CONTROL); + u64 period; + + if (!cfg->available) + return -EINVAL; + if (tnsec & TRGTBUSY0) + return -EBUSY; + if (!sub_second_inc || !systime_flags) + return -EINVAL; + + val &= ~PPSx_MASK(index); + + if (!enable) { + val |= PPSCMDx(index, 0x5); + writel(val, ioaddr + MAC_PPS_CONTROL); + return 0; + } + + val |= PPSCMDx(index, 0x2); + val |= TRGTMODSELx(index, 0x2); + val |= PPSEN0; + + writel(cfg->start.tv_sec, ioaddr + MAC_PPSx_TARGET_TIME_SEC(index)); + + if (!(systime_flags & PTP_TCR_TSCTRLSSR)) + cfg->start.tv_nsec = (cfg->start.tv_nsec * 1000) / 465; + writel(cfg->start.tv_nsec, ioaddr + MAC_PPSx_TARGET_TIME_NSEC(index)); + + period = cfg->period.tv_sec * 1000000000; + period += cfg->period.tv_nsec; + + do_div(period, sub_second_inc); + + if (period <= 1) + return -EINVAL; + + writel(period - 1, ioaddr + MAC_PPSx_INTERVAL(index)); + + period >>= 1; + if (period <= 1) + return -EINVAL; + + writel(period - 1, ioaddr + MAC_PPSx_WIDTH(index)); + + /* Finally, activate it */ + writel(val, ioaddr + MAC_PPS_CONTROL); + return 0; +} diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac5.h b/drivers/net/ethernet/stmicro/stmmac/dwmac5.h index cc810aff7100..775db776b3cc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac5.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac5.h @@ -11,6 +11,25 @@ #define PRTYEN BIT(1) #define TMOUTEN BIT(0) +#define MAC_PPS_CONTROL 0x00000b70 +#define PPS_MAXIDX(x) ((((x) + 1) * 8) - 1) +#define PPS_MINIDX(x) ((x) * 8) +#define PPSx_MASK(x) GENMASK(PPS_MAXIDX(x), PPS_MINIDX(x)) +#define MCGRENx(x) BIT(PPS_MAXIDX(x)) +#define TRGTMODSELx(x, val) \ + GENMASK(PPS_MAXIDX(x) - 1, PPS_MAXIDX(x) - 2) & \ + ((val) << (PPS_MAXIDX(x) - 2)) +#define PPSCMDx(x, val) \ + GENMASK(PPS_MINIDX(x) + 3, PPS_MINIDX(x)) & \ + ((val) << PPS_MINIDX(x)) +#define PPSEN0 BIT(4) +#define MAC_PPSx_TARGET_TIME_SEC(x) (0x00000b80 + ((x) * 0x10)) +#define MAC_PPSx_TARGET_TIME_NSEC(x) (0x00000b84 + ((x) * 0x10)) +#define TRGTBUSY0 BIT(31) +#define TTSL0 GENMASK(30, 0) +#define MAC_PPSx_INTERVAL(x) (0x00000b88 + ((x) * 0x10)) +#define MAC_PPSx_WIDTH(x) (0x00000b8c + ((x) * 0x10)) + #define MTL_RXP_CONTROL_STATUS 0x00000ca0 #define RXPI BIT(31) #define NPE GENMASK(23, 16) @@ -61,5 +80,8 @@ int dwmac5_safety_feat_dump(struct stmmac_safety_stats *stats, int index, unsigned long *count, const char **desc); int dwmac5_rxp_config(void __iomem *ioaddr, struct stmmac_tc_entry *entries, unsigned int count); +int dwmac5_flex_pps_config(void __iomem *ioaddr, int index, + struct stmmac_pps_cfg *cfg, bool enable, + u32 sub_second_inc, u32 systime_flags); #endif /* __DWMAC5_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index f499a7fad6f0..e44e7b26ce82 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -241,6 +241,7 @@ struct net_device; struct rgmii_adv; struct stmmac_safety_stats; struct stmmac_tc_entry; +struct stmmac_pps_cfg; /* Helpers to program the MAC core */ struct stmmac_ops { @@ -313,6 +314,10 @@ struct stmmac_ops { /* Flexible RX Parser */ int (*rxp_config)(void __iomem *ioaddr, struct stmmac_tc_entry *entries, unsigned int count); + /* Flexible PPS */ + int (*flex_pps_config)(void __iomem *ioaddr, int index, + struct stmmac_pps_cfg *cfg, bool enable, + u32 sub_second_inc, u32 systime_flags); }; #define stmmac_core_init(__priv, __args...) \ @@ -379,6 +384,8 @@ struct stmmac_ops { stmmac_do_callback(__priv, mac, safety_feat_dump, __args) #define stmmac_rxp_config(__priv, __args...) \ stmmac_do_callback(__priv, mac, rxp_config, __args) +#define stmmac_flex_pps_config(__priv, __args...) \ + stmmac_do_callback(__priv, mac, flex_pps_config, __args) /* PTP and HW Timer helpers */ struct stmmac_hwtimestamp { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index fbfe5dcefa87..025efbf6145c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -100,6 +100,13 @@ struct stmmac_tc_entry { } __packed val; }; +#define STMMAC_PPS_MAX 4 +struct stmmac_pps_cfg { + bool available; + struct timespec64 start; + struct timespec64 period; +}; + struct stmmac_priv { /* Frequently used values are kept adjacent for cache effect */ u32 tx_count_frames; @@ -160,6 +167,8 @@ struct stmmac_priv { struct ptp_clock *ptp_clock; struct ptp_clock_info ptp_clock_ops; unsigned int default_addend; + u32 sub_second_inc; + u32 systime_flags; u32 adv_ts; int use_riwt; int irq_wake; @@ -181,6 +190,9 @@ struct stmmac_priv { unsigned int tc_entries_max; unsigned int tc_off_max; struct stmmac_tc_entry *tc_entries; + + /* Pulse Per Second output */ + struct stmmac_pps_cfg pps[STMMAC_PPS_MAX]; }; enum stmmac_state { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 77af85c981db..11fb7c777d89 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -721,6 +721,10 @@ static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) priv->plat->has_gmac4, &sec_inc); temp = div_u64(1000000000ULL, sec_inc); + /* Store sub second increment and flags for later use */ + priv->sub_second_inc = sec_inc; + priv->systime_flags = value; + /* calculate default added value: * formula is : * addend = (2^32)/freq_div_ratio; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c index 7d3a5c7f5db6..0cb0e39a2be9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c @@ -140,17 +140,43 @@ static int stmmac_set_time(struct ptp_clock_info *ptp, static int stmmac_enable(struct ptp_clock_info *ptp, struct ptp_clock_request *rq, int on) { - return -EOPNOTSUPP; + struct stmmac_priv *priv = + container_of(ptp, struct stmmac_priv, ptp_clock_ops); + struct stmmac_pps_cfg *cfg; + int ret = -EOPNOTSUPP; + unsigned long flags; + + switch (rq->type) { + case PTP_CLK_REQ_PEROUT: + cfg = &priv->pps[rq->perout.index]; + + cfg->start.tv_sec = rq->perout.start.sec; + cfg->start.tv_nsec = rq->perout.start.nsec; + cfg->period.tv_sec = rq->perout.period.sec; + cfg->period.tv_nsec = rq->perout.period.nsec; + + spin_lock_irqsave(&priv->ptp_lock, flags); + ret = stmmac_flex_pps_config(priv, priv->ioaddr, + rq->perout.index, cfg, on, + priv->sub_second_inc, + priv->systime_flags); + spin_unlock_irqrestore(&priv->ptp_lock, flags); + break; + default: + break; + } + + return ret; } /* structure describing a PTP hardware clock */ -static const struct ptp_clock_info stmmac_ptp_clock_ops = { +static struct ptp_clock_info stmmac_ptp_clock_ops = { .owner = THIS_MODULE, .name = "stmmac_ptp_clock", .max_adj = 62500000, .n_alarm = 0, .n_ext_ts = 0, - .n_per_out = 0, + .n_per_out = 0, /* will be overwritten in stmmac_ptp_register */ .n_pins = 0, .pps = 0, .adjfreq = stmmac_adjust_freq, @@ -168,6 +194,16 @@ static const struct ptp_clock_info stmmac_ptp_clock_ops = { */ void stmmac_ptp_register(struct stmmac_priv *priv) { + int i; + + for (i = 0; i < priv->dma_cap.pps_out_num; i++) { + if (i >= STMMAC_PPS_MAX) + break; + priv->pps[i].available = true; + } + + stmmac_ptp_clock_ops.n_per_out = priv->dma_cap.pps_out_num; + spin_lock_init(&priv->ptp_lock); priv->ptp_clock_ops = stmmac_ptp_clock_ops; diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c index 8b508e2cf29b..83f7420ddea5 100644 --- a/drivers/net/net_failover.c +++ b/drivers/net/net_failover.c @@ -380,7 +380,8 @@ static rx_handler_result_t net_failover_handle_frame(struct sk_buff **pskb) static void net_failover_compute_features(struct net_device *dev) { - u32 vlan_features = FAILOVER_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL; + netdev_features_t vlan_features = FAILOVER_VLAN_FEATURES & + NETIF_F_ALL_FOR_ALL; netdev_features_t enc_features = FAILOVER_ENC_FEATURES; unsigned short max_hard_header_len = ETH_HLEN; unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE | diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 267dcc929f6c..8863fa023500 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1004,7 +1004,8 @@ static void team_port_disable(struct team *team, static void __team_compute_features(struct team *team) { struct team_port *port; - u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL; + netdev_features_t vlan_features = TEAM_VLAN_FEATURES & + NETIF_F_ALL_FOR_ALL; netdev_features_t enc_features = TEAM_ENC_FEATURES; unsigned short max_hard_header_len = ETH_HLEN; unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE | diff --git a/drivers/net/tun.c b/drivers/net/tun.c index c94fffee5ea9..067fc9e7e3ed 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -81,6 +81,9 @@ #include <linux/uaccess.h> #include <linux/proc_fs.h> +static void tun_default_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd); + /* Uncomment to enable debugging */ /* #define TUN_DEBUG 1 */ @@ -242,6 +245,7 @@ struct tun_struct { struct bpf_prog __rcu *xdp_prog; struct tun_prog __rcu *steering_prog; struct tun_prog __rcu *filter_prog; + struct ethtool_link_ksettings link_ksettings; }; struct veth { @@ -2295,6 +2299,7 @@ static void tun_setup(struct net_device *dev) tun->owner = INVALID_UID; tun->group = INVALID_GID; + tun_default_link_ksettings(dev, &tun->link_ksettings); dev->ethtool_ops = &tun_ethtool_ops; dev->needs_free_netdev = true; @@ -3326,8 +3331,8 @@ static struct miscdevice tun_miscdev = { /* ethtool interface */ -static int tun_get_link_ksettings(struct net_device *dev, - struct ethtool_link_ksettings *cmd) +static void tun_default_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) { ethtool_link_ksettings_zero_link_mode(cmd, supported); ethtool_link_ksettings_zero_link_mode(cmd, advertising); @@ -3336,6 +3341,23 @@ static int tun_get_link_ksettings(struct net_device *dev, cmd->base.port = PORT_TP; cmd->base.phy_address = 0; cmd->base.autoneg = AUTONEG_DISABLE; +} + +static int tun_get_link_ksettings(struct net_device *dev, + struct ethtool_link_ksettings *cmd) +{ + struct tun_struct *tun = netdev_priv(dev); + + memcpy(cmd, &tun->link_ksettings, sizeof(*cmd)); + return 0; +} + +static int tun_set_link_ksettings(struct net_device *dev, + const struct ethtool_link_ksettings *cmd) +{ + struct tun_struct *tun = netdev_priv(dev); + + memcpy(&tun->link_ksettings, cmd, sizeof(*cmd)); return 0; } @@ -3406,6 +3428,7 @@ static const struct ethtool_ops tun_ethtool_ops = { .get_coalesce = tun_get_coalesce, .set_coalesce = tun_set_coalesce, .get_link_ksettings = tun_get_link_ksettings, + .set_link_ksettings = tun_set_link_ksettings, }; static int tun_queue_resize(struct tun_struct *tun) diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c index 33df76405b86..4205dfd19da3 100644 --- a/drivers/net/wan/fsl_ucc_hdlc.c +++ b/drivers/net/wan/fsl_ucc_hdlc.c @@ -270,10 +270,10 @@ static int uhdlc_init(struct ucc_hdlc_private *priv) iowrite16be(DEFAULT_HDLC_ADDR, &priv->ucc_pram->haddr4); /* Get BD buffer */ - bd_buffer = dma_alloc_coherent(priv->dev, - (RX_BD_RING_LEN + TX_BD_RING_LEN) * - MAX_RX_BUF_LENGTH, - &bd_dma_addr, GFP_KERNEL); + bd_buffer = dma_zalloc_coherent(priv->dev, + (RX_BD_RING_LEN + TX_BD_RING_LEN) * + MAX_RX_BUF_LENGTH, + &bd_dma_addr, GFP_KERNEL); if (!bd_buffer) { dev_err(priv->dev, "Could not allocate buffer descriptors\n"); @@ -281,9 +281,6 @@ static int uhdlc_init(struct ucc_hdlc_private *priv) goto free_tiptr; } - memset(bd_buffer, 0, (RX_BD_RING_LEN + TX_BD_RING_LEN) - * MAX_RX_BUF_LENGTH); - priv->rx_buffer = bd_buffer; priv->tx_buffer = bd_buffer + RX_BD_RING_LEN * MAX_RX_BUF_LENGTH; |